summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Host/OptionParser.h8
-rw-r--r--lldb/source/Host/common/OptionParser.cpp8
-rw-r--r--lldb/source/Interpreter/CommandAlias.cpp2
-rw-r--r--lldb/source/Interpreter/Options.cpp102
4 files changed, 48 insertions, 72 deletions
diff --git a/lldb/include/lldb/Host/OptionParser.h b/lldb/include/lldb/Host/OptionParser.h
index ca059464564..b03eeb74ec4 100644
--- a/lldb/include/lldb/Host/OptionParser.h
+++ b/lldb/include/lldb/Host/OptionParser.h
@@ -13,6 +13,7 @@
#include <string>
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/ArrayRef.h"
struct option;
@@ -37,8 +38,11 @@ public:
static void EnableError(bool error);
- static int Parse(int argc, char *const argv[], llvm::StringRef optstring,
- const Option *longopts, int *longindex);
+ /// Argv must be an argument vector "as passed to main", i.e. terminated with
+ /// a nullptr.
+ static int Parse(llvm::MutableArrayRef<char *> argv,
+ llvm::StringRef optstring, const Option *longopts,
+ int *longindex);
static char *GetOptionArgument();
static int GetOptionIndex();
diff --git a/lldb/source/Host/common/OptionParser.cpp b/lldb/source/Host/common/OptionParser.cpp
index 92ff6f63d95..1e76f9b8f9f 100644
--- a/lldb/source/Host/common/OptionParser.cpp
+++ b/lldb/source/Host/common/OptionParser.cpp
@@ -27,8 +27,9 @@ void OptionParser::Prepare(std::unique_lock<std::mutex> &lock) {
void OptionParser::EnableError(bool error) { opterr = error ? 1 : 0; }
-int OptionParser::Parse(int argc, char *const argv[], llvm::StringRef optstring,
- const Option *longopts, int *longindex) {
+int OptionParser::Parse(llvm::MutableArrayRef<char *> argv,
+ llvm::StringRef optstring, const Option *longopts,
+ int *longindex) {
std::vector<option> opts;
while (longopts->definition != nullptr) {
option opt;
@@ -41,7 +42,8 @@ int OptionParser::Parse(int argc, char *const argv[], llvm::StringRef optstring,
}
opts.push_back(option());
std::string opt_cstr = optstring;
- return getopt_long_only(argc, argv, opt_cstr.c_str(), &opts[0], longindex);
+ return getopt_long_only(argv.size() - 1, argv.data(), opt_cstr.c_str(),
+ &opts[0], longindex);
}
char *OptionParser::GetOptionArgument() { return optarg; }
diff --git a/lldb/source/Interpreter/CommandAlias.cpp b/lldb/source/Interpreter/CommandAlias.cpp
index 7d159a3baa0..8c40574ee50 100644
--- a/lldb/source/Interpreter/CommandAlias.cpp
+++ b/lldb/source/Interpreter/CommandAlias.cpp
@@ -30,6 +30,8 @@ static bool ProcessAliasOptionsArgs(lldb::CommandObjectSP &cmd_obj_sp,
Args args(options_args);
std::string options_string(options_args);
+ // TODO: Find a way to propagate errors in this CommandReturnObject up the
+ // stack.
CommandReturnObject result;
// Check to see if the command being aliased can take any command options.
Options *options = cmd_obj_sp->GetOptions();
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index e015ee4c575..ba15c020f2d 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -930,6 +930,7 @@ static std::vector<char *> GetArgvForParsing(const Args &args) {
result.push_back(const_cast<char *>("<FAKE-ARG0>"));
for (const Args::ArgEntry &entry : args)
result.push_back(const_cast<char *>(entry.c_str()));
+ result.push_back(nullptr);
return result;
}
@@ -972,19 +973,15 @@ static size_t FindArgumentIndexForOption(const Args &args,
return size_t(-1);
}
-llvm::Expected<Args> Options::ParseAlias(const Args &args,
- OptionArgVector *option_arg_vector,
- std::string &input_line) {
- StreamString sstr;
- int i;
- Option *long_options = GetLongOptions();
+static std::string BuildShortOptions(const Option *long_options) {
+ std::string storage;
+ llvm::raw_string_ostream sstr(storage);
- if (long_options == nullptr) {
- return llvm::make_error<llvm::StringError>("Invalid long options",
- llvm::inconvertibleErrorCode());
- }
+ // Leading : tells getopt to return a : for a missing option argument AND to
+ // suppress error messages.
+ sstr << ":";
- for (i = 0; long_options[i].definition != nullptr; ++i) {
+ for (size_t i = 0; long_options[i].definition != nullptr; ++i) {
if (long_options[i].flag == nullptr) {
sstr << (char)long_options[i].val;
switch (long_options[i].definition->option_has_arg) {
@@ -1000,6 +997,20 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
}
}
}
+ return std::move(sstr.str());
+}
+
+llvm::Expected<Args> Options::ParseAlias(const Args &args,
+ OptionArgVector *option_arg_vector,
+ std::string &input_line) {
+ Option *long_options = GetLongOptions();
+
+ if (long_options == nullptr) {
+ return llvm::make_error<llvm::StringError>("Invalid long options",
+ llvm::inconvertibleErrorCode());
+ }
+
+ std::string short_options = BuildShortOptions(long_options);
Args args_copy = args;
std::vector<char *> argv = GetArgvForParsing(args);
@@ -1009,8 +1020,13 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
int val;
while (true) {
int long_options_index = -1;
- val = OptionParser::Parse(argv.size(), &*argv.begin(), sstr.GetString(),
- long_options, &long_options_index);
+ val = OptionParser::Parse(argv, short_options, long_options,
+ &long_options_index);
+
+ if (val == ':') {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "last option requires an argument");
+ }
if (val == -1)
break;
@@ -1116,33 +1132,13 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
OptionElementVector Options::ParseForCompletion(const Args &args,
uint32_t cursor_index) {
OptionElementVector option_element_vector;
- StreamString sstr;
Option *long_options = GetLongOptions();
option_element_vector.clear();
if (long_options == nullptr)
return option_element_vector;
- // Leading : tells getopt to return a : for a missing option argument AND to
- // suppress error messages.
-
- sstr << ":";
- for (int i = 0; long_options[i].definition != nullptr; ++i) {
- if (long_options[i].flag == nullptr) {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg) {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ":";
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
+ std::string short_options = BuildShortOptions(long_options);
std::unique_lock<std::mutex> lock;
OptionParser::Prepare(lock);
@@ -1153,10 +1149,6 @@ OptionElementVector Options::ParseForCompletion(const Args &args,
std::vector<char *> dummy_vec = GetArgvForParsing(args);
- // I stick an element on the end of the input, because if the last element
- // is option that requires an argument, getopt_long_only will freak out.
- dummy_vec.push_back(const_cast<char *>("<FAKE-VALUE>"));
-
bool failed_once = false;
uint32_t dash_dash_pos = -1;
@@ -1164,8 +1156,8 @@ OptionElementVector Options::ParseForCompletion(const Args &args,
bool missing_argument = false;
int long_options_index = -1;
- val = OptionParser::Parse(dummy_vec.size(), &dummy_vec[0], sstr.GetString(),
- long_options, &long_options_index);
+ val = OptionParser::Parse(dummy_vec, short_options, long_options,
+ &long_options_index);
if (val == -1) {
// When we're completing a "--" which is the last option on line,
@@ -1328,7 +1320,6 @@ llvm::Expected<Args> Options::Parse(const Args &args,
ExecutionContext *execution_context,
lldb::PlatformSP platform_sp,
bool require_validation) {
- StreamString sstr;
Status error;
Option *long_options = GetLongOptions();
if (long_options == nullptr) {
@@ -1336,38 +1327,15 @@ llvm::Expected<Args> Options::Parse(const Args &args,
llvm::inconvertibleErrorCode());
}
- // Leading : tells getopt to return a : for a missing option argument AND to
- // suppress error messages.
- sstr << ":";
- for (int i = 0; long_options[i].definition != nullptr; ++i) {
- if (long_options[i].flag == nullptr) {
- if (isprint8(long_options[i].val)) {
- sstr << (char)long_options[i].val;
- switch (long_options[i].definition->option_has_arg) {
- default:
- case OptionParser::eNoArgument:
- break;
- case OptionParser::eRequiredArgument:
- sstr << ':';
- break;
- case OptionParser::eOptionalArgument:
- sstr << "::";
- break;
- }
- }
- }
- }
+ std::string short_options = BuildShortOptions(long_options);
std::vector<char *> argv = GetArgvForParsing(args);
- // If the last option requires an argument but doesn't have one,
- // some implementations of getopt_long will still try to read it.
- argv.push_back(nullptr);
std::unique_lock<std::mutex> lock;
OptionParser::Prepare(lock);
int val;
while (true) {
int long_options_index = -1;
- val = OptionParser::Parse(argv.size() - 1, &*argv.begin(), sstr.GetString(),
- long_options, &long_options_index);
+ val = OptionParser::Parse(argv, short_options, long_options,
+ &long_options_index);
if (val == ':') {
error.SetErrorStringWithFormat("last option requires an argument");
OpenPOWER on IntegriCloud