revert optimization in change#4700 (it appears OPpRUNTIME flag
[p5sagit/p5-mst-13.2.git] / win32 / gstartup.c
CommitLineData
7a958ec3 1/*
2 * gstartup.c
3 *
4 * Startup file for GCC/Mingw32 builds
5 * (replaces gcc's default c:\egcs\...\{crt1.o,dllcrt1.o})
6 *
7 * This file is taken from the Mingw32 package.
8 * Created by Colin Peters for Mingw32
9 * Modified by Mumit Khan
10 *
11 * History with Perl:
12 * Added (in modified form) to Perl standard distribution to fix
13 * problems linking against PerlCRT or MSVCRT
14 * -- Benjamin Stuhl <sho_pi@hotmail.com> 10-17-1999
15*/
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <io.h>
20#include <fcntl.h>
21#include <process.h>
22#include <float.h>
23#include <windows.h>
24#include <signal.h>
25
26/*
27 * Access to a standard 'main'-like argument count and list. Also included
28 * is a table of environment variables.
29 */
30int _argc;
31char **_argv;
32
33extern int _CRT_glob;
34
35#ifdef __MSVCRT__
36typedef struct {
37 int newmode;
38} _startupinfo;
39extern void __getmainargs (int *, char ***, char ***, int, _startupinfo *);
40#else
41extern void __GetMainArgs (int *, char ***, char ***, int);
42#endif
43
44/*
45 * Initialize the _argc, _argv and environ variables.
46 */
47static void
48_mingw32_init_mainargs ()
49{
50 /* The environ variable is provided directly in stdlib.h through
51 * a dll function call. */
52 char **dummy_environ;
53#ifdef __MSVCRT__
54 _startupinfo start_info;
55 start_info.newmode = 0;
56#endif
57
58 /*
59 * Microsoft's runtime provides a function for doing just that.
60 */
61#ifdef __MSVCRT__
62 (void) __getmainargs (&_argc, &_argv, &dummy_environ, _CRT_glob,
63 &start_info);
64#else
65 /* CRTDLL version */
66 (void) __GetMainArgs (&_argc, &_argv, &dummy_environ, _CRT_glob);
67#endif
68}
69
70#if defined(EXESTARTUP) /* gcrt0.o - startup for an executable */
71
72extern int main (int, char **, char **);
73
74/*
75 * Must have the correct app type for MSVCRT.
76 */
77
78#ifdef __MSVCRT__
79#define __UNKNOWN_APP 0
80#define __CONSOLE_APP 1
81#define __GUI_APP 2
82__MINGW_IMPORT void __set_app_type(int);
83#endif /* __MSVCRT__ */
84
85/*
86 * Setup the default file handles to have the _CRT_fmode mode, as well as
87 * any new files created by the user.
88 */
89extern unsigned int _CRT_fmode;
90
91static void
92_mingw32_init_fmode ()
93{
94 /* Don't set the file mode if the user hasn't set any value for it. */
95 if (_CRT_fmode)
96 {
97 _fmode = _CRT_fmode;
98
99 /*
100 * This overrides the default file mode settings for stdin,
101 * stdout and stderr. At first I thought you would have to
102 * test with isatty, but it seems that the DOS console at
103 * least is smart enough to handle _O_BINARY stdout and
104 * still display correctly.
105 */
106 if (stdin)
107 {
108 _setmode (_fileno (stdin), _CRT_fmode);
109 }
110 if (stdout)
111 {
112 _setmode (_fileno (stdout), _CRT_fmode);
113 }
114 if (stderr)
115 {
116 _setmode (_fileno (stderr), _CRT_fmode);
117 }
118 }
119}
120
121/* This function will be called when a trap occurs. Thanks to Jacob
122 Navia for his contribution. */
123static CALLBACK long
124_gnu_exception_handler (EXCEPTION_POINTERS * exception_data)
125{
126 void (*old_handler) (int);
127 long action = EXCEPTION_CONTINUE_SEARCH;
128 int reset_fpu = 0;
129
130 switch (exception_data->ExceptionRecord->ExceptionCode)
131 {
132 case EXCEPTION_ACCESS_VIOLATION:
133 /* test if the user has set SIGSEGV */
134 old_handler = signal (SIGSEGV, 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 (SIGSEGV, 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) (SIGSEGV);
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 */
186static int
187__mingw_CRTStartup ()
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 _fpreset (); /* Supplied by the runtime library. */
203
204 /*
205 * Set up __argc, __argv and _environ.
206 */
207 _mingw32_init_mainargs ();
208
209 /*
210 * Sets the default file mode for stdin, stdout and stderr, as well
211 * as files later opened by the user, to _CRT_fmode.
212 * NOTE: DLLs don't do this because that would be rude!
213 */
214 _mingw32_init_fmode ();
215
216 /*
217 * Call the main function. If the user does not supply one
218 * the one in the 'libmingw32.a' library will be linked in, and
219 * that one calls WinMain. See main.c in the 'lib' dir
220 * for more details.
221 */
222 nRet = main (_argc, _argv, environ);
223
224 /*
225 * Perform exit processing for the C library. This means
226 * flushing output and calling 'atexit' registered functions.
227 */
228 _cexit ();
229
230 ExitProcess (nRet);
231
232 return 0;
233}
234
235/*
236 * The function mainCRTStartup is the entry point for all console programs.
237 */
238int
239mainCRTStartup ()
240{
241#ifdef __MSVCRT__
242 __set_app_type (__CONSOLE_APP);
243#endif
244 __mingw_CRTStartup ();
245 return 0;
246}
247
248/*
249 * For now the GUI startup function is the same as the console one.
250 * This simply gets rid of the annoying warning about not being able
251 * to find WinMainCRTStartup when linking GUI applications.
252 */
253int
254WinMainCRTStartup ()
255{
256#ifdef __MSVCRT__
257 __set_app_type (__GUI_APP);
258#endif
259 __mingw_CRTStartup ();
260}
261
262#elif defined(DLLSTARTUP) /* dllcrt0.o - startup for a DLL */
263
264/* Unlike normal crt1, I don't initialize the FPU, because the process
265 * should have done that already. I also don't set the file handle modes,
266 * because that would be rude. */
267
268#ifdef __GNUC__
269extern void __main ();
270extern void __do_global_dtors ();
271#endif
272
273extern BOOL WINAPI DllMain (HANDLE, DWORD, LPVOID);
274
275BOOL WINAPI
276DllMainCRTStartup (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
277{
278 BOOL bRet;
279
280 if (dwReason == DLL_PROCESS_ATTACH)
281 {
282 _mingw32_init_mainargs ();
283
284#ifdef __GNUC__
285 /* From libgcc.a, calls global class constructors. */
286 __main ();
287#endif
288 }
289
290 /*
291 * Call the user-supplied DllMain subroutine
292 * NOTE: DllMain is optional, so libmingw32.a includes a stub
293 * which will be used if the user does not supply one.
294 */
295 bRet = DllMain (hDll, dwReason, lpReserved);
296
297#ifdef __GNUC__
298 if (dwReason == DLL_PROCESS_DETACH)
299 {
300 /* From libgcc.a, calls global class destructors. */
301 __do_global_dtors ();
302 }
303#endif
304
305 return bRet;
306}
307
308/*
309 * For the moment a dummy atexit. Atexit causes problems in DLLs, especially
310 * if they are dynamically loaded. For now atexit inside a DLL does nothing.
311 * NOTE: We need this even if the DLL author never calls atexit because
312 * the global constructor function __do_global_ctors called from __main
313 * will attempt to register __do_global_dtors using atexit.
314 * Thanks to Andrey A. Smirnov for pointing this one out.
315 */
316int
317atexit (void (*pfn) ())
318{
319 return 0;
320}
321
322#else
323#error No startup target!
324#endif /* EXESTARTUP */