diff --git a/ChangeLog b/ChangeLog index 39611945..382833cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2009-02-07 Tatsuhiro Tsujikawa + + Added OptionParser::parseArg() which internally uses getopt_long + to parse command-line options. All command-line options are now + configured by OptionHandler. No manual editing of struct option* + is required any more. + * src/NameMatchOptionHandler.h + * src/OptionHandler.h + * src/OptionHandlerFactory.cc + * src/OptionHandlerImpl.h + * src/OptionParser.cc + * src/OptionParser.h + * src/array_fun.h + * src/main.cc + * src/option_processing.cc + * test/OptionHandlerTest.cc + * test/OptionParserTest.cc + 2009-02-07 Tatsuhiro Tsujikawa Fixed configure error with --disable-epoll diff --git a/src/NameMatchOptionHandler.h b/src/NameMatchOptionHandler.h index 8ef962fa..a1024951 100644 --- a/src/NameMatchOptionHandler.h +++ b/src/NameMatchOptionHandler.h @@ -36,14 +36,17 @@ #define _D_NAME_MATCH_OPTION_HANDLER_H_ #include "OptionHandler.h" -#include "A2STR.h" -#include "Util.h" -#include "OptionHandlerException.h" + #include + #include #include #include +#include "A2STR.h" +#include "Util.h" +#include "OptionHandlerException.h" + #define NO_DESCRIPTION A2STR::NIL #define NO_DEFAULT_VALUE A2STR::NIL @@ -59,20 +62,30 @@ protected: std::string _defaultValue; - bool _hidden; - std::deque _tags; - virtual void parseArg(Option* option, const std::string& arg) = 0; + int _id; + + OptionHandler::ARG_TYPE _argType; + + char _shortName; + + bool _hidden; + + virtual void parseArg(Option& option, const std::string& arg) = 0; public: NameMatchOptionHandler(const std::string& optName, const std::string& description = NO_DESCRIPTION, const std::string& defaultValue = NO_DEFAULT_VALUE, - bool hidden = false): + ARG_TYPE argType = REQ_ARG, + char shortName = 0): _optName(optName), _description(description), _defaultValue(defaultValue), - _hidden(hidden) {} + _id(0), + _argType(argType), + _shortName(shortName), + _hidden(false) {} virtual ~NameMatchOptionHandler() {} @@ -81,7 +94,7 @@ public: return strcasecmp(_optName.c_str(), optName.c_str()) == 0; } - virtual void parse(Option* option, const std::string& arg) + virtual void parse(Option& option, const std::string& arg) { try { parseArg(option, arg); @@ -128,6 +141,30 @@ public: return _hidden; } + void hide() + { + _hidden = true; + } + + virtual char getShortName() const + { + return _shortName; + } + + virtual int getOptionID() const + { + return _id; + } + + virtual void setOptionID(int id) + { + _id = id; + } + + virtual OptionHandler::ARG_TYPE getArgType() const + { + return _argType; + } }; typedef SharedHandle NameMatchOptionHandlerHandle; diff --git a/src/OptionHandler.h b/src/OptionHandler.h index 5a5eb952..c8306488 100644 --- a/src/OptionHandler.h +++ b/src/OptionHandler.h @@ -36,11 +36,13 @@ #define _D_OPTION_HANDLER_H_ #include "common.h" -#include "SharedHandle.h" + #include #include #include +#include "SharedHandle.h" + namespace aria2 { class Option; @@ -50,7 +52,7 @@ public: virtual ~OptionHandler() {} virtual bool canHandle(const std::string& optName) = 0; - virtual void parse(Option* option, const std::string& arg) = 0; + virtual void parse(Option& option, const std::string& arg) = 0; virtual std::string createPossibleValuesString() const = 0; @@ -67,6 +69,20 @@ public: virtual const std::string& getDefaultValue() const = 0; virtual bool isHidden() const = 0; + + enum ARG_TYPE { + REQ_ARG, + OPT_ARG, + NO_ARG + }; + + virtual ARG_TYPE getArgType() const = 0; + + virtual char getShortName() const = 0; + + virtual int getOptionID() const = 0; + + virtual void setOptionID(int id) = 0; }; typedef SharedHandle OptionHandlerHandle; diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index 0b3ac849..df0df63c 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -64,19 +64,23 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#ifdef ENABLE_ASYNC_DNS { SharedHandle op(new BooleanOptionHandler (PREF_ASYNC_DNS, TEXT_ASYNC_DNS, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#endif // ENABLE_ASYNC_DNS { SharedHandle op(new BooleanOptionHandler (PREF_AUTO_FILE_RENAMING, TEXT_AUTO_FILE_RENAMING, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_ADVANCED); handlers.push_back(op); } @@ -89,16 +93,20 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#ifdef ENABLE_MESSAGE_DIGEST { SharedHandle op(new BooleanOptionHandler (PREF_CHECK_INTEGRITY, TEXT_CHECK_INTEGRITY, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG, + 'V')); op->addTag(TAG_BASIC); op->addTag(TAG_BITTORRENT); op->addTag(TAG_METALINK); handlers.push_back(op); } +#endif // ENABLE_MESSAGE_DIGEST { SharedHandle op(new DefaultOptionHandler (PREF_CONF_PATH, @@ -111,7 +119,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_CONTINUE, TEXT_CONTINUE, - V_FALSE)); // TODO ommit? + V_FALSE, // TODO ommit? + OptionHandler::NO_ARG, + 'c')); op->addTag(TAG_BASIC); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); @@ -121,7 +131,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_DAEMON, TEXT_DAEMON, - V_FALSE)); // TODO ommit? + V_FALSE, + OptionHandler::NO_ARG, + 'D')); // TODO ommit? op->addTag(TAG_ADVANCED); handlers.push_back(op); } @@ -129,32 +141,39 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new DefaultOptionHandler (PREF_DIR, TEXT_DIR, - ".")); + ".", + A2STR::NIL, + OptionHandler::REQ_ARG, + 'd')); op->addTag(TAG_BASIC); handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_DNS_TIMEOUT, - NO_DESCRIPTION, - "30", - 1, 60, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_DNS_TIMEOUT, + NO_DESCRIPTION, + "30", + 1, 60)); + op->hide(); handlers.push_back(op); } +#ifdef ENABLE_DIRECT_IO { SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_DIRECT_IO, TEXT_ENABLE_DIRECT_IO, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#endif // ENABLE_DIRECT_IO { SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_HTTP_SERVER, TEXT_ENABLE_HTTP_SERVER, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG)); op->addTag(TAG_EXPERIMENTAL); handlers.push_back(op); } @@ -183,7 +202,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_FILE_ALLOCATION, TEXT_FILE_ALLOCATION, V_PREALLOC, - V_NONE, V_PREALLOC)); + V_NONE, V_PREALLOC, + 'a')); op->addTag(TAG_BASIC); handlers.push_back(op); } @@ -191,7 +211,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_FORCE_SEQUENTIAL, TEXT_FORCE_SEQUENTIAL, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG, + 'Z')); op->addTag(TAG_BASIC); handlers.push_back(op); } @@ -209,7 +231,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_INPUT_FILE, TEXT_INPUT_FILE, NO_DEFAULT_VALUE, - "FILENAME,-")); + "FILENAME,-", + OptionHandler::REQ_ARG, + 'i')); op->addTag(TAG_BASIC); handlers.push_back(op); } @@ -218,7 +242,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_LOG, TEXT_LOG, NO_DEFAULT_VALUE, - "FILENAME,-")); + "FILENAME,-", + OptionHandler::REQ_ARG, + 'l')); op->addTag(TAG_BASIC); handlers.push_back(op); } @@ -239,7 +265,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_MAX_CONCURRENT_DOWNLOADS, TEXT_MAX_CONCURRENT_DOWNLOADS, "5", - 1, 45)); + 1, 45, + 'j')); op->addTag(TAG_BASIC); handlers.push_back(op); } @@ -258,7 +285,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_NO_CONF, TEXT_NO_CONF, - V_FALSE)); + V_FALSE, + OptionHandler::NO_ARG)); op->addTag(TAG_ADVANCED); handlers.push_back(op); } @@ -275,7 +303,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_PARAMETERIZED_URI, TEXT_PARAMETERIZED_URI, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG, + 'P')); op->addTag(TAG_ADVANCED); handlers.push_back(op); } @@ -283,10 +313,13 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_QUIET, TEXT_QUIET, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG, + 'q')); op->addTag(TAG_ADVANCED); handlers.push_back(op); } +#ifdef ENABLE_MESSAGE_DIGEST { SharedHandle op(new BooleanOptionHandler (PREF_REALTIME_CHUNK_CHECKSUM, @@ -295,6 +328,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_METALINK); handlers.push_back(op); } +#endif // ENABLE_MESSAGE_DIGEST { SharedHandle op(new NumberOptionHandler (PREF_STOP, @@ -349,7 +383,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_MAX_TRIES, TEXT_MAX_TRIES, "5", - 0)); + 0, -1, + 'm')); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); handlers.push_back(op); @@ -359,7 +394,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_OUT, TEXT_OUT, NO_DEFAULT_VALUE, - "FILENAME")); + "FILENAME", + OptionHandler::REQ_ARG, + 'o')); op->addTag(TAG_BASIC); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); @@ -369,7 +406,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_REMOTE_TIME, TEXT_REMOTE_TIME, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG, + 'R')); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); handlers.push_back(op); @@ -385,12 +424,12 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new UnitNumberOptionHandler - (PREF_SEGMENT_SIZE, - NO_DESCRIPTION, - "1M", - 1024, -1, - true)); + SharedHandle op(new UnitNumberOptionHandler + (PREF_SEGMENT_SIZE, + NO_DESCRIPTION, + "1M", + 1024, -1)); + op->hide(); handlers.push_back(op); } { @@ -428,19 +467,20 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_SPLIT, TEXT_SPLIT, "5", - 1)); + 1, -1, + 's')); op->addTag(TAG_BASIC); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_STARTUP_IDLE_TIME, - NO_DESCRIPTION, - "10", - 1, 60, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_STARTUP_IDLE_TIME, + NO_DESCRIPTION, + "10", + 1, 60)); + op->hide(); handlers.push_back(op); } { @@ -448,7 +488,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_TIMEOUT, TEXT_TIMEOUT, "60", - 1, 600)); + 1, 600, + 't')); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); handlers.push_back(op); @@ -487,7 +528,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_CHECK_CERTIFICATE, TEXT_CHECK_CERTIFICATE, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_HTTP); op->addTag(TAG_HTTPS); handlers.push_back(op); @@ -496,7 +538,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_HTTP_KEEP_ALIVE, TEXT_ENABLE_HTTP_KEEP_ALIVE, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_HTTP); handlers.push_back(op); } @@ -504,7 +547,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_HTTP_PIPELINING, TEXT_ENABLE_HTTP_PIPELINING, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG)); op->addTag(TAG_HTTP); handlers.push_back(op); } @@ -553,12 +597,12 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_MAX_HTTP_PIPELINING, - NO_DESCRIPTION, - "2", - 1, 8, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_MAX_HTTP_PIPELINING, + NO_DESCRIPTION, + "2", + 1, 8)); + op->hide(); handlers.push_back(op); } { @@ -577,10 +621,11 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new DefaultOptionHandler + SharedHandle op(new BooleanOptionHandler (PREF_USE_HEAD, TEXT_USE_HEAD, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_HTTP); handlers.push_back(op); } @@ -588,7 +633,10 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new DefaultOptionHandler (PREF_USER_AGENT, TEXT_USER_AGENT, - "aria2")); + "aria2", + A2STR::NIL, + OptionHandler::REQ_ARG, + 'U')); op->addTag(TAG_HTTP); handlers.push_back(op); } @@ -605,7 +653,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_FTP_PASV, TEXT_FTP_PASV, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG, + 'p')); op->addTag(TAG_FTP); handlers.push_back(op); } @@ -613,7 +663,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_FTP_REUSE_CONNECTION, TEXT_FTP_REUSE_CONNECTION, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_FTP); handlers.push_back(op); } @@ -635,19 +686,21 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new DefaultOptionHandler - (PREF_NETRC_PATH, - NO_DESCRIPTION, - Util::getHomeDir()+"/.netrc", - "/PATH/TO/NETRC", - true)); + SharedHandle op(new DefaultOptionHandler + (PREF_NETRC_PATH, + NO_DESCRIPTION, + Util::getHomeDir()+"/.netrc", + "/PATH/TO/NETRC")); + op->hide(); handlers.push_back(op); } { SharedHandle op(new BooleanOptionHandler (PREF_NO_NETRC, TEXT_NO_NETRC, - V_FALSE)); // TODO ommit? + V_FALSE, // TODO ommit? + OptionHandler::NO_ARG, + 'n')); op->addTag(TAG_FTP); op->addTag(TAG_HTTP); handlers.push_back(op); @@ -705,6 +758,7 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } // BitTorrent/Metalink Options +#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK { SharedHandle op(new IntegerRangeOptionHandler (PREF_SELECT_FILE, @@ -719,13 +773,17 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_SHOW_FILES, TEXT_SHOW_FILES, - V_FALSE)); // TODO ommit? + V_FALSE, // TODO ommit? + OptionHandler::NO_ARG, + 'S')); op->addTag(TAG_BASIC); op->addTag(TAG_BITTORRENT); op->addTag(TAG_METALINK); handlers.push_back(op); } +#endif // ENABLE_BITTORRENT || ENABLE_METALINK // BitTorrent Specific Options +#ifdef ENABLE_BITTORRENT { SharedHandle op(new DefaultOptionHandler (PREF_BT_EXTERNAL_IP, @@ -736,19 +794,20 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_BT_KEEP_ALIVE_INTERVAL, - NO_DESCRIPTION, - "120", - 1, 120, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_BT_KEEP_ALIVE_INTERVAL, + NO_DESCRIPTION, + "120", + 1, 120)); + op->hide(); handlers.push_back(op); } { SharedHandle op(new BooleanOptionHandler (PREF_BT_HASH_CHECK_SEED, TEXT_BT_HASH_CHECK_SEED, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_BITTORRENT); handlers.push_back(op); } @@ -798,29 +857,30 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_BT_REQUEST_TIMEOUT, - NO_DESCRIPTION, - "60", - 1, 600, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_BT_REQUEST_TIMEOUT, + NO_DESCRIPTION, + "60", + 1, 600)); + op->hide(); handlers.push_back(op); } { SharedHandle op(new BooleanOptionHandler (PREF_BT_SEED_UNVERIFIED, TEXT_BT_SEED_UNVERIFIED, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG)); op->addTag(TAG_BITTORRENT); handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_BT_TIMEOUT, - NO_DESCRIPTION, - "180", - 1, 600, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_BT_TIMEOUT, + NO_DESCRIPTION, + "180", + 1, 600)); + op->hide(); handlers.push_back(op); } { @@ -864,7 +924,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_DHT, TEXT_ENABLE_DHT, - V_FALSE)); + V_FALSE, + OptionHandler::OPT_ARG)); op->addTag(TAG_BASIC); op->addTag(TAG_BITTORRENT); handlers.push_back(op); @@ -873,7 +934,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_ENABLE_PEER_EXCHANGE, TEXT_ENABLE_PEER_EXCHANGE, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_BITTORRENT); handlers.push_back(op); } @@ -911,18 +973,19 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_MAX_UPLOAD_LIMIT, TEXT_MAX_UPLOAD_LIMIT, "0", - 0)); + 0, -1, + 'u')); op->addTag(TAG_BASIC); op->addTag(TAG_BITTORRENT); handlers.push_back(op); } { - SharedHandle op(new NumberOptionHandler - (PREF_PEER_CONNECTION_TIMEOUT, - NO_DESCRIPTION, - "20", - 1, 600, - true)); + SharedHandle op(new NumberOptionHandler + (PREF_PEER_CONNECTION_TIMEOUT, + NO_DESCRIPTION, + "20", + 1, 600)); + op->hide(); handlers.push_back(op); } { @@ -954,12 +1017,18 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() { SharedHandle op(new DefaultOptionHandler (PREF_TORRENT_FILE, - TEXT_TORRENT_FILE)); + TEXT_TORRENT_FILE, + NO_DEFAULT_VALUE, + A2STR::NIL, + OptionHandler::REQ_ARG, + 'T')); op->addTag(TAG_BASIC); op->addTag(TAG_BITTORRENT); handlers.push_back(op); } +#endif // ENABLE_BITTORRENT // Metalink Specific Options +#ifdef ENABLE_METALINK { SharedHandle op(new ParameterOptionHandler (PREF_FOLLOW_METALINK, @@ -973,14 +1042,19 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() SharedHandle op(new BooleanOptionHandler (PREF_METALINK_ENABLE_UNIQUE_PROTOCOL, TEXT_METALINK_ENABLE_UNIQUE_PROTOCOL, - V_TRUE)); + V_TRUE, + OptionHandler::OPT_ARG)); op->addTag(TAG_METALINK); handlers.push_back(op); } { SharedHandle op(new DefaultOptionHandler (PREF_METALINK_FILE, - TEXT_METALINK_FILE)); + TEXT_METALINK_FILE, + NO_DEFAULT_VALUE, + A2STR::NIL, + OptionHandler::REQ_ARG, + 'M')); op->addTag(TAG_BASIC); op->addTag(TAG_METALINK); handlers.push_back(op); @@ -1022,7 +1096,8 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() (PREF_METALINK_SERVERS, TEXT_METALINK_SERVERS, "5", - 1)); + 1, -1, + 'C')); op->addTag(TAG_METALINK); handlers.push_back(op); } @@ -1033,6 +1108,19 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_METALINK); handlers.push_back(op); } +#endif // ENABLE_METALINK + // Version Option + { + SharedHandle op(new DefaultOptionHandler + ("version", + TEXT_VERSION, + NO_DEFAULT_VALUE, + A2STR::NIL, + OptionHandler::NO_ARG, + 'v')); + op->addTag(TAG_BASIC); + handlers.push_back(op); + } // Help Option { SharedHandle op(new DefaultOptionHandler @@ -1048,7 +1136,9 @@ OptionHandlers OptionHandlerFactory::createOptionHandlers() TAG_METALINK, TAG_BITTORRENT, TAG_EXPERIMENTAL, - TAG_HELP).str())); + TAG_HELP).str(), + OptionHandler::OPT_ARG, + 'h')); op->addTag(TAG_BASIC); op->addTag(TAG_HELP); handlers.push_back(op); diff --git a/src/OptionHandlerImpl.h b/src/OptionHandlerImpl.h index b9160115..5d3b00d8 100644 --- a/src/OptionHandlerImpl.h +++ b/src/OptionHandlerImpl.h @@ -56,12 +56,14 @@ namespace aria2 { class NullOptionHandler : public OptionHandler { +private: + int _id; public: virtual ~NullOptionHandler() {} virtual bool canHandle(const std::string& optName) { return true; } - virtual void parse(Option* option, const std::string& arg) {} + virtual void parse(Option& option, const std::string& arg) {} virtual bool hasTag(const std::string& tag) const { return false; } @@ -78,23 +80,47 @@ public: virtual std::string createPossibleValuesString() const { return A2STR::NIL; } virtual bool isHidden() const { return true; } + + virtual OptionHandler::ARG_TYPE getArgType() const + { + return OptionHandler::NO_ARG; + } + + virtual int getOptionID() const + { + return _id; + } + + virtual void setOptionID(int id) + { + _id = id; + } + + virtual char getShortName() const + { + return 0; + } }; class BooleanOptionHandler : public NameMatchOptionHandler { public: BooleanOptionHandler(const std::string& optName, const std::string& description = NO_DESCRIPTION, - const std::string& defaultValue = NO_DEFAULT_VALUE): - NameMatchOptionHandler(optName, description, defaultValue) {} + const std::string& defaultValue = NO_DEFAULT_VALUE, + OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + argType, shortName) {} virtual ~BooleanOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { - if(optarg == "true") { - option->put(_optName, V_TRUE); + if(optarg == "true" || + (_argType == OptionHandler::OPT_ARG && optarg.empty())) { + option.put(_optName, V_TRUE); } else if(optarg == "false") { - option->put(_optName, V_FALSE); + option.put(_optName, V_FALSE); } else { std::string msg = _optName+" "+_("must be either 'true' or 'false'."); throw FatalException(msg); @@ -115,13 +141,15 @@ public: IntegerRangeOptionHandler(const std::string& optName, const std::string& description, const std::string& defaultValue, - int32_t min, int32_t max): - NameMatchOptionHandler(optName, description, defaultValue), + int32_t min, int32_t max, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName), _min(min), _max(max) {} virtual ~IntegerRangeOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { IntSequence seq = Util::parseIntRange(optarg); while(seq.hasNext()) { @@ -132,7 +160,7 @@ public: (StringFormat(msg.c_str(), Util::itos(_min).c_str(), Util::itos(_max).c_str()).str()); } - option->put(_optName, optarg); + option.put(_optName, optarg); } } @@ -152,22 +180,23 @@ public: const std::string& defaultValue = NO_DEFAULT_VALUE, int64_t min = -1, int64_t max = -1, - bool hidden = false): - NameMatchOptionHandler(optName, description, defaultValue, hidden), + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName), _min(min), _max(max) {} virtual ~NumberOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { int64_t num = Util::parseLLInt(optarg); parseArg(option, num); } - void parseArg(Option* option, int64_t number) + void parseArg(Option& option, int64_t number) { if((_min == -1 || _min <= number) && (_max == -1 || number <= _max)) { - option->put(_optName, Util::itos(number)); + option.put(_optName, Util::itos(number)); } else { std::string msg = _optName+" "; if(_min == -1 && _max != -1) { @@ -200,12 +229,13 @@ public: const std::string& defaultValue = NO_DEFAULT_VALUE, int64_t min = -1, int64_t max = -1, - bool hidden = false): - NumberOptionHandler(optName, description, defaultValue, min, max, hidden) {} + char shortName = 0): + NumberOptionHandler(optName, description, defaultValue, min, max, + shortName) {} virtual ~UnitNumberOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { int64_t num = Util::getRealSize(optarg); NumberOptionHandler::parseArg(option, num); @@ -220,17 +250,19 @@ public: FloatNumberOptionHandler(const std::string& optName, const std::string& description = NO_DESCRIPTION, const std::string& defaultValue = NO_DEFAULT_VALUE, - double min = -1, double max = -1): - NameMatchOptionHandler(optName, description, defaultValue), + double min = -1, double max = -1, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName), _min(min), _max(max) {} virtual ~FloatNumberOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { double number = strtod(optarg.c_str(), 0); if((_min < 0 || _min <= number) && (_max < 0 || number <= _max)) { - option->put(_optName, optarg); + option.put(_optName, optarg); } else { std::string msg = _optName+" "; if(_min < 0 && _max >= 0) { @@ -279,15 +311,17 @@ public: const std::string& description = NO_DESCRIPTION, const std::string& defaultValue = NO_DEFAULT_VALUE, const std::string& possibleValuesString = A2STR::NIL, - bool hidden = false): - NameMatchOptionHandler(optName, description, defaultValue, hidden), + OptionHandler::ARG_TYPE argType = OptionHandler::REQ_ARG, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, argType, + shortName), _possibleValuesString(possibleValuesString) {} virtual ~DefaultOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { - option->put(_optName, optarg); + option.put(_optName, optarg); } virtual std::string createPossibleValuesString() const @@ -306,18 +340,22 @@ public: const std::string& description, const std::string& defaultValue, const std::string& delim, - const std::string& possibleValuesString = A2STR::NIL): - NameMatchOptionHandler(optName, description, defaultValue), + const std::string& possibleValuesString = A2STR::NIL, + OptionHandler::ARG_TYPE argType = + OptionHandler::REQ_ARG, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, argType, + shortName), _delim(delim), _possibleValuesString(possibleValuesString) {} virtual ~CumulativeOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { - std::string value = option->get(_optName); + std::string value = option.get(_optName); value += optarg+_delim; - option->put(_optName, value); + option.put(_optName, value); } virtual std::string createPossibleValuesString() const @@ -333,15 +371,19 @@ public: ParameterOptionHandler(const std::string& optName, const std::string& description, const std::string& defaultValue, - const std::deque& validParamValues): - NameMatchOptionHandler(optName, description, defaultValue), + const std::deque& validParamValues, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName), _validParamValues(validParamValues) {} ParameterOptionHandler(const std::string& optName, const std::string& description, const std::string& defaultValue, - const std::string& validParamValue): - NameMatchOptionHandler(optName, description, defaultValue) + const std::string& validParamValue, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName) { _validParamValues.push_back(validParamValue); } @@ -350,8 +392,10 @@ public: const std::string& description, const std::string& defaultValue, const std::string& validParamValue1, - const std::string& validParamValue2): - NameMatchOptionHandler(optName, description, defaultValue) + const std::string& validParamValue2, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName) { _validParamValues.push_back(validParamValue1); _validParamValues.push_back(validParamValue2); @@ -362,8 +406,10 @@ public: const std::string& defaultValue, const std::string& validParamValue1, const std::string& validParamValue2, - const std::string& validParamValue3): - NameMatchOptionHandler(optName, description, defaultValue) + const std::string& validParamValue3, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName) { _validParamValues.push_back(validParamValue1); _validParamValues.push_back(validParamValue2); @@ -372,7 +418,7 @@ public: virtual ~ParameterOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { std::deque::const_iterator itr = std::find(_validParamValues.begin(), _validParamValues.end(), optarg); @@ -388,7 +434,7 @@ public: } throw FatalException(msg); } else { - option->put(_optName, optarg); + option.put(_optName, optarg); } } @@ -411,14 +457,16 @@ public: const std::string& description, const std::string& defaultValue, const std::string& hostOptionName, - const std::string& portOptionName): - NameMatchOptionHandler(optName, description, defaultValue), + const std::string& portOptionName, + char shortName = 0): + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName), _hostOptionName(hostOptionName), _portOptionName(portOptionName) {} virtual ~HostPortOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { std::pair proxy = Util::split(optarg, ":"); int32_t port = Util::parseInt(proxy.second); @@ -426,14 +474,14 @@ public: port <= 0 || 65535 < port) { throw FatalException(_("unrecognized proxy format")); } - option->put(_optName, optarg); + option.put(_optName, optarg); setHostAndPort(option, proxy.first, port); } - void setHostAndPort(Option* option, const std::string& hostname, uint16_t port) + void setHostAndPort(Option& option, const std::string& hostname, uint16_t port) { - option->put(_hostOptionName, hostname); - option->put(_portOptionName, Util::uitos(port)); + option.put(_hostOptionName, hostname); + option.put(_portOptionName, Util::uitos(port)); } virtual std::string createPossibleValuesString() const @@ -446,14 +494,16 @@ class HttpProxyOptionHandler : public NameMatchOptionHandler { public: HttpProxyOptionHandler(const std::string& optName, const std::string& description, - const std::string& defaultValue) + const std::string& defaultValue, + char shortName = 0) : - NameMatchOptionHandler(optName, description, defaultValue) + NameMatchOptionHandler(optName, description, defaultValue, + OptionHandler::REQ_ARG, shortName) {} virtual ~HttpProxyOptionHandler() {} - virtual void parseArg(Option* option, const std::string& optarg) + virtual void parseArg(Option& option, const std::string& optarg) { Request req; std::string url; @@ -463,7 +513,7 @@ public: url = "http://"+optarg; } if(req.setUrl(url)) { - option->put(_optName, url); + option.put(_optName, url); } else { throw FatalException(_("unrecognized proxy format")); } diff --git a/src/OptionParser.cc b/src/OptionParser.cc index a2db7b06..c2ef8333 100644 --- a/src/OptionParser.cc +++ b/src/OptionParser.cc @@ -33,17 +33,126 @@ */ /* copyright --> */ #include "OptionParser.h" + +#include +#include + +#include +#include +#include + #include "Util.h" #include "OptionHandlerImpl.h" #include "Option.h" #include "A2STR.h" #include "a2functional.h" -#include -#include +#include "array_fun.h" namespace aria2 { -void OptionParser::parse(Option* option, std::istream& is) +OptionParser::OptionParser():_idCounter(0) {} + +template +static size_t countPublicOption(InputIterator first, InputIterator last) +{ + size_t count = 0; + for(; first != last; ++first) { + if(!(*first)->isHidden()) { + ++count; + } + } + return count; +} + +template +static void putOptions(struct option* longOpts, int* plopt, + InputIterator first, InputIterator last) +{ + for(; first != last; ++first) { + if(!(*first)->isHidden()) { + (*longOpts).name = (*first)->getName().c_str(); + switch((*first)->getArgType()) { + case OptionHandler::REQ_ARG: + (*longOpts).has_arg = required_argument; + break; + case OptionHandler::OPT_ARG: + (*longOpts).has_arg = optional_argument; + break; + case OptionHandler::NO_ARG: + (*longOpts).has_arg = no_argument; + break; + default: + abort(); + } + if((*first)->getShortName() == 0) { + (*longOpts).flag = plopt; + (*longOpts).val = (*first)->getOptionID(); + } else { + (*longOpts).flag = 0; + (*longOpts).val = (*first)->getShortName(); + } + ++longOpts; + } + } + (*longOpts).name = 0; + (*longOpts).has_arg = 0; + (*longOpts).flag = 0; + (*longOpts).val = 0; +} + +template +static std::string createOptstring(InputIterator first, InputIterator last) +{ + std::string str = ""; + for(; first != last; ++first) { + if(!(*first)->isHidden()) { + if((*first)->getShortName() != 0) { + str += (*first)->getShortName(); + if((*first)->getArgType() == OptionHandler::REQ_ARG) { + str += ":"; + } else if((*first)->getArgType() == OptionHandler::OPT_ARG) { + str += "::"; + } + } + } + } + return str; +} + +void OptionParser::parseArg +(std::ostream& out, std::deque& nonopts, int argc, char* const argv[]) +{ + size_t numPublicOption = countPublicOption(_optionHandlers.begin(), + _optionHandlers.end()); + int lopt; + array_ptr longOpts(new struct option[numPublicOption+1]); + putOptions(&longOpts[0], &lopt,_optionHandlers.begin(),_optionHandlers.end()); + std::string optstring = createOptstring(_optionHandlers.begin(), + _optionHandlers.end()); + while(1) { + int c = getopt_long(argc, argv, optstring.c_str(), &longOpts[0], 0); + if(c == -1) { + break; + } + SharedHandle op; + if(c == 0) { + op = findByID(lopt); + } else { + op = findByShortName(c); + } + if(op.isNull()) { + throw FatalException("Unknown option"); + } + out << op->getName() << "="; + if(optarg) { + out << optarg; + } + out << "\n"; + } + std::copy(argv+optind, argv+argc, std::back_inserter(nonopts)); +} + +void OptionParser::parse(Option& option, std::istream& is) { std::string line; int32_t linenum = 0; @@ -72,15 +181,20 @@ OptionHandlerHandle OptionParser::getOptionHandlerByName(const std::string& optN void OptionParser::setOptionHandlers(const std::deque >& optionHandlers) { _optionHandlers = optionHandlers; + for(std::deque >::iterator i = + _optionHandlers.begin(); i != _optionHandlers.end(); ++i) { + (*i)->setOptionID(++_idCounter); + } } void OptionParser::addOptionHandler (const SharedHandle& optionHandler) { + optionHandler->setOptionID(++_idCounter); _optionHandlers.push_back(optionHandler); } -void OptionParser::parseDefaultValues(Option* option) const +void OptionParser::parseDefaultValues(Option& option) const { for(std::deque >::const_iterator i = _optionHandlers.begin(); i != _optionHandlers.end(); ++i) { @@ -137,6 +251,27 @@ OptionParser::findByNameSubstring(const std::string& substring) const return result; } +std::deque > OptionParser::findAll() const +{ + std::deque > result; + std::remove_copy_if(_optionHandlers.begin(), _optionHandlers.end(), + std::back_inserter(result), + mem_fun_sh(&OptionHandler::isHidden)); + return result; +} + +template +static SharedHandle findOptionHandler +(InputIterator first, InputIterator last, Predicate pred) +{ + InputIterator i = std::find_if(first, last, pred); + if(i == last) { + return SharedHandle(); + } else { + return *i; + } +} + class FindByName : public std::unary_function , bool> { private: @@ -150,28 +285,52 @@ public: } }; -std::deque > OptionParser::findAll() const -{ - std::deque > result; - std::remove_copy_if(_optionHandlers.begin(), _optionHandlers.end(), - std::back_inserter(result), - mem_fun_sh(&OptionHandler::isHidden)); - return result; -} - SharedHandle OptionParser::findByName(const std::string& name) const { - std::deque >::const_iterator i = - std::find_if(_optionHandlers.begin(), _optionHandlers.end(), - FindByName(name)); - if(i == _optionHandlers.end()) { - return SharedHandle(); - } else { - return *i; - } + return findOptionHandler(_optionHandlers.begin(), _optionHandlers.end(), + FindByName(name)); } +class FindByID:public std::unary_function, bool> { +private: + int _id; +public: + FindByID(int id):_id(id) {} + + bool operator()(const SharedHandle& optionHandler) const + { + return !optionHandler->isHidden() && optionHandler->getOptionID() == _id; + } +}; + +SharedHandle OptionParser::findByID(int id) const +{ + return findOptionHandler(_optionHandlers.begin(), _optionHandlers.end(), + FindByID(id)); +} + +class FindByShortName: + public std::unary_function, bool> { +private: + char _shortName; +public: + FindByShortName(char shortName):_shortName(shortName) {} + + bool operator()(const SharedHandle& optionHandler) const + { + return !optionHandler->isHidden() && + optionHandler->getShortName() == _shortName; + } +}; + +SharedHandle OptionParser::findByShortName(char shortName) const +{ + return findOptionHandler(_optionHandlers.begin(), _optionHandlers.end(), + FindByShortName(shortName)); +} + + const std::deque >& OptionParser::getOptionHandlers() const { diff --git a/src/OptionParser.h b/src/OptionParser.h index fc5fce9c..b02f46c1 100644 --- a/src/OptionParser.h +++ b/src/OptionParser.h @@ -36,11 +36,13 @@ #define _D_OPTION_PARSER_H_ #include "common.h" -#include "SharedHandle.h" + #include #include #include +#include "SharedHandle.h" + namespace aria2 { class Option; @@ -48,16 +50,26 @@ class OptionHandler; class OptionParser { private: + int _idCounter; + std::deque > _optionHandlers; SharedHandle getOptionHandlerByName(const std::string& optName); public: + OptionParser(); + ~OptionParser() {} - void parse(Option* option, std::istream& ios); + // Parses options in argv and writes option name and value to out in + // NAME=VALUE format. Non-option strings are stored in nonopts. + // Throws FatalException when an unrecognized option is found. + void parseArg(std::ostream& out, std::deque& nonopts, + int argc, char* const argv[]); - void parseDefaultValues(Option* option) const; + void parse(Option& option, std::istream& ios); + + void parseDefaultValues(Option& option) const; void setOptionHandlers (const std::deque >& optionHandlers); @@ -75,6 +87,10 @@ public: SharedHandle findByName(const std::string& name) const; + SharedHandle findByID(int id) const; + + SharedHandle findByShortName(char shortName) const; + const std::deque >& getOptionHandlers() const; }; diff --git a/src/array_fun.h b/src/array_fun.h index ccf837a0..0c2327f4 100644 --- a/src/array_fun.h +++ b/src/array_fun.h @@ -215,6 +215,43 @@ size_t arrayLength(T (&a)[0u]) return 0; } +template +class array_ptr { +private: + T* _array; + + // Copies are not allowed. Let's make them private. + array_ptr(const array_ptr& s); + + template + array_ptr(const array_ptr& s); + + array_ptr& operator=(const array_ptr& s); + + template + array_ptr& operator=(const array_ptr& s); + +public: + array_ptr():_array(0) {} + + explicit array_ptr(T* array):_array(array) {} + + ~array_ptr() + { + delete [] _array; + } + + T& operator[](size_t index) + { + return _array[index]; + } + + const T& operator[](size_t index) const + { + return _array[index]; + } +}; + } // namespace aria2 #endif // _D_ARRAY_FUN_H_ diff --git a/src/main.cc b/src/main.cc index 2ca2479d..aea7bcc2 100644 --- a/src/main.cc +++ b/src/main.cc @@ -157,32 +157,34 @@ static void showFiles(const std::deque& uris, const Option* op) } #endif // ENABLE_BITTORRENT || ENABLE_METALINK -extern Option* option_processing(int argc, char* const argv[]); +extern void option_processing(Option& option, std::deque& uris, + int argc, char* const argv[]); DownloadResult::RESULT main(int argc, char* argv[]) { - Option* op = option_processing(argc, argv); - std::deque args(argv+optind, argv+argc); + std::deque args; + Option op; + option_processing(op, args, argc, argv); SimpleRandomizer::init(); BitfieldManFactory::setDefaultRandomizer(SimpleRandomizer::getInstance()); - if(op->get(PREF_LOG) == "-") { + if(op.get(PREF_LOG) == "-") { LogFactory::setLogFile(DEV_STDOUT); - } else if(!op->get(PREF_LOG).empty()) { - LogFactory::setLogFile(op->get(PREF_LOG)); + } else if(!op.get(PREF_LOG).empty()) { + LogFactory::setLogFile(op.get(PREF_LOG)); } else { LogFactory::setLogFile(DEV_NULL); } - LogFactory::setLogLevel(op->get(PREF_LOG_LEVEL)); - if(op->getAsBool(PREF_QUIET)) { + LogFactory::setLogLevel(op.get(PREF_LOG_LEVEL)); + if(op.getAsBool(PREF_QUIET)) { LogFactory::setConsoleOutput(false); } #ifdef HAVE_EPOLL - if(op->get(PREF_EVENT_POLL) == V_EPOLL) { + if(op.get(PREF_EVENT_POLL) == V_EPOLL) { SocketCore::useEpoll(); } else #endif // HAVE_EPOLL - if(op->get(PREF_EVENT_POLL) == V_SELECT) { + if(op.get(PREF_EVENT_POLL) == V_SELECT) { SocketCore::useSelect(); } DownloadResult::RESULT exitStatus = DownloadResult::FINISHED; @@ -203,48 +205,47 @@ DownloadResult::RESULT main(int argc, char* argv[]) #endif std::deque > requestGroups; #ifdef ENABLE_BITTORRENT - if(!op->blank(PREF_TORRENT_FILE)) { - if(op->get(PREF_SHOW_FILES) == V_TRUE) { - showTorrentFile(op->get(PREF_TORRENT_FILE)); + if(!op.blank(PREF_TORRENT_FILE)) { + if(op.get(PREF_SHOW_FILES) == V_TRUE) { + showTorrentFile(op.get(PREF_TORRENT_FILE)); return exitStatus; } else { - createRequestGroupForBitTorrent(requestGroups, op, args); + createRequestGroupForBitTorrent(requestGroups, &op, args); } } else #endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK - if(!op->blank(PREF_METALINK_FILE)) { - if(op->get(PREF_SHOW_FILES) == V_TRUE) { - showMetalinkFile(op->get(PREF_METALINK_FILE), op); + if(!op.blank(PREF_METALINK_FILE)) { + if(op.get(PREF_SHOW_FILES) == V_TRUE) { + showMetalinkFile(op.get(PREF_METALINK_FILE), &op); return exitStatus; } else { - createRequestGroupForMetalink(requestGroups, op); + createRequestGroupForMetalink(requestGroups, &op); } } else #endif // ENABLE_METALINK - if(!op->blank(PREF_INPUT_FILE)) { - createRequestGroupForUriList(requestGroups, op); + if(!op.blank(PREF_INPUT_FILE)) { + createRequestGroupForUriList(requestGroups, &op); #if defined ENABLE_BITTORRENT || defined ENABLE_METALINK - } else if(op->get(PREF_SHOW_FILES) == V_TRUE) { - showFiles(args, op); + } else if(op.get(PREF_SHOW_FILES) == V_TRUE) { + showFiles(args, &op); #endif // ENABLE_METALINK || ENABLE_METALINK } else { - createRequestGroupForUri(requestGroups, op, args); + createRequestGroupForUri(requestGroups, &op, args); } if(requestGroups.empty()) { std::cout << MSG_NO_FILES_TO_DOWNLOAD << std::endl; } else { - exitStatus = MultiUrlRequestInfo(requestGroups, op, getStatCalc(op), - getSummaryOut(op)).execute(); + exitStatus = MultiUrlRequestInfo(requestGroups, &op, getStatCalc(&op), + getSummaryOut(&op)).execute(); } } catch(Exception& ex) { std::cerr << EX_EXCEPTION_CAUGHT << "\n" << ex.stackTrace() << std::endl; exitStatus = DownloadResult::UNKNOWN_ERROR; } - delete op; LogFactory::release(); return exitStatus; } diff --git a/src/option_processing.cc b/src/option_processing.cc index 81e72096..681c531f 100644 --- a/src/option_processing.cc +++ b/src/option_processing.cc @@ -55,27 +55,12 @@ #include "OptionHandlerException.h" #include "DownloadResult.h" -extern char* optarg; -extern int optind, opterr, optopt; -#include - namespace aria2 { extern void showVersion(); extern void showUsage(const std::string& keyword, const OptionParser& oparser); -static std::string toBoolArg(const char* optarg) -{ - std::string arg; - if(!optarg || strlen(optarg) == 0) { - arg = V_TRUE; - } else { - arg = optarg; - } - return arg; -} - -static void overrideWithEnv(Option* op, const OptionParser& optionParser, +static void overrideWithEnv(Option& op, const OptionParser& optionParser, const std::string& pref, const std::string& envName) { @@ -92,501 +77,33 @@ static void overrideWithEnv(Option* op, const OptionParser& optionParser, } } -Option* option_processing(int argc, char* const argv[]) +void option_processing(Option& op, std::deque& uris, + int argc, char* const argv[]) { - std::stringstream cmdstream; - int32_t c; - Option* op = new Option(); - - // following options are not parsed by OptionHandler and not stored in Option. - bool noConf = false; - std::string ucfname; - OptionParser oparser; oparser.setOptionHandlers(OptionHandlerFactory::createOptionHandlers()); try { - oparser.parseDefaultValues(op); - } catch(Exception& e) { - std::cerr << e.stackTrace(); - exit(DownloadResult::UNKNOWN_ERROR); - } + bool noConf = false; + std::string ucfname; + std::stringstream cmdstream; + oparser.parseArg(cmdstream, uris, argc, argv); + { + // first evaluate --no-conf and --conf-path options. + Option op; + oparser.parse(op, cmdstream); + noConf = op.getAsBool(PREF_NO_CONF); + ucfname = op.get(PREF_CONF_PATH); - while(1) { - int optIndex = 0; - int lopt; - static struct option longOpts[] = { -#ifdef HAVE_DAEMON - { PREF_DAEMON.c_str(), no_argument, NULL, 'D' }, -#endif // HAVE_DAEMON - { PREF_DIR.c_str(), required_argument, NULL, 'd' }, - { PREF_OUT.c_str(), required_argument, NULL, 'o' }, - { PREF_LOG.c_str(), required_argument, NULL, 'l' }, - { PREF_SPLIT.c_str(), required_argument, NULL, 's' }, - { PREF_TIMEOUT.c_str(), required_argument, NULL, 't' }, - { PREF_MAX_TRIES.c_str(), required_argument, NULL, 'm' }, - { PREF_HTTP_PROXY.c_str(), required_argument, &lopt, 1 }, - { PREF_HTTP_USER.c_str(), required_argument, &lopt, 2 }, - { PREF_HTTP_PASSWD.c_str(), required_argument, &lopt, 3 }, - { "http-proxy-user", required_argument, &lopt, 4 }, - { "http-proxy-passwd", required_argument, &lopt, 5 }, - { PREF_HTTP_AUTH_SCHEME.c_str(), required_argument, &lopt, 6 }, - { PREF_REFERER.c_str(), required_argument, &lopt, 7 }, - { PREF_RETRY_WAIT.c_str(), required_argument, &lopt, 8 }, - { PREF_FTP_USER.c_str(), required_argument, &lopt, 9 }, - { PREF_FTP_PASSWD.c_str(), required_argument, &lopt, 10 }, - { PREF_FTP_TYPE.c_str(), required_argument, &lopt, 11 }, - { PREF_FTP_PASV.c_str(), optional_argument, 0, 'p' }, - { "ftp-via-http-proxy", required_argument, &lopt, 12 }, - { "http-proxy-method", required_argument, &lopt, 14 }, - { PREF_LOWEST_SPEED_LIMIT.c_str(), required_argument, &lopt, 200 }, - { PREF_MAX_DOWNLOAD_LIMIT.c_str(), required_argument, &lopt, 201 }, - { PREF_FILE_ALLOCATION.c_str(), required_argument, 0, 'a' }, - { PREF_ALLOW_OVERWRITE.c_str(), required_argument, &lopt, 202 }, -#ifdef ENABLE_MESSAGE_DIGEST - { PREF_CHECK_INTEGRITY.c_str(), optional_argument, 0, 'V' }, - { PREF_REALTIME_CHUNK_CHECKSUM.c_str(), required_argument, &lopt, 204 }, -#endif // ENABLE_MESSAGE_DIGEST - { PREF_CONTINUE.c_str(), no_argument, 0, 'c' }, - { PREF_USER_AGENT.c_str(), required_argument, 0, 'U' }, - { PREF_NO_NETRC.c_str(), no_argument, 0, 'n' }, - { PREF_INPUT_FILE.c_str(), required_argument, 0, 'i' }, - { PREF_MAX_CONCURRENT_DOWNLOADS.c_str(), required_argument, 0, 'j' }, - { PREF_LOAD_COOKIES.c_str(), required_argument, &lopt, 205 }, - { PREF_FORCE_SEQUENTIAL.c_str(), optional_argument, 0, 'Z' }, - { PREF_AUTO_FILE_RENAMING.c_str(), optional_argument, &lopt, 206 }, - { PREF_PARAMETERIZED_URI.c_str(), optional_argument, 0, 'P' }, - { PREF_ENABLE_HTTP_KEEP_ALIVE.c_str(), optional_argument, &lopt, 207 }, - { PREF_ENABLE_HTTP_PIPELINING.c_str(), optional_argument, &lopt, 208 }, - { PREF_NO_FILE_ALLOCATION_LIMIT.c_str(), required_argument, &lopt, 209 }, -#ifdef ENABLE_DIRECT_IO - { PREF_ENABLE_DIRECT_IO.c_str(), optional_argument, &lopt, 210 }, -#endif // ENABLE_DIRECT_IO - { PREF_ALLOW_PIECE_LENGTH_CHANGE.c_str(), required_argument, &lopt, 211 }, - { PREF_NO_CONF.c_str(), no_argument, &lopt, 212 }, - { PREF_CONF_PATH.c_str(), required_argument, &lopt, 213 }, - { PREF_STOP.c_str(), required_argument, &lopt, 214 }, - { PREF_HEADER.c_str(), required_argument, &lopt, 215 }, - { PREF_QUIET.c_str(), optional_argument, 0, 'q' }, -#ifdef ENABLE_ASYNC_DNS - { PREF_ASYNC_DNS.c_str(), optional_argument, &lopt, 216 }, -#endif // ENABLE_ASYNC_DNS - { PREF_FTP_REUSE_CONNECTION.c_str(), optional_argument, &lopt, 217 }, - { PREF_SUMMARY_INTERVAL.c_str(), required_argument, &lopt, 218 }, - { PREF_LOG_LEVEL.c_str(), required_argument, &lopt, 219 }, - { PREF_URI_SELECTOR.c_str(), required_argument, &lopt, 220 }, - { PREF_SERVER_STAT_IF.c_str(), required_argument, &lopt, 221 }, - { PREF_SERVER_STAT_OF.c_str(), required_argument, &lopt, 222 }, - { PREF_SERVER_STAT_TIMEOUT.c_str(), required_argument, &lopt, 223 }, - { PREF_REMOTE_TIME.c_str(), optional_argument, 0, 'R' }, - { PREF_CONNECT_TIMEOUT.c_str(), required_argument, &lopt, 224 }, - { PREF_MAX_FILE_NOT_FOUND.c_str(), required_argument, &lopt, 225 }, - { PREF_AUTO_SAVE_INTERVAL.c_str(), required_argument, &lopt, 226 }, - { PREF_HTTPS_PROXY.c_str(), required_argument, &lopt, 227 }, - { PREF_FTP_PROXY.c_str(), required_argument, &lopt, 228 }, - { PREF_ALL_PROXY.c_str(), required_argument, &lopt, 229 }, - { PREF_PROXY_METHOD.c_str(), required_argument, &lopt, 230 }, - { PREF_CERTIFICATE.c_str(), required_argument, &lopt, 231 }, - { PREF_PRIVATE_KEY.c_str(), required_argument, &lopt, 232 }, - { PREF_CA_CERTIFICATE.c_str(), optional_argument, &lopt, 233 }, - { PREF_CHECK_CERTIFICATE.c_str(), optional_argument, &lopt, 234 }, - { PREF_NO_PROXY.c_str(), required_argument, &lopt, 235 }, - { PREF_USE_HEAD.c_str(), optional_argument, &lopt, 236 }, - { PREF_EVENT_POLL.c_str(), required_argument, &lopt, 237 }, - { PREF_HTTP_SERVER_LISTEN_PORT.c_str(), required_argument, &lopt, 238 }, - { PREF_ENABLE_HTTP_SERVER.c_str(), optional_argument, &lopt, 239 }, -#if defined ENABLE_BITTORRENT || defined ENABLE_METALINK - { PREF_SHOW_FILES.c_str(), no_argument, NULL, 'S' }, - { PREF_SELECT_FILE.c_str(), required_argument, &lopt, 21 }, -#endif // ENABLE_BITTORRENT || ENABLE_METALINK -#ifdef ENABLE_BITTORRENT - { PREF_TORRENT_FILE.c_str(), required_argument, NULL, 'T' }, - { PREF_LISTEN_PORT.c_str(), required_argument, &lopt, 15 }, - { PREF_FOLLOW_TORRENT.c_str(), required_argument, &lopt, 16 }, - { PREF_DIRECT_FILE_MAPPING.c_str(), required_argument, &lopt, 19 }, - // TODO remove upload-limit. - //{ "upload-limit".c_str(), required_argument, &lopt, 20 }, - { PREF_SEED_TIME.c_str(), required_argument, &lopt, 22 }, - { PREF_SEED_RATIO.c_str(), required_argument, &lopt, 23 }, - { PREF_MAX_UPLOAD_LIMIT.c_str(), required_argument, 0, 'u' }, - { PREF_PEER_ID_PREFIX.c_str(), required_argument, &lopt, 25 }, - { PREF_ENABLE_PEER_EXCHANGE.c_str(), optional_argument, &lopt, 26 }, - { PREF_ENABLE_DHT.c_str(), optional_argument, &lopt, 27 }, - { PREF_DHT_LISTEN_PORT.c_str(), required_argument, &lopt, 28 }, - { PREF_DHT_ENTRY_POINT.c_str(), required_argument, &lopt, 29 }, - { PREF_BT_MIN_CRYPTO_LEVEL.c_str(), required_argument, &lopt, 30 }, - { PREF_BT_REQUIRE_CRYPTO.c_str(), required_argument, &lopt, 31 }, - { PREF_BT_REQUEST_PEER_SPEED_LIMIT.c_str(), required_argument, &lopt, 32 }, - { PREF_BT_MAX_OPEN_FILES.c_str(), required_argument, &lopt, 33 }, - { PREF_BT_SEED_UNVERIFIED.c_str(), optional_argument, &lopt, 34 }, - { PREF_DHT_FILE_PATH.c_str(), required_argument, &lopt, 35 }, - { PREF_MAX_OVERALL_UPLOAD_LIMIT.c_str(), required_argument, &lopt, 36 }, - { PREF_BT_HASH_CHECK_SEED.c_str(), optional_argument, &lopt, 37 }, - { PREF_BT_MAX_PEERS.c_str(), required_argument, &lopt, 38 }, - { PREF_BT_EXTERNAL_IP.c_str(), required_argument, &lopt, 39 }, -#endif // ENABLE_BITTORRENT -#ifdef ENABLE_METALINK - { PREF_METALINK_FILE.c_str(), required_argument, NULL, 'M' }, - { PREF_METALINK_SERVERS.c_str(), required_argument, NULL, 'C' }, - { PREF_METALINK_VERSION.c_str(), required_argument, &lopt, 100 }, - { PREF_METALINK_LANGUAGE.c_str(), required_argument, &lopt, 101 }, - { PREF_METALINK_OS.c_str(), required_argument, &lopt, 102 }, - { PREF_FOLLOW_METALINK.c_str(), required_argument, &lopt, 103 }, - { PREF_METALINK_LOCATION.c_str(), required_argument, &lopt, 104 }, - { PREF_METALINK_PREFERRED_PROTOCOL.c_str(), required_argument, &lopt, 105 }, - { PREF_METALINK_ENABLE_UNIQUE_PROTOCOL.c_str(), optional_argument, &lopt, 106 }, -#endif // ENABLE_METALINK - { "version", no_argument, NULL, 'v' }, - { "help", optional_argument, NULL, 'h' }, - { 0, 0, 0, 0 } - }; - c = getopt_long(argc, argv, - "Dd:o:l:s:p::t:m:vh::ST:M:C:a:cU:ni:j:Z::P::q::R::V::u:", - longOpts, &optIndex); - if(c == -1) { - break; - } - switch(c) { - case 0:{ - switch(lopt) { - case 1: - cmdstream << PREF_HTTP_PROXY << "=" << optarg << "\n"; - break; - case 2: - cmdstream << PREF_HTTP_USER << "=" << optarg << "\n"; - break; - case 3: - cmdstream << PREF_HTTP_PASSWD << "=" << optarg << "\n"; - break; - case 4: - std::cout << "--http-proxy-user was deprecated. See --http-proxy," - << " --https-proxy, --ftp-proxy, --all-proxy options." - << std::endl; - exit(DownloadResult::UNKNOWN_ERROR); - case 5: - std::cout << "--http-proxy-passwd was deprecated. See --http-proxy," - << " --https-proxy, --ftp-proxy, --all-proxy options." - << std::endl; - exit(DownloadResult::UNKNOWN_ERROR); - case 6: - cmdstream << PREF_HTTP_AUTH_SCHEME << "=" << optarg << "\n"; - break; - case 7: - cmdstream << PREF_REFERER << "=" << optarg << "\n"; - break; - case 8: - cmdstream << PREF_RETRY_WAIT << "=" << optarg << "\n"; - break; - case 9: - cmdstream << PREF_FTP_USER << "=" << optarg << "\n"; - break; - case 10: - cmdstream << PREF_FTP_PASSWD << "=" << optarg << "\n"; - break; - case 11: - cmdstream << PREF_FTP_TYPE << "=" << optarg << "\n"; - break; - case 12: - std::cout << "--ftp-via-http-proxy was deprecated." - << " Use --http-proxy-method option instead." - << std::endl; - exit(DownloadResult::UNKNOWN_ERROR); - case 14: - std::cout << "--http-proxy-method was deprecated." - << " Use --proxy-method option instead." - << std::endl; - exit(DownloadResult::UNKNOWN_ERROR); - case 15: - cmdstream << PREF_LISTEN_PORT << "=" << optarg << "\n"; - break; - case 16: - cmdstream << PREF_FOLLOW_TORRENT << "=" << optarg << "\n"; - break; - case 19: - cmdstream << PREF_DIRECT_FILE_MAPPING << "=" << optarg << "\n"; - break; - case 21: - cmdstream << PREF_SELECT_FILE << "=" << optarg << "\n"; - break; - case 22: - cmdstream << PREF_SEED_TIME << "=" << optarg << "\n"; - break; - case 23: - cmdstream << PREF_SEED_RATIO << "=" << optarg << "\n"; - break; - case 25: - cmdstream << PREF_PEER_ID_PREFIX << "=" << optarg << "\n"; - break; - case 26: - cmdstream << PREF_ENABLE_PEER_EXCHANGE << "=" << toBoolArg(optarg) << "\n"; - break; - case 27: - cmdstream << PREF_ENABLE_DHT << "=" << toBoolArg(optarg) << "\n"; - break; - case 28: - cmdstream << PREF_DHT_LISTEN_PORT << "=" << optarg << "\n"; - break; - case 29: - cmdstream << PREF_DHT_ENTRY_POINT << "=" << optarg << "\n"; - break; - case 30: - cmdstream << PREF_BT_MIN_CRYPTO_LEVEL << "=" << optarg << "\n"; - break; - case 31: - cmdstream << PREF_BT_REQUIRE_CRYPTO << "=" << optarg << "\n"; - break; - case 32: - cmdstream << PREF_BT_REQUEST_PEER_SPEED_LIMIT << "=" << optarg << "\n"; - break; - case 33: - cmdstream << PREF_BT_MAX_OPEN_FILES << "=" << optarg << "\n"; - break; - case 34: - cmdstream << PREF_BT_SEED_UNVERIFIED << "=" << toBoolArg(optarg) - << "\n"; - break; - case 35: - cmdstream << PREF_DHT_FILE_PATH << "=" << optarg << "\n"; - break; - case 36: - cmdstream << PREF_MAX_OVERALL_UPLOAD_LIMIT << "=" << optarg << "\n"; - break; - case 37: - cmdstream << PREF_BT_HASH_CHECK_SEED << "=" << optarg << "\n"; - break; - case 38: - cmdstream << PREF_BT_MAX_PEERS << "=" << optarg << "\n"; - break; - case 39: - cmdstream << PREF_BT_EXTERNAL_IP << "=" << optarg << "\n"; - break; - case 100: - cmdstream << PREF_METALINK_VERSION << "=" << optarg << "\n"; - break; - case 101: - cmdstream << PREF_METALINK_LANGUAGE << "=" << optarg << "\n"; - break; - case 102: - cmdstream << PREF_METALINK_OS << "=" << optarg << "\n"; - break; - case 103: - cmdstream << PREF_FOLLOW_METALINK << "=" << optarg << "\n"; - break; - case 104: - cmdstream << PREF_METALINK_LOCATION << "=" << optarg << "\n"; - break; - case 105: - cmdstream << PREF_METALINK_PREFERRED_PROTOCOL << "=" << optarg << "\n"; - break; - case 106: - cmdstream << PREF_METALINK_ENABLE_UNIQUE_PROTOCOL << "=" << toBoolArg(optarg) << "\n"; - break; - case 200: - cmdstream << PREF_LOWEST_SPEED_LIMIT << "=" << optarg << "\n"; - break; - case 201: - cmdstream << PREF_MAX_DOWNLOAD_LIMIT << "=" << optarg << "\n"; - break; - case 202: - cmdstream << PREF_ALLOW_OVERWRITE << "=" << optarg << "\n"; - break; - case 204: - cmdstream << PREF_REALTIME_CHUNK_CHECKSUM << "=" << optarg << "\n"; - break; - case 205: - cmdstream << PREF_LOAD_COOKIES << "=" << optarg << "\n"; - break; - case 206: - cmdstream << PREF_AUTO_FILE_RENAMING << "=" << toBoolArg(optarg) << "\n"; - break; - case 207: - cmdstream << PREF_ENABLE_HTTP_KEEP_ALIVE << "=" << toBoolArg(optarg) << "\n"; - break; - case 208: - cmdstream << PREF_ENABLE_HTTP_PIPELINING << "=" << toBoolArg(optarg) << "\n"; - break; - case 209: - cmdstream << PREF_NO_FILE_ALLOCATION_LIMIT << "=" << optarg << "\n"; - break; - case 210: - cmdstream << PREF_ENABLE_DIRECT_IO << "=" << toBoolArg(optarg) << "\n"; - break; - case 211: - cmdstream << PREF_ALLOW_PIECE_LENGTH_CHANGE << "=" << optarg << "\n"; - break; - case 212: - noConf = true; - break; - case 213: - ucfname = optarg; - break; - case 214: - cmdstream << PREF_STOP << "=" << optarg << "\n"; - break; - case 215: - cmdstream << PREF_HEADER << "=" << optarg << "\n"; - break; -#ifdef ENABLE_ASYNC_DNS - case 216: - cmdstream << PREF_ASYNC_DNS << "=" << toBoolArg(optarg) << "\n"; - break; -#endif // ENABLE_ASYNC_DNS - case 217: - cmdstream << PREF_FTP_REUSE_CONNECTION << "=" << toBoolArg(optarg) << "\n"; - break; - case 218: - cmdstream << PREF_SUMMARY_INTERVAL << "=" << optarg << "\n"; - break; - case 219: - cmdstream << PREF_LOG_LEVEL << "=" << optarg << "\n"; - break; - case 220: - cmdstream << PREF_URI_SELECTOR << "=" << optarg << "\n"; - break; - case 221: - cmdstream << PREF_SERVER_STAT_IF << "=" << optarg << "\n"; - break; - case 222: - cmdstream << PREF_SERVER_STAT_OF << "=" << optarg << "\n"; - break; - case 223: - cmdstream << PREF_SERVER_STAT_TIMEOUT << "=" << optarg << "\n"; - break; - case 224: - cmdstream << PREF_CONNECT_TIMEOUT << "=" << optarg << "\n"; - break; - case 225: - cmdstream << PREF_MAX_FILE_NOT_FOUND << "=" << optarg << "\n"; - break; - case 226: - cmdstream << PREF_AUTO_SAVE_INTERVAL << "=" << optarg << "\n"; - break; - case 227: - cmdstream << PREF_HTTPS_PROXY << "=" << optarg << "\n"; - break; - case 228: - cmdstream << PREF_FTP_PROXY << "=" << optarg << "\n"; - break; - case 229: - cmdstream << PREF_ALL_PROXY << "=" << optarg << "\n"; - break; - case 230: - cmdstream << PREF_PROXY_METHOD << "=" << optarg << "\n"; - break; - case 231: - cmdstream << PREF_CERTIFICATE << "=" << optarg << "\n"; - break; - case 232: - cmdstream << PREF_PRIVATE_KEY << "=" << optarg << "\n"; - break; - case 233: - cmdstream << PREF_CA_CERTIFICATE << "=" << optarg << "\n"; - break; - case 234: - cmdstream << PREF_CHECK_CERTIFICATE << "=" << toBoolArg(optarg) << "\n"; - break; - case 235: - cmdstream << PREF_NO_PROXY << "=" << optarg << "\n"; - break; - case 236: - cmdstream << PREF_USE_HEAD << "=" << toBoolArg(optarg) << "\n"; - break; - case 237: - cmdstream << PREF_EVENT_POLL << "=" << optarg << "\n"; - break; - case 238: - cmdstream << PREF_HTTP_SERVER_LISTEN_PORT << "=" << optarg << "\n"; - break; - case 239: - cmdstream << PREF_ENABLE_HTTP_SERVER << "=" << toBoolArg(optarg) - << "\n"; - break; + if(op.defined("version")) { + showVersion(); + exit(DownloadResult::FINISHED); } - break; - } -#ifdef HAVE_DAEMON - case 'D': - cmdstream << PREF_DAEMON << "=" << V_TRUE << "\n"; - break; -#endif // HAVE_DAEMON - case 'd': - cmdstream << PREF_DIR << "=" << optarg << "\n"; - break; - case 'o': - cmdstream << PREF_OUT << "=" << optarg << "\n"; - break; - case 'l': - cmdstream << PREF_LOG << "=" << optarg << "\n"; - break; - case 's': - cmdstream << PREF_SPLIT << "=" << optarg << "\n"; - break; - case 't': - cmdstream << PREF_TIMEOUT << "=" << optarg << "\n"; - break; - case 'm': - cmdstream << PREF_MAX_TRIES << "=" << optarg << "\n"; - break; - case 'p': - cmdstream << PREF_FTP_PASV << "=" << toBoolArg(optarg) << "\n"; - break; - case 'S': - cmdstream << PREF_SHOW_FILES << "=" << V_TRUE << "\n"; - break; - case 'T': - cmdstream << PREF_TORRENT_FILE << "=" << optarg << "\n"; - break; - case 'M': - cmdstream << PREF_METALINK_FILE << "=" << optarg << "\n"; - break; - case 'C': - cmdstream << PREF_METALINK_SERVERS << "=" << optarg << "\n"; - break; - case 'a': - cmdstream << PREF_FILE_ALLOCATION << "=" << optarg << "\n"; - break; - case 'c': - cmdstream << PREF_CONTINUE << "=" << V_TRUE << "\n"; - break; - case 'U': - cmdstream << PREF_USER_AGENT << "=" << optarg << "\n"; - break; - case 'n': - cmdstream << PREF_NO_NETRC << "=" << V_TRUE << "\n"; - break; - case 'i': - cmdstream << PREF_INPUT_FILE << "=" << optarg << "\n"; - break; - case 'j': - cmdstream << PREF_MAX_CONCURRENT_DOWNLOADS << "=" << optarg << "\n"; - break; - case 'Z': - cmdstream << PREF_FORCE_SEQUENTIAL << "=" << toBoolArg(optarg) << "\n"; - break; - case 'P': - cmdstream << PREF_PARAMETERIZED_URI << "=" << toBoolArg(optarg) << "\n"; - break; - case 'q': - cmdstream << PREF_QUIET << "=" << toBoolArg(optarg) << "\n"; - break; - case 'R': - cmdstream << PREF_REMOTE_TIME << "=" << toBoolArg(optarg) << "\n"; - break; - case 'V': - cmdstream << PREF_CHECK_INTEGRITY << "=" << toBoolArg(optarg) << "\n"; - break; - case 'u': - cmdstream << PREF_MAX_UPLOAD_LIMIT << "=" << optarg << "\n"; - break; - case 'v': - showVersion(); - exit(DownloadResult::FINISHED); - case 'h': - { + if(op.defined("help")) { std::string keyword; - if(optarg == 0 || strlen(optarg) == 0) { + if(op.get("help").empty()) { keyword = TAG_BASIC; } else { - keyword = optarg; + keyword = op.get("help"); if(Util::startsWith(keyword, "--")) { keyword = keyword.substr(2); } @@ -598,13 +115,10 @@ Option* option_processing(int argc, char* const argv[]) showUsage(keyword, oparser); exit(DownloadResult::FINISHED); } - default: - showUsage(TAG_HELP, oparser); - exit(DownloadResult::UNKNOWN_ERROR); } - } - { + oparser.parseDefaultValues(op); + if(!noConf) { std::string cfname = ucfname.empty() ? @@ -642,43 +156,44 @@ Option* option_processing(int argc, char* const argv[]) overrideWithEnv(op, oparser, PREF_ALL_PROXY, "all_proxy"); overrideWithEnv(op, oparser, PREF_NO_PROXY, "no_proxy"); - try { - oparser.parse(op, cmdstream); - } catch(OptionHandlerException& e) { - std::cerr << e.stackTrace() << "\n" - << "Usage:" << "\n" - << oparser.findByName(e.getOptionName())->getDescription() - << std::endl; - exit(DownloadResult::UNKNOWN_ERROR); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - showUsage(TAG_HELP, oparser); - exit(DownloadResult::UNKNOWN_ERROR); - } + // we must clear eof bit and seek to the beginning of the buffer. + cmdstream.clear(); + cmdstream.seekg(0, std::ios::beg); + // finaly let's parse and store command-iine options. + oparser.parse(op, cmdstream); + } catch(OptionHandlerException& e) { + std::cerr << e.stackTrace() << "\n" + << "Usage:" << "\n" + << oparser.findByName(e.getOptionName())->getDescription() + << std::endl; + exit(DownloadResult::UNKNOWN_ERROR); + } catch(Exception& e) { + std::cerr << e.stackTrace() << std::endl; + showUsage(TAG_HELP, oparser); + exit(DownloadResult::UNKNOWN_ERROR); } if( #ifdef ENABLE_BITTORRENT - op->blank(PREF_TORRENT_FILE) && + op.blank(PREF_TORRENT_FILE) && #endif // ENABLE_BITTORRENT #ifdef ENABLE_METALINK - op->blank(PREF_METALINK_FILE) && + op.blank(PREF_METALINK_FILE) && #endif // ENABLE_METALINK - op->blank(PREF_INPUT_FILE)) { - if(optind == argc) { + op.blank(PREF_INPUT_FILE)) { + if(uris.empty()) { std::cerr << MSG_URI_REQUIRED << std::endl; showUsage(TAG_HELP, oparser); exit(DownloadResult::UNKNOWN_ERROR); } } #ifdef HAVE_DAEMON - if(op->getAsBool(PREF_DAEMON)) { + if(op.getAsBool(PREF_DAEMON)) { if(daemon(1, 1) < 0) { perror(MSG_DAEMON_FAILED); exit(DownloadResult::UNKNOWN_ERROR); } } #endif // HAVE_DAEMON - return op; } } // namespace aria2 diff --git a/test/OptionHandlerTest.cc b/test/OptionHandlerTest.cc index 67d5de35..b99c91d3 100644 --- a/test/OptionHandlerTest.cc +++ b/test/OptionHandlerTest.cc @@ -1,8 +1,9 @@ #include "OptionHandlerImpl.h" + +#include + #include "prefs.h" #include "Exception.h" -#include -#include namespace aria2 { @@ -53,7 +54,9 @@ void OptionHandlerTest::testNullOptionHandler() { NullOptionHandler handler; CPPUNIT_ASSERT(handler.canHandle("foo")); - handler.parse(0, "bar"); + Option option; + handler.parse(option, "bar"); + CPPUNIT_ASSERT(!option.defined("bar")); } void OptionHandlerTest::testBooleanOptionHandler() @@ -62,16 +65,14 @@ void OptionHandlerTest::testBooleanOptionHandler() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, V_TRUE); + handler.parse(option, V_TRUE); CPPUNIT_ASSERT_EQUAL(std::string(V_TRUE), option.get("foo")); - handler.parse(&option, V_FALSE); + handler.parse(option, V_FALSE); CPPUNIT_ASSERT_EQUAL(std::string(V_FALSE), option.get("foo")); try { - handler.parse(&option, "hello"); + handler.parse(option, "hello"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("true,false"), handler.createPossibleValuesString()); } @@ -82,7 +83,7 @@ void OptionHandlerTest::testNumberOptionHandler() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "0"); + handler.parse(option, "0"); CPPUNIT_ASSERT_EQUAL(std::string("0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(std::string("*-*"), handler.createPossibleValuesString()); @@ -92,14 +93,12 @@ void OptionHandlerTest::testNumberOptionHandler_min() { NumberOptionHandler handler("foo", "", "", 1); Option option; - handler.parse(&option, "1"); + handler.parse(option, "1"); CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get("foo")); try { - handler.parse(&option, "0"); + handler.parse(option, "0"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("1-*"), handler.createPossibleValuesString()); } @@ -108,14 +107,12 @@ void OptionHandlerTest::testNumberOptionHandler_max() { NumberOptionHandler handler("foo", "", "", -1, 100); Option option; - handler.parse(&option, "100"); + handler.parse(option, "100"); CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get("foo")); try { - handler.parse(&option, "101"); + handler.parse(option, "101"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("*-100"), handler.createPossibleValuesString()); } @@ -124,22 +121,18 @@ void OptionHandlerTest::testNumberOptionHandler_min_max() { NumberOptionHandler handler("foo", "", "", 1, 100); Option option; - handler.parse(&option, "1"); + handler.parse(option, "1"); CPPUNIT_ASSERT_EQUAL(std::string("1"), option.get("foo")); - handler.parse(&option, "100"); + handler.parse(option, "100"); CPPUNIT_ASSERT_EQUAL(std::string("100"), option.get("foo")); try { - handler.parse(&option, "0"); + handler.parse(option, "0"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} try { - handler.parse(&option, "101"); + handler.parse(option, "101"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("1-100"), handler.createPossibleValuesString()); } @@ -150,29 +143,23 @@ void OptionHandlerTest::testUnitNumberOptionHandler() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "4294967296"); + handler.parse(option, "4294967296"); CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get("foo")); - handler.parse(&option, "4096M"); + handler.parse(option, "4096M"); CPPUNIT_ASSERT_EQUAL(std::string("4294967296"), option.get("foo")); - handler.parse(&option, "4096K"); + handler.parse(option, "4096K"); CPPUNIT_ASSERT_EQUAL(std::string("4194304"), option.get("foo")); try { - handler.parse(&option, "K"); + handler.parse(option, "K"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace(); - } + } catch(Exception& e) {} try { - handler.parse(&option, "M"); - } catch(Exception& e) { - std::cerr << e.stackTrace(); - } + handler.parse(option, "M"); + } catch(Exception& e) {} try { - handler.parse(&option, ""); + handler.parse(option, ""); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace(); - } + } catch(Exception& e) {} } void OptionHandlerTest::testParameterOptionHandler_1argInit() @@ -181,14 +168,12 @@ void OptionHandlerTest::testParameterOptionHandler_1argInit() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "value1"); + handler.parse(option, "value1"); CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo")); try { - handler.parse(&option, "value3"); + handler.parse(option, "value3"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("value1"), handler.createPossibleValuesString()); } @@ -199,16 +184,14 @@ void OptionHandlerTest::testParameterOptionHandler_2argsInit() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "value1"); + handler.parse(option, "value1"); CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo")); - handler.parse(&option, "value2"); + handler.parse(option, "value2"); CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get("foo")); try { - handler.parse(&option, "value3"); + handler.parse(option, "value3"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("value1,value2"), handler.createPossibleValuesString()); } @@ -223,16 +206,14 @@ void OptionHandlerTest::testParameterOptionHandler_listInit() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "value1"); + handler.parse(option, "value1"); CPPUNIT_ASSERT_EQUAL(std::string("value1"), option.get("foo")); - handler.parse(&option, "value2"); + handler.parse(option, "value2"); CPPUNIT_ASSERT_EQUAL(std::string("value2"), option.get("foo")); try { - handler.parse(&option, "value3"); + handler.parse(option, "value3"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("value1,value2"), handler.createPossibleValuesString()); } @@ -243,9 +224,9 @@ void OptionHandlerTest::testDefaultOptionHandler() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "bar"); + handler.parse(option, "bar"); CPPUNIT_ASSERT_EQUAL(std::string("bar"), option.get("foo")); - handler.parse(&option, ""); + handler.parse(option, ""); CPPUNIT_ASSERT_EQUAL(std::string(""), option.get("foo")); CPPUNIT_ASSERT_EQUAL(std::string(""), handler.createPossibleValuesString()); @@ -264,7 +245,7 @@ void OptionHandlerTest::testFloatNumberOptionHandler() CPPUNIT_ASSERT(handler.canHandle("foo")); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "1.0"); + handler.parse(option, "1.0"); CPPUNIT_ASSERT_EQUAL(std::string("1.0"), option.get("foo")); CPPUNIT_ASSERT_EQUAL(std::string("*-*"), handler.createPossibleValuesString()); @@ -274,14 +255,12 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min() { FloatNumberOptionHandler handler("foo", "", "", 0.0); Option option; - handler.parse(&option, "0.0"); + handler.parse(option, "0.0"); CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get("foo")); try { - handler.parse(&option, "-0.1"); + handler.parse(option, "-0.1"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("0.0-*"), handler.createPossibleValuesString()); } @@ -290,14 +269,12 @@ void OptionHandlerTest::testFloatNumberOptionHandler_max() { FloatNumberOptionHandler handler("foo", "", "", -1, 10.0); Option option; - handler.parse(&option, "10.0"); + handler.parse(option, "10.0"); CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get("foo")); try { - handler.parse(&option, "10.1"); + handler.parse(option, "10.1"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("*-10.0"), handler.createPossibleValuesString()); } @@ -306,22 +283,18 @@ void OptionHandlerTest::testFloatNumberOptionHandler_min_max() { FloatNumberOptionHandler handler("foo", "", "", 0.0, 10.0); Option option; - handler.parse(&option, "0.0"); + handler.parse(option, "0.0"); CPPUNIT_ASSERT_EQUAL(std::string("0.0"), option.get("foo")); - handler.parse(&option, "10.0"); + handler.parse(option, "10.0"); CPPUNIT_ASSERT_EQUAL(std::string("10.0"), option.get("foo")); try { - handler.parse(&option, "-0.1"); + handler.parse(option, "-0.1"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} try { - handler.parse(&option, "10.1"); + handler.parse(option, "10.1"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("0.0-10.0"), handler.createPossibleValuesString()); } @@ -332,24 +305,22 @@ void OptionHandlerTest::testHttpProxyOptionHandler() CPPUNIT_ASSERT(handler.canHandle(PREF_HTTP_PROXY)); CPPUNIT_ASSERT(!handler.canHandle("foobar")); Option option; - handler.parse(&option, "proxy:65535"); + handler.parse(option, "proxy:65535"); CPPUNIT_ASSERT_EQUAL(std::string("http://proxy:65535"), option.get(PREF_HTTP_PROXY)); - handler.parse(&option, "http://proxy:8080"); + handler.parse(option, "http://proxy:8080"); CPPUNIT_ASSERT_EQUAL(std::string("http://proxy:8080"), option.get(PREF_HTTP_PROXY)); - handler.parse(&option, "ftp://proxy:8080"); + handler.parse(option, "ftp://proxy:8080"); CPPUNIT_ASSERT_EQUAL(std::string("http://ftp://proxy:8080"), option.get(PREF_HTTP_PROXY)); try { - handler.parse(&option, "http://bar:65536"); + handler.parse(option, "http://bar:65536"); CPPUNIT_FAIL("exception must be thrown."); - } catch(Exception& e) { - std::cerr << e.stackTrace() << std::endl; - } + } catch(Exception& e) {} CPPUNIT_ASSERT_EQUAL(std::string("[http://][USER:PASSWORD@]HOST[:PORT]"), handler.createPossibleValuesString()); } diff --git a/test/OptionParserTest.cc b/test/OptionParserTest.cc index 1e561b0e..e4188123 100644 --- a/test/OptionParserTest.cc +++ b/test/OptionParserTest.cc @@ -1,10 +1,16 @@ #include "OptionParser.h" + +#include +#include +#include + +#include + #include "OptionHandlerImpl.h" #include "Exception.h" #include "Util.h" #include "Option.h" -#include -#include +#include "array_fun.h" namespace aria2 { @@ -15,7 +21,10 @@ class OptionParserTest:public CppUnit::TestFixture { CPPUNIT_TEST(testFindByNameSubstring); CPPUNIT_TEST(testFindByTag); CPPUNIT_TEST(testFindByName); + CPPUNIT_TEST(testFindByShortName); + CPPUNIT_TEST(testFindByID); CPPUNIT_TEST(testParseDefaultValues); + CPPUNIT_TEST(testParseArg); CPPUNIT_TEST_SUITE_END(); private: SharedHandle _oparser; @@ -24,26 +33,27 @@ public: { _oparser.reset(new OptionParser()); - SharedHandle alpha(new DefaultOptionHandler("alpha", - "", - "ALPHA")); + SharedHandle alpha + (new DefaultOptionHandler("alpha", NO_DESCRIPTION, "ALPHA", "", + OptionHandler::REQ_ARG, 'A')); alpha->addTag("apple"); _oparser->addOptionHandler(alpha); + SharedHandle bravo(new DefaultOptionHandler("bravo")); bravo->addTag("apple"); bravo->addTag("orange"); bravo->addTag("pineapple"); _oparser->addOptionHandler(bravo); - SharedHandle charlie(new DefaultOptionHandler("charlie", - "", - "CHARLIE", - "", - true)); + + SharedHandle charlie + (new DefaultOptionHandler("charlie", NO_DESCRIPTION, "CHARLIE", "", + OptionHandler::REQ_ARG, 'C')); + charlie->hide(); charlie->addTag("pineapple"); _oparser->addOptionHandler(charlie); - SharedHandle delta(new UnitNumberOptionHandler("delta", - "", - "1M")); + + SharedHandle delta + (new UnitNumberOptionHandler("delta", NO_DESCRIPTION, "1M", -1, -1, 'D')); delta->addTag("pineapple"); _oparser->addOptionHandler(delta); } @@ -54,7 +64,10 @@ public: void testFindByNameSubstring(); void testFindByTag(); void testFindByName(); + void testFindByShortName(); + void testFindByID(); void testParseDefaultValues(); + void testParseArg(); }; @@ -97,14 +110,69 @@ void OptionParserTest::testFindByName() CPPUNIT_ASSERT(charlie.isNull()); } +void OptionParserTest::testFindByShortName() +{ + SharedHandle alpha = _oparser->findByShortName('A'); + CPPUNIT_ASSERT(!alpha.isNull()); + CPPUNIT_ASSERT_EQUAL(std::string("alpha"), alpha->getName()); + + CPPUNIT_ASSERT(_oparser->findByShortName('C').isNull()); +} + +void OptionParserTest::testFindByID() +{ + SharedHandle alpha = _oparser->findByID(1); + CPPUNIT_ASSERT(!alpha.isNull()); + CPPUNIT_ASSERT_EQUAL(std::string("alpha"), alpha->getName()); + + CPPUNIT_ASSERT(_oparser->findByID(3).isNull()); +} + void OptionParserTest::testParseDefaultValues() { Option option; - _oparser->parseDefaultValues(&option); + _oparser->parseDefaultValues(option); CPPUNIT_ASSERT_EQUAL(std::string("ALPHA"), option.get("alpha")); CPPUNIT_ASSERT_EQUAL(std::string("1048576"), option.get("delta")); CPPUNIT_ASSERT_EQUAL(std::string("CHARLIE"), option.get("charlie")); CPPUNIT_ASSERT(!option.defined("bravo")); } +void OptionParserTest::testParseArg() +{ + Option option; + char prog[7]; + strncpy(prog, "aria2c", sizeof(prog)); + + char optionAlpha[3]; + strncpy(optionAlpha, "-A", sizeof(optionAlpha)); + char argAlpha[6]; + strncpy(argAlpha, "ALPHA", sizeof(argAlpha)); + char optionBravo[8]; + strncpy(optionBravo, "--bravo", sizeof(optionBravo)); + char argBravo[6]; + strncpy(argBravo, "BRAVO", sizeof(argBravo)); + + char nonopt1[8]; + strncpy(nonopt1, "nonopt1", sizeof(nonopt1)); + char nonopt2[8]; + strncpy(nonopt2, "nonopt2", sizeof(nonopt2)); + + char* const argv[] = { prog, optionAlpha, argAlpha, optionBravo, argBravo, + nonopt1, nonopt2 }; + int argc = arrayLength(argv); + + std::stringstream s; + std::deque nonopts; + + _oparser->parseArg(s, nonopts, argc, argv); + + CPPUNIT_ASSERT_EQUAL(std::string("alpha=ALPHA\n" + "bravo=BRAVO\n"), s.str()); + + CPPUNIT_ASSERT_EQUAL((size_t)2, nonopts.size()); + CPPUNIT_ASSERT_EQUAL(std::string("nonopt1"), nonopts[0]); + CPPUNIT_ASSERT_EQUAL(std::string("nonopt2"), nonopts[1]); +} + } // namespace aria2