1/****************************************************************************
2 *                                                                          *
3 *                         GNAT COMPILER COMPONENTS                         *
4 *                                                                          *
5 *                           I N I T I A L I Z E                            *
6 *                                                                          *
7 *                          C Implementation File                           *
8 *                                                                          *
9 *            Copyright (C) 2014-2015, Free Software Foundation, Inc.       *
10 *                                                                          *
11 * GNAT is free software;  you can  redistribute it  and/or modify it under *
12 * terms of the  GNU General Public License as published  by the Free Soft- *
13 * ware  Foundation;  either version 3,  or (at your option) any later ver- *
14 * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
15 * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
16 * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
17 *                                                                          *
18 * As a special exception under Section 7 of GPL version 3, you are granted *
19 * additional permissions described in the GCC Runtime Library Exception,   *
20 * version 3.1, as published by the Free Software Foundation.               *
21 *                                                                          *
22 * You should have received a copy of the GNU General Public License and    *
23 * a copy of the GCC Runtime Library Exception along with this program;     *
24 * see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    *
25 * <http://www.gnu.org/licenses/>.                                          *
26 *                                                                          *
27 * GNAT was originally developed  by the GNAT team at  New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc.      *
29 *                                                                          *
30 ****************************************************************************/
31
32/*  This unit provides implementation for __gnat_runtime_initialize ()
33    which is called in adainit() to do special initialization needed by
34    the GNAT runtime.  */
35
36
37/* The following include is here to meet the published VxWorks requirement
38   that the __vxworks header appear before any other include.  */
39#ifdef __vxworks
40#include "vxWorks.h"
41#endif
42
43#ifdef IN_RTS
44#include "tconfig.h"
45#include "tsystem.h"
46/* We don't have libiberty, so use malloc.  */
47#define xmalloc(S) malloc (S)
48#define xrealloc(V,S) realloc (V,S)
49#else
50#include "config.h"
51#include "system.h"
52#endif
53
54#include "raise.h"
55#include <fcntl.h>
56
57#ifdef __cplusplus
58extern "C" {
59#endif
60
61/**************************************************/
62/* __gnat_runtime_initialize (NT-mingw32 Version) */
63/**************************************************/
64
65extern void __gnat_install_handler(void);
66
67int __gnat_wide_text_translation_required = 0;
68/* wide text translation, 0=none, 1=activated */
69
70int __gnat_rt_init_count = 0;
71/* number of references to the GNAT runtime, this is used to initialize
72   and finalize properly the run-time. */
73
74#if defined (__MINGW32__)
75#include "mingw32.h"
76#include <windows.h>
77
78extern void __gnat_init_float (void);
79
80extern int gnat_argc;
81extern char **gnat_argv;
82extern CRITICAL_SECTION ProcListCS;
83extern HANDLE ProcListEvt;
84
85#ifdef GNAT_UNICODE_SUPPORT
86
87#define EXPAND_ARGV_RATE 128
88
89static void
90append_arg (int *index, LPWSTR dir, LPWSTR value,
91	    char ***argv, int *last, int quoted)
92{
93  int size;
94  LPWSTR fullvalue;
95  int vallen = _tcslen (value);
96  int dirlen;
97
98  if (dir == NULL)
99    {
100      /* no dir prefix */
101      dirlen = 0;
102      fullvalue = (LPWSTR) xmalloc ((vallen + 1) * sizeof(TCHAR));
103    }
104  else
105    {
106      /* Add dir first */
107      dirlen = _tcslen (dir);
108
109      fullvalue = (LPWSTR) xmalloc ((dirlen + vallen + 1) * sizeof(TCHAR));
110      _tcscpy (fullvalue, dir);
111    }
112
113  /* Append value */
114
115  if (quoted)
116    {
117      _tcsncpy (fullvalue + dirlen, value + 1, vallen - 1);
118      fullvalue [dirlen + vallen - sizeof(TCHAR)] = _T('\0');
119    }
120  else
121    _tcscpy (fullvalue + dirlen, value);
122
123  if (*last <= *index)
124    {
125      *last += EXPAND_ARGV_RATE;
126      *argv = (char **) xrealloc (*argv, (*last) * sizeof (char *));
127    }
128
129  size = WS2SC (NULL, fullvalue, 0);
130  (*argv)[*index] = (char *) xmalloc (size + sizeof(TCHAR));
131  WS2SC ((*argv)[*index], fullvalue, size);
132
133  free (fullvalue);
134
135  (*index)++;
136}
137#endif
138
139void
140__gnat_runtime_initialize(int install_handler)
141{
142  /*  increment the reference counter */
143
144  __gnat_rt_init_count++;
145
146  /*  if already initialized return now */
147  if (__gnat_rt_init_count > 1)
148    return;
149
150   /* Initialize floating-point coprocessor. This call is needed because
151      the MS libraries default to 64-bit precision instead of 80-bit
152      precision, and we require the full precision for proper operation,
153      given that we have set Max_Digits etc with this in mind */
154
155   __gnat_init_float ();
156
157   /* Initialize the critical section and event handle for the win32_wait()
158      implementation, see adaint.c */
159
160   InitializeCriticalSection (&ProcListCS);
161   ProcListEvt = CreateEvent (NULL, FALSE, FALSE, NULL);
162
163#ifdef GNAT_UNICODE_SUPPORT
164   /* Set current code page for filenames handling. */
165   {
166     char *codepage = getenv ("GNAT_CODE_PAGE");
167
168     /* Default code page is UTF-8.  */
169     CurrentCodePage = CP_UTF8;
170
171     if (codepage != NULL)
172       {
173	 if (strcmp (codepage, "CP_ACP") == 0)
174	   CurrentCodePage = CP_ACP;
175	 else if (strcmp (codepage, "CP_UTF8") == 0)
176	   CurrentCodePage = CP_UTF8;
177       }
178   }
179
180   /* Set current encoding for the IO.  */
181   {
182     char *ccsencoding = getenv ("GNAT_CCS_ENCODING");
183
184     /* Default CCS Encoding.  */
185     CurrentCCSEncoding = _O_TEXT;
186     __gnat_wide_text_translation_required = 0;
187
188     if (ccsencoding != NULL)
189       {
190	 if (strcmp (ccsencoding, "U16TEXT") == 0)
191           {
192             CurrentCCSEncoding = _O_U16TEXT;
193             __gnat_wide_text_translation_required = 1;
194           }
195	 else if (strcmp (ccsencoding, "TEXT") == 0)
196           {
197             CurrentCCSEncoding = _O_TEXT;
198             __gnat_wide_text_translation_required = 0;
199           }
200	 else if (strcmp (ccsencoding, "WTEXT") == 0)
201           {
202             CurrentCCSEncoding = _O_WTEXT;
203             __gnat_wide_text_translation_required = 1;
204           }
205	 else if (strcmp (ccsencoding, "U8TEXT") == 0)
206           {
207             CurrentCCSEncoding = _O_U8TEXT;
208             __gnat_wide_text_translation_required = 1;
209           }
210       }
211   }
212
213   /* Adjust gnat_argv to support Unicode characters. */
214   {
215     LPWSTR *wargv;
216     int wargc;
217     int k;
218     int last;
219     int argc_expanded = 0;
220     TCHAR result [MAX_PATH];
221     int quoted;
222
223     wargv = CommandLineToArgvW (GetCommandLineW(), &wargc);
224
225     if (wargv != NULL)
226       {
227	 /* Set gnat_argv with arguments encoded in UTF-8. */
228	 last = wargc + 1;
229	 gnat_argv = (char **) xmalloc ((last) * sizeof (char *));
230
231	 /* argv[0] is the executable full path-name. */
232
233	 SearchPath (NULL, wargv[0], _T(".exe"), MAX_PATH, result, NULL);
234	 append_arg (&argc_expanded, NULL, result, &gnat_argv, &last, 0);
235
236	 for (k=1; k<wargc; k++)
237	   {
238	     quoted = (wargv[k][0] == _T('\''));
239
240	     /* Check for wildcard expansion if the argument is not quoted. */
241	     if (!quoted
242		 && (_tcsstr (wargv[k], _T("?")) != 0 ||
243		     _tcsstr (wargv[k], _T("*")) != 0))
244	       {
245		 /* Wilcards are present, append all corresponding matches. */
246		 WIN32_FIND_DATA FileData;
247		 HANDLE hDir = FindFirstFile (wargv[k], &FileData);
248		 LPWSTR dir = NULL;
249		 LPWSTR ldir = _tcsrchr (wargv[k], _T('\\'));
250
251		 if (ldir == NULL)
252		   ldir = _tcsrchr (wargv[k], _T('/'));
253
254		 if (hDir == INVALID_HANDLE_VALUE)
255		   {
256		     /* No match, append arg as-is. */
257		     append_arg (&argc_expanded, NULL, wargv[k],
258				 &gnat_argv, &last, quoted);
259		   }
260		 else
261		   {
262		     if (ldir != NULL)
263		       {
264			 int n = ldir - wargv[k] + 1;
265			 dir = (LPWSTR) xmalloc ((n + 1) * sizeof (TCHAR));
266			 _tcsncpy (dir, wargv[k], n);
267			 dir[n] = _T('\0');
268		       }
269
270		     /* Append first match and all remaining ones.  */
271
272		     do {
273		       /* Do not add . and .. special entries */
274
275		       if (_tcscmp (FileData.cFileName, _T(".")) != 0
276			   && _tcscmp (FileData.cFileName, _T("..")) != 0)
277			 append_arg (&argc_expanded, dir, FileData.cFileName,
278				     &gnat_argv, &last, 0);
279		     } while (FindNextFile (hDir, &FileData));
280
281		     FindClose (hDir);
282
283		     if (dir != NULL)
284		       free (dir);
285		   }
286	       }
287	     else
288	       {
289		 /*  No wildcard. Store parameter as-is. Remove quote if
290		     needed. */
291		 append_arg (&argc_expanded, NULL, wargv[k],
292			     &gnat_argv, &last, quoted);
293	       }
294	   }
295
296	 LocalFree (wargv);
297	 gnat_argc = argc_expanded;
298	 gnat_argv = (char **) xrealloc
299	   (gnat_argv, argc_expanded * sizeof (char *));
300       }
301   }
302#endif
303
304  if (install_handler)
305    __gnat_install_handler();
306}
307
308/**************************************************/
309/* __gnat_runtime_initialize (init_float version) */
310/**************************************************/
311
312#elif defined (__Lynx__) || defined (__FreeBSD__) || defined(__NetBSD__) \
313  || defined (__OpenBSD__)
314
315extern void __gnat_init_float (void);
316
317void
318__gnat_runtime_initialize(int install_handler)
319{
320  /*  increment the reference counter */
321
322  __gnat_rt_init_count++;
323
324  /*  if already initialized return now */
325  if (__gnat_rt_init_count > 1)
326    return;
327
328   __gnat_init_float ();
329
330  if (install_handler)
331    __gnat_install_handler();
332}
333
334/***********************************************/
335/* __gnat_runtime_initialize (VxWorks Version) */
336/***********************************************/
337
338#elif defined(__vxworks)
339
340extern void __gnat_init_float (void);
341
342void
343__gnat_runtime_initialize(int install_handler)
344{
345  /*  increment the reference counter */
346
347  __gnat_rt_init_count++;
348
349  /*  if already initialized return now */
350  if (__gnat_rt_init_count > 1)
351    return;
352
353  __gnat_init_float ();
354
355  if (install_handler)
356    __gnat_install_handler();
357}
358
359#else
360
361/***********************************************/
362/* __gnat_runtime_initialize (default version) */
363/***********************************************/
364
365void
366__gnat_runtime_initialize(int install_handler)
367{
368  /*  increment the reference counter */
369
370  __gnat_rt_init_count++;
371
372  /*  if already initialized return now */
373  if (__gnat_rt_init_count > 1)
374    return;
375
376  if (install_handler)
377    __gnat_install_handler();
378}
379
380#endif
381
382#ifdef __cplusplus
383}
384#endif
385