comparison druntime/src/compiler/ldc/dmain2.d @ 759:d3eb054172f9

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