public TCL.CompletionCode cmdProc( Interp interp, TclObject[] argv ) { // Create the call frame and parameter bindings CallFrame frame = interp.newCallFrame( this, argv ); // Execute the body interp.pushDebugStack( srcFileName, srcLineNumber ); try { Parser.eval2( interp, body.array, body.index, body_length, 0 ); } catch ( TclException e ) { TCL.CompletionCode code = e.getCompletionCode(); if ( code == TCL.CompletionCode.RETURN ) { TCL.CompletionCode realCode = interp.updateReturnInfo(); if ( realCode != TCL.CompletionCode.OK ) { e.setCompletionCode( realCode ); throw; } } else if ( code == TCL.CompletionCode.ERROR ) { interp.addErrorInfo( "\n (procedure \"" + argv[0] + "\" line " + interp.errorLine + ")" ); throw; } else if ( code == TCL.CompletionCode.BREAK ) { throw new TclException( interp, "invoked \"break\" outside of a loop" ); } else if ( code == TCL.CompletionCode.CONTINUE ) { throw new TclException( interp, "invoked \"continue\" outside of a loop" ); } else { throw; } } finally { interp.popDebugStack(); // The check below is a hack. The problem is that there // could be unset traces on the variables, which cause // scripts to be evaluated. This will clear the // errInProgress flag, losing stack trace information if // the procedure was exiting with an error. The code // below preserves the flag. Unfortunately, that isn't // really enough: we really should preserve the errorInfo // variable too (otherwise a nested error in the trace // script will trash errorInfo). What's really needed is // a general-purpose mechanism for saving and restoring // interpreter state. if ( interp.errInProgress ) { frame.dispose(); interp.errInProgress = true; } else { frame.dispose(); } } return TCL.CompletionCode.RETURN; }