| /** |
| * @file popt_options.cpp |
| * option parsing |
| * |
| * @remark Copyright 2002 OProfile authors |
| * @remark Read the file COPYING |
| * |
| * @author Philippe Elie |
| * @author John Levon |
| */ |
| |
| #include <iostream> |
| |
| #include "op_popt.h" |
| #include "op_version.h" |
| |
| #include "popt_options.h" |
| #include "string_manip.h" |
| |
| using namespace std; |
| |
| namespace popt { |
| |
| /** |
| * option_base - base class for implementation of a command line option |
| * |
| * Every command line option added before calling parse_options() |
| * is of this type. |
| */ |
| class option_base { |
| public: |
| /** |
| * option_base - construct an option with the given options. |
| * @param option_name name part of long form e.g. --option |
| * @param short_name short form name e.g. -o |
| * @param help_str short description of the option |
| * @param arg_help_str short description of the argument (if any) |
| * @param data a pointer to the data to fill in |
| * @param popt_flags the popt library data type |
| */ |
| option_base(char const * option_name, char short_name, |
| char const * help_str, char const * arg_help_str, |
| void * data, int popt_flags); |
| |
| virtual ~option_base() {} |
| |
| /** |
| * post_process - perform any necessary post-processing |
| */ |
| virtual void post_process() {} |
| |
| protected: |
| char const * option_name; |
| }; |
| |
| |
| /** the popt array singleton options */ |
| static vector<poptOption> & popt_options(void) |
| { |
| static vector<poptOption> *x = new(vector<poptOption>); |
| return *x; |
| } |
| |
| static vector<option_base *> & options_list(void) |
| { |
| static vector<option_base *> *x = new(vector<option_base *>); |
| return *x; |
| } |
| |
| static int showvers; |
| |
| static struct poptOption appended_options[] = { |
| { "version", 'v', POPT_ARG_NONE, &showvers, 0, "show version", NULL, }, |
| POPT_AUTOHELP |
| POPT_TABLEEND |
| }; |
| |
| |
| /* options parameter can't be a local variable because caller can use the |
| * returned poptContext which contains pointer inside the options array */ |
| static poptContext do_parse_options(int argc, char const ** argv, |
| vector<poptOption> & options, |
| vector<string> & additional_params) |
| { |
| options = popt_options(); |
| |
| int const nr_appended_options = |
| sizeof(appended_options) / sizeof(appended_options[0]); |
| |
| options.insert(options.end(), appended_options, |
| appended_options + nr_appended_options); |
| |
| poptContext con = op_poptGetContext(NULL, argc, argv, &options[0], 0); |
| |
| if (showvers) |
| show_version(argv[0]); |
| |
| char const * file; |
| while ((file = poptGetArg(con)) != 0) |
| additional_params.push_back(file); |
| |
| for (size_t i = 0 ; i < options_list().size() ; ++i) |
| options_list()[i]->post_process(); |
| |
| return con; |
| } |
| |
| |
| void parse_options(int argc, char const ** argv, |
| vector<string> & additional_params) |
| { |
| vector<poptOption> options; |
| |
| poptContext con = |
| do_parse_options(argc, argv, options, additional_params); |
| |
| poptFreeContext(con); |
| } |
| |
| |
| template <typename T> class option_imp; |
| |
| |
| /** |
| * option<void> - a binary option |
| * |
| * Use this option type for constructing specified / not-specified |
| * options e.g. --frob |
| */ |
| template <> class option_imp<void> : public option_base { |
| public: |
| option_imp(bool & value, char const * option_name, char short_name, |
| char const * help_str); |
| |
| ~option_imp() {} |
| |
| void post_process(); |
| |
| private: |
| bool & value; |
| int popt_value; |
| }; |
| |
| |
| /** |
| * option<int> - a integer option |
| * |
| * Use this for options taking an integer e.g. --frob 6 |
| */ |
| template <> class option_imp<int> : public option_base { |
| public: |
| option_imp(int & value, char const * option_name, char short_name, |
| char const * help_str, char const * arg_help_str); |
| |
| ~option_imp() {} |
| }; |
| |
| |
| /** |
| * option<string> - a string option |
| * |
| * Use this for options taking a string e.g. --frob parsley |
| */ |
| template <> class option_imp<string> : public option_base { |
| public: |
| option_imp(string & value, char const * option_name, |
| char short_name, char const * help_str, |
| char const * arg_help_str); |
| |
| void post_process(); |
| |
| ~option_imp() {} |
| |
| private: |
| // we need an intermediate char array to pass to popt libs |
| char * popt_value; |
| string & value; |
| }; |
| |
| |
| /** |
| * option< vector<string> > - a string vector option |
| * |
| * Use this for options taking a number of string arguments, |
| * separated by the given separator. |
| */ |
| template <> class option_imp< vector<string> > : public option_base { |
| public: |
| option_imp(vector<string> & value, |
| char const * option_name, char short_name, |
| char const * help_str, char const * arg_help_str, |
| char separator = ','); |
| |
| void post_process(); |
| |
| ~option_imp() {} |
| |
| private: |
| vector<string> & value; |
| // we need an intermediate char array to pass to popt libs |
| char * popt_value; |
| char const separator; |
| }; |
| |
| |
| option::~option() |
| { |
| delete the_option; |
| } |
| |
| |
| /// non templatized ctor for boolean option |
| option::option(bool & value, char const * name, char short_name, char const * help) |
| : the_option(new option_imp<void>(value, name, short_name, help)) |
| { |
| } |
| |
| |
| /// specialization of option ctor for integer option |
| template <> |
| option::option(int & value, char const * name, char short_name, |
| char const * help, char const * arg_help) |
| : the_option(new option_imp<int> |
| (value, name, short_name, help, arg_help)) |
| { |
| } |
| |
| |
| /// specialization of option ctor for string option |
| template <> |
| option::option(string & value, char const * name, char short_name, |
| char const * help, char const * arg_help) |
| : the_option(new option_imp<string> |
| (value, name, short_name, help, arg_help)) |
| { |
| } |
| |
| |
| /// specialization of option ctor for vector<string> option |
| template <> |
| option::option(vector<string> & value, char const * name, char short_name, |
| char const * help, char const * arg_help) |
| : the_option(new option_imp< vector<string> > |
| (value, name, short_name, help, arg_help)) |
| { |
| } |
| |
| |
| option_base::option_base(char const * name, char short_name, |
| char const * help, char const * arg_help, |
| void * data, int popt_flags) |
| : option_name(name) |
| { |
| poptOption const opt = { name, short_name, popt_flags, |
| data, 0, help, arg_help }; |
| |
| popt_options().push_back(opt); |
| |
| options_list().push_back(this); |
| } |
| |
| |
| option_imp<void>::option_imp(bool & val, char const * name, char short_name, |
| char const * help) |
| : option_base(name, short_name, help, 0, &popt_value, POPT_ARG_NONE), |
| value(val), popt_value(0) |
| { |
| } |
| |
| |
| void option_imp<void>::post_process() |
| { |
| if (popt_value) { |
| if (is_prefix(option_name, "no-")) |
| value = !popt_value; |
| else |
| value = popt_value; |
| } |
| } |
| |
| |
| option_imp<int>::option_imp(int & value, char const * name, char short_name, |
| char const * help, char const * arg_help) |
| : option_base(name, short_name, help, arg_help, &value, POPT_ARG_INT) |
| { |
| } |
| |
| |
| option_imp<string>::option_imp(string & val, char const * name, char short_name, |
| char const * help, char const * arg_help) |
| : option_base(name, short_name, help, arg_help, |
| &popt_value, POPT_ARG_STRING), |
| popt_value(0), value(val) |
| { |
| } |
| |
| |
| void option_imp<string>::post_process() |
| { |
| if (popt_value) { |
| value = popt_value; |
| popt_value = 0; |
| } |
| } |
| |
| |
| option_imp< vector<string> >::option_imp(vector<string> & val, |
| char const * name, char short_name, |
| char const * help, |
| char const * arg_help, char sepchar) |
| : option_base(name, short_name, help, arg_help, |
| &popt_value, POPT_ARG_STRING), |
| value(val), popt_value(0), separator(sepchar) |
| { |
| } |
| |
| |
| void option_imp< vector<string> >::post_process() |
| { |
| if (popt_value) { |
| value = separate_token(popt_value, separator); |
| |
| popt_value = 0; |
| } |
| } |
| |
| } // namespace popt |