blob: df70bc9aea3393b4a3cf34660534882f01a42444 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectSourceFile.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 "CommandObjectSourceFile.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Args.h"
17#include "lldb/Interpreter/CommandContext.h"
18#include "lldb/Interpreter/CommandInterpreter.h"
19#include "lldb/Interpreter/CommandReturnObject.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Core/SourceManager.h"
22#include "lldb/Target/TargetList.h"
23#include "lldb/Interpreter/CommandCompletions.h"
24
25using namespace lldb;
26using namespace lldb_private;
27
28CommandObjectSourceFile::CommandOptions::CommandOptions () :
29 Options()
30{
31}
32
33CommandObjectSourceFile::CommandOptions::~CommandOptions ()
34{
35}
36
37Error
38CommandObjectSourceFile::CommandOptions::SetOptionValue (int option_idx, const char *option_arg)
39{
40 Error error;
41 const char short_option = g_option_table[option_idx].short_option;
42 switch (short_option)
43 {
44 case 'l':
45 start_line = Args::StringToUInt32 (option_arg, 0);
46 if (start_line == 0)
47 error.SetErrorStringWithFormat("Invalid line number: '%s'.\n", option_arg);
48 break;
49
50 case 'n':
51 num_lines = Args::StringToUInt32 (option_arg, 0);
52 if (num_lines == 0)
53 error.SetErrorStringWithFormat("Invalid line count: '%s'.\n", option_arg);
54 break;
55
56 case 'f':
57 file_name = option_arg;
58 break;
59
60 default:
61 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
62 break;
63 }
64
65 return error;
66}
67
68void
69CommandObjectSourceFile::CommandOptions::ResetOptionValues ()
70{
71 Options::ResetOptionValues();
72
73 file_spec.Clear();
74 file_name.clear();
75 start_line = 0;
76 num_lines = 10;
77}
78
79const lldb::OptionDefinition*
80CommandObjectSourceFile::CommandOptions::GetDefinitions ()
81{
82 return g_option_table;
83}
84
85lldb::OptionDefinition
86CommandObjectSourceFile::CommandOptions::g_option_table[] =
87{
88{ 0, false, "line", 'l', required_argument, NULL, 0, "<line>", "The line number at which to start the display source."},
89{ 0, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, "<file>", "The file from which to display source."},
90{ 0, false, "count", 'n', required_argument, NULL, 0, "<count>", "The number of source lines to display."},
91{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
92};
93
94
95
96//-------------------------------------------------------------------------
97// CommandObjectSourceFile
98//-------------------------------------------------------------------------
99
100CommandObjectSourceFile::CommandObjectSourceFile() :
101 CommandObject ("source-file",
102 "Display source files from the current executable's debug info.",
103 "source-file [<cmd-options>] [<filename>]")
104{
105}
106
107CommandObjectSourceFile::~CommandObjectSourceFile ()
108{
109}
110
111
112Options *
113CommandObjectSourceFile::GetOptions ()
114{
115 return &m_options;
116}
117
118
119bool
120CommandObjectSourceFile::Execute
121(
122 Args& args,
123 CommandContext *context,
124 CommandInterpreter *interpreter,
125 CommandReturnObject &result
126)
127{
128 const int argc = args.GetArgumentCount();
129
130 if (argc != 0)
131 {
132 result.AppendErrorWithFormat("'%s' takes no arguments, only flags.\n", GetCommandName());
133 result.SetStatus (eReturnStatusFailed);
134 }
135
136 ExecutionContext exe_ctx(context->GetExecutionContext());
137 if (m_options.file_name.empty())
138 {
139 // Last valid source manager context, or the current frame if no
140 // valid last context in source manager.
141 // One little trick here, if you type the exact same list command twice in a row, it is
142 // more likely because you typed it once, then typed it again
143 if (m_options.start_line == 0)
144 {
145 if (interpreter->GetSourceManager().DisplayMoreWithLineNumbers (&result.GetOutputStream()))
146 {
147 result.SetStatus (eReturnStatusSuccessFinishResult);
148 }
149 }
150 else
151 {
152 if (interpreter->GetSourceManager().DisplaySourceLinesWithLineNumbersUsingLastFile(
153 m_options.start_line, // Line to display
154 0, // Lines before line to display
155 m_options.num_lines, // Lines after line to display
156 "", // Don't mark "line"
157 &result.GetOutputStream()))
158 {
159 result.SetStatus (eReturnStatusSuccessFinishResult);
160 }
161
162 }
163 }
164 else
165 {
166 const char *filename = m_options.file_name.c_str();
167 Target *target = context->GetTarget();
168 if (target == NULL)
169 {
170 result.AppendError ("invalid target, set executable file using 'file' command");
171 result.SetStatus (eReturnStatusFailed);
172 return false;
173 }
174
175
176 bool check_inlines = false;
177 SymbolContextList sc_list;
178 size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (filename,
179 0,
180 check_inlines,
181 eSymbolContextModule | eSymbolContextCompUnit,
182 sc_list);
183 if (num_matches > 0)
184 {
185 SymbolContext sc;
186 if (sc_list.GetContextAtIndex(0, sc))
187 {
188 if (sc.comp_unit)
189 {
190 interpreter->GetSourceManager ().DisplaySourceLinesWithLineNumbers (sc.comp_unit,
191 m_options.start_line, // Line to display
192 0, // Lines before line to display
193 m_options.num_lines, // Lines after line to display
194 "", // Don't mark "line"
195 &result.GetOutputStream());
196
197 result.SetStatus (eReturnStatusSuccessFinishResult);
198
199 }
200 }
201 }
202 }
203
204 return result.Succeeded();
205}
206