Author Topic: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$  (Read 5556 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
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.

« Last Edit: December 13, 2020, 10:47:49 pm by hanness »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
@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.
« Last Edit: December 14, 2020, 08:52:56 am by SpriggsySpriggs »
Shuwatch!

FellippeHeitor

  • Guest
If you pass it without the quotes and read COMMAND$ (without the indexing parameter), you can get the full command line, backslash included:

  [ You are not allowed to view this attachment ]  

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.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
@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.
Shuwatch!

FellippeHeitor

  • Guest
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.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Ah, I see. That makes sense.
Shuwatch!

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
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.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
@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/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;
« Last Edit: December 14, 2020, 11:11:10 am by SpriggsySpriggs »
Shuwatch!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
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.
Shuwatch!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Must be Fellippe's hatred of backslash manifesting itself.
Thats\ why\ I\ use\ them\ as\ much\ as\ I\ Can\!\ :)\

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

Muha ha ha ha ha!
Granted after becoming radioactive I only have a half-life!

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
« Reply #10 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


Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
« Reply #11 on: December 16, 2020, 09:31:22 am »
So, out of curiosity, any chance that this issue could be fixed for Version 1.5?

FellippeHeitor

  • Guest
Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
« Reply #12 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

Offline hanness

  • Forum Regular
  • Posts: 210
    • View Profile
Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
« Reply #13 on: December 16, 2020, 03:54:52 pm »
Thanks

Marked as best answer by hanness on December 17, 2020, 09:15:17 pm

Offline mpgcan

  • Newbie
  • Posts: 26
    • View Profile
Re: Possible bug? Difficulty passing parameters to a QB64 program with COMMAND$
« Reply #14 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:

  • Parameters are always separated by a space.
  • If a parameter does not contain any spaces or double quotes, no need to enclose that parameter in double quotes.
  • Enclose spaces in a double quoted section.
  • A double quoted section can be anywhere within a parameter.
  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
  •     A double quotation mark preceded by a backslash (\") is interpreted as a literal double quotation character (").
  •     An even number of backslashes followed by a double quotation mark. Interpreted as one backslash for every pair of backslashes, and the double quotation mark as a string delimiter.
  •    An odd number of backslashes followed by a double quotation mark. Interpreted as one backslash for every pair of backslashes, and the double quotation mark is "escaped" by the remaining backslash producing a literal double quotation mark (").
  • Inside a double quoted block a pair of double quotes (i.e. "") interpreted as a literal double quotation mark (")