tclproc.c
来自「tcl是工具命令语言」· C语言 代码 · 共 1,707 行 · 第 1/4 页
C
1,707 行
*/static intProcessProcResultCode(interp, procName, nameLen, returnCode) Tcl_Interp *interp; /* The interpreter in which the procedure * was called and returned returnCode. */ char *procName; /* Name of the procedure. Used for error * messages and trace information. */ int nameLen; /* Number of bytes in procedure's name. */ int returnCode; /* The unexpected result code. */{ Interp *iPtr = (Interp *) interp; char msg[100 + TCL_INTEGER_SPACE]; char *ellipsis = ""; if (returnCode == TCL_OK) { return TCL_OK; } if ((returnCode > TCL_CONTINUE) || (returnCode < TCL_OK)) { return returnCode; } if (returnCode == TCL_RETURN) { return TclUpdateReturnInfo(iPtr); } if (returnCode != TCL_ERROR) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), ((returnCode == TCL_BREAK) ? "invoked \"break\" outside of a loop" : "invoked \"continue\" outside of a loop"), -1); } if (nameLen > 60) { nameLen = 60; ellipsis = "..."; } sprintf(msg, "\n (procedure \"%.*s%s\" line %d)", nameLen, procName, ellipsis, iPtr->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * TclProcDeleteProc -- * * This procedure is invoked just before a command procedure is * removed from an interpreter. Its job is to release all the * resources allocated to the procedure. * * Results: * None. * * Side effects: * Memory gets freed, unless the procedure is actively being * executed. In this case the cleanup is delayed until the * last call to the current procedure completes. * *---------------------------------------------------------------------- */voidTclProcDeleteProc(clientData) ClientData clientData; /* Procedure to be deleted. */{ Proc *procPtr = (Proc *) clientData; procPtr->refCount--; if (procPtr->refCount <= 0) { TclProcCleanupProc(procPtr); }}/* *---------------------------------------------------------------------- * * TclProcCleanupProc -- * * This procedure does all the real work of freeing up a Proc * structure. It's called only when the structure's reference * count becomes zero. * * Results: * None. * * Side effects: * Memory gets freed. * *---------------------------------------------------------------------- */voidTclProcCleanupProc(procPtr) register Proc *procPtr; /* Procedure to be deleted. */{ register CompiledLocal *localPtr; Tcl_Obj *bodyPtr = procPtr->bodyPtr; Tcl_Obj *defPtr; Tcl_ResolvedVarInfo *resVarInfo; if (bodyPtr != NULL) { Tcl_DecrRefCount(bodyPtr); } for (localPtr = procPtr->firstLocalPtr; localPtr != NULL; ) { CompiledLocal *nextPtr = localPtr->nextPtr; resVarInfo = localPtr->resolveInfo; if (resVarInfo) { if (resVarInfo->deleteProc) { (*resVarInfo->deleteProc)(resVarInfo); } else { ckfree((char *) resVarInfo); } } if (localPtr->defValuePtr != NULL) { defPtr = localPtr->defValuePtr; Tcl_DecrRefCount(defPtr); } ckfree((char *) localPtr); localPtr = nextPtr; } ckfree((char *) procPtr);}/* *---------------------------------------------------------------------- * * TclUpdateReturnInfo -- * * This procedure is called when procedures return, and at other * points where the TCL_RETURN code is used. It examines fields * such as iPtr->returnCode and iPtr->errorCode and modifies * the real return status accordingly. * * Results: * The return value is the true completion code to use for * the procedure, instead of TCL_RETURN. * * Side effects: * The errorInfo and errorCode variables may get modified. * *---------------------------------------------------------------------- */intTclUpdateReturnInfo(iPtr) Interp *iPtr; /* Interpreter for which TCL_RETURN * exception is being processed. */{ int code; char *errorCode; code = iPtr->returnCode; iPtr->returnCode = TCL_OK; if (code == TCL_ERROR) { errorCode = ((iPtr->errorCode != NULL) ? iPtr->errorCode : "NONE"); Tcl_ObjSetVar2((Tcl_Interp *) iPtr, iPtr->execEnvPtr->errorCode, NULL, Tcl_NewStringObj(errorCode, -1), TCL_GLOBAL_ONLY); iPtr->flags |= ERROR_CODE_SET; if (iPtr->errorInfo != NULL) { Tcl_ObjSetVar2((Tcl_Interp *) iPtr, iPtr->execEnvPtr->errorInfo, NULL, Tcl_NewStringObj(iPtr->errorInfo, -1), TCL_GLOBAL_ONLY); iPtr->flags |= ERR_IN_PROGRESS; } } return code;}/* *---------------------------------------------------------------------- * * TclGetInterpProc -- * * Returns a pointer to the TclProcInterpProc procedure; this is different * from the value obtained from the TclProcInterpProc reference on systems * like Windows where import and export versions of a procedure exported * by a DLL exist. * * Results: * Returns the internal address of the TclProcInterpProc procedure. * * Side effects: * None. * *---------------------------------------------------------------------- */TclCmdProcTypeTclGetInterpProc(){ return (TclCmdProcType) TclProcInterpProc;}/* *---------------------------------------------------------------------- * * TclGetObjInterpProc -- * * Returns a pointer to the TclObjInterpProc procedure; this is different * from the value obtained from the TclObjInterpProc reference on systems * like Windows where import and export versions of a procedure exported * by a DLL exist. * * Results: * Returns the internal address of the TclObjInterpProc procedure. * * Side effects: * None. * *---------------------------------------------------------------------- */TclObjCmdProcTypeTclGetObjInterpProc(){ return (TclObjCmdProcType) TclObjInterpProc;}/* *---------------------------------------------------------------------- * * TclNewProcBodyObj -- * * Creates a new object, of type "procbody", whose internal * representation is the given Proc struct. * The newly created object's reference count is 0. * * Results: * Returns a pointer to a newly allocated Tcl_Obj, 0 on error. * * Side effects: * The reference count in the ByteCode attached to the Proc is bumped up * by one, since the internal rep stores a pointer to it. * *---------------------------------------------------------------------- */Tcl_Obj *TclNewProcBodyObj(procPtr) Proc *procPtr; /* the Proc struct to store as the internal * representation. */{ Tcl_Obj *objPtr; if (!procPtr) { return (Tcl_Obj *) NULL; } objPtr = Tcl_NewStringObj("", 0); if (objPtr) { objPtr->typePtr = &tclProcBodyType; objPtr->internalRep.otherValuePtr = (VOID *) procPtr; procPtr->refCount++; } return objPtr;}/* *---------------------------------------------------------------------- * * ProcBodyDup -- * * Tcl_ObjType's Dup function for the proc body object. * Bumps the reference count on the Proc stored in the internal * representation. * * Results: * None. * * Side effects: * Sets up the object in dupPtr to be a duplicate of the one in srcPtr. * *---------------------------------------------------------------------- */static void ProcBodyDup(srcPtr, dupPtr) Tcl_Obj *srcPtr; /* object to copy */ Tcl_Obj *dupPtr; /* target object for the duplication */{ Proc *procPtr = (Proc *) srcPtr->internalRep.otherValuePtr; dupPtr->typePtr = &tclProcBodyType; dupPtr->internalRep.otherValuePtr = (VOID *) procPtr; procPtr->refCount++;}/* *---------------------------------------------------------------------- * * ProcBodyFree -- * * Tcl_ObjType's Free function for the proc body object. * The reference count on its Proc struct is decreased by 1; if the count * reaches 0, the proc is freed. * * Results: * None. * * Side effects: * If the reference count on the Proc struct reaches 0, the struct is freed. * *---------------------------------------------------------------------- */static voidProcBodyFree(objPtr) Tcl_Obj *objPtr; /* the object to clean up */{ Proc *procPtr = (Proc *) objPtr->internalRep.otherValuePtr; procPtr->refCount--; if (procPtr->refCount <= 0) { TclProcCleanupProc(procPtr); }}/* *---------------------------------------------------------------------- * * ProcBodySetFromAny -- * * Tcl_ObjType's SetFromAny function for the proc body object. * Calls panic. * * Results: * Theoretically returns a TCL result code. * * Side effects: * Calls panic, since we can't set the value of the object from a string * representation (or any other internal ones). * *---------------------------------------------------------------------- */static intProcBodySetFromAny(interp, objPtr) Tcl_Interp *interp; /* current interpreter */ Tcl_Obj *objPtr; /* object pointer */{ panic("called ProcBodySetFromAny"); /* * this to keep compilers happy. */ return TCL_OK;}/* *---------------------------------------------------------------------- * * ProcBodyUpdateString -- * * Tcl_ObjType's UpdateString function for the proc body object. * Calls panic. * * Results: * None. * * Side effects: * Calls panic, since we this type has no string representation. * *---------------------------------------------------------------------- */static voidProcBodyUpdateString(objPtr) Tcl_Obj *objPtr; /* the object to update */{ panic("called ProcBodyUpdateString");}/* *---------------------------------------------------------------------- * * TclCompileNoOp -- * * Procedure called to compile noOp's * * Results: * The return value is TCL_OK, indicating successful compilation. * * Side effects: * Instructions are added to envPtr to execute a noOp at runtime. * *---------------------------------------------------------------------- */static intTclCompileNoOp(interp, parsePtr, envPtr) Tcl_Interp *interp; /* Used for error reporting. */ Tcl_Parse *parsePtr; /* Points to a parse structure for the * command created by Tcl_ParseCommand. */ CompileEnv *envPtr; /* Holds resulting instructions. */{ Tcl_Token *tokenPtr; int i, code; int savedStackDepth = envPtr->currStackDepth; tokenPtr = parsePtr->tokenPtr; for(i = 1; i < parsePtr->numWords; i++) { tokenPtr = tokenPtr + tokenPtr->numComponents + 1; envPtr->currStackDepth = savedStackDepth; if (tokenPtr->type != TCL_TOKEN_SIMPLE_WORD) { code = TclCompileTokens(interp, tokenPtr+1, tokenPtr->numComponents, envPtr); if (code != TCL_OK) { return code; } TclEmitOpcode(INST_POP, envPtr); } } envPtr->currStackDepth = savedStackDepth; TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr); return TCL_OK;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?