QB64.org Forum

Active Forums => QB64 Discussion => Topic started by: hanness on December 13, 2020, 10:33:28 pm

Title: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 13, 2020, 10:33:28 pm
EDIT: I neglected to note that I am using the Dec 7, 2020 Development release of QB64 (64-bit) running on Win 10 20H2

I'm passing parameters to a QB64 program but can't get it consistently read the parameters.

There is something really interesting about the behavior.

Let's start with sample code:

Code: QB64: [Select]
  1. WIDTH 120, 30
  2.  
  3. DIM count AS INTEGER
  4.  
  5.  
  6. FOR c = 1 TO count
  7.     PRINT "Parameter: "; c; "is : "; COMMAND$(c)
  8.  
  9.  

I compile the program and call it "test.exe".

Brief explanation: All that this program does is display the parameters passed to it on the command line.

This where it gets interesting.

Below are several runs of the program with the resulting output. My comments are shown before each run. Note that my goal is to pass GUID volume IDs as at least one of the parameters but as the last sample below shows, the problem is not limited to passing GUID Vol IDs.

1) In this run I pass a GUID Volume ID with a backslash at the end. On my particular system this is equivalent to "I:\". Note how the backslash at the end has been stripped off.

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\"
Parameter 1 is : \\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}"

2) Here I run the command with "\Folder1" at the end (equivalent to "I:\Folder1" on my system). The output is fine.

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\Folder1"
Parameter 1 is : \\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\Folder1

3) I add a backslash and it gets stripped off.

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\Folder1\"
Parameter 1 is : \\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}"\Folder1

4) Here is a path with a space in it and it is handled just fine.

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\Folder1\Folder 2"
Parameter 1 is : \\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\Folder1\Folder 2

5) Here is another path with a space in it. Notice how the output on this one is completely butchered!

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\My Media"
Parameter 1 is : \\My Media

6) This next one is not a valid path, but it simply illustrates the odd behavior. This is the same input as #5 above but without the backslash before "my media", and this works fine! Why?

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}my media"
Parameter 1 is : \\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}my media

7) Just to show that the issue has nothing to do with the structure of a GUID vol ID, here is a simpler input that outputs incorrectly:

C:\QB64_Test>test "this is a test\"
Parameter 1 is : this is a test"

-------------------

Why is this behavior so odd? My code is crazy simple so I have a hard time believing I have anything wrong within the code, but if I do I would love to know what it is.

Any insight would be greatly appreciated.

Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SpriggsySpriggs on December 14, 2020, 08:26:55 am
@hanness

I'm not sure running the latest build is always the best thing but just running the current stable (1.4) I do see some of the problems you are having. The last backslash is stripped off no matter what unless I escape with another backslash, which then causes it to show two backslashes rather than one. For this parameter:
Quote
"\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\My Media"
I had no issues. It showed just fine. All others were like you say. Backslash disappears. QB64 doesn't require an ending backslash on a path (try doing PRINT _CWD$) so you should still be OK when things like that happen (not saying they should happen, just that it shouldn't break anything). Or, of course, you can add the backslash yourself if it isn't present by checking if the last character is a backslash and adding it if not.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: FellippeHeitor on December 14, 2020, 09:53:23 am
If you pass it without the quotes and read COMMAND$ (without the indexing parameter), you can get the full command line, backslash included:

  [ This attachment cannot be displayed inline in 'Print Page' view ]  

There's nothing explicitly removing backslashes in the internal code for COMMAND$(), so I'm assuming it's something specific to C++'s argv - still haven't tested it though.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SpriggsySpriggs on December 14, 2020, 09:54:27 am
@FellippeHeitor Yes, but now part of the parameter is thought to be part of other parameters rather than just the first. By adding spaces and no quotes, there are now 4 parameters rather than 1.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: FellippeHeitor on December 14, 2020, 09:55:51 am
I meant not to use the index, but just read COMMAND$ - that'll work if he's only going to be passing one parameter. No need for _COMMANDCOUNT in that case.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SpriggsySpriggs on December 14, 2020, 09:57:43 am
Ah, I see. That makes sense.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 14, 2020, 10:55:00 am
The problem is that I will frequently be passing 5 or 6 parameters and on occasion even more, so I really need quotes on paths to indicate that this is a single parameter.

Bear in mind that QB64 should really not be trying to read this as a path. It could be any kind of data that I am passing, who is to say that what is between the quotes is actually a path? Whatever I send in quotes should be taken literally as a single parameter and not interpreted in any manner as anything other than a string of characters.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SpriggsySpriggs on December 14, 2020, 10:58:03 am
@hanness

I don't think it is just interpreting it as a path and automatically stripping the backslash because of this. I think it is just like you said: a bug (but maybe not a bug of QB64 itself). It just plain disappears, which it shouldn't. This, however, could be related to this:

https://stackoverflow.com/questions/9287812/backslash-and-quote-in-command-line-arguments (https://stackoverflow.com/questions/9287812/backslash-and-quote-in-command-line-arguments)
https://stackoverflow.com/questions/1291291/how-to-accept-command-line-args-ending-in-backslash (https://stackoverflow.com/questions/1291291/how-to-accept-command-line-args-ending-in-backslash)

