diff options
-rw-r--r-- | generic/tclResolve.c | 394 |
1 files changed, 190 insertions, 204 deletions
diff --git a/generic/tclResolve.c b/generic/tclResolve.c index 49c21ca..e61e49d 100644 --- a/generic/tclResolve.c +++ b/generic/tclResolve.c @@ -1,113 +1,110 @@ /* * tclResolve.c -- * - * Contains hooks for customized command/variable name resolution - * schemes. These hooks allow extensions like [incr Tcl] to add - * their own name resolution rules to the Tcl language. Rules can - * be applied to a particular namespace, to the interpreter as a - * whole, or both. + * Contains hooks for customized command/variable name resolution + * schemes. These hooks allow extensions like [incr Tcl] to add their own + * name resolution rules to the Tcl language. Rules can be applied to a + * particular namespace, to the interpreter as a whole, or both. * * Copyright (c) 1998 Lucent Technologies, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclResolve.c,v 1.5 2005/05/30 00:04:48 dkf Exp $ + * RCS: @(#) $Id: tclResolve.c,v 1.6 2005/07/15 15:09:31 dkf Exp $ */ #include "tclInt.h" /* - * Declarations for procedures local to this file: + * Declarations for functions local to this file: */ static void BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr)); - /* *---------------------------------------------------------------------- * * Tcl_AddInterpResolvers -- * - * Adds a set of command/variable resolution procedures to an - * interpreter. These procedures are consulted when commands - * are resolved in Tcl_FindCommand, and when variables are - * resolved in TclLookupVar and LookupCompiledLocal. Each - * namespace may also have its own set of resolution procedures - * which take precedence over those for the interpreter. + * Adds a set of command/variable resolution functions to an interpreter. + * These functions are consulted when commands are resolved in + * Tcl_FindCommand, and when variables are resolved in TclLookupVar and + * LookupCompiledLocal. Each namespace may also have its own set of + * resolution functions which take precedence over those for the + * interpreter. * - * When a name is resolved, it is handled as follows. First, - * the name is passed to the resolution procedures for the - * namespace. If not resolved, the name is passed to each of - * the resolution procedures added to the interpreter. Finally, - * if still not resolved, the name is handled using the default - * Tcl rules for name resolution. + * When a name is resolved, it is handled as follows. First, the name is + * passed to the resolution functions for the namespace. If not resolved, + * the name is passed to each of the resolution functions added to the + * interpreter. Finally, if still not resolved, the name is handled using + * the default Tcl rules for name resolution. * * Results: - * Returns pointers to the current name resolution procedures - * in the cmdProcPtr, varProcPtr and compiledVarProcPtr - * arguments. + * Returns pointers to the current name resolution functions in the + * cmdProcPtr, varProcPtr and compiledVarProcPtr arguments. * * Side effects: - * If a compiledVarProc is specified, this procedure bumps the - * compileEpoch for the interpreter, forcing all code to be - * recompiled. If a cmdProc is specified, this procedure bumps - * the cmdRefEpoch in all namespaces, forcing commands to be - * resolved again using the new rules. + * If a compiledVarProc is specified, this function bumps the + * compileEpoch for the interpreter, forcing all code to be recompiled. + * If a cmdProc is specified, this function bumps the cmdRefEpoch in all + * namespaces, forcing commands to be resolved again using the new rules. * *---------------------------------------------------------------------- */ void Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc) - Tcl_Interp *interp; /* Interpreter whose name resolution * rules are being modified. */ CONST char *name; /* Name of this resolution scheme. */ - Tcl_ResolveCmdProc *cmdProc; /* New procedure for command - * resolution */ - Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution - * at runtime */ + Tcl_ResolveCmdProc *cmdProc; /* New function for command + * resolution. */ + Tcl_ResolveVarProc *varProc; /* Function for variable resolution at + * runtime. */ Tcl_ResolveCompiledVarProc *compiledVarProc; - /* Procedure for variable resolution - * at compile time. */ + /* Function for variable resolution at + * compile time. */ { - Interp *iPtr = (Interp*)interp; + Interp *iPtr = (Interp *) interp; ResolverScheme *resPtr; /* - * Since we're adding a new name resolution scheme, we must force - * all code to be recompiled to use the new scheme. If there - * are new compiled variable resolution rules, bump the compiler - * epoch to invalidate compiled code. If there are new command - * resolution rules, bump the cmdRefEpoch in all namespaces. + * Since we're adding a new name resolution scheme, we must force all code + * to be recompiled to use the new scheme. If there are new compiled + * variable resolution rules, bump the compiler epoch to invalidate + * compiled code. If there are new command resolution rules, bump the + * cmdRefEpoch in all namespaces. */ + if (compiledVarProc) { - iPtr->compileEpoch++; + iPtr->compileEpoch++; } if (cmdProc) { - BumpCmdRefEpochs(iPtr->globalNsPtr); + BumpCmdRefEpochs(iPtr->globalNsPtr); } /* - * Look for an existing scheme with the given name. If found, - * then replace its rules. + * Look for an existing scheme with the given name. If found, then replace + * its rules. */ - for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { - if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { - resPtr->cmdResProc = cmdProc; - resPtr->varResProc = varProc; - resPtr->compiledVarResProc = compiledVarProc; - return; - } + + for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + resPtr->cmdResProc = cmdProc; + resPtr->varResProc = varProc; + resPtr->compiledVarResProc = compiledVarProc; + return; + } } /* - * Otherwise, this is a new scheme. Add it to the FRONT - * of the linked list, so that it overrides existing schemes. + * Otherwise, this is a new scheme. Add it to the FRONT of the linked + * list, so that it overrides existing schemes. */ + resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme)); - resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1)); + resPtr->name = (char *) ckalloc((unsigned)(strlen(name) + 1)); strcpy(resPtr->name, name); resPtr->cmdResProc = cmdProc; resPtr->varResProc = varProc; @@ -121,15 +118,14 @@ Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc) * * Tcl_GetInterpResolvers -- * - * Looks for a set of command/variable resolution procedures with - * the given name in an interpreter. These procedures are - * registered by calling Tcl_AddInterpResolvers. + * Looks for a set of command/variable resolution functions with the + * given name in an interpreter. These functions are registered by + * calling Tcl_AddInterpResolvers. * * Results: - * If the name is recognized, this procedure returns non-zero, - * along with pointers to the name resolution procedures in - * the Tcl_ResolverInfo structure. If the name is not recognized, - * this procedure returns zero. + * If the name is recognized, this function returns non-zero, along with + * pointers to the name resolution functions in the Tcl_ResolverInfo + * structure. If the name is not recognized, this function returns zero. * * Side effects: * None. @@ -139,27 +135,27 @@ Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc) int Tcl_GetInterpResolvers(interp, name, resInfoPtr) - Tcl_Interp *interp; /* Interpreter whose name resolution * rules are being queried. */ - CONST char *name; /* Look for a scheme with this name. */ - Tcl_ResolverInfo *resInfoPtr; /* Returns pointers to the procedures, + CONST char *name; /* Look for a scheme with this name. */ + Tcl_ResolverInfo *resInfoPtr; /* Returns pointers to the functions, * if found */ { - Interp *iPtr = (Interp*)interp; + Interp *iPtr = (Interp *) interp; ResolverScheme *resPtr; /* - * Look for an existing scheme with the given name. If found, - * then return pointers to its procedures. + * Look for an existing scheme with the given name. If found, then return + * pointers to its functions. */ - for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { - if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + + for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { resInfoPtr->cmdResProc = resPtr->cmdResProc; resInfoPtr->varResProc = resPtr->varResProc; resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc; - return 1; - } + return 1; + } } return 0; @@ -170,68 +166,69 @@ Tcl_GetInterpResolvers(interp, name, resInfoPtr) * * Tcl_RemoveInterpResolvers -- * - * Removes a set of command/variable resolution procedures - * previously added by Tcl_AddInterpResolvers. The next time - * a command/variable name is resolved, these procedures - * won't be consulted. + * Removes a set of command/variable resolution functions previously + * added by Tcl_AddInterpResolvers. The next time a command/variable name + * is resolved, these functions won't be consulted. * * Results: - * Returns non-zero if the name was recognized and the - * resolution scheme was deleted. Returns zero otherwise. + * Returns non-zero if the name was recognized and the resolution scheme + * was deleted. Returns zero otherwise. * * Side effects: - * If a scheme with a compiledVarProc was deleted, this procedure - * bumps the compileEpoch for the interpreter, forcing all code - * to be recompiled. If a scheme with a cmdProc was deleted, - * this procedure bumps the cmdRefEpoch in all namespaces, - * forcing commands to be resolved again using the new rules. + * If a scheme with a compiledVarProc was deleted, this function bumps + * the compileEpoch for the interpreter, forcing all code to be + * recompiled. If a scheme with a cmdProc was deleted, this function + * bumps the cmdRefEpoch in all namespaces, forcing commands to be + * resolved again using the new rules. * *---------------------------------------------------------------------- */ int Tcl_RemoveInterpResolvers(interp, name) - Tcl_Interp *interp; /* Interpreter whose name resolution * rules are being modified. */ - CONST char *name; /* Name of the scheme to be removed. */ + CONST char *name; /* Name of the scheme to be removed. */ { - Interp *iPtr = (Interp*)interp; + Interp *iPtr = (Interp *) interp; ResolverScheme **prevPtrPtr, *resPtr; /* - * Look for an existing scheme with the given name. + * Look for an existing scheme with the given name. */ + prevPtrPtr = &iPtr->resolverPtr; - for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) { - if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { - break; - } - prevPtrPtr = &resPtr->nextPtr; + for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { + if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { + break; + } + prevPtrPtr = &resPtr->nextPtr; } /* - * If we found the scheme, delete it. + * If we found the scheme, delete it. */ + if (resPtr) { - /* - * If we're deleting a scheme with compiled variable resolution - * rules, bump the compiler epoch to invalidate compiled code. - * If we're deleting a scheme with command resolution rules, - * bump the cmdRefEpoch in all namespaces. - */ - if (resPtr->compiledVarResProc) { - iPtr->compileEpoch++; - } - if (resPtr->cmdResProc) { - BumpCmdRefEpochs(iPtr->globalNsPtr); - } - - *prevPtrPtr = resPtr->nextPtr; - ckfree(resPtr->name); - ckfree((char *) resPtr); - - return 1; + /* + * If we're deleting a scheme with compiled variable resolution rules, + * bump the compiler epoch to invalidate compiled code. If we're + * deleting a scheme with command resolution rules, bump the + * cmdRefEpoch in all namespaces. + */ + + if (resPtr->compiledVarResProc) { + iPtr->compileEpoch++; + } + if (resPtr->cmdResProc) { + BumpCmdRefEpochs(iPtr->globalNsPtr); + } + + *prevPtrPtr = resPtr->nextPtr; + ckfree(resPtr->name); + ckfree((char *) resPtr); + + return 1; } return 0; } @@ -241,17 +238,17 @@ Tcl_RemoveInterpResolvers(interp, name) * * BumpCmdRefEpochs -- * - * This procedure is used to bump the cmdRefEpoch counters in - * the specified namespace and all of its child namespaces. - * It is used whenever name resolution schemes are added/removed - * from an interpreter, to invalidate all command references. + * This function is used to bump the cmdRefEpoch counters in the + * specified namespace and all of its child namespaces. It is used + * whenever name resolution schemes are added/removed from an + * interpreter, to invalidate all command references. * * Results: * None. * * Side effects: - * Bumps the cmdRefEpoch in the specified namespace and its - * children, recursively. + * Bumps the cmdRefEpoch in the specified namespace and its children, + * recursively. * *---------------------------------------------------------------------- */ @@ -262,16 +259,13 @@ BumpCmdRefEpochs(nsPtr) { Tcl_HashEntry *entry; Tcl_HashSearch search; - Namespace *childNsPtr; nsPtr->cmdRefEpoch++; for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search); - entry != NULL; - entry = Tcl_NextHashEntry(&search)) { - - childNsPtr = (Namespace *) Tcl_GetHashValue(entry); - BumpCmdRefEpochs(childNsPtr); + entry != NULL; entry = Tcl_NextHashEntry(&search)) { + Namespace *childNsPtr = (Namespace *) Tcl_GetHashValue(entry); + BumpCmdRefEpochs(childNsPtr); } TclInvalidateNsPath(nsPtr); } @@ -281,66 +275,61 @@ BumpCmdRefEpochs(nsPtr) * * Tcl_SetNamespaceResolvers -- * - * Sets the command/variable resolution procedures for a namespace, - * thereby changing the way that command/variable names are - * interpreted. This allows extension writers to support different - * name resolution schemes, such as those for object-oriented - * packages. - * - * Command resolution is handled by a procedure of the following - * type: - * - * typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_(( - * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context, - * int flags, Tcl_Command *rPtr)); - * - * Whenever a command is executed or Tcl_FindCommand is invoked - * within the namespace, this procedure is called to resolve the - * command name. If this procedure is able to resolve the name, - * it should return the status code TCL_OK, along with the - * corresponding Tcl_Command in the rPtr argument. Otherwise, - * the procedure can return TCL_CONTINUE, and the command will - * be treated under the usual name resolution rules. Or, it can - * return TCL_ERROR, and the command will be considered invalid. - * - * Variable resolution is handled by two procedures. The first - * is called whenever a variable needs to be resolved at compile - * time: - * - * typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_(( - * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context, - * Tcl_ResolvedVarInfo *rPtr)); - * - * If this procedure is able to resolve the name, it should return - * the status code TCL_OK, along with variable resolution info in - * the rPtr argument; this info will be used to set up compiled - * locals in the call frame at runtime. The procedure may also - * return TCL_CONTINUE, and the variable will be treated under - * the usual name resolution rules. Or, it can return TCL_ERROR, - * and the variable will be considered invalid. - * - * Another procedure is used whenever a variable needs to be - * resolved at runtime but it is not recognized as a compiled local. - * (For example, the variable may be requested via - * Tcl_FindNamespaceVar.) This procedure has the following type: - * - * typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_(( - * Tcl_Interp* interp, CONST char* name, Tcl_Namespace *context, - * int flags, Tcl_Var *rPtr)); - * - * This procedure is quite similar to the compile-time version. - * It returns the same status codes, but if variable resolution - * succeeds, this procedure returns a Tcl_Var directly via the - * rPtr argument. + * Sets the command/variable resolution functions for a namespace, + * thereby changing the way that command/variable names are interpreted. + * This allows extension writers to support different name resolution + * schemes, such as those for object-oriented packages. + * + * Command resolution is handled by a function of the following type: + * + * typedef int (*Tcl_ResolveCmdProc)(Tcl_Interp *interp, + * CONST char *name, Tcl_Namespace *context, + * int flags, Tcl_Command *rPtr); + * + * Whenever a command is executed or Tcl_FindCommand is invoked within + * the namespace, this function is called to resolve the command name. + * If this function is able to resolve the name, it should return the + * status code TCL_OK, along with the corresponding Tcl_Command in the + * rPtr argument. Otherwise, the function can return TCL_CONTINUE, and + * the command will be treated under the usual name resolution rules. + * Or, it can return TCL_ERROR, and the command will be considered + * invalid. + * + * Variable resolution is handled by two functions. The first is called + * whenever a variable needs to be resolved at compile time: + * + * typedef int (*Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp, + * CONST char *name, Tcl_Namespace *context, + * Tcl_ResolvedVarInfo *rPtr); + * + * If this function is able to resolve the name, it should return the + * status code TCL_OK, along with variable resolution info in the rPtr + * argument; this info will be used to set up compiled locals in the call + * frame at runtime. The function may also return TCL_CONTINUE, and the + * variable will be treated under the usual name resolution rules. Or, it + * can return TCL_ERROR, and the variable will be considered invalid. + * + * Another function is used whenever a variable needs to be resolved at + * runtime but it is not recognized as a compiled local. (For example, + * the variable may be requested via Tcl_FindNamespaceVar.) This function + * has the following type: + * + * typedef int (*Tcl_ResolveVarProc)(Tcl_Interp *interp, + * CONST char *name, Tcl_Namespace *context, + * int flags, Tcl_Var *rPtr); + * + * This function is quite similar to the compile-time version. It returns + * the same status codes, but if variable resolution succeeds, this + * function returns a Tcl_Var directly via the rPtr argument. * * Results: * Nothing. * * Side effects: - * Bumps the command epoch counter for the namespace, invalidating - * all command references in that namespace. Also bumps the - * resolver epoch counter for the namespace, forcing all code - * in the namespace to be recompiled. + * Bumps the command epoch counter for the namespace, invalidating all + * command references in that namespace. Also bumps the resolver epoch + * counter for the namespace, forcing all code in the namespace to be + * recompiled. * *---------------------------------------------------------------------- */ @@ -349,20 +338,21 @@ void Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc) Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules * are being modified. */ - Tcl_ResolveCmdProc *cmdProc; /* Procedure for command resolution */ - Tcl_ResolveVarProc *varProc; /* Procedure for variable resolution - * at runtime */ + Tcl_ResolveCmdProc *cmdProc; /* Function for command resolution */ + Tcl_ResolveVarProc *varProc; /* Function for variable resolution at + * run-time */ Tcl_ResolveCompiledVarProc *compiledVarProc; - /* Procedure for variable resolution - * at compile time. */ + /* Function for variable resolution at + * compile time. */ { - Namespace *nsPtr = (Namespace*)namespacePtr; + Namespace *nsPtr = (Namespace *) namespacePtr; /* - * Plug in the new command resolver, and bump the epoch counters - * so that all code will have to be recompiled and all commands - * will have to be resolved again using the new policy. + * Plug in the new command resolver, and bump the epoch counters so that + * all code will have to be recompiled and all commands will have to be + * resolved again using the new policy. */ + nsPtr->cmdResProc = cmdProc; nsPtr->varResProc = varProc; nsPtr->compiledVarResProc = compiledVarProc; @@ -377,17 +367,15 @@ Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc) * * Tcl_GetNamespaceResolvers -- * - * Returns the current command/variable resolution procedures - * for a namespace. By default, these procedures are NULL. - * New procedures can be installed by calling - * Tcl_SetNamespaceResolvers, to provide new name resolution - * rules. + * Returns the current command/variable resolution functions for a + * namespace. By default, these functions are NULL. New functions can be + * installed by calling Tcl_SetNamespaceResolvers, to provide new name + * resolution rules. * * Results: - * Returns non-zero if any name resolution procedures have been - * assigned to this namespace; also returns pointers to the - * procedures in the Tcl_ResolverInfo structure. Returns zero - * otherwise. + * Returns non-zero if any name resolution functions have been assigned + * to this namespace; also returns pointers to the functions in the + * Tcl_ResolverInfo structure. Returns zero otherwise. * * Side effects: * None. @@ -397,22 +385,20 @@ Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc) int Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr) - Tcl_Namespace *namespacePtr; /* Namespace whose resolution rules * are being modified. */ - Tcl_ResolverInfo *resInfoPtr; /* Returns: pointers for all - * name resolution procedures - * assigned to this namespace. */ + Tcl_ResolverInfo *resInfoPtr; /* Returns: pointers for all name + * resolution functions assigned to + * this namespace. */ { - Namespace *nsPtr = (Namespace*)namespacePtr; + Namespace *nsPtr = (Namespace *) namespacePtr; resInfoPtr->cmdResProc = nsPtr->cmdResProc; resInfoPtr->varResProc = nsPtr->varResProc; resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc; - if (nsPtr->cmdResProc != NULL || - nsPtr->varResProc != NULL || - nsPtr->compiledVarResProc != NULL) { + if (nsPtr->cmdResProc != NULL || nsPtr->varResProc != NULL || + nsPtr->compiledVarResProc != NULL) { return 1; } return 0; |