Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

Guide to the DEC Text Processing Utility


Previous Contents Index

4.9.4.14 Error Handling

A block of code starting with ON_ERROR and ending with ENDON_ERROR defines the actions that are to be taken when a procedure fails to execute successfully. Such a block of code is called an error handler. An error handler is an optional part of a DECTPU procedure or program. An error handler traps WARNING and ERROR status values. (See SET (INFORMATIONAL) and SET (SUCCESS) in the DEC Text Processing Utility Reference Manual for information on handling informational and success status values.)

It is good programming practice to put an error handler in all but the simplest procedures. However, if you omit the error handler, DECTPU's default error handling behavior is as follows:

In a procedure, the error handler must be placed at the beginning of a procedure---after the procedure parameter list, the LOCAL or CONSTANT declarations, if present, and before the body of the procedure. In a program, the ON_ERROR language statements must be placed after all the global declarations (PROCEDURE, CONSTANT, and VARIABLE) and before any executable statements. Error statements can contain any DECTPU language statements except other ON_ERROR statements.

There are three DECTPU lexical elements that are useful in an error handler: ERROR, ERROR_LINE, and ERROR_TEXT.

ERROR returns a keyword for the error or warning. The DEC Text Processing Utility Reference Manual includes information on the possible error and warning keywords that each built-in procedure can return.

ERROR_LINE returns the line number at which the error or warning occurs. If a procedure was compiled from a buffer or range, ERROR_LINE returns the line number within the buffer. (This may be different from the line number within the procedure.) If the procedure was compiled from a string, ERROR_LINE returns 1.

ERROR_TEXT returns the text of the error or warning, exactly as DECTPU would display it in the message buffer, with all parameters filled in.

After the execution of an error statement, you can choose where to resume execution of a program. The options are the following:

If you do not specify ABORT or RETURN, the default is to continue executing the program from the point at which the error occurred.

DECTPU provides two forms of error handler: procedural and case style.

4.9.4.15 Procedural Error Handlers

If a WARNING status is trapped by an ON_ERROR statement, the warning message is suppressed. However, if an ERROR status is trapped, the message is displayed. With the ON_ERROR trap, you can do additional error handling after the DECTPU message is displayed.

Syntax

ON_ERROR 
   statement_1; 
   statement_2; 
     . 
     . 
     . 
   statement_n; 
ENDON_ERROR; 

Example 4-10 shows error statements at the beginning of a procedure. These statements return control to the caller if the input on the command line of an interface is not correct. Any warning or error status returned by a statement in the body of the procedure causes the error statements to be executed.

Example 4-10 Procedure That Uses the ON_ERROR Statement

! 
! Gold 7 emulation (command line processing) 
! 
PROCEDURE command_line 
 
LOCAL 
   line_read, X; 
 
ON_ERROR 
    MESSAGE ("Unrecognized command: " + line_read); 
    RETURN; 
ENDON_ERROR; 
! 
! Get the command(s) to execute 
! 
line_read := READ_LINE ("DECTPU Statement: "); ! get line from user 
! 
! compile them 
 
! 
IF line_read <> "" 
THEN  
    X := COMPILE (line_read); 
ELSE  
    RETURN 
ENDIF; 
! 
! execute 
! 
IF X <> 0 
THEN 
    EXECUTE (X); 
ENDIF; 
 
ENDPROCEDURE; 

The effects of a procedural error handler are as follows:

If an error or warning is generated during execution of a procedural error handler, DECTPU behaves as follows:

4.9.4.16 Case-Style Error Handlers

Case-style error handlers provide a number of advantages over procedural error handlers. With case-style error handlers, you can do the following:

Syntax

ON_ERROR [condition_1]: statement_1;... [condition_2]: statement_2;... . . .
[condition_n]: statement_n; ENDON_ERROR;

You can use the [OTHERWISE] selector alone in an error handler as a shortcut. For example, the following two error handlers have the same effect:


! This error handler uses [OTHERWISE] alone as a shortcut. 
 
ON_ERROR 
[OTHERWISE] : ; 
ENDON_ERROR 
 
! This error handler has the same effect as using 
! [OTHERWISE] alone. 
 
ON_ERROR 
[OTHERWISE] : 
   LEARN_ABORT; 
   RETURN (FALSE); 
