mirror of
https://github.com/autc04/Retro68.git
synced 2024-09-27 12:57:21 +00:00
587 lines
15 KiB
C
587 lines
15 KiB
C
/****************************************************************************
|
|
* *
|
|
* GNAT COMPILER COMPONENTS *
|
|
* *
|
|
* I N I T I A L I Z E *
|
|
* *
|
|
* C Implementation File *
|
|
* *
|
|
* Copyright (C) 2014-2022, Free Software Foundation, Inc. *
|
|
* *
|
|
* GNAT is free software; you can redistribute it and/or modify it under *
|
|
* terms of the GNU General Public License as published by the Free Soft- *
|
|
* ware Foundation; either version 3, or (at your option) any later ver- *
|
|
* sion. GNAT is distributed in the hope that it will be useful, but WITH- *
|
|
* OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY *
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. *
|
|
* *
|
|
* As a special exception under Section 7 of GPL version 3, you are granted *
|
|
* additional permissions described in the GCC Runtime Library Exception, *
|
|
* version 3.1, as published by the Free Software Foundation. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License and *
|
|
* a copy of the GCC Runtime Library Exception along with this program; *
|
|
* see the files COPYING3 and COPYING.RUNTIME respectively. If not, see *
|
|
* <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
* GNAT was originally developed by the GNAT team at New York University. *
|
|
* Extensive contributions were provided by Ada Core Technologies Inc. *
|
|
* *
|
|
****************************************************************************/
|
|
|
|
/* This unit provides implementation for __gnat_runtime_initialize ()
|
|
which is called in adainit() to do special initialization needed by
|
|
the GNAT runtime. */
|
|
|
|
|
|
/* The following include is here to meet the published VxWorks requirement
|
|
that the __vxworks header appear before any other include. */
|
|
#ifdef __vxworks
|
|
#include "vxWorks.h"
|
|
#endif
|
|
|
|
#ifdef IN_RTS
|
|
/* We don't have libiberty, so use malloc. */
|
|
#define xmalloc(S) malloc (S)
|
|
#define xrealloc(V,S) realloc (V,S)
|
|
#else
|
|
#include "config.h"
|
|
#include "system.h"
|
|
#endif
|
|
|
|
#include "raise.h"
|
|
#include <fcntl.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**************************************************/
|
|
/* __gnat_runtime_initialize (NT-mingw32 Version) */
|
|
/**************************************************/
|
|
|
|
extern void __gnat_install_handler (void);
|
|
|
|
int __gnat_wide_text_translation_required = 0;
|
|
/* wide text translation, 0=none, 1=activated */
|
|
|
|
int __gnat_rt_init_count = 0;
|
|
/* number of references to the GNAT runtime, this is used to initialize
|
|
and finalize properly the run-time. */
|
|
|
|
#if defined (__MINGW32__)
|
|
#include "mingw32.h"
|
|
#include <windows.h>
|
|
|
|
extern void __gnat_init_float (void);
|
|
|
|
extern int gnat_argc;
|
|
extern char **gnat_argv;
|
|
extern CRITICAL_SECTION ProcListCS;
|
|
extern HANDLE ProcListEvt;
|
|
|
|
#ifdef GNAT_UNICODE_SUPPORT
|
|
|
|
#define EXPAND_ARGV_RATE 128
|
|
|
|
int __gnat_do_argv_expansion = 1;
|
|
#pragma weak __gnat_do_argv_expansion
|
|
|
|
/* Assuming we are pointing to the beginning of a quoted part of an
|
|
argument, skip until the end of the quoted part. */
|
|
static void skip_quoted_string (const WCHAR **current_in,
|
|
WCHAR **current_out)
|
|
{
|
|
/* Number of backslashes buffered. */
|
|
int qbs_count = 0;
|
|
|
|
/* Pointer to current input character. */
|
|
const WCHAR *ci = *current_in;
|
|
|
|
/* Pointer to next output character. */
|
|
WCHAR *co = *current_out;
|
|
|
|
/* Skip initial quote. */
|
|
ci++;
|
|
|
|
while (*ci)
|
|
{
|
|
if (*ci == '\\')
|
|
{
|
|
/* Buffer incoming backslashes. */
|
|
qbs_count++;
|
|
}
|
|
else if (*ci == '"')
|
|
{
|
|
/* Append qbs_count / 2 backslahes. */
|
|
for (int i=0; i<qbs_count / 2; i++)
|
|
{
|
|
*co = '\\';
|
|
co++;
|
|
}
|
|
if ((qbs_count & 1) == 0)
|
|
{
|
|
/* 2n backslashes means that the quotation mark is the end of
|
|
the quoted portion. */
|
|
qbs_count = 0;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise this is a double quote literal. */
|
|
qbs_count = 0;
|
|
*co = '"'; co++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* If the character is not a double quote we should append
|
|
qbs_count backslashes. */
|
|
for (int i=0; i<qbs_count; i++)
|
|
{
|
|
*co = '\\';
|
|
co++;
|
|
}
|
|
*co = *ci; co++;
|
|
qbs_count = 0;
|
|
}
|
|
ci++;
|
|
}
|
|
|
|
/* Handle the case in which a nul character was found instead of a closing
|
|
double quote. In that case consider all the backslashes as literal
|
|
characters. */
|
|
if (*ci == '\0')
|
|
{
|
|
for (int i=0; i<qbs_count; i++)
|
|
{
|
|
*co='\\';
|
|
co++;
|
|
}
|
|
}
|
|
|
|
*current_in = ci;
|
|
*current_out = co;
|
|
}
|
|
|
|
/* Assuming that this is the beginning of an argument. Skip characters
|
|
until we reach the character right after the last argument character. */
|
|
static void skip_argument (const WCHAR **current_in,
|
|
WCHAR **current_out)
|
|
{
|
|
/* Number of backslashes buffered. */
|
|
int bs_count = 0;
|
|
|
|
/* Pointer to current input character. */
|
|
const WCHAR *ci = *current_in;
|
|
|
|
/* Pointer to next output character. */
|
|
WCHAR *co = *current_out;
|
|
|
|
while (*ci && ! (*ci == ' ' || *ci == '\t'))
|
|
{
|
|
if (*ci == '\\')
|
|
{
|
|
/* Buffer incoming backslashes. */
|
|
bs_count++;
|
|
}
|
|
else if (*ci == '"')
|
|
{
|
|
/* Append qbs_count / 2 backslahes. */
|
|
for (int i=0; i< bs_count / 2; i++)
|
|
{
|
|
*co = '\\'; co++;
|
|
}
|
|
if ((bs_count & 1) == 0)
|
|
{
|
|
/* 2n backslashes followed by a quotation mark means that
|
|
this is a start of a quoted string. */
|
|
skip_quoted_string (&ci, &co);
|
|
}
|
|
else
|
|
{
|
|
/* Otherwise this is quotation mark literal. */
|
|
*co = '"';
|
|
co++;
|
|
}
|
|
bs_count = 0;
|
|
}
|
|
else
|
|
{
|
|
/* This is a regular character. */
|
|
/* Backslashes are interpreted literally. */
|
|
for (int i=0; i<bs_count; i++)
|
|
{
|
|
*co = '\\';
|
|
co++;
|
|
}
|
|
bs_count = 0;
|
|
*co = *ci; co++;
|
|
}
|
|
if (*ci != '\0')
|
|
{
|
|
ci++;
|
|
}
|
|
}
|
|
|
|
for (int i=0; i<bs_count; i++)
|
|
{
|
|
*co = '\\';
|
|
co++;
|
|
}
|
|
|
|
/* End the argument with a null character. */
|
|
*co = '\0';
|
|
co++;
|
|
|
|
*current_in = ci;
|
|
*current_out = co;
|
|
}
|
|
|
|
|
|
void __gnat_get_argw (const WCHAR *command_line, WCHAR ***argv, int *argc)
|
|
{
|
|
WCHAR *inline_argv;
|
|
WCHAR *co;
|
|
int arg_count = 1;
|
|
const WCHAR *ci;
|
|
|
|
inline_argv =
|
|
(WCHAR *) xmalloc ((wcslen (command_line) + 1) * sizeof (WCHAR));
|
|
co = inline_argv;
|
|
|
|
/* Start iteration on command line characters. */
|
|
ci = command_line;
|
|
|
|
/* Skip command name. Note that if the command line starts with whitechars
|
|
then the command name will be the empty string. */
|
|
skip_argument (&ci, &co);
|
|
|
|
/* Count remaining arguments. */
|
|
while (*ci)
|
|
{
|
|
/* skip whitechar */
|
|
while (*ci && (*ci == ' ' || *ci == '\t')) { ci++; }
|
|
if (*ci)
|
|
{
|
|
skip_argument (&ci, &co);
|
|
arg_count++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
/* Allocate table with pointer to each arguments */
|
|
argv[0] = (WCHAR **) xmalloc (arg_count * sizeof (WCHAR *));
|
|
|
|
for (int idx = 0; idx < arg_count; idx++)
|
|
{
|
|
argv[0][idx] = inline_argv;
|
|
while (*inline_argv)
|
|
{
|
|
inline_argv++;
|
|
}
|
|
inline_argv++;
|
|
}
|
|
*argc = arg_count;
|
|
}
|
|
|
|
static void
|
|
append_arg (int *index, LPWSTR dir, LPWSTR value,
|
|
char ***argv, int *last, int quoted)
|
|
{
|
|
int size;
|
|
LPWSTR fullvalue;
|
|
int vallen = _tcslen (value);
|
|
int dirlen;
|
|
|
|
if (dir == NULL)
|
|
{
|
|
/* no dir prefix */
|
|
dirlen = 0;
|
|
fullvalue = (LPWSTR) xmalloc ((vallen + 1) * sizeof (TCHAR));
|
|
}
|
|
else
|
|
{
|
|
/* Add dir first */
|
|
dirlen = _tcslen (dir);
|
|
|
|
fullvalue = (LPWSTR) xmalloc ((dirlen + vallen + 1) * sizeof (TCHAR));
|
|
_tcscpy (fullvalue, dir);
|
|
}
|
|
|
|
/* Append value */
|
|
|
|
if (quoted)
|
|
{
|
|
_tcsncpy (fullvalue + dirlen, value + 1, vallen - 1);
|
|
fullvalue [dirlen + vallen - sizeof (TCHAR)] = _T ('\0');
|
|
}
|
|
else
|
|
_tcscpy (fullvalue + dirlen, value);
|
|
|
|
if (*last <= *index)
|
|
{
|
|
*last += EXPAND_ARGV_RATE;
|
|
*argv = (char **) xrealloc (*argv, (*last) * sizeof (char *));
|
|
}
|
|
|
|
size = WS2SC (NULL, fullvalue, 0);
|
|
(*argv)[*index] = (char *) xmalloc (size + sizeof (TCHAR));
|
|
WS2SC ((*argv)[*index], fullvalue, size);
|
|
|
|
free (fullvalue);
|
|
|
|
(*index)++;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
__gnat_runtime_initialize (int install_handler)
|
|
{
|
|
/* increment the reference counter */
|
|
|
|
__gnat_rt_init_count++;
|
|
|
|
/* if already initialized return now */
|
|
if (__gnat_rt_init_count > 1)
|
|
return;
|
|
|
|
/* Initialize floating-point coprocessor. This call is needed because
|
|
the MS libraries default to 64-bit precision instead of 80-bit
|
|
precision, and we require the full precision for proper operation,
|
|
given that we have set Max_Digits etc with this in mind */
|
|
|
|
__gnat_init_float ();
|
|
|
|
/* Initialize the critical section and event handle for the win32_wait()
|
|
implementation, see adaint.c */
|
|
|
|
InitializeCriticalSection (&ProcListCS);
|
|
ProcListEvt = CreateEvent (NULL, FALSE, FALSE, NULL);
|
|
|
|
#ifdef GNAT_UNICODE_SUPPORT
|
|
/* Set current code page for filenames handling. */
|
|
{
|
|
char *codepage = getenv ("GNAT_CODE_PAGE");
|
|
|
|
/* Default code page is UTF-8. */
|
|
__gnat_current_codepage = CP_UTF8;
|
|
|
|
if (codepage != NULL)
|
|
{
|
|
if (strcmp (codepage, "CP_ACP") == 0)
|
|
__gnat_current_codepage = CP_ACP;
|
|
else if (strcmp (codepage, "CP_UTF8") == 0)
|
|
__gnat_current_codepage = CP_UTF8;
|
|
}
|
|
}
|
|
|
|
/* Set current encoding for the IO. */
|
|
{
|
|
char *ccsencoding = getenv ("GNAT_CCS_ENCODING");
|
|
|
|
/* Default CCS Encoding. */
|
|
__gnat_current_ccs_encoding = _O_TEXT;
|
|
__gnat_wide_text_translation_required = 0;
|
|
|
|
if (ccsencoding != NULL)
|
|
{
|
|
if (strcmp (ccsencoding, "U16TEXT") == 0)
|
|
{
|
|
__gnat_current_ccs_encoding = _O_U16TEXT;
|
|
__gnat_wide_text_translation_required = 1;
|
|
}
|
|
else if (strcmp (ccsencoding, "TEXT") == 0)
|
|
{
|
|
__gnat_current_ccs_encoding = _O_TEXT;
|
|
__gnat_wide_text_translation_required = 0;
|
|
}
|
|
else if (strcmp (ccsencoding, "WTEXT") == 0)
|
|
{
|
|
__gnat_current_ccs_encoding = _O_WTEXT;
|
|
__gnat_wide_text_translation_required = 1;
|
|
}
|
|
else if (strcmp (ccsencoding, "U8TEXT") == 0)
|
|
{
|
|
__gnat_current_ccs_encoding = _O_U8TEXT;
|
|
__gnat_wide_text_translation_required = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Adjust gnat_argv to support Unicode characters. */
|
|
{
|
|
LPWSTR *wargv;
|
|
int wargc;
|
|
int k;
|
|
int last;
|
|
int argc_expanded = 0;
|
|
TCHAR result [MAX_PATH];
|
|
int quoted;
|
|
|
|
__gnat_get_argw (GetCommandLineW (), &wargv, &wargc);
|
|
|
|
if (wargv != NULL)
|
|
{
|
|
/* Set gnat_argv with arguments encoded in UTF-8. */
|
|
last = wargc + 1;
|
|
gnat_argv = (char **) xmalloc ((last) * sizeof (char *));
|
|
|
|
/* argv[0] is the executable full path-name. */
|
|
|
|
SearchPath (NULL, wargv[0], _T(".exe"), MAX_PATH, result, NULL);
|
|
append_arg (&argc_expanded, NULL, result, &gnat_argv, &last, 0);
|
|
|
|
for (k=1; k<wargc; k++)
|
|
{
|
|
quoted = (wargv[k][0] == _T('\''));
|
|
|
|
/* Check for wildcard expansion if the argument is not quoted. */
|
|
if (!quoted && __gnat_do_argv_expansion
|
|
&& (_tcsstr (wargv[k], _T("?")) != 0 ||
|
|
_tcsstr (wargv[k], _T("*")) != 0))
|
|
{
|
|
/* Wilcards are present, append all corresponding matches. */
|
|
WIN32_FIND_DATA FileData;
|
|
HANDLE hDir = FindFirstFile (wargv[k], &FileData);
|
|
LPWSTR dir = NULL;
|
|
LPWSTR ldir = _tcsrchr (wargv[k], _T('\\'));
|
|
|
|
if (ldir == NULL)
|
|
ldir = _tcsrchr (wargv[k], _T('/'));
|
|
|
|
if (hDir == INVALID_HANDLE_VALUE)
|
|
{
|
|
/* No match, append arg as-is. */
|
|
append_arg (&argc_expanded, NULL, wargv[k],
|
|
&gnat_argv, &last, quoted);
|
|
}
|
|
else
|
|
{
|
|
if (ldir != NULL)
|
|
{
|
|
int n = ldir - wargv[k] + 1;
|
|
dir = (LPWSTR) xmalloc ((n + 1) * sizeof (TCHAR));
|
|
_tcsncpy (dir, wargv[k], n);
|
|
dir[n] = _T('\0');
|
|
}
|
|
|
|
/* Append first match and all remaining ones. */
|
|
|
|
do {
|
|
/* Do not add . and .. special entries */
|
|
|
|
if (_tcscmp (FileData.cFileName, _T(".")) != 0
|
|
&& _tcscmp (FileData.cFileName, _T("..")) != 0)
|
|
append_arg (&argc_expanded, dir, FileData.cFileName,
|
|
&gnat_argv, &last, 0);
|
|
} while (FindNextFile (hDir, &FileData));
|
|
|
|
FindClose (hDir);
|
|
|
|
if (dir != NULL)
|
|
free (dir);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No wildcard. Store parameter as-is. Remove quote if
|
|
needed. */
|
|
append_arg (&argc_expanded, NULL, wargv[k],
|
|
&gnat_argv, &last,
|
|
quoted && __gnat_do_argv_expansion);
|
|
}
|
|
}
|
|
|
|
free (wargv[0]);
|
|
free (wargv);
|
|
gnat_argc = argc_expanded;
|
|
gnat_argv = (char **) xrealloc
|
|
(gnat_argv, argc_expanded * sizeof (char *));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (install_handler)
|
|
__gnat_install_handler();
|
|
}
|
|
|
|
/**************************************************/
|
|
/* __gnat_runtime_initialize (init_float version) */
|
|
/**************************************************/
|
|
|
|
#elif defined (__Lynx__) || defined (__FreeBSD__) || defined(__NetBSD__) \
|
|
|| defined (__OpenBSD__)
|
|
|
|
extern void __gnat_init_float (void);
|
|
|
|
void
|
|
__gnat_runtime_initialize(int install_handler)
|
|
{
|
|
/* increment the reference counter */
|
|
|
|
__gnat_rt_init_count++;
|
|
|
|
/* if already initialized return now */
|
|
if (__gnat_rt_init_count > 1)
|
|
return;
|
|
|
|
__gnat_init_float ();
|
|
|
|
if (install_handler)
|
|
__gnat_install_handler();
|
|
}
|
|
|
|
/***********************************************/
|
|
/* __gnat_runtime_initialize (VxWorks Version) */
|
|
/***********************************************/
|
|
|
|
#elif defined(__vxworks)
|
|
|
|
extern void __gnat_init_float (void);
|
|
|
|
void
|
|
__gnat_runtime_initialize(int install_handler)
|
|
{
|
|
/* increment the reference counter */
|
|
|
|
__gnat_rt_init_count++;
|
|
|
|
/* if already initialized return now */
|
|
if (__gnat_rt_init_count > 1)
|
|
return;
|
|
|
|
__gnat_init_float ();
|
|
|
|
if (install_handler)
|
|
__gnat_install_handler();
|
|
}
|
|
|
|
#else
|
|
|
|
/***********************************************/
|
|
/* __gnat_runtime_initialize (default version) */
|
|
/***********************************************/
|
|
|
|
void
|
|
__gnat_runtime_initialize(int install_handler)
|
|
{
|
|
/* increment the reference counter */
|
|
|
|
__gnat_rt_init_count++;
|
|
|
|
/* if already initialized return now */
|
|
if (__gnat_rt_init_count > 1)
|
|
return;
|
|
|
|
if (install_handler)
|
|
__gnat_install_handler();
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|