Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Command$ issues
#1
I am writing a parser which accepts the token input from the keyword Command$
used when Alt-R -> C(ommand) is set to 10 * (10 - 1) and the parser gets the command line override.

The parser is accepting the * as multiplication and calculates the result. Only when setting
Inpt$ = Command$ the string shows up as a lengthy list of all files in the default directory!?

I know if the override is surrounded by Quotes this does not happen but I can't guarentee any user would..

Is this a feature or a bug??

Erik.
Reply
#2
This is a feature of the command line shell, not anything QB64 is doing, so from a program standpoint there's nothing that can fix this. If you use an unquoted * then the shell automatically expands it into a list of all the files in the current directory. * isn't the only special character either, plenty of other character do special stuff and require quoting (Ex. `>` and `<` for redirection)

Ideally anyone who uses command line programs often would understand the need to quote this kind of input so I wouldn't really worry about it much personally, it's just something to mention in documentation.

As for the `Modify COMMAND$` dialog in the QB64 IDE, that's an interesting case but I think having the IDE treat it as it would work on the command line (for that host) is probably the best behavior, even if it's a bit surprising. Any quoting we attempted would screw up the individual command entries (`Command$(i)`) so it would be annoying in different ways. Additionally it wouldn't really fix your problem, anybody who goes to use the program outside the IDE will still need to do the quoting so the IDE would be giving you a false sense of how it actually works in practice
Reply
#3
I've developed this some time ago to make sure I really get the parameters exaclty as typed by the user:

Code: (Select All)
Function getCommand$ (n%)
  $If WIN Then
    Static cmd$(100), ccount As Integer
    If cmd$(0) = "" Then
      Declare Library
        Function GetCommandLineA%& ()
      End Declare
      Dim m As _MEM, ms As String * 1000
      a%& = GetCommandLineA: m = _Mem(a%&, Len(ms)): ms = _MemGet(m, m.OFFSET, String * 1000)
      ccount = -1: p0% = 1: p% = 1
      Do While Asc(ms, p%) > 0
        Select Case Mid$(ms, p%, 1)
          Case Chr$(34)
            qq% = 1 - qq%
          Case "'"
            q% = 1 - q%
          Case " "
            If q% = 0 And qq% = 0 Then
              ccount = ccount + 1
              cmd$(ccount) = _Trim$(Mid$(ms, p0%, p% - p0%))
              first$ = Left$(cmd$(ccount), 1): last$ = Right$(cmd$(ccount), 1)
              If first$ = last$ _AndAlso InStr("'" + Chr$(34), first$) > 0 Then
                cmd$(ccount) = Mid$(cmd$(ccount), 2, Len(cmd$(ccount)) - 2)
              End If
              If cmd$(ccount) = "" Then ccount = ccount - 1
              p0% = p% + 1
            End If
          Case Else
        End Select
        p% = p% + 1
      Loop
      If p% > p0% Then
        ccount = ccount + 1
        cmd$(ccount) = _Trim$(Mid$(ms, p0%, p% - p0%))
        first$ = Left$(cmd$(ccount), 1): last$ = Right$(cmd$(ccount), 1)
        If first$ = last$ _AndAlso InStr("'" + Chr$(34), first$) > 0 Then
          cmd$(ccount) = Mid$(cmd$(ccount), 2, Len(cmd$(ccount)) - 2)
        End If
        If cmd$(ccount) = "" Then ccount = ccount - 1
      End If
      _MemFree m
    End If
    If n% < 0 Then
      getCommand$ = _Trim$(Str$(ccount))
    ElseIf n% <= ccount Then
      getCommand$ = cmd$(n%)
    Else
      getCommand$ = ""
    End If
  $Else
    getCommand$ = Command$(n%)
  $End If
End Function

Val(getCommand$(-1)) returns the number of params
getCommand$(0) returns the name of the executable/command
getCommand$(1) and further return the params
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#4
if you are doing any programming for linux.  you have to be careful with dollar sign as well.  unprotected something like $HOME would surprise another user of your program.  but this should be needed in an utility which processes text files, which converts audio or images.  or something like that.  not in a gui program.

keep in mind that qb64 treats command$ differently from qb45.  the older product had that function returning its value only in uppercase.  there wouldn't have been an easy way around that.  i used to write utilities that relied on the value of command$.  but eventually had to turn away to look for ini-type files that could provide more input information.  which could be a different pain for another person using my program.  although i always required the main input text file to be in the same directory as the executable.
Reply
#5
The getCommand$ function works well! Parses 10 * (10 - 1) correctly as well as "abc def"

Kinda lengthy though however, using the following works!

Code: (Select All)
Rem get command$
Rem $Dynamic
DefLng A-Z
x$ = getCommand$(-1)
v = Int(Val(x$))
x$ = ""
For z = 1 To v
  x$ = x$ + getCommand$(z)
Next
Print x$
End

It parses spaces and symbols quite nicely which is what I wanted it to do...

@mdijkens: thanks for your work!
Reply
#6
@mdijkens: thanks for your work! 

btw: your getCommand$ function does not parse the following correctly:

"abc def","def ghi"

instead it returns:

"abc def",def ghi

can this be fixed?

Thanks.
Reply
#7
Hmm,
When I try this:  "abc def","def ghi"
I get this:  abc def","def ghi
Which is correct, since this is 1 parameter with quotes around it; the comma is not a parameter separator in wndows and linux; the space is
If you want this example to be 2 parameter, use:  "abc def" "def ghi"
45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
Reply
#8
I don't really don't want to parse the command line and place the values in an array and recombine the returned array...

What I needed was simply the entire command line such as this:

Code: (Select All)
Rem $Dynamic
DefLng A-Z
x$ = readCommand$
Print x$
End

Function readCommand$
  Declare Library
      Function GetCommandLineA%& ()
  End Declare
  Dim m As _MEM, ms As String * 1000
  a%& = GetCommandLineA
  m = _Mem(a%&, Len(ms))
  ms = _MemGet(m, m.OFFSET, String * 1000)
  If a%& Then
      cmd$ = ms
      eol = InStr(cmd$, Chr$(0))
      If eol Then
        cmd$ = Left$(cmd$, eol - 1)
      End If
      ' parse off program name.
      eol = InStr(2, cmd$, Chr$(34)) + 1
      cmd$ = Mid$(cmd$, eol)
  End If
  _MemFree m
  readCommand$ = cmd$
End Function
Reply
#9
Quote:45y and 2M lines of MBASIC>BASICA>QBASIC>QBX>QB64 experience
MBASIC>BASICA>QBASIC>QBX>VB10>QB64>VB5 experience
Reply




Users browsing this thread: 1 Guest(s)