1254721Semaste//===-- CommandObject.cpp ---------------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Interpreter/CommandObject.h"
11254721Semaste
12254721Semaste#include <string>
13288943Sdim#include <sstream>
14254721Semaste#include <map>
15254721Semaste
16254721Semaste#include <stdlib.h>
17254721Semaste#include <ctype.h>
18254721Semaste
19254721Semaste#include "lldb/Core/Address.h"
20254721Semaste#include "lldb/Core/ArchSpec.h"
21254721Semaste#include "lldb/Interpreter/Options.h"
22254721Semaste
23254721Semaste// These are for the Sourcename completers.
24254721Semaste// FIXME: Make a separate file for the completers.
25254721Semaste#include "lldb/Host/FileSpec.h"
26254721Semaste#include "lldb/Core/FileSpecList.h"
27288943Sdim#include "lldb/DataFormatters/FormatManager.h"
28254721Semaste#include "lldb/Target/Process.h"
29254721Semaste#include "lldb/Target/Target.h"
30254721Semaste
31296417Sdim#include "lldb/Target/Language.h"
32296417Sdim
33254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
34254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
35254721Semaste
36254721Semasteusing namespace lldb;
37254721Semasteusing namespace lldb_private;
38254721Semaste
39254721Semaste//-------------------------------------------------------------------------
40254721Semaste// CommandObject
41254721Semaste//-------------------------------------------------------------------------
42254721Semaste
43254721SemasteCommandObject::CommandObject
44254721Semaste(
45254721Semaste    CommandInterpreter &interpreter,
46254721Semaste    const char *name,
47254721Semaste    const char *help,
48254721Semaste    const char *syntax,
49254721Semaste    uint32_t flags
50254721Semaste) :
51254721Semaste    m_interpreter (interpreter),
52280031Sdim    m_cmd_name (name ? name : ""),
53254721Semaste    m_cmd_help_short (),
54254721Semaste    m_cmd_help_long (),
55254721Semaste    m_cmd_syntax (),
56254721Semaste    m_is_alias (false),
57254721Semaste    m_flags (flags),
58254721Semaste    m_arguments(),
59276479Sdim    m_deprecated_command_override_callback (nullptr),
60276479Sdim    m_command_override_callback (nullptr),
61276479Sdim    m_command_override_baton (nullptr)
62254721Semaste{
63254721Semaste    if (help && help[0])
64254721Semaste        m_cmd_help_short = help;
65254721Semaste    if (syntax && syntax[0])
66254721Semaste        m_cmd_syntax = syntax;
67254721Semaste}
68254721Semaste
69254721SemasteCommandObject::~CommandObject ()
70254721Semaste{
71254721Semaste}
72254721Semaste
73254721Semasteconst char *
74254721SemasteCommandObject::GetHelp ()
75254721Semaste{
76254721Semaste    return m_cmd_help_short.c_str();
77254721Semaste}
78254721Semaste
79254721Semasteconst char *
80254721SemasteCommandObject::GetHelpLong ()
81254721Semaste{
82254721Semaste    return m_cmd_help_long.c_str();
83254721Semaste}
84254721Semaste
85254721Semasteconst char *
86254721SemasteCommandObject::GetSyntax ()
87254721Semaste{
88254721Semaste    if (m_cmd_syntax.length() == 0)
89254721Semaste    {
90254721Semaste        StreamString syntax_str;
91254721Semaste        syntax_str.Printf ("%s", GetCommandName());
92276479Sdim        if (GetOptions() != nullptr)
93254721Semaste            syntax_str.Printf (" <cmd-options>");
94254721Semaste        if (m_arguments.size() > 0)
95254721Semaste        {
96254721Semaste            syntax_str.Printf (" ");
97254721Semaste            if (WantsRawCommandString() && GetOptions() && GetOptions()->NumCommandOptions())
98254721Semaste                syntax_str.Printf("-- ");
99254721Semaste            GetFormattedCommandArguments (syntax_str);
100254721Semaste        }
101254721Semaste        m_cmd_syntax = syntax_str.GetData ();
102254721Semaste    }
103254721Semaste
104254721Semaste    return m_cmd_syntax.c_str();
105254721Semaste}
106254721Semaste
107254721Semasteconst char *
108254721SemasteCommandObject::GetCommandName ()
109254721Semaste{
110254721Semaste    return m_cmd_name.c_str();
111254721Semaste}
112254721Semaste
113254721Semastevoid
114254721SemasteCommandObject::SetCommandName (const char *name)
115254721Semaste{
116254721Semaste    m_cmd_name = name;
117254721Semaste}
118254721Semaste
119254721Semastevoid
120254721SemasteCommandObject::SetHelp (const char *cstr)
121254721Semaste{
122254721Semaste    m_cmd_help_short = cstr;
123254721Semaste}
124254721Semaste
125254721Semastevoid
126288943SdimCommandObject::SetHelp (std::string str)
127288943Sdim{
128288943Sdim    m_cmd_help_short = str;
129288943Sdim}
130288943Sdim
131288943Sdimvoid
132254721SemasteCommandObject::SetHelpLong (const char *cstr)
133254721Semaste{
134254721Semaste    m_cmd_help_long = cstr;
135254721Semaste}
136254721Semaste
137254721Semastevoid
138254721SemasteCommandObject::SetHelpLong (std::string str)
139254721Semaste{
140254721Semaste    m_cmd_help_long = str;
141254721Semaste}
142254721Semaste
143254721Semastevoid
144254721SemasteCommandObject::SetSyntax (const char *cstr)
145254721Semaste{
146254721Semaste    m_cmd_syntax = cstr;
147254721Semaste}
148254721Semaste
149254721SemasteOptions *
150254721SemasteCommandObject::GetOptions ()
151254721Semaste{
152254721Semaste    // By default commands don't have options unless this virtual function
153254721Semaste    // is overridden by base classes.
154276479Sdim    return nullptr;
155254721Semaste}
156254721Semaste
157254721Semastebool
158254721SemasteCommandObject::ParseOptions
159254721Semaste(
160254721Semaste    Args& args,
161254721Semaste    CommandReturnObject &result
162254721Semaste)
163254721Semaste{
164254721Semaste    // See if the subclass has options?
165254721Semaste    Options *options = GetOptions();
166276479Sdim    if (options != nullptr)
167254721Semaste    {
168254721Semaste        Error error;
169254721Semaste        options->NotifyOptionParsingStarting();
170254721Semaste
171254721Semaste        // ParseOptions calls getopt_long_only, which always skips the zero'th item in the array and starts at position 1,
172254721Semaste        // so we need to push a dummy value into position zero.
173254721Semaste        args.Unshift("dummy_string");
174254721Semaste        error = args.ParseOptions (*options);
175254721Semaste
176254721Semaste        // The "dummy_string" will have already been removed by ParseOptions,
177254721Semaste        // so no need to remove it.
178254721Semaste
179254721Semaste        if (error.Success())
180254721Semaste            error = options->NotifyOptionParsingFinished();
181254721Semaste
182254721Semaste        if (error.Success())
183254721Semaste        {
184254721Semaste            if (options->VerifyOptions (result))
185254721Semaste                return true;
186254721Semaste        }
187254721Semaste        else
188254721Semaste        {
189254721Semaste            const char *error_cstr = error.AsCString();
190254721Semaste            if (error_cstr)
191254721Semaste            {
192254721Semaste                // We got an error string, lets use that
193254721Semaste                result.AppendError(error_cstr);
194254721Semaste            }
195254721Semaste            else
196254721Semaste            {
197254721Semaste                // No error string, output the usage information into result
198254721Semaste                options->GenerateOptionUsage (result.GetErrorStream(), this);
199254721Semaste            }
200254721Semaste        }
201254721Semaste        result.SetStatus (eReturnStatusFailed);
202254721Semaste        return false;
203254721Semaste    }
204254721Semaste    return true;
205254721Semaste}
206254721Semaste
207254721Semaste
208254721Semaste
209254721Semastebool
210254721SemasteCommandObject::CheckRequirements (CommandReturnObject &result)
211254721Semaste{
212254721Semaste#ifdef LLDB_CONFIGURATION_DEBUG
213254721Semaste    // Nothing should be stored in m_exe_ctx between running commands as m_exe_ctx
214254721Semaste    // has shared pointers to the target, process, thread and frame and we don't
215254721Semaste    // want any CommandObject instances to keep any of these objects around
216254721Semaste    // longer than for a single command. Every command should call
217254721Semaste    // CommandObject::Cleanup() after it has completed
218254721Semaste    assert (m_exe_ctx.GetTargetPtr() == NULL);
219254721Semaste    assert (m_exe_ctx.GetProcessPtr() == NULL);
220254721Semaste    assert (m_exe_ctx.GetThreadPtr() == NULL);
221254721Semaste    assert (m_exe_ctx.GetFramePtr() == NULL);
222254721Semaste#endif
223254721Semaste
224254721Semaste    // Lock down the interpreter's execution context prior to running the
225254721Semaste    // command so we guarantee the selected target, process, thread and frame
226254721Semaste    // can't go away during the execution
227254721Semaste    m_exe_ctx = m_interpreter.GetExecutionContext();
228254721Semaste
229254721Semaste    const uint32_t flags = GetFlags().Get();
230288943Sdim    if (flags & (eCommandRequiresTarget   |
231288943Sdim                 eCommandRequiresProcess  |
232288943Sdim                 eCommandRequiresThread   |
233288943Sdim                 eCommandRequiresFrame    |
234288943Sdim                 eCommandTryTargetAPILock ))
235254721Semaste    {
236254721Semaste
237288943Sdim        if ((flags & eCommandRequiresTarget) && !m_exe_ctx.HasTargetScope())
238254721Semaste        {
239254721Semaste            result.AppendError (GetInvalidTargetDescription());
240254721Semaste            return false;
241254721Semaste        }
242254721Semaste
243288943Sdim        if ((flags & eCommandRequiresProcess) && !m_exe_ctx.HasProcessScope())
244254721Semaste        {
245280031Sdim            if (!m_exe_ctx.HasTargetScope())
246280031Sdim                result.AppendError (GetInvalidTargetDescription());
247280031Sdim            else
248280031Sdim                result.AppendError (GetInvalidProcessDescription());
249254721Semaste            return false;
250254721Semaste        }
251254721Semaste
252288943Sdim        if ((flags & eCommandRequiresThread) && !m_exe_ctx.HasThreadScope())
253254721Semaste        {
254280031Sdim            if (!m_exe_ctx.HasTargetScope())
255280031Sdim                result.AppendError (GetInvalidTargetDescription());
256280031Sdim            else if (!m_exe_ctx.HasProcessScope())
257280031Sdim                result.AppendError (GetInvalidProcessDescription());
258280031Sdim            else
259280031Sdim                result.AppendError (GetInvalidThreadDescription());
260254721Semaste            return false;
261254721Semaste        }
262254721Semaste
263288943Sdim        if ((flags & eCommandRequiresFrame) && !m_exe_ctx.HasFrameScope())
264254721Semaste        {
265280031Sdim            if (!m_exe_ctx.HasTargetScope())
266280031Sdim                result.AppendError (GetInvalidTargetDescription());
267280031Sdim            else if (!m_exe_ctx.HasProcessScope())
268280031Sdim                result.AppendError (GetInvalidProcessDescription());
269280031Sdim            else if (!m_exe_ctx.HasThreadScope())
270280031Sdim                result.AppendError (GetInvalidThreadDescription());
271280031Sdim            else
272280031Sdim                result.AppendError (GetInvalidFrameDescription());
273254721Semaste            return false;
274254721Semaste        }
275254721Semaste
276288943Sdim        if ((flags & eCommandRequiresRegContext) && (m_exe_ctx.GetRegisterContext() == nullptr))
277254721Semaste        {
278254721Semaste            result.AppendError (GetInvalidRegContextDescription());
279254721Semaste            return false;
280254721Semaste        }
281254721Semaste
282288943Sdim        if (flags & eCommandTryTargetAPILock)
283254721Semaste        {
284254721Semaste            Target *target = m_exe_ctx.GetTargetPtr();
285254721Semaste            if (target)
286262528Semaste                m_api_locker.Lock (target->GetAPIMutex());
287254721Semaste        }
288254721Semaste    }
289254721Semaste
290288943Sdim    if (GetFlags().AnySet (eCommandProcessMustBeLaunched | eCommandProcessMustBePaused))
291254721Semaste    {
292254721Semaste        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
293276479Sdim        if (process == nullptr)
294254721Semaste        {
295254721Semaste            // A process that is not running is considered paused.
296288943Sdim            if (GetFlags().Test(eCommandProcessMustBeLaunched))
297254721Semaste            {
298254721Semaste                result.AppendError ("Process must exist.");
299254721Semaste                result.SetStatus (eReturnStatusFailed);
300254721Semaste                return false;
301254721Semaste            }
302254721Semaste        }
303254721Semaste        else
304254721Semaste        {
305254721Semaste            StateType state = process->GetState();
306254721Semaste            switch (state)
307254721Semaste            {
308254721Semaste            case eStateInvalid:
309254721Semaste            case eStateSuspended:
310254721Semaste            case eStateCrashed:
311254721Semaste            case eStateStopped:
312254721Semaste                break;
313254721Semaste
314254721Semaste            case eStateConnected:
315254721Semaste            case eStateAttaching:
316254721Semaste            case eStateLaunching:
317254721Semaste            case eStateDetached:
318254721Semaste            case eStateExited:
319254721Semaste            case eStateUnloaded:
320288943Sdim                if (GetFlags().Test(eCommandProcessMustBeLaunched))
321254721Semaste                {
322254721Semaste                    result.AppendError ("Process must be launched.");
323254721Semaste                    result.SetStatus (eReturnStatusFailed);
324254721Semaste                    return false;
325254721Semaste                }
326254721Semaste                break;
327254721Semaste
328254721Semaste            case eStateRunning:
329254721Semaste            case eStateStepping:
330288943Sdim                if (GetFlags().Test(eCommandProcessMustBePaused))
331254721Semaste                {
332254721Semaste                    result.AppendError ("Process is running.  Use 'process interrupt' to pause execution.");
333254721Semaste                    result.SetStatus (eReturnStatusFailed);
334254721Semaste                    return false;
335254721Semaste                }
336254721Semaste            }
337254721Semaste        }
338254721Semaste    }
339254721Semaste    return true;
340254721Semaste}
341254721Semaste
342254721Semastevoid
343254721SemasteCommandObject::Cleanup ()
344254721Semaste{
345254721Semaste    m_exe_ctx.Clear();
346254721Semaste    m_api_locker.Unlock();
347254721Semaste}
348254721Semaste
349254721Semaste
350254721Semasteclass CommandDictCommandPartialMatch
351254721Semaste{
352254721Semaste    public:
353254721Semaste        CommandDictCommandPartialMatch (const char *match_str)
354254721Semaste        {
355254721Semaste            m_match_str = match_str;
356254721Semaste        }
357254721Semaste        bool operator() (const std::pair<std::string, lldb::CommandObjectSP> map_element) const
358254721Semaste        {
359254721Semaste            // A NULL or empty string matches everything.
360276479Sdim            if (m_match_str == nullptr || *m_match_str == '\0')
361254721Semaste                return true;
362254721Semaste
363254721Semaste            return map_element.first.find (m_match_str, 0) == 0;
364254721Semaste        }
365254721Semaste
366254721Semaste    private:
367254721Semaste        const char *m_match_str;
368254721Semaste};
369254721Semaste
370254721Semasteint
371254721SemasteCommandObject::AddNamesMatchingPartialString (CommandObject::CommandMap &in_map, const char *cmd_str,
372254721Semaste                                              StringList &matches)
373254721Semaste{
374254721Semaste    int number_added = 0;
375254721Semaste    CommandDictCommandPartialMatch matcher(cmd_str);
376254721Semaste
377254721Semaste    CommandObject::CommandMap::iterator matching_cmds = std::find_if (in_map.begin(), in_map.end(), matcher);
378254721Semaste
379254721Semaste    while (matching_cmds != in_map.end())
380254721Semaste    {
381254721Semaste        ++number_added;
382254721Semaste        matches.AppendString((*matching_cmds).first.c_str());
383254721Semaste        matching_cmds = std::find_if (++matching_cmds, in_map.end(), matcher);;
384254721Semaste    }
385254721Semaste    return number_added;
386254721Semaste}
387254721Semaste
388254721Semasteint
389254721SemasteCommandObject::HandleCompletion
390254721Semaste(
391254721Semaste    Args &input,
392254721Semaste    int &cursor_index,
393254721Semaste    int &cursor_char_position,
394254721Semaste    int match_start_point,
395254721Semaste    int max_return_elements,
396254721Semaste    bool &word_complete,
397254721Semaste    StringList &matches
398254721Semaste)
399254721Semaste{
400296417Sdim    // Default implementation of WantsCompletion() is !WantsRawCommandString().
401254721Semaste    // Subclasses who want raw command string but desire, for example,
402254721Semaste    // argument completion should override WantsCompletion() to return true,
403254721Semaste    // instead.
404254721Semaste    if (WantsRawCommandString() && !WantsCompletion())
405254721Semaste    {
406254721Semaste        // FIXME: Abstract telling the completion to insert the completion character.
407254721Semaste        matches.Clear();
408254721Semaste        return -1;
409254721Semaste    }
410254721Semaste    else
411254721Semaste    {
412254721Semaste        // Can we do anything generic with the options?
413254721Semaste        Options *cur_options = GetOptions();
414254721Semaste        CommandReturnObject result;
415254721Semaste        OptionElementVector opt_element_vector;
416254721Semaste
417276479Sdim        if (cur_options != nullptr)
418254721Semaste        {
419254721Semaste            // Re-insert the dummy command name string which will have been
420254721Semaste            // stripped off:
421254721Semaste            input.Unshift ("dummy-string");
422254721Semaste            cursor_index++;
423254721Semaste
424254721Semaste
425254721Semaste            // I stick an element on the end of the input, because if the last element is
426254721Semaste            // option that requires an argument, getopt_long_only will freak out.
427254721Semaste
428254721Semaste            input.AppendArgument ("<FAKE-VALUE>");
429254721Semaste
430254721Semaste            input.ParseArgsForCompletion (*cur_options, opt_element_vector, cursor_index);
431254721Semaste
432254721Semaste            input.DeleteArgumentAtIndex(input.GetArgumentCount() - 1);
433254721Semaste
434254721Semaste            bool handled_by_options;
435254721Semaste            handled_by_options = cur_options->HandleOptionCompletion (input,
436254721Semaste                                                                      opt_element_vector,
437254721Semaste                                                                      cursor_index,
438254721Semaste                                                                      cursor_char_position,
439254721Semaste                                                                      match_start_point,
440254721Semaste                                                                      max_return_elements,
441254721Semaste                                                                      word_complete,
442254721Semaste                                                                      matches);
443254721Semaste            if (handled_by_options)
444254721Semaste                return matches.GetSize();
445254721Semaste        }
446254721Semaste
447254721Semaste        // If we got here, the last word is not an option or an option argument.
448254721Semaste        return HandleArgumentCompletion (input,
449254721Semaste                                         cursor_index,
450254721Semaste                                         cursor_char_position,
451254721Semaste                                         opt_element_vector,
452254721Semaste                                         match_start_point,
453254721Semaste                                         max_return_elements,
454254721Semaste                                         word_complete,
455254721Semaste                                         matches);
456254721Semaste    }
457254721Semaste}
458254721Semaste
459254721Semastebool
460254721SemasteCommandObject::HelpTextContainsWord (const char *search_word)
461254721Semaste{
462254721Semaste    std::string options_usage_help;
463254721Semaste
464254721Semaste    bool found_word = false;
465254721Semaste
466254721Semaste    const char *short_help = GetHelp();
467254721Semaste    const char *long_help = GetHelpLong();
468254721Semaste    const char *syntax_help = GetSyntax();
469254721Semaste
470254721Semaste    if (short_help && strcasestr (short_help, search_word))
471254721Semaste        found_word = true;
472254721Semaste    else if (long_help && strcasestr (long_help, search_word))
473254721Semaste        found_word = true;
474254721Semaste    else if (syntax_help && strcasestr (syntax_help, search_word))
475254721Semaste        found_word = true;
476254721Semaste
477254721Semaste    if (!found_word
478276479Sdim        && GetOptions() != nullptr)
479254721Semaste    {
480254721Semaste        StreamString usage_help;
481254721Semaste        GetOptions()->GenerateOptionUsage (usage_help, this);
482254721Semaste        if (usage_help.GetSize() > 0)
483254721Semaste        {
484254721Semaste            const char *usage_text = usage_help.GetData();
485254721Semaste            if (strcasestr (usage_text, search_word))
486254721Semaste              found_word = true;
487254721Semaste        }
488254721Semaste    }
489254721Semaste
490254721Semaste    return found_word;
491254721Semaste}
492254721Semaste
493254721Semasteint
494254721SemasteCommandObject::GetNumArgumentEntries  ()
495254721Semaste{
496254721Semaste    return m_arguments.size();
497254721Semaste}
498254721Semaste
499254721SemasteCommandObject::CommandArgumentEntry *
500254721SemasteCommandObject::GetArgumentEntryAtIndex (int idx)
501254721Semaste{
502276479Sdim    if (static_cast<size_t>(idx) < m_arguments.size())
503254721Semaste        return &(m_arguments[idx]);
504254721Semaste
505276479Sdim    return nullptr;
506254721Semaste}
507254721Semaste
508288943Sdimconst CommandObject::ArgumentTableEntry *
509254721SemasteCommandObject::FindArgumentDataByType (CommandArgumentType arg_type)
510254721Semaste{
511254721Semaste    const ArgumentTableEntry *table = CommandObject::GetArgumentTable();
512254721Semaste
513254721Semaste    for (int i = 0; i < eArgTypeLastArg; ++i)
514254721Semaste        if (table[i].arg_type == arg_type)
515288943Sdim            return &(table[i]);
516254721Semaste
517276479Sdim    return nullptr;
518254721Semaste}
519254721Semaste
520254721Semastevoid
521254721SemasteCommandObject::GetArgumentHelp (Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter)
522254721Semaste{
523254721Semaste    const ArgumentTableEntry* table = CommandObject::GetArgumentTable();
524288943Sdim    const ArgumentTableEntry *entry = &(table[arg_type]);
525254721Semaste
526254721Semaste    // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
527254721Semaste
528254721Semaste    if (entry->arg_type != arg_type)
529254721Semaste        entry = CommandObject::FindArgumentDataByType (arg_type);
530254721Semaste
531254721Semaste    if (!entry)
532254721Semaste        return;
533254721Semaste
534254721Semaste    StreamString name_str;
535254721Semaste    name_str.Printf ("<%s>", entry->arg_name);
536254721Semaste
537254721Semaste    if (entry->help_function)
538254721Semaste    {
539254721Semaste        const char* help_text = entry->help_function();
540254721Semaste        if (!entry->help_function.self_formatting)
541254721Semaste        {
542254721Semaste            interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", help_text,
543254721Semaste                                                 name_str.GetSize());
544254721Semaste        }
545254721Semaste        else
546254721Semaste        {
547254721Semaste            interpreter.OutputHelpText(str, name_str.GetData(), "--", help_text,
548254721Semaste                                       name_str.GetSize());
549254721Semaste        }
550254721Semaste    }
551254721Semaste    else
552254721Semaste        interpreter.OutputFormattedHelpText (str, name_str.GetData(), "--", entry->help_text, name_str.GetSize());
553254721Semaste}
554254721Semaste
555254721Semasteconst char *
556254721SemasteCommandObject::GetArgumentName (CommandArgumentType arg_type)
557254721Semaste{
558288943Sdim    const ArgumentTableEntry *entry = &(CommandObject::GetArgumentTable()[arg_type]);
559254721Semaste
560254721Semaste    // The table is *supposed* to be kept in arg_type order, but someone *could* have messed it up...
561254721Semaste
562254721Semaste    if (entry->arg_type != arg_type)
563254721Semaste        entry = CommandObject::FindArgumentDataByType (arg_type);
564254721Semaste
565254721Semaste    if (entry)
566254721Semaste        return entry->arg_name;
567254721Semaste
568254721Semaste    StreamString str;
569254721Semaste    str << "Arg name for type (" << arg_type << ") not in arg table!";
570254721Semaste    return str.GetData();
571254721Semaste}
572254721Semaste
573254721Semastebool
574254721SemasteCommandObject::IsPairType (ArgumentRepetitionType arg_repeat_type)
575254721Semaste{
576254721Semaste    if ((arg_repeat_type == eArgRepeatPairPlain)
577254721Semaste        ||  (arg_repeat_type == eArgRepeatPairOptional)
578254721Semaste        ||  (arg_repeat_type == eArgRepeatPairPlus)
579254721Semaste        ||  (arg_repeat_type == eArgRepeatPairStar)
580254721Semaste        ||  (arg_repeat_type == eArgRepeatPairRange)
581254721Semaste        ||  (arg_repeat_type == eArgRepeatPairRangeOptional))
582254721Semaste        return true;
583254721Semaste
584254721Semaste    return false;
585254721Semaste}
586254721Semaste
587254721Semastestatic CommandObject::CommandArgumentEntry
588254721SemasteOptSetFiltered(uint32_t opt_set_mask, CommandObject::CommandArgumentEntry &cmd_arg_entry)
589254721Semaste{
590254721Semaste    CommandObject::CommandArgumentEntry ret_val;
591254721Semaste    for (unsigned i = 0; i < cmd_arg_entry.size(); ++i)
592254721Semaste        if (opt_set_mask & cmd_arg_entry[i].arg_opt_set_association)
593254721Semaste            ret_val.push_back(cmd_arg_entry[i]);
594254721Semaste    return ret_val;
595254721Semaste}
596254721Semaste
597254721Semaste// Default parameter value of opt_set_mask is LLDB_OPT_SET_ALL, which means take
598254721Semaste// all the argument data into account.  On rare cases where some argument sticks
599254721Semaste// with certain option sets, this function returns the option set filtered args.
600254721Semastevoid
601254721SemasteCommandObject::GetFormattedCommandArguments (Stream &str, uint32_t opt_set_mask)
602254721Semaste{
603254721Semaste    int num_args = m_arguments.size();
604254721Semaste    for (int i = 0; i < num_args; ++i)
605254721Semaste    {
606254721Semaste        if (i > 0)
607254721Semaste            str.Printf (" ");
608254721Semaste        CommandArgumentEntry arg_entry =
609254721Semaste            opt_set_mask == LLDB_OPT_SET_ALL ? m_arguments[i]
610254721Semaste                                             : OptSetFiltered(opt_set_mask, m_arguments[i]);
611254721Semaste        int num_alternatives = arg_entry.size();
612254721Semaste
613254721Semaste        if ((num_alternatives == 2)
614254721Semaste            && IsPairType (arg_entry[0].arg_repetition))
615254721Semaste        {
616254721Semaste            const char *first_name = GetArgumentName (arg_entry[0].arg_type);
617254721Semaste            const char *second_name = GetArgumentName (arg_entry[1].arg_type);
618254721Semaste            switch (arg_entry[0].arg_repetition)
619254721Semaste            {
620254721Semaste                case eArgRepeatPairPlain:
621254721Semaste                    str.Printf ("<%s> <%s>", first_name, second_name);
622254721Semaste                    break;
623254721Semaste                case eArgRepeatPairOptional:
624254721Semaste                    str.Printf ("[<%s> <%s>]", first_name, second_name);
625254721Semaste                    break;
626254721Semaste                case eArgRepeatPairPlus:
627254721Semaste                    str.Printf ("<%s> <%s> [<%s> <%s> [...]]", first_name, second_name, first_name, second_name);
628254721Semaste                    break;
629254721Semaste                case eArgRepeatPairStar:
630254721Semaste                    str.Printf ("[<%s> <%s> [<%s> <%s> [...]]]", first_name, second_name, first_name, second_name);
631254721Semaste                    break;
632254721Semaste                case eArgRepeatPairRange:
633254721Semaste                    str.Printf ("<%s_1> <%s_1> ... <%s_n> <%s_n>", first_name, second_name, first_name, second_name);
634254721Semaste                    break;
635254721Semaste                case eArgRepeatPairRangeOptional:
636254721Semaste                    str.Printf ("[<%s_1> <%s_1> ... <%s_n> <%s_n>]", first_name, second_name, first_name, second_name);
637254721Semaste                    break;
638254721Semaste                // Explicitly test for all the rest of the cases, so if new types get added we will notice the
639254721Semaste                // missing case statement(s).
640254721Semaste                case eArgRepeatPlain:
641254721Semaste                case eArgRepeatOptional:
642254721Semaste                case eArgRepeatPlus:
643254721Semaste                case eArgRepeatStar:
644254721Semaste                case eArgRepeatRange:
645254721Semaste                    // These should not be reached, as they should fail the IsPairType test above.
646254721Semaste                    break;
647254721Semaste            }
648254721Semaste        }
649254721Semaste        else
650254721Semaste        {
651254721Semaste            StreamString names;
652254721Semaste            for (int j = 0; j < num_alternatives; ++j)
653254721Semaste            {
654254721Semaste                if (j > 0)
655254721Semaste                    names.Printf (" | ");
656254721Semaste                names.Printf ("%s", GetArgumentName (arg_entry[j].arg_type));
657254721Semaste            }
658254721Semaste            switch (arg_entry[0].arg_repetition)
659254721Semaste            {
660254721Semaste                case eArgRepeatPlain:
661254721Semaste                    str.Printf ("<%s>", names.GetData());
662254721Semaste                    break;
663254721Semaste                case eArgRepeatPlus:
664254721Semaste                    str.Printf ("<%s> [<%s> [...]]", names.GetData(), names.GetData());
665254721Semaste                    break;
666254721Semaste                case eArgRepeatStar:
667254721Semaste                    str.Printf ("[<%s> [<%s> [...]]]", names.GetData(), names.GetData());
668254721Semaste                    break;
669254721Semaste                case eArgRepeatOptional:
670254721Semaste                    str.Printf ("[<%s>]", names.GetData());
671254721Semaste                    break;
672254721Semaste                case eArgRepeatRange:
673254721Semaste                    str.Printf ("<%s_1> .. <%s_n>", names.GetData(), names.GetData());
674254721Semaste                    break;
675254721Semaste                // Explicitly test for all the rest of the cases, so if new types get added we will notice the
676254721Semaste                // missing case statement(s).
677254721Semaste                case eArgRepeatPairPlain:
678254721Semaste                case eArgRepeatPairOptional:
679254721Semaste                case eArgRepeatPairPlus:
680254721Semaste                case eArgRepeatPairStar:
681254721Semaste                case eArgRepeatPairRange:
682254721Semaste                case eArgRepeatPairRangeOptional:
683254721Semaste                    // These should not be hit, as they should pass the IsPairType test above, and control should
684254721Semaste                    // have gone into the other branch of the if statement.
685254721Semaste                    break;
686254721Semaste            }
687254721Semaste        }
688254721Semaste    }
689254721Semaste}
690254721Semaste
691254721SemasteCommandArgumentType
692254721SemasteCommandObject::LookupArgumentName (const char *arg_name)
693254721Semaste{
694254721Semaste    CommandArgumentType return_type = eArgTypeLastArg;
695254721Semaste
696254721Semaste    std::string arg_name_str (arg_name);
697254721Semaste    size_t len = arg_name_str.length();
698254721Semaste    if (arg_name[0] == '<'
699254721Semaste        && arg_name[len-1] == '>')
700254721Semaste        arg_name_str = arg_name_str.substr (1, len-2);
701254721Semaste
702254721Semaste    const ArgumentTableEntry *table = GetArgumentTable();
703254721Semaste    for (int i = 0; i < eArgTypeLastArg; ++i)
704254721Semaste        if (arg_name_str.compare (table[i].arg_name) == 0)
705254721Semaste            return_type = g_arguments_data[i].arg_type;
706254721Semaste
707254721Semaste    return return_type;
708254721Semaste}
709254721Semaste
710254721Semastestatic const char *
711254721SemasteRegisterNameHelpTextCallback ()
712254721Semaste{
713254721Semaste    return "Register names can be specified using the architecture specific names.  "
714254721Semaste    "They can also be specified using generic names.  Not all generic entities have "
715254721Semaste    "registers backing them on all architectures.  When they don't the generic name "
716254721Semaste    "will return an error.\n"
717254721Semaste    "The generic names defined in lldb are:\n"
718254721Semaste    "\n"
719254721Semaste    "pc       - program counter register\n"
720254721Semaste    "ra       - return address register\n"
721254721Semaste    "fp       - frame pointer register\n"
722254721Semaste    "sp       - stack pointer register\n"
723254721Semaste    "flags    - the flags register\n"
724254721Semaste    "arg{1-6} - integer argument passing registers.\n";
725254721Semaste}
726254721Semaste
727254721Semastestatic const char *
728254721SemasteBreakpointIDHelpTextCallback ()
729254721Semaste{
730254721Semaste    return "Breakpoint ID's consist major and minor numbers;  the major number "
731254721Semaste    "corresponds to the single entity that was created with a 'breakpoint set' "
732254721Semaste    "command; the minor numbers correspond to all the locations that were actually "
733254721Semaste    "found/set based on the major breakpoint.  A full breakpoint ID might look like "
734254721Semaste    "3.14, meaning the 14th location set for the 3rd breakpoint.  You can specify "
735254721Semaste    "all the locations of a breakpoint by just indicating the major breakpoint "
736254721Semaste    "number. A valid breakpoint id consists either of just the major id number, "
737254721Semaste    "or the major number, a dot, and the location number (e.g. 3 or 3.2 could "
738254721Semaste    "both be valid breakpoint ids).";
739254721Semaste}
740254721Semaste
741254721Semastestatic const char *
742254721SemasteBreakpointIDRangeHelpTextCallback ()
743254721Semaste{
744254721Semaste    return "A 'breakpoint id list' is a manner of specifying multiple breakpoints. "
745254721Semaste    "This can be done  through several mechanisms.  The easiest way is to just "
746254721Semaste    "enter a space-separated list of breakpoint ids.  To specify all the "
747254721Semaste    "breakpoint locations under a major breakpoint, you can use the major "
748254721Semaste    "breakpoint number followed by '.*', eg. '5.*' means all the locations under "
749254721Semaste    "breakpoint 5.  You can also indicate a range of breakpoints by using "
750254721Semaste    "<start-bp-id> - <end-bp-id>.  The start-bp-id and end-bp-id for a range can "
751254721Semaste    "be any valid breakpoint ids.  It is not legal, however, to specify a range "
752254721Semaste    "using specific locations that cross major breakpoint numbers.  I.e. 3.2 - 3.7"
753254721Semaste    " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal.";
754254721Semaste}
755254721Semaste
756254721Semastestatic const char *
757280031SdimBreakpointNameHelpTextCallback ()
758280031Sdim{
759280031Sdim    return "A name that can be added to a breakpoint when it is created, or later "
760280031Sdim    "on with the \"breakpoint name add\" command.  "
761280031Sdim    "Breakpoint names can be used to specify breakpoints in all the places breakpoint ID's "
762280031Sdim    "and breakpoint ID ranges can be used.  As such they provide a convenient way to group breakpoints, "
763280031Sdim    "and to operate on breakpoints you create without having to track the breakpoint number.  "
764280031Sdim    "Note, the attributes you set when using a breakpoint name in a breakpoint command don't "
765280031Sdim    "adhere to the name, but instead are set individually on all the breakpoints currently tagged with that name.  Future breakpoints "
766280031Sdim    "tagged with that name will not pick up the attributes previously given using that name.  "
767280031Sdim    "In order to distinguish breakpoint names from breakpoint ID's and ranges, "
768280031Sdim    "names must start with a letter from a-z or A-Z and cannot contain spaces, \".\" or \"-\".  "
769280031Sdim    "Also, breakpoint names can only be applied to breakpoints, not to breakpoint locations.";
770280031Sdim}
771280031Sdim
772280031Sdimstatic const char *
773254721SemasteGDBFormatHelpTextCallback ()
774254721Semaste{
775254721Semaste    return "A GDB format consists of a repeat count, a format letter and a size letter. "
776254721Semaste    "The repeat count is optional and defaults to 1. The format letter is optional "
777254721Semaste    "and defaults to the previous format that was used. The size letter is optional "
778254721Semaste    "and defaults to the previous size that was used.\n"
779254721Semaste    "\n"
780254721Semaste    "Format letters include:\n"
781254721Semaste    "o - octal\n"
782254721Semaste    "x - hexadecimal\n"
783254721Semaste    "d - decimal\n"
784254721Semaste    "u - unsigned decimal\n"
785254721Semaste    "t - binary\n"
786254721Semaste    "f - float\n"
787254721Semaste    "a - address\n"
788254721Semaste    "i - instruction\n"
789254721Semaste    "c - char\n"
790254721Semaste    "s - string\n"
791254721Semaste    "T - OSType\n"
792254721Semaste    "A - float as hex\n"
793254721Semaste    "\n"
794254721Semaste    "Size letters include:\n"
795254721Semaste    "b - 1 byte  (byte)\n"
796254721Semaste    "h - 2 bytes (halfword)\n"
797254721Semaste    "w - 4 bytes (word)\n"
798254721Semaste    "g - 8 bytes (giant)\n"
799254721Semaste    "\n"
800254721Semaste    "Example formats:\n"
801254721Semaste    "32xb - show 32 1 byte hexadecimal integer values\n"
802254721Semaste    "16xh - show 16 2 byte hexadecimal integer values\n"
803254721Semaste    "64   - show 64 2 byte hexadecimal integer values (format and size from the last format)\n"
804254721Semaste    "dw   - show 1 4 byte decimal integer value\n"
805254721Semaste    ;
806254721Semaste}
807254721Semaste
808254721Semastestatic const char *
809254721SemasteFormatHelpTextCallback ()
810254721Semaste{
811254721Semaste
812276479Sdim    static char* help_text_ptr = nullptr;
813254721Semaste
814254721Semaste    if (help_text_ptr)
815254721Semaste        return help_text_ptr;
816254721Semaste
817254721Semaste    StreamString sstr;
818254721Semaste    sstr << "One of the format names (or one-character names) that can be used to show a variable's value:\n";
819254721Semaste    for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
820254721Semaste    {
821254721Semaste        if (f != eFormatDefault)
822254721Semaste            sstr.PutChar('\n');
823254721Semaste
824254721Semaste        char format_char = FormatManager::GetFormatAsFormatChar(f);
825254721Semaste        if (format_char)
826254721Semaste            sstr.Printf("'%c' or ", format_char);
827254721Semaste
828254721Semaste        sstr.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
829254721Semaste    }
830254721Semaste
831254721Semaste    sstr.Flush();
832254721Semaste
833254721Semaste    std::string data = sstr.GetString();
834254721Semaste
835254721Semaste    help_text_ptr = new char[data.length()+1];
836254721Semaste
837254721Semaste    data.copy(help_text_ptr, data.length());
838254721Semaste
839254721Semaste    return help_text_ptr;
840254721Semaste}
841254721Semaste
842254721Semastestatic const char *
843254721SemasteLanguageTypeHelpTextCallback ()
844254721Semaste{
845276479Sdim    static char* help_text_ptr = nullptr;
846254721Semaste
847254721Semaste    if (help_text_ptr)
848254721Semaste        return help_text_ptr;
849254721Semaste
850254721Semaste    StreamString sstr;
851254721Semaste    sstr << "One of the following languages:\n";
852288943Sdim
853296417Sdim    Language::PrintAllLanguages(sstr, "  ", "\n");
854288943Sdim
855254721Semaste    sstr.Flush();
856254721Semaste
857254721Semaste    std::string data = sstr.GetString();
858254721Semaste
859254721Semaste    help_text_ptr = new char[data.length()+1];
860254721Semaste
861254721Semaste    data.copy(help_text_ptr, data.length());
862254721Semaste
863254721Semaste    return help_text_ptr;
864254721Semaste}
865254721Semaste
866254721Semastestatic const char *
867254721SemasteSummaryStringHelpTextCallback()
868254721Semaste{
869254721Semaste    return
870254721Semaste        "A summary string is a way to extract information from variables in order to present them using a summary.\n"
871254721Semaste        "Summary strings contain static text, variables, scopes and control sequences:\n"
872254721Semaste        "  - Static text can be any sequence of non-special characters, i.e. anything but '{', '}', '$', or '\\'.\n"
873254721Semaste        "  - Variables are sequences of characters beginning with ${, ending with } and that contain symbols in the format described below.\n"
874254721Semaste        "  - 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"
875254721Semaste        "  - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus '\\$', '\\{' and '\\}'.\n"
876254721Semaste        "A summary string works by copying static text verbatim, turning control sequences into their character counterpart, expanding variables and trying to expand scopes.\n"
877254721Semaste        "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"
878254721Semaste        "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"
879254721Semaste        " (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"
880254721Semaste        " ${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."
881254721Semaste        " 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"
882254721Semaste        "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."
883254721Semaste        "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"
884254721Semaste        " path refers to:\n"
885254721Semaste        "  - 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"
886254721Semaste        " and displayed as an individual variable\n"
887254721Semaste        "  - 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"
888254721Semaste        " 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"
889254721Semaste        "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"
890254721Semaste        "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"
891254721Semaste        " special symbols only allowed as part of a variable:\n"
892254721Semaste        "    %V: show the value of the object by default\n"
893254721Semaste        "    %S: show the summary of the object by default\n"
894254721Semaste        "    %@: show the runtime-provided object description (for Objective-C, it calls NSPrintForDebugger; for C/C++ it does nothing)\n"
895254721Semaste        "    %L: show the location of the object (memory address or a register name)\n"
896254721Semaste        "    %#: show the number of children of the object\n"
897254721Semaste        "    %T: show the type of the object\n"
898254721Semaste        "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"
899254721Semaste        " 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"
900254721Semaste        " count the number of actual elements stored in an std::list:\n"
901254721Semaste        "type summary add -s \"${svar%#}\" -x \"std::list<\"";
902254721Semaste}
903254721Semaste
904254721Semastestatic const char *
905254721SemasteExprPathHelpTextCallback()
906254721Semaste{
907254721Semaste    return
908254721Semaste    "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"
909254721Semaste    "For instance, given a class:\n"
910254721Semaste    "  class foo {\n"
911254721Semaste    "      int a;\n"
912254721Semaste    "      int b; .\n"
913254721Semaste    "      foo* next;\n"
914254721Semaste    "  };\n"
915254721Semaste    "the expression to read item b in the item pointed to by next for foo aFoo would be aFoo.next->b.\n"
916254721Semaste    "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"
917254721Semaste    "Expression paths in LLDB include dot (.) and arrow (->) operators, and most commands using expression paths have ways to also accept the star (*) operator.\n"
918254721Semaste    "The meaning of these operators is the same as the usual one given to them by the C/C++ standards.\n"
919254721Semaste    "LLDB also has support for indexing ([ ]) in expression paths, and extends the traditional meaning of the square brackets operator to allow bitfield extraction:\n"
920254721Semaste    "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"
921254721Semaste    " 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"
922254721Semaste    " 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"
923254721Semaste    " meaning of array slicing (taking elements n thru m inside the array or pointed-to memory).";
924254721Semaste}
925254721Semaste
926254721Semastevoid
927288943SdimCommandObject::FormatLongHelpText (Stream &output_strm, const char *long_help)
928288943Sdim{
929288943Sdim    CommandInterpreter& interpreter = GetCommandInterpreter();
930288943Sdim    std::stringstream lineStream (long_help);
931288943Sdim    std::string line;
932288943Sdim    while (std::getline (lineStream, line)) {
933288943Sdim        if (line.empty()) {
934288943Sdim            output_strm << "\n";
935288943Sdim            continue;
936288943Sdim        }
937288943Sdim        size_t result = line.find_first_not_of (" \t");
938288943Sdim        if (result == std::string::npos) {
939288943Sdim            result = 0;
940288943Sdim        }
941288943Sdim        std::string whitespace_prefix = line.substr (0, result);
942288943Sdim        std::string remainder = line.substr (result);
943288943Sdim        interpreter.OutputFormattedHelpText(output_strm, whitespace_prefix.c_str(), remainder.c_str());
944288943Sdim    }
945288943Sdim}
946288943Sdim
947288943Sdimvoid
948254721SemasteCommandObject::GenerateHelpText (CommandReturnObject &result)
949254721Semaste{
950254721Semaste    GenerateHelpText(result.GetOutputStream());
951254721Semaste
952254721Semaste    result.SetStatus (eReturnStatusSuccessFinishNoResult);
953254721Semaste}
954254721Semaste
955254721Semastevoid
956254721SemasteCommandObject::GenerateHelpText (Stream &output_strm)
957254721Semaste{
958254721Semaste    CommandInterpreter& interpreter = GetCommandInterpreter();
959276479Sdim    if (GetOptions() != nullptr)
960254721Semaste    {
961254721Semaste        if (WantsRawCommandString())
962254721Semaste        {
963254721Semaste            std::string help_text (GetHelp());
964254721Semaste            help_text.append ("  This command takes 'raw' input (no need to quote stuff).");
965254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
966254721Semaste        }
967254721Semaste        else
968254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
969254721Semaste        output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
970254721Semaste        GetOptions()->GenerateOptionUsage (output_strm, this);
971254721Semaste        const char *long_help = GetHelpLong();
972276479Sdim        if ((long_help != nullptr)
973254721Semaste            && (strlen (long_help) > 0))
974288943Sdim            FormatLongHelpText (output_strm, long_help);
975254721Semaste        if (WantsRawCommandString() && !WantsCompletion())
976254721Semaste        {
977254721Semaste            // Emit the message about using ' -- ' between the end of the command options and the raw input
978254721Semaste            // conditionally, i.e., only if the command object does not want completion.
979254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "",
980254721Semaste                                                 "\nIMPORTANT NOTE:  Because this command takes 'raw' input, if you use any command options"
981254721Semaste                                                 " you must use ' -- ' between the end of the command options and the beginning of the raw input.", 1);
982254721Semaste        }
983254721Semaste        else if (GetNumArgumentEntries() > 0
984254721Semaste                 && GetOptions()
985254721Semaste                 && GetOptions()->NumCommandOptions() > 0)
986254721Semaste        {
987254721Semaste            // Also emit a warning about using "--" in case you are using a command that takes options and arguments.
988254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "",
989254721Semaste                                                 "\nThis command takes options and free-form arguments.  If your arguments resemble"
990254721Semaste                                                 " option specifiers (i.e., they start with a - or --), you must use ' -- ' between"
991254721Semaste                                                 " the end of the command options and the beginning of the arguments.", 1);
992254721Semaste        }
993254721Semaste    }
994254721Semaste    else if (IsMultiwordObject())
995254721Semaste    {
996254721Semaste        if (WantsRawCommandString())
997254721Semaste        {
998254721Semaste            std::string help_text (GetHelp());
999254721Semaste            help_text.append ("  This command takes 'raw' input (no need to quote stuff).");
1000254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
1001254721Semaste        }
1002254721Semaste        else
1003254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
1004254721Semaste        GenerateHelpText (output_strm);
1005254721Semaste    }
1006254721Semaste    else
1007254721Semaste    {
1008254721Semaste        const char *long_help = GetHelpLong();
1009276479Sdim        if ((long_help != nullptr)
1010254721Semaste            && (strlen (long_help) > 0))
1011288943Sdim            FormatLongHelpText (output_strm, long_help);
1012254721Semaste        else if (WantsRawCommandString())
1013254721Semaste        {
1014254721Semaste            std::string help_text (GetHelp());
1015254721Semaste            help_text.append ("  This command takes 'raw' input (no need to quote stuff).");
1016254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", help_text.c_str(), 1);
1017254721Semaste        }
1018254721Semaste        else
1019254721Semaste            interpreter.OutputFormattedHelpText (output_strm, "", "", GetHelp(), 1);
1020254721Semaste        output_strm.Printf ("\nSyntax: %s\n", GetSyntax());
1021254721Semaste    }
1022254721Semaste}
1023254721Semaste
1024254721Semastevoid
1025254721SemasteCommandObject::AddIDsArgumentData(CommandArgumentEntry &arg, CommandArgumentType ID, CommandArgumentType IDRange)
1026254721Semaste{
1027254721Semaste    CommandArgumentData id_arg;
1028254721Semaste    CommandArgumentData id_range_arg;
1029254721Semaste
1030254721Semaste    // Create the first variant for the first (and only) argument for this command.
1031254721Semaste    id_arg.arg_type = ID;
1032254721Semaste    id_arg.arg_repetition = eArgRepeatOptional;
1033254721Semaste
1034254721Semaste    // Create the second variant for the first (and only) argument for this command.
1035254721Semaste    id_range_arg.arg_type = IDRange;
1036254721Semaste    id_range_arg.arg_repetition = eArgRepeatOptional;
1037254721Semaste
1038254721Semaste    // The first (and only) argument for this command could be either an id or an id_range.
1039254721Semaste    // Push both variants into the entry for the first argument for this command.
1040254721Semaste    arg.push_back(id_arg);
1041254721Semaste    arg.push_back(id_range_arg);
1042254721Semaste}
1043254721Semaste
1044254721Semasteconst char *
1045254721SemasteCommandObject::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type)
1046254721Semaste{
1047288943Sdim    assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentTypeAsCString");
1048288943Sdim    return g_arguments_data[arg_type].arg_name;
1049254721Semaste}
1050254721Semaste
1051254721Semasteconst char *
1052254721SemasteCommandObject::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type)
1053254721Semaste{
1054288943Sdim    assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentDescriptionAsCString");
1055288943Sdim    return g_arguments_data[arg_type].help_text;
1056254721Semaste}
1057254721Semaste
1058280031SdimTarget *
1059280031SdimCommandObject::GetDummyTarget()
1060280031Sdim{
1061280031Sdim    return m_interpreter.GetDebugger().GetDummyTarget();
1062280031Sdim}
1063280031Sdim
1064280031SdimTarget *
1065280031SdimCommandObject::GetSelectedOrDummyTarget(bool prefer_dummy)
1066280031Sdim{
1067280031Sdim    return m_interpreter.GetDebugger().GetSelectedOrDummyTarget(prefer_dummy);
1068280031Sdim}
1069280031Sdim
1070254721Semastebool
1071254721SemasteCommandObjectParsed::Execute (const char *args_string, CommandReturnObject &result)
1072254721Semaste{
1073254721Semaste    bool handled = false;
1074254721Semaste    Args cmd_args (args_string);
1075276479Sdim    if (HasOverrideCallback())
1076254721Semaste    {
1077254721Semaste        Args full_args (GetCommandName ());
1078254721Semaste        full_args.AppendArguments(cmd_args);
1079276479Sdim        handled = InvokeOverrideCallback (full_args.GetConstArgumentVector(), result);
1080254721Semaste    }
1081254721Semaste    if (!handled)
1082254721Semaste    {
1083254721Semaste        for (size_t i = 0; i < cmd_args.GetArgumentCount();  ++i)
1084254721Semaste        {
1085254721Semaste            const char *tmp_str = cmd_args.GetArgumentAtIndex (i);
1086254721Semaste            if (tmp_str[0] == '`')  // back-quote
1087254721Semaste                cmd_args.ReplaceArgumentAtIndex (i, m_interpreter.ProcessEmbeddedScriptCommands (tmp_str));
1088254721Semaste        }
1089254721Semaste
1090254721Semaste        if (CheckRequirements(result))
1091254721Semaste        {
1092254721Semaste            if (ParseOptions (cmd_args, result))
1093254721Semaste            {
1094254721Semaste                // Call the command-specific version of 'Execute', passing it the already processed arguments.
1095254721Semaste                handled = DoExecute (cmd_args, result);
1096254721Semaste            }
1097254721Semaste        }
1098254721Semaste
1099254721Semaste        Cleanup();
1100254721Semaste    }
1101254721Semaste    return handled;
1102254721Semaste}
1103254721Semaste
1104254721Semastebool
1105254721SemasteCommandObjectRaw::Execute (const char *args_string, CommandReturnObject &result)
1106254721Semaste{
1107254721Semaste    bool handled = false;
1108276479Sdim    if (HasOverrideCallback())
1109254721Semaste    {
1110254721Semaste        std::string full_command (GetCommandName ());
1111254721Semaste        full_command += ' ';
1112254721Semaste        full_command += args_string;
1113276479Sdim        const char *argv[2] = { nullptr, nullptr };
1114254721Semaste        argv[0] = full_command.c_str();
1115276479Sdim        handled = InvokeOverrideCallback (argv, result);
1116254721Semaste    }
1117254721Semaste    if (!handled)
1118254721Semaste    {
1119254721Semaste        if (CheckRequirements(result))
1120254721Semaste            handled = DoExecute (args_string, result);
1121254721Semaste
1122254721Semaste        Cleanup();
1123254721Semaste    }
1124254721Semaste    return handled;
1125254721Semaste}
1126254721Semaste
1127254721Semastestatic
1128254721Semasteconst char *arch_helper()
1129254721Semaste{
1130254721Semaste    static StreamString g_archs_help;
1131254721Semaste    if (g_archs_help.Empty())
1132254721Semaste    {
1133254721Semaste        StringList archs;
1134276479Sdim        ArchSpec::AutoComplete(nullptr, archs);
1135254721Semaste        g_archs_help.Printf("These are the supported architecture names:\n");
1136254721Semaste        archs.Join("\n", g_archs_help);
1137254721Semaste    }
1138254721Semaste    return g_archs_help.GetData();
1139254721Semaste}
1140254721Semaste
1141254721SemasteCommandObject::ArgumentTableEntry
1142254721SemasteCommandObject::g_arguments_data[] =
1143254721Semaste{
1144276479Sdim    { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid address in the target program's execution space." },
1145276479Sdim    { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "An expression that resolves to an address." },
1146276479Sdim    { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." },
1147276479Sdim    { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition.  (See 'help commands alias' for more information.)" },
1148254721Semaste    { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." },
1149276479Sdim    { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" },
1150276479Sdim    { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr },
1151276479Sdim    { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr },
1152280031Sdim    { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eNoCompletion, { BreakpointNameHelpTextCallback, false }, nullptr },
1153276479Sdim    { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." },
1154276479Sdim    { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." },
1155276479Sdim    { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." },
1156276479Sdim    { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
1157276479Sdim    { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { nullptr, false }, "A directory name." },
1158276479Sdim    { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eNoCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin.  Currently the only valid options are \"att\" and \"intel\" for Intel targets" },
1159276479Sdim    { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { nullptr, false }, "How verbose the output of 'po' should be." },
1160276479Sdim    { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1161276479Sdim    { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1162276479Sdim    { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, nullptr },
1163276479Sdim    { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" },
1164276479Sdim    { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." },
1165276479Sdim    { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr },
1166276479Sdim    { eArgTypeFrameIndex, "frame-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into a thread's list of frames." },
1167276479Sdim    { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1168276479Sdim    { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." },
1169276479Sdim    { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." },
1170276479Sdim    { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr },
1171280031Sdim    { eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" },
1172276479Sdim    { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." },
1173276479Sdim    { eArgTypeLanguage, "language", CommandCompletions::eNoCompletion, { LanguageTypeHelpTextCallback, true }, nullptr },
1174276479Sdim    { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." },
1175276479Sdim    { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, 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." },
1176276479Sdim    { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, 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)." },
1177276479Sdim    { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { nullptr, false }, "A C++ method name." },
1178276479Sdim    { eArgTypeName, "name", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1179276479Sdim    { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1180276479Sdim    { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of lines to use." },
1181276479Sdim    { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of items per line to display." },
1182276479Sdim    { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1183276479Sdim    { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1184276479Sdim    { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { nullptr, false }, "A command that is entered as a single line of text." },
1185276479Sdim    { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." },
1186276479Sdim    { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." },
1187276479Sdim    { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." },
1188276479Sdim    { eArgTypePid, "pid", CommandCompletions::eNoCompletion, { nullptr, false }, "The process ID number." },
1189276479Sdim    { eArgTypePlugin, "plugin", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1190276479Sdim    { eArgTypeProcessName, "process-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the process." },
1191276479Sdim    { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." },
1192276479Sdim    { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." },
1193276479Sdim    { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." },
1194276479Sdim    { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the thread queue." },
1195276479Sdim    { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, nullptr },
1196276479Sdim    { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A regular expression." },
1197276479Sdim    { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." },
1198276479Sdim    { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1199276479Sdim    { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." },
1200276479Sdim    { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { nullptr, false }, "The scripting language to be used for script-based commands.  Currently only Python is valid." },
1201276479Sdim    { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "The word for which you wish to search for information about." },
1202276479Sdim    { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { nullptr, false }, "An Objective-C selector name." },
1203276479Sdim    { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." },
1204276479Sdim    { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." },
1205276479Sdim    { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" },
1206276479Sdim    { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable.  Type 'settings list' to see a complete list of such variables." },
1207276479Sdim    { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a shared library." },
1208276479Sdim    { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { nullptr, false }, "The name of a source file.." },
1209276479Sdim    { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify a sort order when dumping lists." },
1210276479Sdim    { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1211276479Sdim    { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, nullptr },
1212276479Sdim    { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" },
1213276479Sdim    { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." },
1214276479Sdim    { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." },
1215276479Sdim    { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." },
1216288943Sdim    { eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A type name." },
1217276479Sdim    { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." },
1218276479Sdim    { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." },
1219276479Sdim    { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." },
1220276479Sdim    { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { nullptr, false }, "A value could be anything, depending on where and how it is used." },
1221276479Sdim    { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." },
1222276479Sdim    { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { nullptr, false }, "No help available for this." },
1223276479Sdim    { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." },
1224276479Sdim    { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." },
1225276479Sdim    { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." },
1226276479Sdim    { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }
1227254721Semaste};
1228254721Semaste
1229254721Semasteconst CommandObject::ArgumentTableEntry*
1230254721SemasteCommandObject::GetArgumentTable ()
1231254721Semaste{
1232254721Semaste    // If this assertion fires, then the table above is out of date with the CommandArgumentType enumeration
1233254721Semaste    assert ((sizeof (CommandObject::g_arguments_data) / sizeof (CommandObject::ArgumentTableEntry)) == eArgTypeLastArg);
1234254721Semaste    return CommandObject::g_arguments_data;
1235254721Semaste}
1236254721Semaste
1237254721Semaste
1238