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