1 #include "AIClientApp.h"
2 
3 #include "../../util/OptionsDB.h"
4 #include "../../util/Directories.h"
5 #include "../../util/Logger.h"
6 #include "../../util/Version.h"
7 #include "../../util/i18n.h"
8 
9 #include <GG/utf8/checked.h>
10 
11 #include <boost/filesystem/fstream.hpp>
12 
13 #if defined(FREEORION_LINUX)
14 /* Freeorion aims to have exceptions handled and operation continue normally.
15 An example of good exception handling is the exceptions caught around config.xml loading.
16 After catching and informing the user it continues normally with the default values.
17 
18 An exception that can not be handled should allow freeorion to crash and keep
19 a complete stack trace of the intial exception.
20 Some platforms do not support this behavior.
21 
22 When FREEORION_CAMAIN_KEEP_BACKTRACE is defined, do not catch an unhandled exceptions,
23 unroll and hide the stack trace, print a message and still crash anyways. */
24 #define FREEORION_CAMAIN_KEEP_STACKTRACE
25 #endif
26 
27 #ifndef FREEORION_WIN32
main(int argc,char * argv[])28 int main(int argc, char* argv[]) {
29     InitDirs(argv[0]);
30     std::vector<std::string> args;
31     for (int i = 0; i < argc; ++i)
32         args.push_back(argv[i]);
33 
34 #else
35 int wmain(int argc, wchar_t* argv[], wchar_t* envp[]) {
36     // copy UTF-16 command line arguments to UTF-8 vector
37     std::vector<std::string> args;
38     for (int i = 0; i < argc; ++i) {
39         std::wstring argi16(argv[i]);
40         std::string argi8;
41         utf8::utf16to8(argi16.begin(), argi16.end(), std::back_inserter(argi8));
42         args.push_back(argi8);
43     }
44     InitDirs((args.empty() ? "" : *args.begin()));
45 #endif
46 
47     GetOptionsDB().AddFlag("testing", UserStringNop("OPTIONS_DB_TESTING"), false);
48     GetOptionsDB().Add<std::string>('h', "help", UserStringNop("OPTIONS_DB_HELP"), "NOOP",
49                                     Validator<std::string>(), false);
50 
51     // if config.xml and persistent_config.xml are present, read and set options entries
52     GetOptionsDB().SetFromFile(GetConfigPath(), FreeOrionVersionString());
53     GetOptionsDB().SetFromFile(GetPersistentConfigPath());
54     GetOptionsDB().SetFromCommandLine(args);
55 
56     auto help_arg = GetOptionsDB().Get<std::string>("help");
57     if (help_arg != "NOOP") {
58         GetOptionsDB().GetUsage(std::cerr, help_arg);
59         ShutdownLoggingSystemFileSink();
60         return 0;
61     }
62 
63 #ifndef FREEORION_CAMAIN_KEEP_STACKTRACE
64     try {
65 #endif
66         AIClientApp g_app(args);
67 
68         g_app.Run();
69 
70 #ifndef FREEORION_CAMAIN_KEEP_STACKTRACE
71     } catch (const std::invalid_argument& e) {
72         ErrorLogger() << "main() caught exception(std::invalid_arg): " << e.what();
73         std::cerr << "main() caught exception(std::invalid_arg): " << e.what() << std::endl;
74         ShutdownLoggingSystemFileSink();
75         return 1;
76     } catch (const std::runtime_error& e) {
77         ErrorLogger() << "main() caught exception(std::runtime_error): " << e.what();
78         std::cerr << "main() caught exception(std::runtime_error): " << e.what() << std::endl;
79         ShutdownLoggingSystemFileSink();
80         return 1;
81     } catch (const std::exception& e) {
82         ErrorLogger() << "main() caught exception(std::exception): " << e.what();
83         std::cerr << "main() caught exception(std::exception): " << e.what() << std::endl;
84         ShutdownLoggingSystemFileSink();
85         return 1;
86     } catch (...) {
87         ErrorLogger() << "main() caught unknown exception.";
88         std::cerr << "main() caught unknown exception." << std::endl;
89         ShutdownLoggingSystemFileSink();
90         return 1;
91     }
92 #endif
93     DebugLogger() << "AI client main exited cleanly.";
94     ShutdownLoggingSystemFileSink();
95     return 0;
96 }
97 
98