blob: aafd0f8147d92c312a48f1beafbfc2581bfd4fc5 [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);
52 if (pos != m_subcommand_dict.end())
53 return_cmd_sp = pos->second;
54 else
55 {
56
57 StringList local_matches;
58 if (matches == NULL)
59 matches = &local_matches;
60 int num_matches = CommandObject::AddNamesMatchingPartialString (m_subcommand_dict, sub_cmd, *matches);
61
62 if (num_matches == 1)
63 {
64 // Cleaner, but slightly less efficient would be to call back into this function, since I now
65 // know I have an exact match...
66
67 sub_cmd = matches->GetStringAtIndex(0);
68 pos = m_subcommand_dict.find(sub_cmd);
69 if (pos != m_subcommand_dict.end())
70 return_cmd_sp = pos->second;
71 }
72 }
73 }
74 return return_cmd_sp;
75}
76
77CommandObject *
78CommandObjectMultiword::GetSubcommandObject (const char *sub_cmd, StringList *matches)
79{
80 return GetSubcommandSP(sub_cmd, matches).get();
81}
82
83bool
Greg Clayton63094e02010-06-23 01:19:29 +000084CommandObjectMultiword::LoadSubCommand
85(
Greg Clayton63094e02010-06-23 01:19:29 +000086 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 Clayton238c0a12010-09-18 01:14:36 +000097 m_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(
108 Args& args,
Chris Lattner24943d22010-06-08 16:52:24 +0000109 CommandReturnObject &result
110)
111{
112 const size_t argc = args.GetArgumentCount();
113 if (argc == 0)
114 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000115 GenerateHelpText (result);
Chris Lattner24943d22010-06-08 16:52:24 +0000116 }
117 else
118 {
119 const char *sub_command = args.GetArgumentAtIndex (0);
120
121 if (sub_command)
122 {
123 if (::strcasecmp (sub_command, "help") == 0)
124 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000125 GenerateHelpText (result);
Chris Lattner24943d22010-06-08 16:52:24 +0000126 }
127 else if (!m_subcommand_dict.empty())
128 {
129 StringList matches;
130 CommandObject *sub_cmd_obj = GetSubcommandObject(sub_command, &matches);
131 if (sub_cmd_obj != NULL)
132 {
133 // Now call CommandObject::Execute to process and options in 'rest_of_line'. From there
134 // the command-specific version of Execute will be called, with the processed arguments.
135
136 args.Shift();
137
Greg Clayton238c0a12010-09-18 01:14:36 +0000138 sub_cmd_obj->ExecuteWithOptions (args, result);
Chris Lattner24943d22010-06-08 16:52:24 +0000139 }
140 else
141 {
142 std::string error_msg;
143 int num_subcmd_matches = matches.GetSize();
144 if (num_subcmd_matches > 0)
145 error_msg.assign ("ambiguous command ");
146 else
147 error_msg.assign ("invalid command ");
148
149 error_msg.append ("'");
150 error_msg.append (GetCommandName());
151 error_msg.append (" ");
152 error_msg.append (sub_command);
153 error_msg.append ("'");
154
155 if (num_subcmd_matches > 0)
156 {
157 error_msg.append (" Possible completions:");
158 for (int i = 0; i < num_subcmd_matches; i++)
159 {
160 error_msg.append ("\n\t");
161 error_msg.append (matches.GetStringAtIndex (i));
162 }
163 }
164 error_msg.append ("\n");
165 result.AppendRawError (error_msg.c_str(), error_msg.size());
166 result.SetStatus (eReturnStatusFailed);
167 }
168 }
169 else
170 {
171 result.AppendErrorWithFormat ("'%s' does not have any subcommands.\n", GetCommandName());
172 result.SetStatus (eReturnStatusFailed);
173 }
174 }
175 }
176
177 return result.Succeeded();
178}
179
180void
Greg Clayton238c0a12010-09-18 01:14:36 +0000181CommandObjectMultiword::GenerateHelpText (CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000182{
183 // First time through here, generate the help text for the object and
184 // push it to the return result object as well
185
186 StreamString &output_stream = result.GetOutputStream();
187 output_stream.PutCString ("The following subcommands are supported:\n\n");
188
189 CommandMap::iterator pos;
Greg Clayton238c0a12010-09-18 01:14:36 +0000190 uint32_t max_len = m_interpreter.FindLongestCommandWord (m_subcommand_dict);
Chris Lattner24943d22010-06-08 16:52:24 +0000191
Greg Clayton65124ea2010-08-26 22:05:43 +0000192 if (max_len)
193 max_len += 4; // Indent the output by 4 spaces.
Chris Lattner24943d22010-06-08 16:52:24 +0000194
195 for (pos = m_subcommand_dict.begin(); pos != m_subcommand_dict.end(); ++pos)
196 {
197 std::string indented_command (" ");
198 indented_command.append (pos->first);
Caroline Ticefb355112010-10-01 17:46:38 +0000199 if (pos->second->WantsRawCommandString ())
200 {
201 std::string help_text (pos->second->GetHelp());
202 help_text.append (" This command takes 'raw' input (no need to quote stuff).");
203 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
204 indented_command.c_str(),
205 "--",
206 help_text.c_str(),
207 max_len);
208 }
209 else
210 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
211 indented_command.c_str(),
212 "--",
213 pos->second->GetHelp(),
214 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000215 }
216
217 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
218
219 result.SetStatus (eReturnStatusSuccessFinishNoResult);
220}
221
222int
223CommandObjectMultiword::HandleCompletion
224(
225 Args &input,
226 int &cursor_index,
227 int &cursor_char_position,
228 int match_start_point,
229 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000230 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000231 StringList &matches
232)
233{
Jim Ingham802f8b02010-06-30 05:02:46 +0000234 // Any of the command matches will provide a complete word, otherwise the individual
235 // completers will override this.
236 word_complete = true;
237
Chris Lattner24943d22010-06-08 16:52:24 +0000238 if (cursor_index == 0)
239 {
Greg Clayton63094e02010-06-23 01:19:29 +0000240 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
241 input.GetArgumentAtIndex(0),
242 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000243
244 if (matches.GetSize() == 1
245 && matches.GetStringAtIndex(0) != NULL
246 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
247 {
248 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000249 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
250 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000251 if (cmd_obj != NULL)
252 {
253 matches.DeleteStringAtIndex (0);
254 input.Shift();
255 cursor_char_position = 0;
256 input.AppendArgument ("");
Greg Clayton238c0a12010-09-18 01:14:36 +0000257 return cmd_obj->HandleCompletion (input,
258 cursor_index,
Greg Clayton63094e02010-06-23 01:19:29 +0000259 cursor_char_position,
260 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000261 max_return_elements,
262 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000263 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000264 }
265 else
266 return matches.GetSize();
267 }
268 else
269 return matches.GetSize();
270 }
271 else
272 {
Greg Clayton63094e02010-06-23 01:19:29 +0000273 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
274 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000275 if (sub_command_object == NULL)
276 {
277 return matches.GetSize();
278 }
279 else
280 {
281 // Remove the one match that we got from calling GetSubcommandObject.
282 matches.DeleteStringAtIndex(0);
283 input.Shift();
284 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +0000285 return sub_command_object->HandleCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000286 cursor_index,
287 cursor_char_position,
288 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000289 max_return_elements,
290 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000291 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000292 }
293
294 }
295}
296
Jim Ingham767af882010-07-07 03:36:20 +0000297const char *
298CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
299{
Jim Ingham767af882010-07-07 03:36:20 +0000300 index++;
Greg Clayton578ddbb2010-07-20 22:54:09 +0000301 if (current_command_args.GetArgumentCount() <= index)
302 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000303 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
304 if (sub_command_object == NULL)
305 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000306 return sub_command_object->GetRepeatCommand(current_command_args, index);
307}
308