2 * Placed into the Public Domain.
3 * written by Walter Bright
8 * Modified by Sean Kelly for use with the D Runtime Project
16 import core.stdc.stddef;
17 import core.stdc.stdlib;
18 import core.stdc.string;
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
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();
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.
52 void gc_setHandle(void* p);
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;
62 extern (C) void* rt_loadLibrary(in char[] name)
66 char[260] temp = void;
67 temp[0 .. name.length] = name[];
68 temp[name.length] = cast(char) 0;
69 void* ptr = LoadLibraryA(temp.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)
76 gcSet(gc_getHandle());
83 throw new Exception("rt_loadLibrary not yet implemented on linux.");
87 extern (C) void rt_unloadLibrary(void* ptr)
91 gcClrFn gcClr = cast(gcClrFn) GetProcAddress(ptr, "_gc_clrHandle");
92 rtTermFn rtTerm = cast(rtTermFn) GetProcAddress(ptr, "_rt_term");
94 if (gcClr !is null && rtTerm !is null)
99 return FreeLibrary(ptr) != 0;
103 throw new Exception("rt_unloadLibrary not yet implemented on linux.");
107 /***********************************
108 * These functions must be defined for any D program linked
109 * against this library.
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();
118 // this function is called from the utf module
119 //extern (C) void onUnicodeError(string msg, size_t idx);
121 /***********************************
122 * These are internal callbacks for various language errors.
124 extern (C) void _d_assert(string file, uint line)
126 onAssertError(file, line);
129 extern (C) static void _d_assert_msg(string msg, string file, uint line)
131 onAssertErrorMsg(file, line, msg);
134 extern (C) void _d_array_bounds(string file, uint line)
136 onArrayBoundsError(file, line);
139 extern (C) void _d_switch_error(string file, uint line)
141 onSwitchError(file, line);
144 extern (C) void _d_hidden_func()
151 onHiddenFuncError(o);
154 bool _d_isHalting = false;
156 extern (C) bool rt_isHalting()
161 extern (C) bool rt_trapExceptions = true;
163 void _d_criticalInit()
167 _STI_monitor_staticctor();
168 _STI_critical_init();
172 alias void delegate(Throwable) ExceptionHandler;
174 extern (C) bool rt_init(ExceptionHandler dg = null)
199 void _d_criticalTerm()
203 _STD_critical_term();
204 _STD_monitor_staticdtor();
208 extern (C) bool rt_term(ExceptionHandler dg = null)
234 /***********************************
235 * The D main() function supplied by the user's program
237 int main(char[][] args);
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.
245 extern (C) int main(int argc, char **argv)
252 _STI_monitor_staticctor();
253 _STI_critical_init();
258 wchar_t* wcbuf = GetCommandLineW();
259 size_t wclen = wcslen(wcbuf);
261 wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
262 assert(wargc == argc);
265 size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0);
267 cargp = cast(char*) alloca(cargl);
268 args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
270 for (size_t i = 0, p = 0; i < wargc; i++)
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);
284 char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
285 scope(exit) free(am);
287 for (size_t i = 0; i < argc; i++)
289 auto len = strlen(argv[i]);
290 am[i] = argv[i][0 .. len];
292 args = am[0 .. argc];
295 bool trapExceptions = rt_trapExceptions;
297 void tryExec(void delegate() dg)
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");
317 // fprintf(stderr, "%.*s\n", e.toString());
318 console (e.toString)("\n");
322 console ("----------------\n");
330 result = EXIT_FAILURE;
334 // fprintf(stderr, "%.*s\n", o.toString());
335 console (o.toString)("\n");
336 result = EXIT_FAILURE;
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.
365 if (runModuleUnitTests())
377 _STD_critical_term();
378 _STD_monitor_staticdtor();