Function ErrorBlock() Foundation

Defines a code block to execute if a runtime error occurs.

Syntax
ErrorBlock( [<bErrorHandler>] ) --> bLastErrorHandler
Parameters
<bErrorHandler>
<bErrorHandler> is a code block which is evaluated when a runtime error occurs. An error object is generated by the system and is passed to this block. In order to receive the error object and be able to determine information about the runtime error, at least one parameter must be defined for <bErrorHandler>.
Return

When <bErrorHandler> is not specified, the function ErrorBlock() returns the current code block which would be executed if a runtime error occurred. If a new code block is specified, the old one is returned and the new one is set in its place for subsequent error handling.

Description

The function ErrorBlock() is a very efficient function for the treatment of runtime errors. It is frequently used with the control structure BEGIN SEQUENCE..END. Using ErrorBlock(), a code block is specified which calls an error handling routine. Individual error handling routines can be defined in a program to make the program independent of the default error routines in Xbase++. The default routine is part of the runtime library of Xbase++ (see the file ERRORSYS.PRG). If a runtime error occurs, the default handler displays information about the kind of error, sets ErrorLevel() to the value 1 and ends the program with QUIT.

If it is desireable to use a different routine for default error handling, a different ErrorSys() function should be written. This function should call ErrorBlock() to install a code block that calls the desired default error handler. Since ErrorSys() is automatically called on application startup, this method insures that the appropriate code block is installed prior to the start of the actual application.

The code block should receive at least one parameter. A system generated error object containing information about the runtime error that occurred will be passed as this parameter. Common examples for an error code block are:

{| oError |  Break(oError) } 
{| oError |  MyErrorHandler(oError) } 

The code block calls a function and passes the error object on to it. Instead of a single function, the code block can contain a list of expressions but this is rarely as useful.

The return value of the code block (or of the error function) determines further handling of the runtime error. When a failed operation can be repeated, it is retried if the return value is .T. (true). If the return value is .F. (false) the program continues without retrying the failed operation.

Examples
ErrorBlock()
// In the example an error code block is defined to call 
// an error handling routine in which information about 
// the error is displayed on the screen. The program 
// has several expressions which create runtime errors, 
// but is designed to run to completion. The screen 
// output created by the program is shown at the end 
// of the example. 

PROCEDURE Main 
   LOCAL bSaveError, cString 

   bSaveError := ErrorBlock( {|oError| MyErrorHandler(oError) } ) 

   ? 'cString := "Xbase++"' 
      cString := "Xbase++" 

   ? "IF cString > 0" 
      IF cString > 0                 // incorrect data type 
         ? "   cString is numeric" 
      ENDIF 

   ? "USE xyz : " 
      USE xyz                        // file does not exist 

   ? "Left( cString, NIL ) : " 
   ?  Left( cString, NIL )           // incorrect function argument 

   ? "cString[1] : " 
   ?  cString[1]                     // incorrect data type 

   ErrorBlock( bSaveError )          // restore previous 
                                     // error code block 
RETURN 

FUNCTION MyErrorHandler( oError )    // error routine 
   LOCAL lReturn := .F. 

   IF oError:tries < 3               // maximum of 2 tries 

      ? "oError:description", oError:description 
      ? "oError:tries", oError:tries 

      DO CASE 
         CASE oError:canDefault 
              lReturn := .T. 
         CASE oError:canRetry 
              lReturn := .T. 
         CASE oError:canSubstitute 
              lReturn := .T. 
      ENDCASE 
   ENDIF 

RETURN lReturn 

** Screen display for the example program 
// cString := "Xbase++" 
// IF cString > 0 
// oError:description Parameter has incorrect type 
// oError:tries          0 
//    cString is numeric 
// USE xyz : 
// oError:description  File cannot be opened 
// oError:tries          1 
// oError:description  File cannot be opened 
// oError:tries          2 
// Left( cString, NIL ) : 
// oError:description Parameter has incorrect type 
// oError:tries          0 
// .T. 
// cString[1] : 
// oError:description Parameter has incorrect type 
// oError:tries          0 
// .T. 

Write error information into an error log

// The example shows an error routine which writes an 
// extensive log about the runtime errors into a file 
// and then ends the program. 

PROCEDURE Main 
   LOCAL bSaveError, cString 

   bSaveError := ErrorBlock( {|oError| ErrorLog(oError) } ) 

   cString := "Xbase++" 

   IF cString > 0                    // incorrect data type 
      ? "   cString is numeric" 
   ENDIF 

   ErrorBlock( bSaveError )          // restore previous 
                                     // error code block 
RETURN 

FUNCTION ErrorLog( oError ) 
   LOCAL i:=0 
   SET CONSOLE OFF 
   SET PRINTER TO LOG.ERR ADDITIVE 
   SET PRINTER ON 

   DO WHILE ! Empty( ProcName(++i) )  // write call stack 
      ? ProcName(i) + "(" + LTrim(Str(ProcLine(i))) +")" 
   ENDDO 

   IF Valtype( oError ) =="O"         // display error object 
      ?                               // information 
      ? "e:args         :" 
      IF Valtype( oError:Args )=="A" 
         AEval( oError:Args, ; 
                {|x| QOut("->","VALTYPE:",Valtype(x), ; 
                             ", value:",x ) } ) 
      ENDIF 
      ? "e:canDefault   :" , oError:canDefault 
      ? "e:canRetry     :" , oError:canRetry 
      ? "e:canSubstitute:" , oError:canSubstitute 
      ? "e:cargo        :" , oError:cargo 
      ? "e:description  :" , oError:description 
      ? "e:filename     :" , oError:filename 
      ? "e:genCode      :" , oError:genCode 
      ? "e:operation    :" , oError:operation 
      ? "e:osCode       :" , oError:osCode 
      ? "e:severity     :" , oError:severity 
      ? "e:subCode      :" , oError:subCode 
      ? "e:subSystem    :" , oError:subSystem 
      ? "e:thread       :" , oError:thread 
      ? "e:tries        :" , oError:tries 
   ENDIF 

   SET CONSOLE ON 
   SET PRINTER TO 
   SET PRINTER OFF 

   ErrorLevel(1) 
   CLS 
   ? "Error log written to LOG.ERR",Chr(7) 
   QUIT 
RETURN .F. 
ErrorBlock() and BEGIN SEQUENCE..END
// Refer to the function Break() for a detailed example as to 
// how ErrorBlock() can be used together with the control 
// structure BEGIN SEQUENCE..END. 
Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.