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