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