1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Functions and Ctrl-C

Discussion in 'T&T - Functions' started by nchernoff, Jun 4, 2008.

  1. nchernoff

    nchernoff Administrator Staff Member

    Joined:
    May 16, 2008
    Messages:
    42
    Likes Received:
    1
    Migrated From JP Software Wiki

    Description

    A function that expands across multiple lines can be defined using the function command by joining all lines together with the & separator. Single-line functions created this way can't handle cancellation by means of Ctrl-C or Ctrl-Break. This page compares the effects of Ctrl-C cancellation of single-line functions vs. multi-line functions as describe in article Complex Functions.

    To start with, we need to create a single-line function for our batch script. It is easier to write the definition in its own file and then source that file into the batch script.
    Code:
    REM Source the definition of a function
    function /R "%@path[%_batchname]%@name[%_batchname].fun"
    
    In this example, "%@path[%_batchname]%@name[%_batchname].fun" is used instead of specifying a fixed file name of the file that contains the function definition. This allows the script file name to change without having to change the script code. For instance, a script named MyProgram.btm will source a file named MyProgram.fun located in the start directory of the script.

    The function is defined as
    Code:
    : a multi-line function defined on a single line
    Single=%@execstr[^
    pause Single:Press Ctrl-C then do (N)ot cancel batch job... 1>2 &^
    echo Single returns %1^
    ]
    
    Single is a simple function, but it could be much more complex and still be written as a one-liner. All lines are joined using the & separator followed by the ^ escape character as the last character of the line. The command processor knows to join lines together when it finds the escape character at the end of a line.

    Single pauses to print instructions to the standard error file, then prints its return value which is captured by the %@execstr function and returned to the caller.

    Then we need to call Single from our script file
    Code:
    REM Call the function
    echo %@Single[1]
    echo Script ended
    
    and run the script file
    Code:
    C:\>CancelFunction.btm
    Single:Press Ctrl-C then do (N)ot cancel batch job...^C
    
    Cancel batch job C:\CancelFunction.btm ? (Y/N/A) : N
    Script ended
    
    C:\>
    
    In this example, Single did not return its value. This is because pressing Ctrl-C stopped execution of the current line of CancelFunction.btm, that is echo %@Multi[1] to prompt the user for action. When the user pressed N, execution resumed from the next script line, that is echo Script ended.

    Therefore, all pending statements of Single were skipped, since it is defined on a single line. To be able to handle Ctrl-C from within a function, we need to write the function on multiple lines. We start with the body of the function as a subroutine in the script file:
    Code:
    :Multi [a]
    pause Multi: Press Ctrl-C then do (N)ot cancel batch job... 1>2
    echo Multi returns %a
    return
    
    then we wrap the subroutine into a function
    Code:
    REM Define a function on multiple lines
    function Multi=`%@execstr[gosub Multi %$]`
    
    and run the script file

    Code:
    C:\>CancelFunction2.btm
    Multi: Press Ctrl-C then do (N)ot cancel batch job...^C
    
    Cancel batch job C:\CancelFunction2.btm ? (Y/N/A) : N
    Multi returns 1
    Script ended
    In this example, Multi returned its value in spite of the pause statement being cancelled by Ctrl-C.

    For more information about running functions as subroutines read article Complex Functions.

    Single-line functions can still be used effectively with Ctrl-C when it is enough for the script file to detect that the function was interrupted; just use code similar to the following

    Code:
    REM Show how to deal with Ctrl-C in a single-line function
    set return=Single was cancelled
    set return=%@Single[1]
    echo %return
    If Ctrl-C interrupts line set return=%@Single[1], the previous value "Single was cancelled" is not overwritten and can be used to determine that Ctrl-C was hit.

    Contributed by: Stefano Piccardi 09:44, 5 January 2007 (CST)

    CancelFunction.btm

    Code:
    @echo off
    setlocal
    
    REM Source the definition of a function
    function /R "%@path[%_batchname]%@name[%_batchname].fun"
    
    REM Call the function
    echo %@Single[1]
    
    REM Define a function on multiple lines
    function Multi=`%@execstr[gosub Multi %$]`
    
    REM Call the function
    echo %@Multi[1]
    
    REM Show how to deal with Ctrl-C in a single-line function
    set return=Single was cancelled
    set return=%@Single[1]
    echo %return
    
    
    goto end
    
    :Multi [a]
    pause Multi: Press Ctrl-C then do (N)ot cancel batch job... 1>2
    echo Multi returns %a
    return
    
    
    :end
    echo Script ended
    unfunction Single
    unfunction Multi
    
    CancelFunction.fun

    Code:
    : a multi-line function defined on a single line
    Single=%@execstr[^
    pause Single:Press Ctrl-C then do (N)ot cancel batch job... 1>2 &^
    echo Single returns %1^
    ]
    
     
    #1

Share This Page