blob: e0c04f467c97963853fd9eba911d84343923e474 [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"
Chris Lattner24943d22010-06-08 16:52:24 +000017#include "lldb/Core/Stream.h"
18#include "lldb/Core/StreamFile.h"
19#include "lldb/Core/StreamString.h"
Jim Ingham84cdc152010-06-15 19:49:27 +000020#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Interpreter/CommandReturnObject.h"
22
Chris Lattner24943d22010-06-08 16:52:24 +000023using namespace lldb;
24using namespace lldb_private;
25
Chris Lattner24943d22010-06-08 16:52:24 +000026//----------------------------------------------------------------------
27// Args constructor
28//----------------------------------------------------------------------
29Args::Args (const char *command) :
30 m_args(),
31 m_argv()
32{
Greg Clayton928d1302010-12-19 03:41:24 +000033 if (command)
34 SetCommandString (command);
Chris Lattner24943d22010-06-08 16:52:24 +000035}
36
37
38Args::Args (const char *command, size_t len) :
39 m_args(),
40 m_argv()
41{
Greg Clayton928d1302010-12-19 03:41:24 +000042 if (command && len)
43 SetCommandString (command, len);
Chris Lattner24943d22010-06-08 16:52:24 +000044}
45
Chris Lattner24943d22010-06-08 16:52:24 +000046//----------------------------------------------------------------------
47// Destructor
48//----------------------------------------------------------------------
49Args::~Args ()
50{
51}
52
53void
54Args::Dump (Stream *s)
55{
56// int argc = GetArgumentCount();
57//
58// arg_sstr_collection::const_iterator pos, begin = m_args.begin(), end = m_args.end();
59// for (pos = m_args.begin(); pos != end; ++pos)
60// {
61// s->Indent();
62// s->Printf("args[%zu]=%s\n", std::distance(begin, pos), pos->c_str());
63// }
64// s->EOL();
65 const int argc = m_argv.size();
66 for (int i=0; i<argc; ++i)
67 {
68 s->Indent();
69 const char *arg_cstr = m_argv[i];
70 if (arg_cstr)
71 s->Printf("argv[%i]=\"%s\"\n", i, arg_cstr);
72 else
73 s->Printf("argv[%i]=NULL\n", i);
74 }
75 s->EOL();
76}
77
78bool
79Args::GetCommandString (std::string &command)
80{
81 command.clear();
82 int argc = GetArgumentCount();
83 for (int i=0; i<argc; ++i)
84 {
85 if (i > 0)
86 command += ' ';
87 command += m_argv[i];
88 }
89 return argc > 0;
90}
91
Caroline Ticed9105c22010-12-10 00:26:54 +000092bool
93Args::GetQuotedCommandString (std::string &command)
94{
95 command.clear ();
Greg Clayton928d1302010-12-19 03:41:24 +000096 size_t argc = GetArgumentCount ();
97 for (size_t i = 0; i < argc; ++i)
Caroline Ticed9105c22010-12-10 00:26:54 +000098 {
99 if (i > 0)
Greg Clayton928d1302010-12-19 03:41:24 +0000100 command.append (1, ' ');
101 char quote_char = GetArgumentQuoteCharAtIndex(i);
102 if (quote_char)
Caroline Ticed9105c22010-12-10 00:26:54 +0000103 {
Greg Clayton928d1302010-12-19 03:41:24 +0000104 command.append (1, quote_char);
105 command.append (m_argv[i]);
106 command.append (1, quote_char);
Caroline Ticed9105c22010-12-10 00:26:54 +0000107 }
108 else
Greg Clayton928d1302010-12-19 03:41:24 +0000109 command.append (m_argv[i]);
Caroline Ticed9105c22010-12-10 00:26:54 +0000110 }
111 return argc > 0;
112}
113
Chris Lattner24943d22010-06-08 16:52:24 +0000114void
115Args::SetCommandString (const char *command, size_t len)
116{
117 // Use std::string to make sure we get a NULL terminated string we can use
118 // as "command" could point to a string within a large string....
119 std::string null_terminated_command(command, len);
120 SetCommandString(null_terminated_command.c_str());
121}
122
123void
124Args::SetCommandString (const char *command)
125{
126 m_args.clear();
127 m_argv.clear();
Greg Clayton928d1302010-12-19 03:41:24 +0000128 m_args_quote_char.clear();
129
Chris Lattner24943d22010-06-08 16:52:24 +0000130 if (command && command[0])
131 {
Greg Clayton928d1302010-12-19 03:41:24 +0000132 static const char *k_space_separators = " \t";
133 static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"`";
134 const char *arg_end = NULL;
135 const char *arg_pos;
136 for (arg_pos = command;
137 arg_pos && arg_pos[0];
138 arg_pos = arg_end)
Chris Lattner24943d22010-06-08 16:52:24 +0000139 {
Greg Clayton928d1302010-12-19 03:41:24 +0000140 // Skip any leading space separators
141 const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
142
143 // If there were only space separators to the end of the line, then
Chris Lattner24943d22010-06-08 16:52:24 +0000144 // we're done.
145 if (*arg_start == '\0')
146 break;
147
Greg Clayton5d187e52011-01-08 20:28:42 +0000148 // Arguments can be split into multiple discontiguous pieces,
Greg Clayton928d1302010-12-19 03:41:24 +0000149 // for example:
150 // "Hello ""World"
151 // this would result in a single argument "Hello World" (without/
152 // the quotes) since the quotes would be removed and there is
153 // not space between the strings. So we need to keep track of the
154 // current start of each argument piece in "arg_piece_start"
155 const char *arg_piece_start = arg_start;
156 arg_pos = arg_piece_start;
157
Chris Lattner24943d22010-06-08 16:52:24 +0000158 std::string arg;
Greg Clayton928d1302010-12-19 03:41:24 +0000159 // Since we can have multiple quotes that form a single command
160 // in a command like: "Hello "world'!' (which will make a single
161 // argument "Hello world!") we remember the first quote character
162 // we encounter and use that for the quote character.
163 char first_quote_char = '\0';
164 char quote_char = '\0';
165 bool arg_complete = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000166
Greg Clayton928d1302010-12-19 03:41:24 +0000167 do
Chris Lattner24943d22010-06-08 16:52:24 +0000168 {
Greg Clayton928d1302010-12-19 03:41:24 +0000169 arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
170
171 switch (arg_end[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000172 {
Greg Clayton928d1302010-12-19 03:41:24 +0000173 default:
174 assert (!"Unhandled case statement, we must handle this...");
175 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000176
Greg Clayton928d1302010-12-19 03:41:24 +0000177 case '\0':
178 // End of C string
179 if (arg_piece_start && arg_piece_start[0])
180 arg.append (arg_piece_start);
181 arg_complete = true;
182 break;
183
184 case '\\':
185 // Backslash character
186 switch (arg_end[1])
Chris Lattner24943d22010-06-08 16:52:24 +0000187 {
Greg Clayton928d1302010-12-19 03:41:24 +0000188 case '\0':
189 arg.append (arg_piece_start);
190 arg_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000191 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000192
Greg Clayton928d1302010-12-19 03:41:24 +0000193 default:
194 arg_pos = arg_end + 2;
195 break;
196 }
197 break;
198
199 case '"':
200 case '\'':
201 case '`':
202 // Quote characters
203 if (quote_char)
204 {
205 // We found a quote character while inside a quoted
206 // character argument. If it matches our current quote
207 // character, this ends the effect of the quotes. If it
208 // doesn't we ignore it.
209 if (quote_char == arg_end[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000210 {
Greg Clayton928d1302010-12-19 03:41:24 +0000211 arg.append (arg_piece_start, arg_end - arg_piece_start);
212 // Clear the quote character and let parsing
213 // continue (we need to watch for things like:
214 // "Hello ""World"
215 // "Hello "World
216 // "Hello "'World'
217 // All of which will result in a single argument "Hello World"
218 quote_char = '\0'; // Note that we are no longer inside quotes
219 arg_pos = arg_end + 1; // Skip the quote character
220 arg_piece_start = arg_pos; // Note we are starting from later in the string
221 }
222 else
223 {
224 // different quote, skip it and keep going
225 arg_pos = arg_end + 1;
226 }
227 }
228 else
229 {
230 // We found the start of a quote scope.
Greg Clayton5d187e52011-01-08 20:28:42 +0000231 // Make sure there isn't a string that precedes
Greg Clayton928d1302010-12-19 03:41:24 +0000232 // the start of a quote scope like:
233 // Hello" World"
234 // If so, then add the "Hello" to the arg
235 if (arg_end > arg_piece_start)
236 arg.append (arg_piece_start, arg_end - arg_piece_start);
237
238 // Enter into a quote scope
239 quote_char = arg_end[0];
240
241 if (first_quote_char == '\0')
242 first_quote_char = quote_char;
243
244 arg_pos = arg_end;
245
246 if (quote_char != '`')
247 ++arg_pos; // Skip the quote character if it is not a backtick
248
249 arg_piece_start = arg_pos; // Note we are starting from later in the string
250
251 // Skip till the next quote character
252 const char *end_quote = ::strchr (arg_piece_start, quote_char);
253 while (end_quote && end_quote[-1] == '\\')
254 {
255 // Don't skip the quote character if it is
256 // preceded by a '\' character
257 end_quote = ::strchr (end_quote + 1, quote_char);
258 }
259
260 if (end_quote)
261 {
262 if (end_quote > arg_piece_start)
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
Greg Clayton928d1302010-12-19 03:41:24 +0000264 // Keep the backtick quote on commands
265 if (quote_char == '`')
266 arg.append (arg_piece_start, end_quote + 1 - arg_piece_start);
267 else
268 arg.append (arg_piece_start, end_quote - arg_piece_start);
269 }
270
271 // If the next character is a space or the end of
272 // string, this argument is complete...
273 if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
274 {
275 arg_complete = true;
276 arg_end = end_quote + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000277 }
278 else
279 {
Greg Clayton928d1302010-12-19 03:41:24 +0000280 arg_pos = end_quote + 1;
281 arg_piece_start = arg_pos;
Chris Lattner24943d22010-06-08 16:52:24 +0000282 }
Greg Clayton928d1302010-12-19 03:41:24 +0000283 quote_char = '\0';
Chris Lattner24943d22010-06-08 16:52:24 +0000284 }
285 }
Greg Clayton928d1302010-12-19 03:41:24 +0000286 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000287
Greg Clayton928d1302010-12-19 03:41:24 +0000288 case ' ':
289 case '\t':
290 if (quote_char)
Chris Lattner24943d22010-06-08 16:52:24 +0000291 {
Greg Clayton928d1302010-12-19 03:41:24 +0000292 // We are currently processing a quoted character and found
293 // a space character, skip any spaces and keep trying to find
294 // the end of the argument.
295 arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
Chris Lattner24943d22010-06-08 16:52:24 +0000296 }
Greg Clayton928d1302010-12-19 03:41:24 +0000297 else
Chris Lattner24943d22010-06-08 16:52:24 +0000298 {
Greg Clayton928d1302010-12-19 03:41:24 +0000299 // We are not inside any quotes, we just found a space after an
300 // argument
301 if (arg_end > arg_piece_start)
302 arg.append (arg_piece_start, arg_end - arg_piece_start);
303 arg_complete = true;
Chris Lattner24943d22010-06-08 16:52:24 +0000304 }
Greg Clayton928d1302010-12-19 03:41:24 +0000305 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000306 }
Greg Clayton928d1302010-12-19 03:41:24 +0000307 } while (!arg_complete);
Chris Lattner24943d22010-06-08 16:52:24 +0000308
309 m_args.push_back(arg);
Greg Clayton928d1302010-12-19 03:41:24 +0000310 m_args_quote_char.push_back (first_quote_char);
Chris Lattner24943d22010-06-08 16:52:24 +0000311 }
Greg Clayton928d1302010-12-19 03:41:24 +0000312 UpdateArgvFromArgs();
Chris Lattner24943d22010-06-08 16:52:24 +0000313 }
Chris Lattner24943d22010-06-08 16:52:24 +0000314}
315
316void
317Args::UpdateArgsAfterOptionParsing()
318{
319 // Now m_argv might be out of date with m_args, so we need to fix that
320 arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
321 arg_sstr_collection::iterator args_pos;
322 arg_quote_char_collection::iterator quotes_pos;
323
324 for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
325 argv_pos != argv_end && args_pos != m_args.end();
326 ++argv_pos)
327 {
328 const char *argv_cstr = *argv_pos;
329 if (argv_cstr == NULL)
330 break;
331
332 while (args_pos != m_args.end())
333 {
334 const char *args_cstr = args_pos->c_str();
335 if (args_cstr == argv_cstr)
336 {
337 // We found the argument that matches the C string in the
338 // vector, so we can now look for the next one
339 ++args_pos;
340 ++quotes_pos;
341 break;
342 }
343 else
344 {
345 quotes_pos = m_args_quote_char.erase (quotes_pos);
346 args_pos = m_args.erase (args_pos);
347 }
348 }
349 }
350
351 if (args_pos != m_args.end())
352 m_args.erase (args_pos, m_args.end());
353
354 if (quotes_pos != m_args_quote_char.end())
355 m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
356}
357
358void
359Args::UpdateArgvFromArgs()
360{
361 m_argv.clear();
362 arg_sstr_collection::const_iterator pos, end = m_args.end();
363 for (pos = m_args.begin(); pos != end; ++pos)
364 m_argv.push_back(pos->c_str());
365 m_argv.push_back(NULL);
Greg Clayton928d1302010-12-19 03:41:24 +0000366 // Make sure we have enough arg quote chars in the array
367 if (m_args_quote_char.size() < m_args.size())
368 m_args_quote_char.resize (m_argv.size());
Chris Lattner24943d22010-06-08 16:52:24 +0000369}
370
371size_t
372Args::GetArgumentCount() const
373{
374 if (m_argv.empty())
375 return 0;
376 return m_argv.size() - 1;
377}
378
379const char *
380Args::GetArgumentAtIndex (size_t idx) const
381{
382 if (idx < m_argv.size())
383 return m_argv[idx];
384 return NULL;
385}
386
387char
388Args::GetArgumentQuoteCharAtIndex (size_t idx) const
389{
390 if (idx < m_args_quote_char.size())
391 return m_args_quote_char[idx];
392 return '\0';
393}
394
395char **
396Args::GetArgumentVector()
397{
398 if (!m_argv.empty())
399 return (char **)&m_argv[0];
400 return NULL;
401}
402
403const char **
404Args::GetConstArgumentVector() const
405{
406 if (!m_argv.empty())
407 return (const char **)&m_argv[0];
408 return NULL;
409}
410
411void
412Args::Shift ()
413{
414 // Don't pop the last NULL terminator from the argv array
415 if (m_argv.size() > 1)
416 {
417 m_argv.erase(m_argv.begin());
418 m_args.pop_front();
Greg Clayton928d1302010-12-19 03:41:24 +0000419 if (!m_args_quote_char.empty())
420 m_args_quote_char.erase(m_args_quote_char.begin());
Chris Lattner24943d22010-06-08 16:52:24 +0000421 }
422}
423
424const char *
425Args::Unshift (const char *arg_cstr, char quote_char)
426{
427 m_args.push_front(arg_cstr);
428 m_argv.insert(m_argv.begin(), m_args.front().c_str());
429 m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
430 return GetArgumentAtIndex (0);
431}
432
433void
434Args::AppendArguments (const Args &rhs)
435{
436 const size_t rhs_argc = rhs.GetArgumentCount();
437 for (size_t i=0; i<rhs_argc; ++i)
438 AppendArgument(rhs.GetArgumentAtIndex(i));
439}
440
441const char *
442Args::AppendArgument (const char *arg_cstr, char quote_char)
443{
444 return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
445}
446
447const char *
448Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
449{
450 // Since we are using a std::list to hold onto the copied C string and
451 // we don't have direct access to the elements, we have to iterate to
452 // find the value.
453 arg_sstr_collection::iterator pos, end = m_args.end();
454 size_t i = idx;
455 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
456 --i;
457
458 pos = m_args.insert(pos, arg_cstr);
459
Greg Clayton928d1302010-12-19 03:41:24 +0000460 if (idx >= m_args_quote_char.size())
461 {
462 m_args_quote_char.resize(idx + 1);
463 m_args_quote_char[idx] = quote_char;
464 }
465 else
466 m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
Chris Lattner24943d22010-06-08 16:52:24 +0000467
468 UpdateArgvFromArgs();
469 return GetArgumentAtIndex(idx);
470}
471
472const char *
473Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
474{
475 // Since we are using a std::list to hold onto the copied C string and
476 // we don't have direct access to the elements, we have to iterate to
477 // find the value.
478 arg_sstr_collection::iterator pos, end = m_args.end();
479 size_t i = idx;
480 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
481 --i;
482
483 if (pos != end)
484 {
485 pos->assign(arg_cstr);
486 assert(idx < m_argv.size() - 1);
487 m_argv[idx] = pos->c_str();
Greg Clayton928d1302010-12-19 03:41:24 +0000488 if (idx >= m_args_quote_char.size())
489 m_args_quote_char.resize(idx + 1);
Chris Lattner24943d22010-06-08 16:52:24 +0000490 m_args_quote_char[idx] = quote_char;
491 return GetArgumentAtIndex(idx);
492 }
493 return NULL;
494}
495
496void
497Args::DeleteArgumentAtIndex (size_t idx)
498{
499 // Since we are using a std::list to hold onto the copied C string and
500 // we don't have direct access to the elements, we have to iterate to
501 // find the value.
502 arg_sstr_collection::iterator pos, end = m_args.end();
503 size_t i = idx;
504 for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
505 --i;
506
507 if (pos != end)
508 {
509 m_args.erase (pos);
510 assert(idx < m_argv.size() - 1);
511 m_argv.erase(m_argv.begin() + idx);
Greg Clayton928d1302010-12-19 03:41:24 +0000512 if (idx < m_args_quote_char.size())
513 m_args_quote_char.erase(m_args_quote_char.begin() + idx);
Chris Lattner24943d22010-06-08 16:52:24 +0000514 }
515}
516
517void
518Args::SetArguments (int argc, const char **argv)
519{
520 // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
521 // no need to clear it here.
522 m_args.clear();
523 m_args_quote_char.clear();
524
525 // Make a copy of the arguments in our internal buffer
526 size_t i;
527 // First copy each string
528 for (i=0; i<argc; ++i)
529 {
530 m_args.push_back (argv[i]);
Greg Clayton928d1302010-12-19 03:41:24 +0000531 if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
Chris Lattner24943d22010-06-08 16:52:24 +0000532 m_args_quote_char.push_back (argv[i][0]);
533 else
534 m_args_quote_char.push_back ('\0');
535 }
536
537 UpdateArgvFromArgs();
538}
539
540
541Error
542Args::ParseOptions (Options &options)
543{
544 StreamString sstr;
Chris Lattner24943d22010-06-08 16:52:24 +0000545 Error error;
546 struct option *long_options = options.GetLongOptions();
547 if (long_options == NULL)
548 {
549 error.SetErrorStringWithFormat("Invalid long options.\n");
550 return error;
551 }
552
Greg Claytonbef15832010-07-14 00:18:15 +0000553 for (int i=0; long_options[i].name != NULL; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +0000554 {
555 if (long_options[i].flag == NULL)
556 {
557 sstr << (char)long_options[i].val;
558 switch (long_options[i].has_arg)
559 {
560 default:
561 case no_argument: break;
562 case required_argument: sstr << ':'; break;
563 case optional_argument: sstr << "::"; break;
564 }
565 }
566 }
Eli Friedmanef2bc872010-06-13 19:18:49 +0000567#ifdef __GLIBC__
568 optind = 0;
569#else
Chris Lattner24943d22010-06-08 16:52:24 +0000570 optreset = 1;
571 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000572#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000573 int val;
574 while (1)
575 {
576 int long_options_index = -1;
577 val = ::getopt_long(GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
578 &long_options_index);
579 if (val == -1)
580 break;
581
582 // Did we get an error?
583 if (val == '?')
584 {
585 error.SetErrorStringWithFormat("Unknown or ambiguous option.\n");
586 break;
587 }
588 // The option auto-set itself
589 if (val == 0)
590 continue;
591
592 ((Options *) &options)->OptionSeen (val);
593
594 // Lookup the long option index
595 if (long_options_index == -1)
596 {
597 for (int i=0;
598 long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
599 ++i)
600 {
601 if (long_options[i].val == val)
602 {
603 long_options_index = i;
604 break;
605 }
606 }
607 }
608 // Call the callback with the option
609 if (long_options_index >= 0)
610 {
611 error = options.SetOptionValue(long_options_index,
612 long_options[long_options_index].has_arg == no_argument ? NULL : optarg);
613 }
614 else
615 {
616 error.SetErrorStringWithFormat("Invalid option with value '%i'.\n", val);
617 }
618 if (error.Fail())
619 break;
620 }
621
622 // Update our ARGV now that get options has consumed all the options
623 m_argv.erase(m_argv.begin(), m_argv.begin() + optind);
624 UpdateArgsAfterOptionParsing ();
625 return error;
626}
627
628void
629Args::Clear ()
630{
631 m_args.clear ();
632 m_argv.clear ();
633 m_args_quote_char.clear();
634}
635
636int32_t
637Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
638{
639 if (s && s[0])
640 {
641 char *end = NULL;
642 int32_t uval = ::strtol (s, &end, base);
643 if (*end == '\0')
644 {
645 if (success_ptr) *success_ptr = true;
646 return uval; // All characters were used, return the result
647 }
648 }
649 if (success_ptr) *success_ptr = false;
650 return fail_value;
651}
652
653uint32_t
654Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
655{
656 if (s && s[0])
657 {
658 char *end = NULL;
659 uint32_t uval = ::strtoul (s, &end, base);
660 if (*end == '\0')
661 {
662 if (success_ptr) *success_ptr = true;
663 return uval; // All characters were used, return the result
664 }
665 }
666 if (success_ptr) *success_ptr = false;
667 return fail_value;
668}
669
670
671int64_t
672Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
673{
674 if (s && s[0])
675 {
676 char *end = NULL;
677 int64_t uval = ::strtoll (s, &end, base);
678 if (*end == '\0')
679 {
680 if (success_ptr) *success_ptr = true;
681 return uval; // All characters were used, return the result
682 }
683 }
684 if (success_ptr) *success_ptr = false;
685 return fail_value;
686}
687
688uint64_t
689Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
690{
691 if (s && s[0])
692 {
693 char *end = NULL;
694 uint64_t uval = ::strtoull (s, &end, base);
695 if (*end == '\0')
696 {
697 if (success_ptr) *success_ptr = true;
698 return uval; // All characters were used, return the result
699 }
700 }
701 if (success_ptr) *success_ptr = false;
702 return fail_value;
703}
704
705lldb::addr_t
706Args::StringToAddress (const char *s, lldb::addr_t fail_value, bool *success_ptr)
707{
708 if (s && s[0])
709 {
710 char *end = NULL;
711 lldb::addr_t addr = ::strtoull (s, &end, 0);
712 if (*end == '\0')
713 {
714 if (success_ptr) *success_ptr = true;
715 return addr; // All characters were used, return the result
716 }
717 // Try base 16 with no prefix...
718 addr = ::strtoull (s, &end, 16);
719 if (*end == '\0')
720 {
721 if (success_ptr) *success_ptr = true;
722 return addr; // All characters were used, return the result
723 }
724 }
725 if (success_ptr) *success_ptr = false;
726 return fail_value;
727}
728
729bool
730Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
731{
732 if (s && s[0])
733 {
734 if (::strcasecmp (s, "false") == 0 ||
735 ::strcasecmp (s, "off") == 0 ||
736 ::strcasecmp (s, "no") == 0 ||
737 ::strcmp (s, "0") == 0)
738 {
739 if (success_ptr)
740 *success_ptr = true;
741 return false;
742 }
743 else
744 if (::strcasecmp (s, "true") == 0 ||
745 ::strcasecmp (s, "on") == 0 ||
746 ::strcasecmp (s, "yes") == 0 ||
747 ::strcmp (s, "1") == 0)
748 {
749 if (success_ptr) *success_ptr = true;
750 return true;
751 }
752 }
753 if (success_ptr) *success_ptr = false;
754 return fail_value;
755}
756
757int32_t
758Args::StringToOptionEnum (const char *s, lldb::OptionEnumValueElement *enum_values, int32_t fail_value, bool *success_ptr)
759{
760 if (enum_values && s && s[0])
761 {
762 for (int i = 0; enum_values[i].string_value != NULL ; i++)
763 {
764 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
765 {
766 if (success_ptr) *success_ptr = true;
767 return enum_values[i].value;
768 }
769 }
770 }
771 if (success_ptr) *success_ptr = false;
772
773 return fail_value;
774}
775
776ScriptLanguage
777Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
778{
779 if (s && s[0])
780 {
781 if ((::strcasecmp (s, "python") == 0) ||
782 (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
783 {
784 if (success_ptr) *success_ptr = true;
785 return eScriptLanguagePython;
786 }
787 if (::strcasecmp (s, "none"))
788 {
789 if (success_ptr) *success_ptr = true;
790 return eScriptLanguageNone;
791 }
792 }
793 if (success_ptr) *success_ptr = false;
794 return fail_value;
795}
796
797Error
798Args::StringToFormat
799(
800 const char *s,
801 lldb::Format &format
802)
803{
804 format = eFormatInvalid;
805 Error error;
806
807 if (s && s[0])
808 {
809 switch (s[0])
810 {
811 case 'y': format = eFormatBytes; break;
812 case 'Y': format = eFormatBytesWithASCII; break;
813 case 'b': format = eFormatBinary; break;
814 case 'B': format = eFormatBoolean; break;
815 case 'c': format = eFormatChar; break;
816 case 'C': format = eFormatCharPrintable; break;
817 case 'o': format = eFormatOctal; break;
818 case 'i':
819 case 'd': format = eFormatDecimal; break;
820 case 'u': format = eFormatUnsigned; break;
821 case 'x': format = eFormatHex; break;
822 case 'f':
823 case 'e':
824 case 'g': format = eFormatFloat; break;
825 case 'p': format = eFormatPointer; break;
826 case 's': format = eFormatCString; break;
827 default:
828 error.SetErrorStringWithFormat("Invalid format character '%c'. Valid values are:\n"
829 " b - binary\n"
830 " B - boolean\n"
831 " c - char\n"
832 " C - printable char\n"
833 " d - signed decimal\n"
834 " e - float\n"
835 " f - float\n"
836 " g - float\n"
837 " i - signed decimal\n"
838 " o - octal\n"
839 " s - c-string\n"
840 " u - unsigned decimal\n"
841 " x - hex\n"
842 " y - bytes\n"
843 " Y - bytes with ASCII\n", s[0]);
844 break;
845 }
846
847 if (error.Fail())
848 return error;
849 }
850 else
851 {
852 error.SetErrorStringWithFormat("%s option string.\n", s ? "empty" : "invalid");
853 }
854 return error;
855}
856
857void
858Args::LongestCommonPrefix (std::string &common_prefix)
859{
860 arg_sstr_collection::iterator pos, end = m_args.end();
861 pos = m_args.begin();
862 if (pos == end)
863 common_prefix.clear();
864 else
865 common_prefix = (*pos);
866
867 for (++pos; pos != end; ++pos)
868 {
Greg Clayton54e7afa2010-07-09 20:39:50 +0000869 size_t new_size = (*pos).size();
Chris Lattner24943d22010-06-08 16:52:24 +0000870
871 // First trim common_prefix if it is longer than the current element:
872 if (common_prefix.size() > new_size)
873 common_prefix.erase (new_size);
874
875 // Then trim it at the first disparity:
876
Greg Clayton54e7afa2010-07-09 20:39:50 +0000877 for (size_t i = 0; i < common_prefix.size(); i++)
Chris Lattner24943d22010-06-08 16:52:24 +0000878 {
879 if ((*pos)[i] != common_prefix[i])
880 {
881 common_prefix.erase(i);
882 break;
883 }
884 }
885
886 // If we've emptied the common prefix, we're done.
887 if (common_prefix.empty())
888 break;
889 }
890}
891
Caroline Tice44c841d2010-12-07 19:58:26 +0000892size_t
893Args::FindArgumentIndexForOption (struct option *long_options, int long_options_index)
894{
895 char short_buffer[3];
896 char long_buffer[255];
897 ::snprintf (short_buffer, sizeof (short_buffer), "-%c", (char) long_options[long_options_index].val);
898 ::snprintf (long_buffer, sizeof (long_buffer), "--%s", long_options[long_options_index].name);
899 size_t end = GetArgumentCount ();
900 size_t idx = 0;
901 while (idx < end)
902 {
903 if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
904 || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
905 {
906 return idx;
907 }
908 ++idx;
909 }
910
911 return end;
912}
913
914bool
915Args::IsPositionalArgument (const char *arg)
916{
917 if (arg == NULL)
918 return false;
919
920 bool is_positional = true;
921 char *cptr = (char *) arg;
922
923 if (cptr[0] == '%')
924 {
925 ++cptr;
926 while (isdigit (cptr[0]))
927 ++cptr;
928 if (cptr[0] != '\0')
929 is_positional = false;
930 }
931 else
932 is_positional = false;
933
934 return is_positional;
935}
936
Chris Lattner24943d22010-06-08 16:52:24 +0000937void
Caroline Tice5e0894e2010-10-12 17:45:19 +0000938Args::ParseAliasOptions (Options &options,
939 CommandReturnObject &result,
Caroline Ticee0da7a52010-12-09 22:52:49 +0000940 OptionArgVector *option_arg_vector,
941 std::string &raw_input_string)
Chris Lattner24943d22010-06-08 16:52:24 +0000942{
943 StreamString sstr;
944 int i;
945 struct option *long_options = options.GetLongOptions();
946
947 if (long_options == NULL)
948 {
949 result.AppendError ("invalid long options");
950 result.SetStatus (eReturnStatusFailed);
951 return;
952 }
953
954 for (i = 0; long_options[i].name != NULL; ++i)
955 {
956 if (long_options[i].flag == NULL)
957 {
958 sstr << (char) long_options[i].val;
959 switch (long_options[i].has_arg)
960 {
961 default:
962 case no_argument:
963 break;
964 case required_argument:
965 sstr << ":";
966 break;
967 case optional_argument:
968 sstr << "::";
969 break;
970 }
971 }
972 }
973
Eli Friedmanef2bc872010-06-13 19:18:49 +0000974#ifdef __GLIBC__
975 optind = 0;
976#else
Chris Lattner24943d22010-06-08 16:52:24 +0000977 optreset = 1;
978 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +0000979#endif
Chris Lattner24943d22010-06-08 16:52:24 +0000980 int val;
981 while (1)
982 {
983 int long_options_index = -1;
984 val = ::getopt_long (GetArgumentCount(), GetArgumentVector(), sstr.GetData(), long_options,
985 &long_options_index);
986
987 if (val == -1)
988 break;
989
990 if (val == '?')
991 {
992 result.AppendError ("unknown or ambiguous option");
993 result.SetStatus (eReturnStatusFailed);
994 break;
995 }
996
997 if (val == 0)
998 continue;
999
1000 ((Options *) &options)->OptionSeen (val);
1001
1002 // Look up the long option index
1003 if (long_options_index == -1)
1004 {
1005 for (int j = 0;
1006 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1007 ++j)
1008 {
1009 if (long_options[j].val == val)
1010 {
1011 long_options_index = j;
1012 break;
1013 }
1014 }
1015 }
1016
1017 // See if the option takes an argument, and see if one was supplied.
1018 if (long_options_index >= 0)
1019 {
1020 StreamString option_str;
1021 option_str.Printf ("-%c", (char) val);
1022
1023 switch (long_options[long_options_index].has_arg)
1024 {
1025 case no_argument:
Caroline Tice44c841d2010-12-07 19:58:26 +00001026 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1027 OptionArgValue (no_argument, "<no-argument>")));
Caroline Tice2160c3f2010-09-12 04:48:45 +00001028 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Chris Lattner24943d22010-06-08 16:52:24 +00001029 break;
1030 case required_argument:
1031 if (optarg != NULL)
1032 {
1033 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001034 OptionArgValue (required_argument,
1035 std::string (optarg))));
Chris Lattner24943d22010-06-08 16:52:24 +00001036 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1037 }
1038 else
1039 {
1040 result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1041 option_str.GetData());
1042 result.SetStatus (eReturnStatusFailed);
1043 }
1044 break;
1045 case optional_argument:
1046 if (optarg != NULL)
1047 {
1048 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001049 OptionArgValue (optional_argument,
1050 std::string (optarg))));
Chris Lattner24943d22010-06-08 16:52:24 +00001051 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1052 }
1053 else
1054 {
1055 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
Caroline Tice44c841d2010-12-07 19:58:26 +00001056 OptionArgValue (optional_argument, "<no-argument>")));
Chris Lattner24943d22010-06-08 16:52:24 +00001057 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1058 }
1059 break;
1060 default:
1061 result.AppendErrorWithFormat
1062 ("error with options table; invalid value in has_arg field for option '%c'.\n",
1063 (char) val);
1064 result.SetStatus (eReturnStatusFailed);
1065 break;
1066 }
1067 }
1068 else
1069 {
1070 result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", (char) val);
1071 result.SetStatus (eReturnStatusFailed);
1072 }
Caroline Tice5e0894e2010-10-12 17:45:19 +00001073
1074 if (long_options_index >= 0)
1075 {
1076 // 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 +00001077 // supplied. Remove option (and argument, if given) from the argument list. Also remove them from
1078 // the raw_input_string, if one was passed in.
Caroline Tice44c841d2010-12-07 19:58:26 +00001079 size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1080 if (idx < GetArgumentCount())
1081 {
Caroline Ticee0da7a52010-12-09 22:52:49 +00001082 if (raw_input_string.size() > 0)
1083 {
1084 const char *tmp_arg = GetArgumentAtIndex (idx);
1085 size_t pos = raw_input_string.find (tmp_arg);
1086 if (pos != std::string::npos)
1087 raw_input_string.erase (pos, strlen (tmp_arg));
1088 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001089 ReplaceArgumentAtIndex (idx, "");
1090 if ((long_options[long_options_index].has_arg != no_argument)
1091 && (optarg != NULL)
1092 && (idx+1 < GetArgumentCount())
1093 && (strcmp (optarg, GetArgumentAtIndex(idx+1)) == 0))
Caroline Ticee0da7a52010-12-09 22:52:49 +00001094 {
1095 if (raw_input_string.size() > 0)
1096 {
1097 const char *tmp_arg = GetArgumentAtIndex (idx+1);
1098 size_t pos = raw_input_string.find (tmp_arg);
1099 if (pos != std::string::npos)
1100 raw_input_string.erase (pos, strlen (tmp_arg));
1101 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001102 ReplaceArgumentAtIndex (idx+1, "");
Caroline Ticee0da7a52010-12-09 22:52:49 +00001103 }
Caroline Tice44c841d2010-12-07 19:58:26 +00001104 }
Caroline Tice5e0894e2010-10-12 17:45:19 +00001105 }
1106
Chris Lattner24943d22010-06-08 16:52:24 +00001107 if (!result.Succeeded())
1108 break;
1109 }
1110}
1111
1112void
1113Args::ParseArgsForCompletion
1114(
1115 Options &options,
Jim Inghamadb84292010-06-24 20:31:04 +00001116 OptionElementVector &option_element_vector,
1117 uint32_t cursor_index
Chris Lattner24943d22010-06-08 16:52:24 +00001118)
1119{
1120 StreamString sstr;
Chris Lattner24943d22010-06-08 16:52:24 +00001121 struct option *long_options = options.GetLongOptions();
1122 option_element_vector.clear();
1123
1124 if (long_options == NULL)
1125 {
1126 return;
1127 }
1128
1129 // Leading : tells getopt to return a : for a missing option argument AND
1130 // to suppress error messages.
1131
1132 sstr << ":";
Greg Claytonbef15832010-07-14 00:18:15 +00001133 for (int i = 0; long_options[i].name != NULL; ++i)
Chris Lattner24943d22010-06-08 16:52:24 +00001134 {
1135 if (long_options[i].flag == NULL)
1136 {
1137 sstr << (char) long_options[i].val;
1138 switch (long_options[i].has_arg)
1139 {
1140 default:
1141 case no_argument:
1142 break;
1143 case required_argument:
1144 sstr << ":";
1145 break;
1146 case optional_argument:
1147 sstr << "::";
1148 break;
1149 }
1150 }
1151 }
1152
Eli Friedmanef2bc872010-06-13 19:18:49 +00001153#ifdef __GLIBC__
1154 optind = 0;
1155#else
Chris Lattner24943d22010-06-08 16:52:24 +00001156 optreset = 1;
1157 optind = 1;
Eli Friedmanef2bc872010-06-13 19:18:49 +00001158#endif
Chris Lattner24943d22010-06-08 16:52:24 +00001159 opterr = 0;
1160
1161 int val;
1162 const OptionDefinition *opt_defs = options.GetDefinitions();
1163
Jim Inghamadb84292010-06-24 20:31:04 +00001164 // Fooey... getopt_long permutes the GetArgumentVector to move the options to the front.
Chris Lattner24943d22010-06-08 16:52:24 +00001165 // So we have to build another Arg and pass that to getopt_long so it doesn't
Jim Inghamadb84292010-06-24 20:31:04 +00001166 // change the one we have.
Chris Lattner24943d22010-06-08 16:52:24 +00001167
Greg Clayton54e7afa2010-07-09 20:39:50 +00001168 std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
Chris Lattner24943d22010-06-08 16:52:24 +00001169
Jim Inghamadb84292010-06-24 20:31:04 +00001170 bool failed_once = false;
1171 uint32_t dash_dash_pos = -1;
1172
Chris Lattner24943d22010-06-08 16:52:24 +00001173 while (1)
1174 {
1175 bool missing_argument = false;
1176 int parse_start = optind;
1177 int long_options_index = -1;
Jim Inghamadb84292010-06-24 20:31:04 +00001178
Greg Clayton54e7afa2010-07-09 20:39:50 +00001179 val = ::getopt_long (dummy_vec.size() - 1,
Greg Clayton53d68e72010-07-20 22:52:08 +00001180 (char *const *) &dummy_vec.front(),
Greg Clayton54e7afa2010-07-09 20:39:50 +00001181 sstr.GetData(),
1182 long_options,
Chris Lattner24943d22010-06-08 16:52:24 +00001183 &long_options_index);
1184
1185 if (val == -1)
Jim Inghamadb84292010-06-24 20:31:04 +00001186 {
1187 // When we're completing a "--" which is the last option on line,
1188 if (failed_once)
1189 break;
1190
1191 failed_once = true;
1192
1193 // If this is a bare "--" we mark it as such so we can complete it successfully later.
1194 // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1195 // user might want to complete options by long name. I make this work by checking whether the
1196 // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
1197 // I let it pass to getopt_long which will terminate the option parsing.
1198 // Note, in either case we continue parsing the line so we can figure out what other options
1199 // were passed. This will be useful when we come to restricting completions based on what other
1200 // options we've seen on the line.
Chris Lattner24943d22010-06-08 16:52:24 +00001201
Jim Inghamadb84292010-06-24 20:31:04 +00001202 if (optind < dummy_vec.size() - 1
1203 && (strcmp (dummy_vec[optind-1], "--") == 0))
1204 {
1205 dash_dash_pos = optind - 1;
1206 if (optind - 1 == cursor_index)
1207 {
1208 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, optind - 1,
1209 OptionArgElement::eBareDoubleDash));
1210 continue;
1211 }
1212 else
1213 break;
1214 }
1215 else
1216 break;
1217 }
Chris Lattner24943d22010-06-08 16:52:24 +00001218 else if (val == '?')
1219 {
Jim Inghamadb84292010-06-24 20:31:04 +00001220 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1221 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001222 continue;
1223 }
1224 else if (val == 0)
1225 {
1226 continue;
1227 }
1228 else if (val == ':')
1229 {
1230 // This is a missing argument.
1231 val = optopt;
1232 missing_argument = true;
1233 }
1234
1235 ((Options *) &options)->OptionSeen (val);
1236
1237 // Look up the long option index
1238 if (long_options_index == -1)
1239 {
1240 for (int j = 0;
1241 long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1242 ++j)
1243 {
1244 if (long_options[j].val == val)
1245 {
1246 long_options_index = j;
1247 break;
1248 }
1249 }
1250 }
1251
1252 // See if the option takes an argument, and see if one was supplied.
1253 if (long_options_index >= 0)
1254 {
1255 int opt_defs_index = -1;
1256 for (int i = 0; ; i++)
1257 {
1258 if (opt_defs[i].short_option == 0)
1259 break;
1260 else if (opt_defs[i].short_option == val)
1261 {
1262 opt_defs_index = i;
1263 break;
1264 }
1265 }
1266
1267 switch (long_options[long_options_index].has_arg)
1268 {
1269 case no_argument:
1270 option_element_vector.push_back (OptionArgElement (opt_defs_index, parse_start, 0));
1271 break;
1272 case required_argument:
1273 if (optarg != NULL)
1274 {
1275 int arg_index;
1276 if (missing_argument)
1277 arg_index = -1;
1278 else
Jim Inghamadb84292010-06-24 20:31:04 +00001279 arg_index = optind - 1;
Chris Lattner24943d22010-06-08 16:52:24 +00001280
Jim Inghamadb84292010-06-24 20:31:04 +00001281 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, arg_index));
Chris Lattner24943d22010-06-08 16:52:24 +00001282 }
1283 else
1284 {
Jim Inghamadb84292010-06-24 20:31:04 +00001285 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 1, -1));
Chris Lattner24943d22010-06-08 16:52:24 +00001286 }
1287 break;
1288 case optional_argument:
1289 if (optarg != NULL)
1290 {
Jim Inghamadb84292010-06-24 20:31:04 +00001291 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner24943d22010-06-08 16:52:24 +00001292 }
1293 else
1294 {
Jim Inghamadb84292010-06-24 20:31:04 +00001295 option_element_vector.push_back (OptionArgElement (opt_defs_index, optind - 2, optind - 1));
Chris Lattner24943d22010-06-08 16:52:24 +00001296 }
1297 break;
1298 default:
1299 // The options table is messed up. Here we'll just continue
Jim Inghamadb84292010-06-24 20:31:04 +00001300 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1301 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001302 break;
1303 }
1304 }
1305 else
1306 {
Jim Inghamadb84292010-06-24 20:31:04 +00001307 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, optind - 1,
1308 OptionArgElement::eUnrecognizedArg));
Chris Lattner24943d22010-06-08 16:52:24 +00001309 }
1310 }
Jim Inghamadb84292010-06-24 20:31:04 +00001311
1312 // Finally we have to handle the case where the cursor index points at a single "-". We want to mark that in
1313 // the option_element_vector, but only if it is not after the "--". But it turns out that getopt_long just ignores
1314 // an isolated "-". So we have to look it up by hand here. We only care if it is AT the cursor position.
1315
1316 if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
1317 && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1318 {
1319 option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index,
1320 OptionArgElement::eBareDash));
1321
1322 }
Chris Lattner24943d22010-06-08 16:52:24 +00001323}