The real, definitive, Visual C++ support branch. Accept no substitutes
[reactos.git] / lib / 3rdparty / mingw / wcrt1.c
1 /*
2 * crt1.c
3 * This file has no copyright assigned and is placed in the Public Domain.
4 * This file is a part of the mingw-runtime package.
5 * No warranty is given; refer to the file DISCLAIMER within the package.
6 *
7 * Source code for the startup proceedures used by all programs. This code
8 * is compiled to make crt1.o, which should be located in the library path.
9 *
10 */
11
12 /* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
13 avoid problems with older GCC. */
14 #define __IN_MINGW_RUNTIME
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <io.h>
18 #include <process.h>
19 #include <float.h>
20 #include <math.h>
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 #include <signal.h>
24
25 /* NOTE: The code for initializing the _argv, _argc, and environ variables
26 * has been moved to a separate .c file which is included in both
27 * crt1.c and dllcrt1.c. This means changes in the code don't have to
28 * be manually synchronized, but it does lead to this not-generally-
29 * a-good-idea use of include. */
30 #include "winit.c"
31 #include "cpu_features.h"
32
33 extern void _pei386_runtime_relocator (void);
34
35 extern int wmain (int, wchar_t **, wchar_t **);
36
37 /*
38 * Must have the correct app type for MSVCRT.
39 */
40
41 #ifdef __MSVCRT__
42 #define __UNKNOWN_APP 0
43 #define __CONSOLE_APP 1
44 #define __GUI_APP 2
45 __MINGW_IMPORT void __set_app_type(int);
46 #endif /* __MSVCRT__ */
47
48 /* Global _fmode for this .exe, not the one in msvcrt.dll,
49 The default is set in txtmode.o in libmingw32.a */
50 /* Override the dllimport'd declarations in stdlib.h */
51 #undef _fmode
52 extern int _fmode;
53 #ifdef __MSVCRT__
54 extern int* __p__fmode(void); /* To access the dll _fmode */
55 #endif
56
57 /*
58 * Setup the default file handles to have the _CRT_fmode mode, as well as
59 * any new files created by the user.
60 */
61 extern int _CRT_fmode;
62
63 static void
64 _mingw32_init_fmode (void)
65 {
66 /* Don't set the std file mode if the user hasn't set any value for it. */
67 if (_CRT_fmode)
68 {
69 _fmode = _CRT_fmode;
70
71 /*
72 * This overrides the default file mode settings for stdin,
73 * stdout and stderr. At first I thought you would have to
74 * test with isatty, but it seems that the DOS console at
75 * least is smart enough to handle _O_BINARY stdout and
76 * still display correctly.
77 */
78 if (stdin)
79 {
80 _setmode (_fileno (stdin), _CRT_fmode);
81 }
82 if (stdout)
83 {
84 _setmode (_fileno (stdout), _CRT_fmode);
85 }
86 if (stderr)
87 {
88 _setmode (_fileno (stderr), _CRT_fmode);
89 }
90 }
91
92 /* Now sync the dll _fmode to the one for this .exe. */
93 #ifdef __MSVCRT__
94 *__p__fmode() = _fmode;
95 #else
96 *_imp___fmode_dll = _fmode;
97 #endif
98 }
99
100 /* This function will be called when a trap occurs. Thanks to Jacob
101 Navia for his contribution. */
102 static LONG CALLBACK
103 _gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
104 {
105 void (*old_handler) (int);
106 LONG action = EXCEPTION_CONTINUE_SEARCH;
107 int reset_fpu = 0;
108
109 switch (exception_data->ExceptionRecord->ExceptionCode)
110 {
111 case EXCEPTION_ACCESS_VIOLATION:
112 /* test if the user has set SIGSEGV */
113 old_handler = signal (SIGSEGV, SIG_DFL);
114 if (old_handler == SIG_IGN)
115 {
116 /* this is undefined if the signal was raised by anything other
117 than raise (). */
118 signal (SIGSEGV, SIG_IGN);
119 action = EXCEPTION_CONTINUE_EXECUTION;
120 }
121 else if (old_handler != SIG_DFL)
122 {
123 /* This means 'old' is a user defined function. Call it */
124 (*old_handler) (SIGSEGV);
125 action = EXCEPTION_CONTINUE_EXECUTION;
126 }
127 break;
128
129 case EXCEPTION_ILLEGAL_INSTRUCTION:
130 case EXCEPTION_PRIV_INSTRUCTION:
131 /* test if the user has set SIGILL */
132 old_handler = signal (SIGILL, SIG_DFL);
133 if (old_handler == SIG_IGN)
134 {
135 /* this is undefined if the signal was raised by anything other
136 than raise (). */
137 signal (SIGILL, SIG_IGN);
138 action = EXCEPTION_CONTINUE_EXECUTION;
139 }
140 else if (old_handler != SIG_DFL)
141 {
142 /* This means 'old' is a user defined function. Call it */
143 (*old_handler) (SIGILL);
144 action = EXCEPTION_CONTINUE_EXECUTION;
145 }
146 break;
147
148 case EXCEPTION_FLT_INVALID_OPERATION:
149 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
150 case EXCEPTION_FLT_DENORMAL_OPERAND:
151 case EXCEPTION_FLT_OVERFLOW:
152 case EXCEPTION_FLT_UNDERFLOW:
153 case EXCEPTION_FLT_INEXACT_RESULT:
154 reset_fpu = 1;
155 /* fall through. */
156
157 case EXCEPTION_INT_DIVIDE_BY_ZERO:
158 /* test if the user has set SIGFPE */
159 old_handler = signal (SIGFPE, SIG_DFL);
160 if (old_handler == SIG_IGN)
161 {
162 signal (SIGFPE, SIG_IGN);
163 if (reset_fpu)
164 _fpreset ();
165 action = EXCEPTION_CONTINUE_EXECUTION;
166 }
167 else if (old_handler != SIG_DFL)
168 {
169 /* This means 'old' is a user defined function. Call it */
170 (*old_handler) (SIGFPE);
171 action = EXCEPTION_CONTINUE_EXECUTION;
172 }
173 break;
174
175 default:
176 break;
177 }
178 return action;
179 }
180
181 /*
182 * The function mainCRTStartup is the entry point for all console programs.
183 */
184 static void __attribute__((noreturn))
185 __mingw_wCRTStartup (void)
186 {
187 int nRet;
188
189 /*
190 * Set up the top-level exception handler so that signal handling
191 * works as expected. The mapping between ANSI/POSIX signals and
192 * Win32 SE is not 1-to-1, so caveat emptore.
193 *
194 */
195 SetUnhandledExceptionFilter (_gnu_exception_handler);
196
197 /*
198 * Initialize floating point unit.
199 */
200 __cpu_features_init (); /* Do we have SSE, etc.*/
201 _fpreset (); /* Supplied by the runtime library. */
202
203 /*
204 * Set up __argc, __argv and _wenviron.
205 */
206 _mingw32_init_wmainargs ();
207
208 /*
209 * Sets the default file mode.
210 * If _CRT_fmode is set, also set mode for stdin, stdout
211 * and stderr, as well
212 * NOTE: DLLs don't do this because that would be rude!
213 */
214 _mingw32_init_fmode ();
215
216 /* Adust references to dllimported data that have non-zero offsets. */
217 #if defined(__i386__)
218 _pei386_runtime_relocator ();
219 #endif
220
221 #if defined(__i386__)
222 /* Align the stack to 16 bytes for the sake of SSE ops in main
223 or in functions inlined into main. */
224 asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
225 #elif defined(__mips__)
226 /* Align the stack to 16 bytes */
227 asm __volatile__ ("andi %sp,%sp,-16" : : : "%sp");
228 #elif defined(__PowerPC__)
229 /* Align the stack to 16 bytes */
230 asm __volatile__ ("li 0,15\n\tandc 1,1,0" : : : "r1");
231 #else
232 #error Unsupported architecture
233 #endif
234
235 /*
236 * Call the main function. If the user does not supply one
237 * the one in the 'libmingw32.a' library will be linked in, and
238 * that one calls WinMain. See main.c in the 'lib' dir
239 * for more details.
240 */
241 nRet = wmain (_argc, _wargv, _wenviron);
242
243 /*
244 * Perform exit processing for the C library. This means
245 * flushing output and calling 'atexit' registered functions.
246 */
247 _cexit ();
248
249 ExitProcess (nRet);
250 }
251
252 /*
253 * The function mainCRTStartup is the entry point for all console programs.
254 */
255 void
256 wmainCRTStartup (void)
257 {
258 #ifdef __MSVCRT__
259 __set_app_type (__CONSOLE_APP);
260 #endif
261 __mingw_wCRTStartup ();
262 }
263
264 /*
265 * For now the GUI startup function is the same as the console one.
266 * This simply gets rid of the annoying warning about not being able
267 * to find WinMainCRTStartup when linking GUI applications.
268 */
269 void
270 wWinMainCRTStartup (void)
271 {
272 #ifdef __MSVCRT__
273 __set_app_type (__GUI_APP);
274 #endif
275 __mingw_wCRTStartup ();
276 }
277
278 #if 0
279 /*
280 * We force use of library version of atexit, which is only
281 * visible in import lib as _imp__atexit
282 */
283 extern int (*_imp__atexit)(void (*)(void));
284 int atexit (void (* pfn )(void) )
285 {
286 return ( (*_imp__atexit)(pfn));
287 }
288
289 /* Likewise for non-ANSI _onexit */
290 extern _onexit_t (*_imp___onexit)(_onexit_t);
291 _onexit_t
292 _onexit (_onexit_t pfn )
293 {
294 return (*_imp___onexit)(pfn);
295 }
296 #endif