Fix handling of Unicode command-line arguments on Windows with either MinGW or

Branches: main, 11.07

Fix handling of Unicode command-line arguments on Windows with either MinGW or
MSVC.  (For other compilers on Windows, Unicode command-line arguments are not
currently supported.)

The existing approach using GetCommandLineW and CommandLineToArgW caused the
command-line to be parsed in a weird way, e.g. for

   c:\> "C:\ws"\foo.exe

argv[0] was split in two:

   ["c:\ws", "\foo.exe"]


util/mkinit.c:
	Use wmain instead of main with MSVC; this gives us direct access
	to the wide version of the argument vector.

	Use __wgetmainargs to get the wide version of the command-line
	arguments with MinGW.  MinGW doesn't support wmain so we can't
	use that.

	Don't include shellapi.h on Windows, it's no longer required.


compiler/compile_target_code.m:
	Use the wide entry point to the C runtime with MSVC so that
	wmain is invoke isntead of main.
This commit is contained in:
Julien Fischer
2011-12-16 03:38:20 +00:00
parent 34f13238b5
commit 608df4f718
2 changed files with 49 additions and 11 deletions

View File

@@ -2449,7 +2449,7 @@ get_restricted_command_line_link_opts(Globals, LinkTargetType, ResCmdLinkOpts) :
"-nologo",
"-subsystem:console",
"-machine:x86",
"-entry:mainCRTStartup",
"-entry:wmainCRTStartup",
"-defaultlib:libcmt"
],
join_string_list(ResCmdLinkFlags, "", "", " ", ResCmdLinkOpts)

View File

@@ -329,7 +329,6 @@ static const char header2[] =
"#include \"mercury_grade.h\"\n"
"#ifdef MR_WIN32\n"
" #include \"mercury_windows.h\"\n"
" #include <shellapi.h>\n"
"#endif\n"
"\n"
"#define MR_TRACE_ENABLED %d\n"
@@ -539,17 +538,15 @@ static const char mercury_main_func[] =
** Convert wide-character representation of the command line
** arguments to UTF-8.
*/
"#ifdef MR_WIN32\n"
"#if defined(MR_MSVC)\n"
"static char **\n"
"mercury_win32_args(int *argc_ptr)\n"
"mercury_msvc_args(int argc, wchar_t **wargv)\n"
"{\n"
" LPWSTR *wargv;\n"
" char **argv;\n"
" int i;\n"
"\n"
" wargv = CommandLineToArgvW(GetCommandLineW(), argc_ptr);\n"
" argv = MR_GC_NEW_ARRAY(char *, (*argc_ptr + 1));\n"
" for (i = 0; i < (*argc_ptr); i++) {\n"
" argv = MR_GC_NEW_ARRAY(char *, argc + 1);\n"
" for (i = 0; i < argc; i++) {\n"
" int bytes = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1,\n"
" NULL, 0, NULL, NULL);\n"
" argv[i] = MR_GC_malloc(bytes);\n"
@@ -557,9 +554,36 @@ static const char mercury_main_func[] =
" argv[i], bytes, NULL, NULL);\n"
" }\n"
" argv[i] = NULL;\n"
" LocalFree(wargv);\n"
" return argv;\n"
"}\n"
"#elif defined(MR_MINGW)\n"
"extern int __wgetmainargs(int *, wchar_t ***, wchar_t ***, int, int *);\n"
"\n"
"static void\n"
"mercury_win32_args(int *argc_ret, char ***argv_ret)\n"
"{\n"
" int argc;\n"
" char **argv;\n"
" wchar_t **wargv;\n"
" wchar_t **wenv;\n"
" int start_info = 0;\n"
" int i;\n"
"\n"
" if (__wgetmainargs(&argc, &wargv, &wenv, 0, &start_info) != 0) {\n"
" return;\n"
" }\n"
" argv = MR_GC_NEW_ARRAY(char *, argc + 1);\n"
" for (i = 0; i < argc; i++) {\n"
" int bytes = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1,\n"
" NULL, 0, NULL, NULL);\n"
" argv[i] = MR_GC_malloc(bytes);\n"
" WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1,\n"
" argv[i], bytes, NULL, NULL);\n"
" }\n"
" argv[i] = NULL;\n"
" *argc_ret = argc;\n"
" *argv_ret = argv;\n"
"}\n"
"#endif\n"
"\n"
;
@@ -571,6 +595,19 @@ static const char mercury_grade_var[] =
;
static const char main_func[] =
"#if defined(MR_MSVC)\n"
"\n"
"int\n"
"wmain(int argc, wchar_t **wargv)\n"
"{\n"
" int result;\n"
" char **argv;\n"
"\n"
" argv = mercury_msvc_args(argc, wargv);\n"
" result = mercury_main(argc, argv);\n"
" return result;\n"
"}\n"
"#else\n"
"\n"
"int\n"
"main(int argc, char **argv)\n"
@@ -583,8 +620,8 @@ static const char main_func[] =
"#ifdef MR_PROFILE_SBRK\n"
" old_break = sbrk(0);\n"
"#endif\n"
"#ifdef MR_WIN32\n"
" argv = mercury_win32_args(&argc);\n"
"#ifdef MR_MINGW\n"
" mercury_win32_args(&argc, &argv);\n"
"#endif\n"
" result = mercury_main(argc, argv);\n"
"#ifdef MR_PROFILE_SBRK\n"
@@ -594,6 +631,7 @@ static const char main_func[] =
"#endif\n"
" return result;\n"
"}\n"
"#endif\n"
;
/* --- function prototypes --- */