tclResolve.cGo to the documentation of this file.00001 /* 00002 * tclResolve.c -- 00003 * 00004 * Contains hooks for customized command/variable name resolution 00005 * schemes. These hooks allow extensions like [incr Tcl] to add their own 00006 * name resolution rules to the Tcl language. Rules can be applied to a 00007 * particular namespace, to the interpreter as a whole, or both. 00008 * 00009 * Copyright (c) 1998 Lucent Technologies, Inc. 00010 * 00011 * See the file "license.terms" for information on usage and redistribution of 00012 * this file, and for a DISCLAIMER OF ALL WARRANTIES. 00013 * 00014 * RCS: @(#) $Id: tclResolve.c,v 1.9 2007/04/05 13:20:49 dkf Exp $ 00015 */ 00016 00017 #include "tclInt.h" 00018 00019 /* 00020 * Declarations for functions local to this file: 00021 */ 00022 00023 static void BumpCmdRefEpochs(Namespace *nsPtr); 00024 00025 /* 00026 *---------------------------------------------------------------------- 00027 * 00028 * Tcl_AddInterpResolvers -- 00029 * 00030 * Adds a set of command/variable resolution functions to an interpreter. 00031 * These functions are consulted when commands are resolved in 00032 * Tcl_FindCommand, and when variables are resolved in TclLookupVar and 00033 * LookupCompiledLocal. Each namespace may also have its own set of 00034 * resolution functions which take precedence over those for the 00035 * interpreter. 00036 * 00037 * When a name is resolved, it is handled as follows. First, the name is 00038 * passed to the resolution functions for the namespace. If not resolved, 00039 * the name is passed to each of the resolution functions added to the 00040 * interpreter. Finally, if still not resolved, the name is handled using 00041 * the default Tcl rules for name resolution. 00042 * 00043 * Results: 00044 * Returns pointers to the current name resolution functions in the 00045 * cmdProcPtr, varProcPtr and compiledVarProcPtr arguments. 00046 * 00047 * Side effects: 00048 * If a compiledVarProc is specified, this function bumps the 00049 * compileEpoch for the interpreter, forcing all code to be recompiled. 00050 * If a cmdProc is specified, this function bumps the cmdRefEpoch in all 00051 * namespaces, forcing commands to be resolved again using the new rules. 00052 * 00053 *---------------------------------------------------------------------- 00054 */ 00055 00056 void 00057 Tcl_AddInterpResolvers( 00058 Tcl_Interp *interp, /* Interpreter whose name resolution rules are 00059 * being modified. */ 00060 CONST char *name, /* Name of this resolution scheme. */ 00061 Tcl_ResolveCmdProc *cmdProc,/* New function for command resolution. */ 00062 Tcl_ResolveVarProc *varProc,/* Function for variable resolution at 00063 * runtime. */ 00064 Tcl_ResolveCompiledVarProc *compiledVarProc) 00065 /* Function for variable resolution at compile 00066 * time. */ 00067 { 00068 Interp *iPtr = (Interp *) interp; 00069 ResolverScheme *resPtr; 00070 00071 /* 00072 * Since we're adding a new name resolution scheme, we must force all code 00073 * to be recompiled to use the new scheme. If there are new compiled 00074 * variable resolution rules, bump the compiler epoch to invalidate 00075 * compiled code. If there are new command resolution rules, bump the 00076 * cmdRefEpoch in all namespaces. 00077 */ 00078 00079 if (compiledVarProc) { 00080 iPtr->compileEpoch++; 00081 } 00082 if (cmdProc) { 00083 BumpCmdRefEpochs(iPtr->globalNsPtr); 00084 } 00085 00086 /* 00087 * Look for an existing scheme with the given name. If found, then replace 00088 * its rules. 00089 */ 00090 00091 for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { 00092 if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { 00093 resPtr->cmdResProc = cmdProc; 00094 resPtr->varResProc = varProc; 00095 resPtr->compiledVarResProc = compiledVarProc; 00096 return; 00097 } 00098 } 00099 00100 /* 00101 * Otherwise, this is a new scheme. Add it to the FRONT of the linked 00102 * list, so that it overrides existing schemes. 00103 */ 00104 00105 resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme)); 00106 resPtr->name = (char *) ckalloc((unsigned)(strlen(name) + 1)); 00107 strcpy(resPtr->name, name); 00108 resPtr->cmdResProc = cmdProc; 00109 resPtr->varResProc = varProc; 00110 resPtr->compiledVarResProc = compiledVarProc; 00111 resPtr->nextPtr = iPtr->resolverPtr; 00112 iPtr->resolverPtr = resPtr; 00113 } 00114 00115 /* 00116 *---------------------------------------------------------------------- 00117 * 00118 * Tcl_GetInterpResolvers -- 00119 * 00120 * Looks for a set of command/variable resolution functions with the 00121 * given name in an interpreter. These functions are registered by 00122 * calling Tcl_AddInterpResolvers. 00123 * 00124 * Results: 00125 * If the name is recognized, this function returns non-zero, along with 00126 * pointers to the name resolution functions in the Tcl_ResolverInfo 00127 * structure. If the name is not recognized, this function returns zero. 00128 * 00129 * Side effects: 00130 * None. 00131 * 00132 *---------------------------------------------------------------------- 00133 */ 00134 00135 int 00136 Tcl_GetInterpResolvers( 00137 Tcl_Interp *interp, /* Interpreter whose name resolution rules are 00138 * being queried. */ 00139 CONST char *name, /* Look for a scheme with this name. */ 00140 Tcl_ResolverInfo *resInfoPtr) 00141 /* Returns pointers to the functions, if 00142 * found */ 00143 { 00144 Interp *iPtr = (Interp *) interp; 00145 ResolverScheme *resPtr; 00146 00147 /* 00148 * Look for an existing scheme with the given name. If found, then return 00149 * pointers to its functions. 00150 */ 00151 00152 for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { 00153 if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { 00154 resInfoPtr->cmdResProc = resPtr->cmdResProc; 00155 resInfoPtr->varResProc = resPtr->varResProc; 00156 resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc; 00157 return 1; 00158 } 00159 } 00160 00161 return 0; 00162 } 00163 00164 /* 00165 *---------------------------------------------------------------------- 00166 * 00167 * Tcl_RemoveInterpResolvers -- 00168 * 00169 * Removes a set of command/variable resolution functions previously 00170 * added by Tcl_AddInterpResolvers. The next time a command/variable name 00171 * is resolved, these functions won't be consulted. 00172 * 00173 * Results: 00174 * Returns non-zero if the name was recognized and the resolution scheme 00175 * was deleted. Returns zero otherwise. 00176 * 00177 * Side effects: 00178 * If a scheme with a compiledVarProc was deleted, this function bumps 00179 * the compileEpoch for the interpreter, forcing all code to be 00180 * recompiled. If a scheme with a cmdProc was deleted, this function 00181 * bumps the cmdRefEpoch in all namespaces, forcing commands to be 00182 * resolved again using the new rules. 00183 * 00184 *---------------------------------------------------------------------- 00185 */ 00186 00187 int 00188 Tcl_RemoveInterpResolvers( 00189 Tcl_Interp *interp, /* Interpreter whose name resolution rules are 00190 * being modified. */ 00191 CONST char *name) /* Name of the scheme to be removed. */ 00192 { 00193 Interp *iPtr = (Interp *) interp; 00194 ResolverScheme **prevPtrPtr, *resPtr; 00195 00196 /* 00197 * Look for an existing scheme with the given name. 00198 */ 00199 00200 prevPtrPtr = &iPtr->resolverPtr; 00201 for (resPtr=iPtr->resolverPtr ; resPtr!=NULL ; resPtr=resPtr->nextPtr) { 00202 if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) { 00203 break; 00204 } 00205 prevPtrPtr = &resPtr->nextPtr; 00206 } 00207 00208 /* 00209 * If we found the scheme, delete it. 00210 */ 00211 00212 if (resPtr) { 00213 /* 00214 * If we're deleting a scheme with compiled variable resolution rules, 00215 * bump the compiler epoch to invalidate compiled code. If we're 00216 * deleting a scheme with command resolution rules, bump the 00217 * cmdRefEpoch in all namespaces. 00218 */ 00219 00220 if (resPtr->compiledVarResProc) { 00221 iPtr->compileEpoch++; 00222 } 00223 if (resPtr->cmdResProc) { 00224 BumpCmdRefEpochs(iPtr->globalNsPtr); 00225 } 00226 00227 *prevPtrPtr = resPtr->nextPtr; 00228 ckfree(resPtr->name); 00229 ckfree((char *) resPtr); 00230 00231 return 1; 00232 } 00233 return 0; 00234 } 00235 00236 /* 00237 *---------------------------------------------------------------------- 00238 * 00239 * BumpCmdRefEpochs -- 00240 * 00241 * This function is used to bump the cmdRefEpoch counters in the 00242 * specified namespace and all of its child namespaces. It is used 00243 * whenever name resolution schemes are added/removed from an 00244 * interpreter, to invalidate all command references. 00245 * 00246 * Results: 00247 * None. 00248 * 00249 * Side effects: 00250 * Bumps the cmdRefEpoch in the specified namespace and its children, 00251 * recursively. 00252 * 00253 *---------------------------------------------------------------------- 00254 */ 00255 00256 static void 00257 BumpCmdRefEpochs( 00258 Namespace *nsPtr) /* Namespace being modified. */ 00259 { 00260 Tcl_HashEntry *entry; 00261 Tcl_HashSearch search; 00262 00263 nsPtr->cmdRefEpoch++; 00264 00265 for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search); 00266 entry != NULL; entry = Tcl_NextHashEntry(&search)) { 00267 Namespace *childNsPtr = (Namespace *) Tcl_GetHashValue(entry); 00268 BumpCmdRefEpochs(childNsPtr); 00269 } 00270 TclInvalidateNsPath(nsPtr); 00271 } 00272 00273 /* 00274 *---------------------------------------------------------------------- 00275 * 00276 * Tcl_SetNamespaceResolvers -- 00277 * 00278 * Sets the command/variable resolution functions for a namespace, 00279 * thereby changing the way that command/variable names are interpreted. 00280 * This allows extension writers to support different name resolution 00281 * schemes, such as those for object-oriented packages. 00282 * 00283 * Command resolution is handled by a function of the following type: 00284 * 00285 * typedef int (*Tcl_ResolveCmdProc)(Tcl_Interp *interp, 00286 * CONST char *name, Tcl_Namespace *context, 00287 * int flags, Tcl_Command *rPtr); 00288 * 00289 * Whenever a command is executed or Tcl_FindCommand is invoked within 00290 * the namespace, this function is called to resolve the command name. If 00291 * this function is able to resolve the name, it should return the status 00292 * code TCL_OK, along with the corresponding Tcl_Command in the rPtr 00293 * argument. Otherwise, the function can return TCL_CONTINUE, and the 00294 * command will be treated under the usual name resolution rules. Or, it 00295 * can return TCL_ERROR, and the command will be considered invalid. 00296 * 00297 * Variable resolution is handled by two functions. The first is called 00298 * whenever a variable needs to be resolved at compile time: 00299 * 00300 * typedef int (*Tcl_ResolveCompiledVarProc)(Tcl_Interp *interp, 00301 * CONST char *name, Tcl_Namespace *context, 00302 * Tcl_ResolvedVarInfo *rPtr); 00303 * 00304 * If this function is able to resolve the name, it should return the 00305 * status code TCL_OK, along with variable resolution info in the rPtr 00306 * argument; this info will be used to set up compiled locals in the call 00307 * frame at runtime. The function may also return TCL_CONTINUE, and the 00308 * variable will be treated under the usual name resolution rules. Or, it 00309 * can return TCL_ERROR, and the variable will be considered invalid. 00310 * 00311 * Another function is used whenever a variable needs to be resolved at 00312 * runtime but it is not recognized as a compiled local. (For example, 00313 * the variable may be requested via Tcl_FindNamespaceVar.) This function 00314 * has the following type: 00315 * 00316 * typedef int (*Tcl_ResolveVarProc)(Tcl_Interp *interp, 00317 * CONST char *name, Tcl_Namespace *context, 00318 * int flags, Tcl_Var *rPtr); 00319 * 00320 * This function is quite similar to the compile-time version. It returns 00321 * the same status codes, but if variable resolution succeeds, this 00322 * function returns a Tcl_Var directly via the rPtr argument. 00323 * 00324 * Results: 00325 * Nothing. 00326 * 00327 * Side effects: 00328 * Bumps the command epoch counter for the namespace, invalidating all 00329 * command references in that namespace. Also bumps the resolver epoch 00330 * counter for the namespace, forcing all code in the namespace to be 00331 * recompiled. 00332 * 00333 *---------------------------------------------------------------------- 00334 */ 00335 00336 void 00337 Tcl_SetNamespaceResolvers( 00338 Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being 00339 * modified. */ 00340 Tcl_ResolveCmdProc *cmdProc,/* Function for command resolution */ 00341 Tcl_ResolveVarProc *varProc,/* Function for variable resolution at 00342 * run-time */ 00343 Tcl_ResolveCompiledVarProc *compiledVarProc) 00344 /* Function for variable resolution at compile 00345 * time. */ 00346 { 00347 Namespace *nsPtr = (Namespace *) namespacePtr; 00348 00349 /* 00350 * Plug in the new command resolver, and bump the epoch counters so that 00351 * all code will have to be recompiled and all commands will have to be 00352 * resolved again using the new policy. 00353 */ 00354 00355 nsPtr->cmdResProc = cmdProc; 00356 nsPtr->varResProc = varProc; 00357 nsPtr->compiledVarResProc = compiledVarProc; 00358 00359 nsPtr->cmdRefEpoch++; 00360 nsPtr->resolverEpoch++; 00361 TclInvalidateNsPath(nsPtr); 00362 } 00363 00364 /* 00365 *---------------------------------------------------------------------- 00366 * 00367 * Tcl_GetNamespaceResolvers -- 00368 * 00369 * Returns the current command/variable resolution functions for a 00370 * namespace. By default, these functions are NULL. New functions can be 00371 * installed by calling Tcl_SetNamespaceResolvers, to provide new name 00372 * resolution rules. 00373 * 00374 * Results: 00375 * Returns non-zero if any name resolution functions have been assigned 00376 * to this namespace; also returns pointers to the functions in the 00377 * Tcl_ResolverInfo structure. Returns zero otherwise. 00378 * 00379 * Side effects: 00380 * None. 00381 * 00382 *---------------------------------------------------------------------- 00383 */ 00384 00385 int 00386 Tcl_GetNamespaceResolvers( 00387 Tcl_Namespace *namespacePtr,/* Namespace whose resolution rules are being 00388 * modified. */ 00389 Tcl_ResolverInfo *resInfoPtr) 00390 /* Returns: pointers for all name resolution 00391 * functions assigned to this namespace. */ 00392 { 00393 Namespace *nsPtr = (Namespace *) namespacePtr; 00394 00395 resInfoPtr->cmdResProc = nsPtr->cmdResProc; 00396 resInfoPtr->varResProc = nsPtr->varResProc; 00397 resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc; 00398 00399 if (nsPtr->cmdResProc != NULL || nsPtr->varResProc != NULL || 00400 nsPtr->compiledVarResProc != NULL) { 00401 return 1; 00402 } 00403 return 0; 00404 } 00405 00406 /* 00407 * Local Variables: 00408 * mode: c 00409 * c-basic-offset: 4 00410 * fill-column: 78 00411 * End: 00412 */
Generated on Wed Mar 12 12:18:21 2008 by ![]() |