ENDON_ERROR; 

Example 4-11 from the EVE editor shows a procedure with a case-style error handler.

Example 4-11 Procedure with a Case-Style Error Handler

PROCEDURE eve$learn_abort 
 
ON_ERROR 
    [TPU$_CONTROLC]: 
       MESSAGE (ERROR_TEXT); 
       RETURN (LEARN_ABORT); 
ENDON_ERROR; 
 
IF LEARN_ABORT 
THEN 
    eve$message (EVE$_LEARNABORT); 
    RETURN (TRUE); 
ELSE 
    RETURN (FALSE); 
ENDIF; 
 
ENDPROCEDURE; 

If a program or procedure has a case-style error handler, DECTPU handles errors and warnings as follows:

If an error or warning is generated during execution of a case-style error handler, DECTPU behaves as follows:

In a procedure with a case-style error handler, an ABORT statement produces the same effect as the sequence Ctrl/C, with one exception: an ABORT statement in the TPU$_CONTROLC clause of a case-style error handler does not reinvoke the TPU$_CONTROLC clause, as is the case when Ctrl/C is pressed while TPU$_CONTROLC is executing. Instead, an ABORT statement causes DECTPU to exit from the error handler and look for a TPU$_CONTROLC selector in the procedures or program (if any) in which the current procedure is nested. If DECTPU does not find a TPU$_CONTROLC selector in the containing procedures or program, DECTPU places the message associated with TPU$_CONTROLC in the message buffer.

4.9.4.17 Ctrl/C Handling

The ability to trap a Ctrl/C in your DECTPU program is both powerful and dangerous. When you press Ctrl/C, you usually want the application that is running to prompt for a new command. The ability to trap the Ctrl/C is intended to allow a procedure to clean up and exit gracefully.

4.9.4.18 RETURN Statement

The RETURN statement causes a return to the procedure that called the current procedure or program. The return is to the statement that follows the statement that called the current procedure or program. You can specify an expression after the RETURN statement and the value of this expression is passed to the calling procedure.

Syntax

RETURN expression; 

The expression is optional; if it is missing, DECTPU supplies a 0. Also, the RETURN statement itself is optional. That is, if DECTPU reaches the endprocedure of a procedure before encountering a RETURN statement, it will return 0.

Example 4-12 shows a sample procedure in which a value is returned to the calling procedure.

Example 4-12 Procedure That Returns a Value

PROCEDURE user_get_shift_key 
 
LOCAL key_to_shift;  ! Keyword for key pressed after shift key 
 
SET (SHIFT_KEY, LAST_KEY); 
key_to_shift := KEY_NAME (READ_KEY, SHIFT_KEY); 
RETURN key_to_shift; 
 
ENDPROCEDURE; 

In addition to using RETURN to pass a value, you can use a 1 (true) or a 0 (false) with the RETURN statement to indicate the status of a procedure. Example 4-13 shows this usage of the RETURN statement.

Example 4-13 Procedure That Returns a Status

PROCEDURE user_at_end_of_line 
 
! This procedure returns a 1 (true) if user is at the end of a 
! line, or a 0 (false) if the current character is not at the 
! end of a line 
 
ON_ERROR 
! Suppress warning message 
   RETURN (1); 
ENDON_ERROR; 
 
IF CURRENT_OFFSET = LENGTH (CURRENT_LINE) 
THEN 
    RETURN (1); 
ELSE 
    RETURN (0); 
ENDIF; 
 
ENDPROCEDURE; 

You can use the RETURN statement in the ON_ERROR section of a procedure to specify a return to the calling procedure if an error occurs in the current procedure. Example 4-14 uses the RETURN statement in an ON_ERROR section.

Example 4-14 Using RETURN in an ON_ERROR Section

! Attach to the parent process.  Used when EVE is spawned 
! from DCL and run in a subprocess ("kept DECTPU"). The 
! ATTACH command can be used for more flexible process control. 
 
PROCEDURE eve_attach 
 
ON_ERROR 
    IF ERROR = TPU$_NOPARENT 
    THEN  
        MESSAGE ("Not running DECTPU in a subprocess"); 
        RETURN; 
    ENDIF; 
ENDON_ERROR; 
 
