1 /*
2    Copyright (C) 2011 - 2018 by Lukasz Dobrogowski <lukasz.dobrogowski@gmail.com>
3    Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY.
11 
12    See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include <boost/optional.hpp>           // for optional
18 #include <boost/program_options/options_description.hpp>
19 #include <iosfwd>                       // for ostream
20 #include <string>                       // for string
21 #include <tuple>
22 #include <vector>                       // for vector
23 
24 class bad_commandline_resolution : public boost::program_options::error
25 {
26 public:
27     bad_commandline_resolution(const std::string& resolution);
28 };
29 
30 class bad_commandline_tuple : public boost::program_options::error
31 {
32 public:
33 	bad_commandline_tuple(const std::string& str,
34 						  const std::string& expected_format);
35 };
36 
37 class config;
38 
39 class commandline_options
40 {
41 	/// To be used for printing help to the commandline.
42 	friend std::ostream& operator<<(std::ostream &os, const commandline_options& cmdline_opts);
43 
44 public:
45 	commandline_options(const std::vector<std::string>& args);
46 
47 	config to_config() const; /* Used by lua scrips. Not all of the options need to be exposed here, just those exposed to lua */
48 
49 	/// Non-empty if --bunzip2 was given on the command line. Uncompresses a .bz2 file and exits.
50 	boost::optional<std::string> bunzip2;
51 	/// Non-empty if --bzip2 was given on the command line. Compresses a file to .bz2 and exits.
52 	boost::optional<std::string> bzip2;
53 	/// Non-empty if --campaign was given on the command line. ID of the campaign we want to start.
54 	boost::optional<std::string> campaign;
55 	/// Non-empty if --campaign-difficulty was given on the command line. Numerical difficulty of the campaign to be played. Dependent on --campaign.
56 	boost::optional<int> campaign_difficulty;
57 	/// Non-empty if --campaign-scenario was given on the command line. Chooses starting scenario in the campaign to be played. Dependent on --campaign.
58 	boost::optional<std::string> campaign_scenario;
59 	/// True if --skip-story was given on the command line. Skips [story] and [message]s through the end of the "start" event. Dependent on --campaign.
60 	bool campaign_skip_story;
61 	/// True if --clock was given on the command line. Enables
62 	bool clock;
63 	/// Non-empty if --core was given on the command line. Chooses the core to be loaded.
64 	boost::optional<std::string> core_id;
65 	/// True if --data-path was given on the command line. Prints path to data directory and exits.
66 	bool data_path;
67 	/// Non-empty if --data-dir was given on the command line. Sets the config dir to the specified one.
68 	boost::optional<std::string> data_dir;
69 	/// True if --debug was given on the command line. Enables debug mode.
70 	bool debug;
71 	/// True if --debug-lua was given in the commandline. Enables some Lua debugging mechanisms.
72 	bool debug_lua;
73 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
74 	/// Non-empty if --debug-dot-domain was given on the command line.
75 	boost::optional<std::string> debug_dot_domain;
76 	/// Non-empty if --debug-dot-level was given on the command line.
77 	boost::optional<std::string> debug_dot_level;
78 #endif
79 	/// Non-empty if --editor was given on the command line. Goes directly into editor. If string is longer than 0, it contains path to the file to edit.
80 	boost::optional<std::string> editor;
81 	/// True if --fps was given on the command line. Shows number of fps.
82 	bool fps;
83 	/// True if --fullscreen was given on the command line. Starts Wesnoth in fullscreen mode.
84 	bool fullscreen;
85 	/// Non-empty if --gunzip was given on the command line. Uncompresses a .gz file and exits.
86 	boost::optional<std::string> gunzip;
87 	/// Non-empty if --gzip was given on the command line. Compresses a file to .gz and exits.
88 	boost::optional<std::string> gzip;
89 	/// True if --help was given on the command line. Prints help and exits.
90 	bool help;
91 	/// Non-empty if --language was given on the command line. Sets the language for this session.
92 	boost::optional<std::string> language;
93 	/// Contains parsed arguments of --log-* (e.g. --log-debug).
94 	/// Vector of pairs (severity, log domain).
95 	boost::optional<std::vector<std::pair<int, std::string>> > log;
96 	/// Non-empty if --log-strict was given
97 	boost::optional<int> log_strict_level;
98 	/// Non-empty if --load was given on the command line. Savegame specified to load after start.
99 	boost::optional<std::string> load;
100 	/// Non-empty if --logdomains was given on the command line. Prints possible logdomains filtered by given string and exits.
101 	boost::optional<std::string> logdomains;
102 	/// True if --log-precise was given on the command line. Shows timestamps in log with more precision.
103 	bool log_precise_timestamps;
104 	/// True if --multiplayer was given on the command line. Goes directly into multiplayer mode.
105 	bool multiplayer;
106 	/// Non-empty if --ai-config was given on the command line. Vector of pairs (side number, value). Dependent on --multiplayer.
107 	boost::optional<std::vector<std::pair<unsigned int, std::string>> > multiplayer_ai_config;
108 	/// Non-empty if --algorithm was given on the command line. Vector of pairs (side number, value). Dependent on --multiplayer.
109 	boost::optional<std::vector<std::pair<unsigned int, std::string>> > multiplayer_algorithm;
110 	/// Non-empty if --controller was given on the command line. Vector of pairs (side number, controller). Dependent on --multiplayer.
111 	boost::optional<std::vector<std::pair<unsigned int, std::string>> > multiplayer_controller;
112 	/// Non-empty if --era was given on the command line. Dependent on --multiplayer.
113 	boost::optional<std::string> multiplayer_era;
114 	/// True if --exit-at-and was given on the command line. Dependent on --multiplayer.
115 	bool multiplayer_exit_at_end;
116 	/// True if --ignore-map-settings was given at the command line.  Do not use map settings.
117 	bool multiplayer_ignore_map_settings;
118 	/// Non-empty if --label was given on the command line. Dependent on --multiplayer.
119 	boost::optional<std::string> multiplayer_label;
120 	/// Non-empty if --parm was given on the command line. Vector of pairs (side number, parm name, parm value). Dependent on --multiplayer.
121 	boost::optional<std::vector<std::tuple<unsigned int, std::string, std::string>> > multiplayer_parm;
122 	/// Repeats specified by --multiplayer-repeat option. Repeats a multiplayer game after it is finished. Dependent on --multiplayer.
123 	boost::optional<unsigned int> multiplayer_repeat;
124 	/// Non-empty if --scenario was given on the command line. Dependent on --multiplayer.
125 	boost::optional<std::string> multiplayer_scenario;
126 	/// Non-empty if --side was given on the command line. Vector of pairs (side number, faction id). Dependent on --multiplayer.
127 	boost::optional<std::vector<std::pair<unsigned int, std::string>> > multiplayer_side;
128 	/// Non-empty if --turns was given on the command line. Dependent on --multiplayer.
129 	boost::optional<std::string> multiplayer_turns;
130 	/// Max FPS specified by --max-fps option.
131 	boost::optional<int> max_fps;
132 	/// True if --noaddons was given on the command line. Disables the loading of all add-ons.
133 	bool noaddons;
134 	/// True if --nocache was given on the command line. Disables cache usage.
135 	bool nocache;
136 	/// True if --nodelay was given on the command line.
137 	bool nodelay;
138 	/// True if --nogui was given on the command line. Disables GUI.
139 	bool nogui;
140 	/// True if --nomusic was given on the command line. Disables music.
141 	bool nomusic;
142 	/// True if --nosound was given on the command line. Disables sound.
143 	bool nosound;
144 	/// True if --new-widgets was given on the command line. Hidden option to enable the new widget toolkit.
145 	bool new_widgets;
146 	/// True if --preprocess was given on the command line. Starts Wesnoth in preprocessor-only mode.
147 	bool preprocess;
148 	/// Defines that were given to the --preprocess option.
149 	boost::optional<std::vector<std::string>> preprocess_defines;
150 	/// Non-empty if --preprocess-input-macros was given on the command line. Specifies a file that contains [preproc_define]s to be included before preprocessing. Dependent on --preprocess.
151 	boost::optional<std::string> preprocess_input_macros;
152 	/// Non-empty if --preprocess-output-macros was given on the command line. Outputs all preprocessed macros to the specified file. Dependent on --preprocess.
153 	boost::optional<std::string> preprocess_output_macros;
154 	/// Path to parse that was given to the --preprocess option.
155 	boost::optional<std::string> preprocess_path;
156 	/// Target (output) path that was given to the --preprocess option.
157 	boost::optional<std::string> preprocess_target;
158 	/// Pair of AxB values specified after --resolution. Changes Wesnoth resolution.
159 	boost::optional<std::pair<int,int>> resolution;
160 	/// RNG seed specified by --rng-seed option. Initializes RNG with given seed.
161 	boost::optional<unsigned int> rng_seed;
162 	/// Non-empty if --server was given on the command line.  Connects Wesnoth to specified server. If no server was specified afterwards, contains an empty string.
163 	boost::optional<std::string> server;
164 	/// Non-empty if --username was given on the command line. Forces Wesnoth to use this network username.
165 	boost::optional<std::string> username;
166 	/// Non-empty if --password was given on the command line. Forces Wesnoth to use this network password.
167 	boost::optional<std::string> password;
168 	/// Image path to render. First parameter after --render-image
169 	boost::optional<std::string> render_image;
170 	/// Output file to put rendered image path in. Optional second parameter after --render-image
171 	boost::optional<std::string> render_image_dst;
172 	/// True if --screenshot was given on the command line. Starts Wesnoth in screenshot mode.
173 	bool screenshot;
174 	/// Map file to make a screenshot of. First parameter given after --screenshot.
175 	boost::optional<std::string> screenshot_map_file;
176 	/// Output file to put screenshot in. Second parameter given after --screenshot.
177 	boost::optional<std::string> screenshot_output_file;
178 	/// File to load lua script from.
179 	boost::optional<std::string> script_file;
180 	/// File to load a lua plugin (similar to a script) from. Experimental / may replace script.
181 	boost::optional<std::string> plugin_file;
182 	/// Whether to load the "package" package for the scripting environment. (This allows to load arbitrary lua packages, and gives untrusted lua the same permissions as wesnoth executable)
183 	bool script_unsafe_mode;
184 	/// True if --strict-validation was given on the command line. Makes Wesnoth trust validation errors as fatal WML errors and create WML exception, if so.
185 	bool strict_validation;
186 	/// Non-empty if --test was given on the command line. Goes directly into test mode, into a scenario, if specified.
187 	boost::optional<std::string> test;
188 	/// Non-empty if --unit was given on the command line. Goes directly into unit test mode, into a scenario, if specified.
189 	std::vector<std::string> unit_test;
190 	/// True if --unit is used and --showgui is not present.
191 	bool headless_unit_test;
192 	/// True if --noreplaycheck was given on the command line. Dependent on --unit.
193 	bool noreplaycheck;
194 	/// True if --mp-test was given on the command line.
195 	bool mptest;
196 	/// True if --userconfig-path was given on the command line. Prints path to user config directory and exits.
197 	bool userconfig_path;
198 	/// Non-empty if --userconfig-dir was given on the command line. Sets the user config dir to the specified one.
199 	boost::optional<std::string> userconfig_dir;
200 	/// True if --userdata-path was given on the command line. Prints path to user data directory and exits.
201 	bool userdata_path;
202 	/// Non-empty if --userdata-dir was given on the command line. Sets the user data dir to the specified one.
203 	boost::optional<std::string> userdata_dir;
204 	/// True if --validcache was given on the command line. Makes Wesnoth assume the cache is valid.
205 	bool validcache;
206 	/// True if --version was given on the command line. Prints version and exits.
207 	bool version;
208 	/// True if --report was given on the command line. Prints a bug report-style info dump and exits.
209 	bool report;
210 	/// True if --windowed was given on the command line. Starts Wesnoth in windowed mode.
211 	bool windowed;
212 	/// True if --with-replay was given on the command line. Shows replay of the loaded file.
213 	bool with_replay;
214 	/// Non-empty if --all-translations or --translations-over is given on the command line.
215 	boost::optional<unsigned int> translation_percent;
216 private:
217 	void parse_log_domains_(const std::string &domains_string, const int severity);
218 	void parse_log_strictness (const std::string &severity);
219 	void parse_resolution_ (const std::string &resolution_string);
220 	/// A helper function splitting vector of strings of format unsigned int:string to vector of tuples (unsigned int,string)
221 	std::vector<std::pair<unsigned int,std::string>> parse_to_uint_string_tuples_(const std::vector<std::string> &strings, char separator = ':');
222 	/// A helper function splitting vector of strings of format unsigned int:string:string to vector of tuples (unsigned int,string,string)
223 	std::vector<std::tuple<unsigned int,std::string,std::string>> parse_to_uint_string_string_tuples_(const std::vector<std::string> &strings, char separator = ':');
224 	std::vector<std::string> args_;
225 	std::string args0_;
226 	boost::program_options::options_description all_;
227 	boost::program_options::options_description visible_;
228 	boost::program_options::options_description hidden_;
229 };
230