blob: 9530adf86682f59dd0aa2538cdb803ad9a5cefa3 [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);
Greg Clayton238c0a12010-09-18 01:14:36 +0000199 m_interpreter.OutputFormattedHelpText (result.GetOutputStream(),
200 indented_command.c_str(),
201 "--",
202 pos->second->GetHelp(),
203 max_len);
Chris Lattner24943d22010-06-08 16:52:24 +0000204 }
205
206 output_stream.PutCString ("\nFor more help on any particular subcommand, type 'help <command> <subcommand>'.\n");
207
208 result.SetStatus (eReturnStatusSuccessFinishNoResult);
209}
210
211int
212CommandObjectMultiword::HandleCompletion
213(
214 Args &input,
215 int &cursor_index,
216 int &cursor_char_position,
217 int match_start_point,
218 int max_return_elements,
Jim Ingham802f8b02010-06-30 05:02:46 +0000219 bool &word_complete,
Chris Lattner24943d22010-06-08 16:52:24 +0000220 StringList &matches
221)
222{
Jim Ingham802f8b02010-06-30 05:02:46 +0000223 // Any of the command matches will provide a complete word, otherwise the individual
224 // completers will override this.
225 word_complete = true;
226
Chris Lattner24943d22010-06-08 16:52:24 +0000227 if (cursor_index == 0)
228 {
Greg Clayton63094e02010-06-23 01:19:29 +0000229 CommandObject::AddNamesMatchingPartialString (m_subcommand_dict,
230 input.GetArgumentAtIndex(0),
231 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000232
233 if (matches.GetSize() == 1
234 && matches.GetStringAtIndex(0) != NULL
235 && strcmp (input.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0)
236 {
237 StringList temp_matches;
Greg Clayton63094e02010-06-23 01:19:29 +0000238 CommandObject *cmd_obj = GetSubcommandObject (input.GetArgumentAtIndex(0),
239 &temp_matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000240 if (cmd_obj != NULL)
241 {
242 matches.DeleteStringAtIndex (0);
243 input.Shift();
244 cursor_char_position = 0;
245 input.AppendArgument ("");
Greg Clayton238c0a12010-09-18 01:14:36 +0000246 return cmd_obj->HandleCompletion (input,
247 cursor_index,
Greg Clayton63094e02010-06-23 01:19:29 +0000248 cursor_char_position,
249 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000250 max_return_elements,
251 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000252 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000253 }
254 else
255 return matches.GetSize();
256 }
257 else
258 return matches.GetSize();
259 }
260 else
261 {
Greg Clayton63094e02010-06-23 01:19:29 +0000262 CommandObject *sub_command_object = GetSubcommandObject (input.GetArgumentAtIndex(0),
263 &matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000264 if (sub_command_object == NULL)
265 {
266 return matches.GetSize();
267 }
268 else
269 {
270 // Remove the one match that we got from calling GetSubcommandObject.
271 matches.DeleteStringAtIndex(0);
272 input.Shift();
273 cursor_index--;
Greg Clayton238c0a12010-09-18 01:14:36 +0000274 return sub_command_object->HandleCompletion (input,
Greg Clayton63094e02010-06-23 01:19:29 +0000275 cursor_index,
276 cursor_char_position,
277 match_start_point,
Jim Ingham802f8b02010-06-30 05:02:46 +0000278 max_return_elements,
279 word_complete,
Greg Clayton63094e02010-06-23 01:19:29 +0000280 matches);
Chris Lattner24943d22010-06-08 16:52:24 +0000281 }
282
283 }
284}
285
Jim Ingham767af882010-07-07 03:36:20 +0000286const char *
287CommandObjectMultiword::GetRepeatCommand (Args &current_command_args, uint32_t index)
288{
Jim Ingham767af882010-07-07 03:36:20 +0000289 index++;
Greg Clayton578ddbb2010-07-20 22:54:09 +0000290 if (current_command_args.GetArgumentCount() <= index)
291 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000292 CommandObject *sub_command_object = GetSubcommandObject (current_command_args.GetArgumentAtIndex(index));
293 if (sub_command_object == NULL)
294 return NULL;
Jim Ingham767af882010-07-07 03:36:20 +0000295 return sub_command_object->GetRepeatCommand(current_command_args, index);
296}
297