mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-15 17:33:38 +00:00
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:
@@ -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)
|
||||
|
||||
@@ -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 --- */
|
||||
|
||||
Reference in New Issue
Block a user