tclinterp.c
来自「tcl是工具命令语言」· C语言 代码 · 共 2,256 行 · 第 1/5 页
C
2,256 行
Alias *aliasPtr; Tcl_Obj *prefixPtr; /* * If the alias has been renamed in the slave, the master can still use * the original name (with which it was created) to find the alias to * describe it. */ slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr)); if (hPtr == NULL) { return TCL_OK; } aliasPtr = (Alias *) Tcl_GetHashValue(hPtr); prefixPtr = Tcl_NewListObj(aliasPtr->objc, &aliasPtr->objPtr); Tcl_SetObjResult(interp, prefixPtr); return TCL_OK;}/* *---------------------------------------------------------------------- * * AliasList -- * * Computes a list of aliases defined in a slave interpreter. * * Results: * A standard Tcl result. * * Side effects: * None. * *---------------------------------------------------------------------- */static intAliasList(interp, slaveInterp) Tcl_Interp *interp; /* Interp for data return. */ Tcl_Interp *slaveInterp; /* Interp whose aliases to compute. */{ Tcl_HashEntry *entryPtr; Tcl_HashSearch hashSearch; Tcl_Obj *resultPtr; Alias *aliasPtr; Slave *slavePtr; slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; resultPtr = Tcl_GetObjResult(interp); entryPtr = Tcl_FirstHashEntry(&slavePtr->aliasTable, &hashSearch); for ( ; entryPtr != NULL; entryPtr = Tcl_NextHashEntry(&hashSearch)) { aliasPtr = (Alias *) Tcl_GetHashValue(entryPtr); Tcl_ListObjAppendElement(NULL, resultPtr, aliasPtr->namePtr); } return TCL_OK;}/* *---------------------------------------------------------------------- * * AliasObjCmd -- * * This is the procedure that services invocations of aliases in a * slave interpreter. One such command exists for each alias. When * invoked, this procedure redirects the invocation to the target * command in the master interpreter as designated by the Alias * record associated with this command. * * Results: * A standard Tcl result. * * Side effects: * Causes forwarding of the invocation; all possible side effects * may occur as a result of invoking the command to which the * invocation is forwarded. * *---------------------------------------------------------------------- */static intAliasObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Alias record. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument vector. */ {#define ALIAS_CMDV_PREALLOC 10 Tcl_Interp *targetInterp; Alias *aliasPtr; int result, prefc, cmdc; Tcl_Obj **prefv, **cmdv; Tcl_Obj *cmdArr[ALIAS_CMDV_PREALLOC]; aliasPtr = (Alias *) clientData; targetInterp = aliasPtr->targetInterp; /* * Append the arguments to the command prefix and invoke the command * in the target interp's global namespace. */ prefc = aliasPtr->objc; prefv = &aliasPtr->objPtr; cmdc = prefc + objc - 1; if (cmdc <= ALIAS_CMDV_PREALLOC) { cmdv = cmdArr; } else { cmdv = (Tcl_Obj **) ckalloc((unsigned) (cmdc * sizeof(Tcl_Obj *))); } prefv = &aliasPtr->objPtr; memcpy((VOID *) cmdv, (VOID *) prefv, (size_t) (prefc * sizeof(Tcl_Obj *))); memcpy((VOID *) (cmdv+prefc), (VOID *) (objv+1), (size_t) ((objc-1) * sizeof(Tcl_Obj *))); Tcl_ResetResult(targetInterp); if (targetInterp != interp) { Tcl_Preserve((ClientData) targetInterp); result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE); TclTransferResult(targetInterp, result, interp); Tcl_Release((ClientData) targetInterp); } else { result = Tcl_EvalObjv(targetInterp, cmdc, cmdv, TCL_EVAL_INVOKE); } if (cmdv != cmdArr) { ckfree((char *) cmdv); } return result; #undef ALIAS_CMDV_PREALLOC}/* *---------------------------------------------------------------------- * * AliasObjCmdDeleteProc -- * * Is invoked when an alias command is deleted in a slave. Cleans up * all storage associated with this alias. * * Results: * None. * * Side effects: * Deletes the alias record and its entry in the alias table for * the interpreter. * *---------------------------------------------------------------------- */static voidAliasObjCmdDeleteProc(clientData) ClientData clientData; /* The alias record for this alias. */{ Alias *aliasPtr; Target *targetPtr; int i; Tcl_Obj **objv; aliasPtr = (Alias *) clientData; Tcl_DecrRefCount(aliasPtr->namePtr); objv = &aliasPtr->objPtr; for (i = 0; i < aliasPtr->objc; i++) { Tcl_DecrRefCount(objv[i]); } Tcl_DeleteHashEntry(aliasPtr->aliasEntryPtr); targetPtr = (Target *) Tcl_GetHashValue(aliasPtr->targetEntryPtr); ckfree((char *) targetPtr); Tcl_DeleteHashEntry(aliasPtr->targetEntryPtr); ckfree((char *) aliasPtr);}/* *---------------------------------------------------------------------- * * Tcl_CreateSlave -- * * Creates a slave interpreter. The slavePath argument denotes the * name of the new slave relative to the current interpreter; the * slave is a direct descendant of the one-before-last component of * the path, e.g. it is a descendant of the current interpreter if * the slavePath argument contains only one component. Optionally makes * the slave interpreter safe. * * Results: * Returns the interpreter structure created, or NULL if an error * occurred. * * Side effects: * Creates a new interpreter and a new interpreter object command in * the interpreter indicated by the slavePath argument. * *---------------------------------------------------------------------- */Tcl_Interp *Tcl_CreateSlave(interp, slavePath, isSafe) Tcl_Interp *interp; /* Interpreter to start search at. */ CONST char *slavePath; /* Name of slave to create. */ int isSafe; /* Should new slave be "safe" ? */{ Tcl_Obj *pathPtr; Tcl_Interp *slaveInterp; pathPtr = Tcl_NewStringObj(slavePath, -1); slaveInterp = SlaveCreate(interp, pathPtr, isSafe); Tcl_DecrRefCount(pathPtr); return slaveInterp;}/* *---------------------------------------------------------------------- * * Tcl_GetSlave -- * * Finds a slave interpreter by its path name. * * Results: * Returns a Tcl_Interp * for the named interpreter or NULL if not * found. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_Interp *Tcl_GetSlave(interp, slavePath) Tcl_Interp *interp; /* Interpreter to start search from. */ CONST char *slavePath; /* Path of slave to find. */{ Tcl_Obj *pathPtr; Tcl_Interp *slaveInterp; pathPtr = Tcl_NewStringObj(slavePath, -1); slaveInterp = GetInterp(interp, pathPtr); Tcl_DecrRefCount(pathPtr); return slaveInterp;}/* *---------------------------------------------------------------------- * * Tcl_GetMaster -- * * Finds the master interpreter of a slave interpreter. * * Results: * Returns a Tcl_Interp * for the master interpreter or NULL if none. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_Interp *Tcl_GetMaster(interp) Tcl_Interp *interp; /* Get the master of this interpreter. */{ Slave *slavePtr; /* Slave record of this interpreter. */ if (interp == (Tcl_Interp *) NULL) { return NULL; } slavePtr = &((InterpInfo *) ((Interp *) interp)->interpInfo)->slave; return slavePtr->masterInterp;}/* *---------------------------------------------------------------------- * * Tcl_GetInterpPath -- * * Sets the result of the asking interpreter to a proper Tcl list * containing the names of interpreters between the asking and * target interpreters. The target interpreter must be either the * same as the asking interpreter or one of its slaves (including * recursively). * * Results: * TCL_OK if the target interpreter is the same as, or a descendant * of, the asking interpreter; TCL_ERROR else. This way one can * distinguish between the case where the asking and target interps * are the same (an empty list is the result, and TCL_OK is returned) * and when the target is not a descendant of the asking interpreter * (in which case the Tcl result is an error message and the function * returns TCL_ERROR). * * Side effects: * None. * *---------------------------------------------------------------------- */intTcl_GetInterpPath(askingInterp, targetInterp) Tcl_Interp *askingInterp; /* Interpreter to start search from. */ Tcl_Interp *targetInterp; /* Interpreter to find. */{ InterpInfo *iiPtr; if (targetInterp == askingInterp) { return TCL_OK; } if (targetInterp == NULL) { return TCL_ERROR; } iiPtr = (InterpInfo *) ((Interp *) targetInterp)->interpInfo; if (Tcl_GetInterpPath(askingInterp, iiPtr->slave.masterInterp) != TCL_OK) { return TCL_ERROR; } Tcl_AppendElement(askingInterp, Tcl_GetHashKey(&iiPtr->master.slaveTable, iiPtr->slave.slaveEntryPtr)); return TCL_OK;}/* *---------------------------------------------------------------------- * * GetInterp -- * * Helper function to find a slave interpreter given a pathname. * * Results: * Returns the slave interpreter known by that name in the calling * interpreter, or NULL if no interpreter known by that name exists. * * Side effects: * Assigns to the pointer variable passed in, if not NULL. * *---------------------------------------------------------------------- */static Tcl_Interp *GetInterp(interp, pathPtr) Tcl_Interp *interp; /* Interp. to start search from. */ Tcl_Obj *pathPtr; /* List object containing name of interp. to * be found. */{ Tcl_HashEntry *hPtr; /* Search element. */ Slave *slavePtr; /* Interim slave record. */ Tcl_Obj **objv; int objc, i; Tcl_Interp *searchInterp; /* Interim storage for interp. to find. */ InterpInfo *masterInfoPtr; if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { return NULL; } searchInterp = interp; for (i = 0; i < objc; i++) { masterInfoPtr = (InterpInfo *) ((Interp *) searchInterp)->interpInfo; hPtr = Tcl_FindHashEntry(&masterInfoPtr->master.slaveTable, Tcl_GetString(objv[i])); if (hPtr == NULL) { searchInterp = NULL; break; } slavePtr = (Slave *) Tcl_GetHashValue(hPtr); searchInterp = slavePtr->slaveInterp; if (searchInterp == NULL) { break; } } if (searchInterp == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "could not find interpreter \"", Tcl_GetString(pathPtr), "\"", (char *) NULL); } return searchInterp;}/* *---------------------------------------------------------------------- * * SlaveCreate -- * * Helper function to do the actual work of creating a slave interp * and new object command. Also optionally makes the new slave * interpreter "safe". * * Results: * Returns the new Tcl_Interp * if successful or NULL if not. If failed, * the result of the invoking interpreter contains an error message. * * Side effects: * Creates a new slave interpreter and a new object command. * *---------------------------------------------------------------------- */static Tcl_Interp *SlaveCreate(interp, pathPtr, safe) Tcl_Interp *interp; /* Interp. to start search from. */ Tcl_Obj *pathPtr; /* Path (name) of slave to create. */ int safe; /* Should we make it "safe"? */{ Tcl_Interp *masterInterp, *slaveInterp; Slave *slavePtr; InterpInfo *masterInfoPtr; Tcl_HashEntry *hPtr; char *path; int new, objc; Tcl_Obj **objv; if (Tcl_ListObjGetElements(interp, pathPtr, &objc, &objv) != TCL_OK) { return NULL; } if (objc < 2) { masterInterp = interp; path = Tcl_GetString(pathPtr); } else { Tcl_Obj *objPtr; objPtr = Tcl_NewListObj(objc - 1, objv); masterInterp = GetInterp(interp, objPtr); Tcl_DecrRefCount(objPtr); if (masterInterp == NULL) { return NULL; } path = Tcl_GetString(objv[objc - 1]); } if (safe == 0) { safe = Tcl_IsSafe(masterInterp); } masterInfoPtr = (InterpInfo *) ((Interp *) masterInterp)->interpInfo; hPtr = Tcl_CreateHashEntry(&masterInfoPtr->master.slaveTable, path, &new); if (new == 0) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "interpreter named \"", path, "\" already exists, cannot create", (char *) NULL); return NULL; } slaveInterp = Tcl_CreateInterp(); slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave; slavePtr->masterInterp = masterInterp; slavePtr->slaveEntryPtr = hPtr; slavePtr->slaveInterp = slaveInterp; slavePtr->interpCmd = Tcl_CreateObjCommand(masterInterp, path,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?