New wishbone-jtag bridge
This commit is contained in:
@@ -12,21 +12,41 @@ ArgParser::ArgParser(std::string program_name)
|
||||
void ArgParser::addString(const std::string &name,
|
||||
const std::string &default_value,
|
||||
const std::string &help,
|
||||
bool required) {
|
||||
bool required,
|
||||
const std::string &short_name) {
|
||||
order_.push_back(name);
|
||||
meta_[name] = {OptionType::kString, help, required};
|
||||
meta_[name] = {OptionType::kString, help, required, short_name};
|
||||
string_values_[name] = default_value;
|
||||
provided_[name] = false;
|
||||
if (!short_name.empty()) {
|
||||
short_to_long_[short_name] = name;
|
||||
}
|
||||
}
|
||||
|
||||
void ArgParser::addInt(const std::string &name,
|
||||
int default_value,
|
||||
const std::string &help,
|
||||
bool required) {
|
||||
bool required,
|
||||
const std::string &short_name) {
|
||||
order_.push_back(name);
|
||||
meta_[name] = {OptionType::kInt, help, required};
|
||||
meta_[name] = {OptionType::kInt, help, required, short_name};
|
||||
int_values_[name] = default_value;
|
||||
provided_[name] = false;
|
||||
if (!short_name.empty()) {
|
||||
short_to_long_[short_name] = name;
|
||||
}
|
||||
}
|
||||
|
||||
void ArgParser::addFlag(const std::string &name,
|
||||
const std::string &help,
|
||||
const std::string &short_name) {
|
||||
order_.push_back(name);
|
||||
meta_[name] = {OptionType::kFlag, help, false, short_name};
|
||||
flag_values_[name] = false;
|
||||
provided_[name] = false;
|
||||
if (!short_name.empty()) {
|
||||
short_to_long_[short_name] = name;
|
||||
}
|
||||
}
|
||||
|
||||
bool ArgParser::parse(int argc, char **argv, std::string *error) {
|
||||
@@ -39,6 +59,79 @@ bool ArgParser::parse(int argc, char **argv, std::string *error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (token.rfind("--", 0) != 0 && token.rfind("-", 0) == 0) {
|
||||
std::string short_key = token.substr(1);
|
||||
std::string short_value;
|
||||
size_t short_eq = short_key.find('=');
|
||||
if (short_eq != std::string::npos) {
|
||||
short_value = short_key.substr(short_eq + 1);
|
||||
short_key = short_key.substr(0, short_eq);
|
||||
}
|
||||
|
||||
auto sk = short_to_long_.find(short_key);
|
||||
if (sk == short_to_long_.end()) {
|
||||
if (error) {
|
||||
*error = "Unknown option: -" + short_key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
auto m = meta_.find(sk->second);
|
||||
if (m == meta_.end()) {
|
||||
if (error) {
|
||||
*error = "Unknown option: -" + short_key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->second.type == OptionType::kFlag) {
|
||||
if (short_eq != std::string::npos) {
|
||||
if (error) {
|
||||
*error = "Flag does not take a value: -" + short_key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
flag_values_[sk->second] = true;
|
||||
provided_[sk->second] = true;
|
||||
} else if (m->second.type == OptionType::kString) {
|
||||
if (short_eq == std::string::npos) {
|
||||
if (i + 1 >= argc) {
|
||||
if (error) {
|
||||
*error = "Missing value for -" + short_key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
short_value = argv[++i];
|
||||
}
|
||||
string_values_[sk->second] = short_value;
|
||||
provided_[sk->second] = true;
|
||||
} else if (m->second.type == OptionType::kInt) {
|
||||
long parsed;
|
||||
if (short_eq == std::string::npos) {
|
||||
if (i + 1 >= argc) {
|
||||
if (error) {
|
||||
*error = "Missing value for -" + short_key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
short_value = argv[++i];
|
||||
}
|
||||
errno = 0;
|
||||
char *endp = nullptr;
|
||||
parsed = std::strtol(short_value.c_str(), &endp, 0);
|
||||
if (errno != 0 || endp == short_value.c_str() || *endp != '\0' ||
|
||||
parsed < INT_MIN || parsed > INT_MAX) {
|
||||
if (error) {
|
||||
*error = "Invalid integer for -" + short_key + ": " + short_value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int_values_[sk->second] = static_cast<int>(parsed);
|
||||
provided_[sk->second] = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (token.rfind("--", 0) != 0) {
|
||||
if (error) {
|
||||
*error = "Unexpected positional argument: " + token;
|
||||
@@ -51,13 +144,6 @@ bool ArgParser::parse(int argc, char **argv, std::string *error) {
|
||||
size_t eq = token.find('=');
|
||||
if (eq == std::string::npos) {
|
||||
key = token.substr(2);
|
||||
if (i + 1 >= argc) {
|
||||
if (error) {
|
||||
*error = "Missing value for --" + key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
value = argv[++i];
|
||||
} else {
|
||||
key = token.substr(2, eq - 2);
|
||||
value = token.substr(eq + 1);
|
||||
@@ -71,10 +157,32 @@ bool ArgParser::parse(int argc, char **argv, std::string *error) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m->second.type == OptionType::kFlag) {
|
||||
if (eq != std::string::npos) {
|
||||
if (error) {
|
||||
*error = "Flag does not take a value: --" + key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
flag_values_[key] = true;
|
||||
provided_[key] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (eq == std::string::npos) {
|
||||
if (i + 1 >= argc) {
|
||||
if (error) {
|
||||
*error = "Missing value for --" + key;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
value = argv[++i];
|
||||
}
|
||||
|
||||
if (m->second.type == OptionType::kString) {
|
||||
string_values_[key] = value;
|
||||
provided_[key] = true;
|
||||
} else {
|
||||
} else if (m->second.type == OptionType::kInt) {
|
||||
errno = 0;
|
||||
char *endp = nullptr;
|
||||
long parsed = std::strtol(value.c_str(), &endp, 0);
|
||||
@@ -124,6 +232,14 @@ int ArgParser::getInt(const std::string &name) const {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
bool ArgParser::getFlag(const std::string &name) const {
|
||||
auto it = flag_values_.find(name);
|
||||
if (it == flag_values_.end()) {
|
||||
return false;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string ArgParser::helpText() const {
|
||||
std::ostringstream oss;
|
||||
oss << "Usage: " << program_name_ << " [options]\n\n";
|
||||
@@ -135,7 +251,16 @@ std::string ArgParser::helpText() const {
|
||||
continue;
|
||||
}
|
||||
|
||||
oss << " --" << key << " <value>";
|
||||
oss << " ";
|
||||
if (!m->second.short_name.empty()) {
|
||||
oss << "-" << m->second.short_name << ", ";
|
||||
} else {
|
||||
oss << " ";
|
||||
}
|
||||
oss << "--" << key;
|
||||
if (m->second.type != OptionType::kFlag) {
|
||||
oss << " <value>";
|
||||
}
|
||||
if (m->second.required) {
|
||||
oss << " (required)";
|
||||
}
|
||||
@@ -147,9 +272,11 @@ std::string ArgParser::helpText() const {
|
||||
oss << " [default: '" << s->second << "']";
|
||||
}
|
||||
} else {
|
||||
auto iv = int_values_.find(key);
|
||||
if (iv != int_values_.end()) {
|
||||
oss << " [default: " << iv->second << "]";
|
||||
if (m->second.type == OptionType::kInt) {
|
||||
auto iv = int_values_.find(key);
|
||||
if (iv != int_values_.end()) {
|
||||
oss << " [default: " << iv->second << "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
oss << "\n";
|
||||
|
||||
Reference in New Issue
Block a user