diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2008-10-31 22:08:32 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2008-10-31 22:08:32 (GMT) |
commit | ea04b9849eb076f206c65efacd0a6a3aba6f4325 (patch) | |
tree | 48e83fa4c090195326480154283f0888f703a276 /generic/tclOOBasic.c | |
parent | 031a9bda7717f94ece3cbe7bca2b8a89de61e340 (diff) | |
download | tcl-ea04b9849eb076f206c65efacd0a6a3aba6f4325.zip tcl-ea04b9849eb076f206c65efacd0a6a3aba6f4325.tar.gz tcl-ea04b9849eb076f206c65efacd0a6a3aba6f4325.tar.bz2 |
Fix [Bug 2200824] and make class constructor error handling much more robust.
Diffstat (limited to 'generic/tclOOBasic.c')
-rw-r--r-- | generic/tclOOBasic.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/generic/tclOOBasic.c b/generic/tclOOBasic.c index cbece15..394ea60 100644 --- a/generic/tclOOBasic.c +++ b/generic/tclOOBasic.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclOOBasic.c,v 1.13 2008/10/16 22:34:18 nijtmans Exp $ + * RCS: @(#) $Id: tclOOBasic.c,v 1.14 2008/10/31 22:08:32 dkf Exp $ */ #ifdef HAVE_CONFIG_H @@ -975,6 +975,75 @@ TclOOCopyObjectCmd( } /* + * ---------------------------------------------------------------------- + * + * TclOOUpcatchCmd -- + * + * Implementation of the [oo::UpCatch] command, which is a combination of + * [uplevel 1] and [catch] that makes it easier to write transparent + * error handling in scripts. + * + * ---------------------------------------------------------------------- + */ + +int +TclOOUpcatchCmd( + ClientData ignored, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + return Tcl_NRCallObjProc(interp, TclOONRUpcatch, NULL, objc, objv); +} + +static int +UpcatchCallback( + ClientData data[], + Tcl_Interp *interp, + int result) +{ + Interp *iPtr = (Interp *) interp; + CallFrame *savedFramePtr = data[0]; + Tcl_Obj *resultObj[2]; + int rewind = iPtr->execEnvPtr->rewind; + + iPtr->varFramePtr = savedFramePtr; + if (rewind || Tcl_LimitExceeded(interp)) { + Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( + "\n (\"UpCatch\" body line %d)", interp->errorLine)); + return TCL_ERROR; + } + resultObj[0] = Tcl_GetObjResult(interp); + resultObj[1] = Tcl_GetReturnOptions(interp, result); + Tcl_SetObjResult(interp, Tcl_NewListObj(2, resultObj)); + return TCL_OK; +} + +int +TclOONRUpcatch( + ClientData ignored, + Tcl_Interp *interp, + int objc, + Tcl_Obj *const objv[]) +{ + Interp *iPtr = (Interp *) interp; + CallFrame *savedFramePtr = iPtr->varFramePtr; + Tcl_Obj *scriptObj; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 1, objv, "script"); + return TCL_ERROR; + } + if (iPtr->varFramePtr->callerVarPtr != NULL) { + iPtr->varFramePtr = iPtr->varFramePtr->callerVarPtr; + } + + Tcl_NRAddCallback(interp, UpcatchCallback, savedFramePtr, NULL,NULL,NULL); + return TclNREvalObjEx(interp, objv[1], TCL_EVAL_NOERR, + iPtr->cmdFramePtr, 1); +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 |