Bug 5926 – D2 shows empty command line on Windows 98 SE

Status
RESOLVED
Resolution
WONTFIX
Severity
minor
Priority
P5
Component
druntime
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2011-05-04T03:31:00Z
Last change time
2012-07-02T00:57:06Z
Assigned to
nobody
Creator
verylonglogin.reg

Attachments

IDFilenameSummaryContent-TypeSize
959printArgsD.dTest casetext/x-dsrc215
960windowsArgsParser.zipgetCommandLineArgs function with it's unittestsapplication/zip2248
961dmain2-change.dchanges in rt.dmain2, version (Windows) section (from line 371)text/x-dsrc1638
962dmain2-change.dchanges (v2) in rt.dmain2, version (Windows) section (from line 371)text/x-dsrc1739

Comments

Comment #0 by verylonglogin.reg — 2011-05-04T03:31:28Z
Created attachment 959 Test case The problem is in file druntime\src\rt\dmain2.d Windows Windows 98 SE really has GetCommandLineW function, but hasn't CommandLineToArgvW. So dmd v2.052 compiled printArgsD.d always shows args.length is 0 (dmd v1.067 compiled works fine). It is sad to live without command line or to have own CommandLineToArgvW-like function in every small console util...
Comment #1 by issues.dlang — 2011-05-04T04:15:17Z
I certainly won't say that we aren't going to worry about having druntime or Phobos work with Windows 98, but there were a _lot_ of system functions added to Windows with Win2k, and it would be incredibly constraining to have to make it so that everything worked with Windows 98. std.datetime definitely won't, and it can't. And realistically, very few people are using anything prior to Windows XP at this point, let alone something as old as Windows 98, so it's not necessarily realistic to expect that everything work with Windows 98. Now, something as basic as the command line arguments not working is at least worth looking into. However, I'd strongly argue against making it work if it resulted in worse code than what we have now, thereby restricting code on current operating systems just to maintain compatability with an ancient one. So, I'd say whether this is worth fixing strongly depends on what is required to fix the problem and what impact it has on anything built on a more modern OS. However, it is true that we don't want to close such doors if we can reasonably avoid it.
Comment #2 by verylonglogin.reg — 2011-05-04T06:50:01Z
Created attachment 960 getCommandLineArgs function with it's unittests
Comment #3 by verylonglogin.reg — 2011-05-04T06:52:27Z
I wrote a function getCommandLineArgs and tested it on all such arguments: [aZяЫ \t\\"]{1,6} | [\r\nЫ \t\\"]{1,6} and others (in test.d). It's output was equal to CommandLineToArgvW. Please, add it to dmain2.d instead of CommandLineToArgvW at least if second is not available on current system.
Comment #4 by bugzilla — 2011-05-04T10:40:37Z
The std.file functions have a special code path in them for earlier Windows versions. I believe this is a reasonable approach.
Comment #5 by issues.dlang — 2011-05-04T11:04:14Z
That definitely sounds like a good approach where it can be done. And in this case, it looks like that should be possible.
Comment #6 by sean — 2011-05-04T11:38:40Z
Thanks! However, when this routine is run, the GC is not yet initialized, so array operations won't work. What would be ideal is if the new function were a functional clone of CommandLineToArgvW, so the surrounding logic could be reused. ie. wchar_t** doCommandLineToArgvW(wchar_t* cmdLine, int* numArgs) { if (GetVersion() < 0x80000000) { return CommandLineToArgvW(cmdLine, numArgs); } // TODO: parse manually here. }
Comment #7 by bugzilla — 2011-05-04T14:01:50Z
Why is this code there to begin with anyway? The C runtime already sets up argc/argv.
Comment #8 by sean — 2011-05-04T16:36:31Z
It's there because the argv data on Windows is in code pages instead of Unicode, and it seemed easiest to let the OS deal with the conversion.
Comment #9 by bugzilla — 2011-05-04T17:56:09Z
(In reply to comment #8) > It's there because the argv data on Windows is in code pages instead of > Unicode, and it seemed easiest to let the OS deal with the conversion. Here's the code from druntime/src/rt/dmain2.d in question: wchar_t* wcbuf = GetCommandLineW(); size_t wclen = wcslen(wcbuf); int wargc = 0; wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc); assert(wargc == argc); char* cargp = null; size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0); cargp = cast(char*) alloca(cargl); args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc]; for (size_t i = 0, p = 0; i < wargc; i++) { int wlen = wcslen(wargs[i]); int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0) args[i] = cargp[p .. p+clen]; p += clen; assert(p <= cargl); WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0); } LocalFree(wargs); wargs = null; wargc = 0; Since the only thing necessary is to convert argv[] from code pages to utf8, there is no need for the calls to GetCommandLineW and CommandLineToArgvW, and so no compatibility problem.
Comment #10 by verylonglogin.reg — 2011-05-04T22:04:18Z
argv is in windows multi byte format and just can't store every UTF-16 symbol. But, in old windows there are no *W functions to create a process with UTF-16 argumants. Maybe it is possible, but we don't want to support such unusual cases. So, the reasonable solution, I think, is just to use argv for old windows with MultiByteToWideChar instead of CommandLineToArgvW.
Comment #11 by bugzilla — 2011-05-04T22:30:42Z
Sounds reasonable.
Comment #12 by verylonglogin.reg — 2011-05-04T23:18:12Z
Created attachment 961 changes in rt.dmain2, version (Windows) section (from line 371) If there is no mistakes, it should help. For CommandLineToArgvW case the only change is that it really suppose "wargc == argc". For added case in loop "&wargs[i][0]" is just replaced with big enough "warg" with UTF-16 version of argv[i].
Comment #13 by verylonglogin.reg — 2011-05-04T23:24:27Z
Comment on attachment 961 changes in rt.dmain2, version (Windows) section (from line 371) version (Windows) { wchar_t* wcbuf = GetCommandLineW(); size_t wclen = wcslen(wcbuf); char* cargp = null; size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0); cargp = cast(char*) alloca(cargl); args = ((cast(char[]*) alloca(argc * (char[]).sizeof)))[0 .. argc]; if(GetVersion() < 0x80000000) //useWfuncs { int wargc = 0; wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc); assert(wargc == argc); for (size_t i = 0, p = 0; i < wargc; i++) { int wlen = wcslen(wargs[i]); int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0); args[i] = cargp[p .. p+clen]; p += clen; assert(p <= cargl); WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0); } LocalFree(wargs); } else { size_t wargSize = (wclen + 1) * wchar_t.sizeof; wchar_t* warg = cast(wchar_t*) malloc(wargSize); //or alloca is better? for (size_t i = 0, p = 0; i < argc; i++) { int wlen = MultiByteToWideChar(0, 0, argv[i], -1, warg, wargSize); int clen = WideCharToMultiByte(65001, 0, &warg[0], wlen, null, 0, null, 0); args[i] = cargp[p .. p+clen]; p += clen; assert(p <= cargl); WideCharToMultiByte(65001, 0, &warg[0], wlen, &args[i][0], clen, null, 0); } free(warg); //if alloca isn't better } }
Comment #14 by verylonglogin.reg — 2011-05-04T23:38:53Z
Created attachment 962 changes (v2) in rt.dmain2, version (Windows) section (from line 371) Same thing, but without stupid trying to free() alloca's stack memory. Now with separate function to free alloca. Is it good? Does it work?
Comment #15 by bugzilla — 2012-01-20T22:00:30Z
(In reply to comment #14) > Created an attachment (id=962) [details] > Is it good? Does it work? Would you like to make a github pull request for this?
Comment #16 by verylonglogin.reg — 2012-01-22T09:40:18Z
Personally I would vote for marking Windows prior to 2000 as unsupported because this support doesn't worth making druntime/Phobos more complicated. Phobos already contains lots of things like `std.__fileinit` that can be removed to make it easier to support.
Comment #17 by verylonglogin.reg — 2012-07-02T00:57:06Z
Marked as WONTFIX because of a rid of Win9x support since 2.059.