www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Possible bug in std.path?

reply Hugo <dmdpathquestion yopmail.com> writes:
I am having a problem on Windows with the following code:

module mytest;

import std.stdio, std.file, std.path;

enum EXIT_SUCCESS = 0;
enum EXIT_FAILURE = -1;

int main(string[] args) {
   string appdir;
   switch(args.length-1) {
     case 0:
       writeln("You must provide an argument with a valid 
directory path.");
       break;
     case 1:
       appdir = buildNormalizedPath(args[1]);
       if(appdir.exists && appdir.isDir) break;
     default:
       writefln("Error: '%s' is not a valid directory path.", 
appdir);
       return EXIT_FAILURE;
   }
   writeln("OK");
   return EXIT_SUCCESS;
}

Suppose I compiled this unit on current dir and then executed 
these commands:

mkdir "my dir"
mytest "my dir\"

I should get "OK", but instead I get:
Error: 'my test"' is not a valid directory path.

If the trailing backslash is removed it works as intended, but 
IMHO buildNormalizedPath should have worked.

In any case, notice the double quote in the output. To me this 
suggests the backslash is acting not as a path terminator but as 
an escape sequence.
May 18 2016
next sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Thursday, 19 May 2016 at 03:49:36 UTC, Hugo wrote:

 mytest "my dir\"
Here, your backslash is used to escape the second " character.
 Error: 'my test"' is not a valid directory path.
Here you can see the final string value of the program argument in your program. The correct invocation is: mytest "my dir\\" In the future, consider posting to the learn group.
May 18 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Thursday, 19 May 2016 at 05:06:44 UTC, Vladimir Panteleev 
wrote:
 Here you can see the final string value of the program argument 
 in your program.

 The correct invocation is: mytest "my dir\\"
What you suggest is non-standard in Windows, and would require distributing the application with some form of comment saying you have to use double backslashes, which is unprofessional. Software should serve the user and not the other way round. Notice I am not debating the escape character, but the inconsistency of buildNormalizedPath, which IMHO should have worked and fixed the trailing backslash.
 In the future, consider posting to the learn group.
I did not post there because I thought this was not necessarily a newbie question. My apologies.
May 19 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/19/16 9:49 AM, Hugo wrote:
 On Thursday, 19 May 2016 at 05:06:44 UTC, Vladimir Panteleev wrote:
 Here you can see the final string value of the program argument in
 your program.

 The correct invocation is: mytest "my dir\\"
What you suggest is non-standard in Windows, and would require distributing the application with some form of comment saying you have to use double backslashes, which is unprofessional. Software should serve the user and not the other way round.
Then complain to Microsoft :) This is Microsoft's command shell sending that parameter to your program.
 Notice I am not debating the escape character, but the inconsistency of
 buildNormalizedPath, which IMHO should have worked and fixed the
 trailing backslash.
buildNormalizedPath is being send the string `my dir"`, what is it supposed to do with that? -Steve
May 19 2016
parent reply Kagamin <spam here.lot> writes:
On Thursday, 19 May 2016 at 14:53:21 UTC, Steven Schveighoffer 
wrote:
 Then complain to Microsoft :) This is Microsoft's command shell 
 sending that parameter to your program.
This is how CommandLineToArgvW behaves, which is called by druntime to parse the command line. For example, xcopy parses the command line correctly, e.g. this works as expected: xcopy file "..\"
May 19 2016
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/19/16 11:25 AM, Kagamin wrote:
 On Thursday, 19 May 2016 at 14:53:21 UTC, Steven Schveighoffer wrote:
 Then complain to Microsoft :) This is Microsoft's command shell
 sending that parameter to your program.
