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