aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/rtinit.c
diff options
context:
space:
mode:
authorNicolas Roche <roche@adacore.com>2019-07-08 08:14:06 +0000
committerPierre-Marie de Rodat <pmderodat@gcc.gnu.org>2019-07-08 08:14:06 +0000
commit900dd8405fbd327023aa24f856b4535033ebbef0 (patch)
treef4981b82a4a4ba7dceef2ec53de7de5bc6f6dae5 /gcc/ada/rtinit.c
parenteaec429d5be27b5dce89260248c928edc2593d17 (diff)
downloadgcc-900dd8405fbd327023aa24f856b4535033ebbef0.zip
gcc-900dd8405fbd327023aa24f856b4535033ebbef0.tar.gz
gcc-900dd8405fbd327023aa24f856b4535033ebbef0.tar.bz2
[Ada] Remove dependency on Win32 GDI (Graphical Interface)
CommandLineToArgvW drags a dependency on SHELL32.DLL and thus GDI32.DLL. By loading GDI32.DLL some default GDI objects are allocated. On some Windows versions this cause the use of a lock on the graphical interface during process termination. This can impact parallelism significantly as termination of processes is serialized. 2019-07-08 Nicolas Roche <roche@adacore.com> gcc/ada/ * rtinit.c (__gnat_runtime_initialize): Remove dependency on CommandLineToArgvW. From-SVN: r273214
Diffstat (limited to 'gcc/ada/rtinit.c')
-rw-r--r--gcc/ada/rtinit.c200
1 files changed, 192 insertions, 8 deletions
diff --git a/gcc/ada/rtinit.c b/gcc/ada/rtinit.c
index 13bd595..1df98f8 100644
--- a/gcc/ada/rtinit.c
+++ b/gcc/ada/rtinit.c
@@ -62,7 +62,7 @@ extern "C" {
/* __gnat_runtime_initialize (NT-mingw32 Version) */
/**************************************************/
-extern void __gnat_install_handler(void);
+extern void __gnat_install_handler (void);
int __gnat_wide_text_translation_required = 0;
/* wide text translation, 0=none, 1=activated */
@@ -89,6 +89,189 @@ extern HANDLE ProcListEvt;
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++;
+ }
+ *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++;
+ }
+ 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)
@@ -102,14 +285,14 @@ append_arg (int *index, LPWSTR dir, LPWSTR value,
{
/* no dir prefix */
dirlen = 0;
- fullvalue = (LPWSTR) xmalloc ((vallen + 1) * sizeof(TCHAR));
+ fullvalue = (LPWSTR) xmalloc ((vallen + 1) * sizeof (TCHAR));
}
else
{
/* Add dir first */
dirlen = _tcslen (dir);
- fullvalue = (LPWSTR) xmalloc ((dirlen + vallen + 1) * sizeof(TCHAR));
+ fullvalue = (LPWSTR) xmalloc ((dirlen + vallen + 1) * sizeof (TCHAR));
_tcscpy (fullvalue, dir);
}
@@ -118,7 +301,7 @@ append_arg (int *index, LPWSTR dir, LPWSTR value,
if (quoted)
{
_tcsncpy (fullvalue + dirlen, value + 1, vallen - 1);
- fullvalue [dirlen + vallen - sizeof(TCHAR)] = _T('\0');
+ fullvalue [dirlen + vallen - sizeof (TCHAR)] = _T ('\0');
}
else
_tcscpy (fullvalue + dirlen, value);
@@ -130,7 +313,7 @@ append_arg (int *index, LPWSTR dir, LPWSTR value,
}
size = WS2SC (NULL, fullvalue, 0);
- (*argv)[*index] = (char *) xmalloc (size + sizeof(TCHAR));
+ (*argv)[*index] = (char *) xmalloc (size + sizeof (TCHAR));
WS2SC ((*argv)[*index], fullvalue, size);
free (fullvalue);
@@ -140,7 +323,7 @@ append_arg (int *index, LPWSTR dir, LPWSTR value,
#endif
void
-__gnat_runtime_initialize(int install_handler)
+__gnat_runtime_initialize (int install_handler)
{
/* increment the reference counter */
@@ -223,7 +406,7 @@ __gnat_runtime_initialize(int install_handler)
TCHAR result [MAX_PATH];
int quoted;
- wargv = CommandLineToArgvW (GetCommandLineW(), &wargc);
+ __gnat_get_argw (GetCommandLineW (), &wargv, &wargc);
if (wargv != NULL)
{
@@ -297,7 +480,8 @@ __gnat_runtime_initialize(int install_handler)
}
}
- LocalFree (wargv);
+ free (wargv[0]);
+ free (wargv);
gnat_argc = argc_expanded;
gnat_argv = (char **) xrealloc
(gnat_argv, argc_expanded * sizeof (char *));