]> git.tdb.fi Git - libs/core.git/blob - source/core/application.cpp
Store argv0 and application name in the Application class
[libs/core.git] / source / core / application.cpp
1 #include <typeinfo>
2 #include <signal.h>
3 #include <msp/debug/demangle.h>
4 #include <msp/debug/errorreporter.h>
5 #include <msp/fs/utils.h>
6 #include <msp/io/print.h>
7 #include "application.h"
8 #include "getopt.h"
9
10 using namespace std;
11
12 namespace Msp {
13
14 Application *Application::app_ = 0;
15 Application::Starter *Application::starter_ = 0;
16 const char *Application::argv0_ = 0;
17 string Application::name_;
18 void *Application::data_ = 0;
19
20 Application::Application(const string &n):
21         exit_code(0)
22 {
23         if(app_)
24                 throw logic_error("instance already exists");
25
26         if(!n.empty())
27                 name_ = n;
28         else
29                 name_ = FS::basename(argv0_);
30 }
31
32 int Application::run(int argc, char **argv, void *data, void (*created_callback)(void *))
33 {
34         if(!starter_)
35         {
36                 IO::cerr.write("Application::run called with no RegisteredApplication class!\n");
37                 return 126;
38         }
39
40         argv0_ = argv[0];
41         data_ = data;
42
43         try
44         {
45                 try
46                 {
47                         app_ = starter_->create_app(argc, argv);
48                 }
49                 catch(const usage_error &e)
50                 {
51                         IO::print(IO::cerr, "%s\n%s\n", e.what(), e.help());
52                         return 1;
53                 }
54
55                 if(created_callback)
56                         created_callback(data);
57
58                 int result = app_->main();
59                 Application *a = app_;
60                 app_ = 0;
61                 delete a;
62                 return result;
63         }
64         catch(const exception &e)
65         {
66                 bool handled = false;
67                 if(const Debug::ErrorReporter *er = Debug::ErrorReporter::get_current())
68                         handled = er->report_uncaught_exception(e);
69
70                 if(!handled)
71                 {
72                         IO::print(IO::cerr, "An uncaught exception occurred.\n");
73                         IO::print(IO::cerr, "  type:   %s\n", Debug::demangle(typeid(e).name()));
74                         IO::print(IO::cerr, "  what(): %s\n", e.what());
75                 }
76
77                 delete app_;
78                 app_ = 0;
79
80                 return 124;
81         }
82 }
83
84 int Application::main()
85 {
86         done = false;
87         while(!done)
88                 tick();
89
90         return exit_code;
91 }
92
93 void Application::catch_signal(int s)
94 {
95         signal(s, &sighandler_);
96 }
97
98 void Application::exit(int c)
99 {
100         done = true;
101         exit_code = c;
102 }
103
104 void Application::sighandler_(int s)
105 {
106         app_->sighandler(s);
107 }
108
109
110 Application::Starter::Starter()
111 {
112         if(starter_)
113                 throw logic_error("Can't create more than one Starter instance");
114
115         starter_ = this;
116 }
117
118 } // namespace Msp