]> git.llucax.com Git - software/druntime.git/blob - src/compiler/dmd/dmain2.d
4285db869793c22799a71a52f1dc3c4b922c4ef9
[software/druntime.git] / src / compiler / dmd / dmain2.d
1 /*
2  * Placed into the Public Domain.
3  * written by Walter Bright
4  * www.digitalmars.com
5  */
6
7 /*
8  *  Modified by Sean Kelly for use with the D Runtime Project
9  */
10
11 module rt.dmain2;
12
13 private
14 {
15     import util.console;
16     import stdc.stddef;
17     import stdc.stdlib;
18     import stdc.string;
19 }
20
21 version( Windows )
22 {
23     extern (Windows) void*      LocalFree(void*);
24     extern (Windows) wchar_t*   GetCommandLineW();
25     extern (Windows) wchar_t**  CommandLineToArgvW(wchar_t*, int*);
26     extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int);
27     pragma(lib, "shell32.lib");   // needed for CommandLineToArgvW
28 }
29
30 extern (C) void _STI_monitor_staticctor();
31 extern (C) void _STD_monitor_staticdtor();
32 extern (C) void _STI_critical_init();
33 extern (C) void _STD_critical_term();
34 extern (C) void gc_init();
35 extern (C) void gc_term();
36 extern (C) void _minit();
37 extern (C) void _moduleCtor();
38 extern (C) void _moduleDtor();
39 extern (C) void thread_joinAll();
40
41 /***********************************
42  * These functions must be defined for any D program linked
43  * against this library.
44  */
45 extern (C) void onAssertError( string file, size_t line );
46 extern (C) void onAssertErrorMsg( string file, size_t line, string msg );
47 extern (C) void onArrayBoundsError( string file, size_t line );
48 extern (C) void onSwitchError( string file, size_t line );
49 extern (C) bool runModuleUnitTests();
50
51 // this function is called from the utf module
52 //extern (C) void onUnicodeError( string msg, size_t idx );
53
54 /***********************************
55  * These are internal callbacks for various language errors.
56  */
57 extern (C) void _d_assert( string file, uint line )
58 {
59     onAssertError( file, line );
60 }
61
62 extern (C) static void _d_assert_msg( string msg, string file, uint line )
63 {
64     onAssertErrorMsg( file, line, msg );
65 }
66
67 extern (C) void _d_array_bounds( string file, uint line )
68 {
69     onArrayBoundsError( file, line );
70 }
71
72 extern (C) void _d_switch_error( string file, uint line )
73 {
74     onSwitchError( file, line );
75 }
76
77 bool _d_isHalting = false;
78
79 extern (C) bool rt_isHalting()
80 {
81     return _d_isHalting;
82 }
83
84 extern (C) bool rt_trapExceptions = true;
85
86 void _d_criticalInit()
87 {
88     version (linux)
89     {
90         _STI_monitor_staticctor();
91         _STI_critical_init();
92     }
93 }
94
95 alias void delegate( Exception ) ExceptionHandler;
96
97 extern (C) bool rt_init( ExceptionHandler dg = null )
98 {
99     _d_criticalInit();
100
101     try
102     {
103         gc_init();
104         version (Windows)
105             _minit();
106         _moduleCtor();
107         return true;
108     }
109     catch( Exception e )
110     {
111         if( dg )
112             dg( e );
113     }
114     catch
115     {
116
117     }
118     _d_criticalTerm();
119     return false;
120 }
121
122 void _d_criticalTerm()
123 {
124     version (linux)
125     {
126         _STD_critical_term();
127         _STD_monitor_staticdtor();
128     }
129 }
130
131 extern (C) bool rt_term( ExceptionHandler dg = null )
132 {
133     try
134     {
135         thread_joinAll();
136         _d_isHalting = true;
137         _moduleDtor();
138         gc_term();
139         return true;
140     }
141     catch( Exception e )
142     {
143         if( dg )
144             dg( e );
145     }
146     catch
147     {
148
149     }
150     finally
151     {
152         _d_criticalTerm();
153     }
154     return false;
155 }
156
157 /***********************************
158  * The D main() function supplied by the user's program
159  */
160 int main(char[][] args);
161
162 /***********************************
163  * Substitutes for the C main() function.
164  * It's purpose is to wrap the call to the D main()
165  * function and catch any unhandled exceptions.
166  */
167
168 extern (C) int main(int argc, char **argv)
169 {
170     char[][] args;
171     int result;
172
173     version (linux)
174     {
175         _STI_monitor_staticctor();
176         _STI_critical_init();
177     }
178
179     version (Windows)
180     {
181         wchar_t*  wcbuf = GetCommandLineW();
182         size_t    wclen = wcslen(wcbuf);
183         int       wargc = 0;
184         wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
185         assert(wargc == argc);
186
187         char*     cargp = null;
188         size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
189
190         cargp = cast(char*) alloca(cargl);
191         args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
192
193         for (size_t i = 0, p = 0; i < wargc; i++)
194         {
195             int wlen = wcslen( wargs[i] );
196             int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
197             args[i]  = cargp[p .. p+clen];
198             p += clen; assert(p <= cargl);
199             WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
200         }
201         LocalFree(wargs);
202         wargs = null;
203         wargc = 0;
204     }
205     else version (linux)
206     {
207         char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
208         scope(exit) free(am);
209
210         for (size_t i = 0; i < argc; i++)
211         {
212             auto len = strlen(argv[i]);
213             am[i] = argv[i][0 .. len];
214         }
215         args = am[0 .. argc];
216     }
217
218     bool trapExceptions = rt_trapExceptions;
219
220     void tryExec(void delegate() dg)
221     {
222
223         if (trapExceptions)
224         {
225             try
226             {
227                 dg();
228             }
229             catch (Exception e)
230             {
231                 while (e)
232                 {
233                     if (e.file)
234                     {
235                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
236                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.toString)("\n");
237                     }
238                     else
239                     {
240                        // fprintf(stderr, "%.*s\n", e.toString());
241                        console (e.classinfo.name)(": ")(e.toString)("\n");
242                     }
243                     if (e.info)
244                     {
245                         console ("----------------\n");
246                         foreach (t; e.info)
247                             console (t)("\n");
248                     }
249                     if (e.next)
250                         console ("\n");
251                     e = e.next;
252                 }
253                 result = EXIT_FAILURE;
254             }
255             catch (Object o)
256             {
257                 // fprintf(stderr, "%.*s\n", o.toString());
258                 console (o.toString)("\n");
259                 result = EXIT_FAILURE;
260             }
261         }
262         else
263         {
264             dg();
265         }
266     }
267
268     // NOTE: The lifetime of a process is much like the lifetime of an object:
269     //       it is initialized, then used, then destroyed.  If initialization
270     //       fails, the successive two steps are never reached.  However, if
271     //       initialization succeeds, then cleanup will occur even if the use
272     //       step fails in some way.  Here, the use phase consists of running
273     //       the user's main function.  If main terminates with an exception,
274     //       the exception is handled and then cleanup begins.  An exception
275     //       thrown during cleanup, however, will abort the cleanup process.
276
277     void runMain()
278     {
279         result = main(args);
280     }
281
282     void runAll()
283     {
284         gc_init();
285         version (Windows)
286             _minit();
287         _moduleCtor();
288         if (runModuleUnitTests())
289             tryExec(&runMain);
290         thread_joinAll();
291         _d_isHalting = true;
292         _moduleDtor();
293         gc_term();
294     }
295
296     tryExec(&runAll);
297
298     version (linux)
299     {
300         _STD_critical_term();
301         _STD_monitor_staticdtor();
302     }
303     return result;
304 }