ATTACH; 
 
ENDPROCEDURE; 

4.9.4.19 ABORT Statement

The ABORT statement stops any executing procedures and causes DECTPU to wait for the next keystroke. ABORT is commonly used in error handlers. For additional information on using ABORT in error handlers, see Section 4.9.4.14.

Syntax

ABORT 

Example 4-15 shows a simple error handler that contains an ABORT statement.

Example 4-15 Simple Error Handler

ON_ERROR 
   MESSAGE ("Aborting procedure because of error."); 
   ABORT; 
ENDON_ERROR; 

4.9.5 Miscellaneous Declarations

This section describes the following DECTPU language declarations:

4.9.5.1 EQUIVALENCE

With the EQUIVALENCE declaration, you can create synonyms. Equivalences work only when both real_name and synonym_name are defined at the same time. You cannot save a section file that contains real_name and then later use that section file to extend code that uses an EQUIVALENCE of the saved name. To avoid problems, include all EQUIVALENCE declarations in the same compilation unit where real_name is defined.

The equivalences can reside in different compilation units, but you must use all of the compilation units when building the section file from scratch. If you use a base section file that you extend interactively, you cannot make equivalences to procedures or variables defined in the base section file.

Syntax

EQUIVALENCE synonym_name1 = real_name1, synonym_name2 = real_name2,
...;

Elements of the EQUIVALENCE Statement

real_name

A user-defined global variable or procedure name. If real_name is undefined, DECTPU defines it as an ambiguous name. This ambiguous name can become a variable or procedure later.

synonym_name

A name to be defined as a synonym for the real_name.

4.9.5.2 LOCAL

With the LOCAL declaration, you can identify certain variables as local variables rather than global variables. All variables are considered to be global variables unless you explicitly use the LOCAL declaration to identify them as local variables. The LOCAL declaration in a procedure is optional. It must be specified after the PROCEDURE statement and before any ON_ERROR statement. LOCAL declarations and CONSTANT declarations can be intermixed.

The maximum number of local variables you can declare in a procedure is 255. Local variables are initialized to 0.

Syntax

LOCAL 
     variable-name [[,...]]; 

Local variables may also be declared in unbound code. Such variables are accessible only within that unbound code.

Unbound code can occur in the following places:

The following example shows a complete compilation unit. This unit contains a module named mmm that, in turn, contains a procedure bat and some initialization code mmm_module_init, a procedure bar defined outside the module, and some unbound code at the end of the file. In each of these sections of code, a local variable X is defined. The variable is displayed using the MESSAGE built-in procedure.


MODULE mmm IDENT "mmm" 
 
PROCEDURE bat;      ! Declare procedure "bat" in module "mmm" 
 
LOCAL 
    X;  ! "X" is local to procedure "bat" 
 
    X := "Within procedure bat, within module mmm"; 
MESSAGE (X); 
 
ENDPROCEDURE; ! End procedure "bat" 
 
LOCAL 
        X;                      ! "X" is local to 
                                ! procedure "mmm_module_init" 
 
X := "Starting or ending the module init code"; 
MESSAGE (X); 
bat; 
MESSAGE (X); 
 
ENDMODULE;              ! End module "mmm" 
 
PROCEDURE bar           ! Declare procedure "bar" 
 
LOCAL 
        X;                      ! "X" is local to procedure "bar" 
 
X := "In procedure bar, which is outside all modules"; 
MESSAGE (X); 
 
ENDPROCEDURE;           ! End procedure "bar" 
 
LOCAL 
        X;                      ! "X" is local to the unbound code... 
 
X := "Starting or ending the unbound, non-init code"; 
MESSAGE (X); 
mmm_module_init; 
bat; 
bar; 
MESSAGE (X); 
EXIT; 
 

If this code is included in TEMP.TPU, the following command demonstrates the scope of the various local variables:


$ 
EDIT/TPU/NOSECTION/NOINITIALIZE/NODISPLAY/COMMAND=temp.tpu
Starting or ending the unbound, non-init code
Starting or ending the module init code
Within procedure bat, within module mmm
Starting or ending the module init code
Within procedure bat, within module mmm
In procedure bar, which is outside all modules
Starting or ending the unbound, non-init code


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
6018PRO_009.HTML