]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Interpreter/Args.cpp
Import tzdata 2017c
[FreeBSD/FreeBSD.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 // C Includes
11 #include <cstdlib>
12 // C++ Includes
13 // Other libraries and framework includes
14 // Project includes
15 #include "lldb/DataFormatters/FormatManager.h"
16 #include "lldb/Host/OptionParser.h"
17 #include "lldb/Interpreter/Args.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Interpreter/CommandReturnObject.h"
20 #include "lldb/Interpreter/Options.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/Stream.h"
23 #include "lldb/Utility/StreamString.h"
24
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/StringSwitch.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
32
33 // A helper function for argument parsing.
34 // Parses the initial part of the first argument using normal double quote
35 // rules:
36 // backslash escapes the double quote and itself. The parsed string is appended
37 // to the second
38 // argument. The function returns the unparsed portion of the string, starting
39 // at the closing
40 // quote.
41 static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
42                                          std::string &result) {
43   // Inside double quotes, '\' and '"' are special.
44   static const char *k_escapable_characters = "\"\\";
45   while (true) {
46     // Skip over over regular characters and append them.
47     size_t regular = quoted.find_first_of(k_escapable_characters);
48     result += quoted.substr(0, regular);
49     quoted = quoted.substr(regular);
50
51     // If we have reached the end of string or the closing quote, we're done.
52     if (quoted.empty() || quoted.front() == '"')
53       break;
54
55     // We have found a backslash.
56     quoted = quoted.drop_front();
57
58     if (quoted.empty()) {
59       // A lone backslash at the end of string, let's just append it.
60       result += '\\';
61       break;
62     }
63
64     // If the character after the backslash is not a whitelisted escapable
65     // character, we
66     // leave the character sequence untouched.
67     if (strchr(k_escapable_characters, quoted.front()) == nullptr)
68       result += '\\';
69
70     result += quoted.front();
71     quoted = quoted.drop_front();
72   }
73
74   return quoted;
75 }
76
77 static size_t ArgvToArgc(const char **argv) {
78   if (!argv)
79     return 0;
80   size_t count = 0;
81   while (*argv++)
82     ++count;
83   return count;
84 }
85
86 // A helper function for SetCommandString. Parses a single argument from the
87 // command string, processing quotes and backslashes in a shell-like manner.
88 // The function returns a tuple consisting of the parsed argument, the quote
89 // char used, and the unparsed portion of the string starting at the first
90 // unqouted, unescaped whitespace character.
91 static std::tuple<std::string, char, llvm::StringRef>
92 ParseSingleArgument(llvm::StringRef command) {
93   // Argument can be split into multiple discontiguous pieces, for example:
94   //  "Hello ""World"
95   // this would result in a single argument "Hello World" (without the quotes)
96   // since the quotes would be removed and there is not space between the
97   // strings.
98   std::string arg;
99
100   // Since we can have multiple quotes that form a single command
101   // in a command like: "Hello "world'!' (which will make a single
102   // argument "Hello world!") we remember the first quote character
103   // we encounter and use that for the quote character.
104   char first_quote_char = '\0';
105
106   bool arg_complete = false;
107   do {
108     // Skip over over regular characters and append them.
109     size_t regular = command.find_first_of(" \t\"'`\\");
110     arg += command.substr(0, regular);
111     command = command.substr(regular);
112
113     if (command.empty())
114       break;
115
116     char special = command.front();
117     command = command.drop_front();
118     switch (special) {
119     case '\\':
120       if (command.empty()) {
121         arg += '\\';
122         break;
123       }
124
125       // If the character after the backslash is not a whitelisted escapable
126       // character, we
127       // leave the character sequence untouched.
128       if (strchr(" \t\\'\"`", command.front()) == nullptr)
129         arg += '\\';
130
131       arg += command.front();
132       command = command.drop_front();
133
134       break;
135
136     case ' ':
137     case '\t':
138       // We are not inside any quotes, we just found a space after an
139       // argument. We are done.
140       arg_complete = true;
141       break;
142
143     case '"':
144     case '\'':
145     case '`':
146       // We found the start of a quote scope.
147       if (first_quote_char == '\0')
148         first_quote_char = special;
149
150       if (special == '"')
151         command = ParseDoubleQuotes(command, arg);
152       else {
153         // For single quotes, we simply skip ahead to the matching quote
154         // character
155         // (or the end of the string).
156         size_t quoted = command.find(special);
157         arg += command.substr(0, quoted);
158         command = command.substr(quoted);
159       }
160
161       // If we found a closing quote, skip it.
162       if (!command.empty())
163         command = command.drop_front();
164
165       break;
166     }
167   } while (!arg_complete);
168
169   return std::make_tuple(arg, first_quote_char, command);
170 }
171
172 Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
173   size_t size = str.size();
174   ptr.reset(new char[size + 1]);
175
176   ::memcpy(data(), str.data() ? str.data() : "", size);
177   ptr[size] = 0;
178   ref = llvm::StringRef(c_str(), size);
179 }
180
181 //----------------------------------------------------------------------
182 // Args constructor
183 //----------------------------------------------------------------------
184 Args::Args(llvm::StringRef command) { SetCommandString(command); }
185
186 Args::Args(const Args &rhs) { *this = rhs; }
187
188 Args &Args::operator=(const Args &rhs) {
189   Clear();
190
191   m_argv.clear();
192   m_entries.clear();
193   for (auto &entry : rhs.m_entries) {
194     m_entries.emplace_back(entry.ref, entry.quote);
195     m_argv.push_back(m_entries.back().data());
196   }
197   m_argv.push_back(nullptr);
198   return *this;
199 }
200
201 //----------------------------------------------------------------------
202 // Destructor
203 //----------------------------------------------------------------------
204 Args::~Args() {}
205
206 void Args::Dump(Stream &s, const char *label_name) const {
207   if (!label_name)
208     return;
209
210   int i = 0;
211   for (auto &entry : m_entries) {
212     s.Indent();
213     s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref);
214   }
215   s.Format("{0}[{1}]=NULL\n", label_name, i);
216   s.EOL();
217 }
218
219 bool Args::GetCommandString(std::string &command) const {
220   command.clear();
221
222   for (size_t i = 0; i < m_entries.size(); ++i) {
223     if (i > 0)
224       command += ' ';
225     command += m_entries[i].ref;
226   }
227
228   return !m_entries.empty();
229 }
230
231 bool Args::GetQuotedCommandString(std::string &command) const {
232   command.clear();
233
234   for (size_t i = 0; i < m_entries.size(); ++i) {
235     if (i > 0)
236       command += ' ';
237
238     if (m_entries[i].quote) {
239       command += m_entries[i].quote;
240       command += m_entries[i].ref;
241       command += m_entries[i].quote;
242     } else {
243       command += m_entries[i].ref;
244     }
245   }
246
247   return !m_entries.empty();
248 }
249
250 void Args::SetCommandString(llvm::StringRef command) {
251   Clear();
252   m_argv.clear();
253
254   static const char *k_space_separators = " \t";
255   command = command.ltrim(k_space_separators);
256   std::string arg;
257   char quote;
258   while (!command.empty()) {
259     std::tie(arg, quote, command) = ParseSingleArgument(command);
260     m_entries.emplace_back(arg, quote);
261     m_argv.push_back(m_entries.back().data());
262     command = command.ltrim(k_space_separators);
263   }
264   m_argv.push_back(nullptr);
265 }
266
267 void Args::UpdateArgsAfterOptionParsing() {
268   assert(!m_argv.empty());
269   assert(m_argv.back() == nullptr);
270
271   // Now m_argv might be out of date with m_entries, so we need to fix that.
272   // This happens because getopt_long_only may permute the order of the
273   // arguments in argv, so we need to re-order the quotes and the refs array
274   // to match.
275   for (size_t i = 0; i < m_argv.size() - 1; ++i) {
276     const char *argv = m_argv[i];
277     auto pos =
278         std::find_if(m_entries.begin() + i, m_entries.end(),
279                      [argv](const ArgEntry &D) { return D.c_str() == argv; });
280     assert(pos != m_entries.end());
281     size_t distance = std::distance(m_entries.begin(), pos);
282     if (i == distance)
283       continue;
284
285     assert(distance > i);
286
287     std::swap(m_entries[i], m_entries[distance]);
288     assert(m_entries[i].ref.data() == m_argv[i]);
289   }
290   m_entries.resize(m_argv.size() - 1);
291 }
292
293 size_t Args::GetArgumentCount() const { return m_entries.size(); }
294
295 const char *Args::GetArgumentAtIndex(size_t idx) const {
296   if (idx < m_argv.size())
297     return m_argv[idx];
298   return nullptr;
299 }
300
301 char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
302   if (idx < m_entries.size())
303     return m_entries[idx].quote;
304   return '\0';
305 }
306
307 char **Args::GetArgumentVector() {
308   assert(!m_argv.empty());
309   // TODO: functions like execve and posix_spawnp exhibit undefined behavior
310   // when argv or envp is null.  So the code below is actually wrong.  However,
311   // other code in LLDB depends on it being null.  The code has been acting this
312   // way for some time, so it makes sense to leave it this way until someone
313   // has the time to come along and fix it.
314   return (m_argv.size() > 1) ? m_argv.data() : nullptr;
315 }
316
317 const char **Args::GetConstArgumentVector() const {
318   assert(!m_argv.empty());
319   return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
320                              : nullptr;
321 }
322
323 void Args::Shift() {
324   // Don't pop the last NULL terminator from the argv array
325   if (m_entries.empty())
326     return;
327   m_argv.erase(m_argv.begin());
328   m_entries.erase(m_entries.begin());
329 }
330
331 void Args::Unshift(llvm::StringRef arg_str, char quote_char) {
332   InsertArgumentAtIndex(0, arg_str, quote_char);
333 }
334
335 void Args::AppendArguments(const Args &rhs) {
336   assert(m_argv.size() == m_entries.size() + 1);
337   assert(m_argv.back() == nullptr);
338   m_argv.pop_back();
339   for (auto &entry : rhs.m_entries) {
340     m_entries.emplace_back(entry.ref, entry.quote);
341     m_argv.push_back(m_entries.back().data());
342   }
343   m_argv.push_back(nullptr);
344 }
345
346 void Args::AppendArguments(const char **argv) {
347   size_t argc = ArgvToArgc(argv);
348
349   assert(m_argv.size() == m_entries.size() + 1);
350   assert(m_argv.back() == nullptr);
351   m_argv.pop_back();
352   for (auto arg : llvm::makeArrayRef(argv, argc)) {
353     m_entries.emplace_back(arg, '\0');
354     m_argv.push_back(m_entries.back().data());
355   }
356
357   m_argv.push_back(nullptr);
358 }
359
360 void Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
361   InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
362 }
363
364 void Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
365                                  char quote_char) {
366   assert(m_argv.size() == m_entries.size() + 1);
367   assert(m_argv.back() == nullptr);
368
369   if (idx > m_entries.size())
370     return;
371   m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
372   m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
373 }
374
375 void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
376                                   char quote_char) {
377   assert(m_argv.size() == m_entries.size() + 1);
378   assert(m_argv.back() == nullptr);
379
380   if (idx >= m_entries.size())
381     return;
382
383   if (arg_str.size() > m_entries[idx].ref.size()) {
384     m_entries[idx] = ArgEntry(arg_str, quote_char);
385     m_argv[idx] = m_entries[idx].data();
386   } else {
387     const char *src_data = arg_str.data() ? arg_str.data() : "";
388     ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
389     m_entries[idx].ptr[arg_str.size()] = 0;
390     m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
391   }
392 }
393
394 void Args::DeleteArgumentAtIndex(size_t idx) {
395   if (idx >= m_entries.size())
396     return;
397
398   m_argv.erase(m_argv.begin() + idx);
399   m_entries.erase(m_entries.begin() + idx);
400 }
401
402 void Args::SetArguments(size_t argc, const char **argv) {
403   Clear();
404
405   auto args = llvm::makeArrayRef(argv, argc);
406   m_entries.resize(argc);
407   m_argv.resize(argc + 1);
408   for (size_t i = 0; i < args.size(); ++i) {
409     char quote =
410         ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
411             ? args[i][0]
412             : '\0';
413
414     m_entries[i] = ArgEntry(args[i], quote);
415     m_argv[i] = m_entries[i].data();
416   }
417 }
418
419 void Args::SetArguments(const char **argv) {
420   SetArguments(ArgvToArgc(argv), argv);
421 }
422
423 Status Args::ParseOptions(Options &options, ExecutionContext *execution_context,
424                           PlatformSP platform_sp, bool require_validation) {
425   StreamString sstr;
426   Status error;
427   Option *long_options = options.GetLongOptions();
428   if (long_options == nullptr) {
429     error.SetErrorStringWithFormat("invalid long options");
430     return error;
431   }
432
433   for (int i = 0; long_options[i].definition != nullptr; ++i) {
434     if (long_options[i].flag == nullptr) {
435       if (isprint8(long_options[i].val)) {
436         sstr << (char)long_options[i].val;
437         switch (long_options[i].definition->option_has_arg) {
438         default:
439         case OptionParser::eNoArgument:
440           break;
441         case OptionParser::eRequiredArgument:
442           sstr << ':';
443           break;
444         case OptionParser::eOptionalArgument:
445           sstr << "::";
446           break;
447         }
448       }
449     }
450   }
451   std::unique_lock<std::mutex> lock;
452   OptionParser::Prepare(lock);
453   int val;
454   while (1) {
455     int long_options_index = -1;
456     val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
457                               sstr.GetString(), long_options,
458                               &long_options_index);
459     if (val == -1)
460       break;
461
462     // Did we get an error?
463     if (val == '?') {
464       error.SetErrorStringWithFormat("unknown or ambiguous option");
465       break;
466     }
467     // The option auto-set itself
468     if (val == 0)
469       continue;
470
471     ((Options *)&options)->OptionSeen(val);
472
473     // Lookup the long option index
474     if (long_options_index == -1) {
475       for (int i = 0; long_options[i].definition || long_options[i].flag ||
476                       long_options[i].val;
477            ++i) {
478         if (long_options[i].val == val) {
479           long_options_index = i;
480           break;
481         }
482       }
483     }
484     // Call the callback with the option
485     if (long_options_index >= 0 &&
486         long_options[long_options_index].definition) {
487       const OptionDefinition *def = long_options[long_options_index].definition;
488
489       if (!platform_sp) {
490         // User did not pass in an explicit platform.  Try to grab
491         // from the execution context.
492         TargetSP target_sp =
493             execution_context ? execution_context->GetTargetSP() : TargetSP();
494         platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
495       }
496       OptionValidator *validator = def->validator;
497
498       if (!platform_sp && require_validation) {
499         // Caller requires validation but we cannot validate as we
500         // don't have the mandatory platform against which to
501         // validate.
502         error.SetErrorString("cannot validate options: "
503                              "no platform available");
504         return error;
505       }
506
507       bool validation_failed = false;
508       if (platform_sp) {
509         // Ensure we have an execution context, empty or not.
510         ExecutionContext dummy_context;
511         ExecutionContext *exe_ctx_p =
512             execution_context ? execution_context : &dummy_context;
513         if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
514           validation_failed = true;
515           error.SetErrorStringWithFormat("Option \"%s\" invalid.  %s",
516                                          def->long_option,
517                                          def->validator->LongConditionString());
518         }
519       }
520
521       // As long as validation didn't fail, we set the option value.
522       if (!validation_failed)
523         error = options.SetOptionValue(
524             long_options_index,
525             (def->option_has_arg == OptionParser::eNoArgument)
526                 ? nullptr
527                 : OptionParser::GetOptionArgument(),
528             execution_context);
529     } else {
530       error.SetErrorStringWithFormat("invalid option with value '%i'", val);
531     }
532     if (error.Fail())
533       break;
534   }
535
536   // Update our ARGV now that get options has consumed all the options
537   m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
538   UpdateArgsAfterOptionParsing();
539   return error;
540 }
541
542 void Args::Clear() {
543   m_entries.clear();
544   m_argv.clear();
545   m_argv.push_back(nullptr);
546 }
547
548 lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx,
549                                    llvm::StringRef s, lldb::addr_t fail_value,
550                                    Status *error_ptr) {
551   bool error_set = false;
552   if (s.empty()) {
553     if (error_ptr)
554       error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
555                                           s.str().c_str());
556     return fail_value;
557   }
558
559   llvm::StringRef sref = s;
560
561   lldb::addr_t addr = LLDB_INVALID_ADDRESS;
562   if (!s.getAsInteger(0, addr)) {
563     if (error_ptr)
564       error_ptr->Clear();
565     return addr;
566   }
567
568   // Try base 16 with no prefix...
569   if (!s.getAsInteger(16, addr)) {
570     if (error_ptr)
571       error_ptr->Clear();
572     return addr;
573   }
574
575   Target *target = nullptr;
576   if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
577     if (error_ptr)
578       error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
579                                           s.str().c_str());
580     return fail_value;
581   }
582
583   lldb::ValueObjectSP valobj_sp;
584   EvaluateExpressionOptions options;
585   options.SetCoerceToId(false);
586   options.SetUnwindOnError(true);
587   options.SetKeepInMemory(false);
588   options.SetTryAllThreads(true);
589
590   ExpressionResults expr_result =
591       target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);
592
593   bool success = false;
594   if (expr_result == eExpressionCompleted) {
595     if (valobj_sp)
596       valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
597           valobj_sp->GetDynamicValueType(), true);
598     // Get the address to watch.
599     if (valobj_sp)
600       addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
601     if (success) {
602       if (error_ptr)
603         error_ptr->Clear();
604       return addr;
605     } else {
606       if (error_ptr) {
607         error_set = true;
608         error_ptr->SetErrorStringWithFormat(
609             "address expression \"%s\" resulted in a value whose type "
610             "can't be converted to an address: %s",
611             s.str().c_str(), valobj_sp->GetTypeName().GetCString());
612       }
613     }
614
615   } else {
616     // Since the compiler can't handle things like "main + 12" we should
617     // try to do this for now. The compiler doesn't like adding offsets
618     // to function pointer types.
619     static RegularExpression g_symbol_plus_offset_regex(
620         "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
621     RegularExpression::Match regex_match(3);
622     if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
623       uint64_t offset = 0;
624       bool add = true;
625       std::string name;
626       std::string str;
627       if (regex_match.GetMatchAtIndex(s, 1, name)) {
628         if (regex_match.GetMatchAtIndex(s, 2, str)) {
629           add = str[0] == '+';
630
631           if (regex_match.GetMatchAtIndex(s, 3, str)) {
632             if (!llvm::StringRef(str).getAsInteger(0, offset)) {
633               Status error;
634               addr = StringToAddress(exe_ctx, name.c_str(),
635                                      LLDB_INVALID_ADDRESS, &error);
636               if (addr != LLDB_INVALID_ADDRESS) {
637                 if (add)
638                   return addr + offset;
639                 else
640                   return addr - offset;
641               }
642             }
643           }
644         }
645       }
646     }
647
648     if (error_ptr) {
649       error_set = true;
650       error_ptr->SetErrorStringWithFormat(
651           "address expression \"%s\" evaluation failed", s.str().c_str());
652     }
653   }
654
655   if (error_ptr) {
656     if (!error_set)
657       error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
658                                           s.str().c_str());
659   }
660   return fail_value;
661 }
662
663 const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
664                               bool return_null_if_empty) {
665   static const char *k_white_space = " \t\v";
666   if (!s.empty()) {
667     if (leading) {
668       size_t pos = s.find_first_not_of(k_white_space);
669       if (pos == std::string::npos)
670         s.clear();
671       else if (pos > 0)
672         s.erase(0, pos);
673     }
674
675     if (trailing) {
676       size_t rpos = s.find_last_not_of(k_white_space);
677       if (rpos != std::string::npos && rpos + 1 < s.size())
678         s.erase(rpos + 1);
679     }
680   }
681   if (return_null_if_empty && s.empty())
682     return nullptr;
683   return s.c_str();
684 }
685
686 bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value,
687                            bool *success_ptr) {
688   if (success_ptr)
689     *success_ptr = true;
690   ref = ref.trim();
691   if (ref.equals_lower("false") || ref.equals_lower("off") ||
692       ref.equals_lower("no") || ref.equals_lower("0")) {
693     return false;
694   } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
695              ref.equals_lower("yes") || ref.equals_lower("1")) {
696     return true;
697   }
698   if (success_ptr)
699     *success_ptr = false;
700   return fail_value;
701 }
702
703 char Args::StringToChar(llvm::StringRef s, char fail_value, bool *success_ptr) {
704   if (success_ptr)
705     *success_ptr = false;
706   if (s.size() != 1)
707     return fail_value;
708
709   if (success_ptr)
710     *success_ptr = true;
711   return s[0];
712 }
713
714 bool Args::StringToVersion(llvm::StringRef string, uint32_t &major,
715                            uint32_t &minor, uint32_t &update) {
716   major = UINT32_MAX;
717   minor = UINT32_MAX;
718   update = UINT32_MAX;
719
720   if (string.empty())
721     return false;
722
723   llvm::StringRef major_str, minor_str, update_str;
724
725   std::tie(major_str, minor_str) = string.split('.');
726   std::tie(minor_str, update_str) = minor_str.split('.');
727   if (major_str.getAsInteger(10, major))
728     return false;
729   if (!minor_str.empty() && minor_str.getAsInteger(10, minor))
730     return false;
731   if (!update_str.empty() && update_str.getAsInteger(10, update))
732     return false;
733
734   return true;
735 }
736
737 const char *Args::GetShellSafeArgument(const FileSpec &shell,
738                                        const char *unsafe_arg,
739                                        std::string &safe_arg) {
740   struct ShellDescriptor {
741     ConstString m_basename;
742     const char *m_escapables;
743   };
744
745   static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
746                                        {ConstString("tcsh"), " '\"<>()&$"},
747                                        {ConstString("sh"), " '\"<>()&"}};
748
749   // safe minimal set
750   const char *escapables = " '\"";
751
752   if (auto basename = shell.GetFilename()) {
753     for (const auto &Shell : g_Shells) {
754       if (Shell.m_basename == basename) {
755         escapables = Shell.m_escapables;
756         break;
757       }
758     }
759   }
760
761   safe_arg.assign(unsafe_arg);
762   size_t prev_pos = 0;
763   while (prev_pos < safe_arg.size()) {
764     // Escape spaces and quotes
765     size_t pos = safe_arg.find_first_of(escapables, prev_pos);
766     if (pos != std::string::npos) {
767       safe_arg.insert(pos, 1, '\\');
768       prev_pos = pos + 2;
769     } else
770       break;
771   }
772   return safe_arg.c_str();
773 }
774
775 int64_t Args::StringToOptionEnum(llvm::StringRef s,
776                                  OptionEnumValueElement *enum_values,
777                                  int32_t fail_value, Status &error) {
778   error.Clear();
779   if (!enum_values) {
780     error.SetErrorString("invalid enumeration argument");
781     return fail_value;
782   }
783
784   if (s.empty()) {
785     error.SetErrorString("empty enumeration string");
786     return fail_value;
787   }
788
789   for (int i = 0; enum_values[i].string_value != nullptr; i++) {
790     llvm::StringRef this_enum(enum_values[i].string_value);
791     if (this_enum.startswith(s))
792       return enum_values[i].value;
793   }
794
795   StreamString strm;
796   strm.PutCString("invalid enumeration value, valid values are: ");
797   for (int i = 0; enum_values[i].string_value != nullptr; i++) {
798     strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
799   }
800   error.SetErrorString(strm.GetString());
801   return fail_value;
802 }
803
804 lldb::ScriptLanguage
805 Args::StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value,
806                              bool *success_ptr) {
807   if (success_ptr)
808     *success_ptr = true;
809
810   if (s.equals_lower("python"))
811     return eScriptLanguagePython;
812   if (s.equals_lower("default"))
813     return eScriptLanguageDefault;
814   if (s.equals_lower("none"))
815     return eScriptLanguageNone;
816
817   if (success_ptr)
818     *success_ptr = false;
819   return fail_value;
820 }
821
822 Status Args::StringToFormat(const char *s, lldb::Format &format,
823                             size_t *byte_size_ptr) {
824   format = eFormatInvalid;
825   Status error;
826
827   if (s && s[0]) {
828     if (byte_size_ptr) {
829       if (isdigit(s[0])) {
830         char *format_char = nullptr;
831         unsigned long byte_size = ::strtoul(s, &format_char, 0);
832         if (byte_size != ULONG_MAX)
833           *byte_size_ptr = byte_size;
834         s = format_char;
835       } else
836         *byte_size_ptr = 0;
837     }
838
839     const bool partial_match_ok = true;
840     if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
841       StreamString error_strm;
842       error_strm.Printf(
843           "Invalid format character or name '%s'. Valid values are:\n", s);
844       for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
845         char format_char = FormatManager::GetFormatAsFormatChar(f);
846         if (format_char)
847           error_strm.Printf("'%c' or ", format_char);
848
849         error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
850         error_strm.EOL();
851       }
852
853       if (byte_size_ptr)
854         error_strm.PutCString(
855             "An optional byte size can precede the format character.\n");
856       error.SetErrorString(error_strm.GetString());
857     }
858
859     if (error.Fail())
860       return error;
861   } else {
862     error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
863   }
864   return error;
865 }
866
867 lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
868                                       lldb::Encoding fail_value) {
869   return llvm::StringSwitch<lldb::Encoding>(s)
870       .Case("uint", eEncodingUint)
871       .Case("sint", eEncodingSint)
872       .Case("ieee754", eEncodingIEEE754)
873       .Case("vector", eEncodingVector)
874       .Default(fail_value);
875 }
876
877 uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
878   if (s.empty())
879     return LLDB_INVALID_REGNUM;
880   uint32_t result = llvm::StringSwitch<uint32_t>(s)
881                         .Case("pc", LLDB_REGNUM_GENERIC_PC)
882                         .Case("sp", LLDB_REGNUM_GENERIC_SP)
883                         .Case("fp", LLDB_REGNUM_GENERIC_FP)
884                         .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
885                         .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
886                         .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
887                         .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
888                         .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
889                         .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
890                         .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
891                         .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
892                         .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
893                         .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
894                         .Default(LLDB_INVALID_REGNUM);
895   return result;
896 }
897
898 void Args::AddOrReplaceEnvironmentVariable(llvm::StringRef env_var_name,
899                                            llvm::StringRef new_value) {
900   if (env_var_name.empty())
901     return;
902
903   // Build the new entry.
904   std::string var_string(env_var_name);
905   if (!new_value.empty()) {
906     var_string += "=";
907     var_string += new_value;
908   }
909
910   size_t index = 0;
911   if (ContainsEnvironmentVariable(env_var_name, &index)) {
912     ReplaceArgumentAtIndex(index, var_string);
913     return;
914   }
915
916   // We didn't find it.  Append it instead.
917   AppendArgument(var_string);
918 }
919
920 bool Args::ContainsEnvironmentVariable(llvm::StringRef env_var_name,
921                                        size_t *argument_index) const {
922   // Validate args.
923   if (env_var_name.empty())
924     return false;
925
926   // Check each arg to see if it matches the env var name.
927   for (auto arg : llvm::enumerate(m_entries)) {
928     llvm::StringRef name, value;
929     std::tie(name, value) = arg.value().ref.split('=');
930     if (name != env_var_name)
931       continue;
932
933     if (argument_index)
934       *argument_index = arg.index();
935     return true;
936   }
937
938   // We didn't find a match.
939   return false;
940 }
941
942 size_t Args::FindArgumentIndexForOption(Option *long_options,
943                                         int long_options_index) const {
944   char short_buffer[3];
945   char long_buffer[255];
946   ::snprintf(short_buffer, sizeof(short_buffer), "-%c",
947              long_options[long_options_index].val);
948   ::snprintf(long_buffer, sizeof(long_buffer), "--%s",
949              long_options[long_options_index].definition->long_option);
950
951   for (auto entry : llvm::enumerate(m_entries)) {
952     if (entry.value().ref.startswith(short_buffer) ||
953         entry.value().ref.startswith(long_buffer))
954       return entry.index();
955   }
956
957   return size_t(-1);
958 }
959
960 bool Args::IsPositionalArgument(const char *arg) {
961   if (arg == nullptr)
962     return false;
963
964   bool is_positional = true;
965   const char *cptr = arg;
966
967   if (cptr[0] == '%') {
968     ++cptr;
969     while (isdigit(cptr[0]))
970       ++cptr;
971     if (cptr[0] != '\0')
972       is_positional = false;
973   } else
974     is_positional = false;
975
976   return is_positional;
977 }
978
979 std::string Args::ParseAliasOptions(Options &options,
980                                     CommandReturnObject &result,
981                                     OptionArgVector *option_arg_vector,
982                                     llvm::StringRef raw_input_string) {
983   std::string result_string(raw_input_string);
984   StreamString sstr;
985   int i;
986   Option *long_options = options.GetLongOptions();
987
988   if (long_options == nullptr) {
989     result.AppendError("invalid long options");
990     result.SetStatus(eReturnStatusFailed);
991     return result_string;
992   }
993
994   for (i = 0; long_options[i].definition != nullptr; ++i) {
995     if (long_options[i].flag == nullptr) {
996       sstr << (char)long_options[i].val;
997       switch (long_options[i].definition->option_has_arg) {
998       default:
999       case OptionParser::eNoArgument:
1000         break;
1001       case OptionParser::eRequiredArgument:
1002         sstr << ":";
1003         break;
1004       case OptionParser::eOptionalArgument:
1005         sstr << "::";
1006         break;
1007       }
1008     }
1009   }
1010
1011   std::unique_lock<std::mutex> lock;
1012   OptionParser::Prepare(lock);
1013   result.SetStatus(eReturnStatusSuccessFinishNoResult);
1014   int val;
1015   while (1) {
1016     int long_options_index = -1;
1017     val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
1018                               sstr.GetString(), long_options,
1019                               &long_options_index);
1020
1021     if (val == -1)
1022       break;
1023
1024     if (val == '?') {
1025       result.AppendError("unknown or ambiguous option");
1026       result.SetStatus(eReturnStatusFailed);
1027       break;
1028     }
1029
1030     if (val == 0)
1031       continue;
1032
1033     options.OptionSeen(val);
1034
1035     // Look up the long option index
1036     if (long_options_index == -1) {
1037       for (int j = 0; long_options[j].definition || long_options[j].flag ||
1038                       long_options[j].val;
1039            ++j) {
1040         if (long_options[j].val == val) {
1041           long_options_index = j;
1042           break;
1043         }
1044       }
1045     }
1046
1047     // See if the option takes an argument, and see if one was supplied.
1048     if (long_options_index == -1) {
1049       result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val);
1050       result.SetStatus(eReturnStatusFailed);
1051       return result_string;
1052     }
1053
1054     StreamString option_str;
1055     option_str.Printf("-%c", val);
1056     const OptionDefinition *def = long_options[long_options_index].definition;
1057     int has_arg =
1058         (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1059
1060     const char *option_arg = nullptr;
1061     switch (has_arg) {
1062     case OptionParser::eRequiredArgument:
1063       if (OptionParser::GetOptionArgument() == nullptr) {
1064         result.AppendErrorWithFormat(
1065             "Option '%s' is missing argument specifier.\n",
1066             option_str.GetData());
1067         result.SetStatus(eReturnStatusFailed);
1068         return result_string;
1069       }
1070       LLVM_FALLTHROUGH;
1071     case OptionParser::eOptionalArgument:
1072       option_arg = OptionParser::GetOptionArgument();
1073       LLVM_FALLTHROUGH;
1074     case OptionParser::eNoArgument:
1075       break;
1076     default:
1077       result.AppendErrorWithFormat("error with options table; invalid value "
1078                                    "in has_arg field for option '%c'.\n",
1079                                    val);
1080       result.SetStatus(eReturnStatusFailed);
1081       return result_string;
1082     }
1083     if (!option_arg)
1084       option_arg = "<no-argument>";
1085     option_arg_vector->emplace_back(option_str.GetString(), has_arg,
1086                                     option_arg);
1087
1088     // Find option in the argument list; also see if it was supposed to take
1089     // an argument and if one was supplied.  Remove option (and argument, if
1090     // given) from the argument list.  Also remove them from the
1091     // raw_input_string, if one was passed in.
1092     size_t idx = FindArgumentIndexForOption(long_options, long_options_index);
1093     if (idx == size_t(-1))
1094       continue;
1095
1096     if (!result_string.empty()) {
1097       auto tmp_arg = m_entries[idx].ref;
1098       size_t pos = result_string.find(tmp_arg);
1099       if (pos != std::string::npos)
1100         result_string.erase(pos, tmp_arg.size());
1101     }
1102     ReplaceArgumentAtIndex(idx, llvm::StringRef());
1103     if ((long_options[long_options_index].definition->option_has_arg !=
1104          OptionParser::eNoArgument) &&
1105         (OptionParser::GetOptionArgument() != nullptr) &&
1106         (idx + 1 < GetArgumentCount()) &&
1107         (m_entries[idx + 1].ref == OptionParser::GetOptionArgument())) {
1108       if (result_string.size() > 0) {
1109         auto tmp_arg = m_entries[idx + 1].ref;
1110         size_t pos = result_string.find(tmp_arg);
1111         if (pos != std::string::npos)
1112           result_string.erase(pos, tmp_arg.size());
1113       }
1114       ReplaceArgumentAtIndex(idx + 1, llvm::StringRef());
1115     }
1116   }
1117   return result_string;
1118 }
1119
1120 void Args::ParseArgsForCompletion(Options &options,
1121                                   OptionElementVector &option_element_vector,
1122                                   uint32_t cursor_index) {
1123   StreamString sstr;
1124   Option *long_options = options.GetLongOptions();
1125   option_element_vector.clear();
1126
1127   if (long_options == nullptr) {
1128     return;
1129   }
1130
1131   // Leading : tells getopt to return a : for a missing option argument AND
1132   // to suppress error messages.
1133
1134   sstr << ":";
1135   for (int i = 0; long_options[i].definition != nullptr; ++i) {
1136     if (long_options[i].flag == nullptr) {
1137       sstr << (char)long_options[i].val;
1138       switch (long_options[i].definition->option_has_arg) {
1139       default:
1140       case OptionParser::eNoArgument:
1141         break;
1142       case OptionParser::eRequiredArgument:
1143         sstr << ":";
1144         break;
1145       case OptionParser::eOptionalArgument:
1146         sstr << "::";
1147         break;
1148       }
1149     }
1150   }
1151
1152   std::unique_lock<std::mutex> lock;
1153   OptionParser::Prepare(lock);
1154   OptionParser::EnableError(false);
1155
1156   int val;
1157   auto opt_defs = options.GetDefinitions();
1158
1159   // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the
1160   // options to the front. So we have to build another Arg and pass that to
1161   // OptionParser::Parse so it doesn't change the one we have.
1162
1163   std::vector<char *> dummy_vec = m_argv;
1164
1165   bool failed_once = false;
1166   uint32_t dash_dash_pos = -1;
1167
1168   while (1) {
1169     bool missing_argument = false;
1170     int long_options_index = -1;
1171
1172     val = OptionParser::Parse(dummy_vec.size() - 1, &dummy_vec[0],
1173                               sstr.GetString(), long_options,
1174                               &long_options_index);
1175
1176     if (val == -1) {
1177       // When we're completing a "--" which is the last option on line,
1178       if (failed_once)
1179         break;
1180
1181       failed_once = true;
1182
1183       // If this is a bare  "--" we mark it as such so we can complete it
1184       // successfully later.
1185       // Handling the "--" is a little tricky, since that may mean end of
1186       // options or arguments, or the
1187       // user might want to complete options by long name.  I make this work by
1188       // checking whether the
1189       // cursor is in the "--" argument, and if so I assume we're completing the
1190       // long option, otherwise
1191       // I let it pass to OptionParser::Parse which will terminate the option
1192       // parsing.
1193       // Note, in either case we continue parsing the line so we can figure out
1194       // what other options
1195       // were passed.  This will be useful when we come to restricting
1196       // completions based on what other
1197       // options we've seen on the line.
1198
1199       if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1200               dummy_vec.size() - 1 &&
1201           (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1202         dash_dash_pos = OptionParser::GetOptionIndex() - 1;
1203         if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) ==
1204             cursor_index) {
1205           option_element_vector.push_back(
1206               OptionArgElement(OptionArgElement::eBareDoubleDash,
1207                                OptionParser::GetOptionIndex() - 1,
1208                                OptionArgElement::eBareDoubleDash));
1209           continue;
1210         } else
1211           break;
1212       } else
1213         break;
1214     } else if (val == '?') {
1215       option_element_vector.push_back(
1216           OptionArgElement(OptionArgElement::eUnrecognizedArg,
1217                            OptionParser::GetOptionIndex() - 1,
1218                            OptionArgElement::eUnrecognizedArg));
1219       continue;
1220     } else if (val == 0) {
1221       continue;
1222     } else if (val == ':') {
1223       // This is a missing argument.
1224       val = OptionParser::GetOptionErrorCause();
1225       missing_argument = true;
1226     }
1227
1228     ((Options *)&options)->OptionSeen(val);
1229
1230     // Look up the long option index
1231     if (long_options_index == -1) {
1232       for (int j = 0; long_options[j].definition || long_options[j].flag ||
1233                       long_options[j].val;
1234            ++j) {
1235         if (long_options[j].val == val) {
1236           long_options_index = j;
1237           break;
1238         }
1239       }
1240     }
1241
1242     // See if the option takes an argument, and see if one was supplied.
1243     if (long_options_index >= 0) {
1244       int opt_defs_index = -1;
1245       for (size_t i = 0; i < opt_defs.size(); i++) {
1246         if (opt_defs[i].short_option != val)
1247           continue;
1248         opt_defs_index = i;
1249         break;
1250       }
1251
1252       const OptionDefinition *def = long_options[long_options_index].definition;
1253       int has_arg =
1254           (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1255       switch (has_arg) {
1256       case OptionParser::eNoArgument:
1257         option_element_vector.push_back(OptionArgElement(
1258             opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
1259         break;
1260       case OptionParser::eRequiredArgument:
1261         if (OptionParser::GetOptionArgument() != nullptr) {
1262           int arg_index;
1263           if (missing_argument)
1264             arg_index = -1;
1265           else
1266             arg_index = OptionParser::GetOptionIndex() - 1;
1267
1268           option_element_vector.push_back(OptionArgElement(
1269               opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
1270         } else {
1271           option_element_vector.push_back(OptionArgElement(
1272               opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
1273         }
1274         break;
1275       case OptionParser::eOptionalArgument:
1276         if (OptionParser::GetOptionArgument() != nullptr) {
1277           option_element_vector.push_back(OptionArgElement(
1278               opt_defs_index, OptionParser::GetOptionIndex() - 2,
1279               OptionParser::GetOptionIndex() - 1));
1280         } else {
1281           option_element_vector.push_back(OptionArgElement(
1282               opt_defs_index, OptionParser::GetOptionIndex() - 2,
1283               OptionParser::GetOptionIndex() - 1));
1284         }
1285         break;
1286       default:
1287         // The options table is messed up.  Here we'll just continue
1288         option_element_vector.push_back(
1289             OptionArgElement(OptionArgElement::eUnrecognizedArg,
1290                              OptionParser::GetOptionIndex() - 1,
1291                              OptionArgElement::eUnrecognizedArg));
1292         break;
1293       }
1294     } else {
1295       option_element_vector.push_back(
1296           OptionArgElement(OptionArgElement::eUnrecognizedArg,
1297                            OptionParser::GetOptionIndex() - 1,
1298                            OptionArgElement::eUnrecognizedArg));
1299     }
1300   }
1301
1302   // Finally we have to handle the case where the cursor index points at a
1303   // single "-".  We want to mark that in
1304   // the option_element_vector, but only if it is not after the "--".  But it
1305   // turns out that OptionParser::Parse just ignores
1306   // an isolated "-".  So we have to look it up by hand here.  We only care if
1307   // it is AT the cursor position.
1308   // Note, a single quoted dash is not the same as a single dash...
1309
1310   const ArgEntry &cursor = m_entries[cursor_index];
1311   if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1312        cursor_index < dash_dash_pos) &&
1313       cursor.quote == '\0' && cursor.ref == "-") {
1314     option_element_vector.push_back(
1315         OptionArgElement(OptionArgElement::eBareDash, cursor_index,
1316                          OptionArgElement::eBareDash));
1317   }
1318 }
1319
1320 void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
1321   dst.clear();
1322   if (src) {
1323     for (const char *p = src; *p != '\0'; ++p) {
1324       size_t non_special_chars = ::strcspn(p, "\\");
1325       if (non_special_chars > 0) {
1326         dst.append(p, non_special_chars);
1327         p += non_special_chars;
1328         if (*p == '\0')
1329           break;
1330       }
1331
1332       if (*p == '\\') {
1333         ++p; // skip the slash
1334         switch (*p) {
1335         case 'a':
1336           dst.append(1, '\a');
1337           break;
1338         case 'b':
1339           dst.append(1, '\b');
1340           break;
1341         case 'f':
1342           dst.append(1, '\f');
1343           break;
1344         case 'n':
1345           dst.append(1, '\n');
1346           break;
1347         case 'r':
1348           dst.append(1, '\r');
1349           break;
1350         case 't':
1351           dst.append(1, '\t');
1352           break;
1353         case 'v':
1354           dst.append(1, '\v');
1355           break;
1356         case '\\':
1357           dst.append(1, '\\');
1358           break;
1359         case '\'':
1360           dst.append(1, '\'');
1361           break;
1362         case '"':
1363           dst.append(1, '"');
1364           break;
1365         case '0':
1366           // 1 to 3 octal chars
1367           {
1368             // Make a string that can hold onto the initial zero char,
1369             // up to 3 octal digits, and a terminating NULL.
1370             char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
1371
1372             int i;
1373             for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
1374               oct_str[i] = p[i];
1375
1376             // We don't want to consume the last octal character since
1377             // the main for loop will do this for us, so we advance p by
1378             // one less than i (even if i is zero)
1379             p += i - 1;
1380             unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
1381             if (octal_value <= UINT8_MAX) {
1382               dst.append(1, (char)octal_value);
1383             }
1384           }
1385           break;
1386
1387         case 'x':
1388           // hex number in the format
1389           if (isxdigit(p[1])) {
1390             ++p; // Skip the 'x'
1391
1392             // Make a string that can hold onto two hex chars plus a
1393             // NULL terminator
1394             char hex_str[3] = {*p, '\0', '\0'};
1395             if (isxdigit(p[1])) {
1396               ++p; // Skip the first of the two hex chars
1397               hex_str[1] = *p;
1398             }
1399
1400             unsigned long hex_value = strtoul(hex_str, nullptr, 16);
1401             if (hex_value <= UINT8_MAX)
1402               dst.append(1, (char)hex_value);
1403           } else {
1404             dst.append(1, 'x');
1405           }
1406           break;
1407
1408         default:
1409           // Just desensitize any other character by just printing what
1410           // came after the '\'
1411           dst.append(1, *p);
1412           break;
1413         }
1414       }
1415     }
1416   }
1417 }
1418
1419 void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
1420   dst.clear();
1421   if (src) {
1422     for (const char *p = src; *p != '\0'; ++p) {
1423       if (isprint8(*p))
1424         dst.append(1, *p);
1425       else {
1426         switch (*p) {
1427         case '\a':
1428           dst.append("\\a");
1429           break;
1430         case '\b':
1431           dst.append("\\b");
1432           break;
1433         case '\f':
1434           dst.append("\\f");
1435           break;
1436         case '\n':
1437           dst.append("\\n");
1438           break;
1439         case '\r':
1440           dst.append("\\r");
1441           break;
1442         case '\t':
1443           dst.append("\\t");
1444           break;
1445         case '\v':
1446           dst.append("\\v");
1447           break;
1448         case '\'':
1449           dst.append("\\'");
1450           break;
1451         case '"':
1452           dst.append("\\\"");
1453           break;
1454         case '\\':
1455           dst.append("\\\\");
1456           break;
1457         default: {
1458           // Just encode as octal
1459           dst.append("\\0");
1460           char octal_str[32];
1461           snprintf(octal_str, sizeof(octal_str), "%o", *p);
1462           dst.append(octal_str);
1463         } break;
1464         }
1465       }
1466     }
1467   }
1468 }
1469
1470 std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
1471                                             char quote_char) {
1472   const char *chars_to_escape = nullptr;
1473   switch (quote_char) {
1474   case '\0':
1475     chars_to_escape = " \t\\'\"`";
1476     break;
1477   case '\'':
1478     chars_to_escape = "";
1479     break;
1480   case '"':
1481     chars_to_escape = "$\"`\\";
1482     break;
1483   default:
1484     assert(false && "Unhandled quote character");
1485   }
1486
1487   std::string res;
1488   res.reserve(arg.size());
1489   for (char c : arg) {
1490     if (::strchr(chars_to_escape, c))
1491       res.push_back('\\');
1492     res.push_back(c);
1493   }
1494   return res;
1495 }