tclbasic.c

来自「tcl是工具命令语言」· C语言 代码 · 共 2,069 行 · 第 1/5 页

C
2,069
字号
    (VOID *) memset(statsPtr->literalCount, 0,            sizeof(statsPtr->literalCount));#endif /* TCL_COMPILE_STATS */        /*     * Initialise the stub table pointer.     */    iPtr->stubTable = &tclStubs;        /*     * Create the core commands. Do it here, rather than calling     * Tcl_CreateCommand, because it's faster (there's no need to check for     * a pre-existing command by the same name). If a command has a     * Tcl_CmdProc but no Tcl_ObjCmdProc, set the Tcl_ObjCmdProc to     * TclInvokeStringCommand. This is an object-based wrapper procedure     * that extracts strings, calls the string procedure, and creates an     * object for the result. Similarly, if a command has a Tcl_ObjCmdProc     * but no Tcl_CmdProc, set the Tcl_CmdProc to TclInvokeObjectCommand.     */    for (cmdInfoPtr = builtInCmds;  cmdInfoPtr->name != NULL;	    cmdInfoPtr++) {	int new;	Tcl_HashEntry *hPtr;	if ((cmdInfoPtr->proc == (Tcl_CmdProc *) NULL)	        && (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL)	        && (cmdInfoPtr->compileProc == (CompileProc *) NULL)) {	    panic("Tcl_CreateInterp: builtin command with NULL string and object command procs and a NULL compile proc\n");	}		hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,	        cmdInfoPtr->name, &new);	if (new) {	    cmdPtr = (Command *) ckalloc(sizeof(Command));	    cmdPtr->hPtr = hPtr;	    cmdPtr->nsPtr = iPtr->globalNsPtr;	    cmdPtr->refCount = 1;	    cmdPtr->cmdEpoch = 0;	    cmdPtr->compileProc = cmdInfoPtr->compileProc;	    if (cmdInfoPtr->proc == (Tcl_CmdProc *) NULL) {		cmdPtr->proc = TclInvokeObjectCommand;		cmdPtr->clientData = (ClientData) cmdPtr;	    } else {		cmdPtr->proc = cmdInfoPtr->proc;		cmdPtr->clientData = (ClientData) NULL;	    }	    if (cmdInfoPtr->objProc == (Tcl_ObjCmdProc *) NULL) {		cmdPtr->objProc = TclInvokeStringCommand;		cmdPtr->objClientData = (ClientData) cmdPtr;	    } else {		cmdPtr->objProc = cmdInfoPtr->objProc;		cmdPtr->objClientData = (ClientData) NULL;	    }	    cmdPtr->deleteProc = NULL;	    cmdPtr->deleteData = (ClientData) NULL;	    cmdPtr->flags = 0;	    cmdPtr->importRefPtr = NULL;	    cmdPtr->tracePtr = NULL;	    Tcl_SetHashValue(hPtr, cmdPtr);	}    }    /*     * Register the builtin math functions.     */    i = 0;    for (builtinFuncPtr = tclBuiltinFuncTable;  builtinFuncPtr->name != NULL;	    builtinFuncPtr++) {	Tcl_CreateMathFunc((Tcl_Interp *) iPtr, builtinFuncPtr->name,		builtinFuncPtr->numArgs, builtinFuncPtr->argTypes,		(Tcl_MathProc *) NULL, (ClientData) 0);	hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable,		builtinFuncPtr->name);	if (hPtr == NULL) {	    panic("Tcl_CreateInterp: Tcl_CreateMathFunc incorrectly registered '%s'", builtinFuncPtr->name);	    return NULL;	}	mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);	mathFuncPtr->builtinFuncIndex = i;	i++;    }    iPtr->flags |= EXPR_INITIALIZED;    /*     * Do Multiple/Safe Interps Tcl init stuff     */    TclInterpInit(interp);    /*     * We used to create the "errorInfo" and "errorCode" global vars at this     * point because so much of the Tcl implementation assumes they already     * exist. This is not quite enough, however, since they can be unset     * at any time.     *     * There are 2 choices:     *    + Check every place where a GetVar of those is used      *      and the NULL result is not checked (like in tclLoad.c)     *    + Make SetVar,... NULL friendly     * We choose the second option because :     *    + It is easy and low cost to check for NULL pointer before     *      calling strlen()     *    + It can be helpfull to other people using those API     *    + Passing a NULL value to those closest 'meaning' is empty string     *      (specially with the new objects where 0 bytes strings are ok)     * So the following init is commented out:              -- dl     *     * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorInfo", (char *) NULL,     *       "", TCL_GLOBAL_ONLY);     * (void) Tcl_SetVar2((Tcl_Interp *)iPtr, "errorCode", (char *) NULL,     *       "NONE", TCL_GLOBAL_ONLY);     */#ifndef TCL_GENERIC_ONLY    TclSetupEnv(interp);#endif    /*     * Compute the byte order of this machine.     */    order.s = 1;    Tcl_SetVar2(interp, "tcl_platform", "byteOrder",	    ((order.c[0] == 1) ? "littleEndian" : "bigEndian"),	    TCL_GLOBAL_ONLY);    Tcl_SetVar2Ex(interp, "tcl_platform", "wordSize",	    Tcl_NewLongObj((long) sizeof(long)), TCL_GLOBAL_ONLY);    /*     * Set up other variables such as tcl_version and tcl_library     */    Tcl_SetVar(interp, "tcl_patchLevel", TCL_PATCH_LEVEL, TCL_GLOBAL_ONLY);    Tcl_SetVar(interp, "tcl_version", TCL_VERSION, TCL_GLOBAL_ONLY);    Tcl_TraceVar2(interp, "tcl_precision", (char *) NULL,	    TCL_GLOBAL_ONLY|TCL_TRACE_READS|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,	    TclPrecTraceProc, (ClientData) NULL);    TclpSetVariables(interp);#ifdef TCL_THREADS    /*     * The existence of the "threaded" element of the tcl_platform array indicates     * that this particular Tcl shell has been compiled with threads turned on.     * Using "info exists tcl_platform(threaded)" a Tcl script can introspect on the      * interpreter level of thread safety.     */    Tcl_SetVar2(interp, "tcl_platform", "threaded", "1",	    TCL_GLOBAL_ONLY);#endif    /*     * Register Tcl's version number.     */    Tcl_PkgProvideEx(interp, "Tcl", TCL_VERSION, (ClientData) &tclStubs);    #ifdef Tcl_InitStubs#undef Tcl_InitStubs#endif    Tcl_InitStubs(interp, TCL_VERSION, 1);    return interp;}/* *---------------------------------------------------------------------- * * TclHideUnsafeCommands -- * *	Hides base commands that are not marked as safe from this *	interpreter. * * Results: *	TCL_OK if it succeeds, TCL_ERROR else. * * Side effects: *	Hides functionality in an interpreter. * *---------------------------------------------------------------------- */intTclHideUnsafeCommands(interp)    Tcl_Interp *interp;		/* Hide commands in this interpreter. */{    register CmdInfo *cmdInfoPtr;    if (interp == (Tcl_Interp *) NULL) {        return TCL_ERROR;    }    for (cmdInfoPtr = builtInCmds; cmdInfoPtr->name != NULL; cmdInfoPtr++) {        if (!cmdInfoPtr->isSafe) {            Tcl_HideCommand(interp, cmdInfoPtr->name, cmdInfoPtr->name);        }    }    return TCL_OK;}/* *-------------------------------------------------------------- * * Tcl_CallWhenDeleted -- * *	Arrange for a procedure to be called before a given *	interpreter is deleted. The procedure is called as soon *	as Tcl_DeleteInterp is called; if Tcl_CallWhenDeleted is *	called on an interpreter that has already been deleted, *	the procedure will be called when the last Tcl_Release is *	done on the interpreter. * * Results: *	None. * * Side effects: *	When Tcl_DeleteInterp is invoked to delete interp, *	proc will be invoked.  See the manual entry for *	details. * *-------------------------------------------------------------- */voidTcl_CallWhenDeleted(interp, proc, clientData)    Tcl_Interp *interp;		/* Interpreter to watch. */    Tcl_InterpDeleteProc *proc;	/* Procedure to call when interpreter				 * is about to be deleted. */    ClientData clientData;	/* One-word value to pass to proc. */{    Interp *iPtr = (Interp *) interp;    static int assocDataCounter = 0;#ifdef TCL_THREADS    static Tcl_Mutex assocMutex;#endif    int new;    char buffer[32 + TCL_INTEGER_SPACE];    AssocData *dPtr = (AssocData *) ckalloc(sizeof(AssocData));    Tcl_HashEntry *hPtr;    Tcl_MutexLock(&assocMutex);    sprintf(buffer, "Assoc Data Key #%d", assocDataCounter);    assocDataCounter++;    Tcl_MutexUnlock(&assocMutex);    if (iPtr->assocData == (Tcl_HashTable *) NULL) {        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);    }    hPtr = Tcl_CreateHashEntry(iPtr->assocData, buffer, &new);    dPtr->proc = proc;    dPtr->clientData = clientData;    Tcl_SetHashValue(hPtr, dPtr);}/* *-------------------------------------------------------------- * * Tcl_DontCallWhenDeleted -- * *	Cancel the arrangement for a procedure to be called when *	a given interpreter is deleted. * * Results: *	None. * * Side effects: *	If proc and clientData were previously registered as a *	callback via Tcl_CallWhenDeleted, they are unregistered. *	If they weren't previously registered then nothing *	happens. * *-------------------------------------------------------------- */voidTcl_DontCallWhenDeleted(interp, proc, clientData)    Tcl_Interp *interp;		/* Interpreter to watch. */    Tcl_InterpDeleteProc *proc;	/* Procedure to call when interpreter				 * is about to be deleted. */    ClientData clientData;	/* One-word value to pass to proc. */{    Interp *iPtr = (Interp *) interp;    Tcl_HashTable *hTablePtr;    Tcl_HashSearch hSearch;    Tcl_HashEntry *hPtr;    AssocData *dPtr;    hTablePtr = iPtr->assocData;    if (hTablePtr == (Tcl_HashTable *) NULL) {        return;    }    for (hPtr = Tcl_FirstHashEntry(hTablePtr, &hSearch); hPtr != NULL;	    hPtr = Tcl_NextHashEntry(&hSearch)) {        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);        if ((dPtr->proc == proc) && (dPtr->clientData == clientData)) {            ckfree((char *) dPtr);            Tcl_DeleteHashEntry(hPtr);            return;        }    }}/* *---------------------------------------------------------------------- * * Tcl_SetAssocData -- * *	Creates a named association between user-specified data, a delete *	function and this interpreter. If the association already exists *	the data is overwritten with the new data. The delete function will *	be invoked when the interpreter is deleted. * * Results: *	None. * * Side effects: *	Sets the associated data, creates the association if needed. * *---------------------------------------------------------------------- */voidTcl_SetAssocData(interp, name, proc, clientData)    Tcl_Interp *interp;		/* Interpreter to associate with. */    CONST char *name;		/* Name for association. */    Tcl_InterpDeleteProc *proc;	/* Proc to call when interpreter is                                 * about to be deleted. */    ClientData clientData;	/* One-word value to pass to proc. */{    Interp *iPtr = (Interp *) interp;    AssocData *dPtr;    Tcl_HashEntry *hPtr;    int new;    if (iPtr->assocData == (Tcl_HashTable *) NULL) {        iPtr->assocData = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));        Tcl_InitHashTable(iPtr->assocData, TCL_STRING_KEYS);    }    hPtr = Tcl_CreateHashEntry(iPtr->assocData, name, &new);    if (new == 0) {        dPtr = (AssocData *) Tcl_GetHashValue(hPtr);    } else {        dPtr = (AssocData *) ckalloc(sizeof(AssocData));    }    dPtr->proc = proc;    dPtr->clientData = clientData;    Tcl_SetHashValue(hPtr, dPtr);}/* *---------------------------------------------------------------------- * * Tcl_DeleteAssocData -- * *	Deletes a named association of user-specified data with *	the specified interpreter. * * Results: *	None. * * Side effects: *	Deletes the association. * *---------------------------------------------------------------------- */voidTcl_DeleteAssocData(interp, name)    Tcl_Interp *interp;			/* Interpreter to associate with. */    CONST char *name;			/* Name of association. */{    Interp *iPtr = (Interp *) interp;    AssocData *dPtr;    Tcl_HashEntry *hPtr;    if (iPtr->assocData == (Tcl_HashTable *) NULL) {        return;    }    hPtr = Tcl_FindHashEntry(iPtr->assocData, name);    if (hPtr == (Tcl_HashEntry *) NULL) {        return;    }    dPtr = (AssocData *) Tcl_GetHashValue(hPtr);    if (dPtr->proc != NULL) {        (dPtr->proc) (dPtr->clientData, interp);    }    ckfree((char *) dPtr);    Tcl_DeleteHashEntry(hPtr);}/* *---------------------------------------------------------------------- * * Tcl_GetAssocData -- * *	Returns the client data associated with this name in the *	specified interpreter. * * Results: *	The client data in the AssocData record denoted by the named *	association, or NULL. * * Side effects: *	None. * *---------------------------------------------------------------------- */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?