blob: 9e02d9eec32209a2dc740a4c8c8d369a7160b562 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectMultiword.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 "lldb/Interpreter/CommandObjectMultiword.h"
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14// Project includes
Greg Clayton63094e02010-06-23 01:19:29 +000015#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Interpreter/CommandInterpreter.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000017#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Interpreter/CommandReturnObject.h"
19
20using namespace lldb;
21using namespace lldb_private;
22
23//-------------------------------------------------------------------------
24// CommandObjectMultiword
25//-------------------------------------------------------------------------
26
27CommandObjectMultiword::CommandObjectMultiword
28(
29 const char *name,
30 const char *help,
31 const char *syntax,
32 uint32_t flags
33) :
34 CommandObject (name, help, syntax, flags)
35{
36}
37
38CommandObjectMultiword::~CommandObjectMultiword ()
39{
40}
41
42CommandObjectSP
43CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
44{
45 CommandObjectSP return_cmd_sp;
46 CommandObject::CommandMap::iterator pos;
47
48 if (!m_subcommand_dict.empty())
49 {
50 pos = m_subcommand_dict.find (sub_cmd);
51 if (pos != m_subcommand_dict.end())
52 return_cmd_sp = pos->second;
53 else
54 {
55
56 StringList local_matches;
57 if (matches == NULL)
58 matches = &local_matches;
59 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
60
61 if (num_matches == 1)
62 {
63 // Cleaner, but slightly less efficient would be to call back into this function, since I now
64 // know I have an exact match...
65
66 sub_cmd = matches->GetStringAtIndex(0);
67 pos = m_subcommand_dict.find(sub_cmd);
68 if (pos != m_subcommand_dict.end())
69 return_cmd_sp = pos->second;
70 }
71 }
72 }
73 return return_cmd_sp;
74}
75
76CommandObject *
77CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
78{
79 return GetSubcommandSP(sub_cmd, matches).get();
80}
81
82bool
Greg Clayton63094e02010-06-23 01:19:29 +000083CommandObjectMultiword::LoadSubCommand
84(
85 CommandInterpreter &interpreter,
86 const char *name,
87 const CommandObjectSP& cmd_obj
88)
Chris Lattner24943d22010-06-08 16:52:24 +000089{
90 CommandMap::iterator pos;
91 bool success = true;
92
93 pos = m_subcommand_dict.find(name);
94 if (pos == m_subcommand_dict.end())
95 {
96 m_subcommand_dict[name] = cmd_obj;
Greg Clayton63094e02010-06-23 01:19:29 +000097 interpreter.CrossRegisterCommand (name, GetCommandName());
Chris Lattner24943d22010-06-08 16:52:24 +000098 }
99 else
100 success = false;
101
102 return success;
103}
104
105bool
106CommandObjectMultiword::Execute
107(
Greg Clayton63094e02010-06-23 01:19:29 +0000108 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000109 Args& args,
Chris Lattner24943d22010-06-08 16:52:24 +0000110 CommandReturnObject &result
111)
112{
113 const size_t argc = args.GetArgumentCount();
114 if (argc == 0)
115 {
Greg Clayton63094e02010-06-23 01:19:29 +0000116 GenerateHelpText (interpreter, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000117 }
118 else
119 {
120 const char *sub_command = args.GetArgumentAtIndex (0);
121
122 if (sub_command)
123 {
124 if (::strcasecmp (sub_command, "help") == 0)
125 {
Greg Clayton63094e02010-06-23 01:19:29 +0000126 GenerateHelpText (interpreter, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000127 }
128 else if (!m_subcommand_dict.empty())
129 {
130 StringList matches;
131 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
132 if (sub_cmd_obj != NULL)
133 {
134 // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there
135 // the command-specific version of Execute will be called, with the processed arguments.
136
137 args.Shift();
138
Greg Clayton63094e02010-06-23 01:19:29 +0000139 sub_cmd_obj->ExecuteWithOptions (interpreter, args, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000140 }
141 else
142 {
143 std::string error_msg;
144 int num_subcmd_matches = matches.GetSize();
145 if (num_subcmd_matches > 0)
146 error_msg.assign ("ambiguous command ");
147 else
148 error_msg.assign ("invalid command ");
149
150 error_msg.append ("'");
151 error_msg.append (GetCommandName());
152 error_msg.append (" ");
153 error_msg.append (sub_command);
154 error_msg.append ("'");
155
156 if (num_subcmd_matches > 0)
157 {
158 error_msg.append (" Possible completions:");
159 for (int i = 0; i < num_subcmd_matches; i++)
160 {
161 error_msg.append ("\n\t");
162 error_msg.append (matches.GetStringAtIndex (i));
163 }
164 }
165 error_msg.append ("\n");
166 result.AppendRawError (error_msg.c_str(), error_msg.size());
167 result.SetStatus (eReturnStatusFailed);
168 }
169 }
170 else
171 {
172 result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
173 result.SetStatus (eReturnStatusFailed);
174 }
175 }
176 }
177
178 return result.Succeeded();
179}
180
181void
Greg Clayton63094e02010-06-23 01:19:29 +0000182CommandObjectMultiword::GenerateHelpText (CommandInterpreter &interpreter, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000183{
184 // First time through here, generate the help text for the object and
185 // push it to the return result object as well
186
187 StreamString &output_stream = result.GetOutputStream();
188 output_stream.PutCString ("The following subcommands are supported:\n\n");
189
190 CommandMap::iterator pos;
Greg Clayton63094e02010-06-23 01:19:29 +0000191 std::string longest_word = interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000192 uint32_t max_len = 0;
193
194 if (! longest_word.empty())
195 max_len = strlen (longest_word.c_str()) + 4; // Indent the output by 4 spaces.
196
197 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
198 {
199 std::string indented_command (" ");
200 indented_command.append (pos->first);
Greg Clayton63094e02010-06-23 01:19:29 +0000201 interpreter.OutputFormattedHelpText (result.GetOutputStream(),
202 indented_command.c_str(),
203 "--",
204 pos->second->GetHelp(),
205 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000206 }
207
208 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
209
210 result.SetStatus (eReturnStatusSuccessFinishNoResult);
211}
212
213int
214CommandObjectMultiword::HandleCompletion
215(
Greg Clayton63094e02010-06-23 01:19:29 +0000216 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +0000217 Args &input,
218 int &cursor_index,
219 int &cursor_char_position,
220 int match_start_point,
221 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000222 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000223 StringList &matches
224)
225{
Jim Ingham802f8b02010-06-30 05:02:46 +0000226 // Any of the command matches will provide a complete word, otherwise the individual
227 // completers will override this.
228 word_complete = true;
229
Chris Lattner24943d22010-06-08 16:52:24 +0000230 if (cursor_index == 0)
231 {
Greg Clayton63094e02010-06-23 01:19:29 +0000232 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
233 input.GetArgumentAtIndex(0),
234 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000235
236 if (matches.GetSize() == 1
237 && matches.GetStringAtIndex(0) != NULL
238 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
239 {
240 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000241 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
242 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000243 if (cmd_obj != NULL)
244 {
245 matches.DeleteStringAtIndex (0);
246 input.Shift();
247 cursor_char_position = 0;
248 input.AppendArgument ("");
Greg Clayton63094e02010-06-23 01:19:29 +0000249 return cmd_obj->HandleCompletion (interpreter,
250 input, cursor_index,
251 cursor_char_position,
252 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000253 max_return_elements,
254 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000255 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000256 }
257 else
258 return matches.GetSize();
259 }
260 else
261 return matches.GetSize();
262 }
263 else
264 {
Greg Clayton63094e02010-06-23 01:19:29 +0000265 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
266 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000267 if (sub_command_object == NULL)
268 {
269 return matches.GetSize();
270 }
271 else
272 {
273 // Remove the one match that we got from calling GetSubcommandObject.
274 matches.DeleteStringAtIndex(0);
275 input.Shift();
276 cursor_index--;
Greg Clayton63094e02010-06-23 01:19:29 +0000277 return sub_command_object->HandleCompletion (interpreter,
278 input,
279 cursor_index,
280 cursor_char_position,
281 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000282 max_return_elements,
283 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000284 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000285 }
286
287 }
288}
289
Jim Ingham767af882010-07-07 03:36:20 +0000290const char *
291CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
292{
293 if (current_command_args.GetArgumentCount() == 0)
294 return NULL;
295 index++;
296 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
297 if (sub_command_object == NULL)
298 return NULL;
299 else
300 return sub_command_object->GetRepeatCommand(current_command_args, index);
301}
302