comparison druntime/src/compiler/ldc/dmain2.d @ 1458:e0b2d67cfe7c

Added druntime (this should be removed once it works).
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 02 Jun 2009 17:43:06 +0100
parents
children
comparison
equal deleted inserted replaced
1456:7b218ec1044f 1458:e0b2d67cfe7c
1 /**
2 * Contains main program entry point and support routines.
3 *
4 * Copyright: Copyright Digital Mars 2000 - 2009.
5 * License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>.
6 * Authors: Walter Bright, Sean Kelly
7 *
8 * Copyright Digital Mars 2000 - 2009.
9 * Distributed under the Boost Software License, Version 1.0.
10 * (See accompanying file LICENSE_1_0.txt or copy at
11 * http://www.boost.org/LICENSE_1_0.txt)
12 */
13 module rt.dmain2;
14
15 private
16 {
17 import rt.memory;
18 import rt.util.console;
19 import core.stdc.stddef;
20 import core.stdc.stdlib;
21 import core.stdc.string;
22 }
23
24 version (Windows)
25 {
26 private import core.stdc.wchar_;
27
28 extern (Windows) alias int function() FARPROC;
29 extern (Windows) FARPROC GetProcAddress(void*, in char*);
30 extern (Windows) void* LoadLibraryA(in char*);
31 extern (Windows) int FreeLibrary(void*);
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 }
38
39 extern (C) void _STI_monitor_staticctor();
40 extern (C) void _STD_monitor_staticdtor();
41 extern (C) void _STI_critical_init();
42 extern (C) void _STD_critical_term();
43 extern (C) void gc_init();
44 extern (C) void gc_term();
45 extern (C) void _minit();
46 extern (C) void _moduleCtor();
47 extern (C) void _moduleDtor();
48 extern (C) void thread_joinAll();
49
50 version (OSX)
51 {
52 // The bottom of the stack
53 extern (C) void* __osx_stack_end = cast(void*)0xC0000000;
54 }
55
56 /***********************************
57 * These are a temporary means of providing a GC hook for DLL use. They may be
58 * replaced with some other similar functionality later.
59 */
60 extern (C)
61 {
62 void* gc_getProxy();
63 void gc_setProxy(void* p);
64 void gc_clrProxy();
65
66 alias void* function() gcGetFn;
67 alias void function(void*) gcSetFn;
68 alias void function() gcClrFn;
69 }
70
71 extern (C) void* rt_loadLibrary(in char[] name)
72 {
73 version (Windows)
74 {
75 char[260] temp = void;
76 temp[0 .. name.length] = name[];
77 temp[name.length] = cast(char) 0;
78 void* ptr = LoadLibraryA(temp.ptr);
79 if (ptr is null)
80 return ptr;
81 gcSetFn gcSet = cast(gcSetFn) GetProcAddress(ptr, "gc_setProxy");
82 if (gcSet !is null)
83 gcSet(gc_getProxy());
84 return ptr;
85
86 }
87 else version (Posix)
88 {
89 throw new Exception("rt_loadLibrary not yet implemented on Posix.");
90 }
91 }
92
93 extern (C) bool rt_unloadLibrary(void* ptr)
94 {
95 version (Windows)
96 {
97 gcClrFn gcClr = cast(gcClrFn) GetProcAddress(ptr, "gc_clrProxy");
98 if (gcClr !is null)
99 gcClr();
100 return FreeLibrary(ptr) != 0;
101 }
102 else version (Posix)
103 {
104 throw new Exception("rt_unloadLibrary not yet implemented on Posix.");
105 }
106 }
107
108 /***********************************
109 * These functions must be defined for any D program linked
110 * against this library.
111 */
112 extern (C) void onAssertError(string file, size_t line);
113 extern (C) void onAssertErrorMsg(string file, size_t line, string msg);
114 extern (C) void onRangeError(string file, size_t line);
115 extern (C) void onHiddenFuncError(Object o);
116 extern (C) void onSwitchError(string file, size_t line);
117 extern (C) bool runModuleUnitTests();
118
119 // this function is called from the utf module
120 //extern (C) void onUnicodeError(string msg, size_t idx);
121
122 /***********************************
123 * These are internal callbacks for various language errors.
124 */
125 extern (C) void _d_assert(string file, uint line)
126 {
127 onAssertError(file, line);
128 }
129
130 extern (C) static void _d_assert_msg(string msg, string file, uint line)
131 {
132 onAssertErrorMsg(file, line, msg);
133 }
134
135 extern (C) void _d_array_bounds(string file, uint line)
136 {
137 onRangeError(file, line);
138 }
139
140 extern (C) void _d_switch_error(string file, uint line)
141 {
142 onSwitchError(file, line);
143 }
144
145 extern (C) void _d_hidden_func()
146 {
147 Object o;
148 asm
149 {
150 mov o, EAX;
151 }
152 onHiddenFuncError(o);
153 }
154
155 shared bool _d_isHalting = false;
156
157 extern (C) bool rt_isHalting()
158 {
159 return _d_isHalting;
160 }
161
162 extern (C) shared bool rt_trapExceptions = true;
163
164 void _d_criticalInit()
165 {
166 version (Posix)
167 {
168 _STI_monitor_staticctor();
169 _STI_critical_init();
170 }
171 }
172
173 alias void delegate(Throwable) ExceptionHandler;
174
175 extern (C) bool rt_init(ExceptionHandler dg = null)
176 {
177 _d_criticalInit();
178
179 try
180 {
181 gc_init();
182 initStaticDataGC();
183 version (Windows)
184 _minit();
185 _moduleCtor();
186 runModuleUnitTests();
187 return true;
188 }
189 catch (Throwable e)
190 {
191 if (dg)
192 dg(e);
193 }
194 catch
195 {
196
197 }
198 _d_criticalTerm();
199 return false;
200 }
201
202 void _d_criticalTerm()
203 {
204 version (Posix)
205 {
206 _STD_critical_term();
207 _STD_monitor_staticdtor();
208 }
209 }
210
211 extern (C) bool rt_term(ExceptionHandler dg = null)
212 {
213 try
214 {
215 thread_joinAll();
216 _d_isHalting = true;
217 _moduleDtor();
218 gc_term();
219 return true;
220 }
221 catch (Throwable e)
222 {
223 if (dg)
224 dg(e);
225 }
226 catch
227 {
228
229 }
230 finally
231 {
232 _d_criticalTerm();
233 }
234 return false;
235 }
236
237 /***********************************
238 * The D main() function supplied by the user's program
239 */
240 int main(char[][] args);
241
242 /***********************************
243 * Substitutes for the C main() function.
244 * It's purpose is to wrap the call to the D main()
245 * function and catch any unhandled exceptions.
246 */
247
248 extern (C) int main(int argc, char **argv)
249 {
250 char[][] args;
251 int result;
252
253 version (OSX)
254 { /* OSX does not provide a way to get at the top of the
255 * stack, except for the magic value 0xC0000000.
256 * But as far as the gc is concerned, argv is at the top
257 * of the main thread's stack, so save the address of that.
258 */
259 __osx_stack_end = cast(void*)&argv;
260 }
261
262 version (Posix)
263 {
264 _STI_monitor_staticctor();
265 _STI_critical_init();
266 }
267
268 version (Windows)
269 {
270 wchar_t* wcbuf = GetCommandLineW();
271 size_t wclen = wcslen(wcbuf);
272 int wargc = 0;
273 wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
274 assert(wargc == argc);
275
276 char* cargp = null;
277 size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
278
279 cargp = cast(char*) alloca(cargl);
280 args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
281
282 for (size_t i = 0, p = 0; i < wargc; i++)
283 {
284 int wlen = wcslen(wargs[i]);
285 int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0);
286 args[i] = cargp[p .. p+clen];
287 p += clen; assert(p <= cargl);
288 WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0);
289 }
290 LocalFree(wargs);
291 wargs = null;
292 wargc = 0;
293 }
294 else version (Posix)
295 {
296 char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
297 scope(exit) free(am);
298
299 for (size_t i = 0; i < argc; i++)
300 {
301 auto len = strlen(argv[i]);
302 am[i] = argv[i][0 .. len];
303 }
304 args = am[0 .. argc];
305 }
306
307 bool trapExceptions = rt_trapExceptions;
308
309 void tryExec(scope void delegate() dg)
310 {
311
312 if (trapExceptions)
313 {
314 try
315 {
316 dg();
317 }
318 catch (Throwable e)
319 {
320 while (e)
321 {
322 if (e.file)
323 {
324 // fprintf(stderr, "%.*s(%u): %.*s\n", e.file, e.line, e.msg);
325 console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n");
326 }
327 else
328 {
329 // fprintf(stderr, "%.*s\n", e.toString());
330 console (e.toString)("\n");
331 }
332 if (e.info)
333 {
334 console ("----------------\n");
335 foreach (t; e.info)
336 console (t)("\n");
337 }
338 if (e.next)
339 console ("\n");
340 e = e.next;
341 }
342 result = EXIT_FAILURE;
343 }
344 catch (Object o)
345 {
346 // fprintf(stderr, "%.*s\n", o.toString());
347 console (o.toString)("\n");
348 result = EXIT_FAILURE;
349 }
350 }
351 else
352 {
353 dg();
354 }
355 }
356
357 // NOTE: The lifetime of a process is much like the lifetime of an object:
358 // it is initialized, then used, then destroyed. If initialization
359 // fails, the successive two steps are never reached. However, if
360 // initialization succeeds, then cleanup will occur even if the use
361 // step fails in some way. Here, the use phase consists of running
362 // the user's main function. If main terminates with an exception,
363 // the exception is handled and then cleanup begins. An exception
364 // thrown during cleanup, however, will abort the cleanup process.
365
366 void runMain()
367 {
368 result = main(args);
369 }
370
371 void runAll()
372 {
373 gc_init();
374 initStaticDataGC();
375 version (Windows)
376 _minit();
377 _moduleCtor();
378 if (runModuleUnitTests())
379 tryExec(&runMain);
380 thread_joinAll();
381 _d_isHalting = true;
382 _moduleDtor();
383 gc_term();
384 }
385
386 tryExec(&runAll);
387
388 version (Posix)
389 {
390 _STD_critical_term();
391 _STD_monitor_staticdtor();
392 }
393 return result;
394 }