/* */ #include "common.h" #include #include #include #include #include "Option.h" #include "prefs.h" #include "OptionParser.h" #include "OptionHandlerFactory.h" #include "OptionHandler.h" #include "util.h" #include "message.h" #include "Exception.h" #include "a2io.h" #include "help_tags.h" #include "File.h" #include "fmt.h" #include "OptionHandlerException.h" #include "UnknownOptionException.h" #include "error_code.h" #include "SimpleRandomizer.h" #include "bittorrent_helper.h" #include "BufferedFile.h" #include "console.h" #include "array_fun.h" #ifndef HAVE_DAEMON #include "daemon.h" #endif // !HAVE_DAEMON namespace aria2 { extern void showVersion(); extern void showUsage (const std::string& keyword, const SharedHandle& oparser, const Console& out); namespace { void overrideWithEnv (Option& op, const SharedHandle& optionParser, const Pref* pref, const std::string& envName) { char* value = getenv(envName.c_str()); if(value) { try { optionParser->find(pref)->parse(op, value); } catch(Exception& e) { global::cerr()->printf (_("Caught Error while parsing environment variable '%s'"), envName.c_str()); global::cerr()->printf("\n%s\n", e.stackTrace().c_str()); } } } } // namespace namespace { // Calculates Damerau–Levenshtein distance between c-string a and b // with given costs. swapcost, subcost, addcost and delcost are cost // to swap 2 adjacent characters, substitute characters, add character // and delete character respectively. int levenshtein (const char* a, const char* b, int swapcost, int subcost, int addcost, int delcost) { int alen = strlen(a); int blen = strlen(b); std::vector > dp(3, std::vector(blen+1)); for(int i = 0; i <= blen; ++i) { dp[1][i] = i; } for(int i = 1; i <= alen; ++i) { dp[0][0] = i; for(int j = 1; j <= blen; ++j) { dp[0][j] = dp[1][j-1]+(a[i-1] == b[j-1] ? 0 : subcost); if(i >= 2 && j >= 2 && a[i-1] != b[j-1] && a[i-2] == b[j-1] && a[i-1] == b[j-2]) { dp[0][j] = std::min(dp[0][j], dp[2][j-2]+swapcost); } dp[0][j] = std::min(dp[0][j], std::min(dp[1][j]+delcost, dp[0][j-1]+addcost)); } std::rotate(dp.begin(), dp.begin()+2, dp.end()); } return dp[1][blen]; } } // namespace namespace { void showCandidates (const std::string& unknownOption, const SharedHandle& parser) { const char* optstr = unknownOption.c_str(); for(; *optstr == '-'; ++optstr); if(*optstr == '\0') { return; } int optstrlen = strlen(optstr); std::vector > cands; for(int i = 1, len = option::countOption(); i < len; ++i) { const Pref* pref = option::i2p(i); const OptionHandler* h = parser->find(pref); if(!h || h->isHidden()) { continue; } // Use cost 0 for prefix match if(util::startsWith(pref->k, pref->k+strlen(pref->k), optstr, optstr+optstrlen)) { cands.push_back(std::make_pair(0, pref)); continue; } // cost values are borrowed from git, help.c. int sim = levenshtein(optstr, pref->k, 0, 2, 1, 4); cands.push_back(std::make_pair(sim, pref)); } if(cands.empty()) { return; } std::sort(cands.begin(), cands.end()); int threshold = cands[0].first; // threshold value 12 is a magic value. if(threshold > 12) { return; } global::cerr()->printf("\n"); global::cerr()->printf(_("Did you mean:")); global::cerr()->printf("\n"); for(std::vector >::iterator i = cands.begin(), eoi = cands.end(); i != eoi && (*i).first <= threshold; ++i) { global::cerr()->printf("\t--%s\n", (*i).second->k); } } } // namespace #ifdef __MINGW32__ namespace { void optionNativeToUtf8(Option& op) { for(size_t i = 1, len = option::countOption(); i < len; ++i) { const Pref* pref = option::i2p(i); if(op.definedLocal(pref) && !util::isUtf8(op.get(pref))) { op.put(pref, nativeToUtf8(op.get(pref))); } } } } // namespace #endif // __MINGW32__ void option_processing(Option& op, bool standalone, std::vector& uris, int argc, char** argv, const KeyVals& options) { const SharedHandle& oparser = OptionParser::getInstance(); try { 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); if(op.defined(PREF_VERSION)) { showVersion(); exit(error_code::FINISHED); } if(op.defined(PREF_HELP)) { std::string keyword; if(op.get(PREF_HELP).empty()) { keyword = strHelpTag(TAG_BASIC); } else { keyword = op.get(PREF_HELP); if(util::startsWith(keyword, "--")) { keyword.erase(keyword.begin(), keyword.begin()+2); } std::string::size_type eqpos = keyword.find("="); if(eqpos != std::string::npos) { keyword.erase(keyword.begin()+eqpos, keyword.end()); } } showUsage(keyword, oparser, global::cout()); exit(error_code::FINISHED); } } SharedHandle