CommandObjectFrame.cpp revision 43b014aa33e20e61790e16ed69a2c57aae2fbc6e
1//===-- CommandObjectFrame.cpp ----------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectFrame.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Debugger.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/StreamFile.h"
19#include "lldb/Core/Timer.h"
20#include "lldb/Core/Value.h"
21#include "lldb/Core/ValueObject.h"
22#include "lldb/Core/ValueObjectVariable.h"
23#include "lldb/Interpreter/Args.h"
24#include "lldb/Interpreter/CommandInterpreter.h"
25#include "lldb/Interpreter/CommandReturnObject.h"
26#include "lldb/Interpreter/Options.h"
27#include "lldb/Symbol/ClangASTType.h"
28#include "lldb/Symbol/ClangASTContext.h"
29#include "lldb/Symbol/ObjectFile.h"
30#include "lldb/Symbol/SymbolContext.h"
31#include "lldb/Symbol/Type.h"
32#include "lldb/Symbol/Variable.h"
33#include "lldb/Symbol/VariableList.h"
34#include "lldb/Target/Process.h"
35#include "lldb/Target/StackFrame.h"
36#include "lldb/Target/Thread.h"
37#include "lldb/Target/Target.h"
38
39#include "CommandObjectThread.h"
40
41using namespace lldb;
42using namespace lldb_private;
43
44#pragma mark CommandObjectFrameInfo
45
46//-------------------------------------------------------------------------
47// CommandObjectFrameInfo
48//-------------------------------------------------------------------------
49
50class CommandObjectFrameInfo : public CommandObject
51{
52public:
53
54    CommandObjectFrameInfo (CommandInterpreter &interpreter) :
55        CommandObject (interpreter,
56                       "frame info",
57                       "List information about the currently selected frame in the current thread.",
58                       "frame info",
59                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
60    {
61    }
62
63    ~CommandObjectFrameInfo ()
64    {
65    }
66
67    bool
68    Execute (Args& command,
69             CommandReturnObject &result)
70    {
71        ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
72        if (exe_ctx.frame)
73        {
74            exe_ctx.frame->DumpUsingSettingsFormat (&result.GetOutputStream());
75            result.GetOutputStream().EOL();
76            result.SetStatus (eReturnStatusSuccessFinishResult);
77        }
78        else
79        {
80            result.AppendError ("no current frame");
81            result.SetStatus (eReturnStatusFailed);
82        }
83        return result.Succeeded();
84    }
85};
86
87#pragma mark CommandObjectFrameSelect
88
89//-------------------------------------------------------------------------
90// CommandObjectFrameSelect
91//-------------------------------------------------------------------------
92
93class CommandObjectFrameSelect : public CommandObject
94{
95public:
96
97    CommandObjectFrameSelect (CommandInterpreter &interpreter) :
98        CommandObject (interpreter,
99                       "frame select",
100                       "Select a frame by index from within the current thread and make it the current frame.",
101                       NULL,
102                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
103    {
104        CommandArgumentEntry arg;
105        CommandArgumentData index_arg;
106
107        // Define the first (and only) variant of this arg.
108        index_arg.arg_type = eArgTypeFrameIndex;
109        index_arg.arg_repetition = eArgRepeatPlain;
110
111        // There is only one variant this argument could be; put it into the argument entry.
112        arg.push_back (index_arg);
113
114        // Push the data for the first argument into the m_arguments vector.
115        m_arguments.push_back (arg);
116    }
117
118    ~CommandObjectFrameSelect ()
119    {
120    }
121
122    bool
123    Execute (Args& command,
124             CommandReturnObject &result)
125    {
126        ExecutionContext exe_ctx (m_interpreter.GetDebugger().GetExecutionContext());
127        if (exe_ctx.thread)
128        {
129            if (command.GetArgumentCount() == 1)
130            {
131                const char *frame_idx_cstr = command.GetArgumentAtIndex(0);
132
133                const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
134                const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0);
135                if (frame_idx < num_frames)
136                {
137                    exe_ctx.thread->SetSelectedFrameByIndex (frame_idx);
138                    exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get();
139
140                    if (exe_ctx.frame)
141                    {
142                        bool already_shown = false;
143                        SymbolContext frame_sc(exe_ctx.frame->GetSymbolContext(eSymbolContextLineEntry));
144                        if (m_interpreter.GetDebugger().GetUseExternalEditor() && frame_sc.line_entry.file && frame_sc.line_entry.line != 0)
145                        {
146                            already_shown = Host::OpenFileInExternalEditor (frame_sc.line_entry.file, frame_sc.line_entry.line);
147                        }
148
149                        if (DisplayFrameForExecutionContext (exe_ctx.thread,
150                                                             exe_ctx.frame,
151                                                             m_interpreter,
152                                                             result.GetOutputStream(),
153                                                             true,
154                                                             !already_shown,
155                                                             3,
156                                                             3))
157                        {
158                            result.SetStatus (eReturnStatusSuccessFinishResult);
159                            return result.Succeeded();
160                        }
161                    }
162                }
163                if (frame_idx == UINT32_MAX)
164                    result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr);
165                else
166                    result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx);
167            }
168            else
169            {
170                result.AppendError ("invalid arguments");
171                result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str());
172            }
173        }
174        else
175        {
176            result.AppendError ("no current thread");
177        }
178        result.SetStatus (eReturnStatusFailed);
179        return false;
180    }
181};
182
183#pragma mark CommandObjectFrameVariable
184//----------------------------------------------------------------------
185// List images with associated information
186//----------------------------------------------------------------------
187class CommandObjectFrameVariable : public CommandObject
188{
189public:
190
191    class CommandOptions : public Options
192    {
193    public:
194
195        CommandOptions () :
196            Options()
197        {
198            ResetOptionValues ();
199        }
200
201        virtual
202        ~CommandOptions ()
203        {
204        }
205
206        virtual Error
207        SetOptionValue (int option_idx, const char *option_arg)
208        {
209            Error error;
210            bool success;
211            char short_option = (char) m_getopt_table[option_idx].val;
212            switch (short_option)
213            {
214            case 'o':   use_objc     = true;  break;
215            case 'n':   name = option_arg;    break;
216            case 'r':   use_regex    = true;  break;
217            case 'a':   show_args    = false; break;
218            case 'l':   show_locals  = false; break;
219            case 'g':   show_globals = true;  break;
220            case 't':   show_types   = false; break;
221            case 'y':   show_summary = false; break;
222            case 'L':   show_location= true;  break;
223            case 'c':   show_decl    = true;  break;
224            case 'D':   debug        = true;  break;
225            case 'd':
226                max_depth = Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success);
227                if (!success)
228                    error.SetErrorStringWithFormat("Invalid max depth '%s'.\n", option_arg);
229                break;
230
231            case 'p':
232                ptr_depth = Args::StringToUInt32 (option_arg, 0, 0, &success);
233                if (!success)
234                    error.SetErrorStringWithFormat("Invalid pointer depth '%s'.\n", option_arg);
235                break;
236
237            case 'G':
238                globals.push_back(ConstString (option_arg));
239                break;
240
241            case 's':
242                show_scope = true;
243                break;
244
245            default:
246                error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
247                break;
248            }
249
250            return error;
251        }
252
253        void
254        ResetOptionValues ()
255        {
256            Options::ResetOptionValues();
257
258            name.clear();
259            use_objc      = false;
260            use_regex     = false;
261            show_args     = true;
262            show_locals   = true;
263            show_globals  = false;
264            show_types    = true;
265            show_scope    = false;
266            show_summary  = true;
267            show_location = false;
268            show_decl     = false;
269            debug         = false;
270            max_depth     = UINT32_MAX;
271            ptr_depth     = 0;
272            globals.clear();
273        }
274
275        const lldb::OptionDefinition*
276        GetDefinitions ()
277        {
278            return g_option_table;
279        }
280
281        // Options table: Required for subclasses of Options.
282
283        static lldb::OptionDefinition g_option_table[];
284        std::string name;
285        bool use_objc:1,
286             use_regex:1,
287             show_args:1,
288             show_locals:1,
289             show_globals:1,
290             show_types:1,
291             show_scope:1,
292             show_summary:1,
293             show_location:1,
294             show_decl:1,
295             debug:1;
296        uint32_t max_depth; // The depth to print when dumping concrete (not pointers) aggreate values
297        uint32_t ptr_depth; // The default depth that is dumped when we find pointers
298        std::vector<ConstString> globals;
299        // Instance variables to hold the values for command options.
300    };
301
302    CommandObjectFrameVariable (CommandInterpreter &interpreter) :
303        CommandObject (interpreter,
304                       "frame variable",
305                       "Show frame variables. All argument and local variables "
306                       "that are in scope will be shown when no arguments are given. "
307                       "If any arguments are specified, they can be names of "
308                       "argument, local, file static and file global variables."
309                       "Children of aggregate variables can be specified such as "
310                       "'var->child.x'.",
311                       NULL)
312    {
313        CommandArgumentEntry arg;
314        CommandArgumentData var_name_arg;
315
316        // Define the first (and only) variant of this arg.
317        var_name_arg.arg_type = eArgTypeVarName;
318        var_name_arg.arg_repetition = eArgRepeatStar;
319
320        // There is only one variant this argument could be; put it into the argument entry.
321        arg.push_back (var_name_arg);
322
323        // Push the data for the first argument into the m_arguments vector.
324        m_arguments.push_back (arg);
325    }
326
327    virtual
328    ~CommandObjectFrameVariable ()
329    {
330    }
331
332    virtual
333    Options *
334    GetOptions ()
335    {
336        return &m_options;
337    }
338
339    void
340    DumpValueObject (CommandReturnObject &result,
341                     ExecutionContextScope *exe_scope,
342                     ValueObject *valobj,
343                     const char *root_valobj_name,
344                     uint32_t ptr_depth,
345                     uint32_t curr_depth,
346                     uint32_t max_depth,
347                     bool use_objc,
348                     bool scope_already_checked)
349    {
350        if (valobj)
351        {
352            Stream &s = result.GetOutputStream();
353
354            //const char *loc_cstr = valobj->GetLocationAsCString();
355            if (m_options.show_location)
356            {
357                s.Printf("%s: ", valobj->GetLocationAsCString(exe_scope));
358            }
359            if (m_options.debug)
360                s.Printf ("%p ValueObject{%u} ", valobj, valobj->GetID());
361
362            s.Indent();
363
364            if (m_options.show_types)
365                s.Printf("(%s) ", valobj->GetTypeName().AsCString());
366
367            const char *name_cstr = root_valobj_name ? root_valobj_name : valobj->GetName().AsCString("");
368            s.Printf ("%s = ", name_cstr);
369
370            if (!scope_already_checked && !valobj->IsInScope(exe_scope->CalculateStackFrame()))
371            {
372                s.PutCString("error: out of scope");
373                return;
374            }
375
376            const char *val_cstr = valobj->GetValueAsCString(exe_scope);
377            const char *err_cstr = valobj->GetError().AsCString();
378
379            if (err_cstr)
380            {
381                s.Printf ("error: %s", err_cstr);
382            }
383            else
384            {
385                const char *sum_cstr = valobj->GetSummaryAsCString(exe_scope);
386
387                const bool is_aggregate = ClangASTContext::IsAggregateType (valobj->GetClangType());
388
389                if (val_cstr)
390                    s.PutCString(val_cstr);
391
392                if (sum_cstr)
393                    s.Printf(" %s", sum_cstr);
394
395                if (use_objc)
396                {
397                    const char *object_desc = valobj->GetObjectDescription(exe_scope);
398                    if (object_desc)
399                        s.Printf("\n%s\n", object_desc);
400                    else
401                        s.Printf ("No description available.\n");
402                    return;
403                }
404
405
406                if (curr_depth < max_depth)
407                {
408                    if (is_aggregate)
409                        s.PutChar('{');
410
411                    bool is_ptr_or_ref = ClangASTContext::IsPointerOrReferenceType (valobj->GetClangType());
412
413                    if (is_ptr_or_ref && ptr_depth == 0)
414                        return;
415
416                    const uint32_t num_children = valobj->GetNumChildren();
417                    if (num_children)
418                    {
419                        s.IndentMore();
420                        for (uint32_t idx=0; idx<num_children; ++idx)
421                        {
422                            ValueObjectSP child_sp(valobj->GetChildAtIndex(idx, true));
423                            if (child_sp.get())
424                            {
425                                s.EOL();
426                                DumpValueObject (result,
427                                                 exe_scope,
428                                                 child_sp.get(),
429                                                 NULL,
430                                                 is_ptr_or_ref ? ptr_depth - 1 : ptr_depth,
431                                                 curr_depth + 1,
432                                                 max_depth,
433                                                 false,
434                                                 true);
435                                if (idx + 1 < num_children)
436                                    s.PutChar(',');
437                            }
438                        }
439                        s.IndentLess();
440                    }
441                    if (is_aggregate)
442                    {
443                        s.EOL();
444                        s.Indent("}");
445                    }
446                }
447                else
448                {
449                    if (is_aggregate)
450                    {
451                        s.PutCString("{...}");
452                    }
453                }
454
455            }
456        }
457    }
458
459    virtual bool
460    Execute
461    (
462        Args& command,
463        CommandReturnObject &result
464    )
465    {
466        ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
467        if (exe_ctx.frame == NULL)
468        {
469            result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
470            result.SetStatus (eReturnStatusFailed);
471            return false;
472        }
473        else
474        {
475            Stream &s = result.GetOutputStream();
476
477            bool get_file_globals = true;
478            VariableList *variable_list = exe_ctx.frame->GetVariableList (get_file_globals);
479
480            VariableSP var_sp;
481            ValueObjectSP valobj_sp;
482            //ValueObjectList &valobj_list = exe_ctx.frame->GetValueObjectList();
483            const char *name_cstr = NULL;
484            size_t idx;
485            if (!m_options.globals.empty())
486            {
487                uint32_t fail_count = 0;
488                if (exe_ctx.target)
489                {
490                    const size_t num_globals = m_options.globals.size();
491                    for (idx = 0; idx < num_globals; ++idx)
492                    {
493                        VariableList global_var_list;
494                        const uint32_t num_matching_globals = exe_ctx.target->GetImages().FindGlobalVariables (m_options.globals[idx], true, UINT32_MAX, global_var_list);
495
496                        if (num_matching_globals == 0)
497                        {
498                            ++fail_count;
499                            result.GetErrorStream().Printf ("error: can't find global variable '%s'\n", m_options.globals[idx].AsCString());
500                        }
501                        else
502                        {
503                            for (uint32_t global_idx=0; global_idx<num_matching_globals; ++global_idx)
504                            {
505                                var_sp = global_var_list.GetVariableAtIndex(global_idx);
506                                if (var_sp)
507                                {
508                                    valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
509                                    if (!valobj_sp)
510                                        valobj_sp = exe_ctx.frame->TrackGlobalVariable (var_sp);
511
512                                    if (valobj_sp)
513                                    {
514                                        if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
515                                        {
516                                            var_sp->GetDeclaration ().DumpStopContext (&s, false);
517                                            s.PutCString (": ");
518                                        }
519
520                                        DumpValueObject (result,
521                                                         exe_ctx.frame,
522                                                         valobj_sp.get(),
523                                                         name_cstr,
524                                                         m_options.ptr_depth,
525                                                         0,
526                                                         m_options.max_depth,
527                                                         m_options.use_objc,
528                                                         false);
529
530                                        s.EOL();
531                                    }
532                                }
533                            }
534                        }
535                    }
536                }
537                if (fail_count)
538                    result.SetStatus (eReturnStatusFailed);
539            }
540            else if (variable_list)
541            {
542                if (command.GetArgumentCount() > 0)
543                {
544                    // If we have any args to the variable command, we will make
545                    // variable objects from them...
546                    for (idx = 0; (name_cstr = command.GetArgumentAtIndex(idx)) != NULL; ++idx)
547                    {
548                        uint32_t ptr_depth = m_options.ptr_depth;
549                        // If first character is a '*', then show pointer contents
550                        if (name_cstr[0] == '*')
551                        {
552                            ++ptr_depth;
553                            name_cstr++; // Skip the '*'
554                        }
555
556                        std::string var_path (name_cstr);
557                        size_t separator_idx = var_path.find_first_of(".-[");
558
559                        ConstString name_const_string;
560                        if (separator_idx == std::string::npos)
561                            name_const_string.SetCString (var_path.c_str());
562                        else
563                            name_const_string.SetCStringWithLength (var_path.c_str(), separator_idx);
564
565                        var_sp = variable_list->FindVariable(name_const_string);
566                        if (var_sp)
567                        {
568                            valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
569
570                            var_path.erase (0, name_const_string.GetLength ());
571                            // We are dumping at least one child
572                            while (separator_idx != std::string::npos)
573                            {
574                                // Calculate the next separator index ahead of time
575                                ValueObjectSP child_valobj_sp;
576                                const char separator_type = var_path[0];
577                                switch (separator_type)
578                                {
579
580                                case '-':
581                                    if (var_path.size() >= 2 && var_path[1] != '>')
582                                    {
583                                        result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
584                                                                        var_path.c_str());
585                                        var_path.clear();
586                                        valobj_sp.reset();
587                                        break;
588                                    }
589                                    var_path.erase (0, 1); // Remove the '-'
590                                    // Fall through
591                                case '.':
592                                    {
593                                        var_path.erase (0, 1); // Remove the '.' or '>'
594                                        separator_idx = var_path.find_first_of(".-[");
595                                        ConstString child_name;
596                                        if (separator_idx == std::string::npos)
597                                            child_name.SetCString (var_path.c_str());
598                                        else
599                                            child_name.SetCStringWithLength(var_path.c_str(), separator_idx);
600
601                                        child_valobj_sp = valobj_sp->GetChildMemberWithName (child_name, true);
602                                        if (!child_valobj_sp)
603                                        {
604                                            result.GetErrorStream().Printf ("error: can't find child of '%s' named '%s'\n",
605                                                                            valobj_sp->GetName().AsCString(),
606                                                                            child_name.GetCString());
607                                            var_path.clear();
608                                            valobj_sp.reset();
609                                            break;
610                                        }
611                                        // Remove the child name from the path
612                                        var_path.erase(0, child_name.GetLength());
613                                    }
614                                    break;
615
616                                case '[':
617                                    // Array member access, or treating pointer as an array
618                                    if (var_path.size() > 2) // Need at least two brackets and a number
619                                    {
620                                        char *end = NULL;
621                                        int32_t child_index = ::strtol (&var_path[1], &end, 0);
622                                        if (end && *end == ']')
623                                        {
624
625                                            if (valobj_sp->IsPointerType ())
626                                            {
627                                                child_valobj_sp = valobj_sp->GetSyntheticArrayMemberFromPointer (child_index, true);
628                                            }
629                                            else
630                                            {
631                                                child_valobj_sp = valobj_sp->GetChildAtIndex (child_index, true);
632                                            }
633
634                                            if (!child_valobj_sp)
635                                            {
636                                                result.GetErrorStream().Printf ("error: invalid array index %u in '%s'\n",
637                                                                                child_index,
638                                                                                valobj_sp->GetName().AsCString());
639                                                var_path.clear();
640                                                valobj_sp.reset();
641                                                break;
642                                            }
643
644                                            // Erase the array member specification '[%i]' where %i is the array index
645                                            var_path.erase(0, (end - var_path.c_str()) + 1);
646                                            separator_idx = var_path.find_first_of(".-[");
647
648                                            // Break out early from the switch since we were able to find the child member
649                                            break;
650                                        }
651                                    }
652                                    result.GetErrorStream().Printf ("error: invalid array member specification for '%s' starting at '%s'\n",
653                                                                    valobj_sp->GetName().AsCString(),
654                                                                    var_path.c_str());
655                                    var_path.clear();
656                                    valobj_sp.reset();
657                                    break;
658
659                                    break;
660
661                                default:
662                                    result.GetErrorStream().Printf ("error: invalid character in variable path starting at '%s'\n",
663                                                                        var_path.c_str());
664                                    var_path.clear();
665                                    valobj_sp.reset();
666                                    separator_idx = std::string::npos;
667                                    break;
668                                }
669
670                                if (child_valobj_sp)
671                                    valobj_sp = child_valobj_sp;
672
673                                if (var_path.empty())
674                                    break;
675
676                            }
677
678                            if (valobj_sp)
679                            {
680                                if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
681                                {
682                                    var_sp->GetDeclaration ().DumpStopContext (&s, false);
683                                    s.PutCString (": ");
684                                }
685
686                                DumpValueObject (result,
687                                                 exe_ctx.frame,
688                                                 valobj_sp.get(),
689                                                 name_cstr,
690                                                 ptr_depth,
691                                                 0,
692                                                 m_options.max_depth,
693                                                 m_options.use_objc,
694                                                 false);
695
696                                s.EOL();
697                            }
698                        }
699                        else
700                        {
701                            result.GetErrorStream().Printf ("error: unable to find any variables named '%s'\n", name_cstr);
702                            var_path.clear();
703                        }
704                    }
705                }
706                else
707                {
708                    const uint32_t num_variables = variable_list->GetSize();
709
710                    if (num_variables > 0)
711                    {
712                        for (uint32_t i=0; i<num_variables; i++)
713                        {
714                            VariableSP var_sp (variable_list->GetVariableAtIndex(i));
715                            bool dump_variable = true;
716
717                            switch (var_sp->GetScope())
718                            {
719                            case eValueTypeVariableGlobal:
720                                dump_variable = m_options.show_globals;
721                                if (dump_variable && m_options.show_scope)
722                                    s.PutCString("GLOBAL: ");
723                                break;
724
725                            case eValueTypeVariableStatic:
726                                dump_variable = m_options.show_globals;
727                                if (dump_variable && m_options.show_scope)
728                                    s.PutCString("STATIC: ");
729                                break;
730
731                            case eValueTypeVariableArgument:
732                                dump_variable = m_options.show_args;
733                                if (dump_variable && m_options.show_scope)
734                                    s.PutCString("   ARG: ");
735                                break;
736
737                            case eValueTypeVariableLocal:
738                                dump_variable = m_options.show_locals;
739                                if (dump_variable && m_options.show_scope)
740                                    s.PutCString(" LOCAL: ");
741                                break;
742
743                            default:
744                                break;
745                            }
746
747                            if (dump_variable)
748                            {
749
750                                // Use the variable object code to make sure we are
751                                // using the same APIs as the the public API will be
752                                // using...
753                                valobj_sp = exe_ctx.frame->GetValueObjectForFrameVariable (var_sp);
754                                if (valobj_sp)
755                                {
756                                    // When dumping all variables, don't print any variables
757                                    // that are not in scope to avoid extra unneeded output
758                                    if (valobj_sp->IsInScope (exe_ctx.frame))
759                                    {
760                                        if (m_options.show_decl && var_sp->GetDeclaration ().GetFile())
761                                        {
762                                            var_sp->GetDeclaration ().DumpStopContext (&s, false);
763                                            s.PutCString (": ");
764                                        }
765                                        DumpValueObject (result,
766                                                         exe_ctx.frame,
767                                                         valobj_sp.get(),
768                                                         name_cstr,
769                                                         m_options.ptr_depth,
770                                                         0,
771                                                         m_options.max_depth,
772                                                         m_options.use_objc,
773                                                         true);
774
775                                        s.EOL();
776                                    }
777                                }
778                            }
779                        }
780                    }
781                }
782                result.SetStatus (eReturnStatusSuccessFinishResult);
783            }
784        }
785        return result.Succeeded();
786    }
787protected:
788
789    CommandOptions m_options;
790};
791
792lldb::OptionDefinition
793CommandObjectFrameVariable::CommandOptions::g_option_table[] =
794{
795{ LLDB_OPT_SET_1, false, "debug",      'D', no_argument,       NULL, 0, eArgTypeNone,    "Enable verbose debug information."},
796{ LLDB_OPT_SET_1, false, "depth",      'd', required_argument, NULL, 0, eArgTypeCount,   "Set the max recurse depth when dumping aggregate types (default is infinity)."},
797{ LLDB_OPT_SET_1, false, "show-globals",'g', no_argument,      NULL, 0, eArgTypeNone,    "Show the current frame source file global and static variables."},
798{ LLDB_OPT_SET_1, false, "find-global",'G', required_argument, NULL, 0, eArgTypeVarName, "Find a global variable by name (which might not be in the current stack frame source file)."},
799{ LLDB_OPT_SET_1, false, "location",   'L', no_argument,       NULL, 0, eArgTypeNone,    "Show variable location information."},
800{ LLDB_OPT_SET_1, false, "show-declaration", 'c', no_argument, NULL, 0, eArgTypeNone,    "Show variable declaration information (source file and line where the variable was declared)."},
801{ LLDB_OPT_SET_1, false, "name",       'n', required_argument, NULL, 0, eArgTypeVarName, "Lookup a variable by name or regex (--regex) for the current execution context."},
802{ LLDB_OPT_SET_1, false, "no-args",    'a', no_argument,       NULL, 0, eArgTypeNone,    "Omit function arguments."},
803{ LLDB_OPT_SET_1, false, "no-locals",  'l', no_argument,       NULL, 0, eArgTypeNone,    "Omit local variables."},
804{ LLDB_OPT_SET_1, false, "no-types",   't', no_argument,       NULL, 0, eArgTypeNone,    "Omit variable type names."},
805{ LLDB_OPT_SET_1, false, "no-summary", 'y', no_argument,       NULL, 0, eArgTypeNone,    "Omit summary information."},
806{ LLDB_OPT_SET_1, false, "scope",      's', no_argument,       NULL, 0, eArgTypeNone,    "Show variable scope (argument, local, global, static)."},
807{ LLDB_OPT_SET_1, false, "objc",       'o', no_argument,       NULL, 0, eArgTypeNone,    "When looking up a variable by name (--name), print as an Objective-C object."},
808{ LLDB_OPT_SET_1, false, "ptr-depth",  'p', required_argument, NULL, 0, eArgTypeCount,   "The number of pointers to be traversed when dumping values (default is zero)."},
809{ LLDB_OPT_SET_1, false, "regex",      'r', no_argument,       NULL, 0, eArgTypeCount,    "The <name> argument for name lookups are regular expressions."},
810{ 0, false, NULL, 0, 0, NULL, NULL, eArgTypeNone, NULL }
811};
812#pragma mark CommandObjectMultiwordFrame
813
814//-------------------------------------------------------------------------
815// CommandObjectMultiwordFrame
816//-------------------------------------------------------------------------
817
818CommandObjectMultiwordFrame::CommandObjectMultiwordFrame (CommandInterpreter &interpreter) :
819    CommandObjectMultiword (interpreter,
820                            "frame",
821                            "A set of commands for operating on the current thread's frames.",
822                            "frame <subcommand> [<subcommand-options>]")
823{
824    LoadSubCommand ("info",   CommandObjectSP (new CommandObjectFrameInfo (interpreter)));
825    LoadSubCommand ("select", CommandObjectSP (new CommandObjectFrameSelect (interpreter)));
826    LoadSubCommand ("variable", CommandObjectSP (new CommandObjectFrameVariable (interpreter)));
827}
828
829CommandObjectMultiwordFrame::~CommandObjectMultiwordFrame ()
830{
831}
832
833