Error Trapping conundrum

Error Trapping conundrum

richie_hodgson
Collaborator Collaborator
1,058 Views
5 Replies
Message 1 of 6

Error Trapping conundrum

richie_hodgson
Collaborator
Collaborator

Hi Guys I am trying to add some error trapping to a bunch of lisp routines, I am using the following error trapping routine

 

(defun error() ;load function

(prompt "\nGlobal Error Trap Loaded") ;inform user

(princ)

);defun

;;;*==========================================================

(defun initerr () ;init error

(setq curlay (getvar "clayer"))

(setq curcol (getvar "cecolor"))

(setq curlin (getvar "celtype"))

(setq curort (getvar "orthomode"))

(setq oldpost (getvar "dimpost"))

(setq curdimtmove (getvar "dimtmove"))

(setq oldos (getvar "osmode")) ;save settings

(setq curpick (getvar "pickbox"))

(setq temperr *error*) ;save *error*

(setq *error* trap) ;reassign *error*

(princ)

);defun

;;;*===========================================================

(defun trap (errmsg) ;define trap

(command nil nil nil)

(if (not (member errmsg '("console break" "Function Cancelled"))

)

(princ (strcat "\nError: " errmsg)) ;print message

)

(command "undo" "b") ;undo back

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "dimtmove" curdimtmove)

(setvar "dimpost" oldpost)

(setvar "osmode" oldos) ;reset settings

(setvar "menuecho" 0)

(setvar "highlight" 1)

(setvar "pickbox" oldpick)

(princ "\nError Resetting Enviroment ") ;inform user

(terpri)

(setq *error* temperr) ;restore *error*

(princ)

);defun

;;;*===========================================================

(defun reset () ;define reset

(setq *error* temperr) ;restore *error*

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "dimtmove" curdimtmove)

(setvar "dimpost" oldpost)

(setvar "osmode" oldos);reset settings

(setvar "menuecho" 0)

(setvar "highlight" 1)

(setvar "pickbox" curpick)

(princ)

);defun

;;; End of Error Trapping functions

 

Then I have a bunch of lisp routines below that typically

 

(defun c:dosomething ()

 (initerr)

    (do something)

 (reset)

)

 

If I quit out of a routine I get the following error

 

Cannot invoke (command) from *error* without prior call to (*push-error-using-command*).
Converting (command) calls to (command-s) is recommended.

 

If I follow through the routines there is no error so I am picking I have messed up the error trap somehow. Where have I messed up?

 

 

 

Richie
0 Likes
1,059 Views
5 Replies
Replies (5)
Message 2 of 6

Kent1Cooper
Consultant
Consultant

They changed *error* handling [in the 2015 version, I think] for some reason, to not allow (command) functions [in *error* only -- you can still use them outside it], unless you jump through extra hoops [the (*push...) business].  You can just do what they say, and change them to (command-s) instead [read about the differences in Help].  Some things that used to be doable with (command) can be done in other ways, such as Undo Begin/End with VLA functions, but I don't think your Undo Back can be done that way [I looked for a way once, and didn't find it, which doesn't mean it isn't out there somewhere].

 

However, be aware that (command-s) will not be recognized by versions prior to whenever they made that change.  I have a location still using Acad2004, as well as much more recent versions elsewhere, so any routines I write use the VLA methods for Undo Begin/End [the main thing for which I used to used (command) in *error*], since those work in any version, and I therefore can use the same routines in all locations.

 

Related:  You are apparently unaware that the *error* function can now be [this hasn't always been true, but for pretty many years now -- since something like Release 14, and I don't mean Acad2014] defined within a command definition, and treated like a variable, including localizing it, so that it simply goes away when the command is finished, and AutoCAD's native version is restored, without your needing to save that as a temporary thing and restore it later yourself.

 

