mingw: replace mingw_startup() hack
Git for Windows has special code to retrieve the command-line parameters (and even the environment) in UTF-16 encoding, so that they can be converted to UTF-8. This is necessary because Git for Windows wants to use UTF-8 encoded strings throughout its code, and the main() function does not get the parameters in that encoding. To do that, we used the __wgetmainargs() function, which is not even a Win32 API function, but provided by the MINGW "runtime" instead. Obviously, this method would not work with any compiler other than GCC, and in preparation for compiling with Visual C++, we would like to avoid precisely that. Lucky us, there is a much more elegant way: we can simply implement the UTF-16 variant of `main()`: `wmain()`. To make that work, we need to link with -municode. The command-line parameters are passed to `wmain()` encoded in UTF-16, as desired, and this method also works with GCC, and also with Visual C++ after adjusting the MSVC linker flags to force it to use `wmain()`. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:

committed by
Junio C Hamano

parent
96a0679441
commit
396ff7547d
@ -2301,18 +2301,13 @@ static void setup_windows_environment(void)
|
||||
setenv("TERM", "cygwin", 1);
|
||||
}
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
/*
|
||||
* Disable MSVCRT command line wildcard expansion (__getmainargs called from
|
||||
* mingw startup code, see init.c in mingw runtime).
|
||||
*/
|
||||
int _CRT_glob = 0;
|
||||
|
||||
typedef struct {
|
||||
int newmode;
|
||||
} _startupinfo;
|
||||
|
||||
extern int __wgetmainargs(int *argc, wchar_t ***argv, wchar_t ***env, int glob,
|
||||
_startupinfo *si);
|
||||
#endif
|
||||
|
||||
static NORETURN void die_startup(void)
|
||||
{
|
||||
@ -2390,22 +2385,25 @@ static void maybe_redirect_std_handles(void)
|
||||
GENERIC_WRITE, FILE_FLAG_NO_BUFFERING);
|
||||
}
|
||||
|
||||
void mingw_startup(void)
|
||||
/*
|
||||
* We implement wmain() and compile with -municode, which would
|
||||
* normally ignore main(), but we call the latter from the former
|
||||
* so that we can handle non-ASCII command-line parameters
|
||||
* appropriately.
|
||||
*
|
||||
* To be more compatible with the core git code, we convert
|
||||
* argv into UTF8 and pass them directly to main().
|
||||
*/
|
||||
int wmain(int argc, const wchar_t **wargv)
|
||||
{
|
||||
int i, maxlen, argc;
|
||||
char *buffer;
|
||||
wchar_t **wenv, **wargv;
|
||||
_startupinfo si;
|
||||
int i, maxlen, exit_status;
|
||||
char *buffer, **save;
|
||||
const char **argv;
|
||||
|
||||
trace2_initialize_clock();
|
||||
|
||||
maybe_redirect_std_handles();
|
||||
|
||||
/* get wide char arguments and environment */
|
||||
si.newmode = 0;
|
||||
if (__wgetmainargs(&argc, &wargv, &wenv, _CRT_glob, &si) < 0)
|
||||
die_startup();
|
||||
|
||||
/* determine size of argv and environ conversion buffer */
|
||||
maxlen = wcslen(wargv[0]);
|
||||
for (i = 1; i < argc; i++)
|
||||
@ -2415,9 +2413,16 @@ void mingw_startup(void)
|
||||
maxlen = 3 * maxlen + 1;
|
||||
buffer = malloc_startup(maxlen);
|
||||
|
||||
/* convert command line arguments and environment to UTF-8 */
|
||||
/*
|
||||
* Create a UTF-8 version of w_argv. Also create a "save" copy
|
||||
* to remember all the string pointers because parse_options()
|
||||
* will remove claimed items from the argv that we pass down.
|
||||
*/
|
||||
ALLOC_ARRAY(argv, argc + 1);
|
||||
ALLOC_ARRAY(save, argc + 1);
|
||||
for (i = 0; i < argc; i++)
|
||||
__argv[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
|
||||
argv[i] = save[i] = wcstoutfdup_startup(buffer, wargv[i], maxlen);
|
||||
argv[i] = save[i] = NULL;
|
||||
free(buffer);
|
||||
|
||||
/* fix Windows specific environment settings */
|
||||
@ -2436,6 +2441,16 @@ void mingw_startup(void)
|
||||
|
||||
/* initialize Unicode console */
|
||||
winansi_init();
|
||||
|
||||
/* invoke the real main() using our utf8 version of argv. */
|
||||
exit_status = main(argc, argv);
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
free(save[i]);
|
||||
free(save);
|
||||
free(argv);
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
|
||||
int uname(struct utsname *buf)
|
||||
|
Reference in New Issue
Block a user