130fdc8d8SChris Lattner //===-- CommandObject.cpp ---------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandObject.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner #include <string> 1330fdc8d8SChris Lattner #include <map> 1430fdc8d8SChris Lattner 1530fdc8d8SChris Lattner #include <getopt.h> 1630fdc8d8SChris Lattner #include <stdlib.h> 1730fdc8d8SChris Lattner #include <ctype.h> 1830fdc8d8SChris Lattner 1930fdc8d8SChris Lattner #include "lldb/Core/Address.h" 20ca7835c6SJohnny Chen #include "lldb/Core/ArchSpec.h" 2140af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner // These are for the Sourcename completers. 2430fdc8d8SChris Lattner // FIXME: Make a separate file for the completers. 2553239f00SGreg Clayton #include "lldb/Host/FileSpec.h" 2630fdc8d8SChris Lattner #include "lldb/Core/FileSpecList.h" 2730fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2830fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2930fdc8d8SChris Lattner 3030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 3130fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 3230fdc8d8SChris Lattner #include "lldb/Interpreter/ScriptInterpreter.h" 3330fdc8d8SChris Lattner #include "lldb/Interpreter/ScriptInterpreterPython.h" 3430fdc8d8SChris Lattner 3530fdc8d8SChris Lattner using namespace lldb; 3630fdc8d8SChris Lattner using namespace lldb_private; 3730fdc8d8SChris Lattner 3830fdc8d8SChris Lattner //------------------------------------------------------------------------- 3930fdc8d8SChris Lattner // CommandObject 4030fdc8d8SChris Lattner //------------------------------------------------------------------------- 4130fdc8d8SChris Lattner 42a7015092SGreg Clayton CommandObject::CommandObject 43a7015092SGreg Clayton ( 44a7015092SGreg Clayton CommandInterpreter &interpreter, 45a7015092SGreg Clayton const char *name, 46a7015092SGreg Clayton const char *help, 47a7015092SGreg Clayton const char *syntax, 48a7015092SGreg Clayton uint32_t flags 49a7015092SGreg Clayton ) : 50a7015092SGreg Clayton m_interpreter (interpreter), 5130fdc8d8SChris Lattner m_cmd_name (name), 5230fdc8d8SChris Lattner m_cmd_help_short (), 5330fdc8d8SChris Lattner m_cmd_help_long (), 5430fdc8d8SChris Lattner m_cmd_syntax (), 55279a6c26SJim Ingham m_is_alias (false), 56e139cf23SCaroline Tice m_flags (flags), 57a9f7b79dSGreg Clayton m_arguments(), 58a9f7b79dSGreg Clayton m_command_override_callback (NULL), 59a9f7b79dSGreg Clayton m_command_override_baton (NULL) 6030fdc8d8SChris Lattner { 6130fdc8d8SChris Lattner if (help && help[0]) 6230fdc8d8SChris Lattner m_cmd_help_short = help; 6330fdc8d8SChris Lattner if (syntax && syntax[0]) 6430fdc8d8SChris Lattner m_cmd_syntax = syntax; 6530fdc8d8SChris Lattner } 6630fdc8d8SChris Lattner 6730fdc8d8SChris Lattner CommandObject::~CommandObject () 6830fdc8d8SChris Lattner { 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner 7130fdc8d8SChris Lattner const char * 7230fdc8d8SChris Lattner CommandObject::GetHelp () 7330fdc8d8SChris Lattner { 7430fdc8d8SChris Lattner return m_cmd_help_short.c_str(); 7530fdc8d8SChris Lattner } 7630fdc8d8SChris Lattner 7730fdc8d8SChris Lattner const char * 7830fdc8d8SChris Lattner CommandObject::GetHelpLong () 7930fdc8d8SChris Lattner { 8030fdc8d8SChris Lattner return m_cmd_help_long.c_str(); 8130fdc8d8SChris Lattner } 8230fdc8d8SChris Lattner 8330fdc8d8SChris Lattner const char * 8430fdc8d8SChris Lattner CommandObject::GetSyntax () 8530fdc8d8SChris Lattner { 86e139cf23SCaroline Tice if (m_cmd_syntax.length() == 0) 87e139cf23SCaroline Tice { 88e139cf23SCaroline Tice StreamString syntax_str; 89e139cf23SCaroline Tice syntax_str.Printf ("%s", GetCommandName()); 90e139cf23SCaroline Tice if (GetOptions() != NULL) 91e139cf23SCaroline Tice syntax_str.Printf (" <cmd-options>"); 92e139cf23SCaroline Tice if (m_arguments.size() > 0) 93e139cf23SCaroline Tice { 94e139cf23SCaroline Tice syntax_str.Printf (" "); 95a4c6ad19SSean Callanan if (WantsRawCommandString()) 96a4c6ad19SSean Callanan syntax_str.Printf("-- "); 97e139cf23SCaroline Tice GetFormattedCommandArguments (syntax_str); 98e139cf23SCaroline Tice } 99e139cf23SCaroline Tice m_cmd_syntax = syntax_str.GetData (); 100e139cf23SCaroline Tice } 101e139cf23SCaroline Tice 10230fdc8d8SChris Lattner return m_cmd_syntax.c_str(); 10330fdc8d8SChris Lattner } 10430fdc8d8SChris Lattner 10530fdc8d8SChris Lattner const char * 10630fdc8d8SChris Lattner CommandObject::Translate () 10730fdc8d8SChris Lattner { 10830fdc8d8SChris Lattner //return m_cmd_func_name.c_str(); 10930fdc8d8SChris Lattner return "This function is currently not implemented."; 11030fdc8d8SChris Lattner } 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner const char * 11330fdc8d8SChris Lattner CommandObject::GetCommandName () 11430fdc8d8SChris Lattner { 11530fdc8d8SChris Lattner return m_cmd_name.c_str(); 11630fdc8d8SChris Lattner } 11730fdc8d8SChris Lattner 11830fdc8d8SChris Lattner void 11930fdc8d8SChris Lattner CommandObject::SetCommandName (const char *name) 12030fdc8d8SChris Lattner { 12130fdc8d8SChris Lattner m_cmd_name = name; 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner void 12530fdc8d8SChris Lattner CommandObject::SetHelp (const char *cstr) 12630fdc8d8SChris Lattner { 12730fdc8d8SChris Lattner m_cmd_help_short = cstr; 12830fdc8d8SChris Lattner } 12930fdc8d8SChris Lattner 13030fdc8d8SChris Lattner void 13130fdc8d8SChris Lattner CommandObject::SetHelpLong (const char *cstr) 13230fdc8d8SChris Lattner { 13330fdc8d8SChris Lattner m_cmd_help_long = cstr; 13430fdc8d8SChris Lattner } 13530fdc8d8SChris Lattner 13630fdc8d8SChris Lattner void 13799f0b8f9SEnrico Granata CommandObject::SetHelpLong (std::string str) 13899f0b8f9SEnrico Granata { 13999f0b8f9SEnrico Granata m_cmd_help_long = str; 14099f0b8f9SEnrico Granata } 14199f0b8f9SEnrico Granata 14299f0b8f9SEnrico Granata void 14330fdc8d8SChris Lattner CommandObject::SetSyntax (const char *cstr) 14430fdc8d8SChris Lattner { 14530fdc8d8SChris Lattner m_cmd_syntax = cstr; 14630fdc8d8SChris Lattner } 14730fdc8d8SChris Lattner 14830fdc8d8SChris Lattner Options * 14930fdc8d8SChris Lattner CommandObject::GetOptions () 15030fdc8d8SChris Lattner { 15130fdc8d8SChris Lattner // By default commands don't have options unless this virtual function 15230fdc8d8SChris Lattner // is overridden by base classes. 15330fdc8d8SChris Lattner return NULL; 15430fdc8d8SChris Lattner } 15530fdc8d8SChris Lattner 15630fdc8d8SChris Lattner bool 15730fdc8d8SChris Lattner CommandObject::ParseOptions 15830fdc8d8SChris Lattner ( 15930fdc8d8SChris Lattner Args& args, 16030fdc8d8SChris Lattner CommandReturnObject &result 16130fdc8d8SChris Lattner ) 16230fdc8d8SChris Lattner { 16330fdc8d8SChris Lattner // See if the subclass has options? 16430fdc8d8SChris Lattner Options *options = GetOptions(); 16530fdc8d8SChris Lattner if (options != NULL) 16630fdc8d8SChris Lattner { 16730fdc8d8SChris Lattner Error error; 168f6b8b581SGreg Clayton options->NotifyOptionParsingStarting(); 16930fdc8d8SChris Lattner 17030fdc8d8SChris Lattner // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1, 17130fdc8d8SChris Lattner // so we need to push a dummy value into position zero. 17230fdc8d8SChris Lattner args.Unshift("dummy_string"); 17330fdc8d8SChris Lattner error = args.ParseOptions (*options); 17430fdc8d8SChris Lattner 17530fdc8d8SChris Lattner // The "dummy_string" will have already been removed by ParseOptions, 17630fdc8d8SChris Lattner // so no need to remove it. 17730fdc8d8SChris Lattner 178f6b8b581SGreg Clayton if (error.Success()) 179f6b8b581SGreg Clayton error = options->NotifyOptionParsingFinished(); 180f6b8b581SGreg Clayton 181f6b8b581SGreg Clayton if (error.Success()) 182f6b8b581SGreg Clayton { 183f6b8b581SGreg Clayton if (options->VerifyOptions (result)) 184f6b8b581SGreg Clayton return true; 185f6b8b581SGreg Clayton } 186f6b8b581SGreg Clayton else 18730fdc8d8SChris Lattner { 18830fdc8d8SChris Lattner const char *error_cstr = error.AsCString(); 18930fdc8d8SChris Lattner if (error_cstr) 19030fdc8d8SChris Lattner { 19130fdc8d8SChris Lattner // We got an error string, lets use that 19286edbf41SGreg Clayton result.AppendError(error_cstr); 19330fdc8d8SChris Lattner } 19430fdc8d8SChris Lattner else 19530fdc8d8SChris Lattner { 19630fdc8d8SChris Lattner // No error string, output the usage information into result 197eb0103f2SGreg Clayton options->GenerateOptionUsage (result.GetErrorStream(), this); 19830fdc8d8SChris Lattner } 199f6b8b581SGreg Clayton } 20030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 20130fdc8d8SChris Lattner return false; 20230fdc8d8SChris Lattner } 20330fdc8d8SChris Lattner return true; 20430fdc8d8SChris Lattner } 20530fdc8d8SChris Lattner 2065a988416SJim Ingham 2075a988416SJim Ingham 2085a988416SJim Ingham bool 2095a988416SJim Ingham CommandObject::CheckFlags (CommandReturnObject &result) 2105a988416SJim Ingham { 211b766a73dSGreg Clayton if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused)) 212b766a73dSGreg Clayton { 213c14ee32dSGreg Clayton Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 21430fdc8d8SChris Lattner if (process == NULL) 21530fdc8d8SChris Lattner { 216b8e8a5f3SJim Ingham // A process that is not running is considered paused. 217b8e8a5f3SJim Ingham if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched)) 218b8e8a5f3SJim Ingham { 21930fdc8d8SChris Lattner result.AppendError ("Process must exist."); 22030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 22130fdc8d8SChris Lattner return false; 22230fdc8d8SChris Lattner } 223b8e8a5f3SJim Ingham } 22430fdc8d8SChris Lattner else 22530fdc8d8SChris Lattner { 22630fdc8d8SChris Lattner StateType state = process->GetState(); 22730fdc8d8SChris Lattner 22830fdc8d8SChris Lattner switch (state) 22930fdc8d8SChris Lattner { 2307a5388bfSGreg Clayton case eStateInvalid: 23130fdc8d8SChris Lattner case eStateSuspended: 23230fdc8d8SChris Lattner case eStateCrashed: 23330fdc8d8SChris Lattner case eStateStopped: 23430fdc8d8SChris Lattner break; 23530fdc8d8SChris Lattner 236b766a73dSGreg Clayton case eStateConnected: 237b766a73dSGreg Clayton case eStateAttaching: 238b766a73dSGreg Clayton case eStateLaunching: 23930fdc8d8SChris Lattner case eStateDetached: 24030fdc8d8SChris Lattner case eStateExited: 24130fdc8d8SChris Lattner case eStateUnloaded: 24273b472d4SGreg Clayton if (GetFlags().Test(CommandObject::eFlagProcessMustBeLaunched)) 24330fdc8d8SChris Lattner { 24430fdc8d8SChris Lattner result.AppendError ("Process must be launched."); 24530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 24630fdc8d8SChris Lattner return false; 24730fdc8d8SChris Lattner } 24830fdc8d8SChris Lattner break; 24930fdc8d8SChris Lattner 25030fdc8d8SChris Lattner case eStateRunning: 25130fdc8d8SChris Lattner case eStateStepping: 25273b472d4SGreg Clayton if (GetFlags().Test(CommandObject::eFlagProcessMustBePaused)) 25330fdc8d8SChris Lattner { 25430fdc8d8SChris Lattner result.AppendError ("Process is running. Use 'process interrupt' to pause execution."); 25530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 25630fdc8d8SChris Lattner return false; 25730fdc8d8SChris Lattner } 25830fdc8d8SChris Lattner } 25930fdc8d8SChris Lattner } 260b766a73dSGreg Clayton } 2615a988416SJim Ingham return true; 26230fdc8d8SChris Lattner } 26330fdc8d8SChris Lattner 26430fdc8d8SChris Lattner class CommandDictCommandPartialMatch 26530fdc8d8SChris Lattner { 26630fdc8d8SChris Lattner public: 26730fdc8d8SChris Lattner CommandDictCommandPartialMatch (const char *match_str) 26830fdc8d8SChris Lattner { 26930fdc8d8SChris Lattner m_match_str = match_str; 27030fdc8d8SChris Lattner } 27130fdc8d8SChris Lattner bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const 27230fdc8d8SChris Lattner { 27330fdc8d8SChris Lattner // A NULL or empty string matches everything. 27430fdc8d8SChris Lattner if (m_match_str == NULL || *m_match_str == '\0') 27530fdc8d8SChris Lattner return 1; 27630fdc8d8SChris Lattner 27730fdc8d8SChris Lattner size_t found = map_element.first.find (m_match_str, 0); 27830fdc8d8SChris Lattner if (found == std::string::npos) 27930fdc8d8SChris Lattner return 0; 28030fdc8d8SChris Lattner else 28130fdc8d8SChris Lattner return found == 0; 28230fdc8d8SChris Lattner } 28330fdc8d8SChris Lattner 28430fdc8d8SChris Lattner private: 28530fdc8d8SChris Lattner const char *m_match_str; 28630fdc8d8SChris Lattner }; 28730fdc8d8SChris Lattner 28830fdc8d8SChris Lattner int 28930fdc8d8SChris Lattner CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str, 29030fdc8d8SChris Lattner StringList &matches) 29130fdc8d8SChris Lattner { 29230fdc8d8SChris Lattner int number_added = 0; 29330fdc8d8SChris Lattner CommandDictCommandPartialMatch matcher(cmd_str); 29430fdc8d8SChris Lattner 29530fdc8d8SChris Lattner CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher); 29630fdc8d8SChris Lattner 29730fdc8d8SChris Lattner while (matching_cmds != in_map.end()) 29830fdc8d8SChris Lattner { 29930fdc8d8SChris Lattner ++number_added; 30030fdc8d8SChris Lattner matches.AppendString((*matching_cmds).first.c_str()); 30130fdc8d8SChris Lattner matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);; 30230fdc8d8SChris Lattner } 30330fdc8d8SChris Lattner return number_added; 30430fdc8d8SChris Lattner } 30530fdc8d8SChris Lattner 30630fdc8d8SChris Lattner int 30730fdc8d8SChris Lattner CommandObject::HandleCompletion 30830fdc8d8SChris Lattner ( 30930fdc8d8SChris Lattner Args &input, 31030fdc8d8SChris Lattner int &cursor_index, 31130fdc8d8SChris Lattner int &cursor_char_position, 31230fdc8d8SChris Lattner int match_start_point, 31330fdc8d8SChris Lattner int max_return_elements, 314558ce124SJim Ingham bool &word_complete, 31530fdc8d8SChris Lattner StringList &matches 31630fdc8d8SChris Lattner ) 31730fdc8d8SChris Lattner { 3186561d15dSJohnny Chen // Default implmentation of WantsCompletion() is !WantsRawCommandString(). 3196561d15dSJohnny Chen // Subclasses who want raw command string but desire, for example, 3206561d15dSJohnny Chen // argument completion should override WantsCompletion() to return true, 3216561d15dSJohnny Chen // instead. 3226f99b637SJohnny Chen if (WantsRawCommandString() && !WantsCompletion()) 32330fdc8d8SChris Lattner { 32430fdc8d8SChris Lattner // FIXME: Abstract telling the completion to insert the completion character. 32530fdc8d8SChris Lattner matches.Clear(); 32630fdc8d8SChris Lattner return -1; 32730fdc8d8SChris Lattner } 32830fdc8d8SChris Lattner else 32930fdc8d8SChris Lattner { 33030fdc8d8SChris Lattner // Can we do anything generic with the options? 33130fdc8d8SChris Lattner Options *cur_options = GetOptions(); 33230fdc8d8SChris Lattner CommandReturnObject result; 33330fdc8d8SChris Lattner OptionElementVector opt_element_vector; 33430fdc8d8SChris Lattner 33530fdc8d8SChris Lattner if (cur_options != NULL) 33630fdc8d8SChris Lattner { 33730fdc8d8SChris Lattner // Re-insert the dummy command name string which will have been 33830fdc8d8SChris Lattner // stripped off: 33930fdc8d8SChris Lattner input.Unshift ("dummy-string"); 34030fdc8d8SChris Lattner cursor_index++; 34130fdc8d8SChris Lattner 34230fdc8d8SChris Lattner 34330fdc8d8SChris Lattner // I stick an element on the end of the input, because if the last element is 34430fdc8d8SChris Lattner // option that requires an argument, getopt_long will freak out. 34530fdc8d8SChris Lattner 34630fdc8d8SChris Lattner input.AppendArgument ("<FAKE-VALUE>"); 34730fdc8d8SChris Lattner 348d43e0094SJim Ingham input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index); 34930fdc8d8SChris Lattner 35030fdc8d8SChris Lattner input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1); 35130fdc8d8SChris Lattner 35230fdc8d8SChris Lattner bool handled_by_options; 353eb0103f2SGreg Clayton handled_by_options = cur_options->HandleOptionCompletion (input, 35430fdc8d8SChris Lattner opt_element_vector, 35530fdc8d8SChris Lattner cursor_index, 35630fdc8d8SChris Lattner cursor_char_position, 35730fdc8d8SChris Lattner match_start_point, 35830fdc8d8SChris Lattner max_return_elements, 359558ce124SJim Ingham word_complete, 36030fdc8d8SChris Lattner matches); 36130fdc8d8SChris Lattner if (handled_by_options) 36230fdc8d8SChris Lattner return matches.GetSize(); 36330fdc8d8SChris Lattner } 36430fdc8d8SChris Lattner 36530fdc8d8SChris Lattner // If we got here, the last word is not an option or an option argument. 366a7015092SGreg Clayton return HandleArgumentCompletion (input, 36730fdc8d8SChris Lattner cursor_index, 36830fdc8d8SChris Lattner cursor_char_position, 36930fdc8d8SChris Lattner opt_element_vector, 37030fdc8d8SChris Lattner match_start_point, 37130fdc8d8SChris Lattner max_return_elements, 372558ce124SJim Ingham word_complete, 37330fdc8d8SChris Lattner matches); 37430fdc8d8SChris Lattner } 37530fdc8d8SChris Lattner } 37630fdc8d8SChris Lattner 37730fdc8d8SChris Lattner bool 378a7015092SGreg Clayton CommandObject::HelpTextContainsWord (const char *search_word) 37930fdc8d8SChris Lattner { 38030fdc8d8SChris Lattner const char *short_help; 38130fdc8d8SChris Lattner const char *long_help; 38230fdc8d8SChris Lattner const char *syntax_help; 38330fdc8d8SChris Lattner std::string options_usage_help; 38430fdc8d8SChris Lattner 38530fdc8d8SChris Lattner 38630fdc8d8SChris Lattner bool found_word = false; 38730fdc8d8SChris Lattner 38830fdc8d8SChris Lattner short_help = GetHelp(); 38930fdc8d8SChris Lattner long_help = GetHelpLong(); 39030fdc8d8SChris Lattner syntax_help = GetSyntax(); 39130fdc8d8SChris Lattner 3924b6fbf37SCaroline Tice if (strcasestr (short_help, search_word)) 39330fdc8d8SChris Lattner found_word = true; 3944b6fbf37SCaroline Tice else if (strcasestr (long_help, search_word)) 39530fdc8d8SChris Lattner found_word = true; 3964b6fbf37SCaroline Tice else if (strcasestr (syntax_help, search_word)) 39730fdc8d8SChris Lattner found_word = true; 39830fdc8d8SChris Lattner 39930fdc8d8SChris Lattner if (!found_word 40030fdc8d8SChris Lattner && GetOptions() != NULL) 40130fdc8d8SChris Lattner { 40230fdc8d8SChris Lattner StreamString usage_help; 403eb0103f2SGreg Clayton GetOptions()->GenerateOptionUsage (usage_help, this); 40430fdc8d8SChris Lattner if (usage_help.GetSize() > 0) 40530fdc8d8SChris Lattner { 40630fdc8d8SChris Lattner const char *usage_text = usage_help.GetData(); 4074b6fbf37SCaroline Tice if (strcasestr (usage_text, search_word)) 40830fdc8d8SChris Lattner found_word = true; 40930fdc8d8SChris Lattner } 41030fdc8d8SChris Lattner } 41130fdc8d8SChris Lattner 41230fdc8d8SChris Lattner return found_word; 41330fdc8d8SChris Lattner } 414e139cf23SCaroline Tice 415e139cf23SCaroline Tice int 416e139cf23SCaroline Tice CommandObject::GetNumArgumentEntries () 417e139cf23SCaroline Tice { 418e139cf23SCaroline Tice return m_arguments.size(); 419e139cf23SCaroline Tice } 420e139cf23SCaroline Tice 421e139cf23SCaroline Tice CommandObject::CommandArgumentEntry * 422e139cf23SCaroline Tice CommandObject::GetArgumentEntryAtIndex (int idx) 423e139cf23SCaroline Tice { 424e139cf23SCaroline Tice if (idx < m_arguments.size()) 425e139cf23SCaroline Tice return &(m_arguments[idx]); 426e139cf23SCaroline Tice 427e139cf23SCaroline Tice return NULL; 428e139cf23SCaroline Tice } 429e139cf23SCaroline Tice 430e139cf23SCaroline Tice CommandObject::ArgumentTableEntry * 431e139cf23SCaroline Tice CommandObject::FindArgumentDataByType (CommandArgumentType arg_type) 432e139cf23SCaroline Tice { 433e139cf23SCaroline Tice const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); 434e139cf23SCaroline Tice 435e139cf23SCaroline Tice for (int i = 0; i < eArgTypeLastArg; ++i) 436e139cf23SCaroline Tice if (table[i].arg_type == arg_type) 437e139cf23SCaroline Tice return (ArgumentTableEntry *) &(table[i]); 438e139cf23SCaroline Tice 439e139cf23SCaroline Tice return NULL; 440e139cf23SCaroline Tice } 441e139cf23SCaroline Tice 442e139cf23SCaroline Tice void 443e139cf23SCaroline Tice CommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter) 444e139cf23SCaroline Tice { 445e139cf23SCaroline Tice const ArgumentTableEntry* table = CommandObject::GetArgumentTable(); 446e139cf23SCaroline Tice ArgumentTableEntry *entry = (ArgumentTableEntry *) &(table[arg_type]); 447e139cf23SCaroline Tice 448e139cf23SCaroline Tice // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up... 449e139cf23SCaroline Tice 450e139cf23SCaroline Tice if (entry->arg_type != arg_type) 451e139cf23SCaroline Tice entry = CommandObject::FindArgumentDataByType (arg_type); 452e139cf23SCaroline Tice 453e139cf23SCaroline Tice if (!entry) 454e139cf23SCaroline Tice return; 455e139cf23SCaroline Tice 456e139cf23SCaroline Tice StreamString name_str; 457e139cf23SCaroline Tice name_str.Printf ("<%s>", entry->arg_name); 458e139cf23SCaroline Tice 459fc7a7f3bSEnrico Granata if (entry->help_function) 46082a7d983SEnrico Granata { 461fc7a7f3bSEnrico Granata const char* help_text = entry->help_function(); 46282a7d983SEnrico Granata if (!entry->help_function.self_formatting) 46382a7d983SEnrico Granata { 46482a7d983SEnrico Granata interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text, 465e139cf23SCaroline Tice name_str.GetSize()); 46682a7d983SEnrico Granata } 46782a7d983SEnrico Granata else 46882a7d983SEnrico Granata { 46982a7d983SEnrico Granata interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text, 47082a7d983SEnrico Granata name_str.GetSize()); 47182a7d983SEnrico Granata } 47282a7d983SEnrico Granata } 473e139cf23SCaroline Tice else 474e139cf23SCaroline Tice interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize()); 475e139cf23SCaroline Tice } 476e139cf23SCaroline Tice 477e139cf23SCaroline Tice const char * 478e139cf23SCaroline Tice CommandObject::GetArgumentName (CommandArgumentType arg_type) 479e139cf23SCaroline Tice { 480deaab222SCaroline Tice ArgumentTableEntry *entry = (ArgumentTableEntry *) &(CommandObject::GetArgumentTable()[arg_type]); 481deaab222SCaroline Tice 482deaab222SCaroline Tice // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up... 483deaab222SCaroline Tice 484deaab222SCaroline Tice if (entry->arg_type != arg_type) 485deaab222SCaroline Tice entry = CommandObject::FindArgumentDataByType (arg_type); 486deaab222SCaroline Tice 487e6acf355SJohnny Chen if (entry) 488deaab222SCaroline Tice return entry->arg_name; 489e6acf355SJohnny Chen 490e6acf355SJohnny Chen StreamString str; 491e6acf355SJohnny Chen str << "Arg name for type (" << arg_type << ") not in arg table!"; 492e6acf355SJohnny Chen return str.GetData(); 493e139cf23SCaroline Tice } 494e139cf23SCaroline Tice 495405fe67fSCaroline Tice bool 496e0d378b3SGreg Clayton CommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type) 497405fe67fSCaroline Tice { 498405fe67fSCaroline Tice if ((arg_repeat_type == eArgRepeatPairPlain) 499405fe67fSCaroline Tice || (arg_repeat_type == eArgRepeatPairOptional) 500405fe67fSCaroline Tice || (arg_repeat_type == eArgRepeatPairPlus) 501405fe67fSCaroline Tice || (arg_repeat_type == eArgRepeatPairStar) 502405fe67fSCaroline Tice || (arg_repeat_type == eArgRepeatPairRange) 503405fe67fSCaroline Tice || (arg_repeat_type == eArgRepeatPairRangeOptional)) 504405fe67fSCaroline Tice return true; 505405fe67fSCaroline Tice 506405fe67fSCaroline Tice return false; 507405fe67fSCaroline Tice } 508405fe67fSCaroline Tice 50934ddc8dbSJohnny Chen static CommandObject::CommandArgumentEntry 51034ddc8dbSJohnny Chen OptSetFiltered(uint32_t opt_set_mask, CommandObject::CommandArgumentEntry &cmd_arg_entry) 51134ddc8dbSJohnny Chen { 51234ddc8dbSJohnny Chen CommandObject::CommandArgumentEntry ret_val; 51334ddc8dbSJohnny Chen for (unsigned i = 0; i < cmd_arg_entry.size(); ++i) 51434ddc8dbSJohnny Chen if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association) 51534ddc8dbSJohnny Chen ret_val.push_back(cmd_arg_entry[i]); 51634ddc8dbSJohnny Chen return ret_val; 51734ddc8dbSJohnny Chen } 51834ddc8dbSJohnny Chen 51934ddc8dbSJohnny Chen // Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take 52034ddc8dbSJohnny Chen // all the argument data into account. On rare cases where some argument sticks 52134ddc8dbSJohnny Chen // with certain option sets, this function returns the option set filtered args. 522e139cf23SCaroline Tice void 52334ddc8dbSJohnny Chen CommandObject::GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask) 524e139cf23SCaroline Tice { 525e139cf23SCaroline Tice int num_args = m_arguments.size(); 526e139cf23SCaroline Tice for (int i = 0; i < num_args; ++i) 527e139cf23SCaroline Tice { 528e139cf23SCaroline Tice if (i > 0) 529e139cf23SCaroline Tice str.Printf (" "); 53034ddc8dbSJohnny Chen CommandArgumentEntry arg_entry = 53134ddc8dbSJohnny Chen opt_set_mask == LLDB_OPT_SET_ALL ? m_arguments[i] 53234ddc8dbSJohnny Chen : OptSetFiltered(opt_set_mask, m_arguments[i]); 533e139cf23SCaroline Tice int num_alternatives = arg_entry.size(); 534405fe67fSCaroline Tice 535405fe67fSCaroline Tice if ((num_alternatives == 2) 536405fe67fSCaroline Tice && IsPairType (arg_entry[0].arg_repetition)) 537405fe67fSCaroline Tice { 538405fe67fSCaroline Tice const char *first_name = GetArgumentName (arg_entry[0].arg_type); 539405fe67fSCaroline Tice const char *second_name = GetArgumentName (arg_entry[1].arg_type); 540405fe67fSCaroline Tice switch (arg_entry[0].arg_repetition) 541405fe67fSCaroline Tice { 542405fe67fSCaroline Tice case eArgRepeatPairPlain: 543405fe67fSCaroline Tice str.Printf ("<%s> <%s>", first_name, second_name); 544405fe67fSCaroline Tice break; 545405fe67fSCaroline Tice case eArgRepeatPairOptional: 546405fe67fSCaroline Tice str.Printf ("[<%s> <%s>]", first_name, second_name); 547405fe67fSCaroline Tice break; 548405fe67fSCaroline Tice case eArgRepeatPairPlus: 549405fe67fSCaroline Tice str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name); 550405fe67fSCaroline Tice break; 551405fe67fSCaroline Tice case eArgRepeatPairStar: 552405fe67fSCaroline Tice str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name); 553405fe67fSCaroline Tice break; 554405fe67fSCaroline Tice case eArgRepeatPairRange: 555405fe67fSCaroline Tice str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name); 556405fe67fSCaroline Tice break; 557405fe67fSCaroline Tice case eArgRepeatPairRangeOptional: 558405fe67fSCaroline Tice str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name); 559405fe67fSCaroline Tice break; 560ca1176aaSCaroline Tice // Explicitly test for all the rest of the cases, so if new types get added we will notice the 561ca1176aaSCaroline Tice // missing case statement(s). 562ca1176aaSCaroline Tice case eArgRepeatPlain: 563ca1176aaSCaroline Tice case eArgRepeatOptional: 564ca1176aaSCaroline Tice case eArgRepeatPlus: 565ca1176aaSCaroline Tice case eArgRepeatStar: 566ca1176aaSCaroline Tice case eArgRepeatRange: 567ca1176aaSCaroline Tice // These should not be reached, as they should fail the IsPairType test above. 568ca1176aaSCaroline Tice break; 569405fe67fSCaroline Tice } 570405fe67fSCaroline Tice } 571405fe67fSCaroline Tice else 572405fe67fSCaroline Tice { 573e139cf23SCaroline Tice StreamString names; 574e139cf23SCaroline Tice for (int j = 0; j < num_alternatives; ++j) 575e139cf23SCaroline Tice { 576e139cf23SCaroline Tice if (j > 0) 577e139cf23SCaroline Tice names.Printf (" | "); 578e139cf23SCaroline Tice names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type)); 579e139cf23SCaroline Tice } 580e139cf23SCaroline Tice switch (arg_entry[0].arg_repetition) 581e139cf23SCaroline Tice { 582e139cf23SCaroline Tice case eArgRepeatPlain: 583e139cf23SCaroline Tice str.Printf ("<%s>", names.GetData()); 584e139cf23SCaroline Tice break; 585e139cf23SCaroline Tice case eArgRepeatPlus: 586e139cf23SCaroline Tice str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData()); 587e139cf23SCaroline Tice break; 588e139cf23SCaroline Tice case eArgRepeatStar: 589e139cf23SCaroline Tice str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData()); 590e139cf23SCaroline Tice break; 591e139cf23SCaroline Tice case eArgRepeatOptional: 592e139cf23SCaroline Tice str.Printf ("[<%s>]", names.GetData()); 593e139cf23SCaroline Tice break; 594405fe67fSCaroline Tice case eArgRepeatRange: 595fd54b368SJason Molenda str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData()); 596ca1176aaSCaroline Tice break; 597ca1176aaSCaroline Tice // Explicitly test for all the rest of the cases, so if new types get added we will notice the 598ca1176aaSCaroline Tice // missing case statement(s). 599ca1176aaSCaroline Tice case eArgRepeatPairPlain: 600ca1176aaSCaroline Tice case eArgRepeatPairOptional: 601ca1176aaSCaroline Tice case eArgRepeatPairPlus: 602ca1176aaSCaroline Tice case eArgRepeatPairStar: 603ca1176aaSCaroline Tice case eArgRepeatPairRange: 604ca1176aaSCaroline Tice case eArgRepeatPairRangeOptional: 605ca1176aaSCaroline Tice // These should not be hit, as they should pass the IsPairType test above, and control should 606ca1176aaSCaroline Tice // have gone into the other branch of the if statement. 607ca1176aaSCaroline Tice break; 608405fe67fSCaroline Tice } 609e139cf23SCaroline Tice } 610e139cf23SCaroline Tice } 611e139cf23SCaroline Tice } 612e139cf23SCaroline Tice 6130c16aa6dSStephen Wilson CommandArgumentType 614e139cf23SCaroline Tice CommandObject::LookupArgumentName (const char *arg_name) 615e139cf23SCaroline Tice { 616e139cf23SCaroline Tice CommandArgumentType return_type = eArgTypeLastArg; 617e139cf23SCaroline Tice 618e139cf23SCaroline Tice std::string arg_name_str (arg_name); 619e139cf23SCaroline Tice size_t len = arg_name_str.length(); 620e139cf23SCaroline Tice if (arg_name[0] == '<' 621e139cf23SCaroline Tice && arg_name[len-1] == '>') 622e139cf23SCaroline Tice arg_name_str = arg_name_str.substr (1, len-2); 623e139cf23SCaroline Tice 624331eff39SJohnny Chen const ArgumentTableEntry *table = GetArgumentTable(); 625e139cf23SCaroline Tice for (int i = 0; i < eArgTypeLastArg; ++i) 626331eff39SJohnny Chen if (arg_name_str.compare (table[i].arg_name) == 0) 627e139cf23SCaroline Tice return_type = g_arguments_data[i].arg_type; 628e139cf23SCaroline Tice 629e139cf23SCaroline Tice return return_type; 630e139cf23SCaroline Tice } 631e139cf23SCaroline Tice 632e139cf23SCaroline Tice static const char * 633931e674aSJim Ingham RegisterNameHelpTextCallback () 634931e674aSJim Ingham { 635931e674aSJim Ingham return "Register names can be specified using the architecture specific names. " 63684c7bd74SJim Ingham "They can also be specified using generic names. Not all generic entities have " 63784c7bd74SJim Ingham "registers backing them on all architectures. When they don't the generic name " 63884c7bd74SJim Ingham "will return an error.\n" 639931e674aSJim Ingham "The generic names defined in lldb are:\n" 640931e674aSJim Ingham "\n" 641931e674aSJim Ingham "pc - program counter register\n" 642931e674aSJim Ingham "ra - return address register\n" 643931e674aSJim Ingham "fp - frame pointer register\n" 644931e674aSJim Ingham "sp - stack pointer register\n" 64584c7bd74SJim Ingham "flags - the flags register\n" 646931e674aSJim Ingham "arg{1-6} - integer argument passing registers.\n"; 647931e674aSJim Ingham } 648931e674aSJim Ingham 649931e674aSJim Ingham static const char * 650e139cf23SCaroline Tice BreakpointIDHelpTextCallback () 651e139cf23SCaroline Tice { 65286edbf41SGreg Clayton return "Breakpoint ID's consist major and minor numbers; the major number " 65386edbf41SGreg Clayton "corresponds to the single entity that was created with a 'breakpoint set' " 65486edbf41SGreg Clayton "command; the minor numbers correspond to all the locations that were actually " 65586edbf41SGreg Clayton "found/set based on the major breakpoint. A full breakpoint ID might look like " 65686edbf41SGreg Clayton "3.14, meaning the 14th location set for the 3rd breakpoint. You can specify " 65786edbf41SGreg Clayton "all the locations of a breakpoint by just indicating the major breakpoint " 65886edbf41SGreg Clayton "number. A valid breakpoint id consists either of just the major id number, " 65986edbf41SGreg Clayton "or the major number, a dot, and the location number (e.g. 3 or 3.2 could " 66086edbf41SGreg Clayton "both be valid breakpoint ids)."; 661e139cf23SCaroline Tice } 662e139cf23SCaroline Tice 663e139cf23SCaroline Tice static const char * 664e139cf23SCaroline Tice BreakpointIDRangeHelpTextCallback () 665e139cf23SCaroline Tice { 66686edbf41SGreg Clayton return "A 'breakpoint id list' is a manner of specifying multiple breakpoints. " 66786edbf41SGreg Clayton "This can be done through several mechanisms. The easiest way is to just " 66886edbf41SGreg Clayton "enter a space-separated list of breakpoint ids. To specify all the " 66986edbf41SGreg Clayton "breakpoint locations under a major breakpoint, you can use the major " 67086edbf41SGreg Clayton "breakpoint number followed by '.*', eg. '5.*' means all the locations under " 67186edbf41SGreg Clayton "breakpoint 5. You can also indicate a range of breakpoints by using " 67286edbf41SGreg Clayton "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a range can " 67386edbf41SGreg Clayton "be any valid breakpoint ids. It is not legal, however, to specify a range " 67486edbf41SGreg Clayton "using specific locations that cross major breakpoint numbers. I.e. 3.2 - 3.7" 67586edbf41SGreg Clayton " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; 67686edbf41SGreg Clayton } 67786edbf41SGreg Clayton 67886edbf41SGreg Clayton static const char * 67986edbf41SGreg Clayton GDBFormatHelpTextCallback () 68086edbf41SGreg Clayton { 681f91381e8SGreg Clayton return "A GDB format consists of a repeat count, a format letter and a size letter. " 682f91381e8SGreg Clayton "The repeat count is optional and defaults to 1. The format letter is optional " 683f91381e8SGreg Clayton "and defaults to the previous format that was used. The size letter is optional " 684f91381e8SGreg Clayton "and defaults to the previous size that was used.\n" 685f91381e8SGreg Clayton "\n" 686f91381e8SGreg Clayton "Format letters include:\n" 687f91381e8SGreg Clayton "o - octal\n" 688f91381e8SGreg Clayton "x - hexadecimal\n" 689f91381e8SGreg Clayton "d - decimal\n" 690f91381e8SGreg Clayton "u - unsigned decimal\n" 691f91381e8SGreg Clayton "t - binary\n" 692f91381e8SGreg Clayton "f - float\n" 693f91381e8SGreg Clayton "a - address\n" 694f91381e8SGreg Clayton "i - instruction\n" 695f91381e8SGreg Clayton "c - char\n" 696f91381e8SGreg Clayton "s - string\n" 697f91381e8SGreg Clayton "T - OSType\n" 698f91381e8SGreg Clayton "A - float as hex\n" 699f91381e8SGreg Clayton "\n" 700f91381e8SGreg Clayton "Size letters include:\n" 701f91381e8SGreg Clayton "b - 1 byte (byte)\n" 702f91381e8SGreg Clayton "h - 2 bytes (halfword)\n" 703f91381e8SGreg Clayton "w - 4 bytes (word)\n" 704f91381e8SGreg Clayton "g - 8 bytes (giant)\n" 705f91381e8SGreg Clayton "\n" 706f91381e8SGreg Clayton "Example formats:\n" 707f91381e8SGreg Clayton "32xb - show 32 1 byte hexadecimal integer values\n" 708f91381e8SGreg Clayton "16xh - show 16 2 byte hexadecimal integer values\n" 709f91381e8SGreg Clayton "64 - show 64 2 byte hexadecimal integer values (format and size from the last format)\n" 710f91381e8SGreg Clayton "dw - show 1 4 byte decimal integer value\n" 711f91381e8SGreg Clayton ; 712e139cf23SCaroline Tice } 713e139cf23SCaroline Tice 7140a3958e0SEnrico Granata static const char * 7150a3958e0SEnrico Granata FormatHelpTextCallback () 7160a3958e0SEnrico Granata { 71782a7d983SEnrico Granata 71882a7d983SEnrico Granata static char* help_text_ptr = NULL; 71982a7d983SEnrico Granata 72082a7d983SEnrico Granata if (help_text_ptr) 72182a7d983SEnrico Granata return help_text_ptr; 72282a7d983SEnrico Granata 7230a3958e0SEnrico Granata StreamString sstr; 7240a3958e0SEnrico Granata sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n"; 7250a3958e0SEnrico Granata for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1)) 7260a3958e0SEnrico Granata { 72782a7d983SEnrico Granata if (f != eFormatDefault) 72882a7d983SEnrico Granata sstr.PutChar('\n'); 72982a7d983SEnrico Granata 7300a3958e0SEnrico Granata char format_char = FormatManager::GetFormatAsFormatChar(f); 7310a3958e0SEnrico Granata if (format_char) 7320a3958e0SEnrico Granata sstr.Printf("'%c' or ", format_char); 7330a3958e0SEnrico Granata 73482a7d983SEnrico Granata sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f)); 7350a3958e0SEnrico Granata } 7360a3958e0SEnrico Granata 7370a3958e0SEnrico Granata sstr.Flush(); 7380a3958e0SEnrico Granata 7390a3958e0SEnrico Granata std::string data = sstr.GetString(); 7400a3958e0SEnrico Granata 74182a7d983SEnrico Granata help_text_ptr = new char[data.length()+1]; 7420a3958e0SEnrico Granata 74382a7d983SEnrico Granata data.copy(help_text_ptr, data.length()); 7440a3958e0SEnrico Granata 74582a7d983SEnrico Granata return help_text_ptr; 7460a3958e0SEnrico Granata } 7470a3958e0SEnrico Granata 7480a3958e0SEnrico Granata static const char * 74982a7d983SEnrico Granata SummaryStringHelpTextCallback() 7500a3958e0SEnrico Granata { 75182a7d983SEnrico Granata return 75282a7d983SEnrico Granata "A summary string is a way to extract information from variables in order to present them using a summary.\n" 75382a7d983SEnrico Granata "Summary strings contain static text, variables, scopes and control sequences:\n" 75482a7d983SEnrico Granata " - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n" 75582a7d983SEnrico Granata " - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n" 75682a7d983SEnrico Granata " - Scopes are any sequence of text between { and }. Anything included in a scope will only appear in the output summary if there were no errors.\n" 75782a7d983SEnrico Granata " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n" 75882a7d983SEnrico Granata "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n" 75982a7d983SEnrico Granata "A variable is expanded by giving it a value other than its textual representation, and the way this is done depends on what comes after the ${ marker.\n" 76082a7d983SEnrico Granata "The most common sequence if ${var followed by an expression path, which is the text one would type to access a member of an aggregate types, given a variable of that type" 76182a7d983SEnrico Granata " (e.g. if type T has a member named x, which has a member named y, and if t is of type T, the expression path would be .x.y and the way to fit that into a summary string would be" 7629128ee2fSEnrico Granata " ${var.x.y}). You can also use ${*var followed by an expression path and in that case the object referred by the path will be dereferenced before being displayed." 7639128ee2fSEnrico Granata " If the object is not a pointer, doing so will cause an error. For additional details on expression paths, you can type 'help expr-path'. \n" 76482a7d983SEnrico Granata "By default, summary strings attempt to display the summary for any variable they reference, and if that fails the value. If neither can be shown, nothing is displayed." 76582a7d983SEnrico Granata "In a summary string, you can also use an array index [n], or a slice-like range [n-m]. This can have two different meanings depending on what kind of object the expression" 76682a7d983SEnrico Granata " path refers to:\n" 76782a7d983SEnrico Granata " - if it is a scalar type (any basic type like int, float, ...) the expression is a bitfield, i.e. the bits indicated by the indexing operator are extracted out of the number" 76882a7d983SEnrico Granata " and displayed as an individual variable\n" 76982a7d983SEnrico Granata " - if it is an array or pointer the array items indicated by the indexing operator are shown as the result of the variable. if the expression is an array, real array items are" 77082a7d983SEnrico Granata " printed; if it is a pointer, the pointer-as-array syntax is used to obtain the values (this means, the latter case can have no range checking)\n" 7719128ee2fSEnrico Granata "If you are trying to display an array for which the size is known, you can also use [] instead of giving an exact range. This has the effect of showing items 0 thru size - 1.\n" 7729128ee2fSEnrico Granata "Additionally, a variable can contain an (optional) format code, as in ${var.x.y%code}, where code can be any of the valid formats described in 'help format', or one of the" 7739128ee2fSEnrico Granata " special symbols only allowed as part of a variable:\n" 7749128ee2fSEnrico Granata " %V: show the value of the object by default\n" 7759128ee2fSEnrico Granata " %S: show the summary of the object by default\n" 7769128ee2fSEnrico Granata " %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n" 7779128ee2fSEnrico Granata " %L: show the location of the object (memory address or a register name)\n" 7789128ee2fSEnrico Granata " %#: show the number of children of the object\n" 7799128ee2fSEnrico Granata " %T: show the type of the object\n" 7809128ee2fSEnrico Granata "Another variable that you can use in summary strings is ${svar . This sequence works exactly like ${var, including the fact that ${*svar is an allowed sequence, but uses" 7819128ee2fSEnrico Granata " the object's synthetic children provider instead of the actual objects. For instance, if you are using STL synthetic children providers, the following summary string would" 7829128ee2fSEnrico Granata " count the number of actual elements stored in an std::list:\n" 7839128ee2fSEnrico Granata "type summary add -s \"${svar%#}\" -x \"std::list<\""; 7849128ee2fSEnrico Granata } 7859128ee2fSEnrico Granata 7869128ee2fSEnrico Granata static const char * 7879128ee2fSEnrico Granata ExprPathHelpTextCallback() 7889128ee2fSEnrico Granata { 7899128ee2fSEnrico Granata return 7909128ee2fSEnrico Granata "An expression path is the sequence of symbols that is used in C/C++ to access a member variable of an aggregate object (class).\n" 7919128ee2fSEnrico Granata "For instance, given a class:\n" 7929128ee2fSEnrico Granata " class foo {\n" 7939128ee2fSEnrico Granata " int a;\n" 7949128ee2fSEnrico Granata " int b; .\n" 7959128ee2fSEnrico Granata " foo* next;\n" 7969128ee2fSEnrico Granata " };\n" 7979128ee2fSEnrico Granata "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n" 7989128ee2fSEnrico Granata "Given that aFoo could just be any object of type foo, the string '.next->b' is the expression path, because it can be attached to any foo instance to achieve the effect.\n" 7999128ee2fSEnrico Granata "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n" 8009128ee2fSEnrico Granata "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n" 8019128ee2fSEnrico Granata "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n" 8029128ee2fSEnrico Granata "for objects of native types (int, float, char, ...) saying '[n-m]' as an expression path (where n and m are any positive integers, e.g. [3-5]) causes LLDB to extract" 8039128ee2fSEnrico Granata " bits n thru m from the value of the variable. If n == m, [n] is also allowed as a shortcut syntax. For arrays and pointers, expression paths can only contain one index" 8049128ee2fSEnrico Granata " and the meaning of the operation is the same as the one defined by C/C++ (item extraction). Some commands extend bitfield-like syntax for arrays and pointers with the" 8059128ee2fSEnrico Granata " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory)."; 8060a3958e0SEnrico Granata } 8070a3958e0SEnrico Granata 808184d7a72SJohnny Chen void 809de753464SJohnny Chen CommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange) 810184d7a72SJohnny Chen { 811184d7a72SJohnny Chen CommandArgumentData id_arg; 812184d7a72SJohnny Chen CommandArgumentData id_range_arg; 813184d7a72SJohnny Chen 814184d7a72SJohnny Chen // Create the first variant for the first (and only) argument for this command. 815de753464SJohnny Chen id_arg.arg_type = ID; 816184d7a72SJohnny Chen id_arg.arg_repetition = eArgRepeatOptional; 817184d7a72SJohnny Chen 818184d7a72SJohnny Chen // Create the second variant for the first (and only) argument for this command. 819de753464SJohnny Chen id_range_arg.arg_type = IDRange; 820184d7a72SJohnny Chen id_range_arg.arg_repetition = eArgRepeatOptional; 821184d7a72SJohnny Chen 822a3234732SJohnny Chen // The first (and only) argument for this command could be either an id or an id_range. 823184d7a72SJohnny Chen // Push both variants into the entry for the first argument for this command. 824184d7a72SJohnny Chen arg.push_back(id_arg); 825184d7a72SJohnny Chen arg.push_back(id_range_arg); 826184d7a72SJohnny Chen } 827184d7a72SJohnny Chen 8289d0402b1SGreg Clayton const char * 8299d0402b1SGreg Clayton CommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type) 8309d0402b1SGreg Clayton { 8319d0402b1SGreg Clayton if (arg_type >=0 && arg_type < eArgTypeLastArg) 8329d0402b1SGreg Clayton return g_arguments_data[arg_type].arg_name; 8339d0402b1SGreg Clayton return NULL; 8349d0402b1SGreg Clayton 8359d0402b1SGreg Clayton } 8369d0402b1SGreg Clayton 8379d0402b1SGreg Clayton const char * 8389d0402b1SGreg Clayton CommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type) 8399d0402b1SGreg Clayton { 8409d0402b1SGreg Clayton if (arg_type >=0 && arg_type < eArgTypeLastArg) 8419d0402b1SGreg Clayton return g_arguments_data[arg_type].help_text; 8429d0402b1SGreg Clayton return NULL; 8439d0402b1SGreg Clayton } 8449d0402b1SGreg Clayton 8455a988416SJim Ingham bool 8465a988416SJim Ingham CommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result) 8475a988416SJim Ingham { 8485a988416SJim Ingham CommandOverrideCallback command_callback = GetOverrideCallback(); 8495a988416SJim Ingham bool handled = false; 8505a988416SJim Ingham Args cmd_args (args_string); 8515a988416SJim Ingham if (command_callback) 8525a988416SJim Ingham { 8535a988416SJim Ingham Args full_args (GetCommandName ()); 8545a988416SJim Ingham full_args.AppendArguments(cmd_args); 8555a988416SJim Ingham handled = command_callback (GetOverrideCallbackBaton(), full_args.GetConstArgumentVector()); 8565a988416SJim Ingham } 8575a988416SJim Ingham if (!handled) 8585a988416SJim Ingham { 8595a988416SJim Ingham for (size_t i = 0; i < cmd_args.GetArgumentCount(); ++i) 8605a988416SJim Ingham { 8615a988416SJim Ingham const char *tmp_str = cmd_args.GetArgumentAtIndex (i); 8625a988416SJim Ingham if (tmp_str[0] == '`') // back-quote 8635a988416SJim Ingham cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str)); 8645a988416SJim Ingham } 8655a988416SJim Ingham 8665a988416SJim Ingham if (!CheckFlags(result)) 8675a988416SJim Ingham return false; 8685a988416SJim Ingham 8695a988416SJim Ingham if (!ParseOptions (cmd_args, result)) 8705a988416SJim Ingham return false; 8715a988416SJim Ingham 8725a988416SJim Ingham // Call the command-specific version of 'Execute', passing it the already processed arguments. 8735a988416SJim Ingham handled = DoExecute (cmd_args, result); 8745a988416SJim Ingham } 8755a988416SJim Ingham return handled; 8765a988416SJim Ingham } 8775a988416SJim Ingham 8785a988416SJim Ingham bool 8795a988416SJim Ingham CommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result) 8805a988416SJim Ingham { 8815a988416SJim Ingham CommandOverrideCallback command_callback = GetOverrideCallback(); 8825a988416SJim Ingham bool handled = false; 8835a988416SJim Ingham if (command_callback) 8845a988416SJim Ingham { 8855a988416SJim Ingham std::string full_command (GetCommandName ()); 8865a988416SJim Ingham full_command += ' '; 8875a988416SJim Ingham full_command += args_string; 8885a988416SJim Ingham const char *argv[2] = { NULL, NULL }; 8895a988416SJim Ingham argv[0] = full_command.c_str(); 8905a988416SJim Ingham handled = command_callback (GetOverrideCallbackBaton(), argv); 8915a988416SJim Ingham } 8925a988416SJim Ingham if (!handled) 8935a988416SJim Ingham { 8945a988416SJim Ingham if (!CheckFlags(result)) 8955a988416SJim Ingham return false; 8965a988416SJim Ingham else 8975a988416SJim Ingham handled = DoExecute (args_string, result); 8985a988416SJim Ingham } 8995a988416SJim Ingham return handled; 9005a988416SJim Ingham } 9015a988416SJim Ingham 902ca7835c6SJohnny Chen static 903ca7835c6SJohnny Chen const char *arch_helper() 904ca7835c6SJohnny Chen { 905d70b14eaSGreg Clayton static StreamString g_archs_help; 906797a1b37SJohnny Chen if (g_archs_help.Empty()) 907d70b14eaSGreg Clayton { 908ca7835c6SJohnny Chen StringList archs; 909ca7835c6SJohnny Chen ArchSpec::AutoComplete(NULL, archs); 910d70b14eaSGreg Clayton g_archs_help.Printf("These are the supported architecture names:\n"); 911797a1b37SJohnny Chen archs.Join("\n", g_archs_help); 912d70b14eaSGreg Clayton } 913d70b14eaSGreg Clayton return g_archs_help.GetData(); 914ca7835c6SJohnny Chen } 915ca7835c6SJohnny Chen 916e139cf23SCaroline Tice CommandObject::ArgumentTableEntry 917e139cf23SCaroline Tice CommandObject::g_arguments_data[] = 918e139cf23SCaroline Tice { 9197f941d95SEnrico Granata { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { NULL, false }, "A valid address in the target program's execution space." }, 9207f941d95SEnrico Granata { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of an abbreviation (alias) for a debugger command." }, 9217f941d95SEnrico Granata { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { NULL, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, 922ca7835c6SJohnny Chen { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." }, 9237f941d95SEnrico Granata { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { NULL, false }, "A Boolean value: 'true' or 'false'" }, 9247f941d95SEnrico Granata { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, NULL }, 9257f941d95SEnrico Granata { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, NULL }, 9267f941d95SEnrico Granata { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { NULL, false }, "Number of bytes to use." }, 9277f941d95SEnrico Granata { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { NULL, false }, "Then name of a class from the debug information in the program." }, 9287f941d95SEnrico Granata { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { NULL, false }, "A debugger command (may be multiple words), without any options or arguments." }, 9297f941d95SEnrico Granata { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, 9307f941d95SEnrico Granata { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9317f941d95SEnrico Granata { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9329128ee2fSEnrico Granata { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, NULL }, 9337f941d95SEnrico Granata { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { NULL, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, 9347f941d95SEnrico Granata { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { NULL, false }, "The name of a file (can include path)." }, 9357f941d95SEnrico Granata { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, NULL }, 9367f941d95SEnrico Granata { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into a thread's list of frames." }, 9377f941d95SEnrico Granata { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9387f941d95SEnrico Granata { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function." }, 939*cd8b7cd0SSean Callanan { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a function or symbol." }, 94086edbf41SGreg Clayton { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, NULL }, 9417f941d95SEnrico Granata { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a list." }, 942fab10e89SJim Ingham { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { NULL, false }, "A source language name." }, 9437f941d95SEnrico Granata { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { NULL, false }, "Line number in a source file." }, 9447f941d95SEnrico Granata { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, 9457f941d95SEnrico Granata { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, 9467f941d95SEnrico Granata { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { NULL, false }, "A C++ method name." }, 9477f941d95SEnrico Granata { eArgTypeName, "name", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9487f941d95SEnrico Granata { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9497f941d95SEnrico Granata { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { NULL, false }, "The number of lines to use." }, 9507f941d95SEnrico Granata { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { NULL, false }, "The number of items per line to display." }, 9517f941d95SEnrico Granata { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9527f941d95SEnrico Granata { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9537f941d95SEnrico Granata { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { NULL, false }, "A command that is entered as a single line of text." }, 9547f941d95SEnrico Granata { eArgTypePath, "path", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9557f941d95SEnrico Granata { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { NULL, false }, "The process ID number." }, 9567f941d95SEnrico Granata { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9577f941d95SEnrico Granata { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the process." }, 9589128ee2fSEnrico Granata { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python class." }, 9599128ee2fSEnrico Granata { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a Python function." }, 9609128ee2fSEnrico Granata { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { NULL, false }, "Source code written in Python." }, 9617f941d95SEnrico Granata { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of the thread queue." }, 962931e674aSJim Ingham { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, NULL }, 9637f941d95SEnrico Granata { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { NULL, false }, "A regular expression." }, 9647f941d95SEnrico Granata { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { NULL, false }, "Arguments to be passed to the target program when it starts executing." }, 9657f941d95SEnrico Granata { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9660a305db7SEnrico Granata { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { NULL, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." }, 9677f941d95SEnrico Granata { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { NULL, false }, "The scripting language to be used for script-based commands. Currently only Python is valid." }, 9687f941d95SEnrico Granata { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { NULL, false }, "The word for which you wish to search for information about." }, 9697f941d95SEnrico Granata { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { NULL, false }, "An Objective-C selector name." }, 9707f941d95SEnrico Granata { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { NULL, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, 9717f941d95SEnrico Granata { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { NULL, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, 9727f941d95SEnrico Granata { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, 9737f941d95SEnrico Granata { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, 9747f941d95SEnrico Granata { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a shared library." }, 9757f941d95SEnrico Granata { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { NULL, false }, "The name of a source file.." }, 9767f941d95SEnrico Granata { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { NULL, false }, "Specify a sort order when dumping lists." }, 9777f941d95SEnrico Granata { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9787f941d95SEnrico Granata { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, NULL }, 9797f941d95SEnrico Granata { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { NULL, false }, "Any symbol name (function name, variable, argument, etc.)" }, 9807f941d95SEnrico Granata { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { NULL, false }, "Thread ID number." }, 9817f941d95SEnrico Granata { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { NULL, false }, "Index into the process' list of threads." }, 9827f941d95SEnrico Granata { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { NULL, false }, "The thread's name." }, 983331eff39SJohnny Chen { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { NULL, false }, "An unsigned integer." }, 9847f941d95SEnrico Granata { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { NULL, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, 9857f941d95SEnrico Granata { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { NULL, false }, "The name of a variable in your program." }, 9867f941d95SEnrico Granata { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { NULL, false }, "A value could be anything, depending on where and how it is used." }, 9877f941d95SEnrico Granata { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { NULL, false }, "Help text goes here." }, 9887f941d95SEnrico Granata { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { NULL, false }, "No help available for this." }, 989b1d7529eSJohnny Chen { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { NULL, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." }, 990de753464SJohnny Chen { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { NULL, false }, "Watchpoint IDs are positive integers." }, 991de753464SJohnny Chen { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { NULL, false }, "For example, '1-3' or '1 to 3'." }, 992887062aeSJohnny Chen { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { NULL, false }, "Specify the type for a watchpoint." } 993e139cf23SCaroline Tice }; 994e139cf23SCaroline Tice 995e139cf23SCaroline Tice const CommandObject::ArgumentTableEntry* 996e139cf23SCaroline Tice CommandObject::GetArgumentTable () 997e139cf23SCaroline Tice { 9989d0402b1SGreg Clayton // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration 9999d0402b1SGreg Clayton assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg); 1000e139cf23SCaroline Tice return CommandObject::g_arguments_data; 1001e139cf23SCaroline Tice } 1002e139cf23SCaroline Tice 1003e139cf23SCaroline Tice 1004