📄 tclbasic.c
字号:
refCmdPtr = oldRefPtr->importedCmdPtr; dataPtr = (ImportedCmdData*)refCmdPtr->objClientData; dataPtr->realCmdPtr = cmdPtr; oldRefPtr = oldRefPtr->nextPtr; } } /* * We just created a command, so in its namespace and all of its parent * namespaces, it may shadow global commands with the same name. If any * shadowed commands are found, invalidate all cached command references * in the affected namespaces. */ TclResetShadowedCmdRefs(interp, cmdPtr); return (Tcl_Command) cmdPtr;}/* *---------------------------------------------------------------------- * * TclInvokeStringCommand -- * * "Wrapper" Tcl_ObjCmdProc used to call an existing string-based * Tcl_CmdProc if no object-based procedure exists for a command. A * pointer to this procedure is stored as the Tcl_ObjCmdProc in a * Command structure. It simply turns around and calls the string * Tcl_CmdProc in the Command structure. * * Results: * A standard Tcl object result value. * * Side effects: * Besides those side effects of the called Tcl_CmdProc, * TclInvokeStringCommand allocates and frees storage. * *---------------------------------------------------------------------- */intTclInvokeStringCommand(clientData, interp, objc, objv) ClientData clientData; /* Points to command's Command structure. */ Tcl_Interp *interp; /* Current interpreter. */ register int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ register Command *cmdPtr = (Command *) clientData; register int i; int result; /* * This procedure generates an argv array for the string arguments. It * starts out with stack-allocated space but uses dynamically-allocated * storage if needed. */#define NUM_ARGS 20 char *(argStorage[NUM_ARGS]); char **argv = argStorage; /* * Create the string argument array "argv". Make sure argv is large * enough to hold the objc arguments plus 1 extra for the zero * end-of-argv word. * THIS FAILS IF ANY ARGUMENT OBJECT CONTAINS AN EMBEDDED NULL. */ if ((objc + 1) > NUM_ARGS) { argv = (char **) ckalloc((unsigned)(objc + 1) * sizeof(char *)); } for (i = 0; i < objc; i++) { argv[i] = Tcl_GetStringFromObj(objv[i], (int *) NULL); } argv[objc] = 0; /* * Invoke the command's string-based Tcl_CmdProc. */ result = (*cmdPtr->proc)(cmdPtr->clientData, interp, objc, argv); /* * Free the argv array if malloc'ed storage was used. */ if (argv != argStorage) { ckfree((char *) argv); } return result;#undef NUM_ARGS}/* *---------------------------------------------------------------------- * * TclInvokeObjectCommand -- * * "Wrapper" Tcl_CmdProc used to call an existing object-based * Tcl_ObjCmdProc if no string-based procedure exists for a command. * A pointer to this procedure is stored as the Tcl_CmdProc in a * Command structure. It simply turns around and calls the object * Tcl_ObjCmdProc in the Command structure. * * Results: * A standard Tcl string result value. * * Side effects: * Besides those side effects of the called Tcl_CmdProc, * TclInvokeStringCommand allocates and frees storage. * *---------------------------------------------------------------------- */intTclInvokeObjectCommand(clientData, interp, argc, argv) ClientData clientData; /* Points to command's Command structure. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ register char **argv; /* Argument strings. */{ Command *cmdPtr = (Command *) clientData; register Tcl_Obj *objPtr; register int i; int length, result; /* * This procedure generates an objv array for object arguments that hold * the argv strings. It starts out with stack-allocated space but uses * dynamically-allocated storage if needed. */#define NUM_ARGS 20 Tcl_Obj *(argStorage[NUM_ARGS]); register Tcl_Obj **objv = argStorage; /* * Create the object argument array "objv". Make sure objv is large * enough to hold the objc arguments plus 1 extra for the zero * end-of-objv word. */ if ((argc + 1) > NUM_ARGS) { objv = (Tcl_Obj **) ckalloc((unsigned)(argc + 1) * sizeof(Tcl_Obj *)); } for (i = 0; i < argc; i++) { length = strlen(argv[i]); TclNewObj(objPtr); TclInitStringRep(objPtr, argv[i], length); Tcl_IncrRefCount(objPtr); objv[i] = objPtr; } objv[argc] = 0; /* * Invoke the command's object-based Tcl_ObjCmdProc. */ result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, argc, objv); /* * Move the interpreter's object result to the string result, * then reset the object result. * FAILS IF OBJECT RESULT'S STRING REPRESENTATION CONTAINS NULL BYTES. */ Tcl_SetResult(interp, TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL), TCL_VOLATILE); /* * Decrement the ref counts for the argument objects created above, * then free the objv array if malloc'ed storage was used. */ for (i = 0; i < argc; i++) { objPtr = objv[i]; Tcl_DecrRefCount(objPtr); } if (objv != argStorage) { ckfree((char *) objv); } return result;#undef NUM_ARGS}/* *---------------------------------------------------------------------- * * TclRenameCommand -- * * Called to give an existing Tcl command a different name. Both the * old command name and the new command name can have "::" namespace * qualifiers. If the new command has a different namespace context, * the command will be moved to that namespace and will execute in * the context of that new namespace. * * If the new command name is NULL or the null string, the command is * deleted. * * Results: * Returns TCL_OK if successful, and TCL_ERROR if anything goes wrong. * * Side effects: * If anything goes wrong, an error message is returned in the * interpreter's result object. * *---------------------------------------------------------------------- */intTclRenameCommand(interp, oldName, newName) Tcl_Interp *interp; /* Current interpreter. */ char *oldName; /* Existing command name. */ char *newName; /* New command name. */{ Interp *iPtr = (Interp *) interp; char *newTail; Namespace *cmdNsPtr, *newNsPtr, *dummy1, *dummy2; Tcl_Command cmd; Command *cmdPtr; Tcl_HashEntry *hPtr, *oldHPtr; int new, result; /* * Find the existing command. An error is returned if cmdName can't * be found. */ cmd = Tcl_FindCommand(interp, oldName, (Tcl_Namespace *) NULL, /*flags*/ 0); cmdPtr = (Command *) cmd; if (cmdPtr == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't ", ((newName == NULL)||(*newName == '\0'))? "delete":"rename", " \"", oldName, "\": command doesn't exist", (char *) NULL); return TCL_ERROR; } cmdNsPtr = cmdPtr->nsPtr; /* * If the new command name is NULL or empty, delete the command. Do this * with Tcl_DeleteCommandFromToken, since we already have the command. */ if ((newName == NULL) || (*newName == '\0')) { Tcl_DeleteCommandFromToken(interp, cmd); return TCL_OK; } /* * Make sure that the destination command does not already exist. * The rename operation is like creating a command, so we should * automatically create the containing namespaces just like * Tcl_CreateCommand would. */ result = TclGetNamespaceForQualName(interp, newName, (Namespace *) NULL, (CREATE_NS_IF_UNKNOWN | TCL_LEAVE_ERR_MSG), &newNsPtr, &dummy1, &dummy2, &newTail); if (result != TCL_OK) { return result; } if ((newNsPtr == NULL) || (newTail == NULL)) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't rename to \"", newName, "\": bad command name", (char *) NULL); return TCL_ERROR; } if (Tcl_FindHashEntry(&newNsPtr->cmdTable, newTail) != NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't rename to \"", newName, "\": command already exists", (char *) NULL); return TCL_ERROR; } /* * Warning: any changes done in the code here are likely * to be needed in Tcl_HideCommand() code too. * (until the common parts are extracted out) --dl */ /* * Put the command in the new namespace so we can check for an alias * loop. Since we are adding a new command to a namespace, we must * handle any shadowing of the global commands that this might create. */ oldHPtr = cmdPtr->hPtr; hPtr = Tcl_CreateHashEntry(&newNsPtr->cmdTable, newTail, &new); Tcl_SetHashValue(hPtr, (ClientData) cmdPtr); cmdPtr->hPtr = hPtr; cmdPtr->nsPtr = newNsPtr; TclResetShadowedCmdRefs(interp, cmdPtr); /* * Now check for an alias loop. If we detect one, put everything back * the way it was and report the error. */ result = TclPreventAliasLoop(interp, interp, (Tcl_Command) cmdPtr); if (result != TCL_OK) { Tcl_DeleteHashEntry(cmdPtr->hPtr); cmdPtr->hPtr = oldHPtr; cmdPtr->nsPtr = cmdNsPtr; return result; } /* * The new command name is okay, so remove the command from its * current namespace. This is like deleting the command, so bump * the cmdEpoch to invalidate any cached references to the command. */ Tcl_DeleteHashEntry(oldHPtr); cmdPtr->cmdEpoch++; /* * If the command being renamed has a compile procedure, increment the * interpreter's compileEpoch to invalidate its compiled code. This * makes sure that we don't later try to execute old code compiled for * the now-renamed command. */ if (cmdPtr->compileProc != NULL) { iPtr->compileEpoch++; } return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_SetCommandInfo -- * * Modifies various information about a Tcl command. Note that * this procedure will not change a command's namespace; use * Tcl_RenameCommand to do that. Also, the isNativeObjectProc * member of *infoPtr is ignored. * * Results: * If cmdName exists in interp, then the information at *infoPtr * is stored with the command in place of the current information * and 1 is returned. If the command doesn't exist then 0 is * returned. * * Side effects: * None. * *---------------------------------------------------------------------- */intTcl_SetCommandInfo(interp, cmdName, infoPtr) Tcl_Interp *interp; /* Interpreter in which to look * for command. */ char *cmdName; /* Name of desired command. */ Tcl_CmdInfo *infoPtr; /* Where to store information about * command. */{ Tcl_Command cmd; Command *cmdPtr; cmd = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace *) NULL, /*flags*/ 0); if (cmd == (Tcl_Command) NULL) { return 0; } /* * The isNativeObjectProc and nsPtr members of *infoPtr are ignored. */ cmdPtr = (Command *) cmd; cmdPtr->proc = infoPtr->proc; cmdPtr->clientData = infoPtr->clientData; if (infoPtr->objProc == (Tcl_ObjCmdProc *) NULL) { cmdPtr->objProc = TclInvokeStringCommand; cmdPtr->objClientData = (ClientData) cmdPtr; } else { cmdPtr->objProc = infoPtr->objProc; cmdPtr->objClientData = infoPtr->objClientData; } cmdPtr->deleteProc = infoPtr->deleteProc; cmdPtr->deleteData = infoPtr->deleteData; return 1;}/* *---------------------------------------------------------------------- * * Tcl_GetCommandInfo -- * * Returns various information about a Tcl command. * * Results: * If cmdName exists in interp, then *infoPtr is modified to * hold information about cmdName and 1 is returned. If the * command doesn't exist then 0 is returned and *infoPtr isn't * modified. * * Side effects: * None. * *---------------------------------------------------------------------- */intTcl_GetCommandInfo(interp, cmdName, infoPtr) Tcl_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -