Page 1 of 1

Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 10:07 am
by ewardd
Hello everyone

I got a really strange situation, but most of times its just me not seeing something obvious.
I have wrote a procedure, that splits text by arguments
Example: "echo hello world" -> echo, hello, world
Example: "echo "hello world" alotofspaces" -> echo, hello world, alotofspaces

Procedure works as I need, but problem starts with saving results. Im passing a pointer *Arg to the procedure (*ArgArray there), and procedure must write pointer to each splitted argument. As much as I know about pointers, it must work.

Actually you dont need to take a look at procedure at all.

Code: Select all

Procedure Engine_ParseCommandLine(Command.s, *ArgArray)
  Argc = 0 : Symbol.s = "" : BackToDQuote = #False : 
  *SelectionStart = @Command

  LenOfCmd = Len(Command)
  For *CursorPos = @Command To @Command+LenOfCmd
    Symbol.s = PeekS(*CursorPos, 1)
    IgnoreEmptyArgument = #False
    
    If Symbol = " " Or *CursorPos = @Command+LenOfCmd
      Argument.s = PeekS(*SelectionStart, *CursorPos-*SelectionStart)
      *SelectionStart = *CursorPos+1
    ElseIf Symbol = #DOUBLEQUOTE$
      Argument.s = PeekS(*SelectionStart, *CursorPos-*SelectionStart)
      ; About situation, when SomeRandomArgument"SecondArgument"
      BackToDQuote  = #True : Goto ParseCommandLine_AddArgument : ParseCommandLine_DQuote:
      
      If *CursorPos+1 < @Command+LenOfCmd
        Pos = FindString(PeekS(*CursorPos+1), #DOUBLEQUOTE$)
        If Pos
          Argument = PeekS(*CursorPos+1, Pos-1) ; We gonna copy everything from dquote to dquote
          *CursorPos+Pos ; Moving loop till second dquote (skip all these characters in quotes)
          *SelectionStart = *CursorPos+1 ; Moving our selection pointer right after closing dquote
          IgnoreEmptyArgument = #True
        Else
          Argument = PeekS(*CursorPos+1) ; Second (close) dquote not found, so we gonna copy everything till end
          *CursorPos = @Command+LenOfCmd ; Moving loop in end.
        EndIf
      EndIf
    EndIf
    ; 
    ParseCommandLine_AddArgument:
    If Argument.s <> "" Or IgnoreEmptyArgument = #True; Ignoring empty spaces
      Argument = ReplaceString(Argument, "\dq", #DQUOTE$)
      *NewArg = AllocateMemory(Len(Argument.s)+1) ; Allocate memory for new argument
      PokeS(*NewArg, Argument) ; Writing Argument intro memory
      PokeI(*ArgArray+Argc*4, *NewArg) ; Writing pointer to our argument intro pointers array
      Argument = "" : Argc+1
    EndIf
    If BackToDQuote  = #True : BackToDQuote  = #False : Goto ParseCommandLine_DQuote : EndIf
    
  Next
  
  ProcedureReturn Argc
EndProcedure

*Arg = AllocateMemory(28)
Debug *Arg
timer = 0
timer2 = 0
QueryPerformanceCounter_(@timer);

Engine_ParseCommandLine("echo hello world", *Arg)
QueryPerformanceCounter_(@timer2) ; Remove this line
Debug timer2-timer
Debug *Arg
Weird thing is that last Debug *Arg shows not an address. Last time I just got value 2.
Tho If you remove QueryPerformanceCounter *Arg shows right address. Probably thats something about stack / pointer register idk. Not really that good yet.

But If you change *Arg on, example, *Argz, everything gonna work okay.

Code: Select all

*Argz = AllocateMemory(28)
Debug *Argz
timer = 0
timer2 = 0
QueryPerformanceCounter_(@timer);

Engine_ParseCommandLine("echo hello world", *Argz)
QueryPerformanceCounter_(@timer2)
Debug timer2-timer
Debug *Argz
So, whats wrong with *Arg? I have no idea, if only *Arg is not used somewhere under PB, but I really dubt.
Im really interested in reason. Thanks.

Re: Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 10:39 am
by nco2k
i only took a quick look, so there might be even more bugs in your code.

change line 35 from:

Code: Select all

*NewArg = AllocateMemory(Len(Argument.s)+1)
to:

Code: Select all

*NewArg = AllocateMemory((Len(Argument.s)+1)*SizeOf(Character))
change line 37 from:

Code: Select all

PokeI(*ArgArray+Argc*4, *NewArg)
to:

Code: Select all

PokeI(*ArgArray+Argc*SizeOf(Integer), *NewArg)
change line 49+50 from:

Code: Select all

timer = 0
timer2 = 0
to:

Code: Select all

timer.q = 0
timer2.q = 0
c ya,
nco2k

Re: Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 11:25 am
by Joris
Just 5 cents...

Code: Select all

QueryPerformanceCounter_
This timer is not always acurate (I experienced). Better use this imo :

Code: Select all

 StartTime = ElapsedMilliseconds()             ; Get the actual value
  Delay(1000)                                   ; Wait 1000 milliseconds
  ElapsedTime = ElapsedMilliseconds()-StartTime ; 'ElapsedTime' value should be about 1000 milliseconds

Re: Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 12:10 pm
by ewardd
nco2k, thanks for corrections. I'd apply them anyway a bit later, just was playing with pointer just as I done this function on fast hand and didnt watch at timer results, so missed that .q type, alright.

Joris, Im using QueryPerformanceCounter_ because its about ns not ms. ElapsedMilliseconds() timer in my case gonna show 0 ms.

I'd like to know whats wrong with *Arg pointer name

Re: Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 12:21 pm
by nco2k
ewardd wrote:I'd like to know whats wrong with *Arg pointer name
and i gave you an answer. QueryPerformanceCounter_() uses a pointer to a quad (8byte). your timer variable is a integer (4byte on win32). you try to write 8 byte into a 4 byte variable -> overflow.

c ya,
nco2k

Re: Pointer doesnt work properly with specific name

Posted: Thu Aug 04, 2016 12:28 pm
by ewardd
Thanks, nco2k. Somewhy didnt even think about it :wink: