]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Interpreter / Args.cpp
1 //===-- 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 #include "lldb/lldb-python.h"
11
12 // C Includes
13 #include <cstdlib>
14 // C++ Includes
15 // Other libraries and framework includes
16 // Project includes
17 #include "lldb/Interpreter/Args.h"
18 #include "lldb/Core/Stream.h"
19 #include "lldb/Core/StreamFile.h"
20 #include "lldb/Core/StreamString.h"
21 #include "lldb/DataFormatters/FormatManager.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Target/Process.h"
25 //#include "lldb/Target/RegisterContext.h"
26 #include "lldb/Target/StackFrame.h"
27 #include "lldb/Target/Target.h"
28 //#include "lldb/Target/Thread.h"
29
30 using namespace lldb;
31 using namespace lldb_private;
32
33 //----------------------------------------------------------------------
34 // Args constructor
35 //----------------------------------------------------------------------
36 Args::Args (const char *command) :
37     m_args(),
38     m_argv(),
39     m_args_quote_char()
40 {
41     if (command)
42         SetCommandString (command);
43 }
44
45
46 Args::Args (const char *command, size_t len) :
47     m_args(),
48     m_argv(),
49     m_args_quote_char()
50 {
51     if (command && len)
52         SetCommandString (command, len);
53 }
54
55 //----------------------------------------------------------------------
56 // We have to be very careful on the copy constructor of this class
57 // to make sure we copy all of the string values, but we can't copy the
58 // rhs.m_argv into m_argv since it will point to the "const char *" c 
59 // strings in rhs.m_args. We need to copy the string list and update our
60 // own m_argv appropriately. 
61 //----------------------------------------------------------------------
62 Args::Args (const Args &rhs) :
63     m_args (rhs.m_args),
64     m_argv (),
65     m_args_quote_char(rhs.m_args_quote_char)
66 {
67     UpdateArgvFromArgs();
68 }
69
70 //----------------------------------------------------------------------
71 // We have to be very careful on the copy constructor of this class
72 // to make sure we copy all of the string values, but we can't copy the
73 // rhs.m_argv into m_argv since it will point to the "const char *" c 
74 // strings in rhs.m_args. We need to copy the string list and update our
75 // own m_argv appropriately. 
76 //----------------------------------------------------------------------
77 const Args &
78 Args::operator= (const Args &rhs)
79 {
80     // Make sure we aren't assigning to self
81     if (this != &rhs)
82     {
83         m_args = rhs.m_args;
84         m_args_quote_char = rhs.m_args_quote_char;
85         UpdateArgvFromArgs();
86     }
87     return *this;
88 }
89
90 //----------------------------------------------------------------------
91 // Destructor
92 //----------------------------------------------------------------------
93 Args::~Args ()
94 {
95 }
96
97 void
98 Args::Dump (Stream *s)
99 {
100     const size_t argc = m_argv.size();
101     for (size_t i=0; i<argc; ++i)
102     {
103         s->Indent();
104         const char *arg_cstr = m_argv[i];
105         if (arg_cstr)
106             s->Printf("argv[%zi]=\"%s\"\n", i, arg_cstr);
107         else
108             s->Printf("argv[%zi]=NULL\n", i);
109     }
110     s->EOL();
111 }
112
113 bool
114 Args::GetCommandString (std::string &command) const
115 {
116     command.clear();
117     const size_t argc = GetArgumentCount();
118     for (size_t i=0; i<argc; ++i)
119     {
120         if (i > 0)
121             command += ' ';
122         command += m_argv[i];
123     }
124     return argc > 0;
125 }
126
127 bool
128 Args::GetQuotedCommandString (std::string &command) const
129 {
130     command.clear ();
131     const size_t argc = GetArgumentCount();
132     for (size_t i = 0; i < argc; ++i)
133     {
134         if (i > 0)
135             command.append (1, ' ');
136         char quote_char = GetArgumentQuoteCharAtIndex(i);
137         if (quote_char)
138         {
139             command.append (1, quote_char);
140             command.append (m_argv[i]);
141             command.append (1, quote_char);
142         }
143         else
144             command.append (m_argv[i]);
145     }
146     return argc > 0;
147 }
148
149 void
150 Args::SetCommandString (const char *command, size_t len)
151 {
152     // Use std::string to make sure we get a NULL terminated string we can use
153     // as "command" could point to a string within a large string....
154     std::string null_terminated_command(command, len);
155     SetCommandString(null_terminated_command.c_str());
156 }
157
158 void
159 Args::SetCommandString (const char *command)
160 {
161     m_args.clear();
162     m_argv.clear();
163     m_args_quote_char.clear();
164
165     if (command && command[0])
166     {
167         static const char *k_space_separators = " \t";
168         static const char *k_space_separators_with_slash_and_quotes = " \t \\'\"";
169         const char *arg_end = NULL;
170         const char *arg_pos;
171         for (arg_pos = command;
172              arg_pos && arg_pos[0];
173              arg_pos = arg_end)
174         {
175             // Skip any leading space separators
176             const char *arg_start = ::strspn (arg_pos, k_space_separators) + arg_pos;
177             
178             // If there were only space separators to the end of the line, then
179             // we're done.
180             if (*arg_start == '\0')
181                 break;
182
183             // Arguments can be split into multiple discontiguous pieces,
184             // for example:
185             //  "Hello ""World"
186             // this would result in a single argument "Hello World" (without/
187             // the quotes) since the quotes would be removed and there is 
188             // not space between the strings. So we need to keep track of the
189             // current start of each argument piece in "arg_piece_start"
190             const char *arg_piece_start = arg_start;
191             arg_pos = arg_piece_start;
192
193             std::string arg;
194             // Since we can have multiple quotes that form a single command
195             // in a command like: "Hello "world'!' (which will make a single
196             // argument "Hello world!") we remember the first quote character
197             // we encounter and use that for the quote character.
198             char first_quote_char = '\0';
199             char quote_char = '\0';
200             bool arg_complete = false;
201
202             do
203             {
204                 arg_end = ::strcspn (arg_pos, k_space_separators_with_slash_and_quotes) + arg_pos;
205
206                 switch (arg_end[0])
207                 {
208                 default:
209                     assert (!"Unhandled case statement, we must handle this...");
210                     break;
211
212                 case '\0':
213                     // End of C string
214                     if (arg_piece_start && arg_piece_start[0])
215                         arg.append (arg_piece_start);
216                     arg_complete = true;
217                     break;
218                     
219                 case '\\':
220                     // Backslash character
221                     switch (arg_end[1])
222                     {
223                         case '\0':
224                             arg.append (arg_piece_start);
225                             ++arg_end;
226                             arg_complete = true;
227                             break;
228
229                         default:
230                             if (quote_char == '\0')
231                             {
232                                 arg.append (arg_piece_start, arg_end - arg_piece_start);
233                                 if (arg_end[1] != '\0')
234                                 {
235                                     arg.append (arg_end + 1, 1);
236                                     arg_pos = arg_end + 2;
237                                     arg_piece_start = arg_pos;
238                                 }
239                             }
240                             else
241                                 arg_pos = arg_end + 2;
242                             break;
243                     }
244                     break;
245                 
246                 case '"':
247                 case '\'':
248                 case '`':
249                     // Quote characters 
250                     if (quote_char)
251                     {
252                         // We found a quote character while inside a quoted
253                         // character argument. If it matches our current quote
254                         // character, this ends the effect of the quotes. If it
255                         // doesn't we ignore it.
256                         if (quote_char == arg_end[0])
257                         {
258                             arg.append (arg_piece_start, arg_end - arg_piece_start);
259                             // Clear the quote character and let parsing
260                             // continue (we need to watch for things like:
261                             // "Hello ""World"
262                             // "Hello "World
263                             // "Hello "'World'
264                             // All of which will result in a single argument "Hello World"
265                             quote_char = '\0'; // Note that we are no longer inside quotes
266                             arg_pos = arg_end + 1; // Skip the quote character
267                             arg_piece_start = arg_pos; // Note we are starting from later in the string
268                         }
269                         else
270                         {
271                             // different quote, skip it and keep going
272                             arg_pos = arg_end + 1;
273                         }
274                     }
275                     else
276                     {
277                         // We found the start of a quote scope.
278                         // Make sure there isn't a string that precedes
279                         // the start of a quote scope like:
280                         // Hello" World"
281                         // If so, then add the "Hello" to the arg
282                         if (arg_end > arg_piece_start)
283                             arg.append (arg_piece_start, arg_end - arg_piece_start);
284                             
285                         // Enter into a quote scope
286                         quote_char = arg_end[0];
287                         
288                         if (first_quote_char == '\0')
289                             first_quote_char = quote_char;
290
291                         arg_pos = arg_end;
292                         ++arg_pos;                 // Skip the quote character
293                         arg_piece_start = arg_pos; // Note we are starting from later in the string
294                         
295                         // Skip till the next quote character
296                         const char *end_quote = ::strchr (arg_piece_start, quote_char);
297                         while (end_quote && end_quote[-1] == '\\')
298                         {
299                             // Don't skip the quote character if it is 
300                             // preceded by a '\' character
301                             end_quote = ::strchr (end_quote + 1, quote_char);
302                         }
303                         
304                         if (end_quote)
305                         {
306                             if (end_quote > arg_piece_start)
307                                 arg.append (arg_piece_start, end_quote - arg_piece_start);
308
309                             // If the next character is a space or the end of 
310                             // string, this argument is complete...
311                             if (end_quote[1] == ' ' || end_quote[1] == '\t' || end_quote[1] == '\0')
312                             {
313                                 arg_complete = true;
314                                 arg_end = end_quote + 1;
315                             }
316                             else
317                             {
318                                 arg_pos = end_quote + 1;
319                                 arg_piece_start = arg_pos;
320                             }
321                             quote_char = '\0';
322                         }
323                         else
324                         {
325                             // Consume the rest of the string as there was no terminating quote
326                             arg.append(arg_piece_start);
327                             arg_end = arg_piece_start + strlen(arg_piece_start);
328                             arg_complete = true;
329                         }
330                     }
331                     break;
332
333                 case ' ':
334                 case '\t':
335                     if (quote_char)
336                     {
337                         // We are currently processing a quoted character and found
338                         // a space character, skip any spaces and keep trying to find
339                         // the end of the argument. 
340                         arg_pos = ::strspn (arg_end, k_space_separators) + arg_end;
341                     }
342                     else
343                     {
344                         // We are not inside any quotes, we just found a space after an
345                         // argument
346                         if (arg_end > arg_piece_start)
347                             arg.append (arg_piece_start, arg_end - arg_piece_start);
348                         arg_complete = true;
349                     }
350                     break;
351                 }
352             } while (!arg_complete);
353
354             m_args.push_back(arg);
355             m_args_quote_char.push_back (first_quote_char);
356         }
357         UpdateArgvFromArgs();
358     }
359 }
360
361 void
362 Args::UpdateArgsAfterOptionParsing()
363 {
364     // Now m_argv might be out of date with m_args, so we need to fix that
365     arg_cstr_collection::const_iterator argv_pos, argv_end = m_argv.end();
366     arg_sstr_collection::iterator args_pos;
367     arg_quote_char_collection::iterator quotes_pos;
368
369     for (argv_pos = m_argv.begin(), args_pos = m_args.begin(), quotes_pos = m_args_quote_char.begin();
370          argv_pos != argv_end && args_pos != m_args.end();
371          ++argv_pos)
372     {
373         const char *argv_cstr = *argv_pos;
374         if (argv_cstr == NULL)
375             break;
376
377         while (args_pos != m_args.end())
378         {
379             const char *args_cstr = args_pos->c_str();
380             if (args_cstr == argv_cstr)
381             {
382                 // We found the argument that matches the C string in the
383                 // vector, so we can now look for the next one
384                 ++args_pos;
385                 ++quotes_pos;
386                 break;
387             }
388             else
389             {
390                 quotes_pos = m_args_quote_char.erase (quotes_pos);
391                 args_pos = m_args.erase (args_pos);
392             }
393         }
394     }
395
396     if (args_pos != m_args.end())
397         m_args.erase (args_pos, m_args.end());
398
399     if (quotes_pos != m_args_quote_char.end())
400         m_args_quote_char.erase (quotes_pos, m_args_quote_char.end());
401 }
402
403 void
404 Args::UpdateArgvFromArgs()
405 {
406     m_argv.clear();
407     arg_sstr_collection::const_iterator pos, end = m_args.end();
408     for (pos = m_args.begin(); pos != end; ++pos)
409         m_argv.push_back(pos->c_str());
410     m_argv.push_back(NULL);
411     // Make sure we have enough arg quote chars in the array
412     if (m_args_quote_char.size() < m_args.size())
413         m_args_quote_char.resize (m_argv.size());
414 }
415
416 size_t
417 Args::GetArgumentCount() const
418 {
419     if (m_argv.empty())
420         return 0;
421     return m_argv.size() - 1;
422 }
423
424 const char *
425 Args::GetArgumentAtIndex (size_t idx) const
426 {
427     if (idx < m_argv.size())
428         return m_argv[idx];
429     return NULL;
430 }
431
432 char
433 Args::GetArgumentQuoteCharAtIndex (size_t idx) const
434 {
435     if (idx < m_args_quote_char.size())
436         return m_args_quote_char[idx];
437     return '\0';
438 }
439
440 char **
441 Args::GetArgumentVector()
442 {
443     if (!m_argv.empty())
444         return (char **)&m_argv[0];
445     return NULL;
446 }
447
448 const char **
449 Args::GetConstArgumentVector() const
450 {
451     if (!m_argv.empty())
452         return (const char **)&m_argv[0];
453     return NULL;
454 }
455
456 void
457 Args::Shift ()
458 {
459     // Don't pop the last NULL terminator from the argv array
460     if (m_argv.size() > 1)
461     {
462         m_argv.erase(m_argv.begin());
463         m_args.pop_front();
464         if (!m_args_quote_char.empty())
465             m_args_quote_char.erase(m_args_quote_char.begin());
466     }
467 }
468
469 const char *
470 Args::Unshift (const char *arg_cstr, char quote_char)
471 {
472     m_args.push_front(arg_cstr);
473     m_argv.insert(m_argv.begin(), m_args.front().c_str());
474     m_args_quote_char.insert(m_args_quote_char.begin(), quote_char);
475     return GetArgumentAtIndex (0);
476 }
477
478 void
479 Args::AppendArguments (const Args &rhs)
480 {
481     const size_t rhs_argc = rhs.GetArgumentCount();
482     for (size_t i=0; i<rhs_argc; ++i)
483         AppendArgument(rhs.GetArgumentAtIndex(i));
484 }
485
486 void
487 Args::AppendArguments (const char **argv)
488 {
489     if (argv)
490     {
491         for (uint32_t i=0; argv[i]; ++i)
492             AppendArgument(argv[i]);
493     }
494 }
495
496 const char *
497 Args::AppendArgument (const char *arg_cstr, char quote_char)
498 {
499     return InsertArgumentAtIndex (GetArgumentCount(), arg_cstr, quote_char);
500 }
501
502 const char *
503 Args::InsertArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
504 {
505     // Since we are using a std::list to hold onto the copied C string and
506     // we don't have direct access to the elements, we have to iterate to
507     // find the value.
508     arg_sstr_collection::iterator pos, end = m_args.end();
509     size_t i = idx;
510     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
511         --i;
512
513     pos = m_args.insert(pos, arg_cstr);
514     
515     if (idx >= m_args_quote_char.size())
516     {
517         m_args_quote_char.resize(idx + 1);
518         m_args_quote_char[idx] = quote_char;
519     }
520     else
521         m_args_quote_char.insert(m_args_quote_char.begin() + idx, quote_char);
522     
523     UpdateArgvFromArgs();
524     return GetArgumentAtIndex(idx);
525 }
526
527 const char *
528 Args::ReplaceArgumentAtIndex (size_t idx, const char *arg_cstr, char quote_char)
529 {
530     // Since we are using a std::list to hold onto the copied C string and
531     // we don't have direct access to the elements, we have to iterate to
532     // find the value.
533     arg_sstr_collection::iterator pos, end = m_args.end();
534     size_t i = idx;
535     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
536         --i;
537
538     if (pos != end)
539     {
540         pos->assign(arg_cstr);
541         assert(idx < m_argv.size() - 1);
542         m_argv[idx] = pos->c_str();
543         if (idx >= m_args_quote_char.size())
544             m_args_quote_char.resize(idx + 1);
545         m_args_quote_char[idx] = quote_char;
546         return GetArgumentAtIndex(idx);
547     }
548     return NULL;
549 }
550
551 void
552 Args::DeleteArgumentAtIndex (size_t idx)
553 {
554     // Since we are using a std::list to hold onto the copied C string and
555     // we don't have direct access to the elements, we have to iterate to
556     // find the value.
557     arg_sstr_collection::iterator pos, end = m_args.end();
558     size_t i = idx;
559     for (pos = m_args.begin(); i > 0 && pos != end; ++pos)
560         --i;
561
562     if (pos != end)
563     {
564         m_args.erase (pos);
565         assert(idx < m_argv.size() - 1);
566         m_argv.erase(m_argv.begin() + idx);
567         if (idx < m_args_quote_char.size())
568             m_args_quote_char.erase(m_args_quote_char.begin() + idx);
569     }
570 }
571
572 void
573 Args::SetArguments (size_t argc, const char **argv)
574 {
575     // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
576     // no need to clear it here.
577     m_args.clear();
578     m_args_quote_char.clear();
579
580     // First copy each string
581     for (size_t i=0; i<argc; ++i)
582     {
583         m_args.push_back (argv[i]);
584         if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
585             m_args_quote_char.push_back (argv[i][0]);
586         else
587             m_args_quote_char.push_back ('\0');
588     }
589
590     UpdateArgvFromArgs();
591 }
592
593 void
594 Args::SetArguments (const char **argv)
595 {
596     // m_argv will be rebuilt in UpdateArgvFromArgs() below, so there is
597     // no need to clear it here.
598     m_args.clear();
599     m_args_quote_char.clear();
600     
601     if (argv)
602     {
603         // First copy each string
604         for (size_t i=0; argv[i]; ++i)
605         {
606             m_args.push_back (argv[i]);
607             if ((argv[i][0] == '\'') || (argv[i][0] == '"') || (argv[i][0] == '`'))
608                 m_args_quote_char.push_back (argv[i][0]);
609             else
610                 m_args_quote_char.push_back ('\0');
611         }
612     }
613     
614     UpdateArgvFromArgs();
615 }
616
617
618 Error
619 Args::ParseOptions (Options &options)
620 {
621     StreamString sstr;
622     Error error;
623     Option *long_options = options.GetLongOptions();
624     if (long_options == NULL)
625     {
626         error.SetErrorStringWithFormat("invalid long options");
627         return error;
628     }
629
630     for (int i=0; long_options[i].name != NULL; ++i)
631     {
632         if (long_options[i].flag == NULL)
633         {
634             if (isprint8(long_options[i].val))
635             {
636                 sstr << (char)long_options[i].val;
637                 switch (long_options[i].has_arg)
638                 {
639                 default:
640                 case OptionParser::eNoArgument:                       break;
641                 case OptionParser::eRequiredArgument: sstr << ':';    break;
642                 case OptionParser::eOptionalArgument: sstr << "::";   break;
643                 }
644             }
645         }
646     }
647     OptionParser::Prepare();
648     int val;
649     while (1)
650     {
651         int long_options_index = -1;
652         val = OptionParser::Parse(GetArgumentCount(),
653                                  GetArgumentVector(),
654                                  sstr.GetData(),
655                                  long_options,
656                                  &long_options_index);
657         if (val == -1)
658             break;
659
660         // Did we get an error?
661         if (val == '?')
662         {
663             error.SetErrorStringWithFormat("unknown or ambiguous option");
664             break;
665         }
666         // The option auto-set itself
667         if (val == 0)
668             continue;
669
670         ((Options *) &options)->OptionSeen (val);
671
672         // Lookup the long option index
673         if (long_options_index == -1)
674         {
675             for (int i=0;
676                  long_options[i].name || long_options[i].has_arg || long_options[i].flag || long_options[i].val;
677                  ++i)
678             {
679                 if (long_options[i].val == val)
680                 {
681                     long_options_index = i;
682                     break;
683                 }
684             }
685         }
686         // Call the callback with the option
687         if (long_options_index >= 0)
688         {
689             error = options.SetOptionValue(long_options_index,
690                                            long_options[long_options_index].has_arg == OptionParser::eNoArgument ? NULL : OptionParser::GetOptionArgument());
691         }
692         else
693         {
694             error.SetErrorStringWithFormat("invalid option with value '%i'", val);
695         }
696         if (error.Fail())
697             break;
698     }
699
700     // Update our ARGV now that get options has consumed all the options
701     m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
702     UpdateArgsAfterOptionParsing ();
703     return error;
704 }
705
706 void
707 Args::Clear ()
708 {
709     m_args.clear ();
710     m_argv.clear ();
711     m_args_quote_char.clear();
712 }
713
714 int32_t
715 Args::StringToSInt32 (const char *s, int32_t fail_value, int base, bool *success_ptr)
716 {
717     if (s && s[0])
718     {
719         char *end = NULL;
720         const long sval = ::strtol (s, &end, base);
721         if (*end == '\0')
722         {
723             if (success_ptr)
724                 *success_ptr = ((sval <= INT32_MAX) && (sval >= INT32_MIN));
725             return (int32_t)sval; // All characters were used, return the result
726         }
727     }
728     if (success_ptr) *success_ptr = false;
729     return fail_value;
730 }
731
732 uint32_t
733 Args::StringToUInt32 (const char *s, uint32_t fail_value, int base, bool *success_ptr)
734 {
735     if (s && s[0])
736     {
737         char *end = NULL;
738         const unsigned long uval = ::strtoul (s, &end, base);
739         if (*end == '\0')
740         {
741             if (success_ptr)
742                 *success_ptr = (uval <= UINT32_MAX);
743             return (uint32_t)uval; // All characters were used, return the result
744         }
745     }
746     if (success_ptr) *success_ptr = false;
747     return fail_value;
748 }
749
750
751 int64_t
752 Args::StringToSInt64 (const char *s, int64_t fail_value, int base, bool *success_ptr)
753 {
754     if (s && s[0])
755     {
756         char *end = NULL;
757         int64_t uval = ::strtoll (s, &end, base);
758         if (*end == '\0')
759         {
760             if (success_ptr) *success_ptr = true;
761             return uval; // All characters were used, return the result
762         }
763     }
764     if (success_ptr) *success_ptr = false;
765     return fail_value;
766 }
767
768 uint64_t
769 Args::StringToUInt64 (const char *s, uint64_t fail_value, int base, bool *success_ptr)
770 {
771     if (s && s[0])
772     {
773         char *end = NULL;
774         uint64_t uval = ::strtoull (s, &end, base);
775         if (*end == '\0')
776         {
777             if (success_ptr) *success_ptr = true;
778             return uval; // All characters were used, return the result
779         }
780     }
781     if (success_ptr) *success_ptr = false;
782     return fail_value;
783 }
784
785 lldb::addr_t
786 Args::StringToAddress (const ExecutionContext *exe_ctx, const char *s, lldb::addr_t fail_value, Error *error_ptr)
787 {
788     bool error_set = false;
789     if (s && s[0])
790     {
791         char *end = NULL;
792         lldb::addr_t addr = ::strtoull (s, &end, 0);
793         if (*end == '\0')
794         {
795             if (error_ptr)
796                 error_ptr->Clear();
797             return addr; // All characters were used, return the result
798         }
799         // Try base 16 with no prefix...
800         addr = ::strtoull (s, &end, 16);
801         if (*end == '\0')
802         {
803             if (error_ptr)
804                 error_ptr->Clear();
805             return addr; // All characters were used, return the result
806         }
807         
808         if (exe_ctx)
809         {
810             Target *target = exe_ctx->GetTargetPtr();
811             if (target)
812             {
813                 lldb::ValueObjectSP valobj_sp;
814                 EvaluateExpressionOptions options;
815                 options.SetCoerceToId(false);
816                 options.SetUnwindOnError(true);
817                 options.SetKeepInMemory(false);
818                 options.SetTryAllThreads(true);
819                 
820                 ExecutionResults expr_result = target->EvaluateExpression(s,
821                                                                           exe_ctx->GetFramePtr(),
822                                                                           valobj_sp,
823                                                                           options);
824
825                 bool success = false;
826                 if (expr_result == eExecutionCompleted)
827                 {
828                     // Get the address to watch.
829                     addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
830                     if (success)
831                     {
832                         if (error_ptr)
833                             error_ptr->Clear();
834                         return addr;
835                     }
836                     else
837                     {
838                         if (error_ptr)
839                         {
840                             error_set = true;
841                             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());
842                         }
843                     }
844                     
845                 }
846                 else
847                 {
848                     // Since the compiler can't handle things like "main + 12" we should
849                     // try to do this for now. The compliler doesn't like adding offsets
850                     // to function pointer types.
851                     static RegularExpression g_symbol_plus_offset_regex("^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
852                     RegularExpression::Match regex_match(3);
853                     if (g_symbol_plus_offset_regex.Execute(s, &regex_match))
854                     {
855                         uint64_t offset = 0;
856                         bool add = true;
857                         std::string name;
858                         std::string str;
859                         if (regex_match.GetMatchAtIndex(s, 1, name))
860                         {
861                             if (regex_match.GetMatchAtIndex(s, 2, str))
862                             {
863                                 add = str[0] == '+';
864                                 
865                                 if (regex_match.GetMatchAtIndex(s, 3, str))
866                                 {
867                                     offset = Args::StringToUInt64(str.c_str(), 0, 0, &success);
868                                     
869                                     if (success)
870                                     {
871                                         Error error;
872                                         addr = StringToAddress (exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
873                                         if (addr != LLDB_INVALID_ADDRESS)
874                                         {
875                                             if (add)
876                                                 return addr + offset;
877                                             else
878                                                 return addr - offset;
879                                         }
880                                     }
881                                 }
882                             }
883                         }
884                     }
885                     
886                     if (error_ptr)
887                     {
888                         error_set = true;
889                         error_ptr->SetErrorStringWithFormat("address expression \"%s\" evaluation failed", s);
890                     }
891                 }
892             }
893         }
894     }
895     if (error_ptr)
896     {
897         if (!error_set)
898             error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"", s);
899     }
900     return fail_value;
901 }
902
903 const char *
904 Args::StripSpaces (std::string &s, bool leading, bool trailing, bool return_null_if_empty)
905 {
906     static const char *k_white_space = " \t\v";
907     if (!s.empty())
908     {
909         if (leading)
910         {
911             size_t pos = s.find_first_not_of (k_white_space);
912             if (pos == std::string::npos)
913                 s.clear();
914             else if (pos > 0)
915                 s.erase(0, pos);
916         }
917         
918         if (trailing)
919         {
920             size_t rpos = s.find_last_not_of(k_white_space);
921             if (rpos != std::string::npos && rpos + 1 < s.size())
922                 s.erase(rpos + 1);
923         }
924     }
925     if (return_null_if_empty && s.empty())
926         return NULL;
927     return s.c_str();
928 }
929
930 bool
931 Args::StringToBoolean (const char *s, bool fail_value, bool *success_ptr)
932 {
933     if (s && s[0])
934     {
935         if (::strcasecmp (s, "false") == 0 ||
936             ::strcasecmp (s, "off") == 0 ||
937             ::strcasecmp (s, "no") == 0 ||
938                 ::strcmp (s, "0") == 0)
939         {
940             if (success_ptr)
941                 *success_ptr = true;
942             return false;
943         }
944         else
945         if (::strcasecmp (s, "true") == 0 ||
946             ::strcasecmp (s, "on") == 0 ||
947             ::strcasecmp (s, "yes") == 0 ||
948                 ::strcmp (s, "1") == 0)
949         {
950             if (success_ptr) *success_ptr = true;
951             return true;
952         }
953     }
954     if (success_ptr) *success_ptr = false;
955     return fail_value;
956 }
957
958 const char *
959 Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update)
960 {
961     major = UINT32_MAX;
962     minor = UINT32_MAX;
963     update = UINT32_MAX;
964
965     if (s && s[0])
966     {
967         char *pos = NULL;
968         unsigned long uval32 = ::strtoul (s, &pos, 0);
969         if (pos == s)
970             return s;
971         major = uval32;
972         if (*pos == '\0')
973         {
974             return pos;   // Decoded major and got end of string
975         }
976         else if (*pos == '.')
977         {
978             const char *minor_cstr = pos + 1;
979             uval32 = ::strtoul (minor_cstr, &pos, 0);
980             if (pos == minor_cstr)
981                 return pos; // Didn't get any digits for the minor version...
982             minor = uval32;
983             if (*pos == '.')
984             {
985                 const char *update_cstr = pos + 1;
986                 uval32 = ::strtoul (update_cstr, &pos, 0);
987                 if (pos == update_cstr)
988                     return pos;
989                 update = uval32;
990             }
991             return pos;
992         }
993     }
994     return 0;
995 }
996
997 const char *
998 Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg)
999 {
1000     safe_arg.assign (unsafe_arg);
1001     size_t prev_pos = 0;
1002     while (prev_pos < safe_arg.size())
1003     {
1004         // Escape spaces and quotes
1005         size_t pos = safe_arg.find_first_of(" '\"", prev_pos);
1006         if (pos != std::string::npos)
1007         {
1008             safe_arg.insert (pos, 1, '\\');
1009             prev_pos = pos + 2;
1010         }
1011         else
1012             break;
1013     }
1014     return safe_arg.c_str();
1015 }
1016
1017
1018 int64_t
1019 Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error)
1020 {    
1021     if (enum_values)
1022     {
1023         if (s && s[0])
1024         {
1025             for (int i = 0; enum_values[i].string_value != NULL ; i++) 
1026             {
1027                 if (strstr(enum_values[i].string_value, s) == enum_values[i].string_value)
1028                 {
1029                     error.Clear();
1030                     return enum_values[i].value;
1031                 }
1032             }
1033         }
1034
1035         StreamString strm;
1036         strm.PutCString ("invalid enumeration value, valid values are: ");
1037         for (int i = 0; enum_values[i].string_value != NULL; i++) 
1038         {
1039             strm.Printf ("%s\"%s\"", 
1040                          i > 0 ? ", " : "",
1041                          enum_values[i].string_value);
1042         }
1043         error.SetErrorString(strm.GetData());
1044     }
1045     else
1046     {
1047         error.SetErrorString ("invalid enumeration argument");
1048     }
1049     return fail_value;
1050 }
1051
1052 ScriptLanguage
1053 Args::StringToScriptLanguage (const char *s, ScriptLanguage fail_value, bool *success_ptr)
1054 {
1055     if (s && s[0])
1056     {
1057         if ((::strcasecmp (s, "python") == 0) ||
1058             (::strcasecmp (s, "default") == 0 && eScriptLanguagePython == eScriptLanguageDefault))
1059         {
1060             if (success_ptr) *success_ptr = true;
1061             return eScriptLanguagePython;
1062         }
1063         if (::strcasecmp (s, "none"))
1064         {
1065             if (success_ptr) *success_ptr = true;
1066             return eScriptLanguageNone;
1067         }
1068     }
1069     if (success_ptr) *success_ptr = false;
1070     return fail_value;
1071 }
1072
1073 Error
1074 Args::StringToFormat
1075 (
1076     const char *s,
1077     lldb::Format &format,
1078     size_t *byte_size_ptr
1079 )
1080 {
1081     format = eFormatInvalid;
1082     Error error;
1083
1084     if (s && s[0])
1085     {
1086         if (byte_size_ptr)
1087         {
1088             if (isdigit (s[0]))
1089             {
1090                 char *format_char = NULL;
1091                 unsigned long byte_size = ::strtoul (s, &format_char, 0);
1092                 if (byte_size != ULONG_MAX)
1093                     *byte_size_ptr = byte_size;
1094                 s = format_char;
1095             }
1096             else
1097                 *byte_size_ptr = 0;
1098         }
1099
1100         const bool partial_match_ok = true;
1101         if (!FormatManager::GetFormatFromCString (s, partial_match_ok, format))
1102         {
1103             StreamString error_strm;
1104             error_strm.Printf ("Invalid format character or name '%s'. Valid values are:\n", s);
1105             for (Format f = eFormatDefault; f < kNumFormats; f = Format(f+1))
1106             {
1107                 char format_char = FormatManager::GetFormatAsFormatChar(f);
1108                 if (format_char)
1109                     error_strm.Printf ("'%c' or ", format_char);
1110             
1111                 error_strm.Printf ("\"%s\"", FormatManager::GetFormatAsCString(f));
1112                 error_strm.EOL();
1113             }
1114             
1115             if (byte_size_ptr)
1116                 error_strm.PutCString ("An optional byte size can precede the format character.\n");
1117             error.SetErrorString(error_strm.GetString().c_str());
1118         }
1119
1120         if (error.Fail())
1121             return error;
1122     }
1123     else
1124     {
1125         error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
1126     }
1127     return error;
1128 }
1129
1130 lldb::Encoding
1131 Args::StringToEncoding (const char *s, lldb::Encoding fail_value)
1132 {
1133     if (s && s[0])
1134     {
1135         if (strcmp(s, "uint") == 0)
1136             return eEncodingUint;
1137         else if (strcmp(s, "sint") == 0)
1138             return eEncodingSint;
1139         else if (strcmp(s, "ieee754") == 0)
1140             return eEncodingIEEE754;
1141         else if (strcmp(s, "vector") == 0)
1142             return eEncodingVector;
1143     }
1144     return fail_value;
1145 }
1146
1147 uint32_t
1148 Args::StringToGenericRegister (const char *s)
1149 {
1150     if (s && s[0])
1151     {
1152         if (strcmp(s, "pc") == 0)
1153             return LLDB_REGNUM_GENERIC_PC;
1154         else if (strcmp(s, "sp") == 0)
1155             return LLDB_REGNUM_GENERIC_SP;
1156         else if (strcmp(s, "fp") == 0)
1157             return LLDB_REGNUM_GENERIC_FP;
1158         else if (strcmp(s, "ra") == 0)
1159             return LLDB_REGNUM_GENERIC_RA;
1160         else if (strcmp(s, "flags") == 0)
1161             return LLDB_REGNUM_GENERIC_FLAGS;
1162         else if (strncmp(s, "arg", 3) == 0)
1163         {
1164             if (s[3] && s[4] == '\0')
1165             {
1166                 switch (s[3])
1167                 {
1168                     case '1': return LLDB_REGNUM_GENERIC_ARG1;
1169                     case '2': return LLDB_REGNUM_GENERIC_ARG2;
1170                     case '3': return LLDB_REGNUM_GENERIC_ARG3;
1171                     case '4': return LLDB_REGNUM_GENERIC_ARG4;
1172                     case '5': return LLDB_REGNUM_GENERIC_ARG5;
1173                     case '6': return LLDB_REGNUM_GENERIC_ARG6;
1174                     case '7': return LLDB_REGNUM_GENERIC_ARG7;
1175                     case '8': return LLDB_REGNUM_GENERIC_ARG8;
1176                 }
1177             }
1178         }
1179     }
1180     return LLDB_INVALID_REGNUM;
1181 }
1182
1183
1184 void
1185 Args::LongestCommonPrefix (std::string &common_prefix)
1186 {
1187     arg_sstr_collection::iterator pos, end = m_args.end();
1188     pos = m_args.begin();
1189     if (pos == end)
1190         common_prefix.clear();
1191     else
1192         common_prefix = (*pos);
1193
1194     for (++pos; pos != end; ++pos)
1195     {
1196         size_t new_size = (*pos).size();
1197
1198         // First trim common_prefix if it is longer than the current element:
1199         if (common_prefix.size() > new_size)
1200             common_prefix.erase (new_size);
1201
1202         // Then trim it at the first disparity:
1203
1204         for (size_t i = 0; i < common_prefix.size(); i++)
1205         {
1206             if ((*pos)[i]  != common_prefix[i])
1207             {
1208                 common_prefix.erase(i);
1209                 break;
1210             }
1211         }
1212
1213         // If we've emptied the common prefix, we're done.
1214         if (common_prefix.empty())
1215             break;
1216     }
1217 }
1218
1219 size_t
1220 Args::FindArgumentIndexForOption (Option *long_options, int long_options_index)
1221 {
1222     char short_buffer[3];
1223     char long_buffer[255];
1224     ::snprintf (short_buffer, sizeof (short_buffer), "-%c", long_options[long_options_index].val);
1225     ::snprintf (long_buffer, sizeof (long_buffer),  "--%s", long_options[long_options_index].name);
1226     size_t end = GetArgumentCount ();
1227     size_t idx = 0;
1228     while (idx < end)
1229     {   
1230         if ((::strncmp (GetArgumentAtIndex (idx), short_buffer, strlen (short_buffer)) == 0)
1231             || (::strncmp (GetArgumentAtIndex (idx), long_buffer, strlen (long_buffer)) == 0))
1232             {
1233                 return idx;
1234             }
1235         ++idx;
1236     }
1237
1238     return end;
1239 }
1240
1241 bool
1242 Args::IsPositionalArgument (const char *arg)
1243 {
1244     if (arg == NULL)
1245         return false;
1246         
1247     bool is_positional = true;
1248     char *cptr = (char *) arg;
1249     
1250     if (cptr[0] == '%')
1251     {
1252         ++cptr;
1253         while (isdigit (cptr[0]))
1254             ++cptr;
1255         if (cptr[0] != '\0')
1256             is_positional = false;
1257     }
1258     else
1259         is_positional = false;
1260
1261     return is_positional;
1262 }
1263
1264 void
1265 Args::ParseAliasOptions (Options &options,
1266                          CommandReturnObject &result,
1267                          OptionArgVector *option_arg_vector,
1268                          std::string &raw_input_string)
1269 {
1270     StreamString sstr;
1271     int i;
1272     Option *long_options = options.GetLongOptions();
1273
1274     if (long_options == NULL)
1275     {
1276         result.AppendError ("invalid long options");
1277         result.SetStatus (eReturnStatusFailed);
1278         return;
1279     }
1280
1281     for (i = 0; long_options[i].name != NULL; ++i)
1282     {
1283         if (long_options[i].flag == NULL)
1284         {
1285             sstr << (char) long_options[i].val;
1286             switch (long_options[i].has_arg)
1287             {
1288                 default:
1289                 case OptionParser::eNoArgument:
1290                     break;
1291                 case OptionParser::eRequiredArgument:
1292                     sstr << ":";
1293                     break;
1294                 case OptionParser::eOptionalArgument:
1295                     sstr << "::";
1296                     break;
1297             }
1298         }
1299     }
1300
1301     OptionParser::Prepare();
1302     int val;
1303     while (1)
1304     {
1305         int long_options_index = -1;
1306         val = OptionParser::Parse (GetArgumentCount(),
1307                                   GetArgumentVector(),
1308                                   sstr.GetData(),
1309                                   long_options,
1310                                   &long_options_index);
1311
1312         if (val == -1)
1313             break;
1314
1315         if (val == '?')
1316         {
1317             result.AppendError ("unknown or ambiguous option");
1318             result.SetStatus (eReturnStatusFailed);
1319             break;
1320         }
1321
1322         if (val == 0)
1323             continue;
1324
1325         ((Options *) &options)->OptionSeen (val);
1326
1327         // Look up the long option index
1328         if (long_options_index == -1)
1329         {
1330             for (int j = 0;
1331                  long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1332                  ++j)
1333             {
1334                 if (long_options[j].val == val)
1335                 {
1336                     long_options_index = j;
1337                     break;
1338                 }
1339             }
1340         }
1341
1342         // See if the option takes an argument, and see if one was supplied.
1343         if (long_options_index >= 0)
1344         {
1345             StreamString option_str;
1346             option_str.Printf ("-%c", val);
1347
1348             switch (long_options[long_options_index].has_arg)
1349             {
1350             case OptionParser::eNoArgument:
1351                 option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()), 
1352                                                              OptionArgValue (OptionParser::eNoArgument, "<no-argument>")));
1353                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1354                 break;
1355             case OptionParser::eRequiredArgument:
1356                 if (OptionParser::GetOptionArgument() != NULL)
1357                 {
1358                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1359                                                                  OptionArgValue (OptionParser::eRequiredArgument,
1360                                                                                  std::string (OptionParser::GetOptionArgument()))));
1361                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1362                 }
1363                 else
1364                 {
1365                     result.AppendErrorWithFormat ("Option '%s' is missing argument specifier.\n",
1366                                                  option_str.GetData());
1367                     result.SetStatus (eReturnStatusFailed);
1368                 }
1369                 break;
1370             case OptionParser::eOptionalArgument:
1371                 if (OptionParser::GetOptionArgument() != NULL)
1372                 {
1373                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1374                                                                  OptionArgValue (OptionParser::eOptionalArgument,
1375                                                                                  std::string (OptionParser::GetOptionArgument()))));
1376                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1377                 }
1378                 else
1379                 {
1380                     option_arg_vector->push_back (OptionArgPair (std::string (option_str.GetData()),
1381                                                                  OptionArgValue (OptionParser::eOptionalArgument, "<no-argument>")));
1382                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1383                 }
1384                 break;
1385             default:
1386                 result.AppendErrorWithFormat ("error with options table; invalid value in has_arg field for option '%c'.\n", val);
1387                 result.SetStatus (eReturnStatusFailed);
1388                 break;
1389             }
1390         }
1391         else
1392         {
1393             result.AppendErrorWithFormat ("Invalid option with value '%c'.\n", val);
1394             result.SetStatus (eReturnStatusFailed);
1395         }
1396
1397         if (long_options_index >= 0)
1398         {
1399             // Find option in the argument list; also see if it was supposed to take an argument and if one was
1400             // supplied.  Remove option (and argument, if given) from the argument list.  Also remove them from
1401             // the raw_input_string, if one was passed in.
1402             size_t idx = FindArgumentIndexForOption (long_options, long_options_index);
1403             if (idx < GetArgumentCount())
1404             {
1405                 if (raw_input_string.size() > 0)
1406                 {
1407                     const char *tmp_arg = GetArgumentAtIndex (idx);
1408                     size_t pos = raw_input_string.find (tmp_arg);
1409                     if (pos != std::string::npos)
1410                         raw_input_string.erase (pos, strlen (tmp_arg));
1411                 }
1412                 ReplaceArgumentAtIndex (idx, "");
1413                 if ((long_options[long_options_index].has_arg != OptionParser::eNoArgument)
1414                     && (OptionParser::GetOptionArgument() != NULL)
1415                     && (idx+1 < GetArgumentCount())
1416                     && (strcmp (OptionParser::GetOptionArgument(), GetArgumentAtIndex(idx+1)) == 0))
1417                 {
1418                     if (raw_input_string.size() > 0)
1419                     {
1420                         const char *tmp_arg = GetArgumentAtIndex (idx+1);
1421                         size_t pos = raw_input_string.find (tmp_arg);
1422                         if (pos != std::string::npos)
1423                             raw_input_string.erase (pos, strlen (tmp_arg));
1424                     }
1425                     ReplaceArgumentAtIndex (idx+1, "");
1426                 }
1427             }
1428         }
1429
1430         if (!result.Succeeded())
1431             break;
1432     }
1433 }
1434
1435 void
1436 Args::ParseArgsForCompletion
1437 (
1438     Options &options,
1439     OptionElementVector &option_element_vector,
1440     uint32_t cursor_index
1441 )
1442 {
1443     StreamString sstr;
1444     Option *long_options = options.GetLongOptions();
1445     option_element_vector.clear();
1446
1447     if (long_options == NULL)
1448     {
1449         return;
1450     }
1451
1452     // Leading : tells getopt to return a : for a missing option argument AND
1453     // to suppress error messages.
1454
1455     sstr << ":";
1456     for (int i = 0; long_options[i].name != NULL; ++i)
1457     {
1458         if (long_options[i].flag == NULL)
1459         {
1460             sstr << (char) long_options[i].val;
1461             switch (long_options[i].has_arg)
1462             {
1463                 default:
1464                 case OptionParser::eNoArgument:
1465                     break;
1466                 case OptionParser::eRequiredArgument:
1467                     sstr << ":";
1468                     break;
1469                 case OptionParser::eOptionalArgument:
1470                     sstr << "::";
1471                     break;
1472             }
1473         }
1474     }
1475
1476     OptionParser::Prepare();
1477     OptionParser::EnableError(false);
1478
1479     int val;
1480     const OptionDefinition *opt_defs = options.GetDefinitions();
1481
1482     // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the options to the front.
1483     // So we have to build another Arg and pass that to OptionParser::Parse so it doesn't
1484     // change the one we have.
1485
1486     std::vector<const char *> dummy_vec (GetArgumentVector(), GetArgumentVector() + GetArgumentCount() + 1);
1487
1488     bool failed_once = false;
1489     uint32_t dash_dash_pos = -1;
1490         
1491     while (1)
1492     {
1493         bool missing_argument = false;
1494         int long_options_index = -1;
1495         
1496         val = OptionParser::Parse (dummy_vec.size() - 1,
1497                                   (char *const *) &dummy_vec.front(),
1498                                   sstr.GetData(),
1499                                   long_options,
1500                                   &long_options_index);
1501
1502         if (val == -1)
1503         {
1504             // When we're completing a "--" which is the last option on line, 
1505             if (failed_once)
1506                 break;
1507                 
1508             failed_once = true;
1509             
1510             // If this is a bare  "--" we mark it as such so we can complete it successfully later.
1511             // Handling the "--" is a little tricky, since that may mean end of options or arguments, or the
1512             // user might want to complete options by long name.  I make this work by checking whether the
1513             // cursor is in the "--" argument, and if so I assume we're completing the long option, otherwise
1514             // I let it pass to OptionParser::Parse which will terminate the option parsing.
1515             // Note, in either case we continue parsing the line so we can figure out what other options
1516             // were passed.  This will be useful when we come to restricting completions based on what other
1517             // options we've seen on the line.
1518
1519             if (OptionParser::GetOptionIndex() < dummy_vec.size() - 1
1520                 && (strcmp (dummy_vec[OptionParser::GetOptionIndex()-1], "--") == 0))
1521             {
1522                 dash_dash_pos = OptionParser::GetOptionIndex() - 1;
1523                 if (OptionParser::GetOptionIndex() - 1 == cursor_index)
1524                 {
1525                     option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDoubleDash, OptionParser::GetOptionIndex() - 1,
1526                                                                    OptionArgElement::eBareDoubleDash));
1527                     continue;
1528                 }
1529                 else
1530                     break;
1531             }
1532             else
1533                 break;
1534         }
1535         else if (val == '?')
1536         {
1537             option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
1538                                                                OptionArgElement::eUnrecognizedArg));
1539             continue;
1540         }
1541         else if (val == 0)
1542         {
1543             continue;
1544         }
1545         else if (val == ':')
1546         {
1547             // This is a missing argument.
1548             val = OptionParser::GetOptionErrorCause();
1549             missing_argument = true;
1550         }
1551
1552         ((Options *) &options)->OptionSeen (val);
1553
1554         // Look up the long option index
1555         if (long_options_index == -1)
1556         {
1557             for (int j = 0;
1558                  long_options[j].name || long_options[j].has_arg || long_options[j].flag || long_options[j].val;
1559                  ++j)
1560             {
1561                 if (long_options[j].val == val)
1562                 {
1563                     long_options_index = j;
1564                     break;
1565                 }
1566             }
1567         }
1568
1569         // See if the option takes an argument, and see if one was supplied.
1570         if (long_options_index >= 0)
1571         {
1572             int opt_defs_index = -1;
1573             for (int i = 0; ; i++)
1574             {
1575                 if (opt_defs[i].short_option == 0)
1576                     break;
1577                 else if (opt_defs[i].short_option == val)
1578                 {
1579                     opt_defs_index = i;
1580                     break;
1581                 }
1582             }
1583
1584             switch (long_options[long_options_index].has_arg)
1585             {
1586             case OptionParser::eNoArgument:
1587                 option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
1588                 break;
1589             case OptionParser::eRequiredArgument:
1590                 if (OptionParser::GetOptionArgument() != NULL)
1591                 {
1592                     int arg_index;
1593                     if (missing_argument)
1594                         arg_index = -1;
1595                     else
1596                         arg_index = OptionParser::GetOptionIndex() - 1;
1597
1598                     option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
1599                 }
1600                 else
1601                 {
1602                     option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
1603                 }
1604                 break;
1605             case OptionParser::eOptionalArgument:
1606                 if (OptionParser::GetOptionArgument() != NULL)
1607                 {
1608                     option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
1609                 }
1610                 else
1611                 {
1612                     option_element_vector.push_back (OptionArgElement (opt_defs_index, OptionParser::GetOptionIndex() - 2, OptionParser::GetOptionIndex() - 1));
1613                 }
1614                 break;
1615             default:
1616                 // The options table is messed up.  Here we'll just continue
1617                 option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
1618                                                                    OptionArgElement::eUnrecognizedArg));
1619                 break;
1620             }
1621         }
1622         else
1623         {
1624             option_element_vector.push_back (OptionArgElement (OptionArgElement::eUnrecognizedArg, OptionParser::GetOptionIndex() - 1,
1625                                                                OptionArgElement::eUnrecognizedArg));
1626         }
1627     }
1628     
1629     // Finally we have to handle the case where the cursor index points at a single "-".  We want to mark that in
1630     // the option_element_vector, but only if it is not after the "--".  But it turns out that OptionParser::Parse just ignores
1631     // an isolated "-".  So we have to look it up by hand here.  We only care if it is AT the cursor position.
1632     
1633     if ((dash_dash_pos == -1 || cursor_index < dash_dash_pos)
1634          && strcmp (GetArgumentAtIndex(cursor_index), "-") == 0)
1635     {
1636         option_element_vector.push_back (OptionArgElement (OptionArgElement::eBareDash, cursor_index, 
1637                                                            OptionArgElement::eBareDash));
1638         
1639     }
1640 }
1641
1642 void
1643 Args::EncodeEscapeSequences (const char *src, std::string &dst)
1644 {
1645     dst.clear();
1646     if (src)
1647     {
1648         for (const char *p = src; *p != '\0'; ++p)
1649         {
1650             size_t non_special_chars = ::strcspn (p, "\\");
1651             if (non_special_chars > 0)
1652             {
1653                 dst.append(p, non_special_chars);
1654                 p += non_special_chars;
1655                 if (*p == '\0')
1656                     break;
1657             }
1658             
1659             if (*p == '\\')
1660             {
1661                 ++p; // skip the slash
1662                 switch (*p)
1663                 {
1664                     case 'a' : dst.append(1, '\a'); break;
1665                     case 'b' : dst.append(1, '\b'); break;
1666                     case 'f' : dst.append(1, '\f'); break;
1667                     case 'n' : dst.append(1, '\n'); break;
1668                     case 'r' : dst.append(1, '\r'); break;
1669                     case 't' : dst.append(1, '\t'); break;
1670                     case 'v' : dst.append(1, '\v'); break;
1671                     case '\\': dst.append(1, '\\'); break;
1672                     case '\'': dst.append(1, '\''); break;
1673                     case '"' : dst.append(1, '"'); break;
1674                     case '0' :
1675                         // 1 to 3 octal chars
1676                     {
1677                         // Make a string that can hold onto the initial zero char,
1678                         // up to 3 octal digits, and a terminating NULL.
1679                         char oct_str[5] = { '\0', '\0', '\0', '\0', '\0' };
1680                         
1681                         int i;
1682                         for (i=0; (p[i] >= '0' && p[i] <= '7') && i<4; ++i)
1683                             oct_str[i] = p[i];
1684                         
1685                         // We don't want to consume the last octal character since
1686                         // the main for loop will do this for us, so we advance p by
1687                         // one less than i (even if i is zero)
1688                         p += i - 1;
1689                         unsigned long octal_value = ::strtoul (oct_str, NULL, 8);
1690                         if (octal_value <= UINT8_MAX)
1691                         {
1692                             dst.append(1, (char)octal_value);
1693                         }
1694                     }
1695                         break;
1696                         
1697                     case 'x':
1698                         // hex number in the format
1699                         if (isxdigit(p[1]))
1700                         {
1701                             ++p;    // Skip the 'x'
1702                             
1703                             // Make a string that can hold onto two hex chars plus a
1704                             // NULL terminator
1705                             char hex_str[3] = { *p, '\0', '\0' };
1706                             if (isxdigit(p[1]))
1707                             {
1708                                 ++p; // Skip the first of the two hex chars
1709                                 hex_str[1] = *p;
1710                             }
1711                             
1712                             unsigned long hex_value = strtoul (hex_str, NULL, 16);
1713                             if (hex_value <= UINT8_MAX)
1714                                 dst.append (1, (char)hex_value);
1715                         }
1716                         else
1717                         {
1718                             dst.append(1, 'x');
1719                         }
1720                         break;
1721                         
1722                     default:
1723                         // Just desensitize any other character by just printing what
1724                         // came after the '\'
1725                         dst.append(1, *p);
1726                         break;
1727                         
1728                 }
1729             }
1730         }
1731     }
1732 }
1733
1734
1735 void
1736 Args::ExpandEscapedCharacters (const char *src, std::string &dst)
1737 {
1738     dst.clear();
1739     if (src)
1740     {
1741         for (const char *p = src; *p != '\0'; ++p)
1742         {
1743             if (isprint8(*p))
1744                 dst.append(1, *p);
1745             else
1746             {
1747                 switch (*p)
1748                 {
1749                     case '\a': dst.append("\\a"); break;
1750                     case '\b': dst.append("\\b"); break;
1751                     case '\f': dst.append("\\f"); break;
1752                     case '\n': dst.append("\\n"); break;
1753                     case '\r': dst.append("\\r"); break;
1754                     case '\t': dst.append("\\t"); break;
1755                     case '\v': dst.append("\\v"); break;
1756                     case '\'': dst.append("\\'"); break;
1757                     case '"': dst.append("\\\""); break;
1758                     case '\\': dst.append("\\\\"); break;
1759                     default:
1760                         {
1761                             // Just encode as octal
1762                             dst.append("\\0");
1763                             char octal_str[32];
1764                             snprintf(octal_str, sizeof(octal_str), "%o", *p);
1765                             dst.append(octal_str);
1766                         }
1767                         break;
1768                 }
1769             }
1770         }
1771     }
1772 }
1773