44         std::size_t maxLineLengthWithoutDescription = 0;
 
   47             std::stringstream lineSchema;
 
   48             const auto shortOption = 
"?";
 
   49             const auto longOption = 
"";
 
   50             const auto arguments = 
"";
 
   51             const auto description = 
"";
 
   52             lineSchema << TWO_SPACES << 
"-" << shortOption << 
"," << ONE_SPACE << 
"--" << longOption << 
"=<" 
   53                        << arguments << 
">" << TWO_SPACES << description;
 
   54             maxLineLengthWithoutDescription = lineSchema.str().size();
 
   58             std::size_t maxLongOptionPlusArgumentLength = 0;
 
   59             for (
const MainOption& opt : mainOptions) {
 
   60                 if (opt.longName.empty()) {
 
   63                 const auto longOptionPlusArgumentLength = opt.longName.size() + opt.argument.size();
 
   64                 if (longOptionPlusArgumentLength > maxLongOptionPlusArgumentLength) {
 
   65                     maxLongOptionPlusArgumentLength = longOptionPlusArgumentLength;
 
   68             maxLineLengthWithoutDescription += maxLongOptionPlusArgumentLength;
 
   73         for (
const MainOption& opt : mainOptions) {
 
   75             std::stringstream line;
 
   78             if (opt.longName.empty()) {
 
   84             if (isalpha(opt.shortName) != 0) {
 
   85                 line << 
"-" << opt.shortName << 
",";
 
   91             line << ONE_SPACE << 
"--" << opt.longName;
 
   94             if (!opt.argument.empty()) {
 
   95                 line << 
"=<" << opt.argument << 
">";
 
   99             for (std::size_t lineLength = line.str().size(); lineLength < maxLineLengthWithoutDescription;
 
  105             line << opt.description << std::endl;
 
  120         option longNames[mainOptions.size()];
 
  122         std::string shortNames = 
"";
 
  124         std::map<const char, const MainOption*> optionTable;
 
  128         for (
const MainOption& opt : mainOptions) {
 
  129             assert(opt.shortName != 
'?' && 
"short name for option cannot be '?'");
 
  131             optionTable[opt.shortName] = &opt;
 
  133             if (!opt.byDefault.empty()) {
 
  134                 set(opt.longName, opt.byDefault);
 
  137             if (opt.longName.empty()) {
 
  141             longNames[
i] = {opt.longName.c_str(), opt.argument.empty() ? 0 : 1, 
nullptr, opt.shortName};
 
  143             shortNames += opt.shortName;
 
  145             if (!opt.argument.empty()) {
 
  152         longNames[
i] = {
nullptr, 0, 
nullptr, 0};
 
  157         while ((c = getopt_long(argc, argv, shortNames.c_str(), longNames, 
nullptr)) != EOF) {
 
  161                 throw std::runtime_error(
"Error: Unknown command line option.");
 
  164             auto iter = optionTable.find(c);
 
  166             assert(iter != optionTable.end() && 
"unexpected case in getopt");
 
  169             std::string arg = optarg != 
nullptr ? std::string(optarg) : 
std::string();
 
  171             if (iter->second->takesMany) {
 
  174                 set(iter->second->longName, 
get(iter->second->longName) + 
' ' + arg);
 
  178                 if (
has(iter->second->longName) &&
 
  179                         (iter->second->byDefault.empty() ||
 
  180                                 !
has(iter->second->longName, iter->second->byDefault))) {
 
  181                     throw std::runtime_error(
 
  182                             "Error: Only one argument allowed for option '" + iter->second->longName + 
"'");
 
  184                 set(iter->second->longName, arg);
 
  191         std::string filename = 
"";
 
  193         if (argc > 1 && optind >= argc) {
 
  195             throw std::runtime_error(
"Error: Unknown command line option.");
 
  198         if (mainOptions[0].longName.empty() && mainOptions[0].takesMany) {
 
  201             set(
"", std::string(argv[optind]));
 
  204             std::string filenames = 
"";
 
  206             for (; optind < argc; optind++) {
 
  208                 if (filenames.empty()) {
 
  209                     filenames = argv[optind];
 
  211                     filenames = filenames + 
" " + std::string(argv[optind]);