commandline_options.cpp

Go to the documentation of this file.
00001 /* $Id: commandline_options.cpp 52910 2012-02-04 12:02:41Z gabba $ */
00002 /*
00003    Copyright (C) 2011 - 2012 by Lukasz Dobrogowski <lukasz.dobrogowski@gmail.com>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any lfooater version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
00014 */
00015 
00016 #include "commandline_options.hpp"
00017 #include "foreach.hpp"
00018 #include "serialization/string_utils.hpp"
00019 #include "util.hpp"
00020 #include "lua/llimits.h"
00021 
00022 #include <boost/version.hpp>
00023 
00024 namespace po = boost::program_options;
00025 
00026 // this class is needed since boost has some templated operators>> declared internally for tuples and we don't want them to interfere. Existence of such operator>> apparently causes program_options to cause the custom class somehow specially... well, the boost::tuple default operator>>  format doesn't suit our needs anyway.
00027 class two_strings : public boost::tuple<std::string,std::string> {};
00028 
00029 static void validate(boost::any& v, const std::vector<std::string>& values,
00030               two_strings*, int)
00031 {
00032     two_strings ret_val;
00033     if (values.size() != 2)
00034 #if BOOST_VERSION >= 104200
00035         throw po::validation_error(po::validation_error::invalid_option_value);
00036 #else
00037         throw po::validation_error("Invalid number of strings provided to option requiring exactly two of them.");
00038 #endif
00039     ret_val.get<0>() = values.at(0);
00040     ret_val.get<1>() = values.at(1);
00041     v = ret_val;
00042 }
00043 
00044 commandline_options::commandline_options ( int argc, char** argv ) :
00045     bpp(),
00046     campaign(),
00047     campaign_difficulty(),
00048     campaign_scenario(),
00049     clock(false),
00050     config_path(false),
00051     config_dir(),
00052     data_dir(),
00053     debug(false),
00054 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
00055     debug_dot_domain(),
00056     debug_dot_level(),
00057 #endif
00058     editor(),
00059     fps(false),
00060     fullscreen(false),
00061     gunzip(),
00062     gzip(),
00063     help(),
00064     language(),
00065     log(),
00066     load(),
00067     logdomains(),
00068     multiplayer(false),
00069     multiplayer_ai_config(),
00070     multiplayer_algorithm(),
00071     multiplayer_controller(),
00072     multiplayer_era(),
00073     multiplayer_exit_at_end(),
00074     multiplayer_label(),
00075     multiplayer_parm(),
00076     multiplayer_scenario(),
00077     multiplayer_side(),
00078     multiplayer_turns(),
00079     max_fps(),
00080     nocache(false),
00081     nodelay(false),
00082     nogui(false),
00083     nomusic(false),
00084     nosound(false),
00085     new_storyscreens(false),
00086     new_syntax(false),
00087     new_widgets(false),
00088     path(false),
00089     preprocess(false),
00090     preprocess_defines(),
00091     preprocess_input_macros(),
00092     preprocess_output_macros(),
00093     preprocess_path(),
00094     preprocess_target(),
00095     proxy(false),
00096     proxy_address(),
00097     proxy_password(),
00098     proxy_port(),
00099     proxy_user(),
00100     resolution(),
00101     rng_seed(),
00102     server(),
00103     username(),
00104     password(),
00105     screenshot(false),
00106     screenshot_map_file(),
00107     screenshot_output_file(),
00108     smallgui(false),
00109     strict_validation(false),
00110     test(),
00111     validcache(false),
00112     version(false),
00113     windowed(false),
00114     with_replay(false),
00115     argc_(argc),
00116     argv_(argv),
00117     all_(),
00118     visible_(),
00119     hidden_()
00120 {
00121     // When adding items don't forget to update doc/man/wesnoth.6
00122     // Options are sorted alphabetically by --long-option.
00123     po::options_description general_opts("General options");
00124     general_opts.add_options()
00125         ("clock", "Adds the option to show a clock for testing the drawing timer.")
00126         ("config-dir", po::value<std::string>(), "sets the path of the user config directory to $HOME/<arg> or My Documents\\My Games\\<arg> for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory.")
00127         ("config-path", "prints the path of the user config directory and exits.")
00128         ("data-dir", po::value<std::string>(), "overrides the data directory with the one specified.")
00129         ("debug,d", "enables additional command mode options in-game.")
00130 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
00131         ("debug-dot-level", po::value<std::string>(), "sets the level of the debug dot files. <arg> should be a comma separated list of levels. These files are used for debugging the widgets especially the for the layout engine. When enabled the engine will produce dot files which can be converted to images with the dot tool. Available levels: size (generate the size info of the widget), state (generate the state info of the widget).")
00132         ("debug-dot-domain", po::value<std::string>(), "sets the domain of the debug dot files. <arg> should be a comma separated list of domains. See --debug-dot-level for more info. Available domains: show (generate the data when the dialog is about to be shown), layout (generate the data during the layout phase - might result in multiple files). The data can also be generated when the F12 is pressed in a dialog.")
00133 #endif
00134         ("editor,e", po::value<std::string>()->implicit_value(std::string()), "starts the in-game map editor directly. If file <arg> is specified, equivalent to -e --load <arg>.")
00135         ("gunzip", po::value<std::string>(), "decompresses a file (<arg>.gz) in gzip format and stores it without the .gz suffix. <arg>.gz will be removed.")
00136         ("gzip", po::value<std::string>(), "compresses a file (<arg>) in gzip format, stores it as <arg>.gz and removes <arg>.")
00137         ("help,h", "prints this message and exits.")
00138         ("language,L", po::value<std::string>(), "uses language <arg> (symbol) this session. Example: --language ang_GB@latin")
00139         ("load,l", po::value<std::string>(), "loads the save <arg> from the standard save game directory. When launching the map editor via -e, the map <arg> is loaded, relative to the current directory. If it is a directory, the editor will start with a load map dialog opened there.")
00140         //disabled until this project continues
00141         //("new-syntax", "enables the new campaign syntax parsing.")
00142         ("nocache", "disables caching of game data.")
00143         ("nodelay", "runs the game without any delays.")
00144         ("nomusic", "runs the game without music.")
00145         ("nosound", "runs the game without sounds and music.")
00146         ("path", "prints the path to the data directory and exits.")
00147         ("rng-seed", po::value<unsigned int>(), "seeds the random number generator with number <arg>. Example: --rng-seed 0")
00148         ("screenshot", po::value<two_strings>()->multitoken(), "takes two arguments: <map> <output>. Saves a screenshot of <map> to <output> without initializing a screen. Editor must be compiled in for this to work.")
00149         ("server,s", po::value<std::string>()->implicit_value(std::string()), "connects to the host <arg> if specified or to the first host in your preferences.")
00150         ("username", po::value<std::string>(), "uses <username> when connecting to a server, ignoring other preferences.")
00151         ("password", po::value<std::string>(), "uses <password> when connecting to a server, ignoring other preferences.")
00152         ("strict-validation", "makes validation errors fatal")
00153         ("test,t", po::value<std::string>()->implicit_value(std::string()), "runs the game in a small test scenario. If specified, scenario <arg> will be used instead.")
00154         ("validcache", "assumes that the cache is valid. (dangerous)")
00155         ("version,v", "prints the game's version number and exits.")
00156         ("with-replay", "replays the file loaded with the --load option.")
00157         ;
00158 
00159     po::options_description campaign_opts("Campaign options");
00160     campaign_opts.add_options()
00161         ("campaign,c", po::value<std::string>()->implicit_value(std::string()), "goes directly to the campaign with id <arg>. A selection menu will appear if no id was specified.")
00162         ("campaign-difficulty", po::value<int>(), "The difficulty of the specified campaign (1 to max). If none specified, the campaign difficulty selection widget will appear.")
00163         ("campaign-scenario", po::value<std::string>(),"The id of the scenario from the specified campaign. The default is the first scenario.")
00164         ;
00165 
00166     po::options_description display_opts("Display options");
00167     display_opts.add_options()
00168         ("bpp", po::value<int>(), "sets BitsPerPixel value. Example: --bpp 32")
00169         ("fps", "displays the number of frames per second the game is currently running at, in a corner of the screen.")
00170         ("fullscreen,f", "runs the game in full screen mode.")
00171         ("max-fps", po::value<int>(), "the maximum fps the game tries to run at. Values should be between 1 and 1000, the default is 50.")
00172         ("new-widgets", "there is a new WIP widget toolkit this switch enables the new toolkit (VERY EXPERIMENTAL don't file bug reports since most are known). Parts of the library are deemed stable and will work without this switch.")
00173         ("resolution,r", po::value<std::string>(), "sets the screen resolution. <arg> should have format XxY. Example: --resolution 800x600")
00174         ("windowed,w", "runs the game in windowed mode.")
00175         ;
00176 
00177     po::options_description logging_opts("Logging options");
00178     logging_opts.add_options()
00179         ("logdomains", po::value<std::string>()->implicit_value(std::string()), "lists defined log domains (only the ones containing <arg> filter if such is provided) and exits.")
00180         ("log-error", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'error'. <arg> should be given as comma separated list of domains, wildcards are allowed. Example: --log-error=network,gui/*,engine/enemies")
00181         ("log-warning", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'warning'. Similar to --log-error.")
00182         ("log-info", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'info'. Similar to --log-error.")
00183         ("log-debug", po::value<std::string>(), "sets the severity level of the specified log domain(s) to 'debug'. Similar to --log-error.")
00184         ;
00185 
00186     po::options_description multiplayer_opts("Multiplayer options");
00187     multiplayer_opts.add_options()
00188         ("multiplayer,m", "Starts a multiplayer game. There are additional options that can be used as explained below:")
00189         ("ai-config", po::value<std::vector<std::string> >()->composing(), "selects a configuration file to load for this side. <arg> should have format side:value")
00190         ("algorithm", po::value<std::vector<std::string> >()->composing(), "selects a non-standard algorithm to be used by the AI controller for this side. <arg> should have format side:value")
00191         ("controller", po::value<std::vector<std::string> >()->composing(), "selects the controller for this side. <arg> should have format side:value")
00192         ("era", po::value<std::string>(), "selects the era to be played in by its id.")
00193         ("exit-at-end", "exit Wesnoth at the end of the scenario.")
00194         ("label", po::value<std::string>(), "sets the label for AIs.") //TODO is the description precise? this option was undocumented before.
00195         ("nogui", "runs the game without the GUI.")
00196         ("parm", po::value<std::vector<std::string> >()->composing(), "sets additional parameters for this side. <arg> should have format side:name:value.")
00197         ("scenario", po::value<std::string>(), "selects a multiplayer scenario. The default scenario is \"multiplayer_The_Freelands\".")
00198         ("side", po::value<std::vector<std::string> >()->composing(), "selects a faction of the current era for this side by id. <arg> should have format side:value.")
00199         ("turns", po::value<std::string>(), "sets the number of turns. The default is \"50\".")
00200         ;
00201 
00202     po::options_description preprocessor_opts("Preprocessor mode options");
00203     preprocessor_opts.add_options()
00204         ("preprocess,p", po::value<two_strings>()->multitoken(), "requires two arguments: <file/folder> <target directory>. Preprocesses a specified file/folder. The preprocessed file(s) will be written in the specified target directory: a plain cfg file and a processed cfg file.")
00205         ("preprocess-defines", po::value<std::string>(), "comma separated list of defines to be used by '--preprocess' command. If 'SKIP_CORE' is in the define list the data/core won't be preprocessed. Example: --preprocess-defines=FOO,BAR")
00206         ("preprocess-input-macros", po::value<std::string>(), "used only by the '--preprocess' command. Specifies source file <arg> that contains [preproc_define]s to be included before preprocessing.")
00207         ("preprocess-output-macros", po::value<std::string>()->implicit_value(std::string()), "used only by the '--preprocess' command. Will output all preprocessed macros in the target file <arg>. If the file is not specified the output will be file '_MACROS_.cfg' in the target directory of preprocess's command.")
00208         ;
00209 
00210     po::options_description proxy_opts("Proxy options");
00211     proxy_opts.add_options()
00212         ("proxy", "enables usage of proxy for network connections.")
00213         ("proxy-address", po::value<std::string>(), "specifies address of the proxy.")
00214         ("proxy-port", po::value<std::string>(), "specifies port of the proxy.")
00215         ("proxy-user", po::value<std::string>(), "specifies username to log in to the proxy.")
00216         ("proxy-password", po::value<std::string>(), "specifies password to log in to the proxy.")
00217         ;
00218 
00219     hidden_.add_options()
00220         ("new-storyscreens", "")
00221         ("smallgui", "")
00222         ;
00223     visible_.add(general_opts).add(campaign_opts).add(display_opts).add(logging_opts).add(multiplayer_opts).add(preprocessor_opts).add(proxy_opts);
00224 
00225     all_.add(visible_).add(hidden_);
00226 
00227     po::positional_options_description positional;
00228     positional.add("data-dir",1);
00229 
00230     po::variables_map vm;
00231     const int parsing_style = po::command_line_style::default_style ^ po::command_line_style::allow_guessing;
00232     po::store(po::command_line_parser(argc_,argv_).options(all_).positional(positional).style(parsing_style).run(),vm);
00233 
00234     if (vm.count("ai-config"))
00235         multiplayer_ai_config = parse_to_uint_string_tuples_(vm["ai-config"].as<std::vector<std::string> >());
00236     if (vm.count("algorithm"))
00237         multiplayer_algorithm = parse_to_uint_string_tuples_(vm["algorithm"].as<std::vector<std::string> >());
00238     if (vm.count("bpp"))
00239         bpp = vm["bpp"].as<int>();
00240     if (vm.count("campaign"))
00241         campaign = vm["campaign"].as<std::string>();
00242     if (vm.count("campaign-difficulty"))
00243         campaign_difficulty = vm["campaign-difficulty"].as<int>();
00244     if (vm.count("campaign-scenario"))
00245         campaign_scenario = vm["campaign-scenario"].as<std::string>();
00246     if (vm.count("clock"))
00247         clock = true;
00248     if (vm.count("config-dir"))
00249         config_dir = vm["config-dir"].as<std::string>();
00250     if (vm.count("config-path"))
00251         config_path = true;
00252     if (vm.count("controller"))
00253         multiplayer_controller = parse_to_uint_string_tuples_(vm["controller"].as<std::vector<std::string> >());
00254     if (vm.count("data-dir"))
00255         data_dir = vm["data-dir"].as<std::string>();
00256     if (vm.count("debug"))
00257         debug = true;
00258 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
00259     if (vm.count("debug-dot-domain")) {
00260         debug_dot_domain = vm["debug-dot-domain"].as<std::string>();
00261     }
00262     if (vm.count("debug-dot-level")) {
00263         debug_dot_level = vm["debug-dot-level"].as<std::string>();
00264     }
00265 #endif
00266     if (vm.count("editor"))
00267         editor = vm["editor"].as<std::string>();
00268     if (vm.count("era"))
00269         multiplayer_era = vm["era"].as<std::string>();
00270     if (vm.count("exit-at-end"))
00271         multiplayer_exit_at_end = true;
00272     if (vm.count("fps"))
00273         fps = true;
00274     if (vm.count("fullscreen"))
00275         fullscreen = true;
00276     if (vm.count("gunzip"))
00277         gunzip = vm["gunzip"].as<std::string>();
00278     if (vm.count("gzip"))
00279         gzip = vm["gzip"].as<std::string>();
00280     if (vm.count("help"))
00281         help = true;
00282     if (vm.count("label"))
00283         multiplayer_label = vm["label"].as<std::string>();
00284     if (vm.count("language"))
00285         language = vm["language"].as<std::string>();
00286     if (vm.count("load"))
00287         load = vm["load"].as<std::string>();
00288     if (vm.count("log-error"))
00289          parse_log_domains_(vm["log-error"].as<std::string>(),0);
00290     if (vm.count("log-warning"))
00291          parse_log_domains_(vm["log-warning"].as<std::string>(),1);
00292     if (vm.count("log-info"))
00293          parse_log_domains_(vm["log-info"].as<std::string>(),2);
00294     if (vm.count("log-debug"))
00295          parse_log_domains_(vm["log-debug"].as<std::string>(),3);
00296     if (vm.count("logdomains"))
00297         logdomains = vm["logdomains"].as<std::string>();
00298     if (vm.count("max-fps"))
00299         max_fps = vm["max-fps"].as<int>();
00300     if (vm.count("multiplayer"))
00301         multiplayer = true;
00302     if (vm.count("new-storyscreens"))
00303         new_storyscreens = true;
00304     if (vm.count("new-syntax"))
00305         new_syntax = true;
00306     if (vm.count("new-widgets"))
00307         new_widgets = true;
00308     if (vm.count("nocache"))
00309         nocache = true;
00310     if (vm.count("nodelay"))
00311         nodelay = true;
00312     if (vm.count("nomusic"))
00313         nomusic = true;
00314     if (vm.count("nosound"))
00315         nosound = true;
00316     if (vm.count("nogui"))
00317         nogui = true;
00318     if (vm.count("parm"))
00319         multiplayer_parm = parse_to_uint_string_string_tuples_(vm["parm"].as<std::vector<std::string> >());
00320     if (vm.count("path"))
00321         path = true;
00322     if (vm.count("preprocess"))
00323     {
00324         preprocess = true;
00325         preprocess_path = vm["preprocess"].as<two_strings>().get<0>();
00326         preprocess_target = vm["preprocess"].as<two_strings>().get<1>();
00327     }
00328     if (vm.count("preprocess-defines"))
00329         preprocess_defines = utils::split(vm["preprocess-defines"].as<std::string>(), ',');
00330     if (vm.count("preprocess-input-macros"))
00331         preprocess_input_macros = vm["preprocess-input-macros"].as<std::string>();
00332     if (vm.count("preprocess-output-macros"))
00333         preprocess_output_macros = vm["preprocess-output-macros"].as<std::string>();
00334     if (vm.count("proxy"))
00335         proxy = true;
00336     if (vm.count("proxy-address"))
00337         proxy_address = vm["proxy-address"].as<std::string>();
00338     if (vm.count("proxy-password"))
00339         proxy_password = vm["proxy-password"].as<std::string>();
00340     if (vm.count("proxy-port"))
00341         proxy_port = vm["proxy-port"].as<std::string>();
00342     if (vm.count("proxy-user"))
00343         proxy_user = vm["proxy-user"].as<std::string>();
00344     if (vm.count("resolution"))
00345         parse_resolution_(vm["resolution"].as<std::string>());
00346     if (vm.count("rng-seed"))
00347         rng_seed = vm["rng-seed"].as<unsigned int>();
00348     if (vm.count("scenario"))
00349         multiplayer_scenario = vm["scenario"].as<std::string>();
00350     if (vm.count("screenshot"))
00351     {
00352         screenshot = true;
00353         screenshot_map_file = vm["screenshot"].as<two_strings>().get<0>();
00354         screenshot_output_file = vm["screenshot"].as<two_strings>().get<1>();
00355     }
00356     if (vm.count("server"))
00357         server = vm["server"].as<std::string>();
00358     if (vm.count("username"))
00359         username = vm["username"].as<std::string>();
00360     if (vm.count("password"))
00361         password = vm["password"].as<std::string>();
00362     if (vm.count("side"))
00363         multiplayer_side = parse_to_uint_string_tuples_(vm["side"].as<std::vector<std::string> >());
00364     if (vm.count("test"))
00365         test = vm["test"].as<std::string>();
00366     if (vm.count("turns"))
00367         multiplayer_turns = vm["turns"].as<std::string>();
00368     if (vm.count("smallgui"))
00369         smallgui = true;
00370     if (vm.count("strict-validation"))
00371         strict_validation = true;
00372     if (vm.count("validcache"))
00373         validcache = true;
00374     if (vm.count("version"))
00375         version = true;
00376     if (vm.count("windowed"))
00377         windowed = true;
00378     if (vm.count("with-replay"))
00379         with_replay = true;
00380 }
00381 
00382 void commandline_options::parse_log_domains_(const std::string &domains_string, const int severity)
00383 {
00384     const std::vector<std::string> domains = utils::split(domains_string, ',');
00385     foreach (const std::string& domain, domains)
00386     {
00387         if (!log)
00388             log = std::vector<boost::tuple<int, std::string> >();
00389         log->push_back(boost::tuple<int, std::string>(severity,domain));
00390     }
00391 }
00392 
00393 void commandline_options::parse_resolution_ ( const std::string& resolution_string )
00394 {
00395     const std::vector<std::string> tokens = utils::split(resolution_string, 'x');
00396     if (tokens.size() != 2)
00397         {} // TODO throw a meaningful exception
00398     int xres = lexical_cast<int>(tokens[0]);
00399     int yres = lexical_cast<int>(tokens[1]);
00400     resolution = boost::tuple<int,int>(xres,yres);
00401 }
00402 
00403 std::vector<boost::tuple<unsigned int,std::string> > commandline_options::parse_to_uint_string_tuples_(const std::vector<std::string> &strings, char separator)
00404 {
00405     std::vector<boost::tuple<unsigned int,std::string> > vec;
00406     boost::tuple<unsigned int,std::string> elem;
00407     foreach(const std::string &s, strings)
00408     {
00409         const std::vector<std::string> tokens = utils::split(s, separator);
00410         if (tokens.size()!=2)
00411         {
00412              //TODO throw a meaningful exception
00413         }
00414         elem.get<0>() = lexical_cast<unsigned int>(tokens[0]);
00415             //TODO catch exception and pack in meaningful something
00416         elem.get<1>() = tokens[1];
00417         vec.push_back(elem);
00418     }
00419     return vec;
00420 }
00421 
00422 std::vector<boost::tuple<unsigned int,std::string,std::string> > commandline_options::parse_to_uint_string_string_tuples_(const std::vector<std::string> &strings, char separator)
00423 {
00424     std::vector<boost::tuple<unsigned int,std::string,std::string> > vec;
00425     boost::tuple<unsigned int,std::string,std::string> elem;
00426     foreach(const std::string &s, strings)
00427     {
00428         const std::vector<std::string> tokens = utils::split(s, separator);
00429         if (tokens.size()!=3)
00430         {
00431              //TODO throw a meaningful exception
00432         }
00433         elem.get<0>() = lexical_cast<unsigned int>(tokens[0]);
00434             //TODO catch exception and pack in meaningful something
00435         elem.get<1>() = tokens[1];
00436         elem.get<2>() = tokens[2];
00437         vec.push_back(elem);
00438     }
00439     return vec;
00440 }
00441 
00442 std::ostream& operator<<(std::ostream &os, const commandline_options& cmdline_opts)
00443 {
00444     os << "Usage: " << cmdline_opts.argv_[0] << " [<options>] [<data-directory>]\n";
00445     os << cmdline_opts.visible_;
00446     return os;
00447 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:32 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs