#include <config.h>
#include <iostream>
#include <cstring>
#include "Option.h"
#include "OptionsCont.h"
#include "OptionsParser.h"
#include <utils/common/UtilExceptions.h>
#include <utils/common/MsgHandler.h>
bool
OptionsParser::parse(const std::vector<std::string>& args, const bool ignoreAppenders) {
bool ok = true;
const int argc = (int)args.size();
for (int i = 1; i < argc;) {
try {
int add;
if (i < argc - 1) {
add = check(args[i], &args[i + 1], ok, ignoreAppenders);
} else {
add = check(args[i], nullptr, ok, ignoreAppenders);
}
i += add;
} catch (ProcessError& e) {
WRITE_ERROR("On processing option '" + args[i] + "':\n " + e.what());
i++;
ok = false;
}
}
return ok;
}
int
OptionsParser::check(const std::string& arg1, const std::string* const arg2, bool& ok, const bool ignoreAppenders) {
if (!checkParameter(arg1)) {
ok = false;
return 1;
}
#ifdef _DEBUG
if ((arg1 == "-tracelevel" || arg1 == "-maxcolors") && arg2 != nullptr) {
ok = true;
return 2;
}
#endif
OptionsCont& oc = OptionsCont::getOptions();
const bool append = arg1[0] == '+';
if (append || arg1[1] == '-') {
const std::string tmp(arg1.substr(append ? 1 : 2));
const std::string::size_type idx1 = tmp.find('=');
if (append && ignoreAppenders) {
return idx1 == std::string::npos ? 2 : 1;
}
if (idx1 != std::string::npos) {
ok &= oc.set(tmp.substr(0, idx1), tmp.substr(idx1 + 1), append);
} else {
if (arg2 == nullptr || (oc.isBool(tmp) && (*arg2)[0] == '-')) {
ok &= oc.set(tmp, "true");
} else {
ok &= oc.set(tmp, *arg2, append);
return 2;
}
}
return 1;
}
const int len = (int)arg1.size();
for (int i = 1; i < len; i++) {
const std::string abbr = arg1.substr(i, 1);
if (oc.isBool(abbr)) {
if (arg2 == nullptr || (*arg2)[0] == '-' || i != len - 1) {
ok &= oc.set(abbr, "true");
} else {
ok &= oc.set(abbr, *arg2);
return 2;
}
} else {
if (arg2 == nullptr || i != len - 1) {
ok &= processNonBooleanSingleSwitch(oc, arg1.substr(i), append);
return 1;
} else {
ok &= oc.set(abbr, *arg2, append);
return 2;
}
}
}
return 1;
}
bool
OptionsParser::processNonBooleanSingleSwitch(OptionsCont& oc, const std::string& arg, const bool append) {
if (arg[1] == '=') {
if (arg.size() < 3) {
WRITE_ERRORF(TL("Missing value for parameter '%'."), arg.substr(0, 1));
return false;
} else {
return oc.set(arg.substr(0, 1), arg.substr(2), append);
}
} else {
if (arg.size() < 2) {
WRITE_ERRORF(TL("Missing value for parameter '%'."), arg);
return false;
} else {
return oc.set(arg.substr(0, 1), arg.substr(1), append);
}
}
}
bool
OptionsParser::checkParameter(const std::string& arg1) {
if (arg1[0] != '-' && arg1[0] != '+') {
WRITE_ERRORF(TL("The parameter '%' is not allowed in this context.\n Switch or parameter name expected."), arg1);
return false;
}
if ((arg1[0] == '-' && arg1[1] == '+') || (arg1[0] == '+' && arg1[1] == '-')) {
WRITE_ERRORF(TL("Mixed parameter syntax in '%'."), arg1);
return false;
}
return true;
}