home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
- *
- * Name: EXAMPLE2.prg
- * Description: ErrorBlock() Demo Program
- * Author: Philip H. Schwartz
- * Audience: Nantucket DEVCON '90
- * Written: June 5, 1990
- * Compiler: Clipper 5.0 V7.7 BETA
- * Comp Option: /N
- * Linker: RTLink Version 1.3 (Clipper)
- * Library: clipper, extend
- * Obj Module: MYERR.obj
- * Link input: rtlink fi example2,myerr out example2 li clipper,extend
- * Headers: STD.ch
- * Copyright: (c) 1990 Philip H. Schwartz
- * Rights: All Commercial & Publishing Rights Reserved
- *
- *********************************************************************/
-
- /* Definitions for MEMORY() function */
- #define MEM_TOTAL 0
- #define MEM_BLOCK 1
- #define MEM_RUN 2
-
- PROCEDURE example2
- LOCAL bErrBlocks,nErrHandler,cErrBlocks,cEnvBlock,cSaveScreen
- PUBLIC bErrSave
-
- cErrBlocks:={"BREAK to RECOVER statement",;
- "You flat out of luck",;
- "RUN debugger.exe",;
- "Use SET ERRORBLOCK= in ENV",;
- "LOCAL handler & pass to Default",;
- "Default Error Block"}
-
- bErrBlocks:={{|e| break(e)},;
- {|e| qout("You flat out of luck."), break(e)},;
- {|e| run(e),.f.}}
-
- CLS
- bErrSave:=ERRORBLOCK() // save the Default Error Block
-
- /* Ask the user to select a code block to post */
- nErrHandler=6
- @ 1,0 to 8,33 DOUBLE
- nErrHandler=ACHOICE(2,1,7,32,cErrBlocks)
-
- /* EXIT if nothing selected */
- IF nErrHandler=0
- RETURN
- ENDIF
-
- DO CASE
- /* Install one of the compiled code blocks */
- CASE nErrHandler>=1 .AND. nErrHandler<=3
- ERRORBLOCK(bErrBlocks[nErrHandler])
-
- /* Check to see if a code block was entered in ASCII via the
- SET ERRORBLOCK feature of DOS. If so, compile it with
- the & operator and install it. NOTE: We must strip the quote
- delimiters from the code block before we compile it or we
- will get an error. */
- CASE nErrHandler=4 .AND. !EMPTY(cEnvBlock:=GETE("ERRORBLOCK"))
- cEnvBlock=SUBSTR(cEnvBlock,2,LEN(cEnvBlock)-2)
- ERRORBLOCK(&cEnvBlock)
-
- /* This example shows how you can install a Local Error Handler to
- trap selected situations. You can then pass on the
- error objects to the default Error Handler for further processing. */
- CASE nErrHandler=5
- ERRORBLOCK({|e| LocErr(e)})
-
- /* Otherwise, we assume Default Error Handler */
- OTHERWISE
- ERRORBLOCK(bErrSave)
- ENDCASE
-
- /* Display options in effect at the top of the screen */
- CLS
- @ 1,0 SAY REPLICATE("-",80)
- @ 2,0 SAY "Current Error Block ===> "+cErrBlocks[nErrHandler]
- IF nErrHandler=4
- @ 3,0 SAY "SET ERRORBLOCK="+IIF(!EMPTY(cEnvBlock),cEnvBlock,;
- "EMPTY --- Default Error Block Substituted")
- ELSE
- @ 3,0 SAY "Using Code Block created at Compile-time"
- ENDIF
- @ 4,0 SAY REPLICATE("-",80)
-
- /* This code support demonstration of the BEGIN/RECOVER/BREAK
- feature of Clipper 5.0. We created a BREAK() UDF to issue
- a BREAK statement so that RECOVER can get control with the
- error object. */
- BEGIN SEQUENCE
- ? "DEBUG(MAIN)=> About to create an error."
- ? 1*unkn // Generate an error
-
- RECOVER e
- ? "DEBUG(MAIN)=> Now in RECOVER mode."
- ? 'DEBUG(MAIN)=> e:description() is "'+e:description()+'"'
- ? "DEBUG(MAIN)=> e:gencode() is "+ltrim(str(e:genCode()))
- // additional RECOVERY statements
- // would follow
- // this line.
-
- END SEQUENCE
- ? "DEBUG(MAIN)=> This line follows the END SEQUENCE."
- // rest of program would follow this line
-
- ERRORBLOCK(bErrSave) // Restore original error handler
- RETURN // RETURN to DOS
-
-
- /* This function shows how a local error handler can pass
- control to the default error block after taking stock of the
- situation. */
- STATIC FUNCTION locerr(e)
- ? "DEBUG(LOCERR)=> Error GenCode is "+LTRIM(STR(e:gencode()))
- ? 'DEBUG(LOCERR)=> Error Description is "'+e:description()+'"'
- ? "DEBUG(LOCERR)=> Now passing control to Default Error Block"
- RETURN(EVAL(bErrSave,e))
-
- /* Since a BREAK can't be issued directly from a code block,
- we create this UDF to issue a BREAK for us. Of course, we
- want the object error to pass on to the RECOVER statement so
- we include the (e) operand on the BREAK line. */
- STATIC FUNCTION break(e)
- ? "DEBUG(BREAK)=> Now in BREAK(e) routine."
- BREAK e
- RETURN NIL
-
- /* This routine allows us to RUN an external .EXE module directly
- from recovery mode. This is only meant to show the flexibility
- of the Error System. Obviously, the environment may be
- too damaged at this point to successfuly execute a program. */
- STATIC FUNCTION RUN(e)
- ? "DEBUG(RUN)=> Now in RUN(e) routine."
- ? "DEBUG(RUN)=> RUN MEMORY available is "+LTRIM(STR(MEMORY(MEM_RUN)))+'K'
- IF FILE('debugger.exe')
- ? "DEBUG(RUN)=> About to call DEBUGGER.EXE"
- cSaveScreen=SAVESCREEN(0,0,24,79)
- RUN debugger
- RESTSCREEN(0,0,24,79,cSaveScreen)
- ? "DEBUG(RUN)=> RETURNing from DEBUGGER.EXE"
- ELSE
- ? "DEBUG(RUN)=> Can't find DEBUGGER.EXE"
- ENDIF
- RETURN(EVAL(bErrSave,e))
- /*EOF*/