source: HiSusy/trunk/Delphes/Delphes-3.0.9/external/tcl/tclResolve.c @ 5

Last change on this file since 5 was 5, checked in by zerwas, 11 years ago

update to Delphes-3.0.9

File size: 13.7 KB
Line 
1/*
2 * tclResolve.c --
3 *
4 *      Contains hooks for customized command/variable name resolution
5 *      schemes.  These hooks allow extensions like [incr Tcl] to add
6 *      their own name resolution rules to the Tcl language.  Rules can
7 *      be applied to a particular namespace, to the interpreter as a
8 *      whole, or both.
9 *
10 * Copyright (c) 1998 Lucent Technologies, Inc.
11 *
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
14 *
15 * RCS: @(#) $Id: tclResolve.c,v 1.1 2008-06-04 13:58:10 demin Exp $
16 */
17
18#include "tclInt.h"
19
20/*
21 * Declarations for procedures local to this file:
22 */
23
24static void             BumpCmdRefEpochs _ANSI_ARGS_((Namespace *nsPtr));
25
26
27/*
28 *----------------------------------------------------------------------
29 *
30 * Tcl_AddInterpResolvers --
31 *
32 *      Adds a set of command/variable resolution procedures to an
33 *      interpreter.  These procedures are consulted when commands
34 *      are resolved in Tcl_FindCommand, and when variables are
35 *      resolved in TclLookupVar and LookupCompiledLocal.  Each
36 *      namespace may also have its own set of resolution procedures
37 *      which take precedence over those for the interpreter.
38 *
39 *      When a name is resolved, it is handled as follows.  First,
40 *      the name is passed to the resolution procedures for the
41 *      namespace.  If not resolved, the name is passed to each of
42 *      the resolution procedures added to the interpreter.  Finally,
43 *      if still not resolved, the name is handled using the default
44 *      Tcl rules for name resolution.
45 *
46 * Results:
47 *      Returns pointers to the current name resolution procedures
48 *      in the cmdProcPtr, varProcPtr and compiledVarProcPtr
49 *      arguments.
50 *
51 * Side effects:
52 *      If a compiledVarProc is specified, this procedure bumps the
53 *      compileEpoch for the interpreter, forcing all code to be
54 *      recompiled.  If a cmdProc is specified, this procedure bumps
55 *      the cmdRefEpoch in all namespaces, forcing commands to be
56 *      resolved again using the new rules.
57 *
58 *----------------------------------------------------------------------
59 */
60
61void
62Tcl_AddInterpResolvers(interp, name, cmdProc, varProc, compiledVarProc)
63
64    Tcl_Interp *interp;                 /* Interpreter whose name resolution
65                                         * rules are being modified. */
66    char *name;                         /* Name of this resolution scheme. */
67    Tcl_ResolveCmdProc *cmdProc;        /* New procedure for command
68                                         * resolution */
69    Tcl_ResolveVarProc *varProc;        /* Procedure for variable resolution
70                                         * at runtime */
71    Tcl_ResolveCompiledVarProc *compiledVarProc;
72                                        /* Procedure for variable resolution
73                                         * at compile time. */
74{
75    Interp *iPtr = (Interp*)interp;
76    ResolverScheme *resPtr;
77
78    /*
79     *  Since we're adding a new name resolution scheme, we must force
80     *  all code to be recompiled to use the new scheme.  If there
81     *  are new compiled variable resolution rules, bump the compiler
82     *  epoch to invalidate compiled code.  If there are new command
83     *  resolution rules, bump the cmdRefEpoch in all namespaces.
84     */
85    if (compiledVarProc) {
86        iPtr->compileEpoch++;
87    }
88    if (cmdProc) {
89        BumpCmdRefEpochs(iPtr->globalNsPtr);
90    }
91
92    /*
93     *  Look for an existing scheme with the given name.  If found,
94     *  then replace its rules.
95     */
96    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
97        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
98            resPtr->cmdResProc = cmdProc;
99            resPtr->varResProc = varProc;
100            resPtr->compiledVarResProc = compiledVarProc;
101            return;
102        }
103    }
104
105    /*
106     *  Otherwise, this is a new scheme.  Add it to the FRONT
107     *  of the linked list, so that it overrides existing schemes.
108     */
109    resPtr = (ResolverScheme *) ckalloc(sizeof(ResolverScheme));
110    resPtr->name = (char*)ckalloc((unsigned)(strlen(name)+1));
111    strcpy(resPtr->name, name);
112    resPtr->cmdResProc = cmdProc;
113    resPtr->varResProc = varProc;
114    resPtr->compiledVarResProc = compiledVarProc;
115    resPtr->nextPtr = iPtr->resolverPtr;
116    iPtr->resolverPtr = resPtr;
117}
118
119/*
120 *----------------------------------------------------------------------
121 *
122 * Tcl_GetInterpResolvers --
123 *
124 *      Looks for a set of command/variable resolution procedures with
125 *      the given name in an interpreter.  These procedures are
126 *      registered by calling Tcl_AddInterpResolvers.
127 *
128 * Results:
129 *      If the name is recognized, this procedure returns non-zero,
130 *      along with pointers to the name resolution procedures in
131 *      the Tcl_ResolverInfo structure.  If the name is not recognized,
132 *      this procedure returns zero.
133 *
134 * Side effects:
135 *      None.
136 *
137 *----------------------------------------------------------------------
138 */
139
140int
141Tcl_GetInterpResolvers(interp, name, resInfoPtr)
142
143    Tcl_Interp *interp;                 /* Interpreter whose name resolution
144                                         * rules are being queried. */
145    char *name;                         /* Look for a scheme with this name. */
146    Tcl_ResolverInfo *resInfoPtr;       /* Returns pointers to the procedures,
147                                         * if found */
148{
149    Interp *iPtr = (Interp*)interp;
150    ResolverScheme *resPtr;
151
152    /*
153     *  Look for an existing scheme with the given name.  If found,
154     *  then return pointers to its procedures.
155     */
156    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
157        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
158            resInfoPtr->cmdResProc = resPtr->cmdResProc;
159            resInfoPtr->varResProc = resPtr->varResProc;
160            resInfoPtr->compiledVarResProc = resPtr->compiledVarResProc;
161            return 1;
162        }
163    }
164
165    return 0;
166}
167
168/*
169 *----------------------------------------------------------------------
170 *
171 * Tcl_RemoveInterpResolvers --
172 *
173 *      Removes a set of command/variable resolution procedures
174 *      previously added by Tcl_AddInterpResolvers.  The next time
175 *      a command/variable name is resolved, these procedures
176 *      won't be consulted.
177 *
178 * Results:
179 *      Returns non-zero if the name was recognized and the
180 *      resolution scheme was deleted.  Returns zero otherwise.
181 *
182 * Side effects:
183 *      If a scheme with a compiledVarProc was deleted, this procedure
184 *      bumps the compileEpoch for the interpreter, forcing all code
185 *      to be recompiled.  If a scheme with a cmdProc was deleted,
186 *      this procedure bumps the cmdRefEpoch in all namespaces,
187 *      forcing commands to be resolved again using the new rules.
188 *
189 *----------------------------------------------------------------------
190 */
191
192int
193Tcl_RemoveInterpResolvers(interp, name)
194
195    Tcl_Interp *interp;                 /* Interpreter whose name resolution
196                                         * rules are being modified. */
197    char *name;                         /* Name of the scheme to be removed. */
198{
199    Interp *iPtr = (Interp*)interp;
200    ResolverScheme **prevPtrPtr, *resPtr;
201
202    /*
203     *  Look for an existing scheme with the given name.
204     */
205    prevPtrPtr = &iPtr->resolverPtr;
206    for (resPtr = iPtr->resolverPtr; resPtr != NULL; resPtr = resPtr->nextPtr) {
207        if (*name == *resPtr->name && strcmp(name, resPtr->name) == 0) {
208            break;
209        }
210        prevPtrPtr = &resPtr->nextPtr;
211    }
212
213    /*
214     *  If we found the scheme, delete it.
215     */
216    if (resPtr) {
217        /*
218         *  If we're deleting a scheme with compiled variable resolution
219         *  rules, bump the compiler epoch to invalidate compiled code.
220         *  If we're deleting a scheme with command resolution rules,
221         *  bump the cmdRefEpoch in all namespaces.
222         */
223        if (resPtr->compiledVarResProc) {
224            iPtr->compileEpoch++;
225        }
226        if (resPtr->cmdResProc) {
227            BumpCmdRefEpochs(iPtr->globalNsPtr);
228        }
229
230        *prevPtrPtr = resPtr->nextPtr;
231        ckfree(resPtr->name);
232        ckfree((char *) resPtr);
233
234        return 1;
235    }
236    return 0;
237}
238
239/*
240 *----------------------------------------------------------------------
241 *
242 * BumpCmdRefEpochs --
243 *
244 *      This procedure is used to bump the cmdRefEpoch counters in
245 *      the specified namespace and all of its child namespaces.
246 *      It is used whenever name resolution schemes are added/removed
247 *      from an interpreter, to invalidate all command references.
248 *
249 * Results:
250 *      None.
251 *
252 * Side effects:
253 *      Bumps the cmdRefEpoch in the specified namespace and its
254 *      children, recursively.
255 *
256 *----------------------------------------------------------------------
257 */
258
259static void
260BumpCmdRefEpochs(nsPtr)
261    Namespace *nsPtr;                   /* Namespace being modified. */
262{
263    Tcl_HashEntry *entry;
264    Tcl_HashSearch search;
265    Namespace *childNsPtr;
266
267    nsPtr->cmdRefEpoch++;
268
269    for (entry = Tcl_FirstHashEntry(&nsPtr->childTable, &search);
270            entry != NULL;
271            entry = Tcl_NextHashEntry(&search)) {
272
273        childNsPtr = (Namespace *) Tcl_GetHashValue(entry);
274        BumpCmdRefEpochs(childNsPtr);
275    }
276}
277
278
279/*
280 *----------------------------------------------------------------------
281 *
282 * Tcl_SetNamespaceResolvers --
283 *
284 *      Sets the command/variable resolution procedures for a namespace,
285 *      thereby changing the way that command/variable names are
286 *      interpreted.  This allows extension writers to support different
287 *      name resolution schemes, such as those for object-oriented
288 *      packages.
289 *
290 *      Command resolution is handled by a procedure of the following
291 *      type:
292 *
293 *        typedef int (Tcl_ResolveCmdProc) _ANSI_ARGS_((
294 *              Tcl_Interp* interp, char* name, Tcl_Namespace *context,
295 *              int flags, Tcl_Command *rPtr));
296 *         
297 *      Whenever a command is executed or Tcl_FindCommand is invoked
298 *      within the namespace, this procedure is called to resolve the
299 *      command name.  If this procedure is able to resolve the name,
300 *      it should return the status code TCL_OK, along with the
301 *      corresponding Tcl_Command in the rPtr argument.  Otherwise,
302 *      the procedure can return TCL_CONTINUE, and the command will
303 *      be treated under the usual name resolution rules.  Or, it can
304 *      return TCL_ERROR, and the command will be considered invalid.
305 *
306 *      Variable resolution is handled by two procedures.  The first
307 *      is called whenever a variable needs to be resolved at compile
308 *      time:
309 *
310 *        typedef int (Tcl_ResolveCompiledVarProc) _ANSI_ARGS_((
311 *              Tcl_Interp* interp, char* name, Tcl_Namespace *context,
312 *              Tcl_ResolvedVarInfo *rPtr));
313 *
314 *      If this procedure is able to resolve the name, it should return
315 *      the status code TCL_OK, along with variable resolution info in
316 *      the rPtr argument; this info will be used to set up compiled
317 *      locals in the call frame at runtime.  The procedure may also
318 *      return TCL_CONTINUE, and the variable will be treated under
319 *      the usual name resolution rules.  Or, it can return TCL_ERROR,
320 *      and the variable will be considered invalid.
321 *
322 *      Another procedure is used whenever a variable needs to be
323 *      resolved at runtime but it is not recognized as a compiled local.
324 *      (For example, the variable may be requested via
325 *      Tcl_FindNamespaceVar.) This procedure has the following type:
326 *
327 *        typedef int (Tcl_ResolveVarProc) _ANSI_ARGS_((
328 *              Tcl_Interp* interp, char* name, Tcl_Namespace *context,
329 *              int flags, Tcl_Var *rPtr));
330 *
331 *      This procedure is quite similar to the compile-time version.
332 *      It returns the same status codes, but if variable resolution
333 *      succeeds, this procedure returns a Tcl_Var directly via the
334 *      rPtr argument.
335 *
336 * Results:
337 *      Nothing.
338 *
339 * Side effects:
340 *      Bumps the command epoch counter for the namespace, invalidating
341 *      all command references in that namespace.  Also bumps the
342 *      resolver epoch counter for the namespace, forcing all code
343 *      in the namespace to be recompiled.
344 *
345 *----------------------------------------------------------------------
346 */
347
348void
349Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc)
350    Tcl_Namespace *namespacePtr;        /* Namespace whose resolution rules
351                                         * are being modified. */
352    Tcl_ResolveCmdProc *cmdProc;        /* Procedure for command resolution */
353    Tcl_ResolveVarProc *varProc;        /* Procedure for variable resolution
354                                         * at runtime */
355    Tcl_ResolveCompiledVarProc *compiledVarProc;
356                                        /* Procedure for variable resolution
357                                         * at compile time. */
358{
359    Namespace *nsPtr = (Namespace*)namespacePtr;
360
361    /*
362     *  Plug in the new command resolver, and bump the epoch counters
363     *  so that all code will have to be recompiled and all commands
364     *  will have to be resolved again using the new policy.
365     */
366    nsPtr->cmdResProc = cmdProc;
367    nsPtr->varResProc = varProc;
368    nsPtr->compiledVarResProc = compiledVarProc;
369
370    nsPtr->cmdRefEpoch++;
371    nsPtr->resolverEpoch++;
372}
373
374/*
375 *----------------------------------------------------------------------
376 *
377 * Tcl_GetNamespaceResolvers --
378 *
379 *      Returns the current command/variable resolution procedures
380 *      for a namespace.  By default, these procedures are NULL.
381 *      New procedures can be installed by calling
382 *      Tcl_SetNamespaceResolvers, to provide new name resolution
383 *      rules.
384 *
385 * Results:
386 *      Returns non-zero if any name resolution procedures have been
387 *      assigned to this namespace; also returns pointers to the
388 *      procedures in the Tcl_ResolverInfo structure.  Returns zero
389 *      otherwise.
390 *
391 * Side effects:
392 *      None.
393 *
394 *----------------------------------------------------------------------
395 */
396
397int
398Tcl_GetNamespaceResolvers(namespacePtr, resInfoPtr)
399
400    Tcl_Namespace *namespacePtr;        /* Namespace whose resolution rules
401                                         * are being modified. */
402    Tcl_ResolverInfo *resInfoPtr;       /* Returns: pointers for all
403                                         * name resolution procedures
404                                         * assigned to this namespace. */
405{
406    Namespace *nsPtr = (Namespace*)namespacePtr;
407
408    resInfoPtr->cmdResProc = nsPtr->cmdResProc;
409    resInfoPtr->varResProc = nsPtr->varResProc;
410    resInfoPtr->compiledVarResProc = nsPtr->compiledVarResProc;
411
412    if (nsPtr->cmdResProc != NULL ||
413        nsPtr->varResProc != NULL ||
414        nsPtr->compiledVarResProc != NULL) {
415        return 1;
416    }
417    return 0;
418}
Note: See TracBrowser for help on using the repository browser.