Welcome to the Southern African Autolisp Website.

Afra-lISP


You are Visitor Number since 10th September 1998


Error Trapping.

This was another area that caused me quite a bit of confusion
when I was first learning AutoLISP.
All AutoLISP routines should contain Error Trapping.
There is nothing worse than running a routine and finding out
that once it has run, or been cancelled, your system variables,
etc. have all changed and nothing works the same any more.

I am going to look at two types of Error Trapping here.
Firstly, an Error Trapping routine build into a function, and
secondly, a Global Error Trapping function.
But first, some background on the AutoCAD *error* function.

AutoLISP provides a method for dealing with user (or program errors).
It is one of the only AutoLISP functions that is user-definable.
This is the *error* function.

(*error* string)

It is executed as a function whenever an AutoLISP error condition exists.
If there is an error, AutoCAD passes one argument to *error*, which is
a string containing a description of the error.

The following function does the same thing that the AutoLISP standard
error handler does. Print error and the description.

	(defun *error* (errmsg)
	 (princ "error: ")
	 (princ errmsg)
	 (princ)
	)

Before designing an Error Trapping function there is a couple of things
to keep in mind.
First, the Error-Trap function must be called *error*. It also must have
an argument passing variable. Our variable is called errmsg.
You can call this variable anything you like. Now, you can put anything
you like in the body of this function. For example :

	(defun *error* (errmsg)
	 (princ "\nAn error has occurred in the programme. ")
	 (terpri)
	 (prompt errmsg)
	 (princ)
	)

To test this error trap, create a lisp file with the preceeding code and load
the file. Begin running any programme or command that you like. In the middle of
the programme hit ESC or Ctrl C. (AutoCAD thinks that this is an error.)
Control should be passed to the Error Trap.

It is important to note, and courteous, that you should never change a users
settings, including an existing Error Trap, without first saving it as a variable
and then replacing it at the end of the programme.
Remember, as well, to place the replacement of this Error Trap in your Error Trap
routine as your programme could also crash.

Here is an example of Error Trap build into an AutoLISP routine :

(defun c:drawline ()					;define function
	(setq temperr *error*)				;store *error*
	(setq *error* trap1)				;re-assign *error*
	(setq oldecho (getvar "cmdecho"))		;store variables			
	(setq oldlayer (getvar "clayer"))
	(setq oldsnap (getvar "osmode"))
	(setvar "cmdecho" 0)				;set variables
	(setvar "osmode" 32)
	(command "undo" "m")				;undo mark
	(setq pt1 (getpoint "\nPick First Point: "))	;get points
	(setq pt2 (getpoint pt1 "\nPick Second Point: "))
	(command "LAYER" "M" "2" "")			;change layer
	(command "Line" pt1 pt2 "")			;draw line
	(setq pt3 (getpoint pt2 "\nPick Third Point: "));get 3rd point
	(setvar "osmode" 0)				;switch off snap
	(command "Line" pt2 pt3 "")			;draw line
	(setvar "clayer" oldlayer)			;reset variables
	(setvar "osmode" oldsnap)
	(setvar "cmdecho" oldecho)
	(setq *error* temperr)				;restore *error*
   (princ)
)

(defun trap1 (errmsg)					;define function
	(command "u" "b")				;undo back
	(setvar "osmode" oldsnap)			;restore variables
	(setvar "clayer" oldlayer)
	(setvar "cmdecho" oldecho)
	(setq *error* temperr)				;restore *error*
	(prompt "\nResetting System Variables ")	;inform user
   (princ)
)

This routine simply asks for 3 points then draws a line, on layer 2,
between them.
As you can see, the existing (*error*) error trap is saved to the variable
temperr. *error* is then re-assigned to the error trap, called trap1.
Any system variables such as object snaps and command echo, are saved
as well as the current layer. An UNDO MARK is then put in place.
When an error occurs, the error trap first performs an UNDO BACK before
resetting the drawing back to it's original settings.
Try choosing the first two points and then hitting ESC or Ctrl C.
Did you see what happened? The first line that was drawn was erased
and your settings have been returned to their initial state.

The following is an example of an Error Trap using a Global Function :

Our drawline routine with some differences!!

(defun c:drawline ()					;define function
	(initerr)					;intitialise error
	(setvar "cmdecho" 0)				;reset variables
	(setvar "osmode" 32)
	(command "undo" "m")				;set mark
	(setq pt1 (getpoint "\nPick First Point: "))	;get points
	(setq pt2 (getpoint pt1 "\nPick Second Point: "))
	(command "LAYER" "M" "2" "")			;change layer
	(command "Line" pt1 pt2 "")			;draw line
	(setq pt3 (getpoint pt2 "\nPick Third Point: "));get 3rd point
	(setvar "osmode" 0)				;reset snap
	(command "Line" pt2 pt3 "")			;draw line
	(reset)						;reset variables
   (princ)
)

(princ)

Now our Global Error Trap named Error.Lsp

(defun error()						;load function
(prompt "\nGlobal Error Trap Loaded")			;inform user
(princ)
);defun
;;;*==========================================================
(defun initerr ()					;initiliase error
  (setq oldlayer (getvar "clayer"))			;save settings
  (setq oldsnap (getvar "osmode"))
  (setq oldpick (getvar "pickbox"))
  (setq temperr *error*)				;save *error*
  (setq *error* trap)					;re-assign *error*
  (princ)
);defun
;;;*===========================================================
(defun trap (errmsg)					;define error trap
  (command nil nil nil)
  (if (not (member errmsg '("console break" "Function Cancelled"))
      )
    (princ (strcat "\nError: " errmsg))			;print error message
  )                 
  (command "undo" "b")					;undo back
  (setvar "clayer" oldlayer)				;reset settings
  (setvar "blipmode" 1)
  (setvar "menuecho" 0)
  (setvar "highlight" 1)
  (setvar "osmode" oldsnap)
  (setvar "pickbox" oldpick)
  (princ "\nError Resetting Enviroment ")		;inform user
  (terpri)
  (setq *error* temperr)				;restore *error*
  (princ)
);defun
;;;*===========================================================
(defun reset ()						;define reset function
  (setq *error* temperr)				;restore *error*
  (setvar "clayer" oldlayer)				;reset settings
  (setvar "blipmode" 1)
  (setvar "menuecho" 0)
  (setvar "highlight" 1)
  (setvar "osmode" oldsnap)
  (setvar "pickbox" oldpick)
  (princ)
);defun
;;;*======================================================
(princ)

To run and test this you must load Error.Lsp before you load Drawline.Lsp.
As you can see, by using a Global Error routine you can save yourself the
bother of writing individual error traps for each of your programmes.
Error.Lsp could easily be loaded from your Acad.Lsp and would then be available
whenever one of your routines wishes to call upon it.

Happy Error Trapping!!!!


Copyright © 1998 by Kenny Ramage
All rights reserved.
Information in this document is subject to change without notice.
Site created and maintained by Kenny Ramage.