This appears to be the code on the backend of QB64 which does the COMMAND$:
Code: C++: [Select]
  1. i=argc;
  2. if (i>1){
  3.     //calculate required size of COMMAND$ string
  4.     i2=0;
  5.     for (i=1;i<argc;i++){
  6.         i2+=strlen(argv[i]);
  7.         if (i!=1) i2++;//for a space
  8.     }
  9.     //create COMMAND$ string
  10.     func_command_str=qbs_new(i2,0);
  11.     //build COMMAND$ string
  12.     i3=0;
  13.     for (i=1;i<argc;i++){
  14.         if (i!=1){func_command_str->chr[i3]=32; i3++;}
  15.         memcpy(&func_command_str->chr[i3],argv[i],strlen(argv[i])); i3+=strlen(argv[i]);
  16.     }
  17.     }else{
  18.     func_command_str=qbs_new(0,0);
  19. }
  20.  
  21. func_command_count = argc;
  22. func_command_array = argv;
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SpriggsySpriggs on December 14, 2020, 12:47:27 pm
The best way right now is to go ahead and do two backslashes for the last backslash. Windows command line sees the backslash quote combo as you using the backslash to escape the quote. Two backslashes would tell it that you are escaping the backslash, therefore printing one of them. I tried it with one of your problematic parameters with no issues. Backslash at the end was preserved.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: Cobalt on December 14, 2020, 12:52:04 pm
Must be Fellippe's hatred of backslash manifesting itself.
Thats\ why\ I\ use\ them\ as\ much\ as\ I\ Can\!\ :)\

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\!

Muha ha ha ha ha!
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 14, 2020, 01:11:01 pm
The best way right now is to go ahead and do two backslashes for the last backslash. Windows command line sees the backslash quote combo as you using the backslash to escape the quote. Two backslashes would tell it that you are escaping the backslash, therefore printing one of them. I tried it with one of your problematic parameters with no issues. Backslash at the end was preserved.

I'll give that a try, but just be aware that the problem does not happen only when a backslash ends the input. Here is an example:

C:\QB64_Test>test "\\?\Volume{72643cab-e1da-4ae2-ae48-57c7a496ae73}\My Media"
\\My Media

Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 16, 2020, 09:31:22 am
So, out of curiosity, any chance that this issue could be fixed for Version 1.5?
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: FellippeHeitor on December 16, 2020, 09:37:21 am
Let us rule out that this is not standard c++ argv behaviour first. If it is, there's no fixing.

Base code is in internal/c/libqb.cpp - that's where we'll all be looking. Search for func_command
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 16, 2020, 03:54:52 pm
Thanks
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: mpgcan on December 17, 2020, 04:44:56 am
It's not a bug. QB64's compiler imitates Microsoft C/C++ compiler in that it adds extra code to the executable. This code is run before calling WinMain (or main), it intercepts and parses the command line before passing onto argv.

The C/C++ parameter parsing rules:

Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: FellippeHeitor on December 17, 2020, 08:01:54 am
Thanks for chiming in, @mpgcan.

The rules above come from https://docs.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments?view=msvc-160&viewFallbackFrom=vs-2017

The code sample provided in that page, simplified/adapted to be compiled with the c compiler we ship:

Code: C++: [Select]
  1. // ARGS.C illustrates the following variables used for accessing
  2. // command-line arguments and environment variables:
  3. // argc  argv  envp
  4. //
  5.  
  6. #include <stdio.h>
  7.  
  8. void main( int argc, // Number of strings in array argv
  9. char *argv[],      // Array of command-line argument strings
  10. char **envp )      // Array of environment variable strings
  11. {
  12.     int count;
  13.  
  14.     // Display each command-line argument.
  15.     printf( "\nCommand-line arguments:\n" );
  16.     for( count = 0; count < argc; count++ )
  17.         printf( "  argv[%d]   %s\n", count, argv[count] );
  18.        
  19.     return;
  20. }

The result:

  [ This attachment cannot be displayed inline in 'Print Page' view ]  

As I stated earlier, there's nothing in the QB64 code that's stripping backslashes. The behavior is inherent to Windows' handling of the command line.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: FellippeHeitor on December 17, 2020, 08:27:26 am
The workaround, as also indicated above, is to double the last backslash:

  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: hanness on December 18, 2020, 02:15:01 am
Thanks. I very much appreciate the analysis. What's odd is that I don't see anything in those rules to explain this particular result:

C:\QB64_Test>test "\\?\Volume{06b8848c-3cfc-11eb-a783-60f2624ff3b8}\My Media"
Parameter 1 is : \\My Media

However, I'm not really going to spend any more cycles figuring that part out because it's a moot point now.

Fortunately, this was going to be for a rather small utility and I can write this up as a batch file easily enough.
Title: Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
Post by: SMcNeill on December 18, 2020, 02:22:54 am
\\My Media is probably a system mapped shortcut, like My Music and My Pictures.

The full path would be something like C:\Users\Bob\My Media, with a network mapping of \\My Media as a shortcut to them.

For whatever reason, windows is returning and passing the registered shortcut rather than the full path, for this shortcut.