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