1 /****************************************************************************
3 * GNAT COMPILER COMPONENTS *
5 * I N I T I A L I Z E *
7 * C Implementation File *
9 * Copyright (C) 2014-2019, Free Software Foundation, Inc. *
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. *
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. *
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/>. *
27 * GNAT was originally developed by the GNAT team at New York University. *
28 * Extensive contributions were provided by Ada Core Technologies Inc. *
30 ****************************************************************************/
32 /* This unit provides implementation for __gnat_runtime_initialize ()
33 which is called in adainit() to do special initialization needed by
37 /* The following include is here to meet the published VxWorks requirement
38 that the __vxworks header appear before any other include. */
44 /* We don't have libiberty, so use malloc. */
45 #define xmalloc(S) malloc (S)
46 #define xrealloc(V,S) realloc (V,S)
59 /**************************************************/
60 /* __gnat_runtime_initialize (NT-mingw32 Version) */
61 /**************************************************/
63 extern void __gnat_install_handler (void);
65 int __gnat_wide_text_translation_required
= 0;
66 /* wide text translation, 0=none, 1=activated */
68 int __gnat_rt_init_count
= 0;
69 /* number of references to the GNAT runtime, this is used to initialize
70 and finalize properly the run-time. */
72 #if defined (__MINGW32__)
76 extern void __gnat_init_float (void);
79 extern char **gnat_argv
;
80 extern CRITICAL_SECTION ProcListCS
;
81 extern HANDLE ProcListEvt
;
83 #ifdef GNAT_UNICODE_SUPPORT
85 #define EXPAND_ARGV_RATE 128
87 int __gnat_do_argv_expansion
= 1;
88 #pragma weak __gnat_do_argv_expansion
90 /* Assuming we are pointing to the beginning of a quoted part of an
91 argument, skip until the end of the quoted part. */
92 static void skip_quoted_string (const WCHAR
**current_in
,
95 /* Number of backslashes buffered. */
98 /* Pointer to current input character. */
99 const WCHAR
*ci
= *current_in
;
101 /* Pointer to next output character. */
102 WCHAR
*co
= *current_out
;
104 /* Skip initial quote. */
111 /* Buffer incoming backslashes. */
116 /* Append qbs_count / 2 backslahes. */
117 for (int i
=0; i
<qbs_count
/ 2; i
++)
122 if ((qbs_count
& 1) == 0)
124 /* 2n backslashes means that the quotation mark is the end of
125 the quoted portion. */
131 /* Otherwise this is a double quote literal. */
138 /* If the character is not a double quote we should append
139 qbs_count backslashes. */
140 for (int i
=0; i
<qbs_count
; i
++)
154 /* Assuming that this is the beginning of an argument. Skip characters
155 until we reach the character right after the last argument character. */
156 static void skip_argument (const WCHAR
**current_in
,
159 /* Number of backslashes buffered. */
162 /* Pointer to current input character. */
163 const WCHAR
*ci
= *current_in
;
165 /* Pointer to next output character. */
166 WCHAR
*co
= *current_out
;
168 while (*ci
&& ! (*ci
== ' ' || *ci
== '\t'))
172 /* Buffer incoming backslashes. */
177 /* Append qbs_count / 2 backslahes. */
178 for (int i
=0; i
< bs_count
/ 2; i
++)
182 if ((bs_count
& 1) == 0)
184 /* 2n backslashes followed by a quotation mark means that
185 this is a start of a quoted string. */
186 skip_quoted_string (&ci
, &co
);
190 /* Otherwise this is quotation mark literal. */
198 /* This is a regular character. */
199 /* Backslashes are interpreted literally. */
200 for (int i
=0; i
<bs_count
; i
++)
211 for (int i
=0; i
<bs_count
; i
++)
217 /* End the argument with a null character. */
226 void __gnat_get_argw (const WCHAR
*command_line
, WCHAR
***argv
, int *argc
)
234 (WCHAR
*) xmalloc ((wcslen (command_line
) + 1) * sizeof (WCHAR
));
237 /* Start iteration on command line characters. */
240 /* Skip command name. Note that if the command line starts with whitechars
241 then the command name will be the empty string. */
242 skip_argument (&ci
, &co
);
244 /* Count remaining arguments. */
248 while (*ci
&& (*ci
== ' ' || *ci
== '\t')) { ci
++; }
251 skip_argument (&ci
, &co
);
258 /* Allocate table with pointer to each arguments */
259 argv
[0] = (WCHAR
**) xmalloc (arg_count
* sizeof (WCHAR
*));
261 for (int idx
= 0; idx
< arg_count
; idx
++)
263 argv
[0][idx
] = inline_argv
;
274 append_arg (int *index
, LPWSTR dir
, LPWSTR value
,
275 char ***argv
, int *last
, int quoted
)
279 int vallen
= _tcslen (value
);
286 fullvalue
= (LPWSTR
) xmalloc ((vallen
+ 1) * sizeof (TCHAR
));
291 dirlen
= _tcslen (dir
);
293 fullvalue
= (LPWSTR
) xmalloc ((dirlen
+ vallen
+ 1) * sizeof (TCHAR
));
294 _tcscpy (fullvalue
, dir
);
301 _tcsncpy (fullvalue
+ dirlen
, value
+ 1, vallen
- 1);
302 fullvalue
[dirlen
+ vallen
- sizeof (TCHAR
)] = _T ('\0');
305 _tcscpy (fullvalue
+ dirlen
, value
);
309 *last
+= EXPAND_ARGV_RATE
;
310 *argv
= (char **) xrealloc (*argv
, (*last
) * sizeof (char *));
313 size
= WS2SC (NULL
, fullvalue
, 0);
314 (*argv
)[*index
] = (char *) xmalloc (size
+ sizeof (TCHAR
));
315 WS2SC ((*argv
)[*index
], fullvalue
, size
);
324 __gnat_runtime_initialize (int install_handler
)
326 /* increment the reference counter */
328 __gnat_rt_init_count
++;
330 /* if already initialized return now */
331 if (__gnat_rt_init_count
> 1)
334 /* Initialize floating-point coprocessor. This call is needed because
335 the MS libraries default to 64-bit precision instead of 80-bit
336 precision, and we require the full precision for proper operation,
337 given that we have set Max_Digits etc with this in mind */
339 __gnat_init_float ();
341 /* Initialize the critical section and event handle for the win32_wait()
342 implementation, see adaint.c */
344 InitializeCriticalSection (&ProcListCS
);
345 ProcListEvt
= CreateEvent (NULL
, FALSE
, FALSE
, NULL
);
347 #ifdef GNAT_UNICODE_SUPPORT
348 /* Set current code page for filenames handling. */
350 char *codepage
= getenv ("GNAT_CODE_PAGE");
352 /* Default code page is UTF-8. */
353 __gnat_current_codepage
= CP_UTF8
;
355 if (codepage
!= NULL
)
357 if (strcmp (codepage
, "CP_ACP") == 0)
358 __gnat_current_codepage
= CP_ACP
;
359 else if (strcmp (codepage
, "CP_UTF8") == 0)
360 __gnat_current_codepage
= CP_UTF8
;
364 /* Set current encoding for the IO. */
366 char *ccsencoding
= getenv ("GNAT_CCS_ENCODING");
368 /* Default CCS Encoding. */
369 __gnat_current_ccs_encoding
= _O_TEXT
;
370 __gnat_wide_text_translation_required
= 0;
372 if (ccsencoding
!= NULL
)
374 if (strcmp (ccsencoding
, "U16TEXT") == 0)
376 __gnat_current_ccs_encoding
= _O_U16TEXT
;
377 __gnat_wide_text_translation_required
= 1;
379 else if (strcmp (ccsencoding
, "TEXT") == 0)
381 __gnat_current_ccs_encoding
= _O_TEXT
;
382 __gnat_wide_text_translation_required
= 0;
384 else if (strcmp (ccsencoding
, "WTEXT") == 0)
386 __gnat_current_ccs_encoding
= _O_WTEXT
;
387 __gnat_wide_text_translation_required
= 1;
389 else if (strcmp (ccsencoding
, "U8TEXT") == 0)
391 __gnat_current_ccs_encoding
= _O_U8TEXT
;
392 __gnat_wide_text_translation_required
= 1;
397 /* Adjust gnat_argv to support Unicode characters. */
403 int argc_expanded
= 0;
404 TCHAR result
[MAX_PATH
];
407 __gnat_get_argw (GetCommandLineW (), &wargv
, &wargc
);
411 /* Set gnat_argv with arguments encoded in UTF-8. */
413 gnat_argv
= (char **) xmalloc ((last
) * sizeof (char *));
415 /* argv[0] is the executable full path-name. */
417 SearchPath (NULL
, wargv
[0], _T(".exe"), MAX_PATH
, result
, NULL
);
418 append_arg (&argc_expanded
, NULL
, result
, &gnat_argv
, &last
, 0);
420 for (k
=1; k
<wargc
; k
++)
422 quoted
= (wargv
[k
][0] == _T('\''));
424 /* Check for wildcard expansion if the argument is not quoted. */
425 if (!quoted
&& __gnat_do_argv_expansion
426 && (_tcsstr (wargv
[k
], _T("?")) != 0 ||
427 _tcsstr (wargv
[k
], _T("*")) != 0))
429 /* Wilcards are present, append all corresponding matches. */
430 WIN32_FIND_DATA FileData
;
431 HANDLE hDir
= FindFirstFile (wargv
[k
], &FileData
);
433 LPWSTR ldir
= _tcsrchr (wargv
[k
], _T('\\'));
436 ldir
= _tcsrchr (wargv
[k
], _T('/'));
438 if (hDir
== INVALID_HANDLE_VALUE
)
440 /* No match, append arg as-is. */
441 append_arg (&argc_expanded
, NULL
, wargv
[k
],
442 &gnat_argv
, &last
, quoted
);
448 int n
= ldir
- wargv
[k
] + 1;
449 dir
= (LPWSTR
) xmalloc ((n
+ 1) * sizeof (TCHAR
));
450 _tcsncpy (dir
, wargv
[k
], n
);
454 /* Append first match and all remaining ones. */
457 /* Do not add . and .. special entries */
459 if (_tcscmp (FileData
.cFileName
, _T(".")) != 0
460 && _tcscmp (FileData
.cFileName
, _T("..")) != 0)
461 append_arg (&argc_expanded
, dir
, FileData
.cFileName
,
462 &gnat_argv
, &last
, 0);
463 } while (FindNextFile (hDir
, &FileData
));
473 /* No wildcard. Store parameter as-is. Remove quote if
475 append_arg (&argc_expanded
, NULL
, wargv
[k
],
477 quoted
&& __gnat_do_argv_expansion
);
483 gnat_argc
= argc_expanded
;
484 gnat_argv
= (char **) xrealloc
485 (gnat_argv
, argc_expanded
* sizeof (char *));
491 __gnat_install_handler();
494 /**************************************************/
495 /* __gnat_runtime_initialize (init_float version) */
496 /**************************************************/
498 #elif defined (__Lynx__) || defined (__FreeBSD__) || defined(__NetBSD__) \
499 || defined (__OpenBSD__)
501 extern void __gnat_init_float (void);
504 __gnat_runtime_initialize(int install_handler
)
506 /* increment the reference counter */
508 __gnat_rt_init_count
++;
510 /* if already initialized return now */
511 if (__gnat_rt_init_count
> 1)
514 __gnat_init_float ();
517 __gnat_install_handler();
520 /***********************************************/
521 /* __gnat_runtime_initialize (VxWorks Version) */
522 /***********************************************/
524 #elif defined(__vxworks)
526 extern void __gnat_init_float (void);
529 __gnat_runtime_initialize(int install_handler
)
531 /* increment the reference counter */
533 __gnat_rt_init_count
++;
535 /* if already initialized return now */
536 if (__gnat_rt_init_count
> 1)
539 __gnat_init_float ();
542 __gnat_install_handler();
547 /***********************************************/
548 /* __gnat_runtime_initialize (default version) */
549 /***********************************************/
552 __gnat_runtime_initialize(int install_handler
)
554 /* increment the reference counter */
556 __gnat_rt_init_count
++;
558 /* if already initialized return now */
559 if (__gnat_rt_init_count
> 1)
563 __gnat_install_handler();