Commit ac0060ac38ecf4fa380f49fd1e40ebaabb479596

Authored by Jay Berkenbilt
1 parent 1c420e85

Refactor arg parsing to allow help option with parameter

Showing 1 changed file with 67 additions and 89 deletions
qpdf/qpdf.cc
@@ -926,7 +926,6 @@ class ArgParser @@ -926,7 +926,6 @@ class ArgParser
926 void usage(std::string const& message); 926 void usage(std::string const& message);
927 void checkCompletion(); 927 void checkCompletion();
928 void initOptionTable(); 928 void initOptionTable();
929 - void handleHelpArgs();  
930 void handleArgFileArguments(); 929 void handleArgFileArguments();
931 void handleBashArguments(); 930 void handleBashArguments();
932 void readArgsFromFile(char const* filename); 931 void readArgsFromFile(char const* filename);
@@ -3412,37 +3411,6 @@ ArgParser::readArgsFromFile(char const* filename) @@ -3412,37 +3411,6 @@ ArgParser::readArgsFromFile(char const* filename)
3412 } 3411 }
3413 3412
3414 void 3413 void
3415 -ArgParser::handleHelpArgs()  
3416 -{  
3417 - // Handle special-case informational options that are only  
3418 - // available as the sole option.  
3419 -  
3420 - if (argc != 2)  
3421 - {  
3422 - return;  
3423 - }  
3424 - char* arg = argv[1];  
3425 - if (*arg != '-')  
3426 - {  
3427 - return;  
3428 - }  
3429 - ++arg;  
3430 - if (*arg == '-')  
3431 - {  
3432 - ++arg;  
3433 - }  
3434 - if (! *arg)  
3435 - {  
3436 - return;  
3437 - }  
3438 - if (this->help_option_table.count(arg))  
3439 - {  
3440 - (this->*(this->help_option_table[arg].bare_arg_handler))();  
3441 - exit(0);  
3442 - }  
3443 -}  
3444 -  
3445 -void  
3446 ArgParser::parseRotationParameter(std::string const& parameter) 3414 ArgParser::parseRotationParameter(std::string const& parameter)
3447 { 3415 {
3448 std::string angle_str; 3416 std::string angle_str;
@@ -3601,22 +3569,23 @@ void @@ -3601,22 +3569,23 @@ void
3601 ArgParser::parseOptions() 3569 ArgParser::parseOptions()
3602 { 3570 {
3603 checkCompletion(); 3571 checkCompletion();
3604 - if (! this->bash_completion)  
3605 - {  
3606 - handleHelpArgs();  
3607 - }  
3608 handleArgFileArguments(); 3572 handleArgFileArguments();
3609 for (cur_arg = 1; cur_arg < argc; ++cur_arg) 3573 for (cur_arg = 1; cur_arg < argc; ++cur_arg)
3610 { 3574 {
  3575 + bool help_option = false;
  3576 + auto oep = this->option_table->end();
3611 char* arg = argv[cur_arg]; 3577 char* arg = argv[cur_arg];
  3578 + char* parameter = nullptr;
  3579 + std::string o_arg(arg);
  3580 + std::string arg_s(arg);
3612 if (strcmp(arg, "--") == 0) 3581 if (strcmp(arg, "--") == 0)
3613 { 3582 {
3614 // Special case for -- option, which is used to break out 3583 // Special case for -- option, which is used to break out
3615 // of subparsers. 3584 // of subparsers.
3616 - OptionEntry& oe = (*this->option_table)["--"];  
3617 - if (oe.bare_arg_handler) 3585 + oep = this->option_table->find("--");
  3586 + if (oep == this->option_table->end())
3618 { 3587 {
3619 - (this->*(oe.bare_arg_handler))(); 3588 + throw std::logic_error("ArgParser: -- handler not registered");
3620 } 3589 }
3621 } 3590 }
3622 else if ((arg[0] == '-') && (strcmp(arg, "-") != 0)) 3591 else if ((arg[0] == '-') && (strcmp(arg, "-") != 0))
@@ -3627,7 +3596,6 @@ ArgParser::parseOptions() @@ -3627,7 +3596,6 @@ ArgParser::parseOptions()
3627 // Be lax about -arg vs --arg 3596 // Be lax about -arg vs --arg
3628 ++arg; 3597 ++arg;
3629 } 3598 }
3630 - char* parameter = 0;  
3631 if (strlen(arg) > 0) 3599 if (strlen(arg) > 0)
3632 { 3600 {
3633 // Prevent --=something from being treated as an empty 3601 // Prevent --=something from being treated as an empty
@@ -3640,72 +3608,82 @@ ArgParser::parseOptions() @@ -3640,72 +3608,82 @@ ArgParser::parseOptions()
3640 *parameter++ = 0; 3608 *parameter++ = 0;
3641 } 3609 }
3642 3610
3643 - std::string arg_s(arg);  
3644 - if (arg_s.empty() ||  
3645 - (arg_s.at(0) == '-') ||  
3646 - (0 == this->option_table->count(arg_s))) 3611 + arg_s = arg;
  3612 + if (! (arg_s.empty() || (arg_s.at(0) == '-')))
3647 { 3613 {
3648 - usage(std::string("unknown option --") + arg); 3614 + oep = this->option_table->find(arg_s);
3649 } 3615 }
3650 3616
3651 - OptionEntry& oe = (*this->option_table)[arg_s];  
3652 - if ((oe.parameter_needed && (0 == parameter)) ||  
3653 - ((! oe.choices.empty() &&  
3654 - ((0 == parameter) ||  
3655 - (0 == oe.choices.count(parameter)))))) 3617 + if ((! this->bash_completion) &&
  3618 + (argc == 2) && (cur_arg == 1) &&
  3619 + (oep == this->option_table->end()))
3656 { 3620 {
3657 - std::string message =  
3658 - "--" + arg_s + " must be given as --" + arg_s + "=";  
3659 - if (! oe.choices.empty()) 3621 + // Handle help option, which is only valid as the sole
  3622 + // option.
  3623 + oep = this->help_option_table.find(arg_s);
  3624 + help_option = true;
  3625 + }
  3626 + }
  3627 + else
  3628 + {
  3629 + // The empty string maps to the positional argument
  3630 + // handler.
  3631 + oep = this->option_table->find("");
  3632 + parameter = arg;
  3633 + }
  3634 +
  3635 + if (oep == this->option_table->end())
  3636 + {
  3637 + usage("unrecognized argument " + o_arg);
  3638 + }
  3639 +
  3640 + OptionEntry& oe = oep->second;
  3641 + if ((oe.parameter_needed && (0 == parameter)) ||
  3642 + ((! oe.choices.empty() &&
  3643 + ((0 == parameter) ||
  3644 + (0 == oe.choices.count(parameter))))))
  3645 + {
  3646 + std::string message =
  3647 + "--" + arg_s + " must be given as --" + arg_s + "=";
  3648 + if (! oe.choices.empty())
  3649 + {
  3650 + QTC::TC("qpdf", "qpdf required choices");
  3651 + message += "{";
  3652 + for (std::set<std::string>::iterator iter =
  3653 + oe.choices.begin();
  3654 + iter != oe.choices.end(); ++iter)
3660 { 3655 {
3661 - QTC::TC("qpdf", "qpdf required choices");  
3662 - message += "{";  
3663 - for (std::set<std::string>::iterator iter =  
3664 - oe.choices.begin();  
3665 - iter != oe.choices.end(); ++iter) 3656 + if (iter != oe.choices.begin())
3666 { 3657 {
3667 - if (iter != oe.choices.begin())  
3668 - {  
3669 - message += ",";  
3670 - }  
3671 - message += *iter; 3658 + message += ",";
3672 } 3659 }
3673 - message += "}";  
3674 - }  
3675 - else if (! oe.parameter_name.empty())  
3676 - {  
3677 - QTC::TC("qpdf", "qpdf required parameter");  
3678 - message += oe.parameter_name;  
3679 - }  
3680 - else  
3681 - {  
3682 - // should not be possible  
3683 - message += "option"; 3660 + message += *iter;
3684 } 3661 }
3685 - usage(message); 3662 + message += "}";
3686 } 3663 }
3687 - if (oe.bare_arg_handler) 3664 + else if (! oe.parameter_name.empty())
3688 { 3665 {
3689 - (this->*(oe.bare_arg_handler))(); 3666 + QTC::TC("qpdf", "qpdf required parameter");
  3667 + message += oe.parameter_name;
3690 } 3668 }
3691 - else if (oe.param_arg_handler) 3669 + else
3692 { 3670 {
3693 - (this->*(oe.param_arg_handler))(parameter); 3671 + // should not be possible
  3672 + message += "option";
3694 } 3673 }
  3674 + usage(message);
3695 } 3675 }
3696 - else if (0 != this->option_table->count("")) 3676 + if (oe.bare_arg_handler)
3697 { 3677 {
3698 - // The empty string maps to the positional argument  
3699 - // handler.  
3700 - OptionEntry& oe = (*this->option_table)[""];  
3701 - if (oe.param_arg_handler)  
3702 - {  
3703 - (this->*(oe.param_arg_handler))(arg);  
3704 - } 3678 + (this->*(oe.bare_arg_handler))();
3705 } 3679 }
3706 - else 3680 + else if (oe.param_arg_handler)
  3681 + {
  3682 + (this->*(oe.param_arg_handler))(parameter);
  3683 + }
  3684 + if (help_option)
3707 { 3685 {
3708 - usage(std::string("unknown argument ") + arg); 3686 + exit(0);
3709 } 3687 }
3710 } 3688 }
3711 if (this->bash_completion) 3689 if (this->bash_completion)