blob: 3e0f4846f1b6c1245f8441aca1900e7354061942 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Args.cpp ------------------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C Includes
Eli Friedman5661f922010-06-09 10:59:23 +000011#include <cstdlib>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012// C++ Includes
13// Other libraries and framework includes
14// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015#include "lldb/Core/Stream.h"
16#include "lldb/Core/StreamFile.h"
17#include "lldb/Core/StreamString.h"
Enrico Granata5548cb52013-01-28 23:47:25 +000018#include "lldb/DataFormatters/FormatManager.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000019#include "lldb/Host/StringConvert.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000020#include "lldb/Interpreter/Args.h"
Zachary Turnerd37221d2014-07-09 16:31:49 +000021#include "lldb/Interpreter/CommandInterpreter.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Kate Stoneb9c1b512016-09-06 20:57:50 +000023#include "lldb/Interpreter/Options.h"
Greg Claytonb9d5df52012-12-06 22:49:16 +000024#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000025#include "lldb/Target/StackFrame.h"
Greg Claytonb9d5df52012-12-06 22:49:16 +000026#include "lldb/Target/Target.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027
Zachary Turner11eb9c62016-10-05 20:03:37 +000028#include "llvm/ADT/STLExtras.h"
Zachary Turner691405b2016-10-03 22:51:09 +000029#include "llvm/ADT/StringExtras.h"
Zachary Turner54695a32016-08-29 19:58:14 +000030#include "llvm/ADT/StringSwitch.h"
31
Chris Lattner30fdc8d2010-06-08 16:52:24 +000032using namespace lldb;
33using namespace lldb_private;
34
Caroline Tice2d5289d2010-12-10 00:26:54 +000035
Pavel Labath00b7f952015-03-02 12:46:22 +000036// A helper function for argument parsing.
Kate Stoneb9c1b512016-09-06 20:57:50 +000037// Parses the initial part of the first argument using normal double quote
38// rules:
39// backslash escapes the double quote and itself. The parsed string is appended
40// to the second
41// argument. The function returns the unparsed portion of the string, starting
42// at the closing
Pavel Labath00b7f952015-03-02 12:46:22 +000043// quote.
Kate Stoneb9c1b512016-09-06 20:57:50 +000044static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
45 std::string &result) {
46 // Inside double quotes, '\' and '"' are special.
47 static const char *k_escapable_characters = "\"\\";
48 while (true) {
49 // Skip over over regular characters and append them.
50 size_t regular = quoted.find_first_of(k_escapable_characters);
51 result += quoted.substr(0, regular);
52 quoted = quoted.substr(regular);
Pavel Labath00b7f952015-03-02 12:46:22 +000053
Kate Stoneb9c1b512016-09-06 20:57:50 +000054 // If we have reached the end of string or the closing quote, we're done.
55 if (quoted.empty() || quoted.front() == '"')
56 break;
Pavel Labath00b7f952015-03-02 12:46:22 +000057
Kate Stoneb9c1b512016-09-06 20:57:50 +000058 // We have found a backslash.
59 quoted = quoted.drop_front();
Pavel Labath00b7f952015-03-02 12:46:22 +000060
Kate Stoneb9c1b512016-09-06 20:57:50 +000061 if (quoted.empty()) {
62 // A lone backslash at the end of string, let's just append it.
63 result += '\\';
64 break;
Pavel Labath00b7f952015-03-02 12:46:22 +000065 }
66
Kate Stoneb9c1b512016-09-06 20:57:50 +000067 // If the character after the backslash is not a whitelisted escapable
68 // character, we
69 // leave the character sequence untouched.
70 if (strchr(k_escapable_characters, quoted.front()) == nullptr)
71 result += '\\';
72
73 result += quoted.front();
74 quoted = quoted.drop_front();
75 }
76
77 return quoted;
Pavel Labath00b7f952015-03-02 12:46:22 +000078}
79
Zachary Turner691405b2016-10-03 22:51:09 +000080static size_t ArgvToArgc(const char **argv) {
81 if (!argv)
82 return 0;
83 size_t count = 0;
84 while (*argv++)
85 ++count;
86 return count;
87}
Pavel Labath00b7f952015-03-02 12:46:22 +000088
Zachary Turner691405b2016-10-03 22:51:09 +000089// A helper function for SetCommandString. Parses a single argument from the
90// command string, processing quotes and backslashes in a shell-like manner.
91// The function returns a tuple consisting of the parsed argument, the quote
92// char used, and the unparsed portion of the string starting at the first
93// unqouted, unescaped whitespace character.
94static std::tuple<std::string, char, llvm::StringRef>
95ParseSingleArgument(llvm::StringRef command) {
96 // Argument can be split into multiple discontiguous pieces, for example:
97 // "Hello ""World"
98 // this would result in a single argument "Hello World" (without the quotes)
99 // since the quotes would be removed and there is not space between the
100 // strings.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 std::string arg;
Pavel Labath00b7f952015-03-02 12:46:22 +0000102
Kate Stoneb9c1b512016-09-06 20:57:50 +0000103 // Since we can have multiple quotes that form a single command
104 // in a command like: "Hello "world'!' (which will make a single
105 // argument "Hello world!") we remember the first quote character
106 // we encounter and use that for the quote character.
107 char first_quote_char = '\0';
Pavel Labath00b7f952015-03-02 12:46:22 +0000108
Kate Stoneb9c1b512016-09-06 20:57:50 +0000109 bool arg_complete = false;
110 do {
111 // Skip over over regular characters and append them.
112 size_t regular = command.find_first_of(" \t\"'`\\");
113 arg += command.substr(0, regular);
114 command = command.substr(regular);
Pavel Labath00b7f952015-03-02 12:46:22 +0000115
Kate Stoneb9c1b512016-09-06 20:57:50 +0000116 if (command.empty())
117 break;
Pavel Labath00b7f952015-03-02 12:46:22 +0000118
Kate Stoneb9c1b512016-09-06 20:57:50 +0000119 char special = command.front();
120 command = command.drop_front();
121 switch (special) {
122 case '\\':
123 if (command.empty()) {
124 arg += '\\';
125 break;
126 }
127
128 // If the character after the backslash is not a whitelisted escapable
129 // character, we
130 // leave the character sequence untouched.
131 if (strchr(" \t\\'\"`", command.front()) == nullptr)
132 arg += '\\';
133
134 arg += command.front();
135 command = command.drop_front();
136
137 break;
138
139 case ' ':
140 case '\t':
141 // We are not inside any quotes, we just found a space after an
142 // argument. We are done.
143 arg_complete = true;
144 break;
145
146 case '"':
147 case '\'':
148 case '`':
149 // We found the start of a quote scope.
150 if (first_quote_char == '\0')
151 first_quote_char = special;
152
153 if (special == '"')
154 command = ParseDoubleQuotes(command, arg);
155 else {
156 // For single quotes, we simply skip ahead to the matching quote
157 // character
158 // (or the end of the string).
159 size_t quoted = command.find(special);
160 arg += command.substr(0, quoted);
161 command = command.substr(quoted);
162 }
163
164 // If we found a closing quote, skip it.
165 if (!command.empty())
Pavel Labath00b7f952015-03-02 12:46:22 +0000166 command = command.drop_front();
Pavel Labath00b7f952015-03-02 12:46:22 +0000167
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 break;
169 }
170 } while (!arg_complete);
Pavel Labath00b7f952015-03-02 12:46:22 +0000171
Zachary Turner691405b2016-10-03 22:51:09 +0000172 return std::make_tuple(arg, first_quote_char, command);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173}
174
Zachary Turner691405b2016-10-03 22:51:09 +0000175Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
176 size_t size = str.size();
177 ptr.reset(new char[size + 1]);
Greg Clayton6ad07dd2010-12-19 03:41:24 +0000178
Zachary Turner691405b2016-10-03 22:51:09 +0000179 ::memcpy(data(), str.data() ? str.data() : "", size);
180 ptr[size] = 0;
181 ref = llvm::StringRef(c_str(), size);
182}
183
184//----------------------------------------------------------------------
185// Args constructor
186//----------------------------------------------------------------------
187Args::Args(llvm::StringRef command) { SetCommandString(command); }
188
189Args::Args(const Args &rhs) { *this = rhs; }
190
191Args &Args::operator=(const Args &rhs) {
192 Clear();
193
194 m_argv.clear();
195 m_entries.clear();
196 for (auto &entry : rhs.m_entries) {
197 m_entries.emplace_back(entry.ref, entry.quote);
198 m_argv.push_back(m_entries.back().data());
199 }
200 m_argv.push_back(nullptr);
201 return *this;
202}
203
204//----------------------------------------------------------------------
205// Destructor
206//----------------------------------------------------------------------
207Args::~Args() {}
208
209void Args::Dump(Stream &s, const char *label_name) const {
210 if (!label_name)
211 return;
212
213 int i = 0;
214 for (auto &entry : m_entries) {
215 s.Indent();
216 s.Printf("%s[%zi]=\"%*s\"\n", label_name, i++, entry.ref.size(),
217 entry.ref.data());
218 }
219 s.Printf("%s[%zi]=NULL\n", label_name, i);
220 s.EOL();
221}
222
223bool Args::GetCommandString(std::string &command) const {
224 command.clear();
225
226 for (size_t i = 0; i < m_entries.size(); ++i) {
227 if (i > 0)
228 command += ' ';
229 command += m_entries[i].ref;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230 }
231
Zachary Turner691405b2016-10-03 22:51:09 +0000232 return !m_entries.empty();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000233}
234
Zachary Turner691405b2016-10-03 22:51:09 +0000235bool Args::GetQuotedCommandString(std::string &command) const {
236 command.clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237
Zachary Turner691405b2016-10-03 22:51:09 +0000238 for (size_t i = 0; i < m_entries.size(); ++i) {
239 if (i > 0)
240 command += ' ';
Kate Stoneb9c1b512016-09-06 20:57:50 +0000241
Zachary Turner691405b2016-10-03 22:51:09 +0000242 if (m_entries[i].quote) {
243 command += m_entries[i].quote;
244 command += m_entries[i].ref;
245 command += m_entries[i].quote;
246 } else {
247 command += m_entries[i].ref;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000248 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 }
Pavel Labath00b7f952015-03-02 12:46:22 +0000250
Zachary Turner691405b2016-10-03 22:51:09 +0000251 return !m_entries.empty();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000252}
253
Zachary Turner691405b2016-10-03 22:51:09 +0000254void Args::SetCommandString(llvm::StringRef command) {
255 Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 m_argv.clear();
Zachary Turner691405b2016-10-03 22:51:09 +0000257
258 static const char *k_space_separators = " \t";
259 command = command.ltrim(k_space_separators);
260 std::string arg;
261 char quote;
262 while (!command.empty()) {
263 std::tie(arg, quote, command) = ParseSingleArgument(command);
264 m_entries.emplace_back(arg, quote);
265 m_argv.push_back(m_entries.back().data());
266 command = command.ltrim(k_space_separators);
267 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000268 m_argv.push_back(nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000269}
270
Zachary Turner691405b2016-10-03 22:51:09 +0000271void Args::UpdateArgsAfterOptionParsing() {
272 assert(!m_argv.empty());
273 assert(m_argv.back() == nullptr);
274
275 // Now m_argv might be out of date with m_entries, so we need to fix that.
276 // This happens because getopt_long_only may permute the order of the
277 // arguments in argv, so we need to re-order the quotes and the refs array
278 // to match.
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000279 for (size_t i = 0; i < m_argv.size() - 1; ++i) {
Zachary Turner691405b2016-10-03 22:51:09 +0000280 const char *argv = m_argv[i];
281 auto pos =
282 std::find_if(m_entries.begin() + i, m_entries.end(),
283 [argv](const ArgEntry &D) { return D.c_str() == argv; });
284 assert(pos != m_entries.end());
285 size_t distance = std::distance(m_entries.begin(), pos);
286 if (i == distance)
287 continue;
288
289 assert(distance > i);
290
291 std::swap(m_entries[i], m_entries[distance]);
292 assert(m_entries[i].ref.data() == m_argv[i]);
293 }
294 m_entries.resize(m_argv.size() - 1);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000295}
296
Zachary Turner691405b2016-10-03 22:51:09 +0000297size_t Args::GetArgumentCount() const { return m_entries.size(); }
298
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299const char *Args::GetArgumentAtIndex(size_t idx) const {
300 if (idx < m_argv.size())
301 return m_argv[idx];
302 return nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000303}
304
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
Zachary Turner691405b2016-10-03 22:51:09 +0000306 if (idx < m_entries.size())
307 return m_entries[idx].quote;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308 return '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309}
310
Kate Stoneb9c1b512016-09-06 20:57:50 +0000311char **Args::GetArgumentVector() {
Zachary Turner691405b2016-10-03 22:51:09 +0000312 assert(!m_argv.empty());
313 // TODO: functions like execve and posix_spawnp exhibit undefined behavior
314 // when argv or envp is null. So the code below is actually wrong. However,
315 // other code in LLDB depends on it being null. The code has been acting this
316 // way for some time, so it makes sense to leave it this way until someone
317 // has the time to come along and fix it.
318 return (m_argv.size() > 1) ? m_argv.data() : nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000319}
320
Kate Stoneb9c1b512016-09-06 20:57:50 +0000321const char **Args::GetConstArgumentVector() const {
Zachary Turner691405b2016-10-03 22:51:09 +0000322 assert(!m_argv.empty());
323 return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
324 : nullptr;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000325}
326
Kate Stoneb9c1b512016-09-06 20:57:50 +0000327void Args::Shift() {
328 // Don't pop the last NULL terminator from the argv array
Zachary Turner691405b2016-10-03 22:51:09 +0000329 if (m_entries.empty())
330 return;
331 m_argv.erase(m_argv.begin());
332 m_entries.erase(m_entries.begin());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000333}
334
Zachary Turner5c725f32016-09-19 21:56:59 +0000335llvm::StringRef Args::Unshift(llvm::StringRef arg_str, char quote_char) {
Zachary Turner691405b2016-10-03 22:51:09 +0000336 return InsertArgumentAtIndex(0, arg_str, quote_char);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000337}
338
Kate Stoneb9c1b512016-09-06 20:57:50 +0000339void Args::AppendArguments(const Args &rhs) {
Zachary Turner691405b2016-10-03 22:51:09 +0000340 assert(m_argv.size() == m_entries.size() + 1);
341 assert(m_argv.back() == nullptr);
342 m_argv.pop_back();
343 for (auto &entry : rhs.m_entries) {
344 m_entries.emplace_back(entry.ref, entry.quote);
345 m_argv.push_back(m_entries.back().data());
346 }
347 m_argv.push_back(nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000348}
349
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350void Args::AppendArguments(const char **argv) {
Zachary Turner691405b2016-10-03 22:51:09 +0000351 size_t argc = ArgvToArgc(argv);
352
353 assert(m_argv.size() == m_entries.size() + 1);
354 assert(m_argv.back() == nullptr);
355 m_argv.pop_back();
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000356 for (auto arg : llvm::makeArrayRef(argv, argc)) {
357 m_entries.emplace_back(arg, '\0');
Zachary Turner691405b2016-10-03 22:51:09 +0000358 m_argv.push_back(m_entries.back().data());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000359 }
Zachary Turner691405b2016-10-03 22:51:09 +0000360
361 m_argv.push_back(nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000362}
363
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000364llvm::StringRef Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
365 return InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
Greg Clayton982c9762011-11-03 21:22:33 +0000366}
367
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000368llvm::StringRef Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
369 char quote_char) {
Zachary Turner691405b2016-10-03 22:51:09 +0000370 assert(m_argv.size() == m_entries.size() + 1);
371 assert(m_argv.back() == nullptr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000372
Zachary Turner691405b2016-10-03 22:51:09 +0000373 if (idx > m_entries.size())
374 return llvm::StringRef();
375 m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
376 m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
377 return m_entries[idx].ref;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378}
379
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000380llvm::StringRef Args::ReplaceArgumentAtIndex(size_t idx,
381 llvm::StringRef arg_str,
382 char quote_char) {
Zachary Turner691405b2016-10-03 22:51:09 +0000383 assert(m_argv.size() == m_entries.size() + 1);
384 assert(m_argv.back() == nullptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000385
Zachary Turner691405b2016-10-03 22:51:09 +0000386 if (idx >= m_entries.size())
387 return llvm::StringRef();
388
389 if (arg_str.size() > m_entries[idx].ref.size()) {
390 m_entries[idx] = ArgEntry(arg_str, quote_char);
391 m_argv[idx] = m_entries[idx].data();
392 } else {
393 const char *src_data = arg_str.data() ? arg_str.data() : "";
394 ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
395 m_entries[idx].ptr[arg_str.size()] = 0;
396 m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 }
Zachary Turner691405b2016-10-03 22:51:09 +0000398
399 return m_entries[idx].ref;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400}
401
Kate Stoneb9c1b512016-09-06 20:57:50 +0000402void Args::DeleteArgumentAtIndex(size_t idx) {
Zachary Turner691405b2016-10-03 22:51:09 +0000403 if (idx >= m_entries.size())
404 return;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000405
Zachary Turner691405b2016-10-03 22:51:09 +0000406 m_argv.erase(m_argv.begin() + idx);
407 m_entries.erase(m_entries.begin() + idx);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408}
409
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410void Args::SetArguments(size_t argc, const char **argv) {
Zachary Turner691405b2016-10-03 22:51:09 +0000411 Clear();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000412
Zachary Turner691405b2016-10-03 22:51:09 +0000413 auto args = llvm::makeArrayRef(argv, argc);
414 m_entries.resize(argc);
415 m_argv.resize(argc + 1);
Zachary Turner5a8ad4592016-10-05 17:07:34 +0000416 for (size_t i = 0; i < args.size(); ++i) {
Zachary Turner691405b2016-10-03 22:51:09 +0000417 char quote =
418 ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
419 ? args[i][0]
420 : '\0';
421
422 m_entries[i] = ArgEntry(args[i], quote);
423 m_argv[i] = m_entries[i].data();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000425}
426
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427void Args::SetArguments(const char **argv) {
Zachary Turner691405b2016-10-03 22:51:09 +0000428 SetArguments(ArgvToArgc(argv), argv);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000429}
430
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431Error Args::ParseOptions(Options &options, ExecutionContext *execution_context,
432 PlatformSP platform_sp, bool require_validation) {
433 StreamString sstr;
434 Error error;
435 Option *long_options = options.GetLongOptions();
436 if (long_options == nullptr) {
437 error.SetErrorStringWithFormat("invalid long options");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000438 return error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441 for (int i = 0; long_options[i].definition != nullptr; ++i) {
442 if (long_options[i].flag == nullptr) {
443 if (isprint8(long_options[i].val)) {
444 sstr << (char)long_options[i].val;
445 switch (long_options[i].definition->option_has_arg) {
Tamas Berghammer89d3f092015-09-02 10:35:27 +0000446 default:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447 case OptionParser::eNoArgument:
448 break;
449 case OptionParser::eRequiredArgument:
450 sstr << ':';
451 break;
452 case OptionParser::eOptionalArgument:
453 sstr << "::";
454 break;
455 }
456 }
Tamas Berghammer89d3f092015-09-02 10:35:27 +0000457 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458 }
459 std::unique_lock<std::mutex> lock;
460 OptionParser::Prepare(lock);
461 int val;
462 while (1) {
463 int long_options_index = -1;
464 val =
465 OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
466 sstr.GetData(), long_options, &long_options_index);
467 if (val == -1)
468 break;
Tamas Berghammer89d3f092015-09-02 10:35:27 +0000469
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 // Did we get an error?
471 if (val == '?') {
472 error.SetErrorStringWithFormat("unknown or ambiguous option");
473 break;
Tamas Berghammer89d3f092015-09-02 10:35:27 +0000474 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000475 // The option auto-set itself
476 if (val == 0)
477 continue;
478
479 ((Options *)&options)->OptionSeen(val);
480
481 // Lookup the long option index
482 if (long_options_index == -1) {
483 for (int i = 0; long_options[i].definition || long_options[i].flag ||
484 long_options[i].val;
485 ++i) {
486 if (long_options[i].val == val) {
487 long_options_index = i;
488 break;
489 }
490 }
491 }
492 // Call the callback with the option
493 if (long_options_index >= 0 &&
494 long_options[long_options_index].definition) {
495 const OptionDefinition *def = long_options[long_options_index].definition;
496
497 if (!platform_sp) {
498 // User did not pass in an explicit platform. Try to grab
499 // from the execution context.
500 TargetSP target_sp =
501 execution_context ? execution_context->GetTargetSP() : TargetSP();
502 platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
503 }
504 OptionValidator *validator = def->validator;
505
506 if (!platform_sp && require_validation) {
507 // Caller requires validation but we cannot validate as we
508 // don't have the mandatory platform against which to
509 // validate.
510 error.SetErrorString("cannot validate options: "
511 "no platform available");
512 return error;
513 }
514
515 bool validation_failed = false;
516 if (platform_sp) {
517 // Ensure we have an execution context, empty or not.
518 ExecutionContext dummy_context;
519 ExecutionContext *exe_ctx_p =
520 execution_context ? execution_context : &dummy_context;
521 if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
522 validation_failed = true;
523 error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
524 def->long_option,
525 def->validator->LongConditionString());
526 }
527 }
528
529 // As long as validation didn't fail, we set the option value.
530 if (!validation_failed)
531 error = options.SetOptionValue(
532 long_options_index,
533 (def->option_has_arg == OptionParser::eNoArgument)
534 ? nullptr
535 : OptionParser::GetOptionArgument(),
536 execution_context);
537 } else {
538 error.SetErrorStringWithFormat("invalid option with value '%i'", val);
539 }
540 if (error.Fail())
541 break;
542 }
543
544 // Update our ARGV now that get options has consumed all the options
545 m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
546 UpdateArgsAfterOptionParsing();
547 return error;
Tamas Berghammer89d3f092015-09-02 10:35:27 +0000548}
549
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550void Args::Clear() {
Zachary Turner691405b2016-10-03 22:51:09 +0000551 m_entries.clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000552 m_argv.clear();
Zachary Turner691405b2016-10-03 22:51:09 +0000553 m_argv.push_back(nullptr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554}
555
556lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx,
557 const char *s, lldb::addr_t fail_value,
558 Error *error_ptr) {
559 bool error_set = false;
560 if (s && s[0]) {
Zachary Turner95eae422016-09-21 16:01:28 +0000561 llvm::StringRef sref = s;
562
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563 char *end = nullptr;
564 lldb::addr_t addr = ::strtoull(s, &end, 0);
565 if (*end == '\0') {
566 if (error_ptr)
567 error_ptr->Clear();
568 return addr; // All characters were used, return the result
569 }
570 // Try base 16 with no prefix...
571 addr = ::strtoull(s, &end, 16);
572 if (*end == '\0') {
573 if (error_ptr)
574 error_ptr->Clear();
575 return addr; // All characters were used, return the result
576 }
577
578 if (exe_ctx) {
579 Target *target = exe_ctx->GetTargetPtr();
580 if (target) {
581 lldb::ValueObjectSP valobj_sp;
582 EvaluateExpressionOptions options;
583 options.SetCoerceToId(false);
584 options.SetUnwindOnError(true);
585 options.SetKeepInMemory(false);
586 options.SetTryAllThreads(true);
587
588 ExpressionResults expr_result = target->EvaluateExpression(
589 s, exe_ctx->GetFramePtr(), valobj_sp, options);
590
591 bool success = false;
592 if (expr_result == eExpressionCompleted) {
593 if (valobj_sp)
594 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
595 valobj_sp->GetDynamicValueType(), true);
596 // Get the address to watch.
597 if (valobj_sp)
598 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
599 if (success) {
600 if (error_ptr)
601 error_ptr->Clear();
602 return addr;
603 } else {
604 if (error_ptr) {
605 error_set = true;
606 error_ptr->SetErrorStringWithFormat(
607 "address expression \"%s\" resulted in a value whose type "
608 "can't be converted to an address: %s",
609 s, valobj_sp->GetTypeName().GetCString());
610 }
611 }
612
613 } else {
614 // Since the compiler can't handle things like "main + 12" we should
615 // try to do this for now. The compiler doesn't like adding offsets
616 // to function pointer types.
Zachary Turner95eae422016-09-21 16:01:28 +0000617 static RegularExpression g_symbol_plus_offset_regex(llvm::StringRef(
618 "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$"));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000619 RegularExpression::Match regex_match(3);
Zachary Turner95eae422016-09-21 16:01:28 +0000620 if (g_symbol_plus_offset_regex.Execute(sref, &regex_match)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000621 uint64_t offset = 0;
622 bool add = true;
623 std::string name;
624 std::string str;
625 if (regex_match.GetMatchAtIndex(s, 1, name)) {
626 if (regex_match.GetMatchAtIndex(s, 2, str)) {
627 add = str[0] == '+';
628
629 if (regex_match.GetMatchAtIndex(s, 3, str)) {
630 offset = StringConvert::ToUInt64(str.c_str(), 0, 0, &success);
631
632 if (success) {
633 Error 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);
652 }
653 }
654 }
655 }
656 }
657 if (error_ptr) {
658 if (!error_set)
659 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
660 s);
661 }
662 return fail_value;
663}
664
665const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
666 bool return_null_if_empty) {
667 static const char *k_white_space = " \t\v";
668 if (!s.empty()) {
669 if (leading) {
670 size_t pos = s.find_first_not_of(k_white_space);
671 if (pos == std::string::npos)
672 s.clear();
673 else if (pos > 0)
674 s.erase(0, pos);
675 }
676
677 if (trailing) {
678 size_t rpos = s.find_last_not_of(k_white_space);
679 if (rpos != std::string::npos && rpos + 1 < s.size())
680 s.erase(rpos + 1);
681 }
682 }
683 if (return_null_if_empty && s.empty())
684 return nullptr;
685 return s.c_str();
686}
687
Kate Stoneb9c1b512016-09-06 20:57:50 +0000688bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value,
689 bool *success_ptr) {
Zachary Turner7b2e5a32016-09-16 19:09:12 +0000690 if (success_ptr)
691 *success_ptr = true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000692 ref = ref.trim();
693 if (ref.equals_lower("false") || ref.equals_lower("off") ||
694 ref.equals_lower("no") || ref.equals_lower("0")) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000695 return false;
696 } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
697 ref.equals_lower("yes") || ref.equals_lower("1")) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000698 return true;
699 }
700 if (success_ptr)
701 *success_ptr = false;
702 return fail_value;
703}
704
Zachary Turner7b2e5a32016-09-16 19:09:12 +0000705char Args::StringToChar(llvm::StringRef s, char fail_value, bool *success_ptr) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000706 if (success_ptr)
Zachary Turner7b2e5a32016-09-16 19:09:12 +0000707 *success_ptr = false;
708 if (s.size() != 1)
709 return fail_value;
710
711 if (success_ptr)
712 *success_ptr = true;
713 return s[0];
Kate Stoneb9c1b512016-09-06 20:57:50 +0000714}
715
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000716bool Args::StringToVersion(llvm::StringRef string, uint32_t &major,
717 uint32_t &minor, uint32_t &update) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000718 major = UINT32_MAX;
719 minor = UINT32_MAX;
720 update = UINT32_MAX;
721
Zachary Turner6fa7681b2016-09-17 02:00:02 +0000722 if (string.empty())
723 return false;
724
725 llvm::StringRef major_str, minor_str, update_str;
726
727 std::tie(major_str, minor_str) = string.split('.');
728 std::tie(minor_str, update_str) = minor_str.split('.');
729 if (major_str.getAsInteger(10, major))
730 return false;
731 if (!minor_str.empty() && minor_str.getAsInteger(10, minor))
732 return false;
733 if (!update_str.empty() && update_str.getAsInteger(10, update))
734 return false;
735
736 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000737}
738
739const char *Args::GetShellSafeArgument(const FileSpec &shell,
740 const char *unsafe_arg,
741 std::string &safe_arg) {
742 struct ShellDescriptor {
743 ConstString m_basename;
744 const char *m_escapables;
745 };
746
747 static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
748 {ConstString("tcsh"), " '\"<>()&$"},
749 {ConstString("sh"), " '\"<>()&"}};
750
751 // safe minimal set
752 const char *escapables = " '\"";
753
754 if (auto basename = shell.GetFilename()) {
755 for (const auto &Shell : g_Shells) {
756 if (Shell.m_basename == basename) {
757 escapables = Shell.m_escapables;
758 break;
759 }
760 }
761 }
762
763 safe_arg.assign(unsafe_arg);
764 size_t prev_pos = 0;
765 while (prev_pos < safe_arg.size()) {
766 // Escape spaces and quotes
767 size_t pos = safe_arg.find_first_of(escapables, prev_pos);
768 if (pos != std::string::npos) {
769 safe_arg.insert(pos, 1, '\\');
770 prev_pos = pos + 2;
771 } else
772 break;
773 }
774 return safe_arg.c_str();
775}
776
Zachary Turner8cef4b02016-09-23 17:48:13 +0000777int64_t Args::StringToOptionEnum(llvm::StringRef s,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000778 OptionEnumValueElement *enum_values,
779 int32_t fail_value, Error &error) {
Zachary Turner8cef4b02016-09-23 17:48:13 +0000780 error.Clear();
781 if (!enum_values) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000782 error.SetErrorString("invalid enumeration argument");
Zachary Turner8cef4b02016-09-23 17:48:13 +0000783 return fail_value;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000784 }
Zachary Turner8cef4b02016-09-23 17:48:13 +0000785
786 if (s.empty()) {
787 error.SetErrorString("empty enumeration string");
788 return fail_value;
789 }
790
791 for (int i = 0; enum_values[i].string_value != nullptr; i++) {
792 llvm::StringRef this_enum(enum_values[i].string_value);
793 if (this_enum.startswith(s))
794 return enum_values[i].value;
795 }
796
797 StreamString strm;
798 strm.PutCString("invalid enumeration value, valid values are: ");
799 for (int i = 0; enum_values[i].string_value != nullptr; i++) {
800 strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
801 }
802 error.SetErrorString(strm.GetData());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000803 return fail_value;
804}
805
Zachary Turner7b2e5a32016-09-16 19:09:12 +0000806lldb::ScriptLanguage
807Args::StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value,
808 bool *success_ptr) {
809 if (success_ptr)
810 *success_ptr = true;
811
812 if (s.equals_lower("python"))
813 return eScriptLanguagePython;
814 if (s.equals_lower("default"))
815 return eScriptLanguageDefault;
816 if (s.equals_lower("none"))
817 return eScriptLanguageNone;
818
Kate Stoneb9c1b512016-09-06 20:57:50 +0000819 if (success_ptr)
820 *success_ptr = false;
821 return fail_value;
822}
823
824Error Args::StringToFormat(const char *s, lldb::Format &format,
825 size_t *byte_size_ptr) {
826 format = eFormatInvalid;
827 Error error;
828
829 if (s && s[0]) {
830 if (byte_size_ptr) {
831 if (isdigit(s[0])) {
832 char *format_char = nullptr;
833 unsigned long byte_size = ::strtoul(s, &format_char, 0);
834 if (byte_size != ULONG_MAX)
835 *byte_size_ptr = byte_size;
836 s = format_char;
837 } else
838 *byte_size_ptr = 0;
839 }
840
841 const bool partial_match_ok = true;
842 if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
843 StreamString error_strm;
844 error_strm.Printf(
845 "Invalid format character or name '%s'. Valid values are:\n", s);
846 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
847 char format_char = FormatManager::GetFormatAsFormatChar(f);
848 if (format_char)
849 error_strm.Printf("'%c' or ", format_char);
850
851 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
852 error_strm.EOL();
853 }
854
855 if (byte_size_ptr)
856 error_strm.PutCString(
857 "An optional byte size can precede the format character.\n");
858 error.SetErrorString(error_strm.GetString().c_str());
859 }
860
861 if (error.Fail())
862 return error;
863 } else {
864 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
865 }
866 return error;
867}
868
Kate Stoneb9c1b512016-09-06 20:57:50 +0000869lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
870 lldb::Encoding fail_value) {
871 return llvm::StringSwitch<lldb::Encoding>(s)
872 .Case("uint", eEncodingUint)
873 .Case("sint", eEncodingSint)
874 .Case("ieee754", eEncodingIEEE754)
875 .Case("vector", eEncodingVector)
876 .Default(fail_value);
877}
878
Kate Stoneb9c1b512016-09-06 20:57:50 +0000879uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
880 if (s.empty())
881 return LLDB_INVALID_REGNUM;
882 uint32_t result = llvm::StringSwitch<uint32_t>(s)
883 .Case("pc", LLDB_REGNUM_GENERIC_PC)
884 .Case("sp", LLDB_REGNUM_GENERIC_SP)
885 .Case("fp", LLDB_REGNUM_GENERIC_FP)
886 .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
887 .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
888 .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
889 .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
890 .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
891 .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
892 .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
893 .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
894 .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
895 .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
896 .Default(LLDB_INVALID_REGNUM);
897 return result;
898}
899
Zachary Turner5c725f32016-09-19 21:56:59 +0000900void Args::AddOrReplaceEnvironmentVariable(llvm::StringRef env_var_name,
901 llvm::StringRef new_value) {
Todd Fiala36bf6a42016-09-22 16:00:01 +0000902 if (env_var_name.empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000903 return;
904
905 // Build the new entry.
Zachary Turner5c725f32016-09-19 21:56:59 +0000906 std::string var_string(env_var_name);
Todd Fiala36bf6a42016-09-22 16:00:01 +0000907 if (!new_value.empty()) {
908 var_string += "=";
909 var_string += new_value;
910 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000911
Zachary Turner5c725f32016-09-19 21:56:59 +0000912 size_t index = 0;
913 if (ContainsEnvironmentVariable(env_var_name, &index)) {
914 ReplaceArgumentAtIndex(index, var_string);
915 return;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916 }
917
918 // We didn't find it. Append it instead.
Zachary Turner5c725f32016-09-19 21:56:59 +0000919 AppendArgument(var_string);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920}
921
Zachary Turner5c725f32016-09-19 21:56:59 +0000922bool Args::ContainsEnvironmentVariable(llvm::StringRef env_var_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000923 size_t *argument_index) const {
924 // Validate args.
Zachary Turner5c725f32016-09-19 21:56:59 +0000925 if (env_var_name.empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000926 return false;
927
928 // Check each arg to see if it matches the env var name.
Zachary Turner11eb9c62016-10-05 20:03:37 +0000929 for (auto arg : llvm::enumerate(m_entries)) {
Zachary Turner5c725f32016-09-19 21:56:59 +0000930 llvm::StringRef name, value;
Zachary Turner11eb9c62016-10-05 20:03:37 +0000931 std::tie(name, value) = arg.Value.ref.split('=');
932 if (name != env_var_name)
933 continue;
934
935 if (argument_index)
936 *argument_index = arg.Index;
937 return true;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000938 }
939
940 // We didn't find a match.
941 return false;
942}
943
944size_t Args::FindArgumentIndexForOption(Option *long_options,
Zachary Turner11eb9c62016-10-05 20:03:37 +0000945 int long_options_index) const {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000946 char short_buffer[3];
947 char long_buffer[255];
948 ::snprintf(short_buffer, sizeof(short_buffer), "-%c",
949 long_options[long_options_index].val);
950 ::snprintf(long_buffer, sizeof(long_buffer), "--%s",
951 long_options[long_options_index].definition->long_option);
Zachary Turner11eb9c62016-10-05 20:03:37 +0000952
953 for (auto entry : llvm::enumerate(m_entries)) {
954 if (entry.Value.ref.startswith(short_buffer) ||
955 entry.Value.ref.startswith(long_buffer))
956 return entry.Index;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000957 }
958
Zachary Turner11eb9c62016-10-05 20:03:37 +0000959 return size_t(-1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000960}
961
962bool Args::IsPositionalArgument(const char *arg) {
963 if (arg == nullptr)
964 return false;
965
966 bool is_positional = true;
967 const char *cptr = arg;
968
969 if (cptr[0] == '%') {
970 ++cptr;
971 while (isdigit(cptr[0]))
972 ++cptr;
973 if (cptr[0] != '\0')
974 is_positional = false;
975 } else
976 is_positional = false;
977
978 return is_positional;
979}
980
Zachary Turnera4496982016-10-05 21:14:38 +0000981std::string Args::ParseAliasOptions(Options &options,
982 CommandReturnObject &result,
983 OptionArgVector *option_arg_vector,
984 llvm::StringRef raw_input_string) {
985 std::string result_string(raw_input_string);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000986 StreamString sstr;
987 int i;
988 Option *long_options = options.GetLongOptions();
989
990 if (long_options == nullptr) {
991 result.AppendError("invalid long options");
992 result.SetStatus(eReturnStatusFailed);
Zachary Turnera4496982016-10-05 21:14:38 +0000993 return result_string;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000994 }
995
996 for (i = 0; long_options[i].definition != nullptr; ++i) {
997 if (long_options[i].flag == nullptr) {
998 sstr << (char)long_options[i].val;
999 switch (long_options[i].definition->option_has_arg) {
1000 default:
1001 case OptionParser::eNoArgument:
1002 break;
1003 case OptionParser::eRequiredArgument:
1004 sstr << ":";
1005 break;
1006 case OptionParser::eOptionalArgument:
1007 sstr << "::";
1008 break;
1009 }
1010 }
1011 }
1012
1013 std::unique_lock<std::mutex> lock;
1014 OptionParser::Prepare(lock);
Zachary Turner5c28c662016-10-03 23:20:36 +00001015 result.SetStatus(eReturnStatusSuccessFinishNoResult);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001016 int val;
1017 while (1) {
1018 int long_options_index = -1;
1019 val =
1020 OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
1021 sstr.GetData(), long_options, &long_options_index);
1022
1023 if (val == -1)
1024 break;
1025
1026 if (val == '?') {
1027 result.AppendError("unknown or ambiguous option");
1028 result.SetStatus(eReturnStatusFailed);
1029 break;
1030 }
1031
1032 if (val == 0)
1033 continue;
1034
1035 options.OptionSeen(val);
1036
1037 // Look up the long option index
1038 if (long_options_index == -1) {
1039 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1040 long_options[j].val;
1041 ++j) {
1042 if (long_options[j].val == val) {
1043 long_options_index = j;
1044 break;
1045 }
1046 }
1047 }
1048
1049 // See if the option takes an argument, and see if one was supplied.
Zachary Turner5c28c662016-10-03 23:20:36 +00001050 if (long_options_index == -1) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001051 result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val);
1052 result.SetStatus(eReturnStatusFailed);
Zachary Turnera4496982016-10-05 21:14:38 +00001053 return result_string;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001054 }
1055
Zachary Turner5c28c662016-10-03 23:20:36 +00001056 StreamString option_str;
1057 option_str.Printf("-%c", val);
1058 const OptionDefinition *def = long_options[long_options_index].definition;
1059 int has_arg =
1060 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1061
1062 const char *option_arg = nullptr;
1063 switch (has_arg) {
1064 case OptionParser::eRequiredArgument:
1065 if (OptionParser::GetOptionArgument() == nullptr) {
1066 result.AppendErrorWithFormat(
1067 "Option '%s' is missing argument specifier.\n",
1068 option_str.GetData());
1069 result.SetStatus(eReturnStatusFailed);
Zachary Turnera4496982016-10-05 21:14:38 +00001070 return result_string;
Zachary Turner5c28c662016-10-03 23:20:36 +00001071 }
1072 LLVM_FALLTHROUGH;
1073 case OptionParser::eOptionalArgument:
1074 option_arg = OptionParser::GetOptionArgument();
1075 LLVM_FALLTHROUGH;
1076 case OptionParser::eNoArgument:
1077 break;
1078 default:
1079 result.AppendErrorWithFormat("error with options table; invalid value "
1080 "in has_arg field for option '%c'.\n",
1081 val);
1082 result.SetStatus(eReturnStatusFailed);
Zachary Turnera4496982016-10-05 21:14:38 +00001083 return result_string;
Zachary Turner5c28c662016-10-03 23:20:36 +00001084 }
1085 if (!option_arg)
1086 option_arg = "<no-argument>";
1087 option_arg_vector->emplace_back(option_str.GetData(), has_arg, option_arg);
1088
1089 // Find option in the argument list; also see if it was supposed to take
1090 // an argument and if one was supplied. Remove option (and argument, if
1091 // given) from the argument list. Also remove them from the
1092 // raw_input_string, if one was passed in.
1093 size_t idx = FindArgumentIndexForOption(long_options, long_options_index);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001094 if (idx == size_t(-1))
1095 continue;
1096
Zachary Turnera4496982016-10-05 21:14:38 +00001097 if (!result_string.empty()) {
Zachary Turner11eb9c62016-10-05 20:03:37 +00001098 const char *tmp_arg = GetArgumentAtIndex(idx);
Zachary Turnera4496982016-10-05 21:14:38 +00001099 size_t pos = result_string.find(tmp_arg);
Zachary Turner11eb9c62016-10-05 20:03:37 +00001100 if (pos != std::string::npos)
Zachary Turnera4496982016-10-05 21:14:38 +00001101 result_string.erase(pos, strlen(tmp_arg));
Zachary Turner11eb9c62016-10-05 20:03:37 +00001102 }
1103 ReplaceArgumentAtIndex(idx, llvm::StringRef());
1104 if ((long_options[long_options_index].definition->option_has_arg !=
1105 OptionParser::eNoArgument) &&
1106 (OptionParser::GetOptionArgument() != nullptr) &&
1107 (idx + 1 < GetArgumentCount()) &&
1108 (strcmp(OptionParser::GetOptionArgument(),
1109 GetArgumentAtIndex(idx + 1)) == 0)) {
Zachary Turnera4496982016-10-05 21:14:38 +00001110 if (result_string.size() > 0) {
Zachary Turner11eb9c62016-10-05 20:03:37 +00001111 const char *tmp_arg = GetArgumentAtIndex(idx + 1);
Zachary Turnera4496982016-10-05 21:14:38 +00001112 size_t pos = result_string.find(tmp_arg);
Zachary Turner5c28c662016-10-03 23:20:36 +00001113 if (pos != std::string::npos)
Zachary Turnera4496982016-10-05 21:14:38 +00001114 result_string.erase(pos, strlen(tmp_arg));
Zachary Turner5c28c662016-10-03 23:20:36 +00001115 }
Zachary Turner11eb9c62016-10-05 20:03:37 +00001116 ReplaceArgumentAtIndex(idx + 1, llvm::StringRef());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001117 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001118 }
Zachary Turnera4496982016-10-05 21:14:38 +00001119 return result_string;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001120}
1121
1122void Args::ParseArgsForCompletion(Options &options,
1123 OptionElementVector &option_element_vector,
1124 uint32_t cursor_index) {
1125 StreamString sstr;
1126 Option *long_options = options.GetLongOptions();
1127 option_element_vector.clear();
1128
1129 if (long_options == nullptr) {
1130 return;
1131 }
1132
1133 // Leading : tells getopt to return a : for a missing option argument AND
1134 // to suppress error messages.
1135
1136 sstr << ":";
1137 for (int i = 0; long_options[i].definition != nullptr; ++i) {
1138 if (long_options[i].flag == nullptr) {
1139 sstr << (char)long_options[i].val;
1140 switch (long_options[i].definition->option_has_arg) {
1141 default:
1142 case OptionParser::eNoArgument:
1143 break;
1144 case OptionParser::eRequiredArgument:
1145 sstr << ":";
1146 break;
1147 case OptionParser::eOptionalArgument:
1148 sstr << "::";
1149 break;
1150 }
1151 }
1152 }
1153
1154 std::unique_lock<std::mutex> lock;
1155 OptionParser::Prepare(lock);
1156 OptionParser::EnableError(false);
1157
1158 int val;
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001159 auto opt_defs = options.GetDefinitions();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001160
1161 // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the
Zachary Turner11eb9c62016-10-05 20:03:37 +00001162 // options to the front. So we have to build another Arg and pass that to
1163 // OptionParser::Parse so it doesn't change the one we have.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001164
Zachary Turner11eb9c62016-10-05 20:03:37 +00001165 std::vector<char *> dummy_vec = m_argv;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001166
1167 bool failed_once = false;
1168 uint32_t dash_dash_pos = -1;
1169
1170 while (1) {
1171 bool missing_argument = false;
1172 int long_options_index = -1;
1173
Zachary Turner11eb9c62016-10-05 20:03:37 +00001174 val =
1175 OptionParser::Parse(dummy_vec.size() - 1, &dummy_vec[0], sstr.GetData(),
1176 long_options, &long_options_index);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001177
1178 if (val == -1) {
1179 // When we're completing a "--" which is the last option on line,
1180 if (failed_once)
1181 break;
1182
1183 failed_once = true;
1184
1185 // If this is a bare "--" we mark it as such so we can complete it
1186 // successfully later.
1187 // Handling the "--" is a little tricky, since that may mean end of
1188 // options or arguments, or the
1189 // user might want to complete options by long name. I make this work by
1190 // checking whether the
1191 // cursor is in the "--" argument, and if so I assume we're completing the
1192 // long option, otherwise
1193 // I let it pass to OptionParser::Parse which will terminate the option
1194 // parsing.
1195 // Note, in either case we continue parsing the line so we can figure out
1196 // what other options
1197 // were passed. This will be useful when we come to restricting
1198 // completions based on what other
1199 // options we've seen on the line.
1200
1201 if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1202 dummy_vec.size() - 1 &&
1203 (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1204 dash_dash_pos = OptionParser::GetOptionIndex() - 1;
1205 if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) ==
1206 cursor_index) {
1207 option_element_vector.push_back(
1208 OptionArgElement(OptionArgElement::eBareDoubleDash,
1209 OptionParser::GetOptionIndex() - 1,
1210 OptionArgElement::eBareDoubleDash));
1211 continue;
1212 } else
1213 break;
1214 } else
1215 break;
1216 } else if (val == '?') {
1217 option_element_vector.push_back(
1218 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1219 OptionParser::GetOptionIndex() - 1,
1220 OptionArgElement::eUnrecognizedArg));
1221 continue;
1222 } else if (val == 0) {
1223 continue;
1224 } else if (val == ':') {
1225 // This is a missing argument.
1226 val = OptionParser::GetOptionErrorCause();
1227 missing_argument = true;
1228 }
1229
1230 ((Options *)&options)->OptionSeen(val);
1231
1232 // Look up the long option index
1233 if (long_options_index == -1) {
1234 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1235 long_options[j].val;
1236 ++j) {
1237 if (long_options[j].val == val) {
1238 long_options_index = j;
1239 break;
1240 }
1241 }
1242 }
1243
1244 // See if the option takes an argument, and see if one was supplied.
1245 if (long_options_index >= 0) {
1246 int opt_defs_index = -1;
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001247 for (size_t i = 0; i < opt_defs.size(); i++) {
1248 if (opt_defs[i].short_option != val)
1249 continue;
1250 opt_defs_index = i;
1251 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001252 }
1253
1254 const OptionDefinition *def = long_options[long_options_index].definition;
1255 int has_arg =
1256 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1257 switch (has_arg) {
1258 case OptionParser::eNoArgument:
1259 option_element_vector.push_back(OptionArgElement(
1260 opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
1261 break;
1262 case OptionParser::eRequiredArgument:
1263 if (OptionParser::GetOptionArgument() != nullptr) {
1264 int arg_index;
1265 if (missing_argument)
1266 arg_index = -1;
1267 else
1268 arg_index = OptionParser::GetOptionIndex() - 1;
1269
1270 option_element_vector.push_back(OptionArgElement(
1271 opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
1272 } else {
1273 option_element_vector.push_back(OptionArgElement(
1274 opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
1275 }
1276 break;
1277 case OptionParser::eOptionalArgument:
1278 if (OptionParser::GetOptionArgument() != nullptr) {
1279 option_element_vector.push_back(OptionArgElement(
1280 opt_defs_index, OptionParser::GetOptionIndex() - 2,
1281 OptionParser::GetOptionIndex() - 1));
1282 } else {
1283 option_element_vector.push_back(OptionArgElement(
1284 opt_defs_index, OptionParser::GetOptionIndex() - 2,
1285 OptionParser::GetOptionIndex() - 1));
1286 }
1287 break;
1288 default:
1289 // The options table is messed up. Here we'll just continue
1290 option_element_vector.push_back(
1291 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1292 OptionParser::GetOptionIndex() - 1,
1293 OptionArgElement::eUnrecognizedArg));
1294 break;
1295 }
1296 } else {
1297 option_element_vector.push_back(
1298 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1299 OptionParser::GetOptionIndex() - 1,
1300 OptionArgElement::eUnrecognizedArg));
1301 }
1302 }
1303
1304 // Finally we have to handle the case where the cursor index points at a
1305 // single "-". We want to mark that in
1306 // the option_element_vector, but only if it is not after the "--". But it
1307 // turns out that OptionParser::Parse just ignores
1308 // an isolated "-". So we have to look it up by hand here. We only care if
1309 // it is AT the cursor position.
1310 // Note, a single quoted dash is not the same as a single dash...
1311
Zachary Turner691405b2016-10-03 22:51:09 +00001312 const ArgEntry &cursor = m_entries[cursor_index];
Kate Stoneb9c1b512016-09-06 20:57:50 +00001313 if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1314 cursor_index < dash_dash_pos) &&
Zachary Turner691405b2016-10-03 22:51:09 +00001315 cursor.quote == '\0' && cursor.ref == "-") {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001316 option_element_vector.push_back(
1317 OptionArgElement(OptionArgElement::eBareDash, cursor_index,
1318 OptionArgElement::eBareDash));
1319 }
1320}
1321
1322void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
1323 dst.clear();
1324 if (src) {
1325 for (const char *p = src; *p != '\0'; ++p) {
1326 size_t non_special_chars = ::strcspn(p, "\\");
1327 if (non_special_chars > 0) {
1328 dst.append(p, non_special_chars);
1329 p += non_special_chars;
1330 if (*p == '\0')
1331 break;
1332 }
1333
1334 if (*p == '\\') {
1335 ++p; // skip the slash
1336 switch (*p) {
1337 case 'a':
1338 dst.append(1, '\a');
1339 break;
1340 case 'b':
1341 dst.append(1, '\b');
1342 break;
1343 case 'f':
1344 dst.append(1, '\f');
1345 break;
1346 case 'n':
1347 dst.append(1, '\n');
1348 break;
1349 case 'r':
1350 dst.append(1, '\r');
1351 break;
1352 case 't':
1353 dst.append(1, '\t');
1354 break;
1355 case 'v':
1356 dst.append(1, '\v');
1357 break;
1358 case '\\':
1359 dst.append(1, '\\');
1360 break;
1361 case '\'':
1362 dst.append(1, '\'');
1363 break;
1364 case '"':
1365 dst.append(1, '"');
1366 break;
1367 case '0':
1368 // 1 to 3 octal chars
1369 {
1370 // Make a string that can hold onto the initial zero char,
1371 // up to 3 octal digits, and a terminating NULL.
1372 char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
1373
1374 int i;
1375 for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
1376 oct_str[i] = p[i];
1377
1378 // We don't want to consume the last octal character since
1379 // the main for loop will do this for us, so we advance p by
1380 // one less than i (even if i is zero)
1381 p += i - 1;
1382 unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
1383 if (octal_value <= UINT8_MAX) {
1384 dst.append(1, (char)octal_value);
1385 }
1386 }
1387 break;
1388
1389 case 'x':
1390 // hex number in the format
1391 if (isxdigit(p[1])) {
1392 ++p; // Skip the 'x'
1393
1394 // Make a string that can hold onto two hex chars plus a
1395 // NULL terminator
1396 char hex_str[3] = {*p, '\0', '\0'};
1397 if (isxdigit(p[1])) {
1398 ++p; // Skip the first of the two hex chars
1399 hex_str[1] = *p;
1400 }
1401
1402 unsigned long hex_value = strtoul(hex_str, nullptr, 16);
1403 if (hex_value <= UINT8_MAX)
1404 dst.append(1, (char)hex_value);
1405 } else {
1406 dst.append(1, 'x');
1407 }
1408 break;
1409
1410 default:
1411 // Just desensitize any other character by just printing what
1412 // came after the '\'
1413 dst.append(1, *p);
1414 break;
1415 }
1416 }
1417 }
1418 }
1419}
1420
1421void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
1422 dst.clear();
1423 if (src) {
1424 for (const char *p = src; *p != '\0'; ++p) {
1425 if (isprint8(*p))
1426 dst.append(1, *p);
1427 else {
1428 switch (*p) {
1429 case '\a':
1430 dst.append("\\a");
1431 break;
1432 case '\b':
1433 dst.append("\\b");
1434 break;
1435 case '\f':
1436 dst.append("\\f");
1437 break;
1438 case '\n':
1439 dst.append("\\n");
1440 break;
1441 case '\r':
1442 dst.append("\\r");
1443 break;
1444 case '\t':
1445 dst.append("\\t");
1446 break;
1447 case '\v':
1448 dst.append("\\v");
1449 break;
1450 case '\'':
1451 dst.append("\\'");
1452 break;
1453 case '"':
1454 dst.append("\\\"");
1455 break;
1456 case '\\':
1457 dst.append("\\\\");
1458 break;
1459 default: {
1460 // Just encode as octal
1461 dst.append("\\0");
1462 char octal_str[32];
1463 snprintf(octal_str, sizeof(octal_str), "%o", *p);
1464 dst.append(octal_str);
1465 } break;
1466 }
1467 }
1468 }
1469 }
1470}
1471
1472std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
1473 char quote_char) {
1474 const char *chars_to_escape = nullptr;
1475 switch (quote_char) {
1476 case '\0':
1477 chars_to_escape = " \t\\'\"`";
1478 break;
1479 case '\'':
1480 chars_to_escape = "";
1481 break;
1482 case '"':
1483 chars_to_escape = "$\"`\\";
1484 break;
1485 default:
1486 assert(false && "Unhandled quote character");
1487 }
1488
1489 std::string res;
1490 res.reserve(arg.size());
1491 for (char c : arg) {
1492 if (::strchr(chars_to_escape, c))
1493 res.push_back('\\');
1494 res.push_back(c);
1495 }
1496 return res;
1497}