in src/controller/cmdline_parser.h [153:246]
void CmdlineParser<CLI>::parse(int argc, char** argv)
{
// generate input data for getopt_long()
option long_opts[CLI::num + 1]; // +1 for NULL-option
char short_opts[CLI::num * 2 + 2] = {0};
short_opts[0] = ':';
char* short_p = &short_opts[1];
for(int i = 0; i < CLI::num; ++i)
{
const Opt& a = CLI::options[i];
long_opts[i].name = a.long_opt;
long_opts[i].has_arg = (a.type == Opt::Type::NOA) ? no_argument : required_argument;
long_opts[i].flag = 0;
long_opts[i].val = 0;
if(a.short_opt)
{
*short_p = a.short_opt;
++short_p;
if(a.type != Opt::Type::NOA)
{
*short_p = ':'; // argument to option is required
++short_p;
}
}
}
// fill last element
memset(&long_opts[CLI::num], 0, sizeof(long_opts[CLI::num]));
// assuming that argc and argv are the same as those passed to program
int opt_index = 0;
while(true)
{
int opt = getopt_long(argc, argv, short_opts, long_opts, &opt_index);
if(opt == -1)
{
break;
}
switch(opt)
{
case 0:
// store long option
set_value(opt_index, optarg);
break;
case '?':
{
std::string unkn{build_name(optopt, argv[optind - 1])};
throw CLIError{std::string{"Unrecognized option: "} + unkn};
}
case ':':
{
std::string miss{build_name(optopt, argv[optind - 1])};
throw CLIError{std::string{"Option requires an argument: "} + miss};
}
default:
{
// if short option found
const int index = short_opt_index(opt);
if(index != -1)
{
set_value(index, optarg);
}
}
}
}
// if we get non-option element in args, throw exception
if(optind != argc)
{
// quote non-option
std::string name{build_name(0, argv[optind])};
throw CLIError{std::string{"Unexpected operand on command line: "} + name};
}
// set default values
for(Opt& o : CLI::options)
{
if(o.value == nullptr // is value still uninitialized?
&& o.deflt != nullptr) // try to substitute by default value
{
o.value = o.deflt;
o.passed = false;
}
}
}