16 #include "addon/manager.hpp" 59 #include "widgets/button.hpp" 74 #include <boost/iostreams/categories.hpp> 75 #include <boost/iostreams/copy.hpp> 76 #include <boost/iostreams/filter/bzip2.hpp> 80 #pragma warning(disable : 4456) 81 #pragma warning(disable : 4458) 84 #include <boost/iostreams/filter/gzip.hpp> 90 #include <boost/iostreams/filtering_stream.hpp> 91 #include <boost/program_options/errors.hpp> 113 #ifdef INADDR_BROADCAST 114 #undef INADDR_BROADCAST 125 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS 129 class end_level_exception;
136 #define LOG_CONFIG LOG_STREAM(info, log_config) 138 #define LOG_GENERAL LOG_STREAM(info, lg::general()) 141 #define LOG_PREPROC LOG_STREAM(info, log_preprocessor) 148 LOG_GENERAL <<
"exiting with code " << res <<
"\n";
153 template<
typename filter>
154 static void encode(
const std::string& input_file,
const std::string& output_file)
157 std::ifstream ifile(input_file.c_str(),
std::ios_base::in | std::ios_base::binary);
161 std::cerr <<
"Input file " << input_file
162 <<
" is not good for reading. Exiting to prevent bzip2 from segfaulting\n";
166 std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
168 boost::iostreams::filtering_stream<boost::iostreams::output> stream;
169 stream.push(filter());
172 boost::iostreams::copy(ifile, stream);
177 std::cerr <<
"IO error: " << e.
what() <<
"\n";
181 template<
typename filter>
182 static void decode(
const std::string& input_file,
const std::string& output_file)
185 std::ofstream ofile(output_file.c_str(), std::ios_base::out | std::ios_base::binary);
186 std::ifstream ifile(input_file.c_str(),
std::ios_base::in | std::ios_base::binary);
188 boost::iostreams::filtering_stream<boost::iostreams::input> stream;
189 stream.push(filter());
192 boost::iostreams::copy(stream, ofile);
197 std::cerr <<
"IO error: " << e.
what() <<
"\n";
201 static void gzip_encode(
const std::string& input_file,
const std::string& output_file)
203 encode<boost::iostreams::gzip_compressor>(input_file, output_file);
206 static void gzip_decode(
const std::string& input_file,
const std::string& output_file)
208 decode<boost::iostreams::gzip_decompressor>(input_file, output_file);
211 static void bzip2_encode(
const std::string& input_file,
const std::string& output_file)
213 encode<boost::iostreams::bzip2_compressor>(input_file, output_file);
216 static void bzip2_decode(
const std::string& input_file,
const std::string& output_file)
218 decode<boost::iostreams::bzip2_decompressor>(input_file, output_file);
228 std::cerr <<
"please specify an existing file. File " << file <<
" doesn't exist.\n";
232 std::cerr << SDL_GetTicks() <<
" Reading cached defines from: " << file <<
"\n";
240 std::cerr <<
"Caught a config error while parsing file '" << file <<
"':\n" << e.
message << std::endl;
248 input_macros[def.first] = def.second;
252 std::cerr << SDL_GetTicks() <<
" Read " << read <<
" defines.\n";
258 uint32_t startTime = SDL_GetTicks();
261 bool skipCore =
false;
262 bool skipTerrainGFX =
false;
271 std::cerr <<
"empty define supplied\n";
275 LOG_PREPROC <<
"adding define: " << define <<
'\n';
278 if(define ==
"SKIP_CORE") {
279 std::cerr <<
"'SKIP_CORE' defined.\n";
281 }
else if(define ==
"NO_TERRAIN_GFX") {
282 std::cerr <<
"'NO_TERRAIN_GFX' defined." << std::endl;
283 skipTerrainGFX =
true;
291 std::cerr <<
"added " << defines_map.size() <<
" defines.\n";
294 if(skipCore ==
false) {
295 std::cerr <<
"preprocessing common macros from 'data/core' ...\n";
300 if(skipTerrainGFX ==
false) {
304 std::cerr <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" 'data/core' defines.\n";
306 std::cerr <<
"skipped 'data/core'\n";
310 std::cerr <<
"preprocessing specified resource: " << resourceToProcess <<
" ...\n";
313 std::cerr <<
"acquired " << (defines_map.size() - input_macros.size()) <<
" total defines.\n";
316 std::string outputFileName =
"_MACROS_.cfg";
321 std::string outputPath = targetDir +
"/" + outputFileName;
323 std::cerr <<
"writing '" << outputPath <<
"' with " << defines_map.size() <<
" defines.\n";
329 for(
auto& define_pair : defines_map) {
330 define_pair.second.write(writer, define_pair.first);
333 std::cerr <<
"couldn't open the file.\n";
337 std::cerr <<
"preprocessing finished. Took " << SDL_GetTicks() - startTime <<
" ticks.\n";
345 for(
const std::string& define : defines) {
347 std::cerr <<
"empty define supplied\n";
351 LOG_PREPROC <<
"adding define: " << define <<
'\n';
354 std::cout <<
"Validating " << file <<
" against schema " << validator.
name_ << std::endl;
358 read(result, *stream, &validator);
360 std::cout <<
"validation failed\n";
362 std::cout <<
"validation succeeded\n";
372 if(cmdline_opts.
log) {
373 for(
const auto& log_pair : *cmdline_opts.
log) {
374 const std::string log_domain = log_pair.second;
375 const int severity = log_pair.first;
377 std::cerr <<
"unknown log domain: " << log_domain <<
'\n';
402 const std::string datadir = *cmdline_opts.
data_dir;
405 if(datadir.c_str()[1] ==
':') {
407 if(datadir[0] ==
'/') {
444 const std::string input_file(*cmdline_opts.
gunzip);
446 std::cerr <<
"file '" << input_file <<
"'isn't a .gz file\n";
450 const std::string output_file(input_file, 0, input_file.length() - 3);
455 const std::string input_file(*cmdline_opts.
bunzip2);
457 std::cerr <<
"file '" << input_file <<
"'isn't a .bz2 file\n";
461 const std::string output_file(input_file, 0, input_file.length() - 4);
465 if(cmdline_opts.
gzip) {
466 const std::string input_file(*cmdline_opts.
gzip);
467 const std::string output_file(*cmdline_opts.
gzip +
".gz");
471 if(cmdline_opts.
bzip2) {
472 const std::string input_file(*cmdline_opts.
bzip2);
473 const std::string output_file(*cmdline_opts.
bzip2 +
".bz2");
477 if(cmdline_opts.
help) {
478 std::cout << cmdline_opts;
496 SDL_setenv(
"SDL_VIDEODRIVER",
"dummy", 1);
530 std::ifstream in_left(cmdline_opts.
diff_left);
531 std::ifstream in_right(cmdline_opts.
diff_right);
533 read(right, in_right);
534 std::ostream* os = &std::cout;
540 if(os != &std::cout)
delete os;
546 std::ifstream in_base(cmdline_opts.
diff_left);
547 std::ifstream in_diff(cmdline_opts.
diff_right);
551 std::ostream* os = &std::cout;
557 if(os != &std::cout)
delete os;
569 std::string schema_path;
584 std::cerr <<
"That --preprocess-* option is only supported when using --preprocess or --validate-wml.\n";
601 #if defined _WIN32 || defined __APPLE__ 602 setlocale(LC_ALL,
"English");
604 std::setlocale(LC_ALL,
"C");
627 <<
"An error at this point during initialization usually indicates that the data\n" 628 <<
"directory above was not correctly set or detected. Try passing the correct path\n" 629 <<
"in the command line with the --data-dir switch or as the only argument.\n";
638 static bool first_time =
true;
657 if(_controlfp_s(&f_control, 0, 0) == 0) {
659 uint32_t rounding_mode = f_control & _MCW_RC;
661 if(rounding_mode != _RC_NEAR) {
662 std::cerr <<
"Floating point rounding mode is currently '" 663 << ((rounding_mode == _RC_CHOP)
665 : (rounding_mode == _RC_UP)
667 : (rounding_mode == _RC_DOWN)
669 : (rounding_mode == _RC_NEAR) ?
"near" :
"unknown")
670 <<
"' setting to 'near'\n";
672 if(_controlfp_s(&unused, _RC_NEAR, _MCW_RC)) {
673 std::cerr <<
"failed to set floating point rounding type to 'near'\n";
678 uint32_t precision_mode = f_control & _MCW_PC;
679 if(precision_mode != _PC_53) {
680 std::cerr <<
"Floating point precision mode is currently '" 681 << ((precision_mode == _PC_53)
683 : (precision_mode == _PC_24)
685 : (precision_mode == _PC_64) ?
"double extended" :
"unknown")
686 <<
"' setting to 'double'\n";
688 if(_controlfp_s(&unused, _PC_53, _MCW_PC)) {
689 std::cerr <<
"failed to set floating point precision type to 'double'\n";
695 std::cerr <<
"_controlfp_s failed.\n";
701 switch(fegetround()) {
705 std::cerr <<
"Floating point precision mode is currently 'downward'";
708 std::cerr <<
"Floating point precision mode is currently 'toward-zero'";
711 std::cerr <<
"Floating point precision mode is currently 'upward'";
714 std::cerr <<
"Floating point precision mode is currently 'unknown'";
717 std::cerr <<
"setting to 'nearest'";
718 fesetround(FE_TONEAREST);
730 srand(std::time(
nullptr));
739 std::cerr <<
"Press enter to continue..." << std::endl;
747 const auto game = std::make_unique<game_launcher>(cmdline_opts);
748 const int start_ticks = SDL_GetTicks();
759 std::cerr <<
"could not initialize fonts\n";
765 res =
game->init_language();
767 std::cerr <<
"could not initialize the language\n";
771 res =
game->init_video();
773 std::cerr <<
"could not initialize display\n";
781 #if(defined(_X11) && !defined(__APPLE__)) || defined(_WIN32) 782 SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
800 std::cerr <<
"could not initialize game config\n";
808 std::cerr <<
"could not re-initialize fonts for the current language\n";
823 LOG_CONFIG <<
"time elapsed: " << (SDL_GetTicks() - start_ticks) <<
" ms\n";
842 if(!
game->has_load_data()) {
849 config title_music_config;
851 title_music_config[
"append"] =
true;
852 title_music_config[
"immediate"] =
true;
866 return static_cast<int>(
game->unit_test());
869 if(
game->play_test() ==
false) {
873 if(
game->play_screenshot_mode() ==
false) {
877 if(
game->play_render_image_mode() ==
false) {
882 if(
game->goto_campaign() ==
false) {
883 if(
game->jump_to_campaign_id().empty())
891 if(
game->goto_multiplayer() ==
false) {
896 if(
game->play_multiplayer_commandline() ==
false) {
900 if(
game->goto_editor() ==
false) {
909 if(
game->has_load_data() &&
game->load_game()) {
943 game->start_editor();
946 gui2::dialogs::end_credits::display();
965 #define error_exit(res) \ 967 if(lg::using_own_console()) { \ 968 std::cerr << "Press enter to continue..." << std::endl; \ 974 #define error_exit(res) return res 981 int main(
int argc,
char** argv)
985 assert(!args.empty());
988 bool nobanner =
false;
989 for(
const auto& arg : args) {
990 if(arg ==
"--nobanner") {
997 bool log_redirect =
true, native_console_implied =
false;
999 std::optional<bool> native_console_force;
1009 for(
const auto& arg : args) {
1011 static const std::set<std::string> wincon_switches = {
1012 "--wconsole",
"-h",
"--help",
"-v",
"--version",
"-R",
"--report",
"--logdomains",
1013 "--data-path",
"--userdata-path",
"--userconfig-path",
1019 static const std::set<std::string> wincon_arg_switches = {
1020 "-D",
"--diff",
"-p",
"--preprocess",
"-P",
"--patch",
"--render-image",
1021 "--screenshot",
"-V",
"--validate",
"--validate-schema",
1024 auto switch_matches_arg = [&arg](
const std::string&
sw) {
1025 const auto pos = arg.find(
'=');
1026 return pos == std::string::npos ? arg ==
sw : arg.substr(0, pos) ==
sw;
1029 if(wincon_switches.find(arg) != wincon_switches.end() ||
1030 std::find_if(wincon_arg_switches.begin(), wincon_arg_switches.end(), switch_matches_arg) != wincon_arg_switches.end()) {
1031 native_console_implied =
true;
1034 if(arg ==
"--wnoconsole") {
1035 native_console_force =
false;
1036 }
else if(arg ==
"--wconsole") {
1037 native_console_force =
true;
1038 }
else if(arg ==
"--wnoredirect") {
1039 log_redirect =
false;
1043 if(native_console_force.value_or(native_console_implied)) {
1049 if(SDL_Init(SDL_INIT_TIMER) < 0) {
1050 fprintf(stderr,
"Couldn't initialize SDL: %s\n", SDL_GetError());
1055 struct sigaction terminate_handler;
1057 terminate_handler.sa_flags = 0;
1059 sigemptyset(&terminate_handler.sa_mask);
1060 sigaction(SIGTERM, &terminate_handler,
nullptr);
1061 sigaction(SIGINT, &terminate_handler,
nullptr);
1066 #if defined(__APPLE__) && !defined(__IPHONEOS__) 1067 SDL_EventState(SDL_FINGERMOTION, SDL_DISABLE);
1068 SDL_EventState(SDL_FINGERDOWN, SDL_DISABLE);
1069 SDL_EventState(SDL_FINGERUP, SDL_DISABLE);
1075 SDL_StartTextInput();
1080 const std::time_t
t = std::time(
nullptr);
1081 std::cerr <<
"Started on " << ctime(&t) <<
"\n";
1085 if(!exe_dir.empty()) {
1088 std::string auto_dir;
1107 if(!auto_dir.empty()) {
1108 if(!nobanner) std::cerr <<
"Automatically found a possible data directory at " <<
filesystem::sanitize_path(auto_dir) <<
'\n';
1115 }
catch(
const boost::program_options::error&
e) {
1116 std::cerr <<
"Error in command line: " << e.what() <<
'\n';
1119 std::cerr <<
"Could not initialize video.\n\n" << e.
what() <<
"\n\nExiting.\n";
1122 std::cerr <<
"Could not initialize fonts.\n\n" << e.
what() <<
"\n\nExiting.\n";
1125 std::cerr << e.
message <<
"\n";
1128 std::cerr <<
"Could not create button: Image could not be found\n";
1133 std::cerr <<
"caught return_to_play_side_exception, please report this bug (quitting)\n";
1135 std::cerr <<
"caught quit_game_exception (quitting)\n";
1137 std::cerr <<
"WML exception:\nUser message: " << e.
user_message <<
"\nDev message: " << e.
dev_message <<
'\n';
1140 std::cerr << e.
what() <<
"\n\nGame will be aborted.\n";
1143 std::cerr << e.
what();
1148 }
catch(
const std::bad_alloc&) {
1149 std::cerr <<
"Ran out of memory. Aborted.\n";
1151 #if !defined(NO_CATCH_AT_GAME_END) 1152 }
catch(
const std::exception& e) {
1154 std::cerr <<
"Caught general '" <<
typeid(
e).name() <<
"' exception:\n" << e.what() << std::endl;
1156 }
catch(
const std::string& e) {
1157 std::cerr <<
"Caught a string thrown as an exception:\n" << e << std::endl;
1159 }
catch(
const char* e) {
1160 std::cerr <<
"Caught a string thrown as an exception:\n" << e << std::endl;
1167 std::cerr <<
"Caught unspecified general exception. Terminating." << std::endl;
bool log_precise_timestamps
True if –log-precise was given on the command line.
std::optional< std::string > preprocess_path
Path to parse that was given to the –preprocess option.
static void wesnoth_terminate_handler(int)
std::vector< Reg > reg_vec
std::optional< std::string > output_file
Output filename for WML diff or preprocessing.
void set_callback(const std::string &name, callback_function)
std::optional< std::string > preprocess_output_macros
Non-empty if –preprocess-output-macros was given on the command line.
static int handle_validate_command(const std::string &file, abstract_validator &validator, const std::vector< std::string > &defines)
void bind_textdomain(const char *domain, const char *directory, const char *)
const_all_children_itors all_children_range() const
In-order iteration over all children.
bool using_own_console()
Returns true if a console was allocated by the Wesnoth process.
void write(const config &cfg)
bool play_multiplayer(mp_mode mode)
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
std::string library_versions_report()
Produce a plain-text report of library versions suitable for stdout/stderr.
static void bzip2_encode(const std::string &input_file, const std::string &output_file)
static void bzip2_decode(const std::string &input_file, const std::string &output_file)
Interfaces for manipulating version numbers of engine, add-ons, etc.
static lg::log_domain log_preprocessor("preprocessor")
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
std::string optional_features_report()
Produce a plain-text report of features suitable for stdout/stderr.
bool noaddons
True if –noaddons was given on the command line.
Exception used to escape form the ai or ui code to playsingle_controller::play_side.
void set_user_data_dir(std::string newprefdir)
static bool file_exists(const bfs::path &fpath)
child_itors child_range(config_key_type key)
bool userdata_path
True if –userdata-path was given on the command line.
static void gzip_decode(const std::string &input_file, const std::string &output_file)
static void progress(loading_stage stage=loading_stage::none)
filesystem::scoped_istream istream_file(const std::string &fname, bool treat_failure_as_error)
std::string user_message
The message for the user explaining what went wrong.
This class implements the title screen.
std::optional< std::string > preprocess_target
Target (output) path that was given to the –preprocess option.
std::optional< std::string > preprocess_input_macros
Non-empty if –preprocess-input-macros was given on the command line.
Type that can be thrown as an exception to quit to desktop.
std::optional< std::string > userconfig_dir
Non-empty if –userconfig-dir was given on the command line.
void preprocess_resource(const std::string &res_name, preproc_map *defines_map, bool write_cfg, bool write_plain_cfg, const std::string &parent_directory)
std::vector< std::string > unit_test
Non-empty if –unit was given on the command line.
void early_log_file_setup(bool disable)
Sets up the initial temporary log file.
Don't reload if the previous defines equal the new defines.
static void safe_exit(int res)
std::string normalize_path(const std::string &fpath, bool normalize_separators, bool resolve_dot_entries)
Returns the absolute path of a file.
Contains the exception interfaces used to signal completion of a scenario, campaign or turn...
bool show(const unsigned auto_close_time=0)
Shows the window.
Definitions for the interface to Wesnoth Markup Language (WML).
static void decode(const std::string &input_file, const std::string &output_file)
std::string diff_left
Files for diffing or patching.
filesystem::scoped_ostream ostream_file(const std::string &fname, std::ios_base::openmode mode, bool create_directory)
bool preprocess
True if –preprocess was given on the command line.
config get_diff(const config &c) const
A function to get the differences between this object, and 'c', as another config object...
One of the realizations of serialization/validator.hpp abstract validator.
unsigned in
If equal to search_counter, the node is off the list.
Used in parsing config file.
static void warn_early_init_failure()
Print an alert and instructions to stderr about early initialization errors.
bool report
True if –report was given on the command line.
std::optional< std::string > gzip
Non-empty if –gzip was given on the command line.
void read(config &cfg, std::istream &in, abstract_validator *validator)
Class for writing a config out to a file in pieces.
bool simple_version
True if –simple-version was given on the command line.
std::string get_user_data_dir()
std::optional< unsigned int > rng_seed
RNG seed specified by –rng-seed option.
std::optional< std::vector< std::pair< int, std::string > > > log
Contains parsed arguments of –log-* (e.g.
std::string get_intl_dir()
static lg::log_domain log_config("config")
bool strict_validation_enabled
void init()
Initializes the GUI subsystems.
const game_config_view & game_config() const
std::optional< std::string > bunzip2
Non-empty if –bunzip2 was given on the command line.
void enable_native_console_output()
Switches to using a native console instead of log file redirection.
bool is_directory(const std::string &fname)
Returns true if the given file is a directory.
std::unique_ptr< std::istream > scoped_istream
std::string build_arch()
Obtain the processor architecture for this build.
void set_default_textdomain(const char *domain)
void refresh_addon_version_info_cache()
Refreshes the per-session cache of add-on's version information structs.
std::string sanitize_path(const std::string &path)
Sanitizes a path to remove references to the user's name.
void apply_diff(const config &diff, bool track=false)
A function to apply a diff config onto this config object.
const char * what() const noexcept
bool userconfig_path
True if –userconfig-path was given on the command line.
std::optional< std::string > bzip2
Non-empty if –bzip2 was given on the command line.
static void handle_preprocess_command(const commandline_options &cmdline_opts)
bool nobanner
True if –nobanner was given on the command line.
int main(int argc, char **argv)
std::optional< std::string > logdomains
Non-empty if –logdomains was given on the command line.
std::optional< std::string > render_image
Image path to render.
Helper class, don't construct this directly.
static int do_gameloop(const std::vector< std::string > &args)
Setups the game environment and enters the titlescreen or game loops.
std::string dev_message
The message for developers telling which problem was triggered, this shouldn't be translated...
static void gzip_encode(const std::string &input_file, const std::string &output_file)
std::unique_ptr< std::ostream > scoped_ostream
bool is_gzip_file(const std::string &filename)
Returns true if the file ends with '.gz'.
Some defines: VERSION, PACKAGE, MIN_SAVEGAME_VERSION.
static void handle_lua_script_args(game_launcher *game, commandline_options &)
Handles the lua script command line arguments if present.
std::string get_exe_dir()
static void init_locale()
I would prefer to setup locale first so that early error messages can get localized, but we need the game_launcher initialized to have filesystem::get_intl_dir() to work.
Log file control routines for Windows.
void set_user_config_dir(const std::string &newconfigdir)
bool debug_lua
True if –debug-lua was given in the commandline.
std::string get_wml_location(const std::string &filename, const std::string ¤t_dir)
Returns a complete path to the actual WML file or directory or an empty string if the file isn't pres...
bool allow_insecure
True if –allow-insecure was given in the commandline.
const std::string revision
void set_strict_severity(int severity)
static int process_command_args(const commandline_options &cmdline_opts)
Process commandline-arguments.
bool strict_lua
True if –strict-lua was given in the commandline.
std::optional< std::string > gunzip
Non-empty if –gunzip was given on the command line.
An exception object used when an IO error occurs.
structure which will hide all current floating labels, and cause floating labels instantiated after i...
std::optional< std::string > userdata_dir
Non-empty if –userdata-dir was given on the command line.
Declarations for File-IO.
Contains a basic exception class for SDL operations.
const version_info wesnoth_version(VERSION)
static map_location::DIRECTION sw
bool set_log_domain_severity(const std::string &name, int severity)
std::optional< std::string > data_dir
Non-empty if –data-dir was given on the command line.
bool data_path
True if –data-path was given on the command line.
std::vector< std::string > read_argv([[maybe_unused]] int argc, [[maybe_unused]] char **argv)
std::string get_user_config_dir()
bool screenshot
True if –screenshot was given on the command line.
bool is_bzip2_file(const std::string &filename)
Returns true if the file ends with '.bz2'.
int get_retval() const
Returns the cached window exit code.
static void display(std::function< void()> f)
std::vector< aReg > areg_vec
Contains the SDL_Rect helper code.
Base class for all the errors encountered by the engine.
void play_music_config(const config &music_node, bool allow_interrupt_current_track, int i)
std::string list_logdomains(const std::string &filter)
bool version
True if –version was given on the command line.
Standard logging facilities (interface).
std::string str() const
Serializes the version number into string form.
std::optional< std::string > validate_with
Non-empty if –use-schema was given on the command line.
std::optional< std::string > validate_wml
Non-empty if –validate was given on the command line.
bool strict_validation
True if –strict-validation was given on the command line.
std::map< std::string, struct preproc_define > preproc_map
std::optional< std::vector< std::string > > preprocess_defines
Defines that were given to the –preprocess option.
static void encode(const std::string &input_file, const std::string &output_file)
Realization of serialization/validator.hpp abstract validator.
void reload_changed_game_config()
void set_create_exceptions(bool value)
A config object defines a single node in a WML file, with access to child nodes.
filesystem::scoped_istream preprocess_file(const std::string &fname, preproc_map *defines)
Function to use the WML preprocessor on a file.
static preproc_map::value_type read_pair(const config &)
int wesnoth_main(int argc, char **argv)
std::optional< std::string > validate_schema
Non-empty if –validate-schema was given on the command line.
bool init_game_config(FORCE_RELOAD_CONFIG force_reload)
bool help
True if –help was given on the command line.
const config & child(config_key_type key) const
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
std::string full_build_report()
Produce a bug report-style info dump.
std::string wesnoth_program_dir
void precise_timestamps(bool pt)
void set_debug(bool new_debug)