1 2 /* NOTE: This file is based on dmain2.d from the original DMD distribution. 3 4 */ 5 6 /* 7 * Modified by Sean Kelly <sean@f4.ca> for use with Tango. 8 */ 9 module rt.compiler.gdc.rt.dgccmain2; 10 private 11 { 12 import rt.compiler.gdc.rt.memory; 13 import rt.compiler.util.console; 14 15 import tango.stdc.stddef; 16 import tango.stdc.stdlib; 17 import tango.stdc.string; 18 } 19 20 version( Win32 ) 21 { 22 extern (Windows) void* LocalFree(void*); 23 extern (Windows) wchar_t* GetCommandLineW(); 24 extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*); 25 extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int); 26 pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW 27 } 28 29 extern (C) void _STI_monitor_staticctor(); 30 extern (C) void _STD_monitor_staticdtor(); 31 extern (C) void _STI_critical_init(); 32 extern (C) void _STD_critical_term(); 33 extern (C) void gc_init(); 34 extern (C) void gc_term(); 35 extern (C) void _minit(); 36 extern (C) void _moduleCtor(); 37 extern (C) void _moduleDtor(); 38 extern (C) void thread_joinAll(); 39 40 version (GNU_CBridge_Stdio) 41 { 42 extern (C) void _d_gnu_cbridge_init_stdio(); 43 } 44 45 /*********************************** 46 * These functions must be defined for any D program linked 47 * against this library. 48 */ 49 extern (C) void onAssertError( char[] file, size_t line ); 50 extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg ); 51 extern (C) void onArrayBoundsError( char[] file, size_t line ); 52 extern (C) void onSwitchError( char[] file, size_t line ); 53 extern (C) bool runModuleUnitTests(); 54 55 // this function is called from the utf module 56 //extern (C) void onUnicodeError( char[] msg, size_t idx ); 57 58 /*********************************** 59 * These are internal callbacks for various language errors. 60 */ 61 extern (C) void _d_assert( char[] file, uint line ) 62 { 63 onAssertError( file, line ); 64 } 65 66 extern (C) static void _d_assert_msg( char[] msg, char[] file, uint line ) 67 { 68 onAssertErrorMsg( file, line, msg ); 69 } 70 71 extern (C) void _d_array_bounds( char[] file, uint line ) 72 { 73 onArrayBoundsError( file, line ); 74 } 75 76 extern (C) void _d_switch_error( char[] file, uint line ) 77 { 78 onSwitchError( file, line ); 79 } 80 81 bool _d_isHalting = false; 82 83 extern (C) bool rt_isHalting() 84 { 85 return _d_isHalting; 86 } 87 88 extern (C) bool rt_trapExceptions = true; 89 90 void _d_criticalInit() 91 { 92 version (GC_Use_Stack_Guess) 93 { 94 int dummy; 95 stackOriginGuess = &dummy; 96 } 97 version (GNU_CBridge_Stdio) 98 { 99 _d_gnu_cbridge_init_stdio(); 100 } 101 version (all) 102 { 103 _STI_monitor_staticctor(); 104 _STI_critical_init(); 105 initStaticDataPtrs(); 106 } 107 } 108 109 alias void delegate( Exception ) ExceptionHandler; 110 111 extern (C) bool rt_init( ExceptionHandler dg = null ) 112 { 113 _d_criticalInit(); 114 115 try 116 { 117 gc_init(); 118 _moduleCtor(); 119 return true; 120 } 121 catch( Exception e ) 122 { 123 if( dg ){ 124 dg( e ); 125 } else { 126 console("exception while executing module initializers:\n"); 127 e.writeOut(delegate void(char[]s){ 128 console(s); 129 }); 130 console(); 131 } 132 } 133 catch 134 { 135 console("error while executing module initializers\n"); 136 } 137 _d_criticalTerm(); 138 return false; 139 } 140 141 void _d_criticalTerm() 142 { 143 version (all) 144 { 145 _STD_critical_term(); 146 _STD_monitor_staticdtor(); 147 } 148 } 149 150 extern (C) bool rt_term( ExceptionHandler dg = null ) 151 { 152 try 153 { 154 thread_joinAll(); 155 _d_isHalting = true; 156 _moduleDtor(); 157 gc_term(); 158 return true; 159 } 160 catch( Exception e ) 161 { 162 if( dg ) 163 dg( e ); 164 } 165 catch 166 { 167 168 } 169 finally 170 { 171 _d_criticalTerm(); 172 } 173 return false; 174 } 175 176 /*********************************** 177 * The D main() function supplied by the user's program 178 */ 179 //int main(char[][] args); 180 extern (C) alias int function(char[][] args) main_type; 181 182 /*********************************** 183 * Substitutes for the C main() function. 184 * It's purpose is to wrap the call to the D main() 185 * function and catch any unhandled exceptions. 186 */ 187 188 /* Note that this is not the C main function, nor does it refer 189 to the D main function as in the DMD version. The actual C 190 main is in cmain.d 191 192 This serves two purposes: 193 1) Special applications that have a C main declared elsewhere. 194 195 2) It is possible to create D shared libraries that can be used 196 by non-D executables. (TODO: Not complete, need a general library 197 init routine.) 198 */ 199 200 extern (C) int _d_run_main(int argc, char **argv, main_type main_func) 201 { 202 char[][] args; 203 int result; 204 205 version (GC_Use_Stack_Guess) 206 { 207 stackOriginGuess = &argv; 208 } 209 version (GNU_CBridge_Stdio) 210 { 211 _d_gnu_cbridge_init_stdio(); 212 } 213 version (all) 214 { 215 _STI_monitor_staticctor(); 216 _STI_critical_init(); 217 initStaticDataPtrs(); 218 } 219 220 version (all) 221 { 222 char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof); 223 scope(exit) free(am); 224 225 for (size_t i = 0; i < argc; i++) 226 { 227 auto len = strlen(argv[i]); 228 am[i] = argv[i][0 .. len]; 229 } 230 args = am[0 .. argc]; 231 } 232 233 bool trapExceptions = rt_trapExceptions; 234 235 void tryExec(void delegate() dg) 236 { 237 238 if (trapExceptions) 239 { 240 try 241 { 242 dg(); 243 } 244 catch (Exception e) 245 { 246 e.writeOut(delegate void(char[] s){ console(s); }); 247 result = EXIT_FAILURE; 248 } 249 catch (Object o) 250 { 251 // fprintf(stderr, "%.*s\n", o.toString()); 252 console (o.toString)("\n"); 253 result = EXIT_FAILURE; 254 } 255 } 256 else 257 { 258 dg(); 259 } 260 } 261 262 // NOTE: The lifetime of a process is much like the lifetime of an object: 263 // it is initialized, then used, then destroyed. If initialization 264 // fails, the successive two steps are never reached. However, if 265 // initialization succeeds, then cleanup will occur even if the use 266 // step fails in some way. Here, the use phase consists of running 267 // the user's main function. If main terminates with an exception, 268 // the exception is handled and then cleanup begins. An exception 269 // thrown during cleanup, however, will abort the cleanup process. 270 271 void runMain() 272 { 273 result = main_func(args); 274 } 275 276 void runAll() 277 { 278 gc_init(); 279 _moduleCtor(); 280 if (runModuleUnitTests()) 281 tryExec(&runMain); 282 _d_isHalting = true; 283 thread_joinAll(); 284 _moduleDtor(); 285 gc_term(); 286 } 287 288 tryExec(&runAll); 289 290 version (all) 291 { 292 _STD_critical_term(); 293 _STD_monitor_staticdtor(); 294 } 295 return result; 296 }