blob: 50d3fff50a23f20cc57ed574e3f8728cd65da777 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Args.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
Daniel Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012// C Includes
Eli Friedman5661f922010-06-09 10:59:23 +000013#include <cstdlib>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000014// C++ Includes
15// Other libraries and framework includes
16// Project includes
Jim Ingham40af72e2010-06-15 19:49:27 +000017#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/StreamFile.h"
20#include "lldb/Core/StreamString.h"
Enrico Granata5548cb52013-01-28 23:47:25 +000021#include "lldb/DataFormatters/FormatManager.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000022#include "lldb/Host/StringConvert.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000023#include "lldb/Interpreter/Options.h"
Zachary Turnerd37221d2014-07-09 16:31:49 +000024#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonb9d5df52012-12-06 22:49:16 +000026#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000027#include "lldb/Target/StackFrame.h"
Greg Claytonb9d5df52012-12-06 22:49:16 +000028#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030using namespace lldb;
31using namespace lldb_private;
32
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033//----------------------------------------------------------------------
34// Args constructor
35//----------------------------------------------------------------------
36Args::Args (const char *command) :
37 m_args(),
Greg Clayton8b82f082011-04-12 05:54:46 +000038 m_argv(),
39 m_args_quote_char()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040{
Greg Clayton6ad07dd2010-12-19 03:41:24 +000041 if (command)
42 SetCommandString (command);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043}
44
45
46Args::Args (const char *command, size_t len) :
47 m_args(),
Greg Clayton8b82f082011-04-12 05:54:46 +000048 m_argv(),
49 m_args_quote_char()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000050{
Greg Clayton6ad07dd2010-12-19 03:41:24 +000051 if (command && len)
52 SetCommandString (command, len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053}
54
Chris Lattner30fdc8d2010-06-08 16:52:24 +000055//----------------------------------------------------------------------
Greg Clayton8b82f082011-04-12 05:54:46 +000056// We have to be very careful on the copy constructor of this class
57// to make sure we copy all of the string values, but we can't copy the
58// rhs.m_argv into m_argv since it will point to the "const char *" c
59// strings in rhs.m_args. We need to copy the string list and update our
60// own m_argv appropriately.
61//----------------------------------------------------------------------
62Args::Args (const Args &rhs) :
63 m_args (rhs.m_args),
64 m_argv (),
65 m_args_quote_char(rhs.m_args_quote_char)
66{
67 UpdateArgvFromArgs();
68}
69
70//----------------------------------------------------------------------
71// We have to be very careful on the copy constructor of this class
72// to make sure we copy all of the string values, but we can't copy the
73// rhs.m_argv into m_argv since it will point to the "const char *" c
74// strings in rhs.m_args. We need to copy the string list and update our
75// own m_argv appropriately.
76//----------------------------------------------------------------------
77const Args &
78Args::operator= (const Args &rhs)
79{
80 // Make sure we aren't assigning to self
81 if (this != &rhs)
82 {
83 m_args = rhs.m_args;
84 m_args_quote_char = rhs.m_args_quote_char;
85 UpdateArgvFromArgs();
86 }
87 return *this;
88}
89
90//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000091// Destructor
92//----------------------------------------------------------------------
93Args::~Args ()
94{
95}
96
97void
98Args::Dump (Stream *s)
99{
Greg Claytonc7bece562013-01-25 18:06:21 +0000100 const size_t argc = m_argv.size();
101 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000102 {
103 s->Indent();
104 const char *arg_cstr = m_argv[i];
105 if (arg_cstr)
Greg Claytonc7bece562013-01-25 18:06:21 +0000106 s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000107 else
Greg Claytonc7bece562013-01-25 18:06:21 +0000108 s->Printf("argv[%zi]=NULL\n", i);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 }
110 s->EOL();
111}
112
113bool
Greg Claytonda91b172012-04-25 22:30:32 +0000114Args::GetCommandString (std::string &command) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000115{
116 command.clear();
Greg Claytonc7bece562013-01-25 18:06:21 +0000117 const size_t argc = GetArgumentCount();
118 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119 {
120 if (i > 0)
121 command += ' ';
122 command += m_argv[i];
123 }
124 return argc > 0;
125}
126
Caroline Tice2d5289d2010-12-10 00:26:54 +0000127bool
Greg Claytonda91b172012-04-25 22:30:32 +0000128Args::GetQuotedCommandString (std::string &command) const
Caroline Tice2d5289d2010-12-10 00:26:54 +0000129{
130 command.clear ();
Greg Claytonc7bece562013-01-25 18:06:21 +0000131 const size_t argc = GetArgumentCount();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000132 for (size_t i = 0; i < argc; ++i)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000133 {
134 if (i > 0)
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000135 command.append (1, ' ');
136 char quote_char = GetArgumentQuoteCharAtIndex(i);
137 if (quote_char)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000138 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000139 command.append (1, quote_char);
140 command.append (m_argv[i]);
141 command.append (1, quote_char);
Caroline Tice2d5289d2010-12-10 00:26:54 +0000142 }
143 else
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000144 command.append (m_argv[i]);
Caroline Tice2d5289d2010-12-10 00:26:54 +0000145 }
146 return argc > 0;
147}
148
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149void
150Args::SetCommandString (const char *command, size_t len)
151{
152 // Use std::string to make sure we get a NULL terminated string we can use
153 // as "command" could point to a string within a large string....
154 std::string null_terminated_command(command, len);
155 SetCommandString(null_terminated_command.c_str());
156}
157
158void
159Args::SetCommandString (const char *command)
160{
161 m_args.clear();
162 m_argv.clear();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000163 m_args_quote_char.clear();
164
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 if (command && command[0])
166 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000167 static const char *k_space_separators = " \t";
Zachary Turner2d53c312015-01-20 17:53:36 +0000168 static const char *k_escapable_characters = " \t\\'\"";
Ed Masted78c9572014-04-20 00:31:37 +0000169 const char *arg_end = nullptr;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000170 const char *arg_pos;
171 for (arg_pos = command;
172 arg_pos && arg_pos[0];
173 arg_pos = arg_end)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000175 // Skip any leading space separators
176 const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
177
178 // If there were only space separators to the end of the line, then
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000179 // we're done.
180 if (*arg_start == '\0')
181 break;
182
Greg Clayton710dd5a2011-01-08 20:28:42 +0000183 // Arguments can be split into multiple discontiguous pieces,
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000184 // for example:
185 // "Hello ""World"
186 // this would result in a single argument "Hello World" (without/
187 // the quotes) since the quotes would be removed and there is
188 // not space between the strings. So we need to keep track of the
189 // current start of each argument piece in "arg_piece_start"
190 const char *arg_piece_start = arg_start;
191 arg_pos = arg_piece_start;
192
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193 std::string arg;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000194 // Since we can have multiple quotes that form a single command
195 // in a command like: "Hello "world'!' (which will make a single
196 // argument "Hello world!") we remember the first quote character
197 // we encounter and use that for the quote character.
198 char first_quote_char = '\0';
199 char quote_char = '\0';
200 bool arg_complete = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000201
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000202 do
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000203 {
Zachary Turner2d53c312015-01-20 17:53:36 +0000204 arg_end = ::strcspn (arg_pos, k_escapable_characters) + arg_pos;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000205
206 switch (arg_end[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000208 default:
209 assert (!"Unhandled case statement, we must handle this...");
210 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000212 case '\0':
213 // End of C string
214 if (arg_piece_start && arg_piece_start[0])
215 arg.append (arg_piece_start);
216 arg_complete = true;
217 break;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000218 case '\\':
219 // Backslash character
220 switch (arg_end[1])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000221 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000222 case '\0':
223 arg.append (arg_piece_start);
Greg Clayton0c943132012-03-15 17:10:48 +0000224 ++arg_end;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000225 arg_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000227
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000228 default:
Zachary Turner2d53c312015-01-20 17:53:36 +0000229 // Only consider this two-character sequence an escape sequence if we're unquoted and
230 // the character after the backslash is a whitelisted escapable character. Otherwise
231 // leave the character sequence untouched.
232 if (quote_char == '\0' && (nullptr != strchr(k_escapable_characters, arg_end[1])))
Jim Inghama39fb7a2012-07-21 00:12:58 +0000233 {
234 arg.append (arg_piece_start, arg_end - arg_piece_start);
Zachary Turner2d53c312015-01-20 17:53:36 +0000235 arg.append (arg_end + 1, 1);
236 arg_pos = arg_end + 2;
237 arg_piece_start = arg_pos;
Jim Inghama39fb7a2012-07-21 00:12:58 +0000238 }
239 else
240 arg_pos = arg_end + 2;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000241 break;
242 }
243 break;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000244 case '"':
245 case '\'':
246 case '`':
247 // Quote characters
248 if (quote_char)
249 {
250 // We found a quote character while inside a quoted
251 // character argument. If it matches our current quote
252 // character, this ends the effect of the quotes. If it
253 // doesn't we ignore it.
254 if (quote_char == arg_end[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000255 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000256 arg.append (arg_piece_start, arg_end - arg_piece_start);
257 // Clear the quote character and let parsing
258 // continue (we need to watch for things like:
259 // "Hello ""World"
260 // "Hello "World
261 // "Hello "'World'
262 // All of which will result in a single argument "Hello World"
263 quote_char = '\0'; // Note that we are no longer inside quotes
264 arg_pos = arg_end + 1; // Skip the quote character
265 arg_piece_start = arg_pos; // Note we are starting from later in the string
266 }
267 else
268 {
269 // different quote, skip it and keep going
270 arg_pos = arg_end + 1;
271 }
272 }
273 else
274 {
275 // We found the start of a quote scope.
Greg Clayton710dd5a2011-01-08 20:28:42 +0000276 // Make sure there isn't a string that precedes
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000277 // the start of a quote scope like:
278 // Hello" World"
279 // If so, then add the "Hello" to the arg
280 if (arg_end > arg_piece_start)
281 arg.append (arg_piece_start, arg_end - arg_piece_start);
282
283 // Enter into a quote scope
284 quote_char = arg_end[0];
285
286 if (first_quote_char == '\0')
287 first_quote_char = quote_char;
288
289 arg_pos = arg_end;
Johnny Chena28b89c2012-01-19 19:22:41 +0000290 ++arg_pos; // Skip the quote character
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000291 arg_piece_start = arg_pos; // Note we are starting from later in the string
292
293 // Skip till the next quote character
294 const char *end_quote = ::strchr (arg_piece_start, quote_char);
295 while (end_quote && end_quote[-1] == '\\')
296 {
297 // Don't skip the quote character if it is
298 // preceded by a '\' character
299 end_quote = ::strchr (end_quote + 1, quote_char);
300 }
301
302 if (end_quote)
303 {
304 if (end_quote > arg_piece_start)
Johnny Chena28b89c2012-01-19 19:22:41 +0000305 arg.append (arg_piece_start, end_quote - arg_piece_start);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000306
307 // If the next character is a space or the end of
308 // string, this argument is complete...
309 if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
310 {
311 arg_complete = true;
312 arg_end = end_quote + 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000313 }
314 else
315 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000316 arg_pos = end_quote + 1;
317 arg_piece_start = arg_pos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000318 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000319 quote_char = '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000320 }
Greg Clayton0c943132012-03-15 17:10:48 +0000321 else
322 {
323 // Consume the rest of the string as there was no terminating quote
324 arg.append(arg_piece_start);
325 arg_end = arg_piece_start + strlen(arg_piece_start);
326 arg_complete = true;
327 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000329 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000330
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000331 case ' ':
332 case '\t':
333 if (quote_char)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000335 // We are currently processing a quoted character and found
336 // a space character, skip any spaces and keep trying to find
337 // the end of the argument.
338 arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000339 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000340 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000341 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000342 // We are not inside any quotes, we just found a space after an
343 // argument
344 if (arg_end > arg_piece_start)
345 arg.append (arg_piece_start, arg_end - arg_piece_start);
346 arg_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000347 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000348 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000349 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000350 } while (!arg_complete);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000351
352 m_args.push_back(arg);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000353 m_args_quote_char.push_back (first_quote_char);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000354 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000355 UpdateArgvFromArgs();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000356 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357}
358
359void
360Args::UpdateArgsAfterOptionParsing()
361{
362 // Now m_argv might be out of date with m_args, so we need to fix that
363 arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
364 arg_sstr_collection::iterator args_pos;
365 arg_quote_char_collection::iterator quotes_pos;
366
367 for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
368 argv_pos != argv_end && args_pos != m_args.end();
369 ++argv_pos)
370 {
371 const char *argv_cstr = *argv_pos;
Ed Masted78c9572014-04-20 00:31:37 +0000372 if (argv_cstr == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373 break;
374
375 while (args_pos != m_args.end())
376 {
377 const char *args_cstr = args_pos->c_str();
378 if (args_cstr == argv_cstr)
379 {
380 // We found the argument that matches the C string in the
381 // vector, so we can now look for the next one
382 ++args_pos;
383 ++quotes_pos;
384 break;
385 }
386 else
387 {
388 quotes_pos = m_args_quote_char.erase (quotes_pos);
389 args_pos = m_args.erase (args_pos);
390 }
391 }
392 }
393
394 if (args_pos != m_args.end())
395 m_args.erase (args_pos, m_args.end());
396
397 if (quotes_pos != m_args_quote_char.end())
398 m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
399}
400
401void
402Args::UpdateArgvFromArgs()
403{
404 m_argv.clear();
405 arg_sstr_collection::const_iterator pos, end = m_args.end();
406 for (pos = m_args.begin(); pos != end; ++pos)
407 m_argv.push_back(pos->c_str());
Ed Masted78c9572014-04-20 00:31:37 +0000408 m_argv.push_back(nullptr);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000409 // Make sure we have enough arg quote chars in the array
410 if (m_args_quote_char.size() < m_args.size())
411 m_args_quote_char.resize (m_argv.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412}
413
414size_t
415Args::GetArgumentCount() const
416{
417 if (m_argv.empty())
418 return 0;
419 return m_argv.size() - 1;
420}
421
422const char *
423Args::GetArgumentAtIndex (size_t idx) const
424{
425 if (idx < m_argv.size())
426 return m_argv[idx];
Ed Masted78c9572014-04-20 00:31:37 +0000427 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428}
429
430char
431Args::GetArgumentQuoteCharAtIndex (size_t idx) const
432{
433 if (idx < m_args_quote_char.size())
434 return m_args_quote_char[idx];
435 return '\0';
436}
437
438char **
439Args::GetArgumentVector()
440{
441 if (!m_argv.empty())
442 return (char **)&m_argv[0];
Ed Masted78c9572014-04-20 00:31:37 +0000443 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000444}
445
446const char **
447Args::GetConstArgumentVector() const
448{
449 if (!m_argv.empty())
450 return (const char **)&m_argv[0];
Ed Masted78c9572014-04-20 00:31:37 +0000451 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000452}
453
454void
455Args::Shift ()
456{
457 // Don't pop the last NULL terminator from the argv array
458 if (m_argv.size() > 1)
459 {
460 m_argv.erase(m_argv.begin());
461 m_args.pop_front();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000462 if (!m_args_quote_char.empty())
463 m_args_quote_char.erase(m_args_quote_char.begin());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000464 }
465}
466
467const char *
468Args::Unshift (const char *arg_cstr, char quote_char)
469{
470 m_args.push_front(arg_cstr);
471 m_argv.insert(m_argv.begin(), m_args.front().c_str());
472 m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
473 return GetArgumentAtIndex (0);
474}
475
476void
477Args::AppendArguments (const Args &rhs)
478{
479 const size_t rhs_argc = rhs.GetArgumentCount();
480 for (size_t i=0; i<rhs_argc; ++i)
481 AppendArgument(rhs.GetArgumentAtIndex(i));
482}
483
Greg Clayton982c9762011-11-03 21:22:33 +0000484void
485Args::AppendArguments (const char **argv)
486{
487 if (argv)
488 {
489 for (uint32_t i=0; argv[i]; ++i)
490 AppendArgument(argv[i]);
491 }
492}
493
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000494const char *
495Args::AppendArgument (const char *arg_cstr, char quote_char)
496{
497 return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
498}
499
500const char *
501Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
502{
503 // Since we are using a std::list to hold onto the copied C string and
504 // we don't have direct access to the elements, we have to iterate to
505 // find the value.
506 arg_sstr_collection::iterator pos, end = m_args.end();
507 size_t i = idx;
508 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
509 --i;
510
511 pos = m_args.insert(pos, arg_cstr);
512
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000513 if (idx >= m_args_quote_char.size())
514 {
515 m_args_quote_char.resize(idx + 1);
516 m_args_quote_char[idx] = quote_char;
517 }
518 else
519 m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000520
521 UpdateArgvFromArgs();
522 return GetArgumentAtIndex(idx);
523}
524
525const char *
526Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
527{
528 // Since we are using a std::list to hold onto the copied C string and
529 // we don't have direct access to the elements, we have to iterate to
530 // find the value.
531 arg_sstr_collection::iterator pos, end = m_args.end();
532 size_t i = idx;
533 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
534 --i;
535
536 if (pos != end)
537 {
538 pos->assign(arg_cstr);
539 assert(idx < m_argv.size() - 1);
540 m_argv[idx] = pos->c_str();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000541 if (idx >= m_args_quote_char.size())
542 m_args_quote_char.resize(idx + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000543 m_args_quote_char[idx] = quote_char;
544 return GetArgumentAtIndex(idx);
545 }
Ed Masted78c9572014-04-20 00:31:37 +0000546 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000547}
548
549void
550Args::DeleteArgumentAtIndex (size_t idx)
551{
552 // Since we are using a std::list to hold onto the copied C string and
553 // we don't have direct access to the elements, we have to iterate to
554 // find the value.
555 arg_sstr_collection::iterator pos, end = m_args.end();
556 size_t i = idx;
557 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
558 --i;
559
560 if (pos != end)
561 {
562 m_args.erase (pos);
563 assert(idx < m_argv.size() - 1);
564 m_argv.erase(m_argv.begin() + idx);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000565 if (idx < m_args_quote_char.size())
566 m_args_quote_char.erase(m_args_quote_char.begin() + idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000567 }
568}
569
570void
Greg Claytonc7bece562013-01-25 18:06:21 +0000571Args::SetArguments (size_t argc, const char **argv)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000572{
573 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
574 // no need to clear it here.
575 m_args.clear();
576 m_args_quote_char.clear();
577
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578 // First copy each string
Greg Clayton982c9762011-11-03 21:22:33 +0000579 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000580 {
581 m_args.push_back (argv[i]);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000582 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000583 m_args_quote_char.push_back (argv[i][0]);
584 else
585 m_args_quote_char.push_back ('\0');
586 }
587
588 UpdateArgvFromArgs();
589}
590
Greg Clayton982c9762011-11-03 21:22:33 +0000591void
592Args::SetArguments (const char **argv)
593{
594 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
595 // no need to clear it here.
596 m_args.clear();
597 m_args_quote_char.clear();
598
599 if (argv)
600 {
601 // First copy each string
602 for (size_t i=0; argv[i]; ++i)
603 {
604 m_args.push_back (argv[i]);
605 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
606 m_args_quote_char.push_back (argv[i][0]);
607 else
608 m_args_quote_char.push_back ('\0');
609 }
610 }
611
612 UpdateArgvFromArgs();
613}
614
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000615
616Error
617Args::ParseOptions (Options &options)
618{
619 StreamString sstr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000620 Error error;
Virgile Belloe2607b52013-09-05 16:42:23 +0000621 Option *long_options = options.GetLongOptions();
Ed Masted78c9572014-04-20 00:31:37 +0000622 if (long_options == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000623 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000624 error.SetErrorStringWithFormat("invalid long options");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000625 return error;
626 }
627
Zachary Turnerd37221d2014-07-09 16:31:49 +0000628 for (int i=0; long_options[i].definition != nullptr; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000629 {
Ed Masted78c9572014-04-20 00:31:37 +0000630 if (long_options[i].flag == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631 {
Daniel Malea90b0c842012-12-05 20:24:57 +0000632 if (isprint8(long_options[i].val))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000633 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000634 sstr << (char)long_options[i].val;
Zachary Turnerd37221d2014-07-09 16:31:49 +0000635 switch (long_options[i].definition->option_has_arg)
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000636 {
637 default:
Virgile Belloe2607b52013-09-05 16:42:23 +0000638 case OptionParser::eNoArgument: break;
639 case OptionParser::eRequiredArgument: sstr << ':'; break;
640 case OptionParser::eOptionalArgument: sstr << "::"; break;
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000641 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642 }
643 }
644 }
Virgile Belloe2607b52013-09-05 16:42:23 +0000645 OptionParser::Prepare();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 int val;
647 while (1)
648 {
649 int long_options_index = -1;
Virgile Belloe2607b52013-09-05 16:42:23 +0000650 val = OptionParser::Parse(GetArgumentCount(),
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000651 GetArgumentVector(),
652 sstr.GetData(),
653 long_options,
654 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 if (val == -1)
656 break;
657
658 // Did we get an error?
659 if (val == '?')
660 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000661 error.SetErrorStringWithFormat("unknown or ambiguous option");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000662 break;
663 }
664 // The option auto-set itself
665 if (val == 0)
666 continue;
667
668 ((Options *) &options)->OptionSeen (val);
669
670 // Lookup the long option index
671 if (long_options_index == -1)
672 {
673 for (int i=0;
Zachary Turnerd37221d2014-07-09 16:31:49 +0000674 long_options[i].definition || long_options[i].flag || long_options[i].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000675 ++i)
676 {
677 if (long_options[i].val == val)
678 {
679 long_options_index = i;
680 break;
681 }
682 }
683 }
684 // Call the callback with the option
Jason Molenda320e7b32014-10-16 01:26:51 +0000685 if (long_options_index >= 0 && long_options[long_options_index].definition)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000686 {
Zachary Turnerd37221d2014-07-09 16:31:49 +0000687 const OptionDefinition *def = long_options[long_options_index].definition;
688 CommandInterpreter &interpreter = options.GetInterpreter();
689 OptionValidator *validator = def->validator;
690 if (validator && !validator->IsValid(*interpreter.GetPlatform(true), interpreter.GetExecutionContext()))
691 {
692 error.SetErrorStringWithFormat("Option \"%s\" invalid. %s", def->long_option, def->validator->LongConditionString());
693 }
694 else
695 {
696 error = options.SetOptionValue(long_options_index,
Todd Fiala2c77a422014-10-10 01:11:39 +0000697 (def->option_has_arg == OptionParser::eNoArgument) ? nullptr : OptionParser::GetOptionArgument());
Zachary Turnerd37221d2014-07-09 16:31:49 +0000698 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000699 }
700 else
701 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000702 error.SetErrorStringWithFormat("invalid option with value '%i'", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000703 }
704 if (error.Fail())
705 break;
706 }
707
708 // Update our ARGV now that get options has consumed all the options
Virgile Belloe2607b52013-09-05 16:42:23 +0000709 m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000710 UpdateArgsAfterOptionParsing ();
711 return error;
712}
713
714void
715Args::Clear ()
716{
717 m_args.clear ();
718 m_argv.clear ();
719 m_args_quote_char.clear();
720}
721
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000722lldb::addr_t
Greg Claytonb9d5df52012-12-06 22:49:16 +0000723Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000724{
Greg Claytonb9d5df52012-12-06 22:49:16 +0000725 bool error_set = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000726 if (s && s[0])
727 {
Ed Masted78c9572014-04-20 00:31:37 +0000728 char *end = nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000729 lldb::addr_t addr = ::strtoull (s, &end, 0);
730 if (*end == '\0')
731 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000732 if (error_ptr)
733 error_ptr->Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000734 return addr; // All characters were used, return the result
735 }
736 // Try base 16 with no prefix...
737 addr = ::strtoull (s, &end, 16);
738 if (*end == '\0')
739 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000740 if (error_ptr)
741 error_ptr->Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000742 return addr; // All characters were used, return the result
743 }
Greg Claytonb9d5df52012-12-06 22:49:16 +0000744
745 if (exe_ctx)
746 {
747 Target *target = exe_ctx->GetTargetPtr();
748 if (target)
749 {
750 lldb::ValueObjectSP valobj_sp;
751 EvaluateExpressionOptions options;
752 options.SetCoerceToId(false);
753 options.SetUnwindOnError(true);
754 options.SetKeepInMemory(false);
Jim Ingham6fbc48b2013-11-07 00:11:47 +0000755 options.SetTryAllThreads(true);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000756
Jim Ingham1624a2d2014-05-05 02:26:40 +0000757 ExpressionResults expr_result = target->EvaluateExpression(s,
Enrico Granataca0e5ad2014-10-09 23:09:40 +0000758 exe_ctx->GetFramePtr(),
759 valobj_sp,
760 options);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000761
762 bool success = false;
Jim Ingham8646d3c2014-05-05 02:47:44 +0000763 if (expr_result == eExpressionCompleted)
Greg Claytonb9d5df52012-12-06 22:49:16 +0000764 {
Enrico Granataca0e5ad2014-10-09 23:09:40 +0000765 if (valobj_sp)
766 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(valobj_sp->GetDynamicValueType(), true);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000767 // Get the address to watch.
Enrico Granataca0e5ad2014-10-09 23:09:40 +0000768 if (valobj_sp)
769 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000770 if (success)
771 {
772 if (error_ptr)
773 error_ptr->Clear();
774 return addr;
775 }
776 else
777 {
778 if (error_ptr)
779 {
780 error_set = true;
781 error_ptr->SetErrorStringWithFormat("address expression \"%s\" resulted in a value whose type can't be converted to an address: %s", s, valobj_sp->GetTypeName().GetCString());
782 }
783 }
784
785 }
786 else
787 {
788 // Since the compiler can't handle things like "main + 12" we should
789 // try to do this for now. The compliler doesn't like adding offsets
790 // to function pointer types.
Greg Claytonbc43cab2013-04-03 21:37:16 +0000791 static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
792 RegularExpression::Match regex_match(3);
793 if (g_symbol_plus_offset_regex.Execute(s, &regex_match))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000794 {
795 uint64_t offset = 0;
796 bool add = true;
797 std::string name;
798 std::string str;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000799 if (regex_match.GetMatchAtIndex(s, 1, name))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000800 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000801 if (regex_match.GetMatchAtIndex(s, 2, str))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000802 {
803 add = str[0] == '+';
804
Greg Claytonbc43cab2013-04-03 21:37:16 +0000805 if (regex_match.GetMatchAtIndex(s, 3, str))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000806 {
Vince Harron5275aaa2015-01-15 20:08:35 +0000807 offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success);
Greg Claytonb9d5df52012-12-06 22:49:16 +0000808
809 if (success)
810 {
811 Error error;
812 addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
813 if (addr != LLDB_INVALID_ADDRESS)
814 {
815 if (add)
816 return addr + offset;
817 else
818 return addr - offset;
819 }
820 }
821 }
822 }
823 }
824 }
825
826 if (error_ptr)
827 {
828 error_set = true;
829 error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
830 }
831 }
832 }
833 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000834 }
Greg Claytonb9d5df52012-12-06 22:49:16 +0000835 if (error_ptr)
836 {
837 if (!error_set)
838 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
839 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000840 return fail_value;
841}
842
Greg Clayton30820f02013-03-05 23:52:49 +0000843const char *
844Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
845{
846 static const char *k_white_space = " \t\v";
847 if (!s.empty())
848 {
849 if (leading)
850 {
851 size_t pos = s.find_first_not_of (k_white_space);
852 if (pos == std::string::npos)
853 s.clear();
854 else if (pos > 0)
855 s.erase(0, pos);
856 }
857
858 if (trailing)
859 {
860 size_t rpos = s.find_last_not_of(k_white_space);
861 if (rpos != std::string::npos && rpos + 1 < s.size())
862 s.erase(rpos + 1);
863 }
864 }
865 if (return_null_if_empty && s.empty())
Ed Masted78c9572014-04-20 00:31:37 +0000866 return nullptr;
Greg Clayton30820f02013-03-05 23:52:49 +0000867 return s.c_str();
868}
869
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000870bool
871Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
872{
Pavel Labathdf50f942015-02-16 13:13:39 +0000873 llvm::StringRef ref = llvm::StringRef(s).trim();
874 if (ref.equals_lower("false") ||
875 ref.equals_lower("off") ||
876 ref.equals_lower("no") ||
877 ref.equals_lower("0"))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000878 {
Pavel Labathdf50f942015-02-16 13:13:39 +0000879 if (success_ptr)
880 *success_ptr = true;
881 return false;
882 }
883 else
884 if (ref.equals_lower("true") ||
885 ref.equals_lower("on") ||
886 ref.equals_lower("yes") ||
887 ref.equals_lower("1"))
888 {
889 if (success_ptr) *success_ptr = true;
890 return true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000891 }
892 if (success_ptr) *success_ptr = false;
893 return fail_value;
894}
895
Zachary Turner3e7442b2015-01-12 20:44:02 +0000896char
897Args::StringToChar(const char *s, char fail_value, bool *success_ptr)
898{
899 bool success = false;
900 char result = fail_value;
901
902 if (s)
903 {
904 size_t length = strlen(s);
905 if (length == 1)
906 {
907 success = true;
908 result = s[0];
909 }
910 }
911 if (success_ptr)
912 *success_ptr = success;
913 return result;
914}
915
Greg Claytonded470d2011-03-19 01:12:21 +0000916const char *
917Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
918{
919 major = UINT32_MAX;
920 minor = UINT32_MAX;
921 update = UINT32_MAX;
922
923 if (s && s[0])
924 {
Ed Masted78c9572014-04-20 00:31:37 +0000925 char *pos = nullptr;
Greg Claytonc7bece562013-01-25 18:06:21 +0000926 unsigned long uval32 = ::strtoul (s, &pos, 0);
Greg Claytonded470d2011-03-19 01:12:21 +0000927 if (pos == s)
928 return s;
929 major = uval32;
930 if (*pos == '\0')
931 {
932 return pos; // Decoded major and got end of string
933 }
934 else if (*pos == '.')
935 {
936 const char *minor_cstr = pos + 1;
937 uval32 = ::strtoul (minor_cstr, &pos, 0);
938 if (pos == minor_cstr)
939 return pos; // Didn't get any digits for the minor version...
940 minor = uval32;
941 if (*pos == '.')
942 {
943 const char *update_cstr = pos + 1;
944 uval32 = ::strtoul (update_cstr, &pos, 0);
945 if (pos == update_cstr)
946 return pos;
947 update = uval32;
948 }
949 return pos;
950 }
951 }
Ed Masted78c9572014-04-20 00:31:37 +0000952 return nullptr;
Greg Claytonded470d2011-03-19 01:12:21 +0000953}
954
Greg Clayton144f3a92011-11-15 03:53:30 +0000955const char *
956Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
957{
958 safe_arg.assign (unsafe_arg);
959 size_t prev_pos = 0;
960 while (prev_pos < safe_arg.size())
961 {
962 // Escape spaces and quotes
963 size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
964 if (pos != std::string::npos)
965 {
966 safe_arg.insert (pos, 1, '\\');
967 prev_pos = pos + 2;
968 }
969 else
970 break;
971 }
972 return safe_arg.c_str();
973}
974
Greg Claytonded470d2011-03-19 01:12:21 +0000975
Greg Claytonc7bece562013-01-25 18:06:21 +0000976int64_t
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000977Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000978{
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000979 if (enum_values)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000980 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000981 if (s && s[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000982 {
Ed Masted78c9572014-04-20 00:31:37 +0000983 for (int i = 0; enum_values[i].string_value != nullptr ; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000984 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000985 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
986 {
987 error.Clear();
988 return enum_values[i].value;
989 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000990 }
991 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000992
993 StreamString strm;
994 strm.PutCString ("invalid enumeration value, valid values are: ");
Ed Masted78c9572014-04-20 00:31:37 +0000995 for (int i = 0; enum_values[i].string_value != nullptr; i++)
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000996 {
997 strm.Printf ("%s\"%s\"",
998 i > 0 ? ", " : "",
999 enum_values[i].string_value);
1000 }
1001 error.SetErrorString(strm.GetData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001002 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001003 else
1004 {
1005 error.SetErrorString ("invalid enumeration argument");
1006 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001007 return fail_value;
1008}
1009
1010ScriptLanguage
1011Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
1012{
1013 if (s && s[0])
1014 {
1015 if ((::strcasecmp (s, "python") == 0) ||
1016 (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
1017 {
1018 if (success_ptr) *success_ptr = true;
1019 return eScriptLanguagePython;
1020 }
1021 if (::strcasecmp (s, "none"))
1022 {
1023 if (success_ptr) *success_ptr = true;
1024 return eScriptLanguageNone;
1025 }
1026 }
1027 if (success_ptr) *success_ptr = false;
1028 return fail_value;
1029}
1030
1031Error
1032Args::StringToFormat
1033(
1034 const char *s,
Greg Clayton68ebae62011-04-28 20:55:26 +00001035 lldb::Format &format,
Greg Claytonc7bece562013-01-25 18:06:21 +00001036 size_t *byte_size_ptr
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001037)
1038{
1039 format = eFormatInvalid;
1040 Error error;
1041
1042 if (s && s[0])
1043 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001044 if (byte_size_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001045 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001046 if (isdigit (s[0]))
1047 {
Ed Masted78c9572014-04-20 00:31:37 +00001048 char *format_char = nullptr;
Greg Clayton68ebae62011-04-28 20:55:26 +00001049 unsigned long byte_size = ::strtoul (s, &format_char, 0);
1050 if (byte_size != ULONG_MAX)
1051 *byte_size_ptr = byte_size;
1052 s = format_char;
1053 }
1054 else
1055 *byte_size_ptr = 0;
1056 }
1057
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001058 const bool partial_match_ok = true;
1059 if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
Greg Clayton68ebae62011-04-28 20:55:26 +00001060 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001061 StreamString error_strm;
1062 error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
Peter Collingbourne44c9b372011-06-24 01:12:22 +00001063 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
Greg Clayton68ebae62011-04-28 20:55:26 +00001064 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001065 char format_char = FormatManager::GetFormatAsFormatChar(f);
1066 if (format_char)
1067 error_strm.Printf ("'%c' or ", format_char);
1068
1069 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
1070 error_strm.EOL();
Greg Clayton68ebae62011-04-28 20:55:26 +00001071 }
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001072
1073 if (byte_size_ptr)
1074 error_strm.PutCString ("An optional byte size can precede the format character.\n");
1075 error.SetErrorString(error_strm.GetString().c_str());
Greg Clayton68ebae62011-04-28 20:55:26 +00001076 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001077
1078 if (error.Fail())
1079 return error;
1080 }
1081 else
1082 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001083 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001084 }
1085 return error;
1086}
1087
Greg Clayton2443cbd2012-08-24 01:42:50 +00001088lldb::Encoding
1089Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
1090{
1091 if (s && s[0])
1092 {
1093 if (strcmp(s, "uint") == 0)
1094 return eEncodingUint;
1095 else if (strcmp(s, "sint") == 0)
1096 return eEncodingSint;
1097 else if (strcmp(s, "ieee754") == 0)
1098 return eEncodingIEEE754;
1099 else if (strcmp(s, "vector") == 0)
1100 return eEncodingVector;
1101 }
1102 return fail_value;
1103}
1104
1105uint32_t
1106Args::StringToGenericRegister (const char *s)
1107{
1108 if (s && s[0])
1109 {
1110 if (strcmp(s, "pc") == 0)
1111 return LLDB_REGNUM_GENERIC_PC;
1112 else if (strcmp(s, "sp") == 0)
1113 return LLDB_REGNUM_GENERIC_SP;
1114 else if (strcmp(s, "fp") == 0)
1115 return LLDB_REGNUM_GENERIC_FP;
Jason Molenda2fc43a32014-05-09 04:09:48 +00001116 else if (strcmp(s, "ra") == 0 || strcmp(s, "lr") == 0)
Greg Clayton2443cbd2012-08-24 01:42:50 +00001117 return LLDB_REGNUM_GENERIC_RA;
1118 else if (strcmp(s, "flags") == 0)
1119 return LLDB_REGNUM_GENERIC_FLAGS;
1120 else if (strncmp(s, "arg", 3) == 0)
1121 {
1122 if (s[3] && s[4] == '\0')
1123 {
1124 switch (s[3])
1125 {
1126 case '1': return LLDB_REGNUM_GENERIC_ARG1;
1127 case '2': return LLDB_REGNUM_GENERIC_ARG2;
1128 case '3': return LLDB_REGNUM_GENERIC_ARG3;
1129 case '4': return LLDB_REGNUM_GENERIC_ARG4;
1130 case '5': return LLDB_REGNUM_GENERIC_ARG5;
1131 case '6': return LLDB_REGNUM_GENERIC_ARG6;
1132 case '7': return LLDB_REGNUM_GENERIC_ARG7;
1133 case '8': return LLDB_REGNUM_GENERIC_ARG8;
1134 }
1135 }
1136 }
1137 }
1138 return LLDB_INVALID_REGNUM;
1139}
1140
1141
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001142void
1143Args::LongestCommonPrefix (std::string &common_prefix)
1144{
1145 arg_sstr_collection::iterator pos, end = m_args.end();
1146 pos = m_args.begin();
1147 if (pos == end)
1148 common_prefix.clear();
1149 else
1150 common_prefix = (*pos);
1151
1152 for (++pos; pos != end; ++pos)
1153 {
Greg Claytonc982c762010-07-09 20:39:50 +00001154 size_t new_size = (*pos).size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001155
1156 // First trim common_prefix if it is longer than the current element:
1157 if (common_prefix.size() > new_size)
1158 common_prefix.erase (new_size);
1159
1160 // Then trim it at the first disparity:
1161
Greg Claytonc982c762010-07-09 20:39:50 +00001162 for (size_t i = 0; i < common_prefix.size(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001163 {
1164 if ((*pos)[i] != common_prefix[i])
1165 {
1166 common_prefix.erase(i);
1167 break;
1168 }
1169 }
1170
1171 // If we've emptied the common prefix, we're done.
1172 if (common_prefix.empty())
1173 break;
1174 }
1175}
1176
Caroline Ticed9d63362010-12-07 19:58:26 +00001177size_t
Virgile Belloe2607b52013-09-05 16:42:23 +00001178Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
Caroline Ticed9d63362010-12-07 19:58:26 +00001179{
1180 char short_buffer[3];
1181 char long_buffer[255];
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001182 ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
Zachary Turnerd37221d2014-07-09 16:31:49 +00001183 ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].definition->long_option);
Caroline Ticed9d63362010-12-07 19:58:26 +00001184 size_t end = GetArgumentCount ();
1185 size_t idx = 0;
1186 while (idx < end)
1187 {
1188 if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
1189 || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
1190 {
1191 return idx;
1192 }
1193 ++idx;
1194 }
1195
1196 return end;
1197}
1198
1199bool
1200Args::IsPositionalArgument (const char *arg)
1201{
Ed Masted78c9572014-04-20 00:31:37 +00001202 if (arg == nullptr)
Caroline Ticed9d63362010-12-07 19:58:26 +00001203 return false;
1204
1205 bool is_positional = true;
1206 char *cptr = (char *) arg;
1207
1208 if (cptr[0] == '%')
1209 {
1210 ++cptr;
1211 while (isdigit (cptr[0]))
1212 ++cptr;
1213 if (cptr[0] != '\0')
1214 is_positional = false;
1215 }
1216 else
1217 is_positional = false;
1218
1219 return is_positional;
1220}
1221
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001222void
Caroline Tice636d6ed2010-10-12 17:45:19 +00001223Args::ParseAliasOptions (Options &options,
1224 CommandReturnObject &result,
Caroline Tice844d2302010-12-09 22:52:49 +00001225 OptionArgVector *option_arg_vector,
1226 std::string &raw_input_string)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001227{
1228 StreamString sstr;
1229 int i;
Virgile Belloe2607b52013-09-05 16:42:23 +00001230 Option *long_options = options.GetLongOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001231
Ed Masted78c9572014-04-20 00:31:37 +00001232 if (long_options == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001233 {
1234 result.AppendError ("invalid long options");
1235 result.SetStatus (eReturnStatusFailed);
1236 return;
1237 }
1238
Zachary Turnerd37221d2014-07-09 16:31:49 +00001239 for (i = 0; long_options[i].definition != nullptr; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001240 {
Ed Masted78c9572014-04-20 00:31:37 +00001241 if (long_options[i].flag == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242 {
1243 sstr << (char) long_options[i].val;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001244 switch (long_options[i].definition->option_has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245 {
1246 default:
Virgile Belloe2607b52013-09-05 16:42:23 +00001247 case OptionParser::eNoArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001248 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001249 case OptionParser::eRequiredArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001250 sstr << ":";
1251 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001252 case OptionParser::eOptionalArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001253 sstr << "::";
1254 break;
1255 }
1256 }
1257 }
1258
Virgile Belloe2607b52013-09-05 16:42:23 +00001259 OptionParser::Prepare();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001260 int val;
1261 while (1)
1262 {
1263 int long_options_index = -1;
Virgile Belloe2607b52013-09-05 16:42:23 +00001264 val = OptionParser::Parse (GetArgumentCount(),
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001265 GetArgumentVector(),
1266 sstr.GetData(),
1267 long_options,
1268 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001269
1270 if (val == -1)
1271 break;
1272
1273 if (val == '?')
1274 {
1275 result.AppendError ("unknown or ambiguous option");
1276 result.SetStatus (eReturnStatusFailed);
1277 break;
1278 }
1279
1280 if (val == 0)
1281 continue;
1282
Greg Clayton78d10192014-04-07 21:37:03 +00001283 options.OptionSeen (val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001284
1285 // Look up the long option index
1286 if (long_options_index == -1)
1287 {
1288 for (int j = 0;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001289 long_options[j].definition || long_options[j].flag || long_options[j].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001290 ++j)
1291 {
1292 if (long_options[j].val == val)
1293 {
1294 long_options_index = j;
1295 break;
1296 }
1297 }
1298 }
1299
1300 // See if the option takes an argument, and see if one was supplied.
1301 if (long_options_index >= 0)
1302 {
1303 StreamString option_str;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001304 option_str.Printf ("-%c", val);
Zachary Turnerd37221d2014-07-09 16:31:49 +00001305 const OptionDefinition *def = long_options[long_options_index].definition;
1306 int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001307
Zachary Turnerd37221d2014-07-09 16:31:49 +00001308 switch (has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001309 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001310 case OptionParser::eNoArgument:
Caroline Ticed9d63362010-12-07 19:58:26 +00001311 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001312 OptionArgValue (OptionParser::eNoArgument, "<no-argument>")));
Caroline Tice5172e6c2010-09-12 04:48:45 +00001313 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001314 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001315 case OptionParser::eRequiredArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001316 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001317 {
1318 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001319 OptionArgValue (OptionParser::eRequiredArgument,
1320 std::string (OptionParser::GetOptionArgument()))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001321 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1322 }
1323 else
1324 {
1325 result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1326 option_str.GetData());
1327 result.SetStatus (eReturnStatusFailed);
1328 }
1329 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001330 case OptionParser::eOptionalArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001331 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001332 {
1333 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001334 OptionArgValue (OptionParser::eOptionalArgument,
1335 std::string (OptionParser::GetOptionArgument()))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001336 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1337 }
1338 else
1339 {
1340 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001341 OptionArgValue (OptionParser::eOptionalArgument, "<no-argument>")));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001342 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1343 }
1344 break;
1345 default:
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001346 result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001347 result.SetStatus (eReturnStatusFailed);
1348 break;
1349 }
1350 }
1351 else
1352 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001353 result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001354 result.SetStatus (eReturnStatusFailed);
1355 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001356
1357 if (long_options_index >= 0)
1358 {
1359 // Find option in the argument list; also see if it was supposed to take an argument and if one was
Caroline Tice844d2302010-12-09 22:52:49 +00001360 // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
1361 // the raw_input_string, if one was passed in.
Caroline Ticed9d63362010-12-07 19:58:26 +00001362 size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1363 if (idx < GetArgumentCount())
1364 {
Caroline Tice844d2302010-12-09 22:52:49 +00001365 if (raw_input_string.size() > 0)
1366 {
1367 const char *tmp_arg = GetArgumentAtIndex (idx);
1368 size_t pos = raw_input_string.find (tmp_arg);
1369 if (pos != std::string::npos)
1370 raw_input_string.erase (pos, strlen (tmp_arg));
1371 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001372 ReplaceArgumentAtIndex (idx, "");
Zachary Turnerd37221d2014-07-09 16:31:49 +00001373 if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
Ed Masted78c9572014-04-20 00:31:37 +00001374 && (OptionParser::GetOptionArgument() != nullptr)
Caroline Ticed9d63362010-12-07 19:58:26 +00001375 && (idx+1 < GetArgumentCount())
Virgile Belloe2607b52013-09-05 16:42:23 +00001376 && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
Caroline Tice844d2302010-12-09 22:52:49 +00001377 {
1378 if (raw_input_string.size() > 0)
1379 {
1380 const char *tmp_arg = GetArgumentAtIndex (idx+1);
1381 size_t pos = raw_input_string.find (tmp_arg);
1382 if (pos != std::string::npos)
1383 raw_input_string.erase (pos, strlen (tmp_arg));
1384 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001385 ReplaceArgumentAtIndex (idx+1, "");
Caroline Tice844d2302010-12-09 22:52:49 +00001386 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001387 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001388 }
1389
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001390 if (!result.Succeeded())
1391 break;
1392 }
1393}
1394
1395void
1396Args::ParseArgsForCompletion
1397(
1398 Options &options,
Jim Inghamd43e0092010-06-24 20:31:04 +00001399 OptionElementVector &option_element_vector,
1400 uint32_t cursor_index
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001401)
1402{
1403 StreamString sstr;
Virgile Belloe2607b52013-09-05 16:42:23 +00001404 Option *long_options = options.GetLongOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001405 option_element_vector.clear();
1406
Ed Masted78c9572014-04-20 00:31:37 +00001407 if (long_options == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001408 {
1409 return;
1410 }
1411
1412 // Leading : tells getopt to return a : for a missing option argument AND
1413 // to suppress error messages.
1414
1415 sstr << ":";
Zachary Turnerd37221d2014-07-09 16:31:49 +00001416 for (int i = 0; long_options[i].definition != nullptr; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001417 {
Ed Masted78c9572014-04-20 00:31:37 +00001418 if (long_options[i].flag == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001419 {
1420 sstr << (char) long_options[i].val;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001421 switch (long_options[i].definition->option_has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001422 {
1423 default:
Virgile Belloe2607b52013-09-05 16:42:23 +00001424 case OptionParser::eNoArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001425 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001426 case OptionParser::eRequiredArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001427 sstr << ":";
1428 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001429 case OptionParser::eOptionalArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001430 sstr << "::";
1431 break;
1432 }
1433 }
1434 }
1435
Virgile Belloe2607b52013-09-05 16:42:23 +00001436 OptionParser::Prepare();
1437 OptionParser::EnableError(false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001438
1439 int val;
1440 const OptionDefinition *opt_defs = options.GetDefinitions();
1441
Virgile Belloe2607b52013-09-05 16:42:23 +00001442 // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front.
1443 // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't
Jim Inghamd43e0092010-06-24 20:31:04 +00001444 // change the one we have.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001445
Greg Claytonc982c762010-07-09 20:39:50 +00001446 std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001447
Jim Inghamd43e0092010-06-24 20:31:04 +00001448 bool failed_once = false;
1449 uint32_t dash_dash_pos = -1;
1450
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001451 while (1)
1452 {
1453 bool missing_argument = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001454 int long_options_index = -1;
Jim Inghamd43e0092010-06-24 20:31:04 +00001455
Virgile Belloe2607b52013-09-05 16:42:23 +00001456 val = OptionParser::Parse (dummy_vec.size() - 1,
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001457 (char *const *) &dummy_vec.front(),
1458 sstr.GetData(),
1459 long_options,
1460 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001461
1462 if (val == -1)
Jim Inghamd43e0092010-06-24 20:31:04 +00001463 {
1464 // When we're completing a "--" which is the last option on line,
1465 if (failed_once)
1466 break;
1467
1468 failed_once = true;
1469
1470 // If this is a bare "--" we mark it as such so we can complete it successfully later.
1471 // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1472 // user might want to complete options by long name. I make this work by checking whether the
1473 // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
Virgile Belloe2607b52013-09-05 16:42:23 +00001474 // I let it pass to OptionParser::Parse which will terminate the option parsing.
Jim Inghamd43e0092010-06-24 20:31:04 +00001475 // Note, in either case we continue parsing the line so we can figure out what other options
1476 // were passed. This will be useful when we come to restricting completions based on what other
1477 // options we've seen on the line.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001478
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001479 if (static_cast<size_t>(OptionParser::GetOptionIndex()) < dummy_vec.size() - 1
Virgile Belloe2607b52013-09-05 16:42:23 +00001480 && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
Jim Inghamd43e0092010-06-24 20:31:04 +00001481 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001482 dash_dash_pos = OptionParser::GetOptionIndex() - 1;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001483 if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) == cursor_index)
Jim Inghamd43e0092010-06-24 20:31:04 +00001484 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001485 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001486 OptionArgElement::eBareDoubleDash));
1487 continue;
1488 }
1489 else
1490 break;
1491 }
1492 else
1493 break;
1494 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001495 else if (val == '?')
1496 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001497 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001498 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001499 continue;
1500 }
1501 else if (val == 0)
1502 {
1503 continue;
1504 }
1505 else if (val == ':')
1506 {
1507 // This is a missing argument.
Virgile Belloe2607b52013-09-05 16:42:23 +00001508 val = OptionParser::GetOptionErrorCause();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001509 missing_argument = true;
1510 }
1511
1512 ((Options *) &options)->OptionSeen (val);
1513
1514 // Look up the long option index
1515 if (long_options_index == -1)
1516 {
1517 for (int j = 0;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001518 long_options[j].definition || long_options[j].flag || long_options[j].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001519 ++j)
1520 {
1521 if (long_options[j].val == val)
1522 {
1523 long_options_index = j;
1524 break;
1525 }
1526 }
1527 }
1528
1529 // See if the option takes an argument, and see if one was supplied.
1530 if (long_options_index >= 0)
1531 {
1532 int opt_defs_index = -1;
1533 for (int i = 0; ; i++)
1534 {
1535 if (opt_defs[i].short_option == 0)
1536 break;
1537 else if (opt_defs[i].short_option == val)
1538 {
1539 opt_defs_index = i;
1540 break;
1541 }
1542 }
1543
Zachary Turnerd37221d2014-07-09 16:31:49 +00001544 const OptionDefinition *def = long_options[long_options_index].definition;
1545 int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1546 switch (has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001547 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001548 case OptionParser::eNoArgument:
1549 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001550 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001551 case OptionParser::eRequiredArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001552 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001553 {
1554 int arg_index;
1555 if (missing_argument)
1556 arg_index = -1;
1557 else
Virgile Belloe2607b52013-09-05 16:42:23 +00001558 arg_index = OptionParser::GetOptionIndex() - 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001559
Virgile Belloe2607b52013-09-05 16:42:23 +00001560 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001561 }
1562 else
1563 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001564 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001565 }
1566 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001567 case OptionParser::eOptionalArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001568 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001569 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001570 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001571 }
1572 else
1573 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001574 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001575 }
1576 break;
1577 default:
1578 // The options table is messed up. Here we'll just continue
Virgile Belloe2607b52013-09-05 16:42:23 +00001579 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001580 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001581 break;
1582 }
1583 }
1584 else
1585 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001586 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001587 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001588 }
1589 }
Jim Inghamd43e0092010-06-24 20:31:04 +00001590
1591 // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
Virgile Belloe2607b52013-09-05 16:42:23 +00001592 // the option_element_vector, but only if it is not after the "--". But it turns out that OptionParser::Parse just ignores
Jim Inghamd43e0092010-06-24 20:31:04 +00001593 // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
Jim Inghamdc498e52014-08-27 22:06:58 +00001594 // Note, a single quoted dash is not the same as a single dash...
Jim Inghamd43e0092010-06-24 20:31:04 +00001595
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001596 if ((static_cast<int32_t>(dash_dash_pos) == -1 || cursor_index < dash_dash_pos)
Jim Inghamdc498e52014-08-27 22:06:58 +00001597 && m_args_quote_char[cursor_index] == '\0'
Jim Inghamd43e0092010-06-24 20:31:04 +00001598 && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1599 {
1600 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
1601 OptionArgElement::eBareDash));
1602
1603 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001604}
Greg Clayton4c054102012-09-01 00:38:36 +00001605
1606void
1607Args::EncodeEscapeSequences (const char *src, std::string &dst)
1608{
1609 dst.clear();
1610 if (src)
1611 {
1612 for (const char *p = src; *p != '\0'; ++p)
1613 {
1614 size_t non_special_chars = ::strcspn (p, "\\");
1615 if (non_special_chars > 0)
1616 {
1617 dst.append(p, non_special_chars);
1618 p += non_special_chars;
1619 if (*p == '\0')
1620 break;
1621 }
1622
1623 if (*p == '\\')
1624 {
1625 ++p; // skip the slash
1626 switch (*p)
1627 {
1628 case 'a' : dst.append(1, '\a'); break;
1629 case 'b' : dst.append(1, '\b'); break;
1630 case 'f' : dst.append(1, '\f'); break;
1631 case 'n' : dst.append(1, '\n'); break;
1632 case 'r' : dst.append(1, '\r'); break;
1633 case 't' : dst.append(1, '\t'); break;
1634 case 'v' : dst.append(1, '\v'); break;
1635 case '\\': dst.append(1, '\\'); break;
1636 case '\'': dst.append(1, '\''); break;
1637 case '"' : dst.append(1, '"'); break;
1638 case '0' :
1639 // 1 to 3 octal chars
1640 {
1641 // Make a string that can hold onto the initial zero char,
1642 // up to 3 octal digits, and a terminating NULL.
1643 char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
1644
1645 int i;
1646 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
1647 oct_str[i] = p[i];
1648
1649 // We don't want to consume the last octal character since
1650 // the main for loop will do this for us, so we advance p by
1651 // one less than i (even if i is zero)
1652 p += i - 1;
Ed Masted78c9572014-04-20 00:31:37 +00001653 unsigned long octal_value = ::strtoul (oct_str, nullptr, 8);
Greg Clayton4c054102012-09-01 00:38:36 +00001654 if (octal_value <= UINT8_MAX)
1655 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001656 dst.append(1, (char)octal_value);
Greg Clayton4c054102012-09-01 00:38:36 +00001657 }
1658 }
1659 break;
1660
1661 case 'x':
1662 // hex number in the format
1663 if (isxdigit(p[1]))
1664 {
1665 ++p; // Skip the 'x'
1666
1667 // Make a string that can hold onto two hex chars plus a
1668 // NULL terminator
1669 char hex_str[3] = { *p, '\0', '\0' };
1670 if (isxdigit(p[1]))
1671 {
1672 ++p; // Skip the first of the two hex chars
1673 hex_str[1] = *p;
1674 }
1675
Ed Masted78c9572014-04-20 00:31:37 +00001676 unsigned long hex_value = strtoul (hex_str, nullptr, 16);
Greg Clayton4c054102012-09-01 00:38:36 +00001677 if (hex_value <= UINT8_MAX)
1678 dst.append (1, (char)hex_value);
1679 }
1680 else
1681 {
1682 dst.append(1, 'x');
1683 }
1684 break;
1685
1686 default:
1687 // Just desensitize any other character by just printing what
1688 // came after the '\'
1689 dst.append(1, *p);
1690 break;
1691
1692 }
1693 }
1694 }
1695 }
1696}
1697
1698
1699void
1700Args::ExpandEscapedCharacters (const char *src, std::string &dst)
1701{
1702 dst.clear();
1703 if (src)
1704 {
1705 for (const char *p = src; *p != '\0'; ++p)
1706 {
Daniel Malea90b0c842012-12-05 20:24:57 +00001707 if (isprint8(*p))
Greg Clayton4c054102012-09-01 00:38:36 +00001708 dst.append(1, *p);
1709 else
1710 {
1711 switch (*p)
1712 {
1713 case '\a': dst.append("\\a"); break;
1714 case '\b': dst.append("\\b"); break;
1715 case '\f': dst.append("\\f"); break;
1716 case '\n': dst.append("\\n"); break;
1717 case '\r': dst.append("\\r"); break;
1718 case '\t': dst.append("\\t"); break;
1719 case '\v': dst.append("\\v"); break;
1720 case '\'': dst.append("\\'"); break;
1721 case '"': dst.append("\\\""); break;
1722 case '\\': dst.append("\\\\"); break;
1723 default:
1724 {
1725 // Just encode as octal
1726 dst.append("\\0");
1727 char octal_str[32];
1728 snprintf(octal_str, sizeof(octal_str), "%o", *p);
1729 dst.append(octal_str);
1730 }
1731 break;
1732 }
1733 }
1734 }
1735 }
1736}
1737