Function ErrorBlock() Foundation
Defines a code block to execute if a runtime error occurs.
ErrorBlock( [<bErrorHandler>] ) --> bLastErrorHandler
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.
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.
// 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.
// 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.
// Refer to the function Break() for a detailed example as to
// how ErrorBlock() can be used together with the control
// structure BEGIN SEQUENCE..END.
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.