@@ -270,18 +270,20 @@ class cmdline_processor
270270 };
271271 std::vector<arg> args;
272272
273- using callback = void (*)();
273+ using callback0 = void (*)();
274+ using callback1 = void (*)(std::string const &);
274275 struct flag
275276 {
276277 int group = 0 ;
277278 std::string name;
278279 int unique_prefix = 0 ;
279280 std::string description;
280- callback handler;
281+ callback0 handler0;
282+ callback1 handler1;
281283 std::string synonym;
282284
283- flag (int g, std::string_view n, std::string_view d, callback h , std::string_view s)
284- : group{g}, name{n}, description{d}, handler{h }, synonym{s}
285+ flag (int g, std::string_view n, std::string_view d, callback0 h0, callback1 h1 , std::string_view s)
286+ : group{g}, name{n}, description{d}, handler0{h0}, handler1{h1 }, synonym{s}
285287 { }
286288 };
287289 std::vector<flag> flags;
@@ -315,42 +317,59 @@ class cmdline_processor
315317 }
316318
317319 // Look for matches
318- for (auto & arg : args)
320+ for (auto arg = args. begin (); arg != args. end (); ++arg )
319321 {
320322 // The arg should never be empty, but we're going to do a [0]
321323 // subscript next so we should either check or assert
322- if (arg. text .empty ()) {
324+ if (arg-> text .empty ()) {
323325 continue ;
324326 }
325327
326328 // Provide a way to ignore the rest of the command line
327329 // for the purpose of looking for switches
328- if (arg. text == " --" ) {
329- arg. pos = processed;
330+ if (arg-> text == " --" ) {
331+ arg-> pos = processed;
330332 break ;
331333 }
332334
333335 for (auto & flag : flags) {
334- auto length_to_match = std::max (flag.unique_prefix , as<int >(arg. text .length ())-1 );
336+ auto length_to_match = std::max (flag.unique_prefix , as<int >(arg-> text .length ())-1 );
335337 // Allow a switch to start with either - or /
336- if (arg. text .starts_with (" -" + flag.name .substr (0 , length_to_match)) ||
337- arg. text .starts_with (" /" + flag.name .substr (0 , length_to_match)) ||
338- arg. text == " -" + flag.synonym ||
339- arg. text == " /" + flag.synonym
338+ if (arg-> text .starts_with (" -" + flag.name .substr (0 , length_to_match)) ||
339+ arg-> text .starts_with (" /" + flag.name .substr (0 , length_to_match)) ||
340+ arg-> text == " -" + flag.synonym ||
341+ arg-> text == " /" + flag.synonym
340342 )
341343 {
342- flag.handler ();
343- arg.pos = processed;
344+ assert (flag.handler0 || flag.handler1 );
345+
346+ // If this is a standalone switch, just process it
347+ if (flag.handler0 ) {
348+ flag.handler0 ();
349+ }
350+
351+ // Else this is a switch that takes the next arg as its value, so pass that
352+ else {
353+ if (arg+1 == args.end ()) {
354+ print (" Missing argument to option " + arg->text + " (try -help)\n " );
355+ help_requested = true ;
356+ }
357+ arg->pos = processed;
358+ ++arg; // move to next argument, which is the argument to this switch
359+ flag.handler1 (arg->text );
360+ }
361+
362+ arg->pos = processed;
344363 break ;
345364 }
346365 }
347366
348367 // For now comment this out to try leaving unmatched switches alone, so that
349368 // Unix absolute filenames work... and in case an absolute filename collides
350369 // with a legit switch name, also added "--" above... let's see how this works
351- // if (arg. pos != processed && (arg. text.starts_with("-") || arg. text.starts_with("/"))) {
352- // arg. pos = processed;
353- // print("Unknown option: " + arg. text + " (try -help)\n");
370+ // if (arg-> pos != processed && (arg-> text.starts_with("-") || arg-> text.starts_with("/"))) {
371+ // arg-> pos = processed;
372+ // print("Unknown option: " + arg-> text + " (try -help)\n");
354373 // help_requested = true;
355374 // }
356375 }
@@ -391,14 +410,14 @@ class cmdline_processor
391410 }
392411 }
393412
394- auto add_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym) {
395- flags.emplace_back ( group, name, description, handler , synonym );
413+ auto add_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 , std::string_view synonym) {
414+ flags.emplace_back ( group, name, description, handler0, handler1 , synonym );
396415 if (max_flag_length < std::ssize (name)) {
397416 max_flag_length = std::ssize (name);
398417 }
399418 }
400419 struct register_flag {
401- register_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym = {});
420+ register_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 = nullptr , std::string_view synonym = {});
402421 };
403422
404423 auto set_args (int argc, char * argv[]) -> void {
@@ -431,15 +450,16 @@ class cmdline_processor
431450
432451} cmdline;
433452
434- cmdline_processor::register_flag::register_flag (int group, std::string_view name, std::string_view description, callback handler , std::string_view synonym) {
435- cmdline.add_flag ( group, name, description, handler , synonym );
453+ cmdline_processor::register_flag::register_flag (int group, std::string_view name, std::string_view description, callback0 handler0, callback1 handler1 , std::string_view synonym) {
454+ cmdline.add_flag ( group, name, description, handler0, handler1 , synonym );
436455}
437456
438457static cmdline_processor::register_flag cmd_help (
439458 0 ,
440459 " help" ,
441460 " Print help" ,
442461 []{ cmdline.print_help (); },
462+ nullptr ,
443463 " ?"
444464);
445465
0 commit comments