diff options
author | Nicolas Roche <roche@adacore.com> | 2019-07-08 08:14:06 +0000 |
---|---|---|
committer | Pierre-Marie de Rodat <pmderodat@gcc.gnu.org> | 2019-07-08 08:14:06 +0000 |
commit | 900dd8405fbd327023aa24f856b4535033ebbef0 (patch) | |
tree | f4981b82a4a4ba7dceef2ec53de7de5bc6f6dae5 /gcc/ada/rtinit.c | |
parent | eaec429d5be27b5dce89260248c928edc2593d17 (diff) | |
download | gcc-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.c | 200 |
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 *)); |