This is how CommandLineToArgvW behaves, which is called by druntime to parse the command line. For example, xcopy parses the command line correctly, e.g. this works as expected: xcopy file "..\"
Thanks for correcting, this is a difference from posix that I forgot about. The reason for this (as spelled out in the comments) is to get around the poor handling of utf8 by Windows. I think if you write a C program in Windows, your argv/argc will contain .." You'd have to do the same acrobatics D does to get the original, so I don't think this is a problem that we need to solve. Use those low-level functions if you wish. -Steve
May 19 2016
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 5/19/16 12:02 PM, Steven Schveighoffer wrote:
 On 5/19/16 11:25 AM, Kagamin wrote:
 On Thursday, 19 May 2016 at 14:53:21 UTC, Steven Schveighoffer wrote:
 Then complain to Microsoft :) This is Microsoft's command shell
 sending that parameter to your program.
This is how CommandLineToArgvW behaves, which is called by druntime to parse the command line. For example, xcopy parses the command line correctly, e.g. this works as expected: xcopy file "..\"
Thanks for correcting, this is a difference from posix that I forgot about. The reason for this (as spelled out in the comments) is to get around the poor handling of utf8 by Windows. I think if you write a C program in Windows, your argv/argc will contain .." You'd have to do the same acrobatics D does to get the original, so I don't think this is a problem that we need to solve. Use those low-level functions if you wish.
For reference to OP, here is the code that accesses original command line, which you can model for your desired behavior: https://github.com/dlang/druntime/blob/master/src/rt/dmain2.d#L356 -Steve
May 19 2016
prev sibling parent Kagamin <spam here.lot> writes:
On Thursday, 19 May 2016 at 16:02:27 UTC, Steven Schveighoffer 
wrote:
 The reason for this (as spelled out in the comments) is to get 
 around the poor handling of utf8 by Windows.
One receives unicode arguments by declaring wmain function. AFAIK, mingw and msvc do it fine, not sure about dmc.
May 19 2016
prev sibling parent reply Vladimir Panteleev <thecybershadow.lists gmail.com> writes:
On Thursday, 19 May 2016 at 15:25:02 UTC, Kagamin wrote:
 On Thursday, 19 May 2016 at 14:53:21 UTC, Steven Schveighoffer 
 wrote:
 Then complain to Microsoft :) This is Microsoft's command 
 shell sending that parameter to your program.
This is how CommandLineToArgvW behaves, which is called by druntime to parse the command line. For example, xcopy parses the command line correctly, e.g. this works as expected: xcopy file "..\"
As far as I know, CommandLineToArgvW is *the* correct way to parse command-line arguments on Windows. If you do not use it, then your program will not work correctly when invoked by other programs which assume you use it, and this includes most programs which use libraries that accept program arguments as an array (which is the correct abstraction for program arguments anyway). The fact that some standard Windows utilities do not obey this convention is more likely a historical artifact from DOS days.
May 19 2016
parent Kagamin <spam here.lot> writes:
On Thursday, 19 May 2016 at 19:40:16 UTC, Vladimir Panteleev 
wrote:
 The fact that some standard Windows utilities do not obey this 
 convention is more likely a historical artifact from DOS days.
Escaping makes sense for free text arguments, but not for path arguments, hence funny heuristics. That said one can use forward slashes as folder separators on windows.
May 20 2016
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/18/2016 8:49 PM, Hugo wrote:
 mytest "my dir\"

 I should get "OK", but instead I get:
 Error: 'my test"' is not a valid directory path.
Windows command line processing has special handling for " and \. The \ is used to escape the next character, which here is a ". You can see the resulting argument is [my test"]. Note the quote.
 If the trailing backslash is removed it works as intended, but IMHO
 buildNormalizedPath should have worked.
buildNormalizedPath is passed [my test"]. It cannot possibly do as you suggest.
 In any case, notice the double quote in the output. To me this suggests the
 backslash is acting not as a path terminator but as an escape sequence.
This is happening because of how standard Windows programs deal with " and \ on the command line.
May 19 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 19 May 2016 at 22:13:36 UTC, Walter Bright wrote:

 Windows command line processing has special handling for " and 
 \. The \ is used to escape the next character, which here is a 
 ". You can see the resulting argument is [my test"]. Note the 
 quote.
Not exactly... it treats \" as a special case, not \ in general. https://msdn.microsoft.com/en-us/library/windows/desktop/bb776391%28v=vs.85%29.aspx Quote: CommandLineToArgvW has a special interpretation of backslash characters when they are followed by a quotation mark character ("), as follows: 2n backslashes followed by a quotation mark produce n backslashes followed by a quotation mark. (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark. n backslashes not followed by a quotation mark simply produce n backslashes. So indeed, the OP stumbled upon a weird case of Windows command line, but it is really just this one weird case.
May 19 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/19/2016 3:41 PM, Adam D. Ruppe wrote:
 So indeed, the OP stumbled upon a weird case of Windows command line, but it is
 really just this one weird case.
It's not at all weird. It's just garden variety double quoted string behavior. Linux has its own quoting scheme on the command line, too.
May 19 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Thursday, 19 May 2016 at 22:44:06 UTC, Walter Bright wrote:
 On 5/19/2016 3:41 PM, Adam D. Ruppe wrote:
 So indeed, the OP stumbled upon a weird case of Windows 
 command line, but it is
 really just this one weird case.
It's not at all weird. It's just garden variety double quoted string behavior. Linux has its own quoting scheme on the command line, too.
I must confess I was a bit misled then by this portion of the unittest: assert (buildNormalizedPath(`c:\foo\.\bar/..\\baz\`) == `c:\foo\baz`); Since I saw somewhere D could use different quoting styles, I assumed the function would deal with the trailing backslash.
May 19 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 5/19/2016 6:35 PM, Hugo wrote:
 I assumed the
 function would deal with the trailing backslash.
And it can. It just never received a trailing backslash because that was removed by the Windows argument processing.
May 19 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Friday, 20 May 2016 at 03:40:23 UTC, Walter Bright wrote:
 On 5/19/2016 6:35 PM, Hugo wrote:
 I assumed the
 function would deal with the trailing backslash.
And it can. It just never received a trailing backslash because that was removed by the Windows argument processing.
Yes, I can see the problem. On the other hand, regular console commands and many console applications for Windows work as expected, so there must be a way to deal with this properly, and IMHO this would be usefull in buildNormalizedPath, instead of leaving the programmer the task to find a (perhaps sub-optimal) woraround.
May 20 2016
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 20 May 2016 at 15:18:39 UTC, Hugo wrote:
 On the other hand, regular console commands and many console 
 applications for Windows work as expected, so there must be a 
 way to deal with this properly
It is pretty easy to handle, but must happen at a higher level than buildNormalizedPath. Use GetCommandLine to fetch the original thing the user typed, then process it yourself. https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156%28v=vs.85%29.aspx But buildNormalizedPath cannot do this itself because its argument doesn't necessarily come from the command line. Your main() function could use it to get the string you pass to the other functions though. That's probably what most the Windows built in things do when they need to.
May 20 2016
next sibling parent Hugo <dmdpathquestion yopmail.com> writes:
On Friday, 20 May 2016 at 17:41:22 UTC, Adam D. Ruppe wrote:
 On Friday, 20 May 2016 at 15:18:39 UTC, Hugo wrote:
 On the other hand, regular console commands and many console 
 applications for Windows work as expected, so there must be a 
 way to deal with this properly
It is pretty easy to handle, but must happen at a higher level than buildNormalizedPath. Use GetCommandLine to fetch the original thing the user typed, then process it yourself. https://msdn.microsoft.com/en-us/library/windows/desktop/ms683156%28v=vs.85%29.aspx But buildNormalizedPath cannot do this itself because its argument doesn't necessarily come from the command line. Your main() function could use it to get the string you pass to the other functions though. That's probably what most the Windows built in things do when they need to.
Thank you all.
May 21 2016
prev sibling parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Friday, 20 May 2016 at 17:41:22 UTC, Adam D. Ruppe wrote:
 [...]

 Use GetCommandLine to fetch the original thing the user typed, 
 then process it yourself.

 [...]
Then why doesn't the following code produce the expected output? import std.stdio, std.file, std.path; version (Windows) { import core.sys.windows.windows, std.conv; pragma(lib, "shell32.lib"); } enum EXIT_SUCCESS = 0; enum EXIT_FAILURE = 1; int main(string[] originalargs) { string[] args; version (Windows) { SetConsoleOutputCP(65001); int wargc; auto wargs = CommandLineToArgvW(GetCommandLineW(), &wargc); if (wargs) { for(uint i; i < wargc; i++) args ~= buildNormalizedPath(text(wargs[i])); } else { writeln("Error getting command line arguments."); return EXIT_FAILURE; } } else args = originalargs; foreach(uint i, string a; args) writefln("Argument %d: '%s'", i, a); return EXIT_SUCCESS; } Test from Windows: mytestapp dir1 dir2 "..\my parent dir\" (all valid arguments) Output: Argument 0: 'mytestapp' Argument 1: 'dir1' Argument 2: 'dir2' Argument 3: '..\my parent dir"' Notice: I had to use std.conv from master branch because otherwise text() wouldn't dereference wargs (of type wchar**). PS. Please forgive me the delay.
Jun 19 2016
next sibling parent Hugo <dmdpathquestion yopmail.com> writes:
Further, notice what happens if I remove the buildNormalizedPath:

mytestapp dir1 ..\ "another dir\"

Argument 0: 'mytestapp '
Argument 1: 'dir'
Argument 2: '..\'
Argument 3: 'another dir"'

Apparently the backslash is still being interpreted as an escape 
when followed by a double quote, even if the arguments come from 
GetCommandLineW.
Jun 19 2016
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 06/19/2016 02:23 PM, Hugo wrote:
 On Friday, 20 May 2016 at 17:41:22 UTC, Adam D. Ruppe wrote:
 [...]

 Use GetCommandLine to fetch the original thing the user typed, then
 process it yourself.

 [...]
Then why doesn't the following code produce the expected output?
[...]
      auto wargs = CommandLineToArgvW(GetCommandLineW(), &wargc);
You're calling Windows' CommandLineToArgvW here. I don't think that's what Adam meant by "process it yourself". If you don't like how CommandLineToArgvW parses the command line, don't use it.
Jun 19 2016
next sibling parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 14:29:27 UTC, ag0aep6g wrote:
 [...]
      auto wargs = CommandLineToArgvW(GetCommandLineW(), 
 &wargc);
You're calling Windows' CommandLineToArgvW here. I don't think that's what Adam meant by "process it yourself". If you don't like how CommandLineToArgvW parses the command line, don't use it.
I thought the proper way to call GetCommandLineW was precisely through CommandLineToArgvW, now I am lost.
Jun 19 2016
next sibling parent ag0aep6g <anonymous example.com> writes:
On 06/19/2016 05:36 PM, Hugo wrote:
 I thought the proper way to call GetCommandLineW was precisely through
 CommandLineToArgvW, now I am lost.
It may be the proper way, but you don't want the proper way then. I don't know if there's a Windows function for the behavior you want. If there isn't, you may have to implemented it yourself.
Jun 19 2016
prev sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Sunday, 19 June 2016 at 15:36:08 UTC, Hugo wrote:
 I thought the proper way to call GetCommandLineW was precisely 
 through CommandLineToArgvW, now I am lost.
Typically, yes, but you are saying you don't like what CommandLineToArgvW does (it is responsible for handling quotes and backslash escapes), so I'm saying you can do it some other way. GetCommandLineW will give you a raw string of what the user typed. From there, you can treat it all as one argument or split it up however you like. One potentially simple option would be to preprocess it by doing a .replace(`\"`, `\\"`) then pass to CommandLineToArgvW to hack in the extra slash... or you could do a simple little splitter yourself, something along the lines of: --- bool inQuote; size_t startIdx; string[] args; foreach(idx, ch; your_command_line) { if(ch == '"') inQuote = !inQuote; else if(ch == ' ') { if(!inQuote) { args ~= to!string(your_command_line[startIdx .. idx]; startIdx = idx + 1; } } } if(startIdx != your_command_line.length) args ~= to!string(your_command_line[startIdx .. $]; --- or something along those lines, I didn't actually test that. (btw the to!string is optional, you could just leave them as wstrings) But the idea is to just split on space unless you are inside quotes, doing nothing special on backslashes. That'd be what you want (I think).
Jun 19 2016
next sibling parent Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 23:01:26 UTC, Adam D. Ruppe wrote:
 On Sunday, 19 June 2016 at 15:36:08 UTC, Hugo wrote:
 I thought the proper way to call GetCommandLineW was precisely 
 through CommandLineToArgvW, now I am lost.
Typically, yes, but you are saying you don't like what CommandLineToArgvW does (it is responsible for handling quotes and backslash escapes), so I'm saying you can do it some other way. GetCommandLineW will give you a raw string of what the user typed. From there, you can treat it all as one argument or split it up however you like. One potentially simple option would be to preprocess it by doing a .replace(`\"`, `\\"`) then pass to CommandLineToArgvW to hack in the extra slash... or you could do a simple little splitter yourself, something along the lines of: --- bool inQuote; size_t startIdx; string[] args; foreach(idx, ch; your_command_line) { if(ch == '"') inQuote = !inQuote; else if(ch == ' ') { if(!inQuote) { args ~= to!string(your_command_line[startIdx .. idx]; startIdx = idx + 1; } } } if(startIdx != your_command_line.length) args ~= to!string(your_command_line[startIdx .. $]; --- or something along those lines, I didn't actually test that. (btw the to!string is optional, you could just leave them as wstrings) But the idea is to just split on space unless you are inside quotes, doing nothing special on backslashes. That'd be what you want (I think).
Thanks for the ideas, actually I was trying to do a function similar to your splitter (but still having some problems with it): void cleanArgs(in string cmdline, ref string[] args) { uint argc = 0; bool inQuotedMode = false; bool lastCharIsBlank = false; foreach(char c; cmdline) { if(c == '"') inQuotedMode = !inQuotedMode; if(inQuotedMode || (!inQuotedMode && c!=' ')) args[argc] ~= c; if(!inQuotedMode && c==' ' && !lastCharIsBlank) { argc++; lastCharIsBlank = true; } } }
Jun 19 2016
prev sibling parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 23:01:26 UTC, Adam D. Ruppe wrote:
 One potentially simple option would be to preprocess it by 
 doing a .replace(`\"`, `\\"`) then pass to CommandLineToArgvW 
 to hack in the extra slash...
The problem with that approach is that replace does not work with wchar*. I might convert it to string, replace and then typecast as wchar* again because that's what CommandLineToArgvW expects, but when I try to convert the output to strings again, all I get are memory addresses instead. It seems something is lost during conversion or typecast.
Jun 19 2016
parent reply Mike Parker <aldacron gmail.com> writes:
On Monday, 20 June 2016 at 05:11:12 UTC, Hugo wrote:
 On Sunday, 19 June 2016 at 23:01:26 UTC, Adam D. Ruppe wrote:
 One potentially simple option would be to preprocess it by 
 doing a .replace(`\"`, `\\"`) then pass to CommandLineToArgvW 
 to hack in the extra slash...
The problem with that approach is that replace does not work with wchar*. I might convert it to string, replace and then typecast as wchar* again because that's what CommandLineToArgvW expects, but when I try to convert the output to strings again, all I get are memory addresses instead. It seems something is lost during conversion or typecast.
FWIW, it seems there's some problem with print wchar* or strings converted from wchar*. With these lines: auto cmdLine = GetCommandLineW(); auto str = to!string(cmdLine); writeln(str); Whether I use to!string or to!wstring, whether I print str or cmdLine, all I get are addresses. However, replacing GetCommandLineW with GetCommandLineA yields the correct result (my test is compiled as slash.exe): Command: slash "foo\" Output: slash "foo\" It shouldn't hurt to use the A variant, as Windows will do the necessary conversions under the hood. However, I'd love to know what the problem is with converting wchar* to a string type. This also prints an address: auto foo = "I'm a wstring"w.ptr; writeln(to!wstring(foo));
Jun 19 2016
parent Hugo <dmdpathquestion yopmail.com> writes:
On Monday, 20 June 2016 at 05:44:53 UTC, Mike Parker wrote:
 It shouldn't hurt to use the A variant, as Windows will do the 
 necessary conversions under the hood. However, I'd love to know 
 what the problem is with converting wchar* to a string type. 
 This also prints an address:

 auto foo = "I'm a wstring"w.ptr;
 writeln(to!wstring(foo));
There was a bug report in std.conv, which was partially fixed in master branch (the one I used). Compiling your code with that fix produces the expected result. However it seems something is still missing. Regarding GetCommandLineA, I could use it but I believe this would exclude several eastern languages, for example.
Jun 20 2016
prev sibling parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 14:29:27 UTC, ag0aep6g wrote:
 You're calling Windows' CommandLineToArgvW here. I don't think 
 that's what Adam meant by "process it yourself". If you don't 
 like how CommandLineToArgvW parses the command line, don't use 
 it.
What would be the efficient way to talke this then? I tried regex: import std.stdio, std.file, std.path; version (Windows) { import core.sys.windows.windows, std.conv, std.regex; pragma(lib, "shell32.lib"); } enum EXIT_SUCCESS = 0; enum EXIT_FAILURE = 1; int main(string[] originalargs) { string[] args; version (Windows) { SetConsoleOutputCP(65001); static re = regex(`\s+`, "g"); auto wargs = GetCommandLineW(); if (wargs) { args = split(text(wargs), re); debug writefln("'%s'", text(wargs)); } else { writeln("Error getting command line arguments."); return EXIT_FAILURE; } } else args = originalargs; foreach(uint i, string a; args) writefln("Argument %d: '%s'", i, a); return EXIT_SUCCESS; } However it doesn't quite work will all cases (besides I fear in this case a regexp could offer an unnecessary entry point for an exploit): mytestapp dir1 ..\ "another dir\" Argument 0: 'mytestapp' Argument 1: 'dir1' Argument 2: '..\' Argument 3: '"another' Argument 4: 'dir\"'
Jun 19 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 06/19/2016 06:21 PM, Hugo wrote:
 What would be the efficient way to talke this then? I tried regex:
[...]
 However it doesn't quite work will all cases (besides I fear in this
 case a regexp could offer an unnecessary entry point for an exploit):
I don't know if you can solve this with regex alone. May depend on what exact behavior you want. Maybe just write a little function instead that splits the command line, handling quotes and such as you want. If you're not comfortable writing this, then maybe you're in over your head here. Of course, all this wouldn't be necessary if you could change the command line instead to conform with the usual syntax. If the weird behavior you're going for is just personal preference, and there's no actual need, I'd suggest to just write the command lines in the normal way with escape sequences (i.e. "foo\\" to get a trailing backlash instead of a trailing quote).
Jun 19 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 17:49:55 UTC, ag0aep6g wrote:
 I don't know if you can solve this with regex alone. May depend 
 on what exact behavior you want. Maybe just write a little 
 function instead that splits the command line, handling quotes 
 and such as you want. If you're not comfortable writing this, 
 then maybe you're in over your head here.

 Of course, all this wouldn't be necessary if you could change 
 the command line instead to conform with the usual syntax. If 
 the weird behavior you're going for is just personal 
 preference, and there's no actual need, I'd suggest to just 
 write the command lines in the normal way with escape sequences 
 (i.e. "foo\\" to get a trailing backlash instead of a trailing 
 quote).
What you suggest is non-standard in Windows, and besides I might not be the only user of the application. I was thinking in doing pecisely what you suggest, writing a little function. I like programming little apps now and then as a hobby, but giving up every time I encounter a difficulty is not for me. I was just asking in case some of the experienced D programmer here could recommend an efficient and preferably simple way to do it. ;)
Jun 19 2016
parent reply ag0aep6g <anonymous example.com> writes:
On 06/20/2016 12:38 AM, Hugo wrote:
 What you suggest is non-standard in Windows,
I don't buy this. MSDN says about "Parsing C++ Command-Line Arguments" [1]:
 A double quotation mark preceded by a backslash (\") is interpreted 
as a literal double quotation mark character ("). As we've seen, that's also how Windows' own CommandLineToArgvW function behaves. I don't see how you can consider this "non-standard", when Windows provides a nice function for it, while there doesn't seem to be one for your way, or at least it's harder to find. [1] https://msdn.microsoft.com/en-us/library/17w5ykft.aspx
Jun 19 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Sunday, 19 June 2016 at 23:12:10 UTC, ag0aep6g wrote:
 On 06/20/2016 12:38 AM, Hugo wrote:
 What you suggest is non-standard in Windows,
I don't buy this. MSDN says about "Parsing C++ Command-Line Arguments" [1]:
 A double quotation mark preceded by a backslash (\") is
interpreted as a literal double quotation mark character (").
Perhaps I should have said unusual rather than non-standard. But if you want to understand better what I mean, try doing this in the command line, it works correctly: cd \ mkdir test cd test\ mkdir "..\second test\" cd "..\second test\" While it's true that you can also do this, it's not typical: mkdir "\third test\\" cd "\third test\\"
Jun 19 2016
parent reply ag0aep6g <anonymous example.com> writes:
On Monday, 20 June 2016 at 02:19:22 UTC, Hugo wrote:
 Perhaps I should have said unusual rather than non-standard. 
 But if you want to understand better what I mean, try doing 
 this in the command line, it works correctly:

 cd \
 mkdir test
 cd test\
 mkdir "..\second test\"
 cd "..\second test\"
On the other hand, the way D gets the arguments is the same as in C/C++. Doing it differently than that would be unusual, too. Either way, someone is going to be surprised. I would guess that you're in the minority here with your expectation. It's better then to surprise you than the majority of people who expect the same behavior as in C/C++ programs.
Jun 20 2016
parent reply Hugo <dmdpathquestion yopmail.com> writes:
On Monday, 20 June 2016 at 10:01:25 UTC, ag0aep6g wrote:
 On the other hand, the way D gets the arguments is the same as 
 in C/C++. Doing it differently than that would be unusual, too.
Not necessarily, cmd.exe is made in C/C++ AFAIK, most other console applications for Windows behave the same way too.
Jun 20 2016
parent reply ag0aep6g <anonymous example.com> writes:
On Monday, 20 June 2016 at 12:38:23 UTC, Hugo wrote:
 Not necessarily, cmd.exe is made in C/C++
 AFAIK, most other console applications for Windows behave the 
 same way too.
As seen on MSDN, it's how "Microsoft C/C++ startup code" does it. It's what you get in a C main's argv. Populating a D main's args in a different way would be unusual. Of course you can parse the command line yourself, and do it differently then. You can do this in C, in C++, and in D too. But the default is the other way, in all of them.
Jun 20 2016
parent Hugo <dmdpathquestion yopmail.com> writes:
On Monday, 20 June 2016 at 12:55:21 UTC, ag0aep6g wrote:
 On Monday, 20 June 2016 at 12:38:23 UTC, Hugo wrote:
 Not necessarily, cmd.exe is made in C/C++
 AFAIK, most other console applications for Windows behave the 
 same way too.
As seen on MSDN, it's how "Microsoft C/C++ startup code" does it. It's what you get in a C main's argv. Populating a D main's args in a different way would be unusual. Of course you can parse the command line yourself, and do it differently then. You can do this in C, in C++, and in D too. But the default is the other way, in all of them.
I guess all the console programs I have used for MS products (since MS-DOS) have been unusual then according to MSDN. ;)
Jun 20 2016