blob: 4f0219fb858bf13fef3374f9a7be6d7507728225 [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{
873 if (s && s[0])
874 {
875 if (::strcasecmp (s, "false") == 0 ||
876 ::strcasecmp (s, "off") == 0 ||
877 ::strcasecmp (s, "no") == 0 ||
878 ::strcmp (s, "0") == 0)
879 {
880 if (success_ptr)
881 *success_ptr = true;
882 return false;
883 }
884 else
885 if (::strcasecmp (s, "true") == 0 ||
886 ::strcasecmp (s, "on") == 0 ||
887 ::strcasecmp (s, "yes") == 0 ||
888 ::strcmp (s, "1") == 0)
889 {
890 if (success_ptr) *success_ptr = true;
891 return true;
892 }
893 }
894 if (success_ptr) *success_ptr = false;
895 return fail_value;
896}
897
Zachary Turner3e7442b2015-01-12 20:44:02 +0000898char
899Args::StringToChar(const char *s, char fail_value, bool *success_ptr)
900{
901 bool success = false;
902 char result = fail_value;
903
904 if (s)
905 {
906 size_t length = strlen(s);
907 if (length == 1)
908 {
909 success = true;
910 result = s[0];
911 }
912 }
913 if (success_ptr)
914 *success_ptr = success;
915 return result;
916}
917
Greg Claytonded470d2011-03-19 01:12:21 +0000918const char *
919Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
920{
921 major = UINT32_MAX;
922 minor = UINT32_MAX;
923 update = UINT32_MAX;
924
925 if (s && s[0])
926 {
Ed Masted78c9572014-04-20 00:31:37 +0000927 char *pos = nullptr;
Greg Claytonc7bece562013-01-25 18:06:21 +0000928 unsigned long uval32 = ::strtoul (s, &pos, 0);
Greg Claytonded470d2011-03-19 01:12:21 +0000929 if (pos == s)
930 return s;
931 major = uval32;
932 if (*pos == '\0')
933 {
934 return pos; // Decoded major and got end of string
935 }
936 else if (*pos == '.')
937 {
938 const char *minor_cstr = pos + 1;
939 uval32 = ::strtoul (minor_cstr, &pos, 0);
940 if (pos == minor_cstr)
941 return pos; // Didn't get any digits for the minor version...
942 minor = uval32;
943 if (*pos == '.')
944 {
945 const char *update_cstr = pos + 1;
946 uval32 = ::strtoul (update_cstr, &pos, 0);
947 if (pos == update_cstr)
948 return pos;
949 update = uval32;
950 }
951 return pos;
952 }
953 }
Ed Masted78c9572014-04-20 00:31:37 +0000954 return nullptr;
Greg Claytonded470d2011-03-19 01:12:21 +0000955}
956
Greg Clayton144f3a92011-11-15 03:53:30 +0000957const char *
958Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
959{
960 safe_arg.assign (unsafe_arg);
961 size_t prev_pos = 0;
962 while (prev_pos < safe_arg.size())
963 {
964 // Escape spaces and quotes
965 size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
966 if (pos != std::string::npos)
967 {
968 safe_arg.insert (pos, 1, '\\');
969 prev_pos = pos + 2;
970 }
971 else
972 break;
973 }
974 return safe_arg.c_str();
975}
976
Greg Claytonded470d2011-03-19 01:12:21 +0000977
Greg Claytonc7bece562013-01-25 18:06:21 +0000978int64_t
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000979Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000980{
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000981 if (enum_values)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000982 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000983 if (s && s[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000984 {
Ed Masted78c9572014-04-20 00:31:37 +0000985 for (int i = 0; enum_values[i].string_value != nullptr ; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000986 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000987 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
988 {
989 error.Clear();
990 return enum_values[i].value;
991 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000992 }
993 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000994
995 StreamString strm;
996 strm.PutCString ("invalid enumeration value, valid values are: ");
Ed Masted78c9572014-04-20 00:31:37 +0000997 for (int i = 0; enum_values[i].string_value != nullptr; i++)
Greg Claytoncf0e4f02011-10-07 18:58:12 +0000998 {
999 strm.Printf ("%s\"%s\"",
1000 i > 0 ? ", " : "",
1001 enum_values[i].string_value);
1002 }
1003 error.SetErrorString(strm.GetData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001004 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001005 else
1006 {
1007 error.SetErrorString ("invalid enumeration argument");
1008 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001009 return fail_value;
1010}
1011
1012ScriptLanguage
1013Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
1014{
1015 if (s && s[0])
1016 {
1017 if ((::strcasecmp (s, "python") == 0) ||
1018 (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
1019 {
1020 if (success_ptr) *success_ptr = true;
1021 return eScriptLanguagePython;
1022 }
1023 if (::strcasecmp (s, "none"))
1024 {
1025 if (success_ptr) *success_ptr = true;
1026 return eScriptLanguageNone;
1027 }
1028 }
1029 if (success_ptr) *success_ptr = false;
1030 return fail_value;
1031}
1032
1033Error
1034Args::StringToFormat
1035(
1036 const char *s,
Greg Clayton68ebae62011-04-28 20:55:26 +00001037 lldb::Format &format,
Greg Claytonc7bece562013-01-25 18:06:21 +00001038 size_t *byte_size_ptr
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001039)
1040{
1041 format = eFormatInvalid;
1042 Error error;
1043
1044 if (s && s[0])
1045 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001046 if (byte_size_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001047 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001048 if (isdigit (s[0]))
1049 {
Ed Masted78c9572014-04-20 00:31:37 +00001050 char *format_char = nullptr;
Greg Clayton68ebae62011-04-28 20:55:26 +00001051 unsigned long byte_size = ::strtoul (s, &format_char, 0);
1052 if (byte_size != ULONG_MAX)
1053 *byte_size_ptr = byte_size;
1054 s = format_char;
1055 }
1056 else
1057 *byte_size_ptr = 0;
1058 }
1059
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001060 const bool partial_match_ok = true;
1061 if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
Greg Clayton68ebae62011-04-28 20:55:26 +00001062 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001063 StreamString error_strm;
1064 error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
Peter Collingbourne44c9b372011-06-24 01:12:22 +00001065 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
Greg Clayton68ebae62011-04-28 20:55:26 +00001066 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001067 char format_char = FormatManager::GetFormatAsFormatChar(f);
1068 if (format_char)
1069 error_strm.Printf ("'%c' or ", format_char);
1070
1071 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
1072 error_strm.EOL();
Greg Clayton68ebae62011-04-28 20:55:26 +00001073 }
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001074
1075 if (byte_size_ptr)
1076 error_strm.PutCString ("An optional byte size can precede the format character.\n");
1077 error.SetErrorString(error_strm.GetString().c_str());
Greg Clayton68ebae62011-04-28 20:55:26 +00001078 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001079
1080 if (error.Fail())
1081 return error;
1082 }
1083 else
1084 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001085 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001086 }
1087 return error;
1088}
1089
Greg Clayton2443cbd2012-08-24 01:42:50 +00001090lldb::Encoding
1091Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
1092{
1093 if (s && s[0])
1094 {
1095 if (strcmp(s, "uint") == 0)
1096 return eEncodingUint;
1097 else if (strcmp(s, "sint") == 0)
1098 return eEncodingSint;
1099 else if (strcmp(s, "ieee754") == 0)
1100 return eEncodingIEEE754;
1101 else if (strcmp(s, "vector") == 0)
1102 return eEncodingVector;
1103 }
1104 return fail_value;
1105}
1106
1107uint32_t
1108Args::StringToGenericRegister (const char *s)
1109{
1110 if (s && s[0])
1111 {
1112 if (strcmp(s, "pc") == 0)
1113 return LLDB_REGNUM_GENERIC_PC;
1114 else if (strcmp(s, "sp") == 0)
1115 return LLDB_REGNUM_GENERIC_SP;
1116 else if (strcmp(s, "fp") == 0)
1117 return LLDB_REGNUM_GENERIC_FP;
Jason Molenda2fc43a32014-05-09 04:09:48 +00001118 else if (strcmp(s, "ra") == 0 || strcmp(s, "lr") == 0)
Greg Clayton2443cbd2012-08-24 01:42:50 +00001119 return LLDB_REGNUM_GENERIC_RA;
1120 else if (strcmp(s, "flags") == 0)
1121 return LLDB_REGNUM_GENERIC_FLAGS;
1122 else if (strncmp(s, "arg", 3) == 0)
1123 {
1124 if (s[3] && s[4] == '\0')
1125 {
1126 switch (s[3])
1127 {
1128 case '1': return LLDB_REGNUM_GENERIC_ARG1;
1129 case '2': return LLDB_REGNUM_GENERIC_ARG2;
1130 case '3': return LLDB_REGNUM_GENERIC_ARG3;
1131 case '4': return LLDB_REGNUM_GENERIC_ARG4;
1132 case '5': return LLDB_REGNUM_GENERIC_ARG5;
1133 case '6': return LLDB_REGNUM_GENERIC_ARG6;
1134 case '7': return LLDB_REGNUM_GENERIC_ARG7;
1135 case '8': return LLDB_REGNUM_GENERIC_ARG8;
1136 }
1137 }
1138 }
1139 }
1140 return LLDB_INVALID_REGNUM;
1141}
1142
1143
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001144void
1145Args::LongestCommonPrefix (std::string &common_prefix)
1146{
1147 arg_sstr_collection::iterator pos, end = m_args.end();
1148 pos = m_args.begin();
1149 if (pos == end)
1150 common_prefix.clear();
1151 else
1152 common_prefix = (*pos);
1153
1154 for (++pos; pos != end; ++pos)
1155 {
Greg Claytonc982c762010-07-09 20:39:50 +00001156 size_t new_size = (*pos).size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001157
1158 // First trim common_prefix if it is longer than the current element:
1159 if (common_prefix.size() > new_size)
1160 common_prefix.erase (new_size);
1161
1162 // Then trim it at the first disparity:
1163
Greg Claytonc982c762010-07-09 20:39:50 +00001164 for (size_t i = 0; i < common_prefix.size(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001165 {
1166 if ((*pos)[i] != common_prefix[i])
1167 {
1168 common_prefix.erase(i);
1169 break;
1170 }
1171 }
1172
1173 // If we've emptied the common prefix, we're done.
1174 if (common_prefix.empty())
1175 break;
1176 }
1177}
1178
Caroline Ticed9d63362010-12-07 19:58:26 +00001179size_t
Virgile Belloe2607b52013-09-05 16:42:23 +00001180Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
Caroline Ticed9d63362010-12-07 19:58:26 +00001181{
1182 char short_buffer[3];
1183 char long_buffer[255];
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001184 ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
Zachary Turnerd37221d2014-07-09 16:31:49 +00001185 ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].definition->long_option);
Caroline Ticed9d63362010-12-07 19:58:26 +00001186 size_t end = GetArgumentCount ();
1187 size_t idx = 0;
1188 while (idx < end)
1189 {
1190 if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
1191 || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
1192 {
1193 return idx;
1194 }
1195 ++idx;
1196 }
1197
1198 return end;
1199}
1200
1201bool
1202Args::IsPositionalArgument (const char *arg)
1203{
Ed Masted78c9572014-04-20 00:31:37 +00001204 if (arg == nullptr)
Caroline Ticed9d63362010-12-07 19:58:26 +00001205 return false;
1206
1207 bool is_positional = true;
1208 char *cptr = (char *) arg;
1209
1210 if (cptr[0] == '%')
1211 {
1212 ++cptr;
1213 while (isdigit (cptr[0]))
1214 ++cptr;
1215 if (cptr[0] != '\0')
1216 is_positional = false;
1217 }
1218 else
1219 is_positional = false;
1220
1221 return is_positional;
1222}
1223
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001224void
Caroline Tice636d6ed2010-10-12 17:45:19 +00001225Args::ParseAliasOptions (Options &options,
1226 CommandReturnObject &result,
Caroline Tice844d2302010-12-09 22:52:49 +00001227 OptionArgVector *option_arg_vector,
1228 std::string &raw_input_string)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001229{
1230 StreamString sstr;
1231 int i;
Virgile Belloe2607b52013-09-05 16:42:23 +00001232 Option *long_options = options.GetLongOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001233
Ed Masted78c9572014-04-20 00:31:37 +00001234 if (long_options == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001235 {
1236 result.AppendError ("invalid long options");
1237 result.SetStatus (eReturnStatusFailed);
1238 return;
1239 }
1240
Zachary Turnerd37221d2014-07-09 16:31:49 +00001241 for (i = 0; long_options[i].definition != nullptr; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001242 {
Ed Masted78c9572014-04-20 00:31:37 +00001243 if (long_options[i].flag == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001244 {
1245 sstr << (char) long_options[i].val;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001246 switch (long_options[i].definition->option_has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001247 {
1248 default:
Virgile Belloe2607b52013-09-05 16:42:23 +00001249 case OptionParser::eNoArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001250 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001251 case OptionParser::eRequiredArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001252 sstr << ":";
1253 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001254 case OptionParser::eOptionalArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001255 sstr << "::";
1256 break;
1257 }
1258 }
1259 }
1260
Virgile Belloe2607b52013-09-05 16:42:23 +00001261 OptionParser::Prepare();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001262 int val;
1263 while (1)
1264 {
1265 int long_options_index = -1;
Virgile Belloe2607b52013-09-05 16:42:23 +00001266 val = OptionParser::Parse (GetArgumentCount(),
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001267 GetArgumentVector(),
1268 sstr.GetData(),
1269 long_options,
1270 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001271
1272 if (val == -1)
1273 break;
1274
1275 if (val == '?')
1276 {
1277 result.AppendError ("unknown or ambiguous option");
1278 result.SetStatus (eReturnStatusFailed);
1279 break;
1280 }
1281
1282 if (val == 0)
1283 continue;
1284
Greg Clayton78d10192014-04-07 21:37:03 +00001285 options.OptionSeen (val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001286
1287 // Look up the long option index
1288 if (long_options_index == -1)
1289 {
1290 for (int j = 0;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001291 long_options[j].definition || long_options[j].flag || long_options[j].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001292 ++j)
1293 {
1294 if (long_options[j].val == val)
1295 {
1296 long_options_index = j;
1297 break;
1298 }
1299 }
1300 }
1301
1302 // See if the option takes an argument, and see if one was supplied.
1303 if (long_options_index >= 0)
1304 {
1305 StreamString option_str;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001306 option_str.Printf ("-%c", val);
Zachary Turnerd37221d2014-07-09 16:31:49 +00001307 const OptionDefinition *def = long_options[long_options_index].definition;
1308 int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001309
Zachary Turnerd37221d2014-07-09 16:31:49 +00001310 switch (has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001311 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001312 case OptionParser::eNoArgument:
Caroline Ticed9d63362010-12-07 19:58:26 +00001313 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001314 OptionArgValue (OptionParser::eNoArgument, "<no-argument>")));
Caroline Tice5172e6c2010-09-12 04:48:45 +00001315 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001317 case OptionParser::eRequiredArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001318 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001319 {
1320 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001321 OptionArgValue (OptionParser::eRequiredArgument,
1322 std::string (OptionParser::GetOptionArgument()))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001323 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1324 }
1325 else
1326 {
1327 result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1328 option_str.GetData());
1329 result.SetStatus (eReturnStatusFailed);
1330 }
1331 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001332 case OptionParser::eOptionalArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001333 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001334 {
1335 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001336 OptionArgValue (OptionParser::eOptionalArgument,
1337 std::string (OptionParser::GetOptionArgument()))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001338 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1339 }
1340 else
1341 {
1342 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Virgile Belloe2607b52013-09-05 16:42:23 +00001343 OptionArgValue (OptionParser::eOptionalArgument, "<no-argument>")));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001344 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1345 }
1346 break;
1347 default:
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001348 result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001349 result.SetStatus (eReturnStatusFailed);
1350 break;
1351 }
1352 }
1353 else
1354 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001355 result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001356 result.SetStatus (eReturnStatusFailed);
1357 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001358
1359 if (long_options_index >= 0)
1360 {
1361 // 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 +00001362 // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
1363 // the raw_input_string, if one was passed in.
Caroline Ticed9d63362010-12-07 19:58:26 +00001364 size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1365 if (idx < GetArgumentCount())
1366 {
Caroline Tice844d2302010-12-09 22:52:49 +00001367 if (raw_input_string.size() > 0)
1368 {
1369 const char *tmp_arg = GetArgumentAtIndex (idx);
1370 size_t pos = raw_input_string.find (tmp_arg);
1371 if (pos != std::string::npos)
1372 raw_input_string.erase (pos, strlen (tmp_arg));
1373 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001374 ReplaceArgumentAtIndex (idx, "");
Zachary Turnerd37221d2014-07-09 16:31:49 +00001375 if ((long_options[long_options_index].definition->option_has_arg != OptionParser::eNoArgument)
Ed Masted78c9572014-04-20 00:31:37 +00001376 && (OptionParser::GetOptionArgument() != nullptr)
Caroline Ticed9d63362010-12-07 19:58:26 +00001377 && (idx+1 < GetArgumentCount())
Virgile Belloe2607b52013-09-05 16:42:23 +00001378 && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
Caroline Tice844d2302010-12-09 22:52:49 +00001379 {
1380 if (raw_input_string.size() > 0)
1381 {
1382 const char *tmp_arg = GetArgumentAtIndex (idx+1);
1383 size_t pos = raw_input_string.find (tmp_arg);
1384 if (pos != std::string::npos)
1385 raw_input_string.erase (pos, strlen (tmp_arg));
1386 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001387 ReplaceArgumentAtIndex (idx+1, "");
Caroline Tice844d2302010-12-09 22:52:49 +00001388 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001389 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001390 }
1391
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001392 if (!result.Succeeded())
1393 break;
1394 }
1395}
1396
1397void
1398Args::ParseArgsForCompletion
1399(
1400 Options &options,
Jim Inghamd43e0092010-06-24 20:31:04 +00001401 OptionElementVector &option_element_vector,
1402 uint32_t cursor_index
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001403)
1404{
1405 StreamString sstr;
Virgile Belloe2607b52013-09-05 16:42:23 +00001406 Option *long_options = options.GetLongOptions();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001407 option_element_vector.clear();
1408
Ed Masted78c9572014-04-20 00:31:37 +00001409 if (long_options == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001410 {
1411 return;
1412 }
1413
1414 // Leading : tells getopt to return a : for a missing option argument AND
1415 // to suppress error messages.
1416
1417 sstr << ":";
Zachary Turnerd37221d2014-07-09 16:31:49 +00001418 for (int i = 0; long_options[i].definition != nullptr; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001419 {
Ed Masted78c9572014-04-20 00:31:37 +00001420 if (long_options[i].flag == nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001421 {
1422 sstr << (char) long_options[i].val;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001423 switch (long_options[i].definition->option_has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001424 {
1425 default:
Virgile Belloe2607b52013-09-05 16:42:23 +00001426 case OptionParser::eNoArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001427 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001428 case OptionParser::eRequiredArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001429 sstr << ":";
1430 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001431 case OptionParser::eOptionalArgument:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001432 sstr << "::";
1433 break;
1434 }
1435 }
1436 }
1437
Virgile Belloe2607b52013-09-05 16:42:23 +00001438 OptionParser::Prepare();
1439 OptionParser::EnableError(false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001440
1441 int val;
1442 const OptionDefinition *opt_defs = options.GetDefinitions();
1443
Virgile Belloe2607b52013-09-05 16:42:23 +00001444 // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front.
1445 // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't
Jim Inghamd43e0092010-06-24 20:31:04 +00001446 // change the one we have.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001447
Greg Claytonc982c762010-07-09 20:39:50 +00001448 std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001449
Jim Inghamd43e0092010-06-24 20:31:04 +00001450 bool failed_once = false;
1451 uint32_t dash_dash_pos = -1;
1452
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001453 while (1)
1454 {
1455 bool missing_argument = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001456 int long_options_index = -1;
Jim Inghamd43e0092010-06-24 20:31:04 +00001457
Virgile Belloe2607b52013-09-05 16:42:23 +00001458 val = OptionParser::Parse (dummy_vec.size() - 1,
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001459 (char *const *) &dummy_vec.front(),
1460 sstr.GetData(),
1461 long_options,
1462 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001463
1464 if (val == -1)
Jim Inghamd43e0092010-06-24 20:31:04 +00001465 {
1466 // When we're completing a "--" which is the last option on line,
1467 if (failed_once)
1468 break;
1469
1470 failed_once = true;
1471
1472 // If this is a bare "--" we mark it as such so we can complete it successfully later.
1473 // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1474 // user might want to complete options by long name. I make this work by checking whether the
1475 // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
Virgile Belloe2607b52013-09-05 16:42:23 +00001476 // I let it pass to OptionParser::Parse which will terminate the option parsing.
Jim Inghamd43e0092010-06-24 20:31:04 +00001477 // Note, in either case we continue parsing the line so we can figure out what other options
1478 // were passed. This will be useful when we come to restricting completions based on what other
1479 // options we've seen on the line.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001480
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001481 if (static_cast<size_t>(OptionParser::GetOptionIndex()) < dummy_vec.size() - 1
Virgile Belloe2607b52013-09-05 16:42:23 +00001482 && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
Jim Inghamd43e0092010-06-24 20:31:04 +00001483 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001484 dash_dash_pos = OptionParser::GetOptionIndex() - 1;
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001485 if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) == cursor_index)
Jim Inghamd43e0092010-06-24 20:31:04 +00001486 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001487 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001488 OptionArgElement::eBareDoubleDash));
1489 continue;
1490 }
1491 else
1492 break;
1493 }
1494 else
1495 break;
1496 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001497 else if (val == '?')
1498 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001499 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001500 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001501 continue;
1502 }
1503 else if (val == 0)
1504 {
1505 continue;
1506 }
1507 else if (val == ':')
1508 {
1509 // This is a missing argument.
Virgile Belloe2607b52013-09-05 16:42:23 +00001510 val = OptionParser::GetOptionErrorCause();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001511 missing_argument = true;
1512 }
1513
1514 ((Options *) &options)->OptionSeen (val);
1515
1516 // Look up the long option index
1517 if (long_options_index == -1)
1518 {
1519 for (int j = 0;
Zachary Turnerd37221d2014-07-09 16:31:49 +00001520 long_options[j].definition || long_options[j].flag || long_options[j].val;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001521 ++j)
1522 {
1523 if (long_options[j].val == val)
1524 {
1525 long_options_index = j;
1526 break;
1527 }
1528 }
1529 }
1530
1531 // See if the option takes an argument, and see if one was supplied.
1532 if (long_options_index >= 0)
1533 {
1534 int opt_defs_index = -1;
1535 for (int i = 0; ; i++)
1536 {
1537 if (opt_defs[i].short_option == 0)
1538 break;
1539 else if (opt_defs[i].short_option == val)
1540 {
1541 opt_defs_index = i;
1542 break;
1543 }
1544 }
1545
Zachary Turnerd37221d2014-07-09 16:31:49 +00001546 const OptionDefinition *def = long_options[long_options_index].definition;
1547 int has_arg = (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1548 switch (has_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001549 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001550 case OptionParser::eNoArgument:
1551 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001552 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001553 case OptionParser::eRequiredArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001554 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001555 {
1556 int arg_index;
1557 if (missing_argument)
1558 arg_index = -1;
1559 else
Virgile Belloe2607b52013-09-05 16:42:23 +00001560 arg_index = OptionParser::GetOptionIndex() - 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001561
Virgile Belloe2607b52013-09-05 16:42:23 +00001562 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001563 }
1564 else
1565 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001566 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001567 }
1568 break;
Virgile Belloe2607b52013-09-05 16:42:23 +00001569 case OptionParser::eOptionalArgument:
Ed Masted78c9572014-04-20 00:31:37 +00001570 if (OptionParser::GetOptionArgument() != nullptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001571 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001572 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001573 }
1574 else
1575 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001576 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001577 }
1578 break;
1579 default:
1580 // The options table is messed up. Here we'll just continue
Virgile Belloe2607b52013-09-05 16:42:23 +00001581 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001582 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001583 break;
1584 }
1585 }
1586 else
1587 {
Virgile Belloe2607b52013-09-05 16:42:23 +00001588 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
Jim Inghamd43e0092010-06-24 20:31:04 +00001589 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001590 }
1591 }
Jim Inghamd43e0092010-06-24 20:31:04 +00001592
1593 // 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 +00001594 // 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 +00001595 // 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 +00001596 // Note, a single quoted dash is not the same as a single dash...
Jim Inghamd43e0092010-06-24 20:31:04 +00001597
Saleem Abdulrasool3985c8c2014-04-02 03:51:35 +00001598 if ((static_cast<int32_t>(dash_dash_pos) == -1 || cursor_index < dash_dash_pos)
Jim Inghamdc498e52014-08-27 22:06:58 +00001599 && m_args_quote_char[cursor_index] == '\0'
Jim Inghamd43e0092010-06-24 20:31:04 +00001600 && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1601 {
1602 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
1603 OptionArgElement::eBareDash));
1604
1605 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001606}
Greg Clayton4c054102012-09-01 00:38:36 +00001607
1608void
1609Args::EncodeEscapeSequences (const char *src, std::string &dst)
1610{
1611 dst.clear();
1612 if (src)
1613 {
1614 for (const char *p = src; *p != '\0'; ++p)
1615 {
1616 size_t non_special_chars = ::strcspn (p, "\\");
1617 if (non_special_chars > 0)
1618 {
1619 dst.append(p, non_special_chars);
1620 p += non_special_chars;
1621 if (*p == '\0')
1622 break;
1623 }
1624
1625 if (*p == '\\')
1626 {
1627 ++p; // skip the slash
1628 switch (*p)
1629 {
1630 case 'a' : dst.append(1, '\a'); break;
1631 case 'b' : dst.append(1, '\b'); break;
1632 case 'f' : dst.append(1, '\f'); break;
1633 case 'n' : dst.append(1, '\n'); break;
1634 case 'r' : dst.append(1, '\r'); break;
1635 case 't' : dst.append(1, '\t'); break;
1636 case 'v' : dst.append(1, '\v'); break;
1637 case '\\': dst.append(1, '\\'); break;
1638 case '\'': dst.append(1, '\''); break;
1639 case '"' : dst.append(1, '"'); break;
1640 case '0' :
1641 // 1 to 3 octal chars
1642 {
1643 // Make a string that can hold onto the initial zero char,
1644 // up to 3 octal digits, and a terminating NULL.
1645 char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
1646
1647 int i;
1648 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
1649 oct_str[i] = p[i];
1650
1651 // We don't want to consume the last octal character since
1652 // the main for loop will do this for us, so we advance p by
1653 // one less than i (even if i is zero)
1654 p += i - 1;
Ed Masted78c9572014-04-20 00:31:37 +00001655 unsigned long octal_value = ::strtoul (oct_str, nullptr, 8);
Greg Clayton4c054102012-09-01 00:38:36 +00001656 if (octal_value <= UINT8_MAX)
1657 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001658 dst.append(1, (char)octal_value);
Greg Clayton4c054102012-09-01 00:38:36 +00001659 }
1660 }
1661 break;
1662
1663 case 'x':
1664 // hex number in the format
1665 if (isxdigit(p[1]))
1666 {
1667 ++p; // Skip the 'x'
1668
1669 // Make a string that can hold onto two hex chars plus a
1670 // NULL terminator
1671 char hex_str[3] = { *p, '\0', '\0' };
1672 if (isxdigit(p[1]))
1673 {
1674 ++p; // Skip the first of the two hex chars
1675 hex_str[1] = *p;
1676 }
1677
Ed Masted78c9572014-04-20 00:31:37 +00001678 unsigned long hex_value = strtoul (hex_str, nullptr, 16);
Greg Clayton4c054102012-09-01 00:38:36 +00001679 if (hex_value <= UINT8_MAX)
1680 dst.append (1, (char)hex_value);
1681 }
1682 else
1683 {
1684 dst.append(1, 'x');
1685 }
1686 break;
1687
1688 default:
1689 // Just desensitize any other character by just printing what
1690 // came after the '\'
1691 dst.append(1, *p);
1692 break;
1693
1694 }
1695 }
1696 }
1697 }
1698}
1699
1700
1701void
1702Args::ExpandEscapedCharacters (const char *src, std::string &dst)
1703{
1704 dst.clear();
1705 if (src)
1706 {
1707 for (const char *p = src; *p != '\0'; ++p)
1708 {
Daniel Malea90b0c842012-12-05 20:24:57 +00001709 if (isprint8(*p))
Greg Clayton4c054102012-09-01 00:38:36 +00001710 dst.append(1, *p);
1711 else
1712 {
1713 switch (*p)
1714 {
1715 case '\a': dst.append("\\a"); break;
1716 case '\b': dst.append("\\b"); break;
1717 case '\f': dst.append("\\f"); break;
1718 case '\n': dst.append("\\n"); break;
1719 case '\r': dst.append("\\r"); break;
1720 case '\t': dst.append("\\t"); break;
1721 case '\v': dst.append("\\v"); break;
1722 case '\'': dst.append("\\'"); break;
1723 case '"': dst.append("\\\""); break;
1724 case '\\': dst.append("\\\\"); break;
1725 default:
1726 {
1727 // Just encode as octal
1728 dst.append("\\0");
1729 char octal_str[32];
1730 snprintf(octal_str, sizeof(octal_str), "%o", *p);
1731 dst.append(octal_str);
1732 }
1733 break;
1734 }
1735 }
1736 }
1737 }
1738}
1739