| 210 | } |
| 211 | |
| 212 | static PatternList parse_long(Tokens& tokens, std::vector<Option>& options) |
| 213 | { |
| 214 | // long ::= '--' chars [ ( ' ' | '=' ) chars ] ; |
| 215 | std::string longOpt, equal; |
| 216 | value val; |
| 217 | std::tie(longOpt, equal, val) = partition(tokens.pop(), "="); |
| 218 | |
| 219 | assert(starts_with(longOpt, "--")); |
| 220 | |
| 221 | if (equal.empty()) { |
| 222 | val = value{}; |
| 223 | } |
| 224 | |
| 225 | // detect with options match this long option |
| 226 | std::vector<Option const*> similar; |
| 227 | for(auto const& option : options) { |
| 228 | if (option.longOption()==longOpt) |
| 229 | similar.push_back(&option); |
| 230 | } |
| 231 | |
| 232 | // maybe allow similar options that match by prefix |
| 233 | if (tokens.isParsingArgv() && similar.empty()) { |
| 234 | for(auto const& option : options) { |
| 235 | if (option.longOption().empty()) |
| 236 | continue; |
| 237 | if (starts_with(option.longOption(), longOpt)) |
| 238 | similar.push_back(&option); |
| 239 | } |
| 240 | } |
| 241 | |
| 242 | PatternList ret; |
| 243 | |
| 244 | if (similar.size() > 1) { // might be simply specified ambiguously 2+ times? |
| 245 | std::vector<std::string> prefixes = longOptions(similar.begin(), similar.end()); |
| 246 | std::string error = "'" + longOpt + "' is not a unique prefix: "; |
| 247 | error.append(join(prefixes.begin(), prefixes.end(), ", ")); |
| 248 | throw Tokens::OptionError(std::move(error)); |
| 249 | } else if (similar.empty()) { |
| 250 | int argcount = equal.empty() ? 0 : 1; |
| 251 | options.emplace_back("", longOpt, argcount); |
| 252 | |
| 253 | auto o = std::make_shared<Option>(options.back()); |
| 254 | if (tokens.isParsingArgv()) { |
| 255 | o->setValue(argcount ? value{val} : value{true}); |
| 256 | } |
| 257 | ret.push_back(o); |
| 258 | } else { |
| 259 | auto o = std::make_shared<Option>(*similar[0]); |
| 260 | if (o->argCount() == 0) { |
| 261 | if (val) { |
| 262 | std::string error = o->longOption() + " must not have an argument"; |
| 263 | throw Tokens::OptionError(std::move(error)); |
| 264 | } |
| 265 | } else { |
| 266 | if (!val) { |
| 267 | auto const& token = tokens.current(); |
| 268 | if (token.empty() || token=="--") { |
| 269 | std::string error = o->longOption() + " requires an argument"; |
no test coverage detected