[m-rev.] for review: unicode command line arguments on windows
Julien Fischer
juliensf at csse.unimelb.edu.au
Fri Dec 16 04:56:28 AEDT 2011
On Thu, 15 Dec 2011, Peter Wang wrote:
> On Thu, 15 Dec 2011 17:32:06 +1100 (EST), Julien Fischer <juliensf at csse.unimelb.edu.au> wrote:
>>
>> Ok, let me try and get this straight:
>>
>> (1) __wgetmainargs works with MinGW
>> (2) wmain works with MSVC
>
> Yes.
>
>> So let's do that - I would actually make the code conditional on MR_MSVC
>> rather than MR_MINGW though. I suggest breaking mercury_win32_args in
>> two since the lower part of it should be usable by both of them.
>
> I would make __wgetmainargs conditional on MR_MINGW and wmain
> conditional on MR_MSVC until we know either works with other compilers.
>
>>
>>> It's probably better for you to modify the patch and commit it directly.
>>
>> That's fine with me.
>
> Thanks, I'll leave it to you.
The following diff fixes the problem for MinGW and MSVC. Cygwin and clang
will currently fall back to not supporting Unicode command-line arguments.
It incoporates your change to use __wgetmainargs for the MinGW case.
There's a tiny bit of code duplication below, but I think keeping the MSVC
version completely separate is an aid to readibility in this case.
Julien.
-----------------------------
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.
Julien.
Index: compiler/compile_target_code.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/compiler/compile_target_code.m,v
retrieving revision 1.180
diff -u -r1.180 compile_target_code.m
--- compiler/compile_target_code.m 7 Dec 2011 09:17:41 -0000 1.180
+++ compiler/compile_target_code.m 15 Dec 2011 17:36:23 -0000
@@ -2449,7 +2449,7 @@
"-nologo",
"-subsystem:console",
"-machine:x86",
- "-entry:mainCRTStartup",
+ "-entry:wmainCRTStartup",
"-defaultlib:libcmt"
],
join_string_list(ResCmdLinkFlags, "", "", " ", ResCmdLinkOpts)
Index: util/mkinit.c
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/util/mkinit.c,v
retrieving revision 1.126
diff -u -r1.126 mkinit.c
--- util/mkinit.c 14 Dec 2011 05:12:42 -0000 1.126
+++ util/mkinit.c 15 Dec 2011 17:36:36 -0000
@@ -329,7 +329,6 @@
"#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 @@
** 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 @@
" 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 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 @@
"#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 @@
"#endif\n"
" return result;\n"
"}\n"
+ "#endif\n"
;
/* --- function prototypes --- */
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list