]> git.llucax.com Git - software/druntime.git/blob - src/compiler/dmd/dmain2.d
Added "invariant" module to fix link issues because DMD generates references to an...
[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 extern (C) void _d_hidden_func()
78 {
79     // TODO: Figure out what to do with this routine
80 }
81
82 bool _d_isHalting = false;
83
84 extern (C) bool rt_isHalting()
85 {
86     return _d_isHalting;
87 }
88
89 extern (C) bool rt_trapExceptions = true;
90
91 void _d_criticalInit()
92 {
93     version (linux)
94     {
95         _STI_monitor_staticctor();
96         _STI_critical_init();
97     }
98 }
99
100 alias void delegate( Exception ) ExceptionHandler;
101
102 extern (C) bool rt_init( ExceptionHandler dg = null )
103 {
104     _d_criticalInit();
105
106     try
107     {
108         gc_init();
109         version (Windows)
110             _minit();
111         _moduleCtor();
112         return true;
113     }
114     catch( Exception e )
115     {
116         if( dg )
117             dg( e );
118     }
119     catch
120     {
121
122     }
123     _d_criticalTerm();
124     return false;
125 }
126
127 void _d_criticalTerm()
128 {
129     version (linux)
130     {
131         _STD_critical_term();
132         _STD_monitor_staticdtor();
133     }
134 }
135
136 extern (C) bool rt_term( ExceptionHandler dg = null )
137 {
138     try
139     {
140         thread_joinAll();
141         _d_isHalting = true;
142         _moduleDtor();
143         gc_term();
144         return true;
145     }
146     catch( Exception e )
147     {
148         if( dg )
149             dg( e );
150     }
151     catch
152     {
153
154     }
155     finally
156     {
157         _d_criticalTerm();
158     }
159     return false;
160 }
161
162 /***********************************
163  * The D main() function supplied by the user's program
164  */
165 int main(char[][] args);
166
167 /***********************************
168  * Substitutes for the C main() function.
169  * It's purpose is to wrap the call to the D main()
170  * function and catch any unhandled exceptions.
171  */
172
173 extern (C) int main(int argc, char **argv)
174 {
175     char[][] args;
176     int result;
177
178     version (linux)
179     {
180         _STI_monitor_staticctor();
181         _STI_critical_init();
182     }
183
184     version (Windows)
185     {
186         wchar_t*  wcbuf = GetCommandLineW();
187         size_t    wclen = wcslen(wcbuf);
188         int       wargc = 0;
189         wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
190         assert(wargc == argc);
191
192         char*     cargp = null;
193         size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
194
195         cargp = cast(char*) alloca(cargl);
196         args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
197
198         for (size_t i = 0, p = 0; i < wargc; i++)
199         {
200             int wlen = wcslen( wargs[i] );
201             int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
202             args[i]  = cargp[p .. p+clen];
203             p += clen; assert(p <= cargl);
204             WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
205         }
206         LocalFree(wargs);
207         wargs = null;
208         wargc = 0;
209     }
210     else version (linux)
211     {
212         char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
213         scope(exit) free(am);
214
215         for (size_t i = 0; i < argc; i++)
216         {
217             auto len = strlen(argv[i]);
218             am[i] = argv[i][0 .. len];
219         }
220         args = am[0 .. argc];
221     }
222
223     bool trapExceptions = rt_trapExceptions;
224
225     void tryExec(void delegate() dg)
226     {
227
228         if (trapExceptions)
229         {
230             try
231             {
232                 dg();
233             }
234             catch (Exception e)
235             {
236                 while (e)
237                 {
238                     if (e.file)
239                     {
240                        // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
241                        console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.toString)("\n");
242                     }
243                     else
244                     {
245                        // fprintf(stderr, "%.*s\n", e.toString());
246                        console (e.classinfo.name)(": ")(e.toString)("\n");
247                     }
248                     if (e.info)
249                     {
250                         console ("----------------\n");
251                         foreach (t; e.info)
252                             console (t)("\n");
253                     }
254                     if (e.next)
255                         console ("\n");
256                     e = e.next;
257                 }
258                 result = EXIT_FAILURE;
259             }
260             catch (Object o)
261             {
262                 // fprintf(stderr, "%.*s\n", o.toString());
263                 console (o.toString)("\n");
264                 result = EXIT_FAILURE;
265             }
266         }
267         else
268         {
269             dg();
270         }
271     }
272
273     // NOTE: The lifetime of a process is much like the lifetime of an object:
274     //       it is initialized, then used, then destroyed.  If initialization
275     //       fails, the successive two steps are never reached.  However, if
276     //       initialization succeeds, then cleanup will occur even if the use
277     //       step fails in some way.  Here, the use phase consists of running
278     //       the user's main function.  If main terminates with an exception,
279     //       the exception is handled and then cleanup begins.  An exception
280     //       thrown during cleanup, however, will abort the cleanup process.
281
282     void runMain()
283     {
284         result = main(args);
285     }
286
287     void runAll()
288     {
289         gc_init();
290         version (Windows)
291             _minit();
292         _moduleCtor();
293         if (runModuleUnitTests())
294             tryExec(&runMain);
295         thread_joinAll();
296         _d_isHalting = true;
297         _moduleDtor();
298         gc_term();
299     }
300
301     tryExec(&runAll);
302
303     version (linux)
304     {
305         _STD_critical_term();
306         _STD_monitor_staticdtor();
307     }
308     return result;
309 }