From 03779406b844182392afb6956731a04d6ffbc810 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Mon, 10 Sep 2012 22:22:01 +0800 Subject: [PATCH] finish arg parsing --- src/ArgParser.cc | 31 +++++++++++++++++++++---------- src/include/ArgParser.h | 31 ++++++++++++++++++++++++------- src/pdf2htmlEX.cc | 7 +++++-- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/ArgParser.cc b/src/ArgParser.cc index 673a4a3..316c9c2 100644 --- a/src/ArgParser.cc +++ b/src/ArgParser.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include "ArgParser.h" @@ -25,6 +26,8 @@ ArgParser::~ArgParser(void) { for(auto iter = arg_entries.begin(); iter != arg_entries.end(); ++iter) delete (*iter); + for(auto iter = optional_arg_entries.begin(); iter != optional_arg_entries.end(); ++iter) + delete (*iter); } ArgParser & ArgParser::add(const char * optname, const char * description, ArgParserCallBack callback) @@ -80,19 +83,27 @@ void ArgParser::parse(int argc, char ** argv) const { r = getopt_long(argc, argv, &optstring.front(), &longopts.front(), &idx); if(r == -1) - return; - if(r == ':') + break; + assert(r != ':'); + if(r == '?') { ostringstream sout; - sout << "Missing argument for option "; - if(r < 256) - sout << "-" << (char)(opt_map[optopt]->shortname); - else - sout << "--" << opt_map[optopt]->name; - sout << endl; - throw sout.str(); + assert(optopt < 256); + throw string() + ((opt_map.find(optopt) == opt_map.end()) ? "Unknown option: -" : "Missing argument for option -") + (char)optopt; } - cerr << r << ' ' << idx << ' ' << (optarg ? optarg : "") << endl; + + auto iter = opt_map.find(r); + assert(iter != opt_map.end()); + iter->second->parse(optarg); + } + } + + { + int i = optind; + auto iter = optional_arg_entries.begin(); + while((i < argc) && (iter != optional_arg_entries.end())) + { + (*(iter++))->parse(argv[i++]); } } } diff --git a/src/include/ArgParser.h b/src/include/ArgParser.h index b4fcd6e..44424b4 100644 --- a/src/include/ArgParser.h +++ b/src/include/ArgParser.h @@ -19,7 +19,7 @@ class ArgParser public: ~ArgParser(void); - typedef void (*ArgParserCallBack) (void); + typedef void (*ArgParserCallBack) (const char * arg); /* * optname: name of the argment, should be provided as --optname @@ -44,7 +44,7 @@ private: std::string name; std::string description; bool need_arg; - virtual void parse (void) const = 0; + virtual void parse (const char * arg) const = 0; virtual void show_usage (std::ostream & out) const = 0; }; @@ -54,7 +54,7 @@ private: public: ArgEntry(const char * name, T * location, const Tv & deafult_value, ArgParserCallBack callback, const char * description); - virtual void parse (void) const; + virtual void parse (const char * arg) const; virtual void show_usage (std::ostream & out) const; private: @@ -63,14 +63,18 @@ private: ArgParserCallBack callback; }; - std::vector arg_entries; + std::vector arg_entries, optional_arg_entries; static const int arg_col_width; }; template ArgParser & ArgParser::add(const char * optname, T * location, const Tv & default_value, const char * description, ArgParserCallBack callback) { - arg_entries.push_back(new ArgEntry(optname, location, default_value, callback, description)); + // use "" in case nullptr is provided + if((!optname) || (!optname[0])) + optional_arg_entries.push_back(new ArgEntry("", location, default_value, callback, "")); + else + arg_entries.push_back(new ArgEntry(optname, location, default_value, callback, description)); return *this; } @@ -87,8 +91,21 @@ ArgParser::ArgEntry::ArgEntry(const char * name, T * location, const Tv & } template -void ArgParser::ArgEntry::parse(void) const -{ } +void ArgParser::ArgEntry::parse(const char * arg) const +{ + if(need_arg) + { + if(!arg) + throw std::string("Missing argument of option: --") + name; + + std::istringstream sin(arg); + if(!(sin >> (*location))) + throw std::string("Cannot parse argment of option: --") + name; + } + + if(callback) + (*callback)(arg); +} // helper template diff --git a/src/pdf2htmlEX.cc b/src/pdf2htmlEX.cc index e07a3d0..f76b009 100644 --- a/src/pdf2htmlEX.cc +++ b/src/pdf2htmlEX.cc @@ -31,7 +31,7 @@ using namespace std; Param param; ArgParser argparser; -void show_usage_and_exit(void) +void show_usage_and_exit(const char * dummy = nullptr) { cerr << "pdftohtmlEX version " << PDF2HTMLEX_VERSION << endl; cerr << endl; @@ -81,6 +81,8 @@ void parse_options (int argc, char **argv) .add("debug", ¶m.debug, 0, "output debug information") .add("clean-tmp", ¶m.clean_tmp, 1, "clean temporary files after processing") + .add("", ¶m.input_filename, "", "") + .add("", ¶m.output_filename, "", "") ; try @@ -100,7 +102,8 @@ int main(int argc, char **argv) parse_options(argc, argv); if (param.input_filename == "") { - show_usage_and_exit(); + cerr << "Missing input filename" << endl; + exit(EXIT_FAILURE); } //prepare the directories