Home AMX User Forum NetLinx Studio

Bug, or user error?

PROGRAM_NAME='test'

DEFINE_DEVICE
TP = 11001:1:0


DEFINE_VARIABLE
DEFINE_CALL'TEST'{
    LOCAL_VAR CHAR testCmd[20]
    LOCAL_VAR INTEGER x
    local_var integer temp
    
    x = $80
    testCmd = "$FD,$81,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
    F_TEST(testCmd)
    testCmd = "$FD,$82,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
    F_TEST(testCmd)
    testCmd = "$FD,$83,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
    F_TEST(testCmd)
}
DEFINE_FUNCTION INTEGER F_TEST(CHAR msg[]){
    

    local_var INTEGER iAddr
    local_var INTEGER cCmd
    local_var CHAR cData[7]
    
    IF(LENGTH_STRING(msg > 10)){
	msg = MID_STRING(msg,11,10)
    }
    cCmd = msg[2]

    SEND_STRING 0, "'cCmd ', ITOA(cCmd)"
}

DEFINE_EVENT
BUTTON_EVENT[TP, 1]
{	
    PUSH:{
	CALL'TEST'
    }
}

DEFINE_PROGRAM



If you set a breakpoint and single step, you get different output

Comments

  • HedbergHedberg Posts: 671
    travis wrote: »
    PROGRAM_NAME='test'
    
    DEFINE_DEVICE
    TP = 11001:1:0
    
    
    DEFINE_VARIABLE
    DEFINE_CALL'TEST'{
        LOCAL_VAR CHAR testCmd[20]
        LOCAL_VAR INTEGER x
        local_var integer temp
        
        x = $80
        testCmd = "$FD,$81,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
        F_TEST(testCmd)
        testCmd = "$FD,$82,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
        F_TEST(testCmd)
        testCmd = "$FD,$83,$FF,$FF,$FF,$FF,$FF,$FF,$FF,$AB,01,x,$00,$00,$00,$00,$00,$00,$00,$AA"
        F_TEST(testCmd)
    }
    DEFINE_FUNCTION INTEGER F_TEST(CHAR msg[]){
        
    
        local_var INTEGER iAddr
        local_var INTEGER cCmd
        local_var CHAR cData[7]
        
        IF(LENGTH_STRING(msg > 10)){
    	msg = MID_STRING(msg,11,10)
        }
        cCmd = msg[2]
    
        SEND_STRING 0, "'cCmd ', ITOA(cCmd)"
    }
    
    DEFINE_EVENT
    BUTTON_EVENT[TP, 1]
    {	
        PUSH:{
    	CALL'TEST'
        }
    }
    
    DEFINE_PROGRAM
    
    
    

    If you set a breakpoint and single step, you get different output

    If you watch the msg variable in debug you can see what's happening. I have no idea why the variable is keeping its value from the first call of F_Test (like a normal local variable) when you run normally but is being reset with subsequent calls when you single step, but that's what's happening. When you run normally, the value of msg is staying the same for the subsequent calls and your if() fails.

    Probably you already know what the solution is -- don't modify the value of the calling parameter inside the subroutine.

    Something like:
    DEFINE_FUNCTION INTEGER F_TEST(CHAR msg[]){
        
    
        local_var INTEGER iAddr
        local_var INTEGER cCmd
        local_var CHAR cData[7]
        local_var char msg2[10]
        
        IF(LENGTH_STRING(msg > 10)){
    	msg2 = MID_STRING(msg,11,10)
        }
        cCmd = msg2[2]
    
        SEND_STRING 0, "'cCmd ', ITOA(cCmd)"
    }
    
    

    To answer the question -- I think it's a bug.
  • GregGGregG Posts: 251
    It's actually a choice that has to be made when creating a compiler:

    http://qntm.org/call

    Some languages support both ways if you flag the parameter name in the function, NetLinx does not.
  • HedbergHedberg Posts: 671
    GregG wrote: »
    It's actually a choice that has to be made when creating a compiler:

    http://qntm.org/call

    Some languages support both ways if you flag the parameter name in the function, NetLinx does not.

    I understand call by reference and call by value, but saying that Netlinx is call by reference doesn't explain the behavior that we're seeing here. At least, it doesn't explain it to me.

    I understand that in the subroutine F_TEST the value of the variable that is being passed as a parameter is being changed by the subroutine. But then,F_TEST terminates and the parameter is modified and then F_TEST is being called again. Call by reference implies to me that the exact same memory location is being modified with each assignment to the variable so that when F_TEST is called the second time the value in that memory location should be the value that it has in the calling code. That is how it appears to work when you step through the code using debug. Surely the code should not work differently when using debug, should it?
  • GregGGregG Posts: 251
    Hedberg, you are correct and I'm sorry - this is a bug in debug.

    I traced it down to mainly a problem with the "if" test in F_TEST():

    IF(LENGTH_STRING(msg > 10))

    When you change it to what he probably intended to write:

    IF(LENGTH_STRING(msg) > 10)

    Then debug and normal runs act the same.


    Not sure why debug mode would treat LENGTH_STRING(msg>10) as string with length.

    (msg>10) should always evaluate to an integer (boolean) non-array value of 0 or 1 with no length -- msg the string is either > 10 the integer or it isn't. So length_string of that single 0 or 1 should always return 0 and F_TEST() should never execute msg = MID_STRING(msg,11,10)
  • travistravis Posts: 180
    IF(LENGTH_STRING(msg > 10))

    AAAAAUUGHGGGffff1#$%!
Sign In or Register to comment.