summaryrefslogtreecommitdiffstats
path: root/generic/tclOOMethod.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclOOMethod.c')
-rw-r--r--generic/tclOOMethod.c278
1 files changed, 162 insertions, 116 deletions
diff --git a/generic/tclOOMethod.c b/generic/tclOOMethod.c
index 3422660..61215de 100644
--- a/generic/tclOOMethod.c
+++ b/generic/tclOOMethod.c
@@ -3,12 +3,10 @@
*
* This file contains code to create and manage methods.
*
- * Copyright (c) 2005-2008 by Donal K. Fellows
+ * Copyright (c) 2005-2011 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: tclOOMethod.c,v 1.22 2009/04/11 11:18:51 dkf Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -41,6 +39,8 @@ typedef struct {
Tcl_Obj *nameObj; /* The "name" of the command. */
Command cmd; /* The command structure. Mostly bogus. */
ExtraFrameInfo efi; /* Extra information used for [info frame]. */
+ Command *oldCmdPtr; /* Saved cmdPtr so that we can be safe after a
+ * recursive call returns. */
struct PNI pni; /* Specialist information used in the efi
* field for this type of call. */
} PMFrameData;
@@ -108,7 +108,7 @@ static int ProcedureMethodCompiledVarResolver(Tcl_Interp *interp,
*/
static const Tcl_MethodType procMethodType = {
- TCL_OO_METHOD_VERSION_CURRENT, "procedural method",
+ TCL_OO_METHOD_VERSION_CURRENT, "method",
InvokeProcedureMethod, DeleteProcedureMethod, CloneProcedureMethod
};
static const Tcl_MethodType fwdMethodType = {
@@ -157,19 +157,19 @@ Tcl_NewInstanceMethod(
int isNew;
if (nameObj == NULL) {
- mPtr = (Method *) ckalloc(sizeof(Method));
+ mPtr = ckalloc(sizeof(Method));
mPtr->namePtr = NULL;
mPtr->refCount = 1;
goto populate;
}
if (!oPtr->methodsPtr) {
- oPtr->methodsPtr = (Tcl_HashTable *) ckalloc(sizeof(Tcl_HashTable));
+ oPtr->methodsPtr = ckalloc(sizeof(Tcl_HashTable));
Tcl_InitObjHashTable(oPtr->methodsPtr);
oPtr->flags &= ~USE_CLASS_CACHE;
}
hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, (char *) nameObj, &isNew);
if (isNew) {
- mPtr = (Method *) ckalloc(sizeof(Method));
+ mPtr = ckalloc(sizeof(Method));
mPtr->namePtr = nameObj;
mPtr->refCount = 1;
Tcl_IncrRefCount(nameObj);
@@ -225,14 +225,14 @@ Tcl_NewMethod(
int isNew;
if (nameObj == NULL) {
- mPtr = (Method *) ckalloc(sizeof(Method));
+ mPtr = ckalloc(sizeof(Method));
mPtr->namePtr = NULL;
mPtr->refCount = 1;
goto populate;
}
hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, (char *)nameObj,&isNew);
if (isNew) {
- mPtr = (Method *) ckalloc(sizeof(Method));
+ mPtr = ckalloc(sizeof(Method));
mPtr->refCount = 1;
mPtr->namePtr = nameObj;
Tcl_IncrRefCount(nameObj);
@@ -280,7 +280,7 @@ TclOODelMethodRef(
Tcl_DecrRefCount(mPtr->namePtr);
}
- ckfree((char *) mPtr);
+ ckfree(mPtr);
}
}
@@ -344,7 +344,7 @@ TclOONewProcInstanceMethod(
if (Tcl_ListObjLength(interp, argsObj, &argsLen) != TCL_OK) {
return NULL;
}
- pmPtr = (ProcedureMethod *) ckalloc(sizeof(ProcedureMethod));
+ pmPtr = ckalloc(sizeof(ProcedureMethod));
memset(pmPtr, 0, sizeof(ProcedureMethod));
pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
pmPtr->flags = flags & USE_DECLARER_NS;
@@ -353,7 +353,7 @@ TclOONewProcInstanceMethod(
method = TclOOMakeProcInstanceMethod(interp, oPtr, flags, nameObj,
argsObj, bodyObj, &procMethodType, pmPtr, &pmPtr->procPtr);
if (method == NULL) {
- ckfree((char *) pmPtr);
+ ckfree(pmPtr);
} else if (pmPtrPtr != NULL) {
*pmPtrPtr = pmPtr;
}
@@ -405,7 +405,7 @@ TclOONewProcMethod(
procName = (nameObj==NULL ? "<constructor>" : TclGetString(nameObj));
}
- pmPtr = (ProcedureMethod *) ckalloc(sizeof(ProcedureMethod));
+ pmPtr = ckalloc(sizeof(ProcedureMethod));
memset(pmPtr, 0, sizeof(ProcedureMethod));
pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
pmPtr->flags = flags & USE_DECLARER_NS;
@@ -418,7 +418,7 @@ TclOONewProcMethod(
Tcl_DecrRefCount(argsObj);
}
if (method == NULL) {
- ckfree((char *) pmPtr);
+ ckfree(pmPtr);
} else if (pmPtrPtr != NULL) {
*pmPtrPtr = pmPtr;
}
@@ -499,12 +499,12 @@ TclOOMakeProcInstanceMethod(
if (context.line
&& (context.nline >= 4) && (context.line[3] >= 0)) {
int isNew;
- CmdFrame *cfPtr = (CmdFrame *) ckalloc(sizeof(CmdFrame));
+ CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame));
Tcl_HashEntry *hPtr;
cfPtr->level = -1;
cfPtr->type = context.type;
- cfPtr->line = (int *) ckalloc(sizeof(int));
+ cfPtr->line = ckalloc(sizeof(int));
cfPtr->line[0] = context.line[3];
cfPtr->nline = 1;
cfPtr->framePtr = NULL;
@@ -513,8 +513,8 @@ TclOOMakeProcInstanceMethod(
cfPtr->data.eval.path = context.data.eval.path;
Tcl_IncrRefCount(cfPtr->data.eval.path);
- cfPtr->cmd.str.cmd = NULL;
- cfPtr->cmd.str.len = 0;
+ cfPtr->cmd = NULL;
+ cfPtr->len = 0;
hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
(char *) procPtr, &isNew);
@@ -612,12 +612,12 @@ TclOOMakeProcMethod(
if (context.line
&& (context.nline >= 4) && (context.line[3] >= 0)) {
int isNew;
- CmdFrame *cfPtr = (CmdFrame *) ckalloc(sizeof(CmdFrame));
+ CmdFrame *cfPtr = ckalloc(sizeof(CmdFrame));
Tcl_HashEntry *hPtr;
cfPtr->level = -1;
cfPtr->type = context.type;
- cfPtr->line = (int *) ckalloc(sizeof(int));
+ cfPtr->line = ckalloc(sizeof(int));
cfPtr->line[0] = context.line[3];
cfPtr->nline = 1;
cfPtr->framePtr = NULL;
@@ -626,8 +626,8 @@ TclOOMakeProcMethod(
cfPtr->data.eval.path = context.data.eval.path;
Tcl_IncrRefCount(cfPtr->data.eval.path);
- cfPtr->cmd.str.cmd = NULL;
- cfPtr->cmd.str.len = 0;
+ cfPtr->cmd = NULL;
+ cfPtr->len = 0;
hPtr = Tcl_CreateHashEntry(iPtr->linePBodyPtr,
(char *) procPtr, &isNew);
@@ -686,7 +686,7 @@ InvokeProcedureMethod(
* Allocate the special frame data.
*/
- fdPtr = (PMFrameData *) TclStackAlloc(interp, sizeof(PMFrameData));
+ fdPtr = TclStackAlloc(interp, sizeof(PMFrameData));
/*
* Create a call frame for this method.
@@ -711,6 +711,13 @@ InvokeProcedureMethod(
result = pmPtr->preCallProc(pmPtr->clientData, interp, context,
(Tcl_CallFrame *) fdPtr->framePtr, &isFinished);
if (isFinished || result != TCL_OK) {
+ /*
+ * Restore the old cmdPtr so that a subsequent use of [info frame]
+ * won't crash on us. [Bug 3001438]
+ */
+
+ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;
+
Tcl_PopCallFrame(interp);
TclStackFree(interp, fdPtr->framePtr);
if (--pmPtr->refCount < 1) {
@@ -752,6 +759,13 @@ FinalizePMCall(
}
/*
+ * Restore the old cmdPtr so that a subsequent use of [info frame] won't
+ * crash on us. [Bug 3001438]
+ */
+
+ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;
+
+ /*
* Scrap the special frame data now that we're done with it. Note that we
* are inlining DeleteProcedureMethod() here; this location is highly
* sensitive when it comes to performance!
@@ -820,6 +834,14 @@ PushMethodCallFrame(
}
/*
+ * Save the old cmdPtr so that when this recursive call returns, we can
+ * restore it. To do otherwise causes crashes in [info frame] after we
+ * return from a recursive call. [Bug 3001438]
+ */
+
+ fdPtr->oldCmdPtr = pmPtr->procPtr->cmdPtr;
+
+ /*
* Compile the body. This operation may fail.
*/
@@ -838,14 +860,14 @@ PushMethodCallFrame(
if (pmPtr->procPtr->bodyPtr->typePtr == &tclByteCodeType) {
ByteCode *codePtr =
- pmPtr->procPtr->bodyPtr->internalRep.otherValuePtr;
+ pmPtr->procPtr->bodyPtr->internalRep.twoPtrValue.ptr1;
codePtr->nsPtr = nsPtr;
}
result = TclProcCompileProc(interp, pmPtr->procPtr,
pmPtr->procPtr->bodyPtr, nsPtr, "body of method", namePtr);
if (result != TCL_OK) {
- return result;
+ goto failureReturn;
}
/*
@@ -856,7 +878,7 @@ PushMethodCallFrame(
result = TclPushStackFrame(interp, (Tcl_CallFrame **) framePtrPtr,
(Tcl_Namespace *) nsPtr, FRAME_IS_PROC|FRAME_IS_METHOD);
if (result != TCL_OK) {
- return result;
+ goto failureReturn;
}
fdPtr->framePtr->clientData = contextPtr;
@@ -891,6 +913,15 @@ PushMethodCallFrame(
}
return TCL_OK;
+
+ /*
+ * Restore the old cmdPtr so that a subsequent use of [info frame] won't
+ * crash on us. [Bug 3001438]
+ */
+
+ failureReturn:
+ pmPtr->procPtr->cmdPtr = fdPtr->oldCmdPtr;
+ return result;
}
/*
@@ -928,59 +959,26 @@ ProcedureMethodVarResolver(
int flags,
Tcl_Var *varPtr)
{
- Interp *iPtr = (Interp *) interp;
- CallFrame *framePtr = iPtr->varFramePtr;
- CallContext *contextPtr;
- Tcl_Obj *variableObj;
- Tcl_HashEntry *hPtr;
- int i, isNew;
-
- /*
- * Check that the variable is being requested in a context that is also a
- * method call; if not (i.e. we're evaluating in the object's namespace or
- * in a procedure of that namespace) then we do nothing.
- */
+ int result;
+ Tcl_ResolvedVarInfo *rPtr = NULL;
+
+ result = ProcedureMethodCompiledVarResolver(interp, varName,
+ strlen(varName), contextNs, &rPtr);
- if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
- return TCL_CONTINUE;
+ if (result != TCL_OK) {
+ return result;
}
- contextPtr = framePtr->clientData;
- /*
- * Check if the variable is one we want to resolve at all (i.e. whether it
- * is in the list provided by the user). If not, we mustn't do anything
- * either.
- */
-
- if (contextPtr->callPtr->chain[contextPtr->index]
- .mPtr->declaringClassPtr != NULL) {
- FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index]
- .mPtr->declaringClassPtr->variables) {
- if (!strcmp(Tcl_GetString(variableObj), varName)) {
- goto gotMatch;
- }
- }
- } else {
- FOREACH(variableObj, contextPtr->oPtr->variables) {
- if (!strcmp(Tcl_GetString(variableObj), varName)) {
- goto gotMatch;
- }
- }
- }
- return TCL_CONTINUE;
+ *varPtr = rPtr->fetchProc(interp, rPtr);
/*
- * It is a variable we want to resolve, so resolve it.
+ * Must not retain reference to resolved information. [Bug 3105999]
*/
- gotMatch:
- hPtr = Tcl_CreateHashEntry(TclVarTable(contextNs), (char *) variableObj,
- &isNew);
- if (isNew) {
- TclSetVarNamespaceVar((Var *) TclVarHashGetValue(hPtr));
+ if (rPtr != NULL) {
+ rPtr->deleteProc(rPtr);
}
- *varPtr = TclVarHashGetValue(hPtr);
- return TCL_OK;
+ return (*varPtr? TCL_OK : TCL_CONTINUE);
}
static Tcl_Var
@@ -994,8 +992,8 @@ ProcedureMethodCompiledVarConnect(
CallContext *contextPtr;
Tcl_Obj *variableObj;
Tcl_HashEntry *hPtr;
- int i, isNew, cacheIt;
- const char *varName = Tcl_GetString(infoPtr->variableObj);
+ int i, isNew, cacheIt, varLen, len;
+ const char *match, *varName;
/*
* Check that the variable is being requested in a context that is also a
@@ -1023,18 +1021,21 @@ ProcedureMethodCompiledVarConnect(
* either.
*/
+ varName = TclGetStringFromObj(infoPtr->variableObj, &varLen);
if (contextPtr->callPtr->chain[contextPtr->index]
.mPtr->declaringClassPtr != NULL) {
FOREACH(variableObj, contextPtr->callPtr->chain[contextPtr->index]
.mPtr->declaringClassPtr->variables) {
- if (!strcmp(Tcl_GetString(variableObj), varName)) {
+ match = TclGetStringFromObj(variableObj, &len);
+ if ((len == varLen) && !memcmp(match, varName, len)) {
cacheIt = 0;
goto gotMatch;
}
}
} else {
FOREACH(variableObj, contextPtr->oPtr->variables) {
- if (!strcmp(Tcl_GetString(variableObj), varName)) {
+ match = TclGetStringFromObj(variableObj, &len);
+ if ((len == varLen) && !memcmp(match, varName, len)) {
cacheIt = 1;
goto gotMatch;
}
@@ -1054,6 +1055,14 @@ ProcedureMethodCompiledVarConnect(
}
if (cacheIt) {
infoPtr->cachedObjectVar = TclVarHashGetValue(hPtr);
+
+ /*
+ * We must keep a reference to the variable so everything will
+ * continue to work correctly even if it is unset; being unset does
+ * not end the life of the variable at this level. [Bug 3185009]
+ */
+
+ VarHashRefCount(infoPtr->cachedObjectVar)++;
}
return TclVarHashGetValue(hPtr);
}
@@ -1064,8 +1073,16 @@ ProcedureMethodCompiledVarDelete(
{
OOResVarInfo *infoPtr = (OOResVarInfo *) rPtr;
+ /*
+ * Release the reference to the variable if we were holding it.
+ */
+
+ if (infoPtr->cachedObjectVar) {
+ VarHashRefCount(infoPtr->cachedObjectVar)--;
+ TclCleanupVar((Var *) infoPtr->cachedObjectVar, NULL);
+ }
Tcl_DecrRefCount(infoPtr->variableObj);
- ckfree((char *) infoPtr);
+ ckfree(infoPtr);
}
static int
@@ -1090,7 +1107,7 @@ ProcedureMethodCompiledVarResolver(
return TCL_CONTINUE;
}
- infoPtr = (OOResVarInfo *) ckalloc(sizeof(OOResVarInfo));
+ infoPtr = ckalloc(sizeof(OOResVarInfo));
infoPtr->info.fetchProc = ProcedureMethodCompiledVarConnect;
infoPtr->info.deleteProc = ProcedureMethodCompiledVarDelete;
infoPtr->cachedObjectVar = NULL;
@@ -1187,15 +1204,6 @@ ConstructorErrorHandler(
const char *objectName, *kindName;
int objectNameLen;
- if (Tcl_GetErrorLine(interp) == (int) 0xDEADBEEF) {
- /*
- * Horrible hack to deal with certain constructors that must not add
- * information to the error trace.
- */
-
- return;
- }
-
if (mPtr->declaringObjectPtr != NULL) {
declarerPtr = mPtr->declaringObjectPtr;
kindName = "object";
@@ -1261,7 +1269,7 @@ DeleteProcedureMethodRecord(
if (pmPtr->deleteClientdataProc) {
pmPtr->deleteClientdataProc(pmPtr->clientData);
}
- ckfree((char *) pmPtr);
+ ckfree(pmPtr);
}
static void
@@ -1282,12 +1290,57 @@ CloneProcedureMethod(
ClientData *newClientData)
{
ProcedureMethod *pmPtr = clientData;
- ProcedureMethod *pm2Ptr = (ProcedureMethod *)
- ckalloc(sizeof(ProcedureMethod));
+ ProcedureMethod *pm2Ptr;
+ Tcl_Obj *bodyObj, *argsObj;
+ CompiledLocal *localPtr;
+
+ /*
+ * Copy the argument list.
+ */
+
+ argsObj = Tcl_NewObj();
+ for (localPtr=pmPtr->procPtr->firstLocalPtr; localPtr!=NULL;
+ localPtr=localPtr->nextPtr) {
+ if (TclIsVarArgument(localPtr)) {
+ Tcl_Obj *argObj = Tcl_NewObj();
+
+ Tcl_ListObjAppendElement(NULL, argObj,
+ Tcl_NewStringObj(localPtr->name, -1));
+ if (localPtr->defValuePtr != NULL) {
+ Tcl_ListObjAppendElement(NULL, argObj, localPtr->defValuePtr);
+ }
+ Tcl_ListObjAppendElement(NULL, argsObj, argObj);
+ }
+ }
+
+ /*
+ * Must strip the internal representation in order to ensure that any
+ * bound references to instance variables are removed. [Bug 3609693]
+ */
+
+ bodyObj = Tcl_DuplicateObj(pmPtr->procPtr->bodyPtr);
+ TclFreeIntRep(bodyObj);
+
+ /*
+ * Create the actual copy of the method record, manufacturing a new proc
+ * record.
+ */
+ pm2Ptr = ckalloc(sizeof(ProcedureMethod));
memcpy(pm2Ptr, pmPtr, sizeof(ProcedureMethod));
pm2Ptr->refCount = 1;
- pm2Ptr->procPtr->refCount++;
+ Tcl_IncrRefCount(argsObj);
+ Tcl_IncrRefCount(bodyObj);
+ if (TclCreateProc(interp, NULL, "", argsObj, bodyObj,
+ &pm2Ptr->procPtr) != TCL_OK) {
+ Tcl_DecrRefCount(argsObj);
+ Tcl_DecrRefCount(bodyObj);
+ ckfree(pm2Ptr);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(argsObj);
+ Tcl_DecrRefCount(bodyObj);
+
if (pmPtr->cloneClientdataProc) {
pm2Ptr->clientData = pmPtr->cloneClientdataProc(pmPtr->clientData);
}
@@ -1322,15 +1375,15 @@ TclOONewForwardInstanceMethod(
return NULL;
}
if (prefixLen < 1) {
- Tcl_AppendResult(interp, "method forward prefix must be non-empty",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "method forward prefix must be non-empty", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL);
return NULL;
}
- fmPtr = (ForwardMethod *) ckalloc(sizeof(ForwardMethod));
+ fmPtr = ckalloc(sizeof(ForwardMethod));
fmPtr->prefixObj = prefixObj;
Tcl_ListObjIndex(interp, prefixObj, 0, &cmdObj);
- fmPtr->fullyQualified = (strncmp(TclGetString(cmdObj), "::", 2) == 0);
Tcl_IncrRefCount(prefixObj);
return (Method *) Tcl_NewInstanceMethod(interp, (Tcl_Object) oPtr,
nameObj, flags, &fwdMethodType, fmPtr);
@@ -1363,15 +1416,15 @@ TclOONewForwardMethod(
return NULL;
}
if (prefixLen < 1) {
- Tcl_AppendResult(interp, "method forward prefix must be non-empty",
- NULL);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "method forward prefix must be non-empty", -1));
+ Tcl_SetErrorCode(interp, "TCL", "OO", "BAD_FORWARD", NULL);
return NULL;
}
- fmPtr = (ForwardMethod *) ckalloc(sizeof(ForwardMethod));
+ fmPtr = ckalloc(sizeof(ForwardMethod));
fmPtr->prefixObj = prefixObj;
Tcl_ListObjIndex(interp, prefixObj, 0, &cmdObj);
- fmPtr->fullyQualified = (strncmp(TclGetString(cmdObj), "::", 2) == 0);
Tcl_IncrRefCount(prefixObj);
return (Method *) Tcl_NewMethod(interp, (Tcl_Class) clsPtr, nameObj,
flags, &fwdMethodType, fmPtr);
@@ -1400,7 +1453,6 @@ InvokeForwardMethod(
ForwardMethod *fmPtr = clientData;
Tcl_Obj **argObjs, **prefixObjs;
int numPrefixes, len, skip = contextPtr->skip;
- Command *cmdPtr;
/*
* Build the real list of arguments to use. Note that we know that the
@@ -1412,15 +1464,10 @@ InvokeForwardMethod(
Tcl_ListObjGetElements(NULL, fmPtr->prefixObj, &numPrefixes, &prefixObjs);
argObjs = InitEnsembleRewrite(interp, objc, objv, skip,
numPrefixes, prefixObjs, &len);
-
- if (fmPtr->fullyQualified) {
- cmdPtr = NULL;
- } else {
- cmdPtr = (Command *) Tcl_FindCommand(interp, TclGetString(argObjs[0]),
- contextPtr->oPtr->namespacePtr, 0 /* normal lookup */);
- }
Tcl_NRAddCallback(interp, FinalizeForwardCall, argObjs, NULL, NULL, NULL);
- return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_INVOKE, cmdPtr);
+ ((Interp *)interp)->lookupNsPtr
+ = (Namespace *) contextPtr->oPtr->namespacePtr;
+ return TclNREvalObjv(interp, len, argObjs, TCL_EVAL_NOERR, NULL);
}
static int
@@ -1452,7 +1499,7 @@ DeleteForwardMethod(
ForwardMethod *fmPtr = clientData;
Tcl_DecrRefCount(fmPtr->prefixObj);
- ckfree((char *) fmPtr);
+ ckfree(fmPtr);
}
static int
@@ -1462,10 +1509,9 @@ CloneForwardMethod(
ClientData *newClientData)
{
ForwardMethod *fmPtr = clientData;
- ForwardMethod *fm2Ptr = (ForwardMethod *) ckalloc(sizeof(ForwardMethod));
+ ForwardMethod *fm2Ptr = ckalloc(sizeof(ForwardMethod));
fm2Ptr->prefixObj = fmPtr->prefixObj;
- fm2Ptr->fullyQualified = fmPtr->fullyQualified;
Tcl_IncrRefCount(fm2Ptr->prefixObj);
*newClientData = fm2Ptr;
return TCL_OK;
@@ -1655,9 +1701,9 @@ Tcl_Method
TclOONewProcInstanceMethodEx(
Tcl_Interp *interp, /* The interpreter containing the object. */
Tcl_Object oPtr, /* The object to modify. */
- TclOO_PreCallProc preCallPtr,
- TclOO_PostCallProc postCallPtr,
- ProcErrorProc errProc,
+ TclOO_PreCallProc *preCallPtr,
+ TclOO_PostCallProc *postCallPtr,
+ ProcErrorProc *errProc,
ClientData clientData,
Tcl_Obj *nameObj, /* The name of the method, which must not be
* NULL. */
@@ -1692,9 +1738,9 @@ Tcl_Method
TclOONewProcMethodEx(
Tcl_Interp *interp, /* The interpreter containing the class. */
Tcl_Class clsPtr, /* The class to modify. */
- TclOO_PreCallProc preCallPtr,
- TclOO_PostCallProc postCallPtr,
- ProcErrorProc errProc,
+ TclOO_PreCallProc *preCallPtr,
+ TclOO_PostCallProc *postCallPtr,
+ ProcErrorProc *errProc,
ClientData clientData,
Tcl_Obj *nameObj, /* The name of the method, which may be NULL;
* if so, up to caller to manage storage