/* Copyright (C) 2016 Eric Wasylishen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA See file, 'COPYING', for details. */ #include "common/settings.hh" #include "common/threads.hh" #include "common/fs.hh" namespace settings { setting_base::setting_base( setting_container *dictionary, const nameset &names, const setting_group *group, const char *description) : _names(names), _group(group), _description(description) { Q_assert(_names.size() > 0); if (dictionary) { dictionary->registerSetting(this); } } bool setting_base::parseString(const std::string &string, source source) { parser_t p{string}; return parse("", p, source); } setting_group performance_group{"Performance", 10}; setting_group logging_group{"Logging", 5}; setting_group game_group{"Game", 15}; setting_container::~setting_container() = default; void setting_container::reset() { for (auto setting : _settings) { setting->reset(); } } void setting_container::copyFrom(const setting_container &other) { for (auto setting : _settings) { const std::string &pri_name = setting->primaryName(); const auto *other_setting = other.findSetting(pri_name); if (other_setting) { setting->copyFrom(*other_setting); } } } void setting_container::printHelp() { fmt::print("{}usage: {} [-help/-h/-?] [-options] {}\n\n", programDescription, programName, remainderName); for (auto grouped : grouped()) { if (grouped.first) { fmt::print("{}:\n", grouped.first->name); } for (auto setting : grouped.second) { size_t numPadding = max(static_cast(0), 28 - (setting->primaryName().size() + 4)); fmt::print(" -{} {:{}} {}\n", setting->primaryName(), setting->format(), numPadding, setting->getDescription()); for (int i = 1; i < setting->names().size(); i++) { fmt::print(" \\{}\n", setting->names()[i]); } } printf("\n"); } throw quit_after_help_exception(); } void setting_container::printSummary() { logging::print("\n--- Options Summary ---\n"); for (auto setting : _settings) { if (setting->isChanged()) { logging::print(" \"{}\" was set to \"{}\" (from {})\n", setting->primaryName(), setting->stringValue(), setting->sourceString()); } } logging::print("\n"); } std::vector setting_container::parse(parser_base_t &parser) { // the settings parser loop will continuously eat tokens as long as // it begins with a -; once we have no more settings to consume, we // break out of this loop and return the remainder. while (true) { // end of cmd line if (!parser.parse_token(PARSE_PEEK)) { break; } // end of options if (parser.token[0] != '-') { break; } // actually eat the token since we peeked above parser.parse_token(); // remove leading hyphens. we support any number of them. while (parser.token.front() == '-') { parser.token.erase(parser.token.begin()); } if (parser.token.empty()) { throw parse_exception("stray \"-\" in command line; please check your parameters"); } if (parser.token == "help" || parser.token == "h" || parser.token == "?") { printHelp(); } auto setting = findSetting(parser.token); if (!setting) { throw parse_exception(fmt::format("unknown option \"{}\"", parser.token)); } // pass off to setting to parse; store // name for error message below std::string token = std::move(parser.token); if (!setting->parse(token, parser, source::COMMANDLINE)) { throw parse_exception( fmt::format("invalid value for option \"{}\"; should be in format {}", token, setting->format())); } } // return remainder std::vector remainder; while (true) { if (parser.at_end() || !parser.parse_token()) { break; } remainder.emplace_back(std::move(parser.token)); } return remainder; } void common_settings::setParameters(int argc, const char **argv) { programName = fs::path(argv[0]).stem().string(); fmt::print("---- {} / ericw-tools {} ----\n", programName, ERICWTOOLS_VERSION); } void common_settings::postinitialize(int argc, const char **argv) { printSummary(); configureTBB(threads.value(), lowpriority.value()); if (verbose.value()) { logging::mask |= logging::flag::VERBOSE; } if (nopercent.value()) { logging::mask &= ~bitflags(logging::flag::PERCENT); } if (nostat.value()) { logging::mask &= ~bitflags(logging::flag::STAT); } if (noprogress.value()) { logging::mask &= ~bitflags(logging::flag::PROGRESS); } } } // namespace settings