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 926 void usage(std::string const& message);
927 927 void checkCompletion();
928 928 void initOptionTable();
929   - void handleHelpArgs();
930 929 void handleArgFileArguments();
931 930 void handleBashArguments();
932 931 void readArgsFromFile(char const* filename);
... ... @@ -3412,37 +3411,6 @@ ArgParser::readArgsFromFile(char const* filename)
3412 3411 }
3413 3412  
3414 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 3414 ArgParser::parseRotationParameter(std::string const& parameter)
3447 3415 {
3448 3416 std::string angle_str;
... ... @@ -3601,22 +3569,23 @@ void
3601 3569 ArgParser::parseOptions()
3602 3570 {
3603 3571 checkCompletion();
3604   - if (! this->bash_completion)
3605   - {
3606   - handleHelpArgs();
3607   - }
3608 3572 handleArgFileArguments();
3609 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 3577 char* arg = argv[cur_arg];
  3578 + char* parameter = nullptr;
  3579 + std::string o_arg(arg);
  3580 + std::string arg_s(arg);
3612 3581 if (strcmp(arg, "--") == 0)
3613 3582 {
3614 3583 // Special case for -- option, which is used to break out
3615 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 3591 else if ((arg[0] == '-') && (strcmp(arg, "-") != 0))
... ... @@ -3627,7 +3596,6 @@ ArgParser::parseOptions()
3627 3596 // Be lax about -arg vs --arg
3628 3597 ++arg;
3629 3598 }
3630   - char* parameter = 0;
3631 3599 if (strlen(arg) > 0)
3632 3600 {
3633 3601 // Prevent --=something from being treated as an empty
... ... @@ -3640,72 +3608,82 @@ ArgParser::parseOptions()
3640 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 3689 if (this->bash_completion)
... ...