1*30fdc8d8SChris Lattner //===-- CommandObject.cpp ---------------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner 10*30fdc8d8SChris Lattner #include "lldb/Interpreter/CommandObject.h" 11*30fdc8d8SChris Lattner 12*30fdc8d8SChris Lattner #include <string> 13*30fdc8d8SChris Lattner #include <map> 14*30fdc8d8SChris Lattner 15*30fdc8d8SChris Lattner #include <getopt.h> 16*30fdc8d8SChris Lattner #include <stdlib.h> 17*30fdc8d8SChris Lattner #include <ctype.h> 18*30fdc8d8SChris Lattner 19*30fdc8d8SChris Lattner #include "lldb/Core/Address.h" 20*30fdc8d8SChris Lattner #include "lldb/Core/Options.h" 21*30fdc8d8SChris Lattner 22*30fdc8d8SChris Lattner // These are for the Sourcename completers. 23*30fdc8d8SChris Lattner // FIXME: Make a separate file for the completers. 24*30fdc8d8SChris Lattner #include "lldb/Core/FileSpec.h" 25*30fdc8d8SChris Lattner #include "lldb/Core/FileSpecList.h" 26*30fdc8d8SChris Lattner #include "lldb/Target/Process.h" 27*30fdc8d8SChris Lattner #include "lldb/Target/Target.h" 28*30fdc8d8SChris Lattner 29*30fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 30*30fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 31*30fdc8d8SChris Lattner #include "lldb/Interpreter/ScriptInterpreter.h" 32*30fdc8d8SChris Lattner #include "lldb/Interpreter/ScriptInterpreterPython.h" 33*30fdc8d8SChris Lattner 34*30fdc8d8SChris Lattner using namespace lldb; 35*30fdc8d8SChris Lattner using namespace lldb_private; 36*30fdc8d8SChris Lattner 37*30fdc8d8SChris Lattner //------------------------------------------------------------------------- 38*30fdc8d8SChris Lattner // CommandObject 39*30fdc8d8SChris Lattner //------------------------------------------------------------------------- 40*30fdc8d8SChris Lattner 41*30fdc8d8SChris Lattner CommandObject::CommandObject (const char *name, const char *help, const char *syntax, uint32_t flags) : 42*30fdc8d8SChris Lattner m_cmd_name (name), 43*30fdc8d8SChris Lattner m_cmd_help_short (), 44*30fdc8d8SChris Lattner m_cmd_help_long (), 45*30fdc8d8SChris Lattner m_cmd_syntax (), 46*30fdc8d8SChris Lattner m_flags (flags) 47*30fdc8d8SChris Lattner { 48*30fdc8d8SChris Lattner if (help && help[0]) 49*30fdc8d8SChris Lattner m_cmd_help_short = help; 50*30fdc8d8SChris Lattner if (syntax && syntax[0]) 51*30fdc8d8SChris Lattner m_cmd_syntax = syntax; 52*30fdc8d8SChris Lattner } 53*30fdc8d8SChris Lattner 54*30fdc8d8SChris Lattner CommandObject::~CommandObject () 55*30fdc8d8SChris Lattner { 56*30fdc8d8SChris Lattner } 57*30fdc8d8SChris Lattner 58*30fdc8d8SChris Lattner const char * 59*30fdc8d8SChris Lattner CommandObject::GetHelp () 60*30fdc8d8SChris Lattner { 61*30fdc8d8SChris Lattner return m_cmd_help_short.c_str(); 62*30fdc8d8SChris Lattner } 63*30fdc8d8SChris Lattner 64*30fdc8d8SChris Lattner const char * 65*30fdc8d8SChris Lattner CommandObject::GetHelpLong () 66*30fdc8d8SChris Lattner { 67*30fdc8d8SChris Lattner return m_cmd_help_long.c_str(); 68*30fdc8d8SChris Lattner } 69*30fdc8d8SChris Lattner 70*30fdc8d8SChris Lattner const char * 71*30fdc8d8SChris Lattner CommandObject::GetSyntax () 72*30fdc8d8SChris Lattner { 73*30fdc8d8SChris Lattner return m_cmd_syntax.c_str(); 74*30fdc8d8SChris Lattner } 75*30fdc8d8SChris Lattner 76*30fdc8d8SChris Lattner const char * 77*30fdc8d8SChris Lattner CommandObject::Translate () 78*30fdc8d8SChris Lattner { 79*30fdc8d8SChris Lattner //return m_cmd_func_name.c_str(); 80*30fdc8d8SChris Lattner return "This function is currently not implemented."; 81*30fdc8d8SChris Lattner } 82*30fdc8d8SChris Lattner 83*30fdc8d8SChris Lattner const char * 84*30fdc8d8SChris Lattner CommandObject::GetCommandName () 85*30fdc8d8SChris Lattner { 86*30fdc8d8SChris Lattner return m_cmd_name.c_str(); 87*30fdc8d8SChris Lattner } 88*30fdc8d8SChris Lattner 89*30fdc8d8SChris Lattner void 90*30fdc8d8SChris Lattner CommandObject::SetCommandName (const char *name) 91*30fdc8d8SChris Lattner { 92*30fdc8d8SChris Lattner m_cmd_name = name; 93*30fdc8d8SChris Lattner } 94*30fdc8d8SChris Lattner 95*30fdc8d8SChris Lattner void 96*30fdc8d8SChris Lattner CommandObject::SetHelp (const char *cstr) 97*30fdc8d8SChris Lattner { 98*30fdc8d8SChris Lattner m_cmd_help_short = cstr; 99*30fdc8d8SChris Lattner } 100*30fdc8d8SChris Lattner 101*30fdc8d8SChris Lattner void 102*30fdc8d8SChris Lattner CommandObject::SetHelpLong (const char *cstr) 103*30fdc8d8SChris Lattner { 104*30fdc8d8SChris Lattner m_cmd_help_long = cstr; 105*30fdc8d8SChris Lattner } 106*30fdc8d8SChris Lattner 107*30fdc8d8SChris Lattner void 108*30fdc8d8SChris Lattner CommandObject::SetSyntax (const char *cstr) 109*30fdc8d8SChris Lattner { 110*30fdc8d8SChris Lattner m_cmd_syntax = cstr; 111*30fdc8d8SChris Lattner } 112*30fdc8d8SChris Lattner 113*30fdc8d8SChris Lattner Options * 114*30fdc8d8SChris Lattner CommandObject::GetOptions () 115*30fdc8d8SChris Lattner { 116*30fdc8d8SChris Lattner // By default commands don't have options unless this virtual function 117*30fdc8d8SChris Lattner // is overridden by base classes. 118*30fdc8d8SChris Lattner return NULL; 119*30fdc8d8SChris Lattner } 120*30fdc8d8SChris Lattner 121*30fdc8d8SChris Lattner Flags& 122*30fdc8d8SChris Lattner CommandObject::GetFlags() 123*30fdc8d8SChris Lattner { 124*30fdc8d8SChris Lattner return m_flags; 125*30fdc8d8SChris Lattner } 126*30fdc8d8SChris Lattner 127*30fdc8d8SChris Lattner const Flags& 128*30fdc8d8SChris Lattner CommandObject::GetFlags() const 129*30fdc8d8SChris Lattner { 130*30fdc8d8SChris Lattner return m_flags; 131*30fdc8d8SChris Lattner } 132*30fdc8d8SChris Lattner 133*30fdc8d8SChris Lattner bool 134*30fdc8d8SChris Lattner CommandObject::ExecuteCommandString 135*30fdc8d8SChris Lattner ( 136*30fdc8d8SChris Lattner const char *command_line, 137*30fdc8d8SChris Lattner CommandContext *context, 138*30fdc8d8SChris Lattner CommandInterpreter *interpreter, 139*30fdc8d8SChris Lattner CommandReturnObject &result 140*30fdc8d8SChris Lattner ) 141*30fdc8d8SChris Lattner { 142*30fdc8d8SChris Lattner Args command_args(command_line); 143*30fdc8d8SChris Lattner return ExecuteWithOptions (command_args, context, interpreter, result); 144*30fdc8d8SChris Lattner } 145*30fdc8d8SChris Lattner 146*30fdc8d8SChris Lattner bool 147*30fdc8d8SChris Lattner CommandObject::ParseOptions 148*30fdc8d8SChris Lattner ( 149*30fdc8d8SChris Lattner Args& args, 150*30fdc8d8SChris Lattner CommandInterpreter *interpreter, 151*30fdc8d8SChris Lattner CommandReturnObject &result 152*30fdc8d8SChris Lattner ) 153*30fdc8d8SChris Lattner { 154*30fdc8d8SChris Lattner // See if the subclass has options? 155*30fdc8d8SChris Lattner Options *options = GetOptions(); 156*30fdc8d8SChris Lattner if (options != NULL) 157*30fdc8d8SChris Lattner { 158*30fdc8d8SChris Lattner Error error; 159*30fdc8d8SChris Lattner options->ResetOptionValues(); 160*30fdc8d8SChris Lattner 161*30fdc8d8SChris Lattner // ParseOptions calls getopt_long, which always skips the zero'th item in the array and starts at position 1, 162*30fdc8d8SChris Lattner // so we need to push a dummy value into position zero. 163*30fdc8d8SChris Lattner args.Unshift("dummy_string"); 164*30fdc8d8SChris Lattner error = args.ParseOptions (*options); 165*30fdc8d8SChris Lattner 166*30fdc8d8SChris Lattner // The "dummy_string" will have already been removed by ParseOptions, 167*30fdc8d8SChris Lattner // so no need to remove it. 168*30fdc8d8SChris Lattner 169*30fdc8d8SChris Lattner if (error.Fail() || !options->VerifyOptions (result)) 170*30fdc8d8SChris Lattner { 171*30fdc8d8SChris Lattner const char *error_cstr = error.AsCString(); 172*30fdc8d8SChris Lattner if (error_cstr) 173*30fdc8d8SChris Lattner { 174*30fdc8d8SChris Lattner // We got an error string, lets use that 175*30fdc8d8SChris Lattner result.GetErrorStream().PutCString(error_cstr); 176*30fdc8d8SChris Lattner } 177*30fdc8d8SChris Lattner else 178*30fdc8d8SChris Lattner { 179*30fdc8d8SChris Lattner // No error string, output the usage information into result 180*30fdc8d8SChris Lattner options->GenerateOptionUsage (result.GetErrorStream(), this); 181*30fdc8d8SChris Lattner } 182*30fdc8d8SChris Lattner // Set the return status to failed (this was an error). 183*30fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 184*30fdc8d8SChris Lattner return false; 185*30fdc8d8SChris Lattner } 186*30fdc8d8SChris Lattner } 187*30fdc8d8SChris Lattner return true; 188*30fdc8d8SChris Lattner } 189*30fdc8d8SChris Lattner bool 190*30fdc8d8SChris Lattner CommandObject::ExecuteWithOptions 191*30fdc8d8SChris Lattner ( 192*30fdc8d8SChris Lattner Args& args, 193*30fdc8d8SChris Lattner CommandContext *context, 194*30fdc8d8SChris Lattner CommandInterpreter *interpreter, 195*30fdc8d8SChris Lattner CommandReturnObject &result 196*30fdc8d8SChris Lattner ) 197*30fdc8d8SChris Lattner { 198*30fdc8d8SChris Lattner for (size_t i = 0; i < args.GetArgumentCount(); ++i) 199*30fdc8d8SChris Lattner { 200*30fdc8d8SChris Lattner const char *tmp_str = args.GetArgumentAtIndex (i); 201*30fdc8d8SChris Lattner if (tmp_str[0] == '`') // back-quote 202*30fdc8d8SChris Lattner args.ReplaceArgumentAtIndex (i, interpreter->ProcessEmbeddedScriptCommands (tmp_str)); 203*30fdc8d8SChris Lattner } 204*30fdc8d8SChris Lattner 205*30fdc8d8SChris Lattner Process *process = context->GetExecutionContext().process; 206*30fdc8d8SChris Lattner if (process == NULL) 207*30fdc8d8SChris Lattner { 208*30fdc8d8SChris Lattner if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused)) 209*30fdc8d8SChris Lattner { 210*30fdc8d8SChris Lattner result.AppendError ("Process must exist."); 211*30fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 212*30fdc8d8SChris Lattner return false; 213*30fdc8d8SChris Lattner } 214*30fdc8d8SChris Lattner } 215*30fdc8d8SChris Lattner else 216*30fdc8d8SChris Lattner { 217*30fdc8d8SChris Lattner StateType state = process->GetState(); 218*30fdc8d8SChris Lattner 219*30fdc8d8SChris Lattner switch (state) 220*30fdc8d8SChris Lattner { 221*30fdc8d8SChris Lattner 222*30fdc8d8SChris Lattner case eStateAttaching: 223*30fdc8d8SChris Lattner case eStateLaunching: 224*30fdc8d8SChris Lattner case eStateSuspended: 225*30fdc8d8SChris Lattner case eStateCrashed: 226*30fdc8d8SChris Lattner case eStateStopped: 227*30fdc8d8SChris Lattner break; 228*30fdc8d8SChris Lattner 229*30fdc8d8SChris Lattner case eStateDetached: 230*30fdc8d8SChris Lattner case eStateExited: 231*30fdc8d8SChris Lattner case eStateUnloaded: 232*30fdc8d8SChris Lattner if (GetFlags().IsSet(CommandObject::eFlagProcessMustBeLaunched)) 233*30fdc8d8SChris Lattner { 234*30fdc8d8SChris Lattner result.AppendError ("Process must be launched."); 235*30fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 236*30fdc8d8SChris Lattner return false; 237*30fdc8d8SChris Lattner } 238*30fdc8d8SChris Lattner break; 239*30fdc8d8SChris Lattner 240*30fdc8d8SChris Lattner case eStateRunning: 241*30fdc8d8SChris Lattner case eStateStepping: 242*30fdc8d8SChris Lattner if (GetFlags().IsSet(CommandObject::eFlagProcessMustBePaused)) 243*30fdc8d8SChris Lattner { 244*30fdc8d8SChris Lattner result.AppendError ("Process is running. Use 'process interrupt' to pause execution."); 245*30fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 246*30fdc8d8SChris Lattner return false; 247*30fdc8d8SChris Lattner } 248*30fdc8d8SChris Lattner } 249*30fdc8d8SChris Lattner } 250*30fdc8d8SChris Lattner 251*30fdc8d8SChris Lattner if (!ParseOptions (args, interpreter, result)) 252*30fdc8d8SChris Lattner return false; 253*30fdc8d8SChris Lattner 254*30fdc8d8SChris Lattner // Call the command-specific version of 'Execute', passing it the already processed arguments. 255*30fdc8d8SChris Lattner return Execute (args, context, interpreter, result); 256*30fdc8d8SChris Lattner } 257*30fdc8d8SChris Lattner 258*30fdc8d8SChris Lattner class CommandDictCommandPartialMatch 259*30fdc8d8SChris Lattner { 260*30fdc8d8SChris Lattner public: 261*30fdc8d8SChris Lattner CommandDictCommandPartialMatch (const char *match_str) 262*30fdc8d8SChris Lattner { 263*30fdc8d8SChris Lattner m_match_str = match_str; 264*30fdc8d8SChris Lattner } 265*30fdc8d8SChris Lattner bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const 266*30fdc8d8SChris Lattner { 267*30fdc8d8SChris Lattner // A NULL or empty string matches everything. 268*30fdc8d8SChris Lattner if (m_match_str == NULL || *m_match_str == '\0') 269*30fdc8d8SChris Lattner return 1; 270*30fdc8d8SChris Lattner 271*30fdc8d8SChris Lattner size_t found = map_element.first.find (m_match_str, 0); 272*30fdc8d8SChris Lattner if (found == std::string::npos) 273*30fdc8d8SChris Lattner return 0; 274*30fdc8d8SChris Lattner else 275*30fdc8d8SChris Lattner return found == 0; 276*30fdc8d8SChris Lattner } 277*30fdc8d8SChris Lattner 278*30fdc8d8SChris Lattner private: 279*30fdc8d8SChris Lattner const char *m_match_str; 280*30fdc8d8SChris Lattner }; 281*30fdc8d8SChris Lattner 282*30fdc8d8SChris Lattner int 283*30fdc8d8SChris Lattner CommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str, 284*30fdc8d8SChris Lattner StringList &matches) 285*30fdc8d8SChris Lattner { 286*30fdc8d8SChris Lattner int number_added = 0; 287*30fdc8d8SChris Lattner CommandDictCommandPartialMatch matcher(cmd_str); 288*30fdc8d8SChris Lattner 289*30fdc8d8SChris Lattner CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher); 290*30fdc8d8SChris Lattner 291*30fdc8d8SChris Lattner while (matching_cmds != in_map.end()) 292*30fdc8d8SChris Lattner { 293*30fdc8d8SChris Lattner ++number_added; 294*30fdc8d8SChris Lattner matches.AppendString((*matching_cmds).first.c_str()); 295*30fdc8d8SChris Lattner matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);; 296*30fdc8d8SChris Lattner } 297*30fdc8d8SChris Lattner return number_added; 298*30fdc8d8SChris Lattner } 299*30fdc8d8SChris Lattner 300*30fdc8d8SChris Lattner int 301*30fdc8d8SChris Lattner CommandObject::HandleCompletion 302*30fdc8d8SChris Lattner ( 303*30fdc8d8SChris Lattner Args &input, 304*30fdc8d8SChris Lattner int &cursor_index, 305*30fdc8d8SChris Lattner int &cursor_char_position, 306*30fdc8d8SChris Lattner int match_start_point, 307*30fdc8d8SChris Lattner int max_return_elements, 308*30fdc8d8SChris Lattner CommandInterpreter *interpreter, 309*30fdc8d8SChris Lattner StringList &matches 310*30fdc8d8SChris Lattner ) 311*30fdc8d8SChris Lattner { 312*30fdc8d8SChris Lattner if (WantsRawCommandString()) 313*30fdc8d8SChris Lattner { 314*30fdc8d8SChris Lattner // FIXME: Abstract telling the completion to insert the completion character. 315*30fdc8d8SChris Lattner matches.Clear(); 316*30fdc8d8SChris Lattner return -1; 317*30fdc8d8SChris Lattner } 318*30fdc8d8SChris Lattner else 319*30fdc8d8SChris Lattner { 320*30fdc8d8SChris Lattner // Can we do anything generic with the options? 321*30fdc8d8SChris Lattner Options *cur_options = GetOptions(); 322*30fdc8d8SChris Lattner CommandReturnObject result; 323*30fdc8d8SChris Lattner OptionElementVector opt_element_vector; 324*30fdc8d8SChris Lattner 325*30fdc8d8SChris Lattner if (cur_options != NULL) 326*30fdc8d8SChris Lattner { 327*30fdc8d8SChris Lattner // Re-insert the dummy command name string which will have been 328*30fdc8d8SChris Lattner // stripped off: 329*30fdc8d8SChris Lattner input.Unshift ("dummy-string"); 330*30fdc8d8SChris Lattner cursor_index++; 331*30fdc8d8SChris Lattner 332*30fdc8d8SChris Lattner 333*30fdc8d8SChris Lattner // I stick an element on the end of the input, because if the last element is 334*30fdc8d8SChris Lattner // option that requires an argument, getopt_long will freak out. 335*30fdc8d8SChris Lattner 336*30fdc8d8SChris Lattner input.AppendArgument ("<FAKE-VALUE>"); 337*30fdc8d8SChris Lattner 338*30fdc8d8SChris Lattner input.ParseArgsForCompletion (*cur_options, opt_element_vector); 339*30fdc8d8SChris Lattner 340*30fdc8d8SChris Lattner input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1); 341*30fdc8d8SChris Lattner 342*30fdc8d8SChris Lattner bool handled_by_options; 343*30fdc8d8SChris Lattner handled_by_options = cur_options->HandleOptionCompletion(input, 344*30fdc8d8SChris Lattner opt_element_vector, 345*30fdc8d8SChris Lattner cursor_index, 346*30fdc8d8SChris Lattner cursor_char_position, 347*30fdc8d8SChris Lattner match_start_point, 348*30fdc8d8SChris Lattner max_return_elements, 349*30fdc8d8SChris Lattner interpreter, 350*30fdc8d8SChris Lattner matches); 351*30fdc8d8SChris Lattner if (handled_by_options) 352*30fdc8d8SChris Lattner return matches.GetSize(); 353*30fdc8d8SChris Lattner } 354*30fdc8d8SChris Lattner 355*30fdc8d8SChris Lattner // If we got here, the last word is not an option or an option argument. 356*30fdc8d8SChris Lattner return HandleArgumentCompletion(input, 357*30fdc8d8SChris Lattner cursor_index, 358*30fdc8d8SChris Lattner cursor_char_position, 359*30fdc8d8SChris Lattner opt_element_vector, 360*30fdc8d8SChris Lattner match_start_point, 361*30fdc8d8SChris Lattner max_return_elements, 362*30fdc8d8SChris Lattner interpreter, 363*30fdc8d8SChris Lattner matches); 364*30fdc8d8SChris Lattner } 365*30fdc8d8SChris Lattner } 366*30fdc8d8SChris Lattner 367*30fdc8d8SChris Lattner int 368*30fdc8d8SChris Lattner CommandObject::HandleArgumentCompletion 369*30fdc8d8SChris Lattner ( 370*30fdc8d8SChris Lattner Args &input, 371*30fdc8d8SChris Lattner int &cursor_index, 372*30fdc8d8SChris Lattner int &cursor_char_position, 373*30fdc8d8SChris Lattner OptionElementVector &opt_element_vector, 374*30fdc8d8SChris Lattner int match_start_point, 375*30fdc8d8SChris Lattner int max_return_elements, 376*30fdc8d8SChris Lattner CommandInterpreter *interpreter, 377*30fdc8d8SChris Lattner StringList &matches 378*30fdc8d8SChris Lattner ) 379*30fdc8d8SChris Lattner { 380*30fdc8d8SChris Lattner return 0; 381*30fdc8d8SChris Lattner } 382*30fdc8d8SChris Lattner 383*30fdc8d8SChris Lattner // Case insensitive version of ::strstr() 384*30fdc8d8SChris Lattner // Returns true if s2 is contained within s1. 385*30fdc8d8SChris Lattner 386*30fdc8d8SChris Lattner static bool 387*30fdc8d8SChris Lattner contains_string (const char *s1, const char *s2) 388*30fdc8d8SChris Lattner { 389*30fdc8d8SChris Lattner char *locase_s1 = (char *) malloc (strlen (s1) + 1); 390*30fdc8d8SChris Lattner char *locase_s2 = (char *) malloc (strlen (s2) + 1); 391*30fdc8d8SChris Lattner int i; 392*30fdc8d8SChris Lattner for (i = 0; s1 && s1[i] != '\0'; i++) 393*30fdc8d8SChris Lattner locase_s1[i] = ::tolower (s1[i]); 394*30fdc8d8SChris Lattner locase_s1[i] = '\0'; 395*30fdc8d8SChris Lattner for (i = 0; s2 && s2[i] != '\0'; i++) 396*30fdc8d8SChris Lattner locase_s2[i] = ::tolower (s2[i]); 397*30fdc8d8SChris Lattner locase_s2[i] = '\0'; 398*30fdc8d8SChris Lattner 399*30fdc8d8SChris Lattner const char *result = ::strstr (locase_s1, locase_s2); 400*30fdc8d8SChris Lattner free (locase_s1); 401*30fdc8d8SChris Lattner free (locase_s2); 402*30fdc8d8SChris Lattner // 'result' points into freed memory - but we're not 403*30fdc8d8SChris Lattner // deref'ing it so hopefully current/future compilers 404*30fdc8d8SChris Lattner // won't complain.. 405*30fdc8d8SChris Lattner 406*30fdc8d8SChris Lattner if (result == NULL) 407*30fdc8d8SChris Lattner return false; 408*30fdc8d8SChris Lattner else 409*30fdc8d8SChris Lattner return true; 410*30fdc8d8SChris Lattner } 411*30fdc8d8SChris Lattner 412*30fdc8d8SChris Lattner bool 413*30fdc8d8SChris Lattner CommandObject::HelpTextContainsWord (const char *search_word) 414*30fdc8d8SChris Lattner { 415*30fdc8d8SChris Lattner const char *short_help; 416*30fdc8d8SChris Lattner const char *long_help; 417*30fdc8d8SChris Lattner const char *syntax_help; 418*30fdc8d8SChris Lattner std::string options_usage_help; 419*30fdc8d8SChris Lattner 420*30fdc8d8SChris Lattner 421*30fdc8d8SChris Lattner bool found_word = false; 422*30fdc8d8SChris Lattner 423*30fdc8d8SChris Lattner short_help = GetHelp(); 424*30fdc8d8SChris Lattner long_help = GetHelpLong(); 425*30fdc8d8SChris Lattner syntax_help = GetSyntax(); 426*30fdc8d8SChris Lattner 427*30fdc8d8SChris Lattner if (contains_string (short_help, search_word)) 428*30fdc8d8SChris Lattner found_word = true; 429*30fdc8d8SChris Lattner else if (contains_string (long_help, search_word)) 430*30fdc8d8SChris Lattner found_word = true; 431*30fdc8d8SChris Lattner else if (contains_string (syntax_help, search_word)) 432*30fdc8d8SChris Lattner found_word = true; 433*30fdc8d8SChris Lattner 434*30fdc8d8SChris Lattner if (!found_word 435*30fdc8d8SChris Lattner && GetOptions() != NULL) 436*30fdc8d8SChris Lattner { 437*30fdc8d8SChris Lattner StreamString usage_help; 438*30fdc8d8SChris Lattner GetOptions()->GenerateOptionUsage (usage_help, this); 439*30fdc8d8SChris Lattner if (usage_help.GetSize() > 0) 440*30fdc8d8SChris Lattner { 441*30fdc8d8SChris Lattner const char *usage_text = usage_help.GetData(); 442*30fdc8d8SChris Lattner if (contains_string (usage_text, search_word)) 443*30fdc8d8SChris Lattner found_word = true; 444*30fdc8d8SChris Lattner } 445*30fdc8d8SChris Lattner } 446*30fdc8d8SChris Lattner 447*30fdc8d8SChris Lattner return found_word; 448*30fdc8d8SChris Lattner } 449