(defun C:YourCommandName (/ *error* what ever else)

  (defun *error* (errmsg)

    (this function)

    (that function)

    (other function)

  ); end defun -- *error*

  (go on.....

  ....

)

 

Several commands can share a common one by defining it once and calling it within those:

(defun myerror ()

  (if {...message prompting stuff...}

  (...etc...)

)

 

Then:

 

(defun C:CommandA (/ *error* what ever else)

  (defun *error* (errmsg) (myerror))

  (...etc...)

  ....

)

 

(defun C:CommandB (/ *error* some other variables)

  (defun *error* (errmsg) (myerror))

  (...etc...)

  ....

)

 

Poke around and you'll find a lot of routines that do it that way -- saves code, fewer variables, etc.

Kent Cooper, AIA
0 Likes
Message 3 of 6

scot-65
Advisor
Advisor
>> (command nil nil nil)
May not work inside an error handler even while using it inside command-s.

I agree with Kent to make a local error.
This tends to make routines not dependent on outside "menu" functions.

(if curlay (setvar "clayer" curlay))
(setq curlay nil)
Lots of gremlins to corral.

???

Scot-65
A gift of extraordinary Common Sense does not require an Acronym Suffix to be added to my given name.

0 Likes
Message 4 of 6

dgorsman
Consultant
Consultant

Well, having a "global" error handler promotes consistent handling of errors, plus removes the need to constantly define local error handlers which all do the same thing.  For example our standard function resets system variables which were previously pushed along with some diagnostic info to find where and what the error is.  There are circumstances where specific handling is required though; in our case I have it call our base error handler function in addition to that.  Still, I'd recommend avoiding (command ...) calls in the error handling sequence to begin with.

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


0 Likes
Message 5 of 6

richie_hodgson
Collaborator
Collaborator

Hi Kent

 

I have done some poking around to little avail, here is a more full example of the coding I am attempting to achieve

 

(defun initerr () ;init error

(setq curlay (getvar "clayer"))

(setq curcol (getvar "cecolor"))

(setq curlin (getvar "celtype"))

(setq cursnap (getvar "osmode"))

(setq curort (getvar "orthomode")) ;save settings

(setq temperr *error*) ;save *error*

(setq *error* trap) ;reassign *error*

(princ)

);End defun

;

(defun trap (errmsg)

(if (not (member errmsg '("console break" "Function Cancelled"))

)

(princ (strcat "\nError: " errmsg)) ;print message

)

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "osmode" cursnap)

(setvar "orthomode" curort) ;reset settings

);End defun

;

(defun trap (errmsg) ;define trap

(princ "\nError Resetting Enviroment ") ;inform user

(terpri)

(setq *error* temperr) ;restore *error*

(princ)

);End defun

;

(defun reset () ;define reset

(setq *error* temperr) ;restore *error*

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "osmode" cursnap)

(setvar "orthomode" curort)

(princ)

); End defun

;

(defun c:A1 ()

(initerr)

(if (= Nil (tblsearch "layer" "Border")) (command "layer" "m" "Border" "lt" "continuous" "" "c" "4" "" ""))

(setvar "clayer" "Border")

(setvar "cecolor" "bylayer")

(setvar "celtype" "bylayer")

(setq p1 (getpoint "\nPick Start Point"))

(setq p2 '(841 594))

(command "RECTANGLE" p1 (mapcar '+ p1 p2))

(reset)

);End defun

;

(defun c:A0 ()

(initerr)

(if (= Nil (tblsearch "layer" "Border")) (command "layer" "m" "Border" "lt" "continuous" "" "c" "4" "" ""))

(setvar "clayer" "Border")

(setvar "cecolor" "bylayer")

(setvar "celtype" "bylayer")

(setq p1 (getpoint "\nPick Start Point"))

(setq p2 '(1189 841))

(command "RECTANGLE" p1 (mapcar '+ p1 p2))

(reset)

); End defun

; Other similar command functions;;;;;

 

The only errors I am wanting to trap at this stage are escape or return since maths errors don't occur. How do I code it to work in the most efficient manner?

 

we are using 2016. No previous version.

 

Richie
0 Likes
Message 6 of 6

richie_hodgson
Collaborator
Collaborator

Hi Kent

 

Had a spare couple of minutes to look at the code and slapped my head after making sense of what was going on. This seems to be working now. I don't think I need the (if (not ...) bit but will leave it there for the moment till I have time to play with it a bit further.

 

(defun initerr () ;init error

(setq curlay (getvar "clayer"))

(setq curcol (getvar "cecolor"))

(setq curlin (getvar "celtype"))

(setq cursnap (getvar "osmode"))

(setq curort (getvar "orthomode")) ;save settings

);defun

;

(defun trap (errmsg)

(setq *error* temperr)

(if (not (member errmsg '("console break" "Function Cancelled"))

)

(princ (strcat "\nError: " errmsg)) ;print message

)

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "osmode" cursnap)

(setvar "orthomode" curort) ;reset settings

);defun

;

(defun reset () ;define reset

(setvar "clayer" curlay)

(setvar "cecolor" curcol)

(setvar "celtype" curlin)

(setvar "osmode" cursnap)

(setvar "orthomode" curort)

(princ)

);defun

 

(defun c:A1 ()

(initerr)

(setq temperr *error*)

(setq *error* trap)

(if (= Nil (tblsearch "layer" "Border")) (command "layer" "m" "Border" "lt" "continuous" "" "c" "4" "" ""))

(setvar "clayer" "Border")

(setvar "cecolor" "bylayer")

(setvar "celtype" "bylayer")

(setq p1 (getpoint "\nPick Start Point"))

(setq p2 '(841 594))

(command "RECTANGLE" p1 (mapcar '+ p1 p2))

(reset)

)

(defun c:A2 ()

(initerr)

(setq temperr *error*)

(setq *error* trap)

(if (= Nil (tblsearch "layer" "Border")) (command "layer" "m" "Border" "lt" "continuous" "" "c" "4" "" ""))

(setvar "clayer" "Border")

(setvar "cecolor" "bylayer")

(setvar "celtype" "bylayer")

(setq p1 (getpoint "\nPick Start Point"))

(setq p2 '(594 420))

(command "RECTANGLE" p1 (mapcar '+ p1 p2))

(reset)

)

 

 

Richie
0 Likes