blob: 833afd606a1a7aae64aa6cc5dee57d89ba326ec6 [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
Virgile Bellob2f1fb22013-08-23 12:44:05 +000013#ifdef _WIN32
14#define _BSD_SOURCE // Required so that getopt.h defines optreset
15#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016#include <getopt.h>
Eli Friedman5661f922010-06-09 10:59:23 +000017#include <cstdlib>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// C++ Includes
19// Other libraries and framework includes
20// Project includes
Jim Ingham40af72e2010-06-15 19:49:27 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/Stream.h"
23#include "lldb/Core/StreamFile.h"
24#include "lldb/Core/StreamString.h"
Enrico Granata5548cb52013-01-28 23:47:25 +000025#include "lldb/DataFormatters/FormatManager.h"
Jim Ingham40af72e2010-06-15 19:49:27 +000026#include "lldb/Interpreter/Options.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonb9d5df52012-12-06 22:49:16 +000028#include "lldb/Target/Process.h"
29//#include "lldb/Target/RegisterContext.h"
30#include "lldb/Target/StackFrame.h"
31#include "lldb/Target/Target.h"
32//#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000033
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034using namespace lldb;
35using namespace lldb_private;
36
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037//----------------------------------------------------------------------
38// Args constructor
39//----------------------------------------------------------------------
40Args::Args (const char *command) :
41 m_args(),
Greg Clayton8b82f082011-04-12 05:54:46 +000042 m_argv(),
43 m_args_quote_char()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044{
Greg Clayton6ad07dd2010-12-19 03:41:24 +000045 if (command)
46 SetCommandString (command);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000047}
48
49
50Args::Args (const char *command, size_t len) :
51 m_args(),
Greg Clayton8b82f082011-04-12 05:54:46 +000052 m_argv(),
53 m_args_quote_char()
Chris Lattner30fdc8d2010-06-08 16:52:24 +000054{
Greg Clayton6ad07dd2010-12-19 03:41:24 +000055 if (command && len)
56 SetCommandString (command, len);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057}
58
Chris Lattner30fdc8d2010-06-08 16:52:24 +000059//----------------------------------------------------------------------
Greg Clayton8b82f082011-04-12 05:54:46 +000060// We have to be very careful on the copy constructor of this class
61// to make sure we copy all of the string values, but we can't copy the
62// rhs.m_argv into m_argv since it will point to the "const char *" c
63// strings in rhs.m_args. We need to copy the string list and update our
64// own m_argv appropriately.
65//----------------------------------------------------------------------
66Args::Args (const Args &rhs) :
67 m_args (rhs.m_args),
68 m_argv (),
69 m_args_quote_char(rhs.m_args_quote_char)
70{
71 UpdateArgvFromArgs();
72}
73
74//----------------------------------------------------------------------
75// We have to be very careful on the copy constructor of this class
76// to make sure we copy all of the string values, but we can't copy the
77// rhs.m_argv into m_argv since it will point to the "const char *" c
78// strings in rhs.m_args. We need to copy the string list and update our
79// own m_argv appropriately.
80//----------------------------------------------------------------------
81const Args &
82Args::operator= (const Args &rhs)
83{
84 // Make sure we aren't assigning to self
85 if (this != &rhs)
86 {
87 m_args = rhs.m_args;
88 m_args_quote_char = rhs.m_args_quote_char;
89 UpdateArgvFromArgs();
90 }
91 return *this;
92}
93
94//----------------------------------------------------------------------
Chris Lattner30fdc8d2010-06-08 16:52:24 +000095// Destructor
96//----------------------------------------------------------------------
97Args::~Args ()
98{
99}
100
101void
102Args::Dump (Stream *s)
103{
Greg Claytonc7bece562013-01-25 18:06:21 +0000104 const size_t argc = m_argv.size();
105 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000106 {
107 s->Indent();
108 const char *arg_cstr = m_argv[i];
109 if (arg_cstr)
Greg Claytonc7bece562013-01-25 18:06:21 +0000110 s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000111 else
Greg Claytonc7bece562013-01-25 18:06:21 +0000112 s->Printf("argv[%zi]=NULL\n", i);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000113 }
114 s->EOL();
115}
116
117bool
Greg Claytonda91b172012-04-25 22:30:32 +0000118Args::GetCommandString (std::string &command) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000119{
120 command.clear();
Greg Claytonc7bece562013-01-25 18:06:21 +0000121 const size_t argc = GetArgumentCount();
122 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000123 {
124 if (i > 0)
125 command += ' ';
126 command += m_argv[i];
127 }
128 return argc > 0;
129}
130
Caroline Tice2d5289d2010-12-10 00:26:54 +0000131bool
Greg Claytonda91b172012-04-25 22:30:32 +0000132Args::GetQuotedCommandString (std::string &command) const
Caroline Tice2d5289d2010-12-10 00:26:54 +0000133{
134 command.clear ();
Greg Claytonc7bece562013-01-25 18:06:21 +0000135 const size_t argc = GetArgumentCount();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000136 for (size_t i = 0; i < argc; ++i)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000137 {
138 if (i > 0)
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000139 command.append (1, ' ');
140 char quote_char = GetArgumentQuoteCharAtIndex(i);
141 if (quote_char)
Caroline Tice2d5289d2010-12-10 00:26:54 +0000142 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000143 command.append (1, quote_char);
144 command.append (m_argv[i]);
145 command.append (1, quote_char);
Caroline Tice2d5289d2010-12-10 00:26:54 +0000146 }
147 else
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000148 command.append (m_argv[i]);
Caroline Tice2d5289d2010-12-10 00:26:54 +0000149 }
150 return argc > 0;
151}
152
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153void
154Args::SetCommandString (const char *command, size_t len)
155{
156 // Use std::string to make sure we get a NULL terminated string we can use
157 // as "command" could point to a string within a large string....
158 std::string null_terminated_command(command, len);
159 SetCommandString(null_terminated_command.c_str());
160}
161
162void
163Args::SetCommandString (const char *command)
164{
165 m_args.clear();
166 m_argv.clear();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000167 m_args_quote_char.clear();
168
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000169 if (command && command[0])
170 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000171 static const char *k_space_separators = " \t";
Johnny Chena28b89c2012-01-19 19:22:41 +0000172 static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000173 const char *arg_end = NULL;
174 const char *arg_pos;
175 for (arg_pos = command;
176 arg_pos && arg_pos[0];
177 arg_pos = arg_end)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000179 // Skip any leading space separators
180 const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
181
182 // If there were only space separators to the end of the line, then
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000183 // we're done.
184 if (*arg_start == '\0')
185 break;
186
Greg Clayton710dd5a2011-01-08 20:28:42 +0000187 // Arguments can be split into multiple discontiguous pieces,
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000188 // for example:
189 // "Hello ""World"
190 // this would result in a single argument "Hello World" (without/
191 // the quotes) since the quotes would be removed and there is
192 // not space between the strings. So we need to keep track of the
193 // current start of each argument piece in "arg_piece_start"
194 const char *arg_piece_start = arg_start;
195 arg_pos = arg_piece_start;
196
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000197 std::string arg;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000198 // Since we can have multiple quotes that form a single command
199 // in a command like: "Hello "world'!' (which will make a single
200 // argument "Hello world!") we remember the first quote character
201 // we encounter and use that for the quote character.
202 char first_quote_char = '\0';
203 char quote_char = '\0';
204 bool arg_complete = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000205
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000206 do
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000207 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000208 arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
209
210 switch (arg_end[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000211 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000212 default:
213 assert (!"Unhandled case statement, we must handle this...");
214 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000215
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000216 case '\0':
217 // End of C string
218 if (arg_piece_start && arg_piece_start[0])
219 arg.append (arg_piece_start);
220 arg_complete = true;
221 break;
222
223 case '\\':
224 // Backslash character
225 switch (arg_end[1])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000226 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000227 case '\0':
228 arg.append (arg_piece_start);
Greg Clayton0c943132012-03-15 17:10:48 +0000229 ++arg_end;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000230 arg_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000231 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000232
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000233 default:
Jim Inghama39fb7a2012-07-21 00:12:58 +0000234 if (quote_char == '\0')
235 {
236 arg.append (arg_piece_start, arg_end - arg_piece_start);
Adrian Prantl5eeaf742013-06-18 18:24:04 +0000237 if (arg_end[1] != '\0')
Jim Inghama39fb7a2012-07-21 00:12:58 +0000238 {
239 arg.append (arg_end + 1, 1);
240 arg_pos = arg_end + 2;
241 arg_piece_start = arg_pos;
242 }
243 }
244 else
245 arg_pos = arg_end + 2;
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000246 break;
247 }
248 break;
249
250 case '"':
251 case '\'':
252 case '`':
253 // Quote characters
254 if (quote_char)
255 {
256 // We found a quote character while inside a quoted
257 // character argument. If it matches our current quote
258 // character, this ends the effect of the quotes. If it
259 // doesn't we ignore it.
260 if (quote_char == arg_end[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000262 arg.append (arg_piece_start, arg_end - arg_piece_start);
263 // Clear the quote character and let parsing
264 // continue (we need to watch for things like:
265 // "Hello ""World"
266 // "Hello "World
267 // "Hello "'World'
268 // All of which will result in a single argument "Hello World"
269 quote_char = '\0'; // Note that we are no longer inside quotes
270 arg_pos = arg_end + 1; // Skip the quote character
271 arg_piece_start = arg_pos; // Note we are starting from later in the string
272 }
273 else
274 {
275 // different quote, skip it and keep going
276 arg_pos = arg_end + 1;
277 }
278 }
279 else
280 {
281 // We found the start of a quote scope.
Greg Clayton710dd5a2011-01-08 20:28:42 +0000282 // Make sure there isn't a string that precedes
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000283 // the start of a quote scope like:
284 // Hello" World"
285 // If so, then add the "Hello" to the arg
286 if (arg_end > arg_piece_start)
287 arg.append (arg_piece_start, arg_end - arg_piece_start);
288
289 // Enter into a quote scope
290 quote_char = arg_end[0];
291
292 if (first_quote_char == '\0')
293 first_quote_char = quote_char;
294
295 arg_pos = arg_end;
Johnny Chena28b89c2012-01-19 19:22:41 +0000296 ++arg_pos; // Skip the quote character
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000297 arg_piece_start = arg_pos; // Note we are starting from later in the string
298
299 // Skip till the next quote character
300 const char *end_quote = ::strchr (arg_piece_start, quote_char);
301 while (end_quote && end_quote[-1] == '\\')
302 {
303 // Don't skip the quote character if it is
304 // preceded by a '\' character
305 end_quote = ::strchr (end_quote + 1, quote_char);
306 }
307
308 if (end_quote)
309 {
310 if (end_quote > arg_piece_start)
Johnny Chena28b89c2012-01-19 19:22:41 +0000311 arg.append (arg_piece_start, end_quote - arg_piece_start);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000312
313 // If the next character is a space or the end of
314 // string, this argument is complete...
315 if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
316 {
317 arg_complete = true;
318 arg_end = end_quote + 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319 }
320 else
321 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000322 arg_pos = end_quote + 1;
323 arg_piece_start = arg_pos;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000324 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000325 quote_char = '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000326 }
Greg Clayton0c943132012-03-15 17:10:48 +0000327 else
328 {
329 // Consume the rest of the string as there was no terminating quote
330 arg.append(arg_piece_start);
331 arg_end = arg_piece_start + strlen(arg_piece_start);
332 arg_complete = true;
333 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000334 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000335 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000336
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000337 case ' ':
338 case '\t':
339 if (quote_char)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000340 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000341 // We are currently processing a quoted character and found
342 // a space character, skip any spaces and keep trying to find
343 // the end of the argument.
344 arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000345 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000346 else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000347 {
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000348 // We are not inside any quotes, we just found a space after an
349 // argument
350 if (arg_end > arg_piece_start)
351 arg.append (arg_piece_start, arg_end - arg_piece_start);
352 arg_complete = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000353 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000354 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000355 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000356 } while (!arg_complete);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000357
358 m_args.push_back(arg);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000359 m_args_quote_char.push_back (first_quote_char);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000360 }
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000361 UpdateArgvFromArgs();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000363}
364
365void
366Args::UpdateArgsAfterOptionParsing()
367{
368 // Now m_argv might be out of date with m_args, so we need to fix that
369 arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
370 arg_sstr_collection::iterator args_pos;
371 arg_quote_char_collection::iterator quotes_pos;
372
373 for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
374 argv_pos != argv_end && args_pos != m_args.end();
375 ++argv_pos)
376 {
377 const char *argv_cstr = *argv_pos;
378 if (argv_cstr == NULL)
379 break;
380
381 while (args_pos != m_args.end())
382 {
383 const char *args_cstr = args_pos->c_str();
384 if (args_cstr == argv_cstr)
385 {
386 // We found the argument that matches the C string in the
387 // vector, so we can now look for the next one
388 ++args_pos;
389 ++quotes_pos;
390 break;
391 }
392 else
393 {
394 quotes_pos = m_args_quote_char.erase (quotes_pos);
395 args_pos = m_args.erase (args_pos);
396 }
397 }
398 }
399
400 if (args_pos != m_args.end())
401 m_args.erase (args_pos, m_args.end());
402
403 if (quotes_pos != m_args_quote_char.end())
404 m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
405}
406
407void
408Args::UpdateArgvFromArgs()
409{
410 m_argv.clear();
411 arg_sstr_collection::const_iterator pos, end = m_args.end();
412 for (pos = m_args.begin(); pos != end; ++pos)
413 m_argv.push_back(pos->c_str());
414 m_argv.push_back(NULL);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000415 // Make sure we have enough arg quote chars in the array
416 if (m_args_quote_char.size() < m_args.size())
417 m_args_quote_char.resize (m_argv.size());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418}
419
420size_t
421Args::GetArgumentCount() const
422{
423 if (m_argv.empty())
424 return 0;
425 return m_argv.size() - 1;
426}
427
428const char *
429Args::GetArgumentAtIndex (size_t idx) const
430{
431 if (idx < m_argv.size())
432 return m_argv[idx];
433 return NULL;
434}
435
436char
437Args::GetArgumentQuoteCharAtIndex (size_t idx) const
438{
439 if (idx < m_args_quote_char.size())
440 return m_args_quote_char[idx];
441 return '\0';
442}
443
444char **
445Args::GetArgumentVector()
446{
447 if (!m_argv.empty())
448 return (char **)&m_argv[0];
449 return NULL;
450}
451
452const char **
453Args::GetConstArgumentVector() const
454{
455 if (!m_argv.empty())
456 return (const char **)&m_argv[0];
457 return NULL;
458}
459
460void
461Args::Shift ()
462{
463 // Don't pop the last NULL terminator from the argv array
464 if (m_argv.size() > 1)
465 {
466 m_argv.erase(m_argv.begin());
467 m_args.pop_front();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000468 if (!m_args_quote_char.empty())
469 m_args_quote_char.erase(m_args_quote_char.begin());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000470 }
471}
472
473const char *
474Args::Unshift (const char *arg_cstr, char quote_char)
475{
476 m_args.push_front(arg_cstr);
477 m_argv.insert(m_argv.begin(), m_args.front().c_str());
478 m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
479 return GetArgumentAtIndex (0);
480}
481
482void
483Args::AppendArguments (const Args &rhs)
484{
485 const size_t rhs_argc = rhs.GetArgumentCount();
486 for (size_t i=0; i<rhs_argc; ++i)
487 AppendArgument(rhs.GetArgumentAtIndex(i));
488}
489
Greg Clayton982c9762011-11-03 21:22:33 +0000490void
491Args::AppendArguments (const char **argv)
492{
493 if (argv)
494 {
495 for (uint32_t i=0; argv[i]; ++i)
496 AppendArgument(argv[i]);
497 }
498}
499
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000500const char *
501Args::AppendArgument (const char *arg_cstr, char quote_char)
502{
503 return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
504}
505
506const char *
507Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
508{
509 // Since we are using a std::list to hold onto the copied C string and
510 // we don't have direct access to the elements, we have to iterate to
511 // find the value.
512 arg_sstr_collection::iterator pos, end = m_args.end();
513 size_t i = idx;
514 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
515 --i;
516
517 pos = m_args.insert(pos, arg_cstr);
518
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000519 if (idx >= m_args_quote_char.size())
520 {
521 m_args_quote_char.resize(idx + 1);
522 m_args_quote_char[idx] = quote_char;
523 }
524 else
525 m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526
527 UpdateArgvFromArgs();
528 return GetArgumentAtIndex(idx);
529}
530
531const char *
532Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
533{
534 // Since we are using a std::list to hold onto the copied C string and
535 // we don't have direct access to the elements, we have to iterate to
536 // find the value.
537 arg_sstr_collection::iterator pos, end = m_args.end();
538 size_t i = idx;
539 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
540 --i;
541
542 if (pos != end)
543 {
544 pos->assign(arg_cstr);
545 assert(idx < m_argv.size() - 1);
546 m_argv[idx] = pos->c_str();
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000547 if (idx >= m_args_quote_char.size())
548 m_args_quote_char.resize(idx + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549 m_args_quote_char[idx] = quote_char;
550 return GetArgumentAtIndex(idx);
551 }
552 return NULL;
553}
554
555void
556Args::DeleteArgumentAtIndex (size_t idx)
557{
558 // Since we are using a std::list to hold onto the copied C string and
559 // we don't have direct access to the elements, we have to iterate to
560 // find the value.
561 arg_sstr_collection::iterator pos, end = m_args.end();
562 size_t i = idx;
563 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
564 --i;
565
566 if (pos != end)
567 {
568 m_args.erase (pos);
569 assert(idx < m_argv.size() - 1);
570 m_argv.erase(m_argv.begin() + idx);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000571 if (idx < m_args_quote_char.size())
572 m_args_quote_char.erase(m_args_quote_char.begin() + idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000573 }
574}
575
576void
Greg Claytonc7bece562013-01-25 18:06:21 +0000577Args::SetArguments (size_t argc, const char **argv)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578{
579 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
580 // no need to clear it here.
581 m_args.clear();
582 m_args_quote_char.clear();
583
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000584 // First copy each string
Greg Clayton982c9762011-11-03 21:22:33 +0000585 for (size_t i=0; i<argc; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000586 {
587 m_args.push_back (argv[i]);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000588 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000589 m_args_quote_char.push_back (argv[i][0]);
590 else
591 m_args_quote_char.push_back ('\0');
592 }
593
594 UpdateArgvFromArgs();
595}
596
Greg Clayton982c9762011-11-03 21:22:33 +0000597void
598Args::SetArguments (const char **argv)
599{
600 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
601 // no need to clear it here.
602 m_args.clear();
603 m_args_quote_char.clear();
604
605 if (argv)
606 {
607 // First copy each string
608 for (size_t i=0; argv[i]; ++i)
609 {
610 m_args.push_back (argv[i]);
611 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
612 m_args_quote_char.push_back (argv[i][0]);
613 else
614 m_args_quote_char.push_back ('\0');
615 }
616 }
617
618 UpdateArgvFromArgs();
619}
620
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000621
622Error
623Args::ParseOptions (Options &options)
624{
625 StreamString sstr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000626 Error error;
627 struct option *long_options = options.GetLongOptions();
628 if (long_options == NULL)
629 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000630 error.SetErrorStringWithFormat("invalid long options");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631 return error;
632 }
633
Greg Claytonb1320972010-07-14 00:18:15 +0000634 for (int i=0; long_options[i].name != NULL; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000635 {
636 if (long_options[i].flag == NULL)
637 {
Daniel Malea90b0c842012-12-05 20:24:57 +0000638 if (isprint8(long_options[i].val))
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000639 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +0000640 sstr << (char)long_options[i].val;
641 switch (long_options[i].has_arg)
642 {
643 default:
644 case no_argument: break;
645 case required_argument: sstr << ':'; break;
646 case optional_argument: sstr << "::"; break;
647 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000648 }
649 }
650 }
Eli Friedmanadb35022010-06-13 19:18:49 +0000651#ifdef __GLIBC__
652 optind = 0;
653#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000654 optreset = 1;
655 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +0000656#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657 int val;
658 while (1)
659 {
660 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +0000661 val = ::getopt_long_only(GetArgumentCount(),
662 GetArgumentVector(),
663 sstr.GetData(),
664 long_options,
665 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000666 if (val == -1)
667 break;
668
669 // Did we get an error?
670 if (val == '?')
671 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000672 error.SetErrorStringWithFormat("unknown or ambiguous option");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000673 break;
674 }
675 // The option auto-set itself
676 if (val == 0)
677 continue;
678
679 ((Options *) &options)->OptionSeen (val);
680
681 // Lookup the long option index
682 if (long_options_index == -1)
683 {
684 for (int i=0;
685 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
686 ++i)
687 {
688 if (long_options[i].val == val)
689 {
690 long_options_index = i;
691 break;
692 }
693 }
694 }
695 // Call the callback with the option
696 if (long_options_index >= 0)
697 {
698 error = options.SetOptionValue(long_options_index,
699 long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
700 }
701 else
702 {
Greg Clayton86edbf42011-10-26 00:56:27 +0000703 error.SetErrorStringWithFormat("invalid option with value '%i'", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000704 }
705 if (error.Fail())
706 break;
707 }
708
709 // Update our ARGV now that get options has consumed all the options
710 m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
711 UpdateArgsAfterOptionParsing ();
712 return error;
713}
714
715void
716Args::Clear ()
717{
718 m_args.clear ();
719 m_argv.clear ();
720 m_args_quote_char.clear();
721}
722
723int32_t
724Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
725{
726 if (s && s[0])
727 {
728 char *end = NULL;
Greg Claytonc7bece562013-01-25 18:06:21 +0000729 const long sval = ::strtol (s, &end, base);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000730 if (*end == '\0')
731 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000732 if (success_ptr)
733 *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
734 return (int32_t)sval; // All characters were used, return the result
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000735 }
736 }
737 if (success_ptr) *success_ptr = false;
738 return fail_value;
739}
740
741uint32_t
742Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
743{
744 if (s && s[0])
745 {
746 char *end = NULL;
Greg Claytonc7bece562013-01-25 18:06:21 +0000747 const unsigned long uval = ::strtoul (s, &end, base);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000748 if (*end == '\0')
749 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000750 if (success_ptr)
751 *success_ptr = (uval <= UINT32_MAX);
752 return (uint32_t)uval; // All characters were used, return the result
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000753 }
754 }
755 if (success_ptr) *success_ptr = false;
756 return fail_value;
757}
758
759
760int64_t
761Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
762{
763 if (s && s[0])
764 {
765 char *end = NULL;
766 int64_t uval = ::strtoll (s, &end, base);
767 if (*end == '\0')
768 {
769 if (success_ptr) *success_ptr = true;
770 return uval; // All characters were used, return the result
771 }
772 }
773 if (success_ptr) *success_ptr = false;
774 return fail_value;
775}
776
777uint64_t
778Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
779{
780 if (s && s[0])
781 {
782 char *end = NULL;
783 uint64_t uval = ::strtoull (s, &end, base);
784 if (*end == '\0')
785 {
786 if (success_ptr) *success_ptr = true;
787 return uval; // All characters were used, return the result
788 }
789 }
790 if (success_ptr) *success_ptr = false;
791 return fail_value;
792}
793
794lldb::addr_t
Greg Claytonb9d5df52012-12-06 22:49:16 +0000795Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000796{
Greg Claytonb9d5df52012-12-06 22:49:16 +0000797 bool error_set = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000798 if (s && s[0])
799 {
800 char *end = NULL;
801 lldb::addr_t addr = ::strtoull (s, &end, 0);
802 if (*end == '\0')
803 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000804 if (error_ptr)
805 error_ptr->Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000806 return addr; // All characters were used, return the result
807 }
808 // Try base 16 with no prefix...
809 addr = ::strtoull (s, &end, 16);
810 if (*end == '\0')
811 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000812 if (error_ptr)
813 error_ptr->Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000814 return addr; // All characters were used, return the result
815 }
Greg Claytonb9d5df52012-12-06 22:49:16 +0000816
817 if (exe_ctx)
818 {
819 Target *target = exe_ctx->GetTargetPtr();
820 if (target)
821 {
822 lldb::ValueObjectSP valobj_sp;
823 EvaluateExpressionOptions options;
824 options.SetCoerceToId(false);
825 options.SetUnwindOnError(true);
826 options.SetKeepInMemory(false);
827 options.SetRunOthers(true);
828
829 ExecutionResults expr_result = target->EvaluateExpression(s,
830 exe_ctx->GetFramePtr(),
831 valobj_sp,
832 options);
833
834 bool success = false;
835 if (expr_result == eExecutionCompleted)
836 {
837 // Get the address to watch.
838 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
839 if (success)
840 {
841 if (error_ptr)
842 error_ptr->Clear();
843 return addr;
844 }
845 else
846 {
847 if (error_ptr)
848 {
849 error_set = true;
850 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());
851 }
852 }
853
854 }
855 else
856 {
857 // Since the compiler can't handle things like "main + 12" we should
858 // try to do this for now. The compliler doesn't like adding offsets
859 // to function pointer types.
Greg Claytonbc43cab2013-04-03 21:37:16 +0000860 static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
861 RegularExpression::Match regex_match(3);
862 if (g_symbol_plus_offset_regex.Execute(s, &regex_match))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000863 {
864 uint64_t offset = 0;
865 bool add = true;
866 std::string name;
867 std::string str;
Greg Claytonbc43cab2013-04-03 21:37:16 +0000868 if (regex_match.GetMatchAtIndex(s, 1, name))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000869 {
Greg Claytonbc43cab2013-04-03 21:37:16 +0000870 if (regex_match.GetMatchAtIndex(s, 2, str))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000871 {
872 add = str[0] == '+';
873
Greg Claytonbc43cab2013-04-03 21:37:16 +0000874 if (regex_match.GetMatchAtIndex(s, 3, str))
Greg Claytonb9d5df52012-12-06 22:49:16 +0000875 {
876 offset = Args::StringToUInt64(str.c_str(), 0, 0, &success);
877
878 if (success)
879 {
880 Error error;
881 addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
882 if (addr != LLDB_INVALID_ADDRESS)
883 {
884 if (add)
885 return addr + offset;
886 else
887 return addr - offset;
888 }
889 }
890 }
891 }
892 }
893 }
894
895 if (error_ptr)
896 {
897 error_set = true;
898 error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
899 }
900 }
901 }
902 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000903 }
Greg Claytonb9d5df52012-12-06 22:49:16 +0000904 if (error_ptr)
905 {
906 if (!error_set)
907 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
908 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000909 return fail_value;
910}
911
Greg Clayton30820f02013-03-05 23:52:49 +0000912const char *
913Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
914{
915 static const char *k_white_space = " \t\v";
916 if (!s.empty())
917 {
918 if (leading)
919 {
920 size_t pos = s.find_first_not_of (k_white_space);
921 if (pos == std::string::npos)
922 s.clear();
923 else if (pos > 0)
924 s.erase(0, pos);
925 }
926
927 if (trailing)
928 {
929 size_t rpos = s.find_last_not_of(k_white_space);
930 if (rpos != std::string::npos && rpos + 1 < s.size())
931 s.erase(rpos + 1);
932 }
933 }
934 if (return_null_if_empty && s.empty())
935 return NULL;
936 return s.c_str();
937}
938
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000939bool
940Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
941{
942 if (s && s[0])
943 {
944 if (::strcasecmp (s, "false") == 0 ||
945 ::strcasecmp (s, "off") == 0 ||
946 ::strcasecmp (s, "no") == 0 ||
947 ::strcmp (s, "0") == 0)
948 {
949 if (success_ptr)
950 *success_ptr = true;
951 return false;
952 }
953 else
954 if (::strcasecmp (s, "true") == 0 ||
955 ::strcasecmp (s, "on") == 0 ||
956 ::strcasecmp (s, "yes") == 0 ||
957 ::strcmp (s, "1") == 0)
958 {
959 if (success_ptr) *success_ptr = true;
960 return true;
961 }
962 }
963 if (success_ptr) *success_ptr = false;
964 return fail_value;
965}
966
Greg Claytonded470d2011-03-19 01:12:21 +0000967const char *
968Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
969{
970 major = UINT32_MAX;
971 minor = UINT32_MAX;
972 update = UINT32_MAX;
973
974 if (s && s[0])
975 {
976 char *pos = NULL;
Greg Claytonc7bece562013-01-25 18:06:21 +0000977 unsigned long uval32 = ::strtoul (s, &pos, 0);
Greg Claytonded470d2011-03-19 01:12:21 +0000978 if (pos == s)
979 return s;
980 major = uval32;
981 if (*pos == '\0')
982 {
983 return pos; // Decoded major and got end of string
984 }
985 else if (*pos == '.')
986 {
987 const char *minor_cstr = pos + 1;
988 uval32 = ::strtoul (minor_cstr, &pos, 0);
989 if (pos == minor_cstr)
990 return pos; // Didn't get any digits for the minor version...
991 minor = uval32;
992 if (*pos == '.')
993 {
994 const char *update_cstr = pos + 1;
995 uval32 = ::strtoul (update_cstr, &pos, 0);
996 if (pos == update_cstr)
997 return pos;
998 update = uval32;
999 }
1000 return pos;
1001 }
1002 }
1003 return 0;
1004}
1005
Greg Clayton144f3a92011-11-15 03:53:30 +00001006const char *
1007Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
1008{
1009 safe_arg.assign (unsafe_arg);
1010 size_t prev_pos = 0;
1011 while (prev_pos < safe_arg.size())
1012 {
1013 // Escape spaces and quotes
1014 size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
1015 if (pos != std::string::npos)
1016 {
1017 safe_arg.insert (pos, 1, '\\');
1018 prev_pos = pos + 2;
1019 }
1020 else
1021 break;
1022 }
1023 return safe_arg.c_str();
1024}
1025
Greg Claytonded470d2011-03-19 01:12:21 +00001026
Greg Claytonc7bece562013-01-25 18:06:21 +00001027int64_t
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001028Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001029{
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001030 if (enum_values)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001031 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001032 if (s && s[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001033 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001034 for (int i = 0; enum_values[i].string_value != NULL ; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001035 {
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001036 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
1037 {
1038 error.Clear();
1039 return enum_values[i].value;
1040 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001041 }
1042 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001043
1044 StreamString strm;
1045 strm.PutCString ("invalid enumeration value, valid values are: ");
1046 for (int i = 0; enum_values[i].string_value != NULL; i++)
1047 {
1048 strm.Printf ("%s\"%s\"",
1049 i > 0 ? ", " : "",
1050 enum_values[i].string_value);
1051 }
1052 error.SetErrorString(strm.GetData());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001053 }
Greg Claytoncf0e4f02011-10-07 18:58:12 +00001054 else
1055 {
1056 error.SetErrorString ("invalid enumeration argument");
1057 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001058 return fail_value;
1059}
1060
1061ScriptLanguage
1062Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
1063{
1064 if (s && s[0])
1065 {
1066 if ((::strcasecmp (s, "python") == 0) ||
1067 (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
1068 {
1069 if (success_ptr) *success_ptr = true;
1070 return eScriptLanguagePython;
1071 }
1072 if (::strcasecmp (s, "none"))
1073 {
1074 if (success_ptr) *success_ptr = true;
1075 return eScriptLanguageNone;
1076 }
1077 }
1078 if (success_ptr) *success_ptr = false;
1079 return fail_value;
1080}
1081
1082Error
1083Args::StringToFormat
1084(
1085 const char *s,
Greg Clayton68ebae62011-04-28 20:55:26 +00001086 lldb::Format &format,
Greg Claytonc7bece562013-01-25 18:06:21 +00001087 size_t *byte_size_ptr
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001088)
1089{
1090 format = eFormatInvalid;
1091 Error error;
1092
1093 if (s && s[0])
1094 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001095 if (byte_size_ptr)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001096 {
Greg Clayton68ebae62011-04-28 20:55:26 +00001097 if (isdigit (s[0]))
1098 {
1099 char *format_char = NULL;
1100 unsigned long byte_size = ::strtoul (s, &format_char, 0);
1101 if (byte_size != ULONG_MAX)
1102 *byte_size_ptr = byte_size;
1103 s = format_char;
1104 }
1105 else
1106 *byte_size_ptr = 0;
1107 }
1108
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001109 const bool partial_match_ok = true;
1110 if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
Greg Clayton68ebae62011-04-28 20:55:26 +00001111 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001112 StreamString error_strm;
1113 error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
Peter Collingbourne44c9b372011-06-24 01:12:22 +00001114 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
Greg Clayton68ebae62011-04-28 20:55:26 +00001115 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001116 char format_char = FormatManager::GetFormatAsFormatChar(f);
1117 if (format_char)
1118 error_strm.Printf ("'%c' or ", format_char);
1119
1120 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
1121 error_strm.EOL();
Greg Clayton68ebae62011-04-28 20:55:26 +00001122 }
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001123
1124 if (byte_size_ptr)
1125 error_strm.PutCString ("An optional byte size can precede the format character.\n");
1126 error.SetErrorString(error_strm.GetString().c_str());
Greg Clayton68ebae62011-04-28 20:55:26 +00001127 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001128
1129 if (error.Fail())
1130 return error;
1131 }
1132 else
1133 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001134 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001135 }
1136 return error;
1137}
1138
Greg Clayton2443cbd2012-08-24 01:42:50 +00001139lldb::Encoding
1140Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
1141{
1142 if (s && s[0])
1143 {
1144 if (strcmp(s, "uint") == 0)
1145 return eEncodingUint;
1146 else if (strcmp(s, "sint") == 0)
1147 return eEncodingSint;
1148 else if (strcmp(s, "ieee754") == 0)
1149 return eEncodingIEEE754;
1150 else if (strcmp(s, "vector") == 0)
1151 return eEncodingVector;
1152 }
1153 return fail_value;
1154}
1155
1156uint32_t
1157Args::StringToGenericRegister (const char *s)
1158{
1159 if (s && s[0])
1160 {
1161 if (strcmp(s, "pc") == 0)
1162 return LLDB_REGNUM_GENERIC_PC;
1163 else if (strcmp(s, "sp") == 0)
1164 return LLDB_REGNUM_GENERIC_SP;
1165 else if (strcmp(s, "fp") == 0)
1166 return LLDB_REGNUM_GENERIC_FP;
1167 else if (strcmp(s, "ra") == 0)
1168 return LLDB_REGNUM_GENERIC_RA;
1169 else if (strcmp(s, "flags") == 0)
1170 return LLDB_REGNUM_GENERIC_FLAGS;
1171 else if (strncmp(s, "arg", 3) == 0)
1172 {
1173 if (s[3] && s[4] == '\0')
1174 {
1175 switch (s[3])
1176 {
1177 case '1': return LLDB_REGNUM_GENERIC_ARG1;
1178 case '2': return LLDB_REGNUM_GENERIC_ARG2;
1179 case '3': return LLDB_REGNUM_GENERIC_ARG3;
1180 case '4': return LLDB_REGNUM_GENERIC_ARG4;
1181 case '5': return LLDB_REGNUM_GENERIC_ARG5;
1182 case '6': return LLDB_REGNUM_GENERIC_ARG6;
1183 case '7': return LLDB_REGNUM_GENERIC_ARG7;
1184 case '8': return LLDB_REGNUM_GENERIC_ARG8;
1185 }
1186 }
1187 }
1188 }
1189 return LLDB_INVALID_REGNUM;
1190}
1191
1192
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001193void
1194Args::LongestCommonPrefix (std::string &common_prefix)
1195{
1196 arg_sstr_collection::iterator pos, end = m_args.end();
1197 pos = m_args.begin();
1198 if (pos == end)
1199 common_prefix.clear();
1200 else
1201 common_prefix = (*pos);
1202
1203 for (++pos; pos != end; ++pos)
1204 {
Greg Claytonc982c762010-07-09 20:39:50 +00001205 size_t new_size = (*pos).size();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001206
1207 // First trim common_prefix if it is longer than the current element:
1208 if (common_prefix.size() > new_size)
1209 common_prefix.erase (new_size);
1210
1211 // Then trim it at the first disparity:
1212
Greg Claytonc982c762010-07-09 20:39:50 +00001213 for (size_t i = 0; i < common_prefix.size(); i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001214 {
1215 if ((*pos)[i] != common_prefix[i])
1216 {
1217 common_prefix.erase(i);
1218 break;
1219 }
1220 }
1221
1222 // If we've emptied the common prefix, we're done.
1223 if (common_prefix.empty())
1224 break;
1225 }
1226}
1227
Caroline Ticed9d63362010-12-07 19:58:26 +00001228size_t
1229Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
1230{
1231 char short_buffer[3];
1232 char long_buffer[255];
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001233 ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
Caroline Ticed9d63362010-12-07 19:58:26 +00001234 ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
1235 size_t end = GetArgumentCount ();
1236 size_t idx = 0;
1237 while (idx < end)
1238 {
1239 if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
1240 || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
1241 {
1242 return idx;
1243 }
1244 ++idx;
1245 }
1246
1247 return end;
1248}
1249
1250bool
1251Args::IsPositionalArgument (const char *arg)
1252{
1253 if (arg == NULL)
1254 return false;
1255
1256 bool is_positional = true;
1257 char *cptr = (char *) arg;
1258
1259 if (cptr[0] == '%')
1260 {
1261 ++cptr;
1262 while (isdigit (cptr[0]))
1263 ++cptr;
1264 if (cptr[0] != '\0')
1265 is_positional = false;
1266 }
1267 else
1268 is_positional = false;
1269
1270 return is_positional;
1271}
1272
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001273void
Caroline Tice636d6ed2010-10-12 17:45:19 +00001274Args::ParseAliasOptions (Options &options,
1275 CommandReturnObject &result,
Caroline Tice844d2302010-12-09 22:52:49 +00001276 OptionArgVector *option_arg_vector,
1277 std::string &raw_input_string)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001278{
1279 StreamString sstr;
1280 int i;
1281 struct option *long_options = options.GetLongOptions();
1282
1283 if (long_options == NULL)
1284 {
1285 result.AppendError ("invalid long options");
1286 result.SetStatus (eReturnStatusFailed);
1287 return;
1288 }
1289
1290 for (i = 0; long_options[i].name != NULL; ++i)
1291 {
1292 if (long_options[i].flag == NULL)
1293 {
1294 sstr << (char) long_options[i].val;
1295 switch (long_options[i].has_arg)
1296 {
1297 default:
1298 case no_argument:
1299 break;
1300 case required_argument:
1301 sstr << ":";
1302 break;
1303 case optional_argument:
1304 sstr << "::";
1305 break;
1306 }
1307 }
1308 }
1309
Eli Friedmanadb35022010-06-13 19:18:49 +00001310#ifdef __GLIBC__
1311 optind = 0;
1312#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001313 optreset = 1;
1314 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +00001315#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 int val;
1317 while (1)
1318 {
1319 int long_options_index = -1;
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001320 val = ::getopt_long_only (GetArgumentCount(),
1321 GetArgumentVector(),
1322 sstr.GetData(),
1323 long_options,
1324 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001325
1326 if (val == -1)
1327 break;
1328
1329 if (val == '?')
1330 {
1331 result.AppendError ("unknown or ambiguous option");
1332 result.SetStatus (eReturnStatusFailed);
1333 break;
1334 }
1335
1336 if (val == 0)
1337 continue;
1338
1339 ((Options *) &options)->OptionSeen (val);
1340
1341 // Look up the long option index
1342 if (long_options_index == -1)
1343 {
1344 for (int j = 0;
1345 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1346 ++j)
1347 {
1348 if (long_options[j].val == val)
1349 {
1350 long_options_index = j;
1351 break;
1352 }
1353 }
1354 }
1355
1356 // See if the option takes an argument, and see if one was supplied.
1357 if (long_options_index >= 0)
1358 {
1359 StreamString option_str;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001360 option_str.Printf ("-%c", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001361
1362 switch (long_options[long_options_index].has_arg)
1363 {
1364 case no_argument:
Caroline Ticed9d63362010-12-07 19:58:26 +00001365 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1366 OptionArgValue (no_argument, "<no-argument>")));
Caroline Tice5172e6c2010-09-12 04:48:45 +00001367 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001368 break;
1369 case required_argument:
1370 if (optarg != NULL)
1371 {
1372 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Ticed9d63362010-12-07 19:58:26 +00001373 OptionArgValue (required_argument,
1374 std::string (optarg))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001375 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1376 }
1377 else
1378 {
1379 result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1380 option_str.GetData());
1381 result.SetStatus (eReturnStatusFailed);
1382 }
1383 break;
1384 case optional_argument:
1385 if (optarg != NULL)
1386 {
1387 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Ticed9d63362010-12-07 19:58:26 +00001388 OptionArgValue (optional_argument,
1389 std::string (optarg))));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001390 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1391 }
1392 else
1393 {
1394 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Ticed9d63362010-12-07 19:58:26 +00001395 OptionArgValue (optional_argument, "<no-argument>")));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001396 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1397 }
1398 break;
1399 default:
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001400 result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001401 result.SetStatus (eReturnStatusFailed);
1402 break;
1403 }
1404 }
1405 else
1406 {
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001407 result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001408 result.SetStatus (eReturnStatusFailed);
1409 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001410
1411 if (long_options_index >= 0)
1412 {
1413 // 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 +00001414 // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
1415 // the raw_input_string, if one was passed in.
Caroline Ticed9d63362010-12-07 19:58:26 +00001416 size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1417 if (idx < GetArgumentCount())
1418 {
Caroline Tice844d2302010-12-09 22:52:49 +00001419 if (raw_input_string.size() > 0)
1420 {
1421 const char *tmp_arg = GetArgumentAtIndex (idx);
1422 size_t pos = raw_input_string.find (tmp_arg);
1423 if (pos != std::string::npos)
1424 raw_input_string.erase (pos, strlen (tmp_arg));
1425 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001426 ReplaceArgumentAtIndex (idx, "");
1427 if ((long_options[long_options_index].has_arg != no_argument)
1428 && (optarg != NULL)
1429 && (idx+1 < GetArgumentCount())
1430 && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
Caroline Tice844d2302010-12-09 22:52:49 +00001431 {
1432 if (raw_input_string.size() > 0)
1433 {
1434 const char *tmp_arg = GetArgumentAtIndex (idx+1);
1435 size_t pos = raw_input_string.find (tmp_arg);
1436 if (pos != std::string::npos)
1437 raw_input_string.erase (pos, strlen (tmp_arg));
1438 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001439 ReplaceArgumentAtIndex (idx+1, "");
Caroline Tice844d2302010-12-09 22:52:49 +00001440 }
Caroline Ticed9d63362010-12-07 19:58:26 +00001441 }
Caroline Tice636d6ed2010-10-12 17:45:19 +00001442 }
1443
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001444 if (!result.Succeeded())
1445 break;
1446 }
1447}
1448
1449void
1450Args::ParseArgsForCompletion
1451(
1452 Options &options,
Jim Inghamd43e0092010-06-24 20:31:04 +00001453 OptionElementVector &option_element_vector,
1454 uint32_t cursor_index
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001455)
1456{
1457 StreamString sstr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001458 struct option *long_options = options.GetLongOptions();
1459 option_element_vector.clear();
1460
1461 if (long_options == NULL)
1462 {
1463 return;
1464 }
1465
1466 // Leading : tells getopt to return a : for a missing option argument AND
1467 // to suppress error messages.
1468
1469 sstr << ":";
Greg Claytonb1320972010-07-14 00:18:15 +00001470 for (int i = 0; long_options[i].name != NULL; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001471 {
1472 if (long_options[i].flag == NULL)
1473 {
1474 sstr << (char) long_options[i].val;
1475 switch (long_options[i].has_arg)
1476 {
1477 default:
1478 case no_argument:
1479 break;
1480 case required_argument:
1481 sstr << ":";
1482 break;
1483 case optional_argument:
1484 sstr << "::";
1485 break;
1486 }
1487 }
1488 }
1489
Eli Friedmanadb35022010-06-13 19:18:49 +00001490#ifdef __GLIBC__
1491 optind = 0;
1492#else
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001493 optreset = 1;
1494 optind = 1;
Eli Friedmanadb35022010-06-13 19:18:49 +00001495#endif
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001496 opterr = 0;
1497
1498 int val;
1499 const OptionDefinition *opt_defs = options.GetDefinitions();
1500
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001501 // Fooey... getopt_long_only permutes the GetArgumentVector to move the options to the front.
1502 // So we have to build another Arg and pass that to getopt_long_only so it doesn't
Jim Inghamd43e0092010-06-24 20:31:04 +00001503 // change the one we have.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001504
Greg Claytonc982c762010-07-09 20:39:50 +00001505 std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001506
Jim Inghamd43e0092010-06-24 20:31:04 +00001507 bool failed_once = false;
1508 uint32_t dash_dash_pos = -1;
1509
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001510 while (1)
1511 {
1512 bool missing_argument = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001513 int long_options_index = -1;
Jim Inghamd43e0092010-06-24 20:31:04 +00001514
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001515 val = ::getopt_long_only (dummy_vec.size() - 1,
1516 (char *const *) &dummy_vec.front(),
1517 sstr.GetData(),
1518 long_options,
1519 &long_options_index);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001520
1521 if (val == -1)
Jim Inghamd43e0092010-06-24 20:31:04 +00001522 {
1523 // When we're completing a "--" which is the last option on line,
1524 if (failed_once)
1525 break;
1526
1527 failed_once = true;
1528
1529 // If this is a bare "--" we mark it as such so we can complete it successfully later.
1530 // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1531 // user might want to complete options by long name. I make this work by checking whether the
1532 // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001533 // I let it pass to getopt_long_only which will terminate the option parsing.
Jim Inghamd43e0092010-06-24 20:31:04 +00001534 // Note, in either case we continue parsing the line so we can figure out what other options
1535 // were passed. This will be useful when we come to restricting completions based on what other
1536 // options we've seen on the line.
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001537
Jim Inghamd43e0092010-06-24 20:31:04 +00001538 if (optind < dummy_vec.size() - 1
1539 && (strcmp (dummy_vec[optind-1], "--") == 0))
1540 {
1541 dash_dash_pos = optind - 1;
1542 if (optind - 1 == cursor_index)
1543 {
1544 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
1545 OptionArgElement::eBareDoubleDash));
1546 continue;
1547 }
1548 else
1549 break;
1550 }
1551 else
1552 break;
1553 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001554 else if (val == '?')
1555 {
Jim Inghamd43e0092010-06-24 20:31:04 +00001556 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1557 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001558 continue;
1559 }
1560 else if (val == 0)
1561 {
1562 continue;
1563 }
1564 else if (val == ':')
1565 {
1566 // This is a missing argument.
1567 val = optopt;
1568 missing_argument = true;
1569 }
1570
1571 ((Options *) &options)->OptionSeen (val);
1572
1573 // Look up the long option index
1574 if (long_options_index == -1)
1575 {
1576 for (int j = 0;
1577 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1578 ++j)
1579 {
1580 if (long_options[j].val == val)
1581 {
1582 long_options_index = j;
1583 break;
1584 }
1585 }
1586 }
1587
1588 // See if the option takes an argument, and see if one was supplied.
1589 if (long_options_index >= 0)
1590 {
1591 int opt_defs_index = -1;
1592 for (int i = 0; ; i++)
1593 {
1594 if (opt_defs[i].short_option == 0)
1595 break;
1596 else if (opt_defs[i].short_option == val)
1597 {
1598 opt_defs_index = i;
1599 break;
1600 }
1601 }
1602
1603 switch (long_options[long_options_index].has_arg)
1604 {
1605 case no_argument:
Daniel Malea243b3692013-04-23 15:28:10 +00001606 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, 0));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001607 break;
1608 case required_argument:
1609 if (optarg != NULL)
1610 {
1611 int arg_index;
1612 if (missing_argument)
1613 arg_index = -1;
1614 else
Jim Inghamd43e0092010-06-24 20:31:04 +00001615 arg_index = optind - 1;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001616
Jim Inghamd43e0092010-06-24 20:31:04 +00001617 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001618 }
1619 else
1620 {
Jim Inghamd43e0092010-06-24 20:31:04 +00001621 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001622 }
1623 break;
1624 case optional_argument:
1625 if (optarg != NULL)
1626 {
Jim Inghamd43e0092010-06-24 20:31:04 +00001627 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001628 }
1629 else
1630 {
Jim Inghamd43e0092010-06-24 20:31:04 +00001631 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001632 }
1633 break;
1634 default:
1635 // The options table is messed up. Here we'll just continue
Jim Inghamd43e0092010-06-24 20:31:04 +00001636 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1637 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001638 break;
1639 }
1640 }
1641 else
1642 {
Jim Inghamd43e0092010-06-24 20:31:04 +00001643 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1644 OptionArgElement::eUnrecognizedArg));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001645 }
1646 }
Jim Inghamd43e0092010-06-24 20:31:04 +00001647
1648 // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
Greg Claytonb7ad58a2013-04-04 20:35:24 +00001649 // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long_only just ignores
Jim Inghamd43e0092010-06-24 20:31:04 +00001650 // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
1651
1652 if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
1653 && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1654 {
1655 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
1656 OptionArgElement::eBareDash));
1657
1658 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001659}
Greg Clayton4c054102012-09-01 00:38:36 +00001660
1661void
1662Args::EncodeEscapeSequences (const char *src, std::string &dst)
1663{
1664 dst.clear();
1665 if (src)
1666 {
1667 for (const char *p = src; *p != '\0'; ++p)
1668 {
1669 size_t non_special_chars = ::strcspn (p, "\\");
1670 if (non_special_chars > 0)
1671 {
1672 dst.append(p, non_special_chars);
1673 p += non_special_chars;
1674 if (*p == '\0')
1675 break;
1676 }
1677
1678 if (*p == '\\')
1679 {
1680 ++p; // skip the slash
1681 switch (*p)
1682 {
1683 case 'a' : dst.append(1, '\a'); break;
1684 case 'b' : dst.append(1, '\b'); break;
1685 case 'f' : dst.append(1, '\f'); break;
1686 case 'n' : dst.append(1, '\n'); break;
1687 case 'r' : dst.append(1, '\r'); break;
1688 case 't' : dst.append(1, '\t'); break;
1689 case 'v' : dst.append(1, '\v'); break;
1690 case '\\': dst.append(1, '\\'); break;
1691 case '\'': dst.append(1, '\''); break;
1692 case '"' : dst.append(1, '"'); break;
1693 case '0' :
1694 // 1 to 3 octal chars
1695 {
1696 // Make a string that can hold onto the initial zero char,
1697 // up to 3 octal digits, and a terminating NULL.
1698 char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
1699
1700 int i;
1701 for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
1702 oct_str[i] = p[i];
1703
1704 // We don't want to consume the last octal character since
1705 // the main for loop will do this for us, so we advance p by
1706 // one less than i (even if i is zero)
1707 p += i - 1;
1708 unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
1709 if (octal_value <= UINT8_MAX)
1710 {
Greg Claytonc7bece562013-01-25 18:06:21 +00001711 dst.append(1, (char)octal_value);
Greg Clayton4c054102012-09-01 00:38:36 +00001712 }
1713 }
1714 break;
1715
1716 case 'x':
1717 // hex number in the format
1718 if (isxdigit(p[1]))
1719 {
1720 ++p; // Skip the 'x'
1721
1722 // Make a string that can hold onto two hex chars plus a
1723 // NULL terminator
1724 char hex_str[3] = { *p, '\0', '\0' };
1725 if (isxdigit(p[1]))
1726 {
1727 ++p; // Skip the first of the two hex chars
1728 hex_str[1] = *p;
1729 }
1730
1731 unsigned long hex_value = strtoul (hex_str, NULL, 16);
1732 if (hex_value <= UINT8_MAX)
1733 dst.append (1, (char)hex_value);
1734 }
1735 else
1736 {
1737 dst.append(1, 'x');
1738 }
1739 break;
1740
1741 default:
1742 // Just desensitize any other character by just printing what
1743 // came after the '\'
1744 dst.append(1, *p);
1745 break;
1746
1747 }
1748 }
1749 }
1750 }
1751}
1752
1753
1754void
1755Args::ExpandEscapedCharacters (const char *src, std::string &dst)
1756{
1757 dst.clear();
1758 if (src)
1759 {
1760 for (const char *p = src; *p != '\0'; ++p)
1761 {
Daniel Malea90b0c842012-12-05 20:24:57 +00001762 if (isprint8(*p))
Greg Clayton4c054102012-09-01 00:38:36 +00001763 dst.append(1, *p);
1764 else
1765 {
1766 switch (*p)
1767 {
1768 case '\a': dst.append("\\a"); break;
1769 case '\b': dst.append("\\b"); break;
1770 case '\f': dst.append("\\f"); break;
1771 case '\n': dst.append("\\n"); break;
1772 case '\r': dst.append("\\r"); break;
1773 case '\t': dst.append("\\t"); break;
1774 case '\v': dst.append("\\v"); break;
1775 case '\'': dst.append("\\'"); break;
1776 case '"': dst.append("\\\""); break;
1777 case '\\': dst.append("\\\\"); break;
1778 default:
1779 {
1780 // Just encode as octal
1781 dst.append("\\0");
1782 char octal_str[32];
1783 snprintf(octal_str, sizeof(octal_str), "%o", *p);
1784 dst.append(octal_str);
1785 }
1786 break;
1787 }
1788 }
1789 }
1790 }
1791}
1792