summaryrefslogtreecommitdiffstats
path: root/generic/tclOOCall.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2006-10-20 15:16:47 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2006-10-20 15:16:47 (GMT)
commitd3e1aa1876716ce04f520834edee8125724daac9 (patch)
tree6e5adffffcc577f30bfd88dbb0cfad5846a9e410 /generic/tclOOCall.c
parent667340e02adf467adc84a317f84580be29dc5c71 (diff)
downloadtcl-d3e1aa1876716ce04f520834edee8125724daac9.zip
tcl-d3e1aa1876716ce04f520834edee8125724daac9.tar.gz
tcl-d3e1aa1876716ce04f520834edee8125724daac9.tar.bz2
Undo mistaken commit to wrong branch caused by CVS fumble... :-}
Diffstat (limited to 'generic/tclOOCall.c')
-rw-r--r--generic/tclOOCall.c803
1 files changed, 0 insertions, 803 deletions
diff --git a/generic/tclOOCall.c b/generic/tclOOCall.c
deleted file mode 100644
index 71663e4..0000000
--- a/generic/tclOOCall.c
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * tclOO.c --
- *
- * This file contains the method call chain management code for the
- * object-system core.
- *
- * Copyright (c) 2005-2006 by Donal K. Fellows
- *
- * See the file "license.terms" for information on usage and redistribution of
- * this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * RCS: @(#) $Id: tclOOCall.c,v 1.2 2006/10/20 14:04:01 dkf Exp $
- */
-
-#include "tclInt.h"
-#include "tclOO.h"
-
-/*
- * Extra flags used for call chain management.
- */
-
-#define DEFINITE_PRIVATE 0x100000
-#define DEFINITE_PUBLIC 0x200000
-#define KNOWN_STATE (DEFINITE_PRIVATE | DEFINITE_PUBLIC)
-#define SPECIAL (CONSTRUCTOR | DESTRUCTOR)
-
-/*
- * Function declarations for things defined in this file.
- */
-
-static void AddClassFiltersToCallContext(Object *oPtr,
- Class *clsPtr, CallContext *contextPtr,
- Tcl_HashTable *doneFilters);
-static void AddClassMethodNames(Class *clsPtr, int publicOnly,
- Tcl_HashTable *namesPtr);
-static void AddMethodToCallChain(Method *mPtr,
- CallContext *contextPtr,
- Tcl_HashTable *doneFilters);
-static void AddSimpleChainToCallContext(Object *oPtr,
- Tcl_Obj *methodNameObj, CallContext *contextPtr,
- Tcl_HashTable *doneFilters, int isPublic);
-static void AddSimpleClassChainToCallContext(Class *classPtr,
- Tcl_Obj *methodNameObj, CallContext *contextPtr,
- Tcl_HashTable *doneFilters, int isPublic);
-static int CmpStr(const void *ptr1, const void *ptr2);
-static void InitClassHierarchy(Foundation *fPtr, Class *classPtr);
-
-/*
- * ----------------------------------------------------------------------
- *
- * TclOODeleteContext --
- *
- * Destroys a method call-chain context, which should not be in use.
- *
- * ----------------------------------------------------------------------
- */
-
-void
-TclOODeleteContext(
- CallContext *contextPtr)
-{
- if (contextPtr->callChain != contextPtr->staticCallChain) {
- ckfree((char *) contextPtr->callChain);
- }
- ckfree((char *) contextPtr);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * TclOOInvokeContext --
- *
- * Invokes a single step along a method call-chain context. Note that the
- * invokation of a step along the chain can cause further steps along the
- * chain to be invoked. Note that this function is written to be as light
- * in stack usage as possible.
- *
- * ----------------------------------------------------------------------
- */
-
-int
-TclOOInvokeContext(
- Tcl_Interp *interp, /* Interpreter for error reporting, and many
- * other sorts of context handling (e.g.,
- * commands, variables) depending on method
- * implementation. */
- CallContext *contextPtr, /* The method call context. */
- int objc, /* The number of arguments. */
- Tcl_Obj *const *objv) /* The arguments as actually seen. */
-{
- Method *mPtr = contextPtr->callChain[contextPtr->index].mPtr;
- int result, isFirst = (contextPtr->index == 0);
- int isFilter = contextPtr->callChain[contextPtr->index].isFilter;
- int wasFilter;
-
- /*
- * If this is the first step along the chain, we preserve the method
- * entries in the chain so that they do not get deleted out from under our
- * feet.
- */
-
- if (isFirst) {
- int i;
-
- for (i=0 ; i<contextPtr->numCallChain ; i++) {
- Tcl_Preserve(contextPtr->callChain[i].mPtr);
- }
- }
-
- /*
- * Save whether we were in a filter and set up whether we are now.
- */
-
- wasFilter = contextPtr->oPtr->flags & FILTER_HANDLING;
- if (isFilter || contextPtr->flags & FILTER_HANDLING) {
- contextPtr->oPtr->flags |= FILTER_HANDLING;
- } else {
- contextPtr->oPtr->flags &= ~FILTER_HANDLING;
- }
-
- /*
- * Run the method implementation.
- */
-
- result = mPtr->typePtr->callProc(mPtr->clientData, interp,
- (Tcl_ObjectContext) contextPtr, objc, objv);
-
- /*
- * Restore the old filter-ness, release any locks on method
- * implementations, and return the result code.
- */
-
- if (wasFilter) {
- contextPtr->oPtr->flags |= FILTER_HANDLING;
- } else {
- contextPtr->oPtr->flags &= ~FILTER_HANDLING;
- }
- if (isFirst) {
- int i;
-
- for (i=0 ; i<contextPtr->numCallChain ; i++) {
- Tcl_Release(contextPtr->callChain[i].mPtr);
- }
- }
- return result;
-}
-
-static void
-InitClassHierarchy(
- Foundation *fPtr,
- Class *classPtr)
-{
- if (classPtr == fPtr->objectCls) {
- return;
- }
- if (classPtr->classHierarchyEpoch != fPtr->epoch) {
- int i;
- Class *superPtr;
-
- if (classPtr->classHierarchy.num != 0) {
- ckfree((char *) classPtr->classHierarchy.list);
- }
- FOREACH(superPtr, classPtr->superclasses) {
- InitClassHierarchy(fPtr, superPtr);
- }
- if (i == 1) {
- Class **hierlist = (Class **)
- ckalloc(sizeof(Class*) * (1+superPtr->classHierarchy.num));
-
- hierlist[0] = superPtr;
- memcpy(hierlist+1, superPtr->classHierarchy.list,
- sizeof(Class*) * superPtr->classHierarchy.num);
- classPtr->classHierarchy.num = 1 + superPtr->classHierarchy.num;
- classPtr->classHierarchy.list = hierlist;
- classPtr->classHierarchyEpoch = fPtr->epoch;
- return;
- } else {
- int num = classPtr->superclasses.num, j = 0, k, realNum;
- Class **hierlist; /* Temporary work space. */
-
- FOREACH(superPtr, classPtr->superclasses) {
- num += superPtr->classHierarchy.num;
- }
- hierlist = (Class **) ckalloc(sizeof(Class *) * num);
- FOREACH(superPtr, classPtr->superclasses) {
- hierlist[j++] = superPtr;
- if (superPtr == fPtr->objectCls) {
- continue;
- }
- memcpy(hierlist+j, superPtr->classHierarchy.list,
- sizeof(Class *) * superPtr->classHierarchy.num);
- j += superPtr->classHierarchy.num;
- }
- realNum = num;
- for (j=0 ; j<num-1 ; j++) {
- for (k=num-1 ; k>j ; k--) {
- if (hierlist[j] == hierlist[k]) {
- hierlist[j] = NULL;
- realNum--;
- break;
- }
- }
- }
- classPtr->classHierarchy.num = realNum;
- classPtr->classHierarchy.list = (Class **)
- ckalloc(sizeof(Class *) * realNum);
- for (j=k=0 ; j<num ; j++) {
- if (hierlist[j] != NULL) {
- classPtr->classHierarchy.list[k++] = hierlist[j];
- }
- }
- ckfree((char *) hierlist);
- }
- }
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * TclOOGetSortedMethodList --
- *
- * Discovers the list of method names supported by an object.
- *
- * ----------------------------------------------------------------------
- */
-
-int
-TclOOGetSortedMethodList(
- Object *oPtr, /* The object to get the method names for. */
- int publicOnly, /* Whether we just want the public method
- * names. */
- const char ***stringsPtr) /* Where to write a pointer to the array of
- * strings to. */
-{
- Tcl_HashTable names;
- FOREACH_HASH_DECLS;
- int i;
- const char **strings;
- Class *mixinPtr;
- Tcl_Obj *namePtr;
- Method *mPtr;
- void *isWanted;
-
- Tcl_InitObjHashTable(&names);
-
- FOREACH_HASH(namePtr, mPtr, &oPtr->methods) {
- int isNew;
-
- hPtr = Tcl_CreateHashEntry(&names, (char *) namePtr, &isNew);
- if (isNew) {
- isWanted = (void *) (!publicOnly || mPtr->flags & PUBLIC_METHOD);
- Tcl_SetHashValue(hPtr, isWanted);
- }
- }
-
- AddClassMethodNames(oPtr->selfCls, publicOnly, &names);
- FOREACH(mixinPtr, oPtr->mixins) {
- AddClassMethodNames(mixinPtr, publicOnly, &names);
- }
-
- if (names.numEntries == 0) {
- Tcl_DeleteHashTable(&names);
- return 0;
- }
-
- strings = (const char **) ckalloc(sizeof(char *) * names.numEntries);
- i = 0;
- FOREACH_HASH(namePtr, isWanted, &names) {
- if (!publicOnly || isWanted) {
- strings[i++] = TclGetString(namePtr);
- }
- }
-
- /*
- * Note that 'i' may well be less than names.numEntries when we are
- * dealing with public method names.
- */
-
- qsort(strings, (unsigned) i, sizeof(char *), CmpStr);
-
- Tcl_DeleteHashTable(&names);
- *stringsPtr = strings;
- return i;
-}
-
-/* Comparator for GetSortedMethodList */
-static int
-CmpStr(
- const void *ptr1,
- const void *ptr2)
-{
- const char **strPtr1 = (const char **) ptr1;
- const char **strPtr2 = (const char **) ptr2;
-
- return TclpUtfNcmp2(*strPtr1, *strPtr2, strlen(*strPtr1)+1);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * AddClassMethodNames --
- *
- * Adds the method names defined by a class (or its superclasses) to the
- * collection being built. The collection is built in a hash table to
- * ensure that duplicates are excluded. Helper for GetSortedMethodList().
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-AddClassMethodNames(
- Class *clsPtr, /* Class to get method names from. */
- const int publicOnly, /* Whether we are interested in just the
- * public method names. */
- Tcl_HashTable *const namesPtr)
- /* Reference to the hash table to put the
- * information in. The hash table maps the
- * Tcl_Obj * method name to an integral value
- * describing whether the method is wanted.
- * This ensures that public/private override
- * semantics are handled correctly.*/
-{
- /*
- * Scope all declarations so that the compiler can stand a good chance of
- * making the recursive step highly efficient. We also hand-implement the
- * tail-recursive case using a while loop; C compilers typically cannot do
- * tail-recursion optimization usefully.
- */
-
- if (clsPtr->mixins.num != 0) {
- Class *mixinPtr;
- int i;
-
- // TODO: Beware of infinite loops!
- FOREACH(mixinPtr, clsPtr->mixins) {
- AddClassMethodNames(mixinPtr, publicOnly, namesPtr);
- }
- }
-
- while (1) {
- FOREACH_HASH_DECLS;
- Tcl_Obj *namePtr;
- Method *mPtr;
-
- FOREACH_HASH(namePtr, mPtr, &clsPtr->classMethods) {
- int isNew;
-
- hPtr = Tcl_CreateHashEntry(namesPtr, (char *) namePtr, &isNew);
- if (isNew) {
- int isWanted = (!publicOnly || mPtr->flags & PUBLIC_METHOD);
-
- Tcl_SetHashValue(hPtr, (void *) isWanted);
- }
- }
-
- if (clsPtr->superclasses.num != 1) {
- break;
- }
- clsPtr = clsPtr->superclasses.list[0];
- }
- if (clsPtr->superclasses.num != 0) {
- Class *superPtr;
- int i;
-
- FOREACH(superPtr, clsPtr->superclasses) {
- AddClassMethodNames(superPtr, publicOnly, namesPtr);
- }
- }
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * TclOOGetCallContext --
- *
- * Responsible for constructing the call context, an ordered list of all
- * method implementations to be called as part of a method invokation.
- * This method is central to the whole operation of the OO system.
- *
- * ----------------------------------------------------------------------
- */
-
-CallContext *
-TclOOGetCallContext(
- Foundation *fPtr, /* The foundation of the object system. */
- Object *oPtr, /* The object to get the context for. */
- Tcl_Obj *methodNameObj, /* The name of the method to get the context
- * for. NULL when getting a constructor or
- * destructor chain. */
- int flags, /* What sort of context are we looking for.
- * Only the bits OO_PUBLIC_METHOD,
- * CONSTRUCTOR, DESTRUCTOR and FILTER_HANDLING
- * are useful. */
- Tcl_HashTable *cachePtr) /* Where to cache the chain. Ignored for both
- * constructors and destructors. */
-{
- CallContext *contextPtr;
- int i, count, doFilters;
- Tcl_HashEntry *hPtr;
- Tcl_HashTable doneFilters;
-
- if (flags&(SPECIAL|FILTER_HANDLING) || (oPtr->flags&FILTER_HANDLING)) {
- hPtr = NULL;
- doFilters = 0;
- } else {
- doFilters = 1;
- hPtr = Tcl_FindHashEntry(cachePtr, (char *) methodNameObj);
- if (hPtr != NULL && Tcl_GetHashValue(hPtr) != NULL) {
- contextPtr = Tcl_GetHashValue(hPtr);
- Tcl_SetHashValue(hPtr, NULL);
- if ((contextPtr->globalEpoch == fPtr->epoch)
- && (contextPtr->localEpoch == oPtr->epoch)) {
- return contextPtr;
- }
- TclOODeleteContext(contextPtr);
- }
- }
- contextPtr = (CallContext *) ckalloc(sizeof(CallContext));
- contextPtr->numCallChain = 0;
- contextPtr->callChain = contextPtr->staticCallChain;
- contextPtr->filterLength = 0;
- contextPtr->globalEpoch = fPtr->epoch;
- contextPtr->localEpoch = oPtr->epoch;
- contextPtr->flags = 0;
- contextPtr->skip = 2;
- if (flags & (PUBLIC_METHOD | SPECIAL | FILTER_HANDLING)) {
- contextPtr->flags |= flags & (PUBLIC_METHOD|SPECIAL|FILTER_HANDLING);
- }
- contextPtr->oPtr = oPtr;
- contextPtr->index = 0;
-
- /*
- * Ensure that the class hierarchy is trivially iterable.
- */
-
- InitClassHierarchy(fPtr, oPtr->selfCls);
-
- /*
- * Add all defined filters (if any, and if we're going to be processing
- * them; they're not processed for constructors, destructors or when we're
- * in the middle of processing a filter).
- */
-
- if (doFilters) {
- Tcl_Obj *filterObj;
- Class *mixinPtr;
-
- doFilters = 1;
- Tcl_InitObjHashTable(&doneFilters);
- FOREACH(mixinPtr, oPtr->mixins) {
- AddClassFiltersToCallContext(oPtr, mixinPtr, contextPtr,
- &doneFilters);
- }
- FOREACH(filterObj, oPtr->filters) {
- AddSimpleChainToCallContext(oPtr, filterObj, contextPtr,
- &doneFilters, 0);
- }
- AddClassFiltersToCallContext(oPtr, oPtr->selfCls, contextPtr,
- &doneFilters);
- Tcl_DeleteHashTable(&doneFilters);
- }
- count = contextPtr->filterLength = contextPtr->numCallChain;
-
- /*
- * Add the actual method implementations.
- */
-
- AddSimpleChainToCallContext(oPtr, methodNameObj, contextPtr, NULL, flags);
-
- /*
- * Check to see if the method has no implementation. If so, we probably
- * need to add in a call to the unknown method. Otherwise, set up the
- * cacheing of the method implementation (if relevant).
- */
-
- if (count == contextPtr->numCallChain) {
- /*
- * Method does not actually exist. If we're dealing with constructors
- * or destructors, this isn't a problem.
- */
-
- if (flags & SPECIAL) {
- TclOODeleteContext(contextPtr);
- return NULL;
- }
- AddSimpleChainToCallContext(oPtr, fPtr->unknownMethodNameObj,
- contextPtr, NULL, 0);
- contextPtr->flags |= OO_UNKNOWN_METHOD;
- contextPtr->globalEpoch = -1;
- if (count == contextPtr->numCallChain) {
- TclOODeleteContext(contextPtr);
- return NULL;
- }
- } else if (doFilters) {
- if (hPtr == NULL) {
- hPtr = Tcl_CreateHashEntry(cachePtr, (char *) methodNameObj, &i);
- }
- Tcl_SetHashValue(hPtr, NULL);
- }
- return contextPtr;
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * AddClassFiltersToCallContext --
- *
- * Logic to make extracting all the filters from the class context much
- * easier.
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-AddClassFiltersToCallContext(
- Object *const oPtr, /* Object that the filters operate on. */
- Class *clsPtr, /* Class to get the filters from. */
- CallContext *const contextPtr,
- /* Context to fill with call chain entries. */
- Tcl_HashTable *const doneFilters)
- /* Where to record what filters have been
- * processed. Keys are objects, values are
- * ignored. */
-{
- int i;
- Class *superPtr;
- Tcl_Obj *filterObj;
-
- tailRecurse:
- if (clsPtr == NULL) {
- return;
- }
-
- /*
- * Add all the class filters from the current class. Note that the filters
- * are added starting at the object root, as this allows the object to
- * override how filters work to extend their behaviour.
- */
-
- FOREACH(filterObj, clsPtr->filters) {
- int isNew;
-
- (void) Tcl_CreateHashEntry(doneFilters, (char *) filterObj, &isNew);
- if (isNew) {
- AddSimpleChainToCallContext(oPtr, filterObj, contextPtr,
- doneFilters, 0);
- }
- }
-
- /*
- * Now process the recursive case. Notice the tail-call optimization.
- */
-
- switch (clsPtr->superclasses.num) {
- case 1:
- clsPtr = clsPtr->superclasses.list[0];
- goto tailRecurse;
- default:
- FOREACH(superPtr, clsPtr->superclasses) {
- AddClassFiltersToCallContext(oPtr, superPtr, contextPtr,
- doneFilters);
- }
- case 0:
- return;
- }
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * AddSimpleChainToCallContext --
- *
- * The core of the call-chain construction engine, this handles calling a
- * particular method on a particular object. Note that filters and
- * unknown handling are already handled by the logic that uses this
- * function.
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-AddSimpleChainToCallContext(
- Object *oPtr, /* Object to add call chain entries for. */
- Tcl_Obj *methodNameObj, /* Name of method to add the call chain
- * entries for. */
- CallContext *contextPtr, /* Where to add the call chain entries. */
- Tcl_HashTable *doneFilters, /* Where to record what call chain entries
- * have been processed. */
- int flags) /* What sort of call chain are we building. */
-{
- int i;
-
- if (!(flags & (KNOWN_STATE | SPECIAL))) {
- Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&oPtr->methods,
- (char *) methodNameObj);
-
- if (hPtr != NULL) {
- Method *mPtr = Tcl_GetHashValue(hPtr);
-
- if (flags & PUBLIC_METHOD) {
- if (!(mPtr->flags & PUBLIC_METHOD)) {
- return;
- } else {
- flags |= DEFINITE_PUBLIC;
- }
- } else {
- flags |= DEFINITE_PRIVATE;
- }
- }
- }
- if (!(flags & SPECIAL)) {
- Tcl_HashEntry *hPtr;
- Class *mixinPtr, *superPtr;
-
- FOREACH(mixinPtr, oPtr->mixins) {
- AddSimpleClassChainToCallContext(mixinPtr, methodNameObj,
- contextPtr, doneFilters, flags);
- }
- FOREACH(mixinPtr, oPtr->selfCls->mixins) {
- AddSimpleClassChainToCallContext(mixinPtr, methodNameObj,
- contextPtr, doneFilters, flags);
- }
- FOREACH(superPtr, oPtr->selfCls->classHierarchy) {
- int j=i;// HACK: save index so we can nest FOREACHes
- FOREACH(mixinPtr, superPtr->mixins) {
- AddSimpleClassChainToCallContext(mixinPtr, methodNameObj,
- contextPtr, doneFilters, flags);
- }
- i=j;
- }
- hPtr = Tcl_FindHashEntry(&oPtr->methods, (char *) methodNameObj);
- if (hPtr != NULL) {
- AddMethodToCallChain(Tcl_GetHashValue(hPtr), contextPtr,
- doneFilters);
- }
- }
- AddSimpleClassChainToCallContext(oPtr->selfCls, methodNameObj, contextPtr,
- doneFilters, flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * AddSimpleClassChainToCallContext --
- *
- * Construct a call-chain from a class hierarchy.
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-AddSimpleClassChainToCallContext(
- Class *classPtr, /* Class to add the call chain entries for. */
- Tcl_Obj *const methodNameObj,
- /* Name of method to add the call chain
- * entries for. */
- CallContext *const contextPtr,
- /* Where to add the call chain entries. */
- Tcl_HashTable *const doneFilters,
- /* Where to record what call chain entries
- * have been processed. */
- int flags) /* What sort of call chain are we building. */
-{
- /*
- * We hard-code the tail-recursive form. It's by far the most common case
- * *and* it is much more gentle on the stack.
- */
-
- tailRecurse:
- if (flags & CONSTRUCTOR) {
- AddMethodToCallChain(classPtr->constructorPtr, contextPtr,
- doneFilters);
- } else if (flags & DESTRUCTOR) {
- AddMethodToCallChain(classPtr->destructorPtr, contextPtr,
- doneFilters);
- } else {
- Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&classPtr->classMethods,
- (char *) methodNameObj);
-
- if (hPtr != NULL) {
- register Method *mPtr = Tcl_GetHashValue(hPtr);
-
- if (!(flags & KNOWN_STATE)) {
- if (flags & PUBLIC_METHOD) {
- if (mPtr->flags & PUBLIC_METHOD) {
- flags |= DEFINITE_PUBLIC;
- } else {
- return;
- }
- } else {
- flags |= DEFINITE_PRIVATE;
- }
- }
- AddMethodToCallChain(mPtr, contextPtr, doneFilters);
- }
- }
-
- switch (classPtr->superclasses.num) {
- case 1:
- classPtr = classPtr->superclasses.list[0];
- goto tailRecurse;
- default:
- {
- int i;
- Class *superPtr;
-
- FOREACH(superPtr, classPtr->superclasses) {
- AddSimpleClassChainToCallContext(superPtr, methodNameObj,
- contextPtr, doneFilters, flags);
- }
- }
- case 0:
- return;
- }
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * AddMethodToCallChain --
- *
- * Utility method that manages the adding of a particular method
- * implementation to a call-chain.
- *
- * ----------------------------------------------------------------------
- */
-
-static void
-AddMethodToCallChain(
- Method *mPtr, /* Actual method implementation to add to call
- * chain (or NULL, a no-op). */
- CallContext *contextPtr, /* The call chain to add the method
- * implementation to. */
- Tcl_HashTable *doneFilters) /* Where to record what filters have been
- * processed. If NULL, not processing filters.
- * Note that this function does not update
- * this hashtable. */
-{
- int i;
-
- /*
- * Return if this is just an entry used to record whether this is a public
- * method. If so, there's nothing real to call and so nothing to add to
- * the call chain.
- */
-
- if (mPtr == NULL || mPtr->typePtr == NULL) {
- return;
- }
-
- /*
- * First test whether the method is already in the call chain. Skip over
- * any leading filters.
- */
-
- for (i=contextPtr->filterLength ; i<contextPtr->numCallChain ; i++) {
- if (contextPtr->callChain[i].mPtr == mPtr
- && contextPtr->callChain[i].isFilter == (doneFilters!=NULL)) {
- /*
- * Call chain semantics states that methods come as *late* in the
- * call chain as possible. This is done by copying down the
- * following methods. Note that this does not change the number of
- * method invokations in the call chain; it just rearranges them.
- */
-
- for (; i+1<contextPtr->numCallChain ; i++) {
- contextPtr->callChain[i] = contextPtr->callChain[i+1];
- }
- contextPtr->callChain[i].mPtr = mPtr;
- contextPtr->callChain[i].isFilter = (doneFilters != NULL);
- return;
- }
- }
-
- /*
- * Need to really add the method. This is made a bit more complex by the
- * fact that we are using some "static" space initially, and only start
- * realloc-ing if the chain gets long.
- */
-
- if (contextPtr->numCallChain == CALL_CHAIN_STATIC_SIZE) {
- contextPtr->callChain = (struct MInvoke *)
- ckalloc(sizeof(struct MInvoke)*(contextPtr->numCallChain+1));
- memcpy(contextPtr->callChain, contextPtr->staticCallChain,
- sizeof(struct MInvoke) * (contextPtr->numCallChain + 1));
- } else if (contextPtr->numCallChain > CALL_CHAIN_STATIC_SIZE) {
- contextPtr->callChain = (struct MInvoke *)
- ckrealloc((char *) contextPtr->callChain,
- sizeof(struct MInvoke) * (contextPtr->numCallChain + 1));
- }
- contextPtr->callChain[contextPtr->numCallChain].mPtr = mPtr;
- contextPtr->callChain[contextPtr->numCallChain].isFilter =
- (doneFilters != NULL);
- contextPtr->numCallChain++;
-}
-
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */