00001
00012 #include <iostream>
00013
00014 #include "op_popt.h"
00015 #include "op_version.h"
00016
00017 #include "popt_options.h"
00018 #include "string_manip.h"
00019
00020 using namespace std;
00021
00022 namespace popt {
00023
00030 class option_base {
00031 public:
00041 option_base(char const * option_name, char short_name,
00042 char const * help_str, char const * arg_help_str,
00043 void * data, unsigned int popt_flags);
00044
00045 virtual ~option_base() {}
00046
00050 virtual void post_process() {}
00051
00052 protected:
00053 char const * option_name;
00054 };
00055
00056
00058 static vector<poptOption> & popt_options(void)
00059 {
00060 static vector<poptOption> *x = new(vector<poptOption>);
00061 return *x;
00062 }
00063
00064 static vector<option_base *> & options_list(void)
00065 {
00066 static vector<option_base *> *x = new(vector<option_base *>);
00067 return *x;
00068 }
00069
00070 static int showvers;
00071
00072 static struct poptOption appended_options[] = {
00073 { "version", 'v', POPT_ARG_NONE, &showvers, 0, "show version", NULL, },
00074 POPT_AUTOHELP
00075 POPT_TABLEEND
00076 };
00077
00078
00079
00080
00081 static poptContext do_parse_options(int argc, char const ** argv,
00082 vector<poptOption> & options,
00083 vector<string> & additional_params)
00084 {
00085 options = popt_options();
00086
00087 int const nr_appended_options =
00088 sizeof(appended_options) / sizeof(appended_options[0]);
00089
00090 options.insert(options.end(), appended_options,
00091 appended_options + nr_appended_options);
00092
00093 poptContext con = op_poptGetContext(NULL, argc, argv, &options[0], 0);
00094
00095 if (showvers)
00096 show_version(argv[0]);
00097
00098 char const * file;
00099 while ((file = poptGetArg(con)) != 0)
00100 additional_params.push_back(file);
00101
00102 for (size_t i = 0 ; i < options_list().size() ; ++i)
00103 options_list()[i]->post_process();
00104
00105 return con;
00106 }
00107
00108
00109 void parse_options(int argc, char const ** argv,
00110 vector<string> & additional_params)
00111 {
00112 vector<poptOption> options;
00113
00114 poptContext con =
00115 do_parse_options(argc, argv, options, additional_params);
00116
00117 poptFreeContext(con);
00118 }
00119
00120
00121 template <typename T> class option_imp;
00122
00123
00130 template <> class option_imp<void> : public option_base {
00131 public:
00132 option_imp(bool & value, char const * option_name, char short_name,
00133 char const * help_str);
00134
00135 ~option_imp() {}
00136
00137 void post_process();
00138
00139 private:
00140 bool & value;
00141 int popt_value;
00142 };
00143
00144
00150 template <> class option_imp<int> : public option_base {
00151 public:
00152 option_imp(int & value, char const * option_name, char short_name,
00153 char const * help_str, char const * arg_help_str);
00154
00155 ~option_imp() {}
00156 };
00157
00158
00164 template <> class option_imp<string> : public option_base {
00165 public:
00166 option_imp(string & value, char const * option_name,
00167 char short_name, char const * help_str,
00168 char const * arg_help_str);
00169
00170 void post_process();
00171
00172 ~option_imp() {}
00173
00174 private:
00175
00176 char * popt_value;
00177 string & value;
00178 };
00179
00180
00187 template <> class option_imp< vector<string> > : public option_base {
00188 public:
00189 option_imp(vector<string> & value,
00190 char const * option_name, char short_name,
00191 char const * help_str, char const * arg_help_str,
00192 char separator = ',');
00193
00194 void post_process();
00195
00196 ~option_imp() {}
00197
00198 private:
00199 vector<string> & value;
00200
00201 char * popt_value;
00202 char const separator;
00203 };
00204
00205
00206 option::~option()
00207 {
00208 delete the_option;
00209 }
00210
00211
00213 option::option(bool & value, char const * name, char short_name, char const * help)
00214 : the_option(new option_imp<void>(value, name, short_name, help))
00215 {
00216 }
00217
00218
00220 template <>
00221 option::option(int & value, char const * name, char short_name,
00222 char const * help, char const * arg_help)
00223 : the_option(new option_imp<int>
00224 (value, name, short_name, help, arg_help))
00225 {
00226 }
00227
00228
00230 template <>
00231 option::option(string & value, char const * name, char short_name,
00232 char const * help, char const * arg_help)
00233 : the_option(new option_imp<string>
00234 (value, name, short_name, help, arg_help))
00235 {
00236 }
00237
00238
00240 template <>
00241 option::option(vector<string> & value, char const * name, char short_name,
00242 char const * help, char const * arg_help)
00243 : the_option(new option_imp< vector<string> >
00244 (value, name, short_name, help, arg_help))
00245 {
00246 }
00247
00248
00249 option_base::option_base(char const * name, char short_name,
00250 char const * help, char const * arg_help,
00251 void * data, unsigned int popt_flags)
00252 : option_name(name)
00253 {
00254 poptOption const opt = { name, short_name, popt_flags,
00255 data, 0, help, arg_help };
00256
00257 popt_options().push_back(opt);
00258
00259 options_list().push_back(this);
00260 }
00261
00262
00263 option_imp<void>::option_imp(bool & val, char const * name, char short_name,
00264 char const * help)
00265 : option_base(name, short_name, help, 0, &popt_value, POPT_ARG_NONE),
00266 value(val), popt_value(0)
00267 {
00268 }
00269
00270
00271 void option_imp<void>::post_process()
00272 {
00273 if (popt_value) {
00274 if (is_prefix(option_name, "no-"))
00275 value = !popt_value;
00276 else
00277 value = popt_value;
00278 }
00279 }
00280
00281
00282 option_imp<int>::option_imp(int & value, char const * name, char short_name,
00283 char const * help, char const * arg_help)
00284 : option_base(name, short_name, help, arg_help, &value, POPT_ARG_INT)
00285 {
00286 }
00287
00288
00289 option_imp<string>::option_imp(string & val, char const * name, char short_name,
00290 char const * help, char const * arg_help)
00291 : option_base(name, short_name, help, arg_help,
00292 &popt_value, POPT_ARG_STRING),
00293 popt_value(0), value(val)
00294 {
00295 }
00296
00297
00298 void option_imp<string>::post_process()
00299 {
00300 if (popt_value) {
00301 value = popt_value;
00302 popt_value = 0;
00303 }
00304 }
00305
00306
00307 option_imp< vector<string> >::option_imp(vector<string> & val,
00308 char const * name, char short_name,
00309 char const * help,
00310 char const * arg_help, char sepchar)
00311 : option_base(name, short_name, help, arg_help,
00312 &popt_value, POPT_ARG_STRING),
00313 value(val), popt_value(0), separator(sepchar)
00314 {
00315 }
00316
00317
00318 void option_imp< vector<string> >::post_process()
00319 {
00320 if (popt_value) {
00321 value = separate_token(popt_value, separator);
00322
00323 popt_value = 0;
00324 }
00325 }
00326
00327 }