Commit ac0060ac38ecf4fa380f49fd1e40ebaabb479596
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) |