OSDN Git Service

MinGW-Feature-Request [2222263]: Make getopt() GNU / BSD compatibile.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / 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 __main ();
33 extern void _pei386_runtime_relocator (void);
34
35 extern int main (int, char **, char **);
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 CALLBACK long
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_CRTStartup (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 _environ.
205    */
206   _mingw32_init_mainargs ();
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   _pei386_runtime_relocator ();
218
219   /* Align the stack to 16 bytes for the sake of SSE ops in main
220      or in functions inlined into main.  */
221   asm  __volatile__  ("andl $-16, %%esp" : : : "%esp");
222
223    /* From libgcc.a, __main calls global class constructors via
224       __do_global_ctors, This in turn  registers  __do_global_dtors
225       as the first entry of the app's atexit table.  We do this
226       explicitly at app startup rather than rely on gcc to generate
227       the call in main's  prologue, since main may be imported from a dll
228       which has its own __do_global_ctors.  */
229     __main ();
230
231   /*
232    * Call the main function. If the user does not supply one
233    * the one in the 'libmingw32.a' library will be linked in, and
234    * that one calls WinMain. See main.c in the 'lib' dir
235    * for more details.
236    */
237   nRet = main (_argc, _argv, environ);
238
239   /*
240    * Perform exit processing for the C library. This means
241    * flushing output and calling 'atexit' registered functions.
242    */
243   _cexit ();
244
245   ExitProcess (nRet);
246 }
247
248 /*
249  * The function mainCRTStartup is the entry point for all console programs.
250  */
251 void
252 mainCRTStartup (void)
253 {
254 #ifdef __MSVCRT__
255   __set_app_type (__CONSOLE_APP);
256 #endif
257   __mingw_CRTStartup ();
258 }
259
260 /*
261  * For now the GUI startup function is the same as the console one.
262  * This simply gets rid of the annoying warning about not being able
263  * to find WinMainCRTStartup when linking GUI applications.
264  */
265 void
266 WinMainCRTStartup (void)
267 {
268 #ifdef __MSVCRT__
269   __set_app_type (__GUI_APP);
270 #endif
271   __mingw_CRTStartup ();
272 }
273
274 /*
275  *  We force use of library version of atexit, which is only
276  *  visible in import lib as _imp__atexit
277  */
278 extern int (*_imp__atexit)(void (*)(void));
279 int atexit (void (* pfn )(void) )
280 {
281   return ( (*_imp__atexit)(pfn));
282 }
283
284 /* Likewise for non-ANSI _onexit */
285 extern _onexit_t (*_imp___onexit)(_onexit_t);
286 _onexit_t
287 _onexit (_onexit_t pfn )
288 {
289   return (*_imp___onexit)(pfn);
290 }