blob: dfd01ee1565b4896619ada95f136ae02c6ec2b32 [file] [log] [blame]
Chris Lattner24943d22010-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
10// C Includes
11#include <getopt.h>
Eli Friedman27cd8892010-06-09 10:59:23 +000012#include <cstdlib>
Chris Lattner24943d22010-06-08 16:52:24 +000013// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
Greg Clayton3182eff2011-06-23 21:22:24 +000017#include "lldb/Core/FormatManager.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/Stream.h"
19#include "lldb/Core/StreamFile.h"
20#include "lldb/Core/StreamString.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000021#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
23
Chris Lattner24943d22010-06-08 16:52:24 +000024using namespace lldb;
25using namespace lldb_private;
26
Chris Lattner24943d22010-06-08 16:52:24 +000027//----------------------------------------------------------------------
28// Args constructor
29//----------------------------------------------------------------------
30Args::Args (const char *command) :
31 m_args(),
Greg Claytonb72d0f02011-04-12 05:54:46 +000032 m_argv(),
33 m_args_quote_char()
Chris Lattner24943d22010-06-08 16:52:24 +000034{
Greg Clayton928d1302010-12-19 03:41:24 +000035 if (command)
36 SetCommandString (command);
Chris Lattner24943d22010-06-08 16:52:24 +000037}
38
39
40Args::Args (const char *command, size_t len) :
41 m_args(),
Greg Claytonb72d0f02011-04-12 05:54:46 +000042 m_argv(),
43 m_args_quote_char()
Chris Lattner24943d22010-06-08 16:52:24 +000044{
Greg Clayton928d1302010-12-19 03:41:24 +000045 if (command && len)
46 SetCommandString (command, len);
Chris Lattner24943d22010-06-08 16:52:24 +000047}
48
Chris Lattner24943d22010-06-08 16:52:24 +000049//----------------------------------------------------------------------
Greg Claytonb72d0f02011-04-12 05:54:46 +000050// We have to be very careful on the copy constructor of this class
51// to make sure we copy all of the string values, but we can't copy the
52// rhs.m_argv into m_argv since it will point to the "const char *" c
53// strings in rhs.m_args. We need to copy the string list and update our
54// own m_argv appropriately.
55//----------------------------------------------------------------------
56Args::Args (const Args &rhs) :
57 m_args (rhs.m_args),
58 m_argv (),
59 m_args_quote_char(rhs.m_args_quote_char)
60{
61 UpdateArgvFromArgs();
62}
63
64//----------------------------------------------------------------------
65// We have to be very careful on the copy constructor of this class
66// to make sure we copy all of the string values, but we can't copy the
67// rhs.m_argv into m_argv since it will point to the "const char *" c
68// strings in rhs.m_args. We need to copy the string list and update our
69// own m_argv appropriately.
70//----------------------------------------------------------------------
71const Args &
72Args::operator= (const Args &rhs)
73{
74 // Make sure we aren't assigning to self
75 if (this != &rhs)
76 {
77 m_args = rhs.m_args;
78 m_args_quote_char = rhs.m_args_quote_char;
79 UpdateArgvFromArgs();
80 }
81 return *this;
82}
83
84//----------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +000085// Destructor
86//----------------------------------------------------------------------
87Args::~Args ()
88{
89}
90
91void
92Args::Dump (Stream *s)
93{
94// int argc = GetArgumentCount();
95//
96// arg_sstr_collection::const_iterator pos, begin = m_args.begin(), end = m_args.end();
97// for (pos = m_args.begin(); pos != end; ++pos)
98// {
99// s->Indent();
100// s->Printf("args[%zu]=%s\n", std::distance(begin, pos), pos->c_str());
101// }
102// s->EOL();
103 const int argc = m_argv.size();
104 for (int i=0; i<argc; ++i)
105 {
106 s->Indent();
107 const char *arg_cstr = m_argv[i];
108 if (arg_cstr)
109 s->Printf("argv[%i]=\"%s\"\n", i, arg_cstr);
110 else
111 s->Printf("argv[%i]=NULL\n", i);
112 }
113 s->EOL();
114}
115
116bool
117Args::GetCommandString (std::string &command)
118{
119 command.clear();
120 int argc = GetArgumentCount();
121 for (int i=0; i<argc; ++i)
122 {
123 if (i > 0)
124 command += ' ';
125 command += m_argv[i];
126 }
127 return argc > 0;
128}
129
Caroline Ticed9105c22010-12-10 00:26:54 +0000130bool
131Args::GetQuotedCommandString (std::string &command)
132{
133 command.clear ();
Greg Clayton928d1302010-12-19 03:41:24 +0000134 size_t argc = GetArgumentCount ();
135 for (size_t i = 0; i < argc; ++i)
Caroline Ticed9105c22010-12-10 00:26:54 +0000136 {
137 if (i > 0)
Greg Clayton928d1302010-12-19 03:41:24 +0000138 command.append (1, ' ');
139 char quote_char = GetArgumentQuoteCharAtIndex(i);
140 if (quote_char)
Caroline Ticed9105c22010-12-10 00:26:54 +0000141 {
Greg Clayton928d1302010-12-19 03:41:24 +0000142 command.append (1, quote_char);
143 command.append (m_argv[i]);
144 command.append (1, quote_char);
Caroline Ticed9105c22010-12-10 00:26:54 +0000145 }
146 else
Greg Clayton928d1302010-12-19 03:41:24 +0000147 command.append (m_argv[i]);
Caroline Ticed9105c22010-12-10 00:26:54 +0000148 }
149 return argc > 0;
150}
151
Chris Lattner24943d22010-06-08 16:52:24 +0000152void
153Args::SetCommandString (const char *command, size_t len)
154{
155 // Use std::string to make sure we get a NULL terminated string we can use
156 // as "command" could point to a string within a large string....
157 std::string null_terminated_command(command, len);
158 SetCommandString(null_terminated_command.c_str());
159}
160
161void
162Args::SetCommandString (const char *command)
163{
164 m_args.clear();
165 m_argv.clear();
Greg Clayton928d1302010-12-19 03:41:24 +0000166 m_args_quote_char.clear();
167
Chris Lattner24943d22010-06-08 16:52:24 +0000168 if (command && command[0])
169 {
Greg Clayton928d1302010-12-19 03:41:24 +0000170 static const char *k_space_separators = " \t";
Johnny Chena1b0ce12012-01-19 19:22:41 +0000171 static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
Greg Clayton928d1302010-12-19 03:41:24 +0000172 const char *arg_end = NULL;
173 const char *arg_pos;
174 for (arg_pos = command;
175 arg_pos && arg_pos[0];
176 arg_pos = arg_end)
Chris Lattner24943d22010-06-08 16:52:24 +0000177 {
Greg Clayton928d1302010-12-19 03:41:24 +0000178 // Skip any leading space separators
179 const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
180
181 // If there were only space separators to the end of the line, then
Chris Lattner24943d22010-06-08 16:52:24 +0000182 // we're done.
183 if (*arg_start == '\0')
184 break;
185
Greg Clayton5d187e52011-01-08 20:28:42 +0000186 // Arguments can be split into multiple discontiguous pieces,
Greg Clayton928d1302010-12-19 03:41:24 +0000187 // for example:
188 // "Hello ""World"
189 // this would result in a single argument "Hello World" (without/
190 // the quotes) since the quotes would be removed and there is
191 // not space between the strings. So we need to keep track of the
192 // current start of each argument piece in "arg_piece_start"
193 const char *arg_piece_start = arg_start;
194 arg_pos = arg_piece_start;
195
Chris Lattner24943d22010-06-08 16:52:24 +0000196 std::string arg;
Greg Clayton928d1302010-12-19 03:41:24 +0000197 // Since we can have multiple quotes that form a single command
198 // in a command like: "Hello "world'!' (which will make a single
199 // argument "Hello world!") we remember the first quote character
200 // we encounter and use that for the quote character.
201 char first_quote_char = '\0';
202 char quote_char = '\0';
203 bool arg_complete = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000204
Greg Clayton928d1302010-12-19 03:41:24 +0000205 do
Chris Lattner24943d22010-06-08 16:52:24 +0000206 {
Greg Clayton928d1302010-12-19 03:41:24 +0000207 arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
208
209 switch (arg_end[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000210 {
Greg Clayton928d1302010-12-19 03:41:24 +0000211 default:
212 assert (!"Unhandled case statement, we must handle this...");
213 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000214
Greg Clayton928d1302010-12-19 03:41:24 +0000215 case '\0':
216 // End of C string
217 if (arg_piece_start && arg_piece_start[0])
218 arg.append (arg_piece_start);
219 arg_complete = true;
220 break;
221
222 case '\\':
223 // Backslash character
224 switch (arg_end[1])
Chris Lattner24943d22010-06-08 16:52:24 +0000225 {
Greg Clayton928d1302010-12-19 03:41:24 +0000226 case '\0':
227 arg.append (arg_piece_start);
228 arg_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000229 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000230
Greg Clayton928d1302010-12-19 03:41:24 +0000231 default:
232 arg_pos = arg_end + 2;
233 break;
234 }
235 break;
236
237 case '"':
238 case '\'':
239 case '`':
240 // Quote characters
241 if (quote_char)
242 {
243 // We found a quote character while inside a quoted
244 // character argument. If it matches our current quote
245 // character, this ends the effect of the quotes. If it
246 // doesn't we ignore it.
247 if (quote_char == arg_end[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000248 {
Greg Clayton928d1302010-12-19 03:41:24 +0000249 arg.append (arg_piece_start, arg_end - arg_piece_start);
250 // Clear the quote character and let parsing
251 // continue (we need to watch for things like:
252 // "Hello ""World"
253 // "Hello "World
254 // "Hello "'World'
255 // All of which will result in a single argument "Hello World"
256 quote_char = '\0'; // Note that we are no longer inside quotes
257 arg_pos = arg_end + 1; // Skip the quote character
258 arg_piece_start = arg_pos; // Note we are starting from later in the string
259 }
260 else
261 {
262 // different quote, skip it and keep going
263 arg_pos = arg_end + 1;
264 }
265 }
266 else
267 {
268 // We found the start of a quote scope.
Greg Clayton5d187e52011-01-08 20:28:42 +0000269 // Make sure there isn't a string that precedes
Greg Clayton928d1302010-12-19 03:41:24 +0000270 // the start of a quote scope like:
271 // Hello" World"
272 // If so, then add the "Hello" to the arg
273 if (arg_end > arg_piece_start)
274 arg.append (arg_piece_start, arg_end - arg_piece_start);
275
276 // Enter into a quote scope
277 quote_char = arg_end[0];
278
279 if (first_quote_char == '\0')
280 first_quote_char = quote_char;
281
282 arg_pos = arg_end;
Johnny Chena1b0ce12012-01-19 19:22:41 +0000283 ++arg_pos; // Skip the quote character
Greg Clayton928d1302010-12-19 03:41:24 +0000284 arg_piece_start = arg_pos; // Note we are starting from later in the string
285
286 // Skip till the next quote character
287 const char *end_quote = ::strchr (arg_piece_start, quote_char);
288 while (end_quote && end_quote[-1] == '\\')
289 {
290 // Don't skip the quote character if it is
291 // preceded by a '\' character
292 end_quote = ::strchr (end_quote + 1, quote_char);
293 }
294
295 if (end_quote)
296 {
297 if (end_quote > arg_piece_start)
Johnny Chena1b0ce12012-01-19 19:22:41 +0000298 arg.append (arg_piece_start, end_quote - arg_piece_start);
Greg Clayton928d1302010-12-19 03:41:24 +0000299
300 // If the next character is a space or the end of
301 // string, this argument is complete...
302 if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
303 {
304 arg_complete = true;
305 arg_end = end_quote + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000306 }
307 else
308 {
Greg Clayton928d1302010-12-19 03:41:24 +0000309 arg_pos = end_quote + 1;
310 arg_piece_start = arg_pos;
Chris Lattner24943d22010-06-08 16:52:24 +0000311 }
Greg Clayton928d1302010-12-19 03:41:24 +0000312 quote_char = '\0';
Chris Lattner24943d22010-06-08 16:52:24 +0000313 }
314 }
Greg Clayton928d1302010-12-19 03:41:24 +0000315 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000316
Greg Clayton928d1302010-12-19 03:41:24 +0000317 case ' ':
318 case '\t':
319 if (quote_char)
Chris Lattner24943d22010-06-08 16:52:24 +0000320 {
Greg Clayton928d1302010-12-19 03:41:24 +0000321 // We are currently processing a quoted character and found
322 // a space character, skip any spaces and keep trying to find
323 // the end of the argument.
324 arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
Chris Lattner24943d22010-06-08 16:52:24 +0000325 }
Greg Clayton928d1302010-12-19 03:41:24 +0000326 else
Chris Lattner24943d22010-06-08 16:52:24 +0000327 {
Greg Clayton928d1302010-12-19 03:41:24 +0000328 // We are not inside any quotes, we just found a space after an
329 // argument
330 if (arg_end > arg_piece_start)
331 arg.append (arg_piece_start, arg_end - arg_piece_start);
332 arg_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000333 }
Greg Clayton928d1302010-12-19 03:41:24 +0000334 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000335 }
Greg Clayton928d1302010-12-19 03:41:24 +0000336 } while (!arg_complete);
Chris Lattner24943d22010-06-08 16:52:24 +0000337
338 m_args.push_back(arg);
Greg Clayton928d1302010-12-19 03:41:24 +0000339 m_args_quote_char.push_back (first_quote_char);
Chris Lattner24943d22010-06-08 16:52:24 +0000340 }
Greg Clayton928d1302010-12-19 03:41:24 +0000341 UpdateArgvFromArgs();
Chris Lattner24943d22010-06-08 16:52:24 +0000342 }
Chris Lattner24943d22010-06-08 16:52:24 +0000343}
344
345void
346Args::UpdateArgsAfterOptionParsing()
347{
348 // Now m_argv might be out of date with m_args, so we need to fix that
349 arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
350 arg_sstr_collection::iterator args_pos;
351 arg_quote_char_collection::iterator quotes_pos;
352
353 for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
354 argv_pos != argv_end && args_pos != m_args.end();
355 ++argv_pos)
356 {
357 const char *argv_cstr = *argv_pos;
358 if (argv_cstr == NULL)
359 break;
360
361 while (args_pos != m_args.end())
362 {
363 const char *args_cstr = args_pos->c_str();
364 if (args_cstr == argv_cstr)
365 {
366 // We found the argument that matches the C string in the
367 // vector, so we can now look for the next one
368 ++args_pos;
369 ++quotes_pos;
370 break;
371 }
372 else
373 {
374 quotes_pos = m_args_quote_char.erase (quotes_pos);
375 args_pos = m_args.erase (args_pos);
376 }
377 }
378 }
379
380 if (args_pos != m_args.end())
381 m_args.erase (args_pos, m_args.end());
382
383 if (quotes_pos != m_args_quote_char.end())
384 m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
385}
386
387void
388Args::UpdateArgvFromArgs()
389{
390 m_argv.clear();
391 arg_sstr_collection::const_iterator pos, end = m_args.end();
392 for (pos = m_args.begin(); pos != end; ++pos)
393 m_argv.push_back(pos->c_str());
394 m_argv.push_back(NULL);
Greg Clayton928d1302010-12-19 03:41:24 +0000395 // Make sure we have enough arg quote chars in the array
396 if (m_args_quote_char.size() < m_args.size())
397 m_args_quote_char.resize (m_argv.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000398}
399
400size_t
401Args::GetArgumentCount() const
402{
403 if (m_argv.empty())
404 return 0;
405 return m_argv.size() - 1;
406}
407
408const char *
409Args::GetArgumentAtIndex (size_t idx) const
410{
411 if (idx < m_argv.size())
412 return m_argv[idx];
413 return NULL;
414}
415
416char
417Args::GetArgumentQuoteCharAtIndex (size_t idx) const
418{
419 if (idx < m_args_quote_char.size())
420 return m_args_quote_char[idx];
421 return '\0';
422}
423
424char **
425Args::GetArgumentVector()
426{
427 if (!m_argv.empty())
428 return (char **)&m_argv[0];
429 return NULL;
430}
431
432const char **
433Args::GetConstArgumentVector() const
434{
435 if (!m_argv.empty())
436 return (const char **)&m_argv[0];
437 return NULL;
438}
439
440void
441Args::Shift ()
442{
443 // Don't pop the last NULL terminator from the argv array
444 if (m_argv.size() > 1)
445 {
446 m_argv.erase(m_argv.begin());
447 m_args.pop_front();
Greg Clayton928d1302010-12-19 03:41:24 +0000448 if (!m_args_quote_char.empty())
449 m_args_quote_char.erase(m_args_quote_char.begin());
Chris Lattner24943d22010-06-08 16:52:24 +0000450 }
451}
452
453const char *
454Args::Unshift (const char *arg_cstr, char quote_char)
455{
456 m_args.push_front(arg_cstr);
457 m_argv.insert(m_argv.begin(), m_args.front().c_str());
458 m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
459 return GetArgumentAtIndex (0);
460}
461
462void
463Args::AppendArguments (const Args &rhs)
464{
465 const size_t rhs_argc = rhs.GetArgumentCount();
466 for (size_t i=0; i<rhs_argc; ++i)
467 AppendArgument(rhs.GetArgumentAtIndex(i));
468}
469
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000470void
471Args::AppendArguments (const char **argv)
472{
473 if (argv)
474 {
475 for (uint32_t i=0; argv[i]; ++i)
476 AppendArgument(argv[i]);
477 }
478}
479
Chris Lattner24943d22010-06-08 16:52:24 +0000480const char *
481Args::AppendArgument (const char *arg_cstr, char quote_char)
482{
483 return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
484}
485
486const char *
487Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
488{
489 // Since we are using a std::list to hold onto the copied C string and
490 // we don't have direct access to the elements, we have to iterate to
491 // find the value.
492 arg_sstr_collection::iterator pos, end = m_args.end();
493 size_t i = idx;
494 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
495 --i;
496
497 pos = m_args.insert(pos, arg_cstr);
498
Greg Clayton928d1302010-12-19 03:41:24 +0000499 if (idx >= m_args_quote_char.size())
500 {
501 m_args_quote_char.resize(idx + 1);
502 m_args_quote_char[idx] = quote_char;
503 }
504 else
505 m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
Chris Lattner24943d22010-06-08 16:52:24 +0000506
507 UpdateArgvFromArgs();
508 return GetArgumentAtIndex(idx);
509}
510
511const char *
512Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
513{
514 // Since we are using a std::list to hold onto the copied C string and
515 // we don't have direct access to the elements, we have to iterate to
516 // find the value.
517 arg_sstr_collection::iterator pos, end = m_args.end();
518 size_t i = idx;
519 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
520 --i;
521
522 if (pos != end)
523 {
524 pos->assign(arg_cstr);
525 assert(idx < m_argv.size() - 1);
526 m_argv[idx] = pos->c_str();
Greg Clayton928d1302010-12-19 03:41:24 +0000527 if (idx >= m_args_quote_char.size())
528 m_args_quote_char.resize(idx + 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000529 m_args_quote_char[idx] = quote_char;
530 return GetArgumentAtIndex(idx);
531 }
532 return NULL;
533}
534
535void
536Args::DeleteArgumentAtIndex (size_t idx)
537{
538 // Since we are using a std::list to hold onto the copied C string and
539 // we don't have direct access to the elements, we have to iterate to
540 // find the value.
541 arg_sstr_collection::iterator pos, end = m_args.end();
542 size_t i = idx;
543 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
544 --i;
545
546 if (pos != end)
547 {
548 m_args.erase (pos);
549 assert(idx < m_argv.size() - 1);
550 m_argv.erase(m_argv.begin() + idx);
Greg Clayton928d1302010-12-19 03:41:24 +0000551 if (idx < m_args_quote_char.size())
552 m_args_quote_char.erase(m_args_quote_char.begin() + idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000553 }
554}
555
556void
557Args::SetArguments (int argc, const char **argv)
558{
559 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
560 // no need to clear it here.
561 m_args.clear();
562 m_args_quote_char.clear();
563
Chris Lattner24943d22010-06-08 16:52:24 +0000564 // First copy each string
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000565 for (size_t i=0; i<argc; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000566 {
567 m_args.push_back (argv[i]);
Greg Clayton928d1302010-12-19 03:41:24 +0000568 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
Chris Lattner24943d22010-06-08 16:52:24 +0000569 m_args_quote_char.push_back (argv[i][0]);
570 else
571 m_args_quote_char.push_back ('\0');
572 }
573
574 UpdateArgvFromArgs();
575}
576
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000577void
578Args::SetArguments (const char **argv)
579{
580 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
581 // no need to clear it here.
582 m_args.clear();
583 m_args_quote_char.clear();
584
585 if (argv)
586 {
587 // First copy each string
588 for (size_t i=0; argv[i]; ++i)
589 {
590 m_args.push_back (argv[i]);
591 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
592 m_args_quote_char.push_back (argv[i][0]);
593 else
594 m_args_quote_char.push_back ('\0');
595 }
596 }
597
598 UpdateArgvFromArgs();
599}
600
Chris Lattner24943d22010-06-08 16:52:24 +0000601
602Error
603Args::ParseOptions (Options &options)
604{
605 StreamString sstr;
Chris Lattner24943d22010-06-08 16:52:24 +0000606 Error error;
607 struct option *long_options = options.GetLongOptions();
608 if (long_options == NULL)
609 {
Greg Clayton9c236732011-10-26 00:56:27 +0000610 error.SetErrorStringWithFormat("invalid long options");
Chris Lattner24943d22010-06-08 16:52:24 +0000611 return error;
612 }
613
Greg Claytonbef15832010-07-14 00:18:15 +0000614 for (int i=0; long_options[i].name != NULL; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000615 {
616 if (long_options[i].flag == NULL)
617 {
618 sstr << (char)long_options[i].val;
619 switch (long_options[i].has_arg)
620 {
621 default:
622 case no_argument: break;
623 case required_argument: sstr << ':'; break;
624 case optional_argument: sstr << "::"; break;
625 }
626 }
627 }
Eli Friedmanef2bc872010-06-13 19:18:49 +0000628#ifdef __GLIBC__
629 optind = 0;
630#else
Chris Lattner24943d22010-06-08 16:52:24 +0000631 optreset = 1;
632 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000633#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000634 int val;
635 while (1)
636 {
637 int long_options_index = -1;
638 val = ::getopt_long(GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
639 &long_options_index);
640 if (val == -1)
641 break;
642
643 // Did we get an error?
644 if (val == '?')
645 {
Greg Clayton9c236732011-10-26 00:56:27 +0000646 error.SetErrorStringWithFormat("unknown or ambiguous option");
Chris Lattner24943d22010-06-08 16:52:24 +0000647 break;
648 }
649 // The option auto-set itself
650 if (val == 0)
651 continue;
652
653 ((Options *) &options)->OptionSeen (val);
654
655 // Lookup the long option index
656 if (long_options_index == -1)
657 {
658 for (int i=0;
659 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
660 ++i)
661 {
662 if (long_options[i].val == val)
663 {
664 long_options_index = i;
665 break;
666 }
667 }
668 }
669 // Call the callback with the option
670 if (long_options_index >= 0)
671 {
672 error = options.SetOptionValue(long_options_index,
673 long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
674 }
675 else
676 {
Greg Clayton9c236732011-10-26 00:56:27 +0000677 error.SetErrorStringWithFormat("invalid option with value '%i'", val);
Chris Lattner24943d22010-06-08 16:52:24 +0000678 }
679 if (error.Fail())
680 break;
681 }
682
683 // Update our ARGV now that get options has consumed all the options
684 m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
685 UpdateArgsAfterOptionParsing ();
686 return error;
687}
688
689void
690Args::Clear ()
691{
692 m_args.clear ();
693 m_argv.clear ();
694 m_args_quote_char.clear();
695}
696
697int32_t
698Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
699{
700 if (s && s[0])
701 {
702 char *end = NULL;
703 int32_t uval = ::strtol (s, &end, base);
704 if (*end == '\0')
705 {
706 if (success_ptr) *success_ptr = true;
707 return uval; // All characters were used, return the result
708 }
709 }
710 if (success_ptr) *success_ptr = false;
711 return fail_value;
712}
713
714uint32_t
715Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
716{
717 if (s && s[0])
718 {
719 char *end = NULL;
720 uint32_t uval = ::strtoul (s, &end, base);
721 if (*end == '\0')
722 {
723 if (success_ptr) *success_ptr = true;
724 return uval; // All characters were used, return the result
725 }
726 }
727 if (success_ptr) *success_ptr = false;
728 return fail_value;
729}
730
731
732int64_t
733Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
734{
735 if (s && s[0])
736 {
737 char *end = NULL;
738 int64_t uval = ::strtoll (s, &end, base);
739 if (*end == '\0')
740 {
741 if (success_ptr) *success_ptr = true;
742 return uval; // All characters were used, return the result
743 }
744 }
745 if (success_ptr) *success_ptr = false;
746 return fail_value;
747}
748
749uint64_t
750Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
751{
752 if (s && s[0])
753 {
754 char *end = NULL;
755 uint64_t uval = ::strtoull (s, &end, base);
756 if (*end == '\0')
757 {
758 if (success_ptr) *success_ptr = true;
759 return uval; // All characters were used, return the result
760 }
761 }
762 if (success_ptr) *success_ptr = false;
763 return fail_value;
764}
765
766lldb::addr_t
767Args::StringToAddress (const char *s, lldb::addr_t fail_value, bool *success_ptr)
768{
769 if (s && s[0])
770 {
771 char *end = NULL;
772 lldb::addr_t addr = ::strtoull (s, &end, 0);
773 if (*end == '\0')
774 {
775 if (success_ptr) *success_ptr = true;
776 return addr; // All characters were used, return the result
777 }
778 // Try base 16 with no prefix...
779 addr = ::strtoull (s, &end, 16);
780 if (*end == '\0')
781 {
782 if (success_ptr) *success_ptr = true;
783 return addr; // All characters were used, return the result
784 }
785 }
786 if (success_ptr) *success_ptr = false;
787 return fail_value;
788}
789
790bool
791Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
792{
793 if (s && s[0])
794 {
795 if (::strcasecmp (s, "false") == 0 ||
796 ::strcasecmp (s, "off") == 0 ||
797 ::strcasecmp (s, "no") == 0 ||
798 ::strcmp (s, "0") == 0)
799 {
800 if (success_ptr)
801 *success_ptr = true;
802 return false;
803 }
804 else
805 if (::strcasecmp (s, "true") == 0 ||
806 ::strcasecmp (s, "on") == 0 ||
807 ::strcasecmp (s, "yes") == 0 ||
808 ::strcmp (s, "1") == 0)
809 {
810 if (success_ptr) *success_ptr = true;
811 return true;
812 }
813 }
814 if (success_ptr) *success_ptr = false;
815 return fail_value;
816}
817
Greg Claytonb1888f22011-03-19 01:12:21 +0000818const char *
819Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
820{
821 major = UINT32_MAX;
822 minor = UINT32_MAX;
823 update = UINT32_MAX;
824
825 if (s && s[0])
826 {
827 char *pos = NULL;
828 uint32_t uval32;
829 uval32 = ::strtoul (s, &pos, 0);
830 if (pos == s)
831 return s;
832 major = uval32;
833 if (*pos == '\0')
834 {
835 return pos; // Decoded major and got end of string
836 }
837 else if (*pos == '.')
838 {
839 const char *minor_cstr = pos + 1;
840 uval32 = ::strtoul (minor_cstr, &pos, 0);
841 if (pos == minor_cstr)
842 return pos; // Didn't get any digits for the minor version...
843 minor = uval32;
844 if (*pos == '.')
845 {
846 const char *update_cstr = pos + 1;
847 uval32 = ::strtoul (update_cstr, &pos, 0);
848 if (pos == update_cstr)
849 return pos;
850 update = uval32;
851 }
852 return pos;
853 }
854 }
855 return 0;
856}
857
Greg Clayton527154d2011-11-15 03:53:30 +0000858const char *
859Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
860{
861 safe_arg.assign (unsafe_arg);
862 size_t prev_pos = 0;
863 while (prev_pos < safe_arg.size())
864 {
865 // Escape spaces and quotes
866 size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
867 if (pos != std::string::npos)
868 {
869 safe_arg.insert (pos, 1, '\\');
870 prev_pos = pos + 2;
871 }
872 else
873 break;
874 }
875 return safe_arg.c_str();
876}
877
Greg Claytonb1888f22011-03-19 01:12:21 +0000878
Chris Lattner24943d22010-06-08 16:52:24 +0000879int32_t
Greg Clayton61aca5d2011-10-07 18:58:12 +0000880Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
Chris Lattner24943d22010-06-08 16:52:24 +0000881{
Greg Clayton61aca5d2011-10-07 18:58:12 +0000882 if (enum_values)
Chris Lattner24943d22010-06-08 16:52:24 +0000883 {
Greg Clayton61aca5d2011-10-07 18:58:12 +0000884 if (s && s[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000885 {
Greg Clayton61aca5d2011-10-07 18:58:12 +0000886 for (int i = 0; enum_values[i].string_value != NULL ; i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000887 {
Greg Clayton61aca5d2011-10-07 18:58:12 +0000888 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
889 {
890 error.Clear();
891 return enum_values[i].value;
892 }
Chris Lattner24943d22010-06-08 16:52:24 +0000893 }
894 }
Greg Clayton61aca5d2011-10-07 18:58:12 +0000895
896 StreamString strm;
897 strm.PutCString ("invalid enumeration value, valid values are: ");
898 for (int i = 0; enum_values[i].string_value != NULL; i++)
899 {
900 strm.Printf ("%s\"%s\"",
901 i > 0 ? ", " : "",
902 enum_values[i].string_value);
903 }
904 error.SetErrorString(strm.GetData());
Chris Lattner24943d22010-06-08 16:52:24 +0000905 }
Greg Clayton61aca5d2011-10-07 18:58:12 +0000906 else
907 {
908 error.SetErrorString ("invalid enumeration argument");
909 }
Chris Lattner24943d22010-06-08 16:52:24 +0000910 return fail_value;
911}
912
913ScriptLanguage
914Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
915{
916 if (s && s[0])
917 {
918 if ((::strcasecmp (s, "python") == 0) ||
919 (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
920 {
921 if (success_ptr) *success_ptr = true;
922 return eScriptLanguagePython;
923 }
924 if (::strcasecmp (s, "none"))
925 {
926 if (success_ptr) *success_ptr = true;
927 return eScriptLanguageNone;
928 }
929 }
930 if (success_ptr) *success_ptr = false;
931 return fail_value;
932}
933
934Error
935Args::StringToFormat
936(
937 const char *s,
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000938 lldb::Format &format,
939 uint32_t *byte_size_ptr
Chris Lattner24943d22010-06-08 16:52:24 +0000940)
941{
942 format = eFormatInvalid;
943 Error error;
944
945 if (s && s[0])
946 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000947 if (byte_size_ptr)
Chris Lattner24943d22010-06-08 16:52:24 +0000948 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000949 if (isdigit (s[0]))
950 {
951 char *format_char = NULL;
952 unsigned long byte_size = ::strtoul (s, &format_char, 0);
953 if (byte_size != ULONG_MAX)
954 *byte_size_ptr = byte_size;
955 s = format_char;
956 }
957 else
958 *byte_size_ptr = 0;
959 }
960
Greg Clayton3182eff2011-06-23 21:22:24 +0000961 const bool partial_match_ok = true;
962 if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000963 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000964 StreamString error_strm;
965 error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
Peter Collingbournef4d4fcc2011-06-24 01:12:22 +0000966 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000967 {
Greg Clayton3182eff2011-06-23 21:22:24 +0000968 char format_char = FormatManager::GetFormatAsFormatChar(f);
969 if (format_char)
970 error_strm.Printf ("'%c' or ", format_char);
971
972 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
973 error_strm.EOL();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000974 }
Greg Clayton3182eff2011-06-23 21:22:24 +0000975
976 if (byte_size_ptr)
977 error_strm.PutCString ("An optional byte size can precede the format character.\n");
978 error.SetErrorString(error_strm.GetString().c_str());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000979 }
Chris Lattner24943d22010-06-08 16:52:24 +0000980
981 if (error.Fail())
982 return error;
983 }
984 else
985 {
Greg Clayton9c236732011-10-26 00:56:27 +0000986 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
Chris Lattner24943d22010-06-08 16:52:24 +0000987 }
988 return error;
989}
990
991void
992Args::LongestCommonPrefix (std::string &common_prefix)
993{
994 arg_sstr_collection::iterator pos, end = m_args.end();
995 pos = m_args.begin();
996 if (pos == end)
997 common_prefix.clear();
998 else
999 common_prefix = (*pos);
1000
1001 for (++pos; pos != end; ++pos)
1002 {
Greg Clayton54e7afa2010-07-09 20:39:50 +00001003 size_t new_size = (*pos).size();
Chris Lattner24943d22010-06-08 16:52:24 +00001004
1005 // First trim common_prefix if it is longer than the current element:
1006 if (common_prefix.size() > new_size)
1007 common_prefix.erase (new_size);
1008
1009 // Then trim it at the first disparity:
1010
Greg Clayton54e7afa2010-07-09 20:39:50 +00001011 for (size_t i = 0; i < common_prefix.size(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +00001012 {
1013 if ((*pos)[i] != common_prefix[i])
1014 {
1015 common_prefix.erase(i);
1016 break;
1017 }
1018 }
1019
1020 // If we've emptied the common prefix, we're done.
1021 if (common_prefix.empty())
1022 break;
1023 }
1024}
1025
Caroline Tice44c841d2010-12-07 19:58:26 +00001026size_t
1027Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
1028{
1029 char short_buffer[3];
1030 char long_buffer[255];
1031 ::snprintf (short_buffer, sizeof (short_buffer), "-%c", (char) long_options[long_options_index].val);
1032 ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
1033 size_t end = GetArgumentCount ();
1034 size_t idx = 0;
1035 while (idx < end)
1036 {
1037 if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
1038 || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
1039 {
1040 return idx;
1041 }
1042 ++idx;
1043 }
1044
1045 return end;
1046}
1047
1048bool
1049Args::IsPositionalArgument (const char *arg)
1050{
1051 if (arg == NULL)
1052 return false;
1053
1054 bool is_positional = true;
1055 char *cptr = (char *) arg;
1056
1057 if (cptr[0] == '%')
1058 {
1059 ++cptr;
1060 while (isdigit (cptr[0]))
1061 ++cptr;
1062 if (cptr[0] != '\0')
1063 is_positional = false;
1064 }
1065 else
1066 is_positional = false;
1067
1068 return is_positional;
1069}
1070
Chris Lattner24943d22010-06-08 16:52:24 +00001071void
Caroline Tice5e0894e2010-10-12 17:45:19 +00001072Args::ParseAliasOptions (Options &options,
1073 CommandReturnObject &result,
Caroline Ticee0da7a52010-12-09 22:52:49 +00001074 OptionArgVector *option_arg_vector,
1075 std::string &raw_input_string)
Chris Lattner24943d22010-06-08 16:52:24 +00001076{
1077 StreamString sstr;
1078 int i;
1079 struct option *long_options = options.GetLongOptions();
1080
1081 if (long_options == NULL)
1082 {
1083 result.AppendError ("invalid long options");
1084 result.SetStatus (eReturnStatusFailed);
1085 return;
1086 }
1087
1088 for (i = 0; long_options[i].name != NULL; ++i)
1089 {
1090 if (long_options[i].flag == NULL)
1091 {
1092 sstr << (char) long_options[i].val;
1093 switch (long_options[i].has_arg)
1094 {
1095 default:
1096 case no_argument:
1097 break;
1098 case required_argument:
1099 sstr << ":";
1100 break;
1101 case optional_argument:
1102 sstr << "::";
1103 break;
1104 }
1105 }
1106 }
1107
Eli Friedmanef2bc872010-06-13 19:18:49 +00001108#ifdef __GLIBC__
1109 optind = 0;
1110#else
Chris Lattner24943d22010-06-08 16:52:24 +00001111 optreset = 1;
1112 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +00001113#endif
Chris Lattner24943d22010-06-08 16:52:24 +00001114 int val;
1115 while (1)
1116 {
1117 int long_options_index = -1;
1118 val = ::getopt_long (GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
1119 &long_options_index);
1120
1121 if (val == -1)
1122 break;
1123
1124 if (val == '?')
1125 {
1126 result.AppendError ("unknown or ambiguous option");
1127 result.SetStatus (eReturnStatusFailed);
1128 break;
1129 }
1130
1131 if (val == 0)
1132 continue;
1133
1134 ((Options *) &options)->OptionSeen (val);
1135
1136 // Look up the long option index
1137 if (long_options_index == -1)
1138 {
1139 for (int j = 0;
1140 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1141 ++j)
1142 {
1143 if (long_options[j].val == val)
1144 {
1145 long_options_index = j;
1146 break;
1147 }
1148 }
1149 }
1150
1151 // See if the option takes an argument, and see if one was supplied.
1152 if (long_options_index >= 0)
1153 {
1154 StreamString option_str;
1155 option_str.Printf ("-%c", (char) val);
1156
1157 switch (long_options[long_options_index].has_arg)
1158 {
1159 case no_argument:
Caroline Tice44c841d2010-12-07 19:58:26 +00001160 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1161 OptionArgValue (no_argument, "<no-argument>")));
Caroline Tice2160c3f2010-09-12 04:48:45 +00001162 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001163 break;
1164 case required_argument:
1165 if (optarg != NULL)
1166 {
1167 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001168 OptionArgValue (required_argument,
1169 std::string (optarg))));
Chris Lattner24943d22010-06-08 16:52:24 +00001170 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1171 }
1172 else
1173 {
1174 result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1175 option_str.GetData());
1176 result.SetStatus (eReturnStatusFailed);
1177 }
1178 break;
1179 case optional_argument:
1180 if (optarg != NULL)
1181 {
1182 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001183 OptionArgValue (optional_argument,
1184 std::string (optarg))));
Chris Lattner24943d22010-06-08 16:52:24 +00001185 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1186 }
1187 else
1188 {
1189 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001190 OptionArgValue (optional_argument, "<no-argument>")));
Chris Lattner24943d22010-06-08 16:52:24 +00001191 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1192 }
1193 break;
1194 default:
1195 result.AppendErrorWithFormat
1196 ("error with options table; invalid value in has_arg field for option '%c'.\n",
1197 (char) val);
1198 result.SetStatus (eReturnStatusFailed);
1199 break;
1200 }
1201 }
1202 else
1203 {
1204 result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", (char) val);
1205 result.SetStatus (eReturnStatusFailed);
1206 }
Caroline Tice5e0894e2010-10-12 17:45:19 +00001207
1208 if (long_options_index >= 0)
1209 {
1210 // Find option in the argument list; also see if it was supposed to take an argument and if one was
Caroline Ticee0da7a52010-12-09 22:52:49 +00001211 // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
1212 // the raw_input_string, if one was passed in.
Caroline Tice44c841d2010-12-07 19:58:26 +00001213 size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1214 if (idx < GetArgumentCount())
1215 {
Caroline Ticee0da7a52010-12-09 22:52:49 +00001216 if (raw_input_string.size() > 0)
1217 {
1218 const char *tmp_arg = GetArgumentAtIndex (idx);
1219 size_t pos = raw_input_string.find (tmp_arg);
1220 if (pos != std::string::npos)
1221 raw_input_string.erase (pos, strlen (tmp_arg));
1222 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001223 ReplaceArgumentAtIndex (idx, "");
1224 if ((long_options[long_options_index].has_arg != no_argument)
1225 && (optarg != NULL)
1226 && (idx+1 < GetArgumentCount())
1227 && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
Caroline Ticee0da7a52010-12-09 22:52:49 +00001228 {
1229 if (raw_input_string.size() > 0)
1230 {
1231 const char *tmp_arg = GetArgumentAtIndex (idx+1);
1232 size_t pos = raw_input_string.find (tmp_arg);
1233 if (pos != std::string::npos)
1234 raw_input_string.erase (pos, strlen (tmp_arg));
1235 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001236 ReplaceArgumentAtIndex (idx+1, "");
Caroline Ticee0da7a52010-12-09 22:52:49 +00001237 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001238 }
Caroline Tice5e0894e2010-10-12 17:45:19 +00001239 }
1240
Chris Lattner24943d22010-06-08 16:52:24 +00001241 if (!result.Succeeded())
1242 break;
1243 }
1244}
1245
1246void
1247Args::ParseArgsForCompletion
1248(
1249 Options &options,
Jim Inghamadb84292010-06-24 20:31:04 +00001250 OptionElementVector &option_element_vector,
1251 uint32_t cursor_index
Chris Lattner24943d22010-06-08 16:52:24 +00001252)
1253{
1254 StreamString sstr;
Chris Lattner24943d22010-06-08 16:52:24 +00001255 struct option *long_options = options.GetLongOptions();
1256 option_element_vector.clear();
1257
1258 if (long_options == NULL)
1259 {
1260 return;
1261 }
1262
1263 // Leading : tells getopt to return a : for a missing option argument AND
1264 // to suppress error messages.
1265
1266 sstr << ":";
Greg Claytonbef15832010-07-14 00:18:15 +00001267 for (int i = 0; long_options[i].name != NULL; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +00001268 {
1269 if (long_options[i].flag == NULL)
1270 {
1271 sstr << (char) long_options[i].val;
1272 switch (long_options[i].has_arg)
1273 {
1274 default:
1275 case no_argument:
1276 break;
1277 case required_argument:
1278 sstr << ":";
1279 break;
1280 case optional_argument:
1281 sstr << "::";
1282 break;
1283 }
1284 }
1285 }
1286
Eli Friedmanef2bc872010-06-13 19:18:49 +00001287#ifdef __GLIBC__
1288 optind = 0;
1289#else
Chris Lattner24943d22010-06-08 16:52:24 +00001290 optreset = 1;
1291 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +00001292#endif
Chris Lattner24943d22010-06-08 16:52:24 +00001293 opterr = 0;
1294
1295 int val;
1296 const OptionDefinition *opt_defs = options.GetDefinitions();
1297
Jim Inghamadb84292010-06-24 20:31:04 +00001298 // Fooey... getopt_long permutes the GetArgumentVector to move the options to the front.
Chris Lattner24943d22010-06-08 16:52:24 +00001299 // So we have to build another Arg and pass that to getopt_long so it doesn't
Jim Inghamadb84292010-06-24 20:31:04 +00001300 // change the one we have.
Chris Lattner24943d22010-06-08 16:52:24 +00001301
Greg Clayton54e7afa2010-07-09 20:39:50 +00001302 std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
Chris Lattner24943d22010-06-08 16:52:24 +00001303
Jim Inghamadb84292010-06-24 20:31:04 +00001304 bool failed_once = false;
1305 uint32_t dash_dash_pos = -1;
1306
Chris Lattner24943d22010-06-08 16:52:24 +00001307 while (1)
1308 {
1309 bool missing_argument = false;
1310 int parse_start = optind;
1311 int long_options_index = -1;
Jim Inghamadb84292010-06-24 20:31:04 +00001312
Greg Clayton54e7afa2010-07-09 20:39:50 +00001313 val = ::getopt_long (dummy_vec.size() - 1,
Greg Clayton53d68e72010-07-20 22:52:08 +00001314 (char *const *) &dummy_vec.front(),
Greg Clayton54e7afa2010-07-09 20:39:50 +00001315 sstr.GetData(),
1316 long_options,
Chris Lattner24943d22010-06-08 16:52:24 +00001317 &long_options_index);
1318
1319 if (val == -1)
Jim Inghamadb84292010-06-24 20:31:04 +00001320 {
1321 // When we're completing a "--" which is the last option on line,
1322 if (failed_once)
1323 break;
1324
1325 failed_once = true;
1326
1327 // If this is a bare "--" we mark it as such so we can complete it successfully later.
1328 // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1329 // user might want to complete options by long name. I make this work by checking whether the
1330 // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
1331 // I let it pass to getopt_long which will terminate the option parsing.
1332 // Note, in either case we continue parsing the line so we can figure out what other options
1333 // were passed. This will be useful when we come to restricting completions based on what other
1334 // options we've seen on the line.
Chris Lattner24943d22010-06-08 16:52:24 +00001335
Jim Inghamadb84292010-06-24 20:31:04 +00001336 if (optind < dummy_vec.size() - 1
1337 && (strcmp (dummy_vec[optind-1], "--") == 0))
1338 {
1339 dash_dash_pos = optind - 1;
1340 if (optind - 1 == cursor_index)
1341 {
1342 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
1343 OptionArgElement::eBareDoubleDash));
1344 continue;
1345 }
1346 else
1347 break;
1348 }
1349 else
1350 break;
1351 }
Chris Lattner24943d22010-06-08 16:52:24 +00001352 else if (val == '?')
1353 {
Jim Inghamadb84292010-06-24 20:31:04 +00001354 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1355 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001356 continue;
1357 }
1358 else if (val == 0)
1359 {
1360 continue;
1361 }
1362 else if (val == ':')
1363 {
1364 // This is a missing argument.
1365 val = optopt;
1366 missing_argument = true;
1367 }
1368
1369 ((Options *) &options)->OptionSeen (val);
1370
1371 // Look up the long option index
1372 if (long_options_index == -1)
1373 {
1374 for (int j = 0;
1375 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1376 ++j)
1377 {
1378 if (long_options[j].val == val)
1379 {
1380 long_options_index = j;
1381 break;
1382 }
1383 }
1384 }
1385
1386 // See if the option takes an argument, and see if one was supplied.
1387 if (long_options_index >= 0)
1388 {
1389 int opt_defs_index = -1;
1390 for (int i = 0; ; i++)
1391 {
1392 if (opt_defs[i].short_option == 0)
1393 break;
1394 else if (opt_defs[i].short_option == val)
1395 {
1396 opt_defs_index = i;
1397 break;
1398 }
1399 }
1400
1401 switch (long_options[long_options_index].has_arg)
1402 {
1403 case no_argument:
1404 option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, 0));
1405 break;
1406 case required_argument:
1407 if (optarg != NULL)
1408 {
1409 int arg_index;
1410 if (missing_argument)
1411 arg_index = -1;
1412 else
Jim Inghamadb84292010-06-24 20:31:04 +00001413 arg_index = optind - 1;
Chris Lattner24943d22010-06-08 16:52:24 +00001414
Jim Inghamadb84292010-06-24 20:31:04 +00001415 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
Chris Lattner24943d22010-06-08 16:52:24 +00001416 }
1417 else
1418 {
Jim Inghamadb84292010-06-24 20:31:04 +00001419 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
Chris Lattner24943d22010-06-08 16:52:24 +00001420 }
1421 break;
1422 case optional_argument:
1423 if (optarg != NULL)
1424 {
Jim Inghamadb84292010-06-24 20:31:04 +00001425 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner24943d22010-06-08 16:52:24 +00001426 }
1427 else
1428 {
Jim Inghamadb84292010-06-24 20:31:04 +00001429 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner24943d22010-06-08 16:52:24 +00001430 }
1431 break;
1432 default:
1433 // The options table is messed up. Here we'll just continue
Jim Inghamadb84292010-06-24 20:31:04 +00001434 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1435 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001436 break;
1437 }
1438 }
1439 else
1440 {
Jim Inghamadb84292010-06-24 20:31:04 +00001441 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1442 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001443 }
1444 }
Jim Inghamadb84292010-06-24 20:31:04 +00001445
1446 // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
1447 // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long just ignores
1448 // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
1449
1450 if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
1451 && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1452 {
1453 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
1454 OptionArgElement::eBareDash));
1455
1456 }
Chris Lattner24943d22010-06-08 16:52:24 +00001457}