for (int j = 0; opt[j]; j++) {
const char key = opt[j];
if (key == '?') help(argv[0]);
if (is_help && key == '?') help(stderr);
if (!options.count(key)) goto unknown;
const auto *option = options[key];
const char *arg = nullptr;
if (option->arg) {
if (opt[j + 1] != 0) {
// rest of the line is option argument
arg = opt + j + 1;
} else if ((option->flags & ARG_OPTIONAL) == 0) {
// next argv is option argument
if (i == argc) goto missing;
arg = argv[++i];
}
if (!options.count(key)) {
err_code = handle_unknown(1, argv[i]);
goto error;
}
argp->parse(key, arg, this);
// if last option required argument we are done
if (arg) break;
const auto *option = options[key];
bool is_opt = option->flags & ARG_OPTIONAL;
if (!option->arg) argp->parse(key, nullptr, this);
if (opt[j + 1] != 0) {
argp->parse(key, opt + j + 1, this);
break;
} else if (!is_opt) argp->parse(key, nullptr, this);
else if (i + 1 != argc) {
argp->parse(key, argv[++i], this);
break;
} else {
err_code = handle_missing(1, argv[i]);
goto error;
}
}
} else { // long option
const char *opt = argv[i] + 2;
const auto eq = std::strchr(opt, '=');
const auto is_eq = std::strchr(opt, '=');
std::string opt_s = !eq ? opt : std::string(opt, eq - opt);
std::string opt_s = !is_eq ? opt : std::string(opt, is_eq - opt);
if (opt_s == "help") {
if (eq) goto excess;
help(argv[0]);
if (is_help && opt_s == "help") {
if (is_eq) {
err_code = handle_excess(0, argv[i]);
goto error;
}
help(stderr);
continue;
}
if (opt_s == "usage") {
if (eq) goto excess;
usage(argv[0]);
if (is_help && opt_s == "usage") {
if (is_eq) {
err_code = handle_excess(0, argv[i]);
goto error;
}
usage(stderr);
continue;
}
const int key = trie.get(opt_s.data());
if (!key) goto unknown;
if (!key) {
err_code = handle_unknown(0, argv[i]);
goto error;
}
const auto *option = options[key];
const char *arg = nullptr;
if (!option->arg && eq) goto excess;
if (option->arg) {
if (eq) {
// everything after = is option argument
arg = eq + 1;
} else if ((option->flags & ARG_OPTIONAL) == 0) {
// next argv is option argument
if (i == argc) goto missing;
arg = argv[++i];
}
if (!option->arg && is_eq) {
err_code = handle_excess(0, argv[i]);
goto error;
}
argp->parse(key, arg, this);
bool is_opt = option->flags & ARG_OPTIONAL;
if (!option->arg) argp->parse(key, nullptr, this);
else if (is_eq) argp->parse(key, is_eq + 1, this);
else if (is_opt) argp->parse(key, nullptr, this);
else if (i + 1 != argc) argp->parse(key, argv[++i], this);
else {
err_code = handle_missing(0, argv[i]);
goto error;
}
}
}