Mercurial > projects > ldc
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 } |