HP OpenVMS Systems Documentation

Content starts here

HP BASIC for OpenVMS
User Manual


Previous Contents Index

15.2.5.3 Determining Where the Error Occurred (ERN$)

You use the ERN$ function to return the name of the program unit in which the error was detected. ERN$ returns the name of a main program, SUB, FUNCTION, or PICTURE subprogram, or DEF function. If the PROGRAM statement is used with a user-supplied identifier, the ERN$ value is the specified identifier for the main program. The results of ERN$ are undefined until the program generates an error.

In the following example, control passes to the main program for error handling if the error occurs in the module SUBARC:


HANDLER locat_ern
  IF ERN$ = "SUBARC"
     THEN PRINT "ERROR IS ";ERR
          PRINT "RETURNING TO MAIN PROGRAM FOR ERROR HANDLING"
          EXIT HANDLER
     ELSE  PRINT "PROGRAM MODULE GENERATING ERROR IS ";ERN$
  END IF
END HANDLER

Note that ERN$ is invalid when an error occurs in a subprogram compiled with the /NOSETUP qualifier.

15.2.5.4 Determining the Error Message Text (ERT$)

You use the ERT$ function to access the message text associated with a specified error number. Use of the ERT$ function is not limited to the scope of the error handler; you can access ERT$ at any time. The following detached handler tests whether the error occurred in a DEF module named TSLFE, and, if so, prints the text of the signaled error and resumes execution:


HANDLER catch_it
  IF ERN$ = "TSLFE"
        THEN PRINT ERT$(ERR)
        CONTINUE
        ELSE EXIT HANDLER
  END IF
END HANDLER

15.2.5.5 Determining OpenVMS Error Information

HP BASIC provides a built-in function, VMSSTATUS, that returns the originally signaled error before it is translated to a BASIC error. For example, for the BASIC error "End of file on device" (ERR=11), the VMSSTATUS function returns "RMS$_EOF" (RMS end of file). This function is useful when the error is NOTBASIC (ERR=194).

When there is no error pending, VMSSTATUS is undefined. The value returned by this function is the actual signaled error value. If non-BASIC errors are being handled, the VMSSTATUS function might be the only way to find out which error caused the exception.

The following example shows a program that performs file I/O. The first WHEN ERROR block traps any errors that occur while the program is opening the file or requesting user input. The detached handler for this block checks the value of VMSSTATUS to determine the exception that occurred. The inner error handler handles two special errors, BAS$K_RECNOTFOU and BAS$K_RECBUCLOC, separately. If the error signaled does not correspond to one of these, the inner error handler passes control to the outer handler with the EXIT HANDLER statement. The outer handler sets the program status to VMSSTATUS. When the program exits, the operating system displays any status that is of warning severity or greater.


PROGRAM Tester

 OPTION HANDLE = ERROR
 EXTERNAL LONG CONSTANT BAS$K_RECNOTFOU, BAS$K_RECBUCLOC
 DECLARE LONG Final_status
 MAP (Rec_buffer)                           &
      STRING Rec_key        = 5,            &
      STRING Rest_of_record = 20
 Final_status = 1
 WHEN ERROR USE Global_handler
      OPEN "My_database" FOR INPUT AS FILE #1  &
           ,INDEXED FIXED                      &
           ,ACCESS READ                        &
           ,MAP Rec_buffer                     &
           ,PRIMARY Rec_key
 Get_key:
     INPUT "Record to retrieve"; Rec_key
     WHEN ERROR IN
          GET #1%, KEY #0 EQ Rec_key
          PRINT Rest_of_record
     USE
          SELECT ERR
              CASE = BAS$K_RECNOTFOU
                     PRINT "Record not found"
                     CONTINUE Get_key
              CASE = BAS$K_RECBUCLOC
                     SLEEP 2%
                     RETRY
              CASE ELSE
                   EXIT HANDLER
          END SELECT
     END WHEN
    END WHEN
    HANDLER Global_handler
            Final_status = VMSSTATUS
    END HANDLER

END PROGRAM Final_status

15.2.5.6 Determining RMS Error Information

The RMSSTATUS function lets you determine which RMS error caused a resulting HP BASIC error. You must specify an open channel as the first parameter to RMSSTATUS. If this channel is not open, the error "I/O channel not open" (ERR=9) is signaled. The second parameter to the function lets you specify either STATUS or VALUE; this parameter is optional. If you do not specify the second parameter, RMSSTATUS returns the STATUS value by default. STATUS represents the RMS STS field and VALUE corresponds to the RMS STV field.

The following example shows an error handler that prints both the status and the value of any RMS error:


WHEN ERROR IN
     OPEN "file.txt" FOR OUTPUT AS FILE 1%
     PRINT #1%, TIME$(0%)
USE
     !Error 12 is fatal system I/O failure
     IF ERR = 12
        THEN
        PRINT "An unexpected RMS error has occurred:"
        PRINT "Status = "; RMSSTATUS(1%)
        PRINT "Value = "; RMSSTATUS(1%, VALUE)
        EXIT HANDLER
     END IF
END WHEN

CLOSE #1%
GOTO done

done:
    END

If you want to find an RMS status without knowing which particular channel to check, you can use VMSSTATUS to get the STATUS value (STS) if an error has occurred.

15.2.6 Ctrl/C Trapping

Error handling procedures are commonly used to trap user Ctrl/C responses. With Ctrl/C trapping enabled, control is transferred to an error handler if a user presses Ctrl/C during program execution. You enable Ctrl/C trapping in your program by invoking the built-in CTRLC function. For example:


Y% = CTRLC

After you invoke the CTRLC function, a Ctrl/C entered at the terminal transfers control to the error handler. Once the Ctrl/C is trapped, you can include routines to interact with the program, as shown in the following example:


WHEN ERROR IN
  Y% = CTRLC
  OPEN 'FIL_DAT' FOR INPUT AS FILE #1%
  INPUT "HOW MANY RECORDS"; Rec_read%
  FOR I% = 1% TO Rec_read%
    GET #1%
    PRINT Name$, Address$, Emp_code%
    PRINT
  NEXT I%

USE
  !Trap ^C
  IF (ERR = 28%)
     THEN PRINT "CURRENT RECORD IS "; I%
     ELSE EXIT HANDLER
  END IF
  CONTINUE Clean_up
END WHEN
   .
   .
   .
Clean_up:
  CLOSE #1%
  PRINT "END OF PROCESSING"
END

Output


SMITH, DEXTER 231 COLUMBUS ST             09341

TRAVIS, JOHN  PO BOX 80                   64119

^C

THE CURRENT RECORD IS 3

END PROCESSING

Note that the error condition is still pending until the error handler executes the CONTINUE statement. Therefore, if you press Ctrl/C a second time while the error handler is executing, control returns to the HP BASIC error handler, which terminates the program.

To disable Ctrl/C trapping, use the RCTRLC function. The RCTRLC function disables only Ctrl/C trapping, not the Ctrl/C interrupts themselves.

15.2.7 Handling Errors in Multiple-Unit Programs

You can use WHEN ERROR constructs anywhere in your main program or program modules. Procedure and function invocations, such as invocations of DEF and DEF* functions and SUB, FUNCTION, and PICTURE subroutines, as well as non-BASIC programs, are valid within protected regions. GOTO and GOSUB statements are valid within handlers provided that the target is within the handler, an outer handler, or an unprotected region. Note, however, that a detached handler cannot appear within DEF or DEF* functions without the associated protected region.

When an error occurs within nested protected regions, HP BASIC maintains the same priorities for handler use; control always passes to the handler associated with the innermost protected region in which the error occurred. When an exception occurs, all handlers for any outer WHEN ERROR blocks are processed before the program reverts to default error handling. Outer handlers are invoked when an inner handler executes an EXIT HANDLER statement. When there are no more outer handlers, and the outermost handler executes an EXIT HANDLER statement, program control reverts to the handler associated with the calling routine. For example:


SUB LIST(A$)
  WHEN ERROR USE sub_handler

      OPEN A$ FOR INPUT AS FILE #12%
  Get_data:
      LINPUT #12%, B$
      PRINT B$
      GOTO Get_data
  END WHEN
  HANDLER sub_handler
    !Trap end of file
    IF ERR <> 11%
        THEN EXIT HANDLER
    END IF
END HANDLER
CLose_up:
   CLOSE #12%
END SUB

You can call a subprogram while an error is pending; however, if you do, the subprogram cannot resignal an error back to the calling program. If the subprogram tries to resignal an error, HP BASIC signals "Improper error handling" and program execution terminates.

The following rules apply to error handling in function definitions:

  • DEF and DEF* function definitions cannot appear within a protected region. However, protected regions can be contained within the function definitions.
  • To trap errors while a DEF function is active, include protected regions inside the DEF function. If you do this, the associated handler remains in effect until your program leaves the protected region, or the DEF function.

For example:


     WHEN ERROR IN
     .
     .
     .
     Invoke_def:
       A% = FNIN_PUT%("PROMPT")

     USE
        PRINT "ERROR"; ERT$(ERR%);
        IF ERN$ = "FNIN_PUT"
           THEN PRINT "IN FUNCTION"
                CONTINUE
           ELSE PRINT "IN MAIN"
                CONTINUE Invoke_def
        END IF
     END WHEN

     Main_code:
     DEF FNIN_PUT%(P$)
      WHEN ERROR IN
        PRINT P$
        INPUT LINE_IN$
        FNIN_PUT% = INTEGER(LINE_IN$)
     USE
         IF ERR = 50
            THEN RETRY
            ELSE EXIT HANDLER
         END IF
     END WHEN
     END DEF

Note

If you invoke a GOSUB statement or a DEF* function from within a protected region and the invoked procedure is outside of any protected region, all pending errors are handled by the WHEN ERROR handler unless a previously executed ON ERROR statement specifies otherwise.

15.2.8 Forcing Errors

The CAUSE ERROR statement allows a program to artificially generate an error when the program would not otherwise do so. You can force any HP BASIC run-time error. You must specify the number of the error the compiler should force; the error numbers are listed in Appendix B. The following statement forces an end-of-file error (ERR=11) to occur:


CAUSE ERROR 11%

You can use this feature to debug an error handler during program development, as shown in the following example:


WHEN ERROR IN
   .
   .
   .
 CAUSE ERROR 11%
   .
   .
   .
USE
   SELECT ERR
        CASE = 11%
             PRINT "Trapped an end of file on device"
             CONTINUE
        CASE ELSE
             EXIT HANDLER
END WHEN

15.3 Using the ON ERROR Statements

HP BASIC supports ON ERROR statements as an alternative to WHEN blocks primarily for compatibility with existing programs. WHEN ERROR blocks are similar to declarative statements in that they do not depend on run-time flow of control. The ON ERROR statements, however, affect error handling only if the statements execute at run time. For example, if a GOTO statement precedes an ON ERROR statement, the ON ERROR statement will not have any effect because it does not execute.

WHEN ERROR blocks let you handle errors that occur in a specific range of statements. ON ERROR statements let you specify a general error handler that is in effect until you specify another ON ERROR statement or until you pass control to the HP BASIC error handler.

Note

For all current program development, it is recommended that you use WHEN ERROR constructs for user-written error handlers. Mixing WHEN ERROR constructs and ON ERROR statements within the same program is not recommended. The ON ERROR statements are supported for compatibility with other versions of BASIC available from HP. It is important to note that all of these statements are illegal within a protected region, or an attached or detached handler.

The ON ERROR statements are documented in the HP BASIC for OpenVMS Reference Manual. This section briefly describes the main features of the ON ERROR statements.

The ON ERROR statements can be used to transfer control to a labeled block of error handling code. If you have executed an ON ERROR statement and an error occurs, the ON ERROR statement immediately transfers control to the label or line number that starts the error handling code. Otherwise, the ON ERROR statement specifies the branch to be taken in the event of an error.

There are three forms of the ON ERROR statement:

  • ON ERROR GOTO 0
    The ON ERROR GOTO 0 statement reverts control to HP BASIC default error handling in one of two ways:
    • If an error is pending, execution of the ON ERROR GOTO 0 statement returns control to the HP BASIC error handler immediately.
    • If no error is pending, an ON ERROR GOTO 0 statement disables your current error handler. The HP BASIC error handler handles all subsequent errors until another ON ERROR statement is executed, unless an error occurs in a WHEN ERROR protected region.
  • ON ERROR GOTO target
    The ON ERROR GOTO target statement reverts control to the target when subsequent errors occur that are not handled by WHEN block handlers.

  • ON ERROR GO BACK
    The ON ERROR GO BACK statement transfers control to the calling program's error handler if an error occurs in the subprogram or DEF function. If you use ON ERROR GO BACK in a PROGRAM unit (outside of a DEF function) and no other outer protected region exists, it is equivalent to ON ERROR GOTO 0 and HP BASIC default error handling is in effect. With ON ERROR GO BACK, if an error occurs in the execution of a function or subprogram, the error is passed to either the error handler of the surrounding program module (in the case of a DEF function definition) or to the error handler of the calling program (in the case of a separately compiled subprogram).
    An error handler in the DEF function does not permanently override an error handler in the main program. HP BASIC saves the error handler in the main program when you transfer into a DEF, and restores it when you return.

The ON ERROR GOTO statement is usually placed before any other executable statements. The following example clears end-of-file errors and passes all other errors back to the HP BASIC default error handling procedures:


5 ON ERROR GOTO Error_handler
   .
   .
   .
Error_handler:
    !Trap end of file on device
    IF ERR = 11
        THEN
                RESUME 1000
        ELSE
                ON ERROR GO BACK
    END IF

The ON ERROR GOTO statement remains in effect after your program successfully handles an error. When the system signals another error, control once again transfers to the specified error handler.

Every ON ERROR error handler must end with one of the following statements:

  • RESUME [target]
  • ON ERROR GOTO 0
  • ON ERROR GO BACK

If none of these statements is present, the HP BASIC error handler aborts your program with the fatal error "Error trap needs RESUME" as soon as an END, END SUB, END DEF, END FUNCTION, END PROGRAM, or END PICTURE statement is encountered. The RESUME statement, like the RETRY and CONTINUE statements, clears the error condition.

You can resume execution at any line number or label that is in the same module as the RESUME statement, unless that line or target is inside a DEF function, a WHEN ERROR protected region, or a handler. In general, RESUME without a target transfers control to the beginning of the program block where the error occurred.

  • If you resume execution at a multistatement line, execution begins at the first statement after the line number or label---not necessarily at the statement that generated the error.
  • If an entire loop block is associated with a single line number or label and an error occurs within the loop, RESUME with no target transfers control to the statement immediately after the FOR, WHILE, or UNTIL statement, not to the line number or label.

For more information about the RESUME statement, see the HP BASIC for OpenVMS Reference Manual.

Using both ON ERROR statements and WHEN ERROR constructs in the same program is not recommended. However, when this is the case, the order of handler priorities is as follows:

  1. Control passes to the handler associated with the innermost WHEN ERROR block.
  2. If protected regions are nested, the pending error is handled by the handler associated with the next outer WHEN ERROR block.
  3. When no outer protected regions can handle the error, and if an ON ERROR statement is in effect, control transfers to the target of the next outer ON ERROR statement (if one is present).
  4. If no outer handler is available or can handle the error, the error is passed to HP BASIC default error handling. Default error handling is equivalent to ON ERROR GOTO 0 for main procedures, and ON ERROR GO BACK for SUBs, FUNCTIONs, and DEFs.

For information about specific run-time errors, see Appendix B.


Previous Next Contents Index