blob: e11d37bb77db249c6b902b976b70ca5965e59b62 [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(
Greg Clayton238c0a12010-09-18 01:14:36 +000029 CommandInterpreter &interpreter,
Chris Lattner24943d22010-06-08 16:52:24 +000030 const char *name,
31 const char *help,
32 const char *syntax,
33 uint32_t flags
34) :
Greg Clayton238c0a12010-09-18 01:14:36 +000035 CommandObject (interpreter, name, help, syntax, flags)
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37}
38
39CommandObjectMultiword::~CommandObjectMultiword ()
40{
41}
42
43CommandObjectSP
44CommandObjectMultiword::GetSubcommandSP (const char *sub_cmd, StringList *matches)
45{
46 CommandObjectSP return_cmd_sp;
47 CommandObject::CommandMap::iterator pos;
48
49 if (!m_subcommand_dict.empty())
50 {
51 pos = m_subcommand_dict.find (sub_cmd);
Johnny Chendc6c2632010-12-01 01:04:22 +000052 if (pos != m_subcommand_dict.end()) {
53 // An exact match; append the sub_cmd to the 'matches' string list.
54 if (matches)
55 matches->AppendString(sub_cmd);
Chris Lattner24943d22010-06-08 16:52:24 +000056 return_cmd_sp = pos->second;
Johnny Chendc6c2632010-12-01 01:04:22 +000057 }
Chris Lattner24943d22010-06-08 16:52:24 +000058 else
59 {
60
61 StringList local_matches;
62 if (matches == NULL)
63 matches = &local_matches;
64 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
65
66 if (num_matches == 1)
67 {
68 // Cleaner, but slightly less efficient would be to call back into this function, since I now
69 // know I have an exact match...
70
71 sub_cmd = matches->GetStringAtIndex(0);
72 pos = m_subcommand_dict.find(sub_cmd);
73 if (pos != m_subcommand_dict.end())
74 return_cmd_sp = pos->second;
75 }
76 }
77 }
78 return return_cmd_sp;
79}
80
81CommandObject *
82CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
83{
84 return GetSubcommandSP(sub_cmd, matches).get();
85}
86
87bool
Greg Clayton63094e02010-06-23 01:19:29 +000088CommandObjectMultiword::LoadSubCommand
89(
Greg Clayton63094e02010-06-23 01:19:29 +000090 const char *name,
91 const CommandObjectSP& cmd_obj
92)
Chris Lattner24943d22010-06-08 16:52:24 +000093{
94 CommandMap::iterator pos;
95 bool success = true;
96
97 pos = m_subcommand_dict.find(name);
98 if (pos == m_subcommand_dict.end())
99 {
100 m_subcommand_dict[name] = cmd_obj;
Greg Clayton238c0a12010-09-18 01:14:36 +0000101 m_interpreter.CrossRegisterCommand (name, GetCommandName());
Chris Lattner24943d22010-06-08 16:52:24 +0000102 }
103 else
104 success = false;
105
106 return success;
107}
108
109bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000110CommandObjectMultiword::Execute(const char *args_string, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000111{
Jim Inghamda26bd22012-06-08 21:56:10 +0000112 Args args (args_string);
Chris Lattner24943d22010-06-08 16:52:24 +0000113 const size_t argc = args.GetArgumentCount();
114 if (argc == 0)
115 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000116 GenerateHelpText (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 Clayton238c0a12010-09-18 01:14:36 +0000126 GenerateHelpText (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
Jim Inghamda26bd22012-06-08 21:56:10 +0000139 sub_cmd_obj->Execute (args_string, 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 Clayton238c0a12010-09-18 01:14:36 +0000182CommandObjectMultiword::GenerateHelpText (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
Jim Ingham2e8cb8a2011-02-19 02:53:09 +0000187 Stream &output_stream = result.GetOutputStream();
Chris Lattner24943d22010-06-08 16:52:24 +0000188 output_stream.PutCString ("The following subcommands are supported:\n\n");
189
190 CommandMap::iterator pos;
Greg Clayton238c0a12010-09-18 01:14:36 +0000191 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000192
Greg Clayton65124ea2010-08-26 22:05:43 +0000193 if (max_len)
194 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner24943d22010-06-08 16:52:24 +0000195
196 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
197 {
198 std::string indented_command (" ");
199 indented_command.append (pos->first);
Caroline Ticefb355112010-10-01 17:46:38 +0000200 if (pos->second->WantsRawCommandString ())
201 {
202 std::string help_text (pos->second->GetHelp());
203 help_text.append (" This command takes 'raw' input (no need to quote stuff).");
204 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
205 indented_command.c_str(),
206 "--",
207 help_text.c_str(),
208 max_len);
209 }
210 else
211 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
212 indented_command.c_str(),
213 "--",
214 pos->second->GetHelp(),
215 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000216 }
217
218 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
219
220 result.SetStatus (eReturnStatusSuccessFinishNoResult);
221}
222
223int
224CommandObjectMultiword::HandleCompletion
225(
226 Args &input,
227 int &cursor_index,
228 int &cursor_char_position,
229 int match_start_point,
230 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000231 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000232 StringList &matches
233)
234{
Jim Ingham802f8b02010-06-30 05:02:46 +0000235 // Any of the command matches will provide a complete word, otherwise the individual
236 // completers will override this.
237 word_complete = true;
238
Chris Lattner24943d22010-06-08 16:52:24 +0000239 if (cursor_index == 0)
240 {
Greg Clayton63094e02010-06-23 01:19:29 +0000241 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
242 input.GetArgumentAtIndex(0),
243 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000244
245 if (matches.GetSize() == 1
246 && matches.GetStringAtIndex(0) != NULL
247 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
248 {
249 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000250 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
251 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000252 if (cmd_obj != NULL)
253 {
254 matches.DeleteStringAtIndex (0);
255 input.Shift();
256 cursor_char_position = 0;
257 input.AppendArgument ("");
Greg Clayton238c0a12010-09-18 01:14:36 +0000258 return cmd_obj->HandleCompletion (input,
259 cursor_index,
Greg Clayton63094e02010-06-23 01:19:29 +0000260 cursor_char_position,
261 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000262 max_return_elements,
263 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000264 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000265 }
266 else
267 return matches.GetSize();
268 }
269 else
270 return matches.GetSize();
271 }
272 else
273 {
Greg Clayton63094e02010-06-23 01:19:29 +0000274 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
275 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000276 if (sub_command_object == NULL)
277 {
278 return matches.GetSize();
279 }
280 else
281 {
282 // Remove the one match that we got from calling GetSubcommandObject.
283 matches.DeleteStringAtIndex(0);
284 input.Shift();
285 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +0000286 return sub_command_object->HandleCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000287 cursor_index,
288 cursor_char_position,
289 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000290 max_return_elements,
291 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000292 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000293 }
294
295 }
296}
297
Jim Ingham767af882010-07-07 03:36:20 +0000298const char *
299CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
300{
Jim Ingham767af882010-07-07 03:36:20 +0000301 index++;
Greg Clayton578ddbb2010-07-20 22:54:09 +0000302 if (current_command_args.GetArgumentCount() <= index)
303 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000304 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
305 if (sub_command_object == NULL)
306 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000307 return sub_command_object->GetRepeatCommand(current_command_args, index);
308}
309