summaryrefslogtreecommitdiffstats
path: root/tcl8.6/pkgs/itcl4.1.1/generic
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2018-01-02 21:03:49 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2018-01-02 21:03:49 (GMT)
commit914501b5b992e7b6c7e0a4c958712a8ba9cab41c (patch)
treeedbc059b9557d5fdb79e5a5c47889bc54708da53 /tcl8.6/pkgs/itcl4.1.1/generic
parentf88c190a01bc7f57e79dfaf91a3c0c48c2031549 (diff)
downloadblt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.zip
blt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.tar.gz
blt-914501b5b992e7b6c7e0a4c958712a8ba9cab41c.tar.bz2
upgrade to tcl/tk 8.6.8
Diffstat (limited to 'tcl8.6/pkgs/itcl4.1.1/generic')
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/clientData16
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itcl.decls621
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itcl.h203
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.c377
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.h34
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclBase.c838
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclBuiltin.c3783
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclClass.c2640
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclCmd.c2182
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclDecls.h201
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclEnsemble.c2243
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclHelpers.c1510
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclInfo.c5327
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclInt.h854
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclIntDecls.h1046
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclLinkage.c326
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclMethod.c2721
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.c287
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.h87
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclObject.c3845
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclParse.c4309
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclResolve.c697
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclResolve2.c564
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclStubInit.c240
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclStubLib.c69
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclStubs.c231
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.c143
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.h38
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclTestRegisterC.c128
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclUtil.c1202
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclVCInt.h37
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.c234
-rw-r--r--tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.h46
33 files changed, 37079 insertions, 0 deletions
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/clientData b/tcl8.6/pkgs/itcl4.1.1/generic/clientData
new file mode 100644
index 0000000..62e3f3c
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/clientData
@@ -0,0 +1,16 @@
+itcl2TclOO.c: framePtr->clientData = NULL;
+itcl2TclOO.c: framePtr->objc = objc;
+itcl2TclOO.c: framePtr->objv = objv;
+itcl2TclOO.c: framePtr->procPtr = procPtr;
+itcl2TclOO.c: if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
+itcl2TclOO.c: contextPtr = framePtr->clientData;
+itcl2TclOO.c: if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
+itclMigrate2TclCore.c: framePtr->isProcCallFrame |= FRAME_HAS_RESOLVER;
+itclMigrate2TclCore.c: framePtr->resolvePtr = resolvePtr;
+itclMigrate2TclCore.c: framePtr = framePtr->callerVarPtr;
+itclMigrate2TclCore.c: framePtr = framePtr->callerVarPtr;
+itclMigrate2TclCore.c: return (Tcl_Namespace *)framePtr->nsPtr;
+itclMigrate2TclCore.c: return framePtr->clientData;
+itclMigrate2TclCore.c: ((Interp *)interp)->framePtr->nsPtr = (Namespace *)nsPtr;
+itclMigrate2TclCore.c: return ((Interp *)interp)->framePtr->objc;
+itclMigrate2TclCore.c: return ((Interp *)interp)->framePtr->objv;
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itcl.decls b/tcl8.6/pkgs/itcl4.1.1/generic/itcl.decls
new file mode 100644
index 0000000..1530464
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itcl.decls
@@ -0,0 +1,621 @@
+# -*- tcl -*-
+
+# public API
+library itcl
+interface itcl
+hooks {itclInt}
+epoch 0
+scspec ITCLAPI
+
+# Declare each of the functions in the public Tcl interface. Note that
+# the an index should never be reused for a different function in order
+# to preserve backwards compatibility.
+
+declare 2 {
+ int Itcl_RegisterC(Tcl_Interp *interp, const char *name,
+ Tcl_CmdProc *proc, ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc)
+}
+declare 3 {
+ int Itcl_RegisterObjC(Tcl_Interp *interp, const char *name,
+ Tcl_ObjCmdProc *proc, ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc)
+}
+declare 4 {
+ int Itcl_FindC(Tcl_Interp *interp, const char *name,
+ Tcl_CmdProc **argProcPtr, Tcl_ObjCmdProc **objProcPtr,
+ ClientData *cDataPtr)
+}
+declare 5 {
+ void Itcl_InitStack(Itcl_Stack *stack)
+}
+declare 6 {
+ void Itcl_DeleteStack(Itcl_Stack *stack)
+}
+declare 7 {
+ void Itcl_PushStack(ClientData cdata, Itcl_Stack *stack)
+}
+declare 8 {
+ ClientData Itcl_PopStack(Itcl_Stack *stack)
+}
+declare 9 {
+ ClientData Itcl_PeekStack(Itcl_Stack *stack)
+}
+declare 10 {
+ ClientData Itcl_GetStackValue(Itcl_Stack *stack, int pos)
+}
+declare 11 {
+ void Itcl_InitList(Itcl_List *listPtr)
+}
+declare 12 {
+ void Itcl_DeleteList(Itcl_List *listPtr)
+}
+declare 13 {
+ Itcl_ListElem *Itcl_CreateListElem(Itcl_List *listPtr)
+}
+declare 14 {
+ Itcl_ListElem *Itcl_DeleteListElem(Itcl_ListElem *elemPtr)
+}
+declare 15 {
+ Itcl_ListElem *Itcl_InsertList(Itcl_List *listPtr, ClientData val)
+}
+declare 16 {
+ Itcl_ListElem *Itcl_InsertListElem(Itcl_ListElem *pos, ClientData val)
+}
+declare 17 {
+ Itcl_ListElem *Itcl_AppendList(Itcl_List *listPtr, ClientData val)
+}
+declare 18 {
+ Itcl_ListElem *Itcl_AppendListElem(Itcl_ListElem *pos, ClientData val)
+}
+declare 19 {
+ void Itcl_SetListValue(Itcl_ListElem *elemPtr, ClientData val)
+}
+declare 20 {
+ void Itcl_EventuallyFree(ClientData cdata, Tcl_FreeProc *fproc)
+}
+declare 21 {
+ void Itcl_PreserveData(ClientData cdata)
+}
+declare 22 {
+ void Itcl_ReleaseData(ClientData cdata)
+}
+declare 23 {
+ Itcl_InterpState Itcl_SaveInterpState(Tcl_Interp *interp, int status)
+}
+declare 24 {
+ int Itcl_RestoreInterpState(Tcl_Interp *interp, Itcl_InterpState state)
+}
+declare 25 {
+ void Itcl_DiscardInterpState(Itcl_InterpState state)
+}
+
+
+# private API
+interface itclInt
+#
+# Functions used within the package, but not considered "public"
+#
+
+declare 0 {
+ int Itcl_IsClassNamespace(Tcl_Namespace *namesp)
+}
+declare 1 {
+ int Itcl_IsClass(Tcl_Command cmd)
+}
+declare 2 {
+ ItclClass *Itcl_FindClass(Tcl_Interp *interp, const char *path, int autoload)
+}
+declare 3 {
+ int Itcl_FindObject(Tcl_Interp *interp, const char *name, ItclObject **roPtr)
+}
+declare 4 {
+ int Itcl_IsObject(Tcl_Command cmd)
+}
+declare 5 {
+ int Itcl_ObjectIsa(ItclObject *contextObj, ItclClass *cdefn)
+}
+declare 6 {
+ int Itcl_Protection(Tcl_Interp *interp, int newLevel)
+}
+declare 7 {
+ const char *Itcl_ProtectionStr(int pLevel)
+}
+declare 8 {
+ int Itcl_CanAccess(ItclMemberFunc *memberPtr, Tcl_Namespace *fromNsPtr)
+}
+declare 9 {
+ int Itcl_CanAccessFunc(ItclMemberFunc *mfunc, Tcl_Namespace *fromNsPtr)
+}
+declare 11 {
+ void Itcl_ParseNamespPath(const char *name, Tcl_DString *buffer,
+ const char **head, const char **tail)
+}
+declare 12 {
+ int Itcl_DecodeScopedCommand(Tcl_Interp *interp, const char *name,
+ Tcl_Namespace **rNsPtr, char **rCmdPtr)
+}
+declare 13 {
+ int Itcl_EvalArgs(Tcl_Interp *interp, int objc, Tcl_Obj *const objv[])
+}
+declare 14 {
+ Tcl_Obj *Itcl_CreateArgs(Tcl_Interp *interp, const char *string,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 17 {
+ int Itcl_GetContext(Tcl_Interp *interp, ItclClass **iclsPtrPtr,
+ ItclObject **ioPtrPtr)
+}
+declare 18 {
+ void Itcl_InitHierIter(ItclHierIter *iter, ItclClass *iclsPtr)
+}
+declare 19 {
+ void Itcl_DeleteHierIter(ItclHierIter *iter)
+}
+declare 20 {
+ ItclClass *Itcl_AdvanceHierIter(ItclHierIter *iter)
+}
+declare 21 {
+ int Itcl_FindClassesCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 22 {
+ int Itcl_FindObjectsCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 24 {
+ int Itcl_DelClassCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 25 {
+ int Itcl_DelObjectCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 26 {
+ int Itcl_ScopeCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 27 {
+ int Itcl_CodeCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 28 {
+ int Itcl_StubCreateCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 29 {
+ int Itcl_StubExistsCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 30 {
+ int Itcl_IsStub(Tcl_Command cmd)
+}
+
+
+#
+# Functions for manipulating classes
+#
+
+declare 31 {
+ int Itcl_CreateClass(Tcl_Interp *interp, const char *path,
+ ItclObjectInfo *info, ItclClass **rPtr)
+}
+declare 32 {
+ int Itcl_DeleteClass(Tcl_Interp *interp, ItclClass *iclsPtr)
+}
+declare 33 {
+ Tcl_Namespace *Itcl_FindClassNamespace(Tcl_Interp *interp, const char *path)
+}
+declare 34 {
+ int Itcl_HandleClass(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 38 {
+ void Itcl_BuildVirtualTables(ItclClass *iclsPtr)
+}
+declare 39 {
+ int Itcl_CreateVariable(Tcl_Interp *interp, ItclClass *iclsPtr,
+ Tcl_Obj *name, char *init, char *config, ItclVariable **ivPtr)
+}
+declare 40 {
+ void Itcl_DeleteVariable(char *cdata)
+}
+declare 41 {
+ const char *Itcl_GetCommonVar(Tcl_Interp *interp, const char *name,
+ ItclClass *contextClass)
+}
+
+
+#
+# Functions for manipulating objects
+#
+
+declare 44 {
+ int Itcl_CreateObject(Tcl_Interp *interp, const char* name, ItclClass *iclsPtr,
+ int objc, Tcl_Obj *const objv[], ItclObject **rioPtr)
+}
+declare 45 {
+ int Itcl_DeleteObject(Tcl_Interp *interp, ItclObject *contextObj)
+}
+declare 46 {
+ int Itcl_DestructObject(Tcl_Interp *interp, ItclObject *contextObj,
+ int flags)
+}
+declare 48 {
+ const char *Itcl_GetInstanceVar(Tcl_Interp *interp, const char *name,
+ ItclObject *contextIoPtr, ItclClass *contextIclsPtr)
+}
+
+#
+# Functions for manipulating methods and procs
+#
+
+declare 50 {
+ int Itcl_BodyCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 51 {
+ int Itcl_ConfigBodyCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 52 {
+ int Itcl_CreateMethod(Tcl_Interp *interp, ItclClass *iclsPtr,
+ Tcl_Obj *namePtr, const char *arglist, const char *body)
+}
+declare 53 {
+ int Itcl_CreateProc(Tcl_Interp *interp, ItclClass *iclsPtr,
+ Tcl_Obj *namePtr, const char *arglist, const char *body)
+}
+declare 54 {
+ int Itcl_CreateMemberFunc(Tcl_Interp *interp, ItclClass *iclsPtr,
+ Tcl_Obj *name, const char *arglist, const char *body,
+ ItclMemberFunc **mfuncPtr)
+}
+declare 55 {
+ int Itcl_ChangeMemberFunc(Tcl_Interp *interp, ItclMemberFunc *mfunc,
+ const char *arglist, const char *body)
+}
+declare 56 {
+ void Itcl_DeleteMemberFunc(char *cdata)
+}
+declare 57 {
+ int Itcl_CreateMemberCode(Tcl_Interp *interp, ItclClass *iclsPtr, \
+ const char *arglist, const char *body, ItclMemberCode **mcodePtr)
+}
+declare 58 {
+ void Itcl_DeleteMemberCode(char *cdata)
+}
+declare 59 {
+ int Itcl_GetMemberCode(Tcl_Interp *interp, ItclMemberFunc *mfunc)
+}
+declare 61 {
+ int Itcl_EvalMemberCode(Tcl_Interp *interp, ItclMemberFunc *mfunc,
+ ItclObject *contextObj, int objc, Tcl_Obj *const objv[])
+}
+declare 67 {
+ void Itcl_GetMemberFuncUsage(ItclMemberFunc *mfunc,
+ ItclObject *contextObj, Tcl_Obj *objPtr)
+}
+declare 68 {
+ int Itcl_ExecMethod(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 69 {
+ int Itcl_ExecProc(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 71 {
+ int Itcl_ConstructBase(Tcl_Interp *interp, ItclObject *contextObj,
+ ItclClass *contextClass)
+}
+declare 72 {
+ int Itcl_InvokeMethodIfExists(Tcl_Interp *interp, const char *name,
+ ItclClass *contextClass, ItclObject *contextObj, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 74 {
+ int Itcl_ReportFuncErrors(Tcl_Interp *interp, ItclMemberFunc *mfunc,
+ ItclObject *contextObj, int result)
+}
+
+
+#
+# Commands for parsing class definitions
+#
+
+declare 75 {
+ int Itcl_ParseInit(Tcl_Interp *interp, ItclObjectInfo *info)
+}
+declare 76 {
+ int Itcl_ClassCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 77 {
+ int Itcl_ClassInheritCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 78 {
+ int Itcl_ClassProtectionCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 79 {
+ int Itcl_ClassConstructorCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 80 {
+ int Itcl_ClassDestructorCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 81 {
+ int Itcl_ClassMethodCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 82 {
+ int Itcl_ClassProcCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 83 {
+ int Itcl_ClassVariableCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 84 {
+ int Itcl_ClassCommonCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 85 {
+ int Itcl_ParseVarResolver(Tcl_Interp *interp, const char *name,
+ Tcl_Namespace *contextNs, int flags, Tcl_Var *rPtr)
+}
+
+#
+# Commands in the "builtin" namespace
+#
+
+declare 86 {
+ int Itcl_BiInit(Tcl_Interp *interp, ItclObjectInfo *infoPtr)
+}
+declare 87 {
+ int Itcl_InstallBiMethods(Tcl_Interp *interp, ItclClass *cdefn)
+}
+declare 88 {
+ int Itcl_BiIsaCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 89 {
+ int Itcl_BiConfigureCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 90 {
+ int Itcl_BiCgetCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 91 {
+ int Itcl_BiChainCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 92 {
+ int Itcl_BiInfoClassCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 93 {
+ int Itcl_BiInfoInheritCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 94 {
+ int Itcl_BiInfoHeritageCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 95 {
+ int Itcl_BiInfoFunctionCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 96 {
+ int Itcl_BiInfoVariableCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 97 {
+ int Itcl_BiInfoBodyCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 98 {
+ int Itcl_BiInfoArgsCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+#declare 99 {
+# int Itcl_DefaultInfoCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+# Tcl_Obj *const objv[])
+#}
+
+
+#
+# Ensembles
+#
+
+declare 100 {
+ int Itcl_EnsembleInit(Tcl_Interp *interp)
+}
+declare 101 {
+ int Itcl_CreateEnsemble(Tcl_Interp *interp, const char *ensName)
+}
+declare 102 {
+ int Itcl_AddEnsemblePart(Tcl_Interp *interp, const char *ensName,
+ const char *partName, const char *usageInfo, Tcl_ObjCmdProc *objProc,
+ ClientData clientData, Tcl_CmdDeleteProc *deleteProc)
+}
+declare 103 {
+ int Itcl_GetEnsemblePart(Tcl_Interp *interp, const char *ensName,
+ const char *partName, Tcl_CmdInfo *infoPtr)
+}
+declare 104 {
+ int Itcl_IsEnsemble(Tcl_CmdInfo *infoPtr)
+}
+declare 105 {
+ int Itcl_GetEnsembleUsage(Tcl_Interp *interp, const char *ensName,
+ Tcl_Obj *objPtr)
+}
+declare 106 {
+ int Itcl_GetEnsembleUsageForObj(Tcl_Interp *interp, Tcl_Obj *ensObjPtr,
+ Tcl_Obj *objPtr)
+}
+declare 107 {
+ int Itcl_EnsembleCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 108 {
+ int Itcl_EnsPartCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 109 {
+ int Itcl_EnsembleErrorCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 115 {
+ void Itcl_Assert(const char *testExpr, const char *fileName, int lineNum)
+}
+declare 116 {
+ int Itcl_IsObjectCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 117 {
+ int Itcl_IsClassCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+
+#
+# new commands to use TclOO functionality
+#
+
+declare 140 {
+ int Itcl_FilterAddCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 141 {
+ int Itcl_FilterDeleteCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 142 {
+ int Itcl_ForwardAddCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 143 {
+ int Itcl_ForwardDeleteCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 144 {
+ int Itcl_MixinAddCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 145 {
+ int Itcl_MixinDeleteCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+
+#
+# Helper commands
+#
+
+#declare 150 {
+# int Itcl_BiInfoCmd(ClientData clientData, Tcl_Interp *interp, int objc,
+# Tcl_Obj *const objv[])
+#}
+declare 151 {
+ int Itcl_BiInfoUnknownCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 152 {
+ int Itcl_BiInfoVarsCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 153 {
+ int Itcl_CanAccess2(ItclClass *iclsPtr, int protection,
+ Tcl_Namespace *fromNsPtr)
+}
+declare 160 {
+ int Itcl_SetCallFrameResolver(Tcl_Interp *interp,
+ Tcl_Resolve *resolvePtr)
+}
+declare 161 {
+ int ItclEnsembleSubCmd(ClientData clientData, Tcl_Interp *interp,
+ const char *ensembleName, int objc, Tcl_Obj *const *objv,
+ const char *functionName)
+}
+declare 162 {
+ Tcl_Namespace *Itcl_GetUplevelNamespace(Tcl_Interp *interp, int level)
+}
+declare 163 {
+ ClientData Itcl_GetCallFrameClientData(Tcl_Interp *interp)
+}
+declare 165 {
+ int Itcl_SetCallFrameNamespace(Tcl_Interp *interp, Tcl_Namespace *nsPtr)
+}
+declare 166 {
+ int Itcl_GetCallFrameObjc(Tcl_Interp *interp)
+}
+declare 167 {
+ Tcl_Obj *const *Itcl_GetCallFrameObjv(Tcl_Interp *interp)
+}
+declare 168 {
+ int Itcl_NWidgetCmd(ClientData infoPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 169 {
+ int Itcl_AddOptionCmd(ClientData infoPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 170 {
+ int Itcl_AddComponentCmd(ClientData infoPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 171 {
+ int Itcl_BiInfoOptionCmd(ClientData dummy, Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[])
+}
+declare 172 {
+ int Itcl_BiInfoComponentCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[])
+}
+declare 173 {
+ int Itcl_RenameCommand(Tcl_Interp *interp, const char *oldName,
+ const char *newName)
+}
+declare 174 {
+ int Itcl_PushCallFrame(Tcl_Interp *interp, Tcl_CallFrame *framePtr,
+ Tcl_Namespace *nsPtr, int isProcCallFrame)
+}
+declare 175 {
+ void Itcl_PopCallFrame(Tcl_Interp *interp)
+}
+declare 176 {
+ Tcl_CallFrame *Itcl_GetUplevelCallFrame(Tcl_Interp *interp,
+ int level)
+}
+declare 177 {
+ Tcl_CallFrame *Itcl_ActivateCallFrame(Tcl_Interp *interp,
+ Tcl_CallFrame *framePtr)
+}
+declare 178 {
+ const char* ItclSetInstanceVar(Tcl_Interp *interp,
+ const char *name, const char *name2, const char *value,
+ ItclObject *contextIoPtr, ItclClass *contextIclsPtr)
+}
+declare 179 {
+ Tcl_Obj * ItclCapitalize(const char *str)
+}
+declare 180 {
+ int ItclClassBaseCmd(ClientData clientData, Tcl_Interp *interp,
+ int flags, int objc, Tcl_Obj *const objv[], ItclClass **iclsPtrPtr)
+}
+declare 181 {
+ int ItclCreateComponent(Tcl_Interp *interp, ItclClass *iclsPtr,
+ Tcl_Obj *componentPtr, int type, ItclComponent **icPtrPtr)
+}
+declare 182 {
+ void Itcl_SetContext(Tcl_Interp *interp, ItclObject *ioPtr)
+}
+declare 183 {
+ void Itcl_UnsetContext(Tcl_Interp *interp)
+}
+declare 184 {
+ const char * ItclGetInstanceVar(Tcl_Interp *interp, const char *name,
+ const char *name2, ItclObject *ioPtr, ItclClass *iclsPtr)
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itcl.h b/tcl8.6/pkgs/itcl4.1.1/generic/itcl.h
new file mode 100644
index 0000000..23a84a6
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itcl.h
@@ -0,0 +1,203 @@
+/*
+ * itcl.h --
+ *
+ * This file contains definitions for the C-implemeted part of a Itcl
+ * this version of [incr Tcl] (Itcl) is a completely new implementation
+ * based on TclOO extension of Tcl 8.5
+ * It tries to provide the same interfaces as the original implementation
+ * of Michael J. McLennan
+ * Some small pieces of code are taken from that implementation
+ *
+ * Copyright (c) 2007 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * ADDING [incr Tcl] TO A Tcl-BASED APPLICATION:
+ *
+ * To add [incr Tcl] facilities to a Tcl application, modify the
+ * Tcl_AppInit() routine as follows:
+ *
+ * 1) Include this header file near the top of the file containing
+ * Tcl_AppInit():
+ *
+ * #include "itcl.h"
+*
+ * 2) Within the body of Tcl_AppInit(), add the following lines:
+ *
+ * if (Itcl_Init(interp) == TCL_ERROR) {
+ * return TCL_ERROR;
+ * }
+ *
+ * 3) Link your application with libitcl.a
+ *
+ * NOTE: An example file "tclAppInit.c" containing the changes shown
+ * above is included in this distribution.
+ *
+ *---------------------------------------------------------------------
+ */
+
+#ifndef ITCL_H_INCLUDED
+#define ITCL_H_INCLUDED
+
+#include <tcl.h>
+
+#if (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6)
+# error Itcl 4 build requires tcl.h from Tcl 8.6 or later
+#endif
+
+/*
+ * For C++ compilers, use extern "C"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef TCL_ALPHA_RELEASE
+# define TCL_ALPHA_RELEASE 0
+#endif
+#ifndef TCL_BETA_RELEASE
+# define TCL_BETA_RELEASE 1
+#endif
+#ifndef TCL_FINAL_RELEASE
+# define TCL_FINAL_RELEASE 2
+#endif
+
+#define ITCL_MAJOR_VERSION 4
+#define ITCL_MINOR_VERSION 1
+#define ITCL_RELEASE_LEVEL TCL_FINAL_RELEASE
+#define ITCL_RELEASE_SERIAL 1
+
+#define ITCL_VERSION "4.1"
+#define ITCL_PATCH_LEVEL "4.1.1"
+
+
+/*
+ * A special definition used to allow this header file to be included from
+ * windows resource files so that they can obtain version information.
+ * RC_INVOKED is defined by default by the windows RC tool.
+ *
+ * Resource compilers don't like all the C stuff, like typedefs and function
+ * declarations, that occur below, so block them out.
+ */
+
+#ifndef RC_INVOKED
+
+#define ITCL_NAMESPACE "::itcl"
+
+#ifndef ITCLAPI
+# if defined(BUILD_itcl)
+# define ITCLAPI MODULE_SCOPE
+# else
+# define ITCLAPI extern
+# undef USE_ITCL_STUBS
+# define USE_ITCL_STUBS 1
+# endif
+#endif
+
+#if defined(BUILD_itcl) && !defined(STATIC_BUILD)
+# define ITCL_EXTERN extern DLLEXPORT
+#else
+# define ITCL_EXTERN extern
+#endif
+
+ITCL_EXTERN int Itcl_Init(Tcl_Interp *interp);
+ITCL_EXTERN int Itcl_SafeInit(Tcl_Interp *interp);
+
+/*
+ * Protection levels:
+ *
+ * ITCL_PUBLIC - accessible from any namespace
+ * ITCL_PROTECTED - accessible from namespace that imports in "protected" mode
+ * ITCL_PRIVATE - accessible only within the namespace that contains it
+ */
+#define ITCL_PUBLIC 1
+#define ITCL_PROTECTED 2
+#define ITCL_PRIVATE 3
+#define ITCL_DEFAULT_PROTECT 4
+
+/*
+ * Generic stack.
+ */
+typedef struct Itcl_Stack {
+ ClientData *values; /* values on stack */
+ int len; /* number of values on stack */
+ int max; /* maximum size of stack */
+ ClientData space[5]; /* initial space for stack data */
+} Itcl_Stack;
+
+#define Itcl_GetStackSize(stackPtr) ((stackPtr)->len)
+
+/*
+ * Generic linked list.
+ */
+struct Itcl_List;
+typedef struct Itcl_ListElem {
+ struct Itcl_List* owner; /* list containing this element */
+ ClientData value; /* value associated with this element */
+ struct Itcl_ListElem *prev; /* previous element in linked list */
+ struct Itcl_ListElem *next; /* next element in linked list */
+} Itcl_ListElem;
+
+typedef struct Itcl_List {
+ int validate; /* validation stamp */
+ int num; /* number of elements */
+ struct Itcl_ListElem *head; /* previous element in linked list */
+ struct Itcl_ListElem *tail; /* next element in linked list */
+} Itcl_List;
+
+#define Itcl_FirstListElem(listPtr) ((listPtr)->head)
+#define Itcl_LastListElem(listPtr) ((listPtr)->tail)
+#define Itcl_NextListElem(elemPtr) ((elemPtr)->next)
+#define Itcl_PrevListElem(elemPtr) ((elemPtr)->prev)
+#define Itcl_GetListLength(listPtr) ((listPtr)->num)
+#define Itcl_GetListValue(elemPtr) ((elemPtr)->value)
+
+/*
+ * Token representing the state of an interpreter.
+ */
+typedef struct Itcl_InterpState_ *Itcl_InterpState;
+
+
+/*
+ * Include all the public API, generated from itcl.decls.
+ */
+
+#include "itclDecls.h"
+
+#ifdef ITCL_PRESERVE_DEBUG
+#undef Itcl_PreserveData
+#undef Itcl_ReleaseData
+void ItclDbgPreserveData(ClientData cdata, int line, const char *file);
+void ItclDbgReleaseData(ClientData cdata, int line, const char *file);
+#define Itcl_PreserveData(addr) ItclDbgPreserveData(addr, __LINE__, __FILE__)
+#define Itcl_ReleaseData(addr) ItclDbgReleaseData(addr, __LINE__, __FILE__)
+#endif
+
+#endif /* RC_INVOKED */
+
+/*
+ * end block for C++
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ITCL_H_INCLUDED */
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.c b/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.c
new file mode 100644
index 0000000..30ea887
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.c
@@ -0,0 +1,377 @@
+/*
+ * itcl2TclOO.c --
+ *
+ * This file contains code to create and manage methods.
+ *
+ * Copyright (c) 2007 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <tclInt.h>
+#include <tclOOInt.h>
+#include "itclInt.h"
+
+void *
+Itcl_GetCurrentCallbackPtr(
+ Tcl_Interp *interp)
+{
+ return TOP_CB(interp);
+}
+
+int
+Itcl_NRRunCallbacks(
+ Tcl_Interp *interp,
+ void *rootPtr)
+{
+ return TclNRRunCallbacks(interp, TCL_OK, rootPtr);
+}
+
+static int
+CallFinalizePMCall(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Namespace *nsPtr = data[0];
+ TclOO_PostCallProc *postCallProc = (TclOO_PostCallProc *)data[1];
+ ClientData clientData = data[2];
+
+ /*
+ * Give the post-call callback a chance to do some cleanup. Note that at
+ * this point the call frame itself is invalid; it's already been popped.
+ */
+
+ return postCallProc(clientData, interp, NULL, nsPtr, result);
+}
+
+static int
+FreeCommand(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Command *cmdPtr = data[0];
+ Proc *procPtr = data[1];
+
+ ckfree(cmdPtr);
+ procPtr->cmdPtr = NULL;
+
+ return result;
+}
+
+static int
+Tcl_InvokeClassProcedureMethod(
+ Tcl_Interp *interp,
+ Tcl_Obj *namePtr, /* name of the method */
+ Tcl_Namespace *nsPtr, /* namespace for calling method */
+ ProcedureMethod *pmPtr, /* method type specific data */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Arguments as actually seen. */
+{
+ Proc *procPtr = pmPtr->procPtr;
+ CallFrame *framePtr = NULL;
+ CallFrame **framePtrPtr1 = &framePtr;
+ Tcl_CallFrame **framePtrPtr = (Tcl_CallFrame **)framePtrPtr1;
+ int result;
+
+ if (procPtr->cmdPtr == NULL) {
+ Command *cmdPtr = ckalloc(sizeof(Command));
+
+ memset(cmdPtr, 0, sizeof(Command));
+ cmdPtr->nsPtr = (Namespace *) nsPtr;
+ cmdPtr->clientData = NULL;
+ procPtr->cmdPtr = cmdPtr;
+ Tcl_NRAddCallback(interp, FreeCommand, cmdPtr, procPtr, NULL, NULL);
+ }
+
+ result = TclProcCompileProc(interp, procPtr, procPtr->bodyPtr,
+ (Namespace *) nsPtr, "body of method", Tcl_GetString(namePtr));
+ if (result != TCL_OK) {
+ return result;
+ }
+ /*
+ * Make the stack frame and fill it out with information about this call.
+ * This operation may fail.
+ */
+
+
+ result = TclPushStackFrame(interp, framePtrPtr, nsPtr, FRAME_IS_PROC);
+ if (result != TCL_OK) {
+ return result;
+ }
+
+ framePtr->clientData = NULL;
+ framePtr->objc = objc;
+ framePtr->objv = objv;
+ framePtr->procPtr = procPtr;
+
+ /*
+ * Give the pre-call callback a chance to do some setup and, possibly,
+ * veto the call.
+ */
+
+ if (pmPtr->preCallProc != NULL) {
+ int isFinished;
+
+ result = pmPtr->preCallProc(pmPtr->clientData, interp, NULL,
+ (Tcl_CallFrame *) framePtr, &isFinished);
+ if (isFinished || result != TCL_OK) {
+ Tcl_PopCallFrame(interp);
+ TclStackFree(interp, framePtr);
+ goto done;
+ }
+ }
+
+ /*
+ * Now invoke the body of the method. Note that we need to take special
+ * action when doing unknown processing to ensure that the missing method
+ * name is passed as an argument.
+ */
+
+ if (pmPtr->postCallProc) {
+ Tcl_NRAddCallback(interp, CallFinalizePMCall, nsPtr,
+ (Tcl_NRPostProc *)pmPtr->postCallProc, pmPtr->clientData, NULL);
+ }
+ return TclNRInterpProcCore(interp, namePtr, 1, pmPtr->errProc);
+
+done:
+ return result;
+}
+
+int
+Itcl_InvokeProcedureMethod(
+ ClientData clientData, /* Pointer to some per-method context. */
+ Tcl_Interp *interp,
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Arguments as actually seen. */
+{
+ Tcl_Namespace *nsPtr;
+ Method *mPtr;
+
+ mPtr = clientData;
+ if (mPtr->declaringClassPtr == NULL) {
+ /* that is the case for typemethods */
+ nsPtr = mPtr->declaringObjectPtr->namespacePtr;
+ } else {
+ nsPtr = mPtr->declaringClassPtr->thisPtr->namespacePtr;
+ }
+
+ return Tcl_InvokeClassProcedureMethod(interp, mPtr->namePtr, nsPtr,
+ mPtr->clientData, objc, objv);
+}
+
+static int
+FreeProcedureMethod(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ProcedureMethod *pmPtr = data[0];
+ ckfree(pmPtr);
+ return result;
+}
+
+int
+Itcl_InvokeEnsembleMethod(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, /* namespace to call the method in */
+ Tcl_Obj *namePtr, /* name of the method */
+ Tcl_Proc *procPtr,
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const *objv) /* Arguments as actually seen. */
+{
+ ProcedureMethod *pmPtr = ckalloc(sizeof(ProcedureMethod));
+
+ memset(pmPtr, 0, sizeof(ProcedureMethod));
+ pmPtr->version = TCLOO_PROCEDURE_METHOD_VERSION;
+ pmPtr->procPtr = (Proc *)procPtr;
+ pmPtr->flags = USE_DECLARER_NS;
+
+ Tcl_NRAddCallback(interp, FreeProcedureMethod, pmPtr, NULL, NULL, NULL);
+ return Tcl_InvokeClassProcedureMethod(interp, namePtr, nsPtr,
+ pmPtr, objc, objv);
+}
+
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Itcl_PublicObjectCmd, Itcl_PrivateObjectCmd --
+ *
+ * Main entry point for object invokations. The Public* and Private*
+ * wrapper functions are just thin wrappers around the main ObjectCmd
+ * function that does call chain creation, management and invokation.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+int
+Itcl_PublicObjectCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_Class clsPtr,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Object oPtr = (Tcl_Object)clientData;
+ int result;
+
+ result = TclOOInvokeObject(interp, oPtr, clsPtr, PUBLIC_METHOD,
+ objc, objv);
+ return result;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Itcl_NewProcClassMethod --
+ *
+ * Create a new procedure-like method for a class for Itcl.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+Tcl_Method
+Itcl_NewProcClassMethod(
+ Tcl_Interp *interp, /* The interpreter containing the class. */
+ Tcl_Class clsPtr, /* The class to modify. */
+ 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
+ * (e.g., because it is a constructor or
+ * destructor). */
+ Tcl_Obj *argsObj, /* The formal argument list for the method,
+ * which may be NULL; if so, it is equivalent
+ * to an empty list. */
+ Tcl_Obj *bodyObj, /* The body of the method, which must not be
+ * NULL. */
+ ClientData *clientData2)
+{
+ Tcl_Method result;
+
+ result = TclOONewProcMethodEx(interp, clsPtr, preCallPtr, postCallPtr,
+ errProc, clientData, nameObj, argsObj, bodyObj,
+ PUBLIC_METHOD | USE_DECLARER_NS, clientData2);
+ return result;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Itcl_NewProcMethod --
+ *
+ * Create a new procedure-like method for an object for Itcl.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+Tcl_Method
+Itcl_NewProcMethod(
+ Tcl_Interp *interp, /* The interpreter containing the object. */
+ Tcl_Object oPtr, /* The object to modify. */
+ TclOO_PreCallProc *preCallPtr,
+ TclOO_PostCallProc *postCallPtr,
+ ProcErrorProc *errProc,
+ ClientData clientData,
+ Tcl_Obj *nameObj, /* The name of the method, which must not be
+ * NULL. */
+ Tcl_Obj *argsObj, /* The formal argument list for the method,
+ * which must not be NULL. */
+ Tcl_Obj *bodyObj, /* The body of the method, which must not be
+ * NULL. */
+ ClientData *clientData2)
+{
+ return TclOONewProcInstanceMethodEx(interp, oPtr, preCallPtr, postCallPtr,
+ errProc, clientData, nameObj, argsObj, bodyObj,
+ PUBLIC_METHOD | USE_DECLARER_NS, clientData2);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Itcl_NewForwardClassMethod --
+ *
+ * Create a new forwarded method for a class for Itcl.
+ *
+ * ----------------------------------------------------------------------
+ */
+
+Tcl_Method
+Itcl_NewForwardClassMethod(
+ Tcl_Interp *interp,
+ Tcl_Class clsPtr,
+ int flags,
+ Tcl_Obj *nameObj,
+ Tcl_Obj *prefixObj)
+{
+ return (Tcl_Method)TclOONewForwardMethod(interp, (Class *)clsPtr,
+ flags, nameObj, prefixObj);
+}
+
+
+static Tcl_Obj *
+Itcl_TclOOObjectName(
+ Tcl_Interp *interp,
+ Object *oPtr)
+{
+ Tcl_Obj *namePtr;
+
+ if (oPtr->cachedNameObj) {
+ return oPtr->cachedNameObj;
+ }
+ namePtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, oPtr->command, namePtr);
+ Tcl_IncrRefCount(namePtr);
+ oPtr->cachedNameObj = namePtr;
+ return namePtr;
+}
+
+int
+Itcl_SelfCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Interp *iPtr = (Interp *) interp;
+ CallFrame *framePtr = iPtr->varFramePtr;
+ CallContext *contextPtr;
+
+ if (!Itcl_IsMethodCallFrame(interp)) {
+ Tcl_AppendResult(interp, TclGetString(objv[0]),
+ " may only be called from inside a method", NULL);
+ return TCL_ERROR;
+ }
+
+ contextPtr = framePtr->clientData;
+
+ if (objc == 1) {
+ Tcl_SetObjResult(interp, Itcl_TclOOObjectName(interp, contextPtr->oPtr));
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+int
+Itcl_IsMethodCallFrame(
+ Tcl_Interp *interp)
+{
+ Interp *iPtr = (Interp *) interp;
+ CallFrame *framePtr = iPtr->varFramePtr;
+ if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
+ return 0;
+ }
+ return 1;
+}
+
+/* needed as work around for problem in Tcl 8.6.2 TclOO */
+void
+Itcl_IncrObjectRefCount(Tcl_Object ptr) {
+ Object * oPtr = (Object *) ptr;
+ oPtr->refCount++;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.h b/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.h
new file mode 100644
index 0000000..4f9df0a
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itcl2TclOO.h
@@ -0,0 +1,34 @@
+
+#ifndef _TCLINT
+typedef void (ProcErrorProc)(Tcl_Interp *interp, Tcl_Obj *procNameObj);
+#endif
+
+#ifndef TCL_OO_INTERNAL_H
+typedef int (TclOO_PreCallProc)(ClientData clientData, Tcl_Interp *interp,
+ Tcl_ObjectContext context, Tcl_CallFrame *framePtr, int *isFinished);
+typedef int (TclOO_PostCallProc)(ClientData clientData, Tcl_Interp *interp,
+ Tcl_ObjectContext context, Tcl_Namespace *namespacePtr, int result);
+#endif
+
+MODULE_SCOPE int Itcl_NRRunCallbacks(Tcl_Interp *interp, void *rootPtr);
+MODULE_SCOPE void * Itcl_GetCurrentCallbackPtr(Tcl_Interp *interp);
+MODULE_SCOPE Tcl_Method Itcl_NewProcClassMethod(Tcl_Interp *interp, Tcl_Class clsPtr,
+ TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr,
+ ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj,
+ Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ClientData *clientData2);
+MODULE_SCOPE Tcl_Method Itcl_NewProcMethod(Tcl_Interp *interp, Tcl_Object oPtr,
+ TclOO_PreCallProc *preCallPtr, TclOO_PostCallProc *postCallPtr,
+ ProcErrorProc *errProc, ClientData clientData, Tcl_Obj *nameObj,
+ Tcl_Obj *argsObj, Tcl_Obj *bodyObj, ClientData *clientData2);
+MODULE_SCOPE int Itcl_PublicObjectCmd(ClientData clientData, Tcl_Interp *interp,
+ Tcl_Class clsPtr, int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE Tcl_Method Itcl_NewForwardClassMethod(Tcl_Interp *interp,
+ Tcl_Class clsPtr, int flags, Tcl_Obj *nameObj, Tcl_Obj *prefixObj);
+MODULE_SCOPE int Itcl_SelfCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE int Itcl_IsMethodCallFrame(Tcl_Interp *interp);
+MODULE_SCOPE int Itcl_InvokeEnsembleMethod(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ Tcl_Obj *namePtr, Tcl_Proc *procPtr, int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE int Itcl_InvokeProcedureMethod(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE void Itcl_IncrObjectRefCount(Tcl_Object ptr);
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclBase.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclBase.c
new file mode 100644
index 0000000..450074a
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclBase.c
@@ -0,0 +1,838 @@
+/*
+ * itclBase.c --
+ *
+ * This file contains the C-implemented startup part of an
+ * Itcl implemenatation
+ *
+ * Copyright (c) 2007 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <stdlib.h>
+#include "itclInt.h"
+
+static Tcl_ObjCmdProc ItclFinishCmd;
+static Tcl_ObjCmdProc ItclSetHullWindowName;
+static Tcl_ObjCmdProc ItclCheckSetItclHull;
+
+#ifdef OBJ_REF_COUNT_DEBUG
+static Tcl_ObjCmdProc ItclDumpRefCountInfo;
+#endif
+
+#ifdef ITCL_PRESERVE_DEBUG
+static Tcl_ObjCmdProc ItclDumpPreserveInfo;
+#endif
+
+MODULE_SCOPE const ItclStubs itclStubs;
+
+static int Initialize(Tcl_Interp *interp);
+
+static const char initScript[] =
+"namespace eval ::itcl {\n"
+" proc _find_init {} {\n"
+" global env tcl_library\n"
+" variable library\n"
+" variable patchLevel\n"
+" rename _find_init {}\n"
+" if {[info exists library]} {\n"
+" lappend dirs $library\n"
+" } else {\n"
+" set dirs {}\n"
+" if {[info exists env(ITCL_LIBRARY)]} {\n"
+" lappend dirs $env(ITCL_LIBRARY)\n"
+" }\n"
+" lappend dirs [file join [file dirname $tcl_library] itcl$patchLevel]\n"
+" set bindir [file dirname [info nameofexecutable]]\n"
+" lappend dirs [file join . library]\n"
+" lappend dirs [file join $bindir .. lib itcl$patchLevel]\n"
+" lappend dirs [file join $bindir .. library]\n"
+" lappend dirs [file join $bindir .. .. library]\n"
+" lappend dirs [file join $bindir .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. itcl-ng itcl library]\n"
+" # On *nix, check the directories in the tcl_pkgPath\n"
+" # XXX JH - this looks unnecessary, maybe Darwin only?\n"
+" if {[string equal $::tcl_platform(platform) \"unix\"]} {\n"
+" foreach d $::tcl_pkgPath {\n"
+" lappend dirs $d\n"
+" lappend dirs [file join $d itcl$patchLevel]\n"
+" }\n"
+" }\n"
+" }\n"
+" foreach i $dirs {\n"
+" set library $i\n"
+" if {![catch {uplevel #0 [list source [file join $i itcl.tcl]]}]} {\n"
+" set library $i\n"
+" return\n"
+" }\n"
+" }\n"
+" set msg \"Can't find a usable itcl.tcl in the following directories:\n\"\n"
+" append msg \" $dirs\n\"\n"
+" append msg \"This probably means that Itcl/Tcl weren't installed properly.\n\"\n"
+" append msg \"If you know where the Itcl library directory was installed,\n\"\n"
+" append msg \"you can set the environment variable ITCL_LIBRARY to point\n\"\n"
+" append msg \"to the library directory.\n\"\n"
+" error $msg\n"
+" }\n"
+" _find_init\n"
+"}";
+
+/*
+ * The following script is used to initialize Itcl in a safe interpreter.
+ */
+
+static const char safeInitScript[] =
+"proc ::itcl::local {class name args} {\n"
+" set ptr [uplevel [list $class $name] $args]\n"
+" uplevel [list set itcl-local-$ptr $ptr]\n"
+" set cmd [uplevel namespace which -command $ptr]\n"
+" uplevel [list trace variable itcl-local-$ptr u \"::itcl::delete object $cmd; list\"]\n"
+" return $ptr\n"
+"}";
+
+static const char *clazzClassScript =
+"::oo::class create ::itcl::clazz {\n"
+" superclass ::oo::class\n"
+" method unknown args {\n"
+" ::tailcall ::itcl::parser::handleClass [::lindex [::info level 0] 0] [self] {*}$args\n"
+" }\n"
+" unexport create new unknown\n"
+"}";
+
+#define ITCL_IS_ENSEMBLE 0x1
+
+typedef struct ItclCmdsInfo {
+ const char *name;
+ int flags;
+} ItclCmdsInfo;
+static ItclCmdsInfo itclCmds [] = {
+ { "::itcl::class", 0},
+ { "::itcl::find", ITCL_IS_ENSEMBLE},
+ { "::itcl::delete", ITCL_IS_ENSEMBLE},
+ { "::itcl::is", ITCL_IS_ENSEMBLE},
+ { "::itcl::filter", ITCL_IS_ENSEMBLE},
+ { "::itcl::forward", ITCL_IS_ENSEMBLE},
+ { "::itcl::import::stub", ITCL_IS_ENSEMBLE},
+ { "::itcl::mixin", ITCL_IS_ENSEMBLE},
+ { "::itcl::parser::delegate", ITCL_IS_ENSEMBLE},
+ { "::itcl::type", 0},
+ { "::itcl::widget", 0},
+ { "::itcl::widgetadaptor", 0},
+ { "::itcl::nwidget", 0},
+ { "::itcl::addoption", 0},
+ { "::itcl::addobjectoption", 0},
+ { "::itcl::adddelegatedoption", 0},
+ { "::itcl::adddelegatedmethod", 0},
+ { "::itcl::addcomponent", 0},
+ { "::itcl::setcomponent", 0},
+ { "::itcl::extendedclass", 0},
+ { "::itcl::genericclass", 0},
+ { "::itcl::parser::delegate", ITCL_IS_ENSEMBLE},
+ { NULL, 0},
+};
+#ifdef ITCL_DEBUG_C_INTERFACE
+extern void RegisterDebugCFunctions( Tcl_Interp * interp);
+#endif
+
+static const Tcl_ObjectMetadataType objMDT = {
+ TCL_OO_METADATA_VERSION_CURRENT,
+ "ItclObject",
+ ItclDeleteObjectMetadata, /* Not really used yet */
+ NULL
+};
+
+static Tcl_MethodCallProc RootCallProc;
+
+const Tcl_MethodType itclRootMethodType = {
+ TCL_OO_METHOD_VERSION_CURRENT,
+ "itcl root method",
+ RootCallProc,
+ NULL,
+ NULL
+};
+
+static int
+RootCallProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext context,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Object oPtr = Tcl_ObjectContextObject(context);
+ ItclObject *ioPtr = Tcl_ObjectGetMetadata(oPtr, &objMDT);
+ ItclRootMethodProc *proc = (ItclRootMethodProc *)clientData;
+
+ return (*proc)(ioPtr, interp, objc, objv);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * FreeItclObjectInfo()
+ *
+ * called when an interp is deleted to free up memory
+ *
+ * ------------------------------------------------------------------------
+ */
+static void
+FreeItclObjectInfo(
+ ClientData clientData)
+{
+ ItclObjectInfo *infoPtr;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclFinishCmd(infoPtr, infoPtr->interp, 0, NULL);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Initialize()
+ *
+ * that is the starting point when loading the library
+ * it initializes all internal stuff
+ *
+ * ------------------------------------------------------------------------
+ */
+
+#ifdef NEW_PROTO_RESOLVER
+int ItclVarsAndCommandResolveInit(Tcl_Interp *interp);
+#endif
+
+static int
+Initialize (
+ Tcl_Interp *interp)
+{
+ Tcl_Namespace *nsPtr;
+ Tcl_Namespace *itclNs;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ const char * ret;
+ char *res_option;
+ int opt;
+ int isNew;
+ Tcl_Object clazzObjectPtr, root;
+ Tcl_Obj *objPtr;
+
+ if (Tcl_InitStubs(interp, "8.6", 0) == NULL) {
+ return TCL_ERROR;
+ }
+
+ ret = TclOOInitializeStubs(interp, "1.0");
+ if (ret == NULL) {
+ return TCL_ERROR;
+ }
+
+ nsPtr = Tcl_CreateNamespace(interp, ITCL_NAMESPACE, NULL, NULL);
+ if (nsPtr == NULL) {
+ Tcl_Panic("Itcl: cannot create namespace: \"%s\" \n", ITCL_NAMESPACE);
+ }
+
+ nsPtr = Tcl_CreateNamespace(interp, ITCL_NAMESPACE"::internal::dicts",
+ NULL, NULL);
+ if (nsPtr == NULL) {
+ Tcl_Panic("Itcl: cannot create namespace: \"%s::internal::dicts\" \n",
+ ITCL_NAMESPACE);
+ }
+
+ Tcl_CreateObjCommand(interp, ITCL_NAMESPACE"::finish", ItclFinishCmd,
+ NULL, NULL);
+
+ /* for debugging only !!! */
+#ifdef OBJ_REF_COUNT_DEBUG
+ Tcl_CreateObjCommand(interp,
+ ITCL_NAMESPACE"::dumprefcountinfo",
+ ItclDumpRefCountInfo, NULL, NULL);
+#endif
+
+#ifdef ITCL_PRESERVE_DEBUG
+ Tcl_CreateObjCommand(interp,
+ ITCL_NAMESPACE"::dumppreserveinfo",
+ ItclDumpPreserveInfo, NULL, NULL);
+#endif
+ /* END for debugging only !!! */
+
+ /*
+ * Create the top-level data structure for tracking objects.
+ * Store this as "associated data" for easy access, but link
+ * it to the itcl namespace for ownership.
+ */
+ infoPtr = (ItclObjectInfo*)ckalloc(sizeof(ItclObjectInfo));
+ memset(infoPtr, 0, sizeof(ItclObjectInfo));
+ infoPtr->interp = interp;
+ infoPtr->class_meta_type = (Tcl_ObjectMetadataType *)ckalloc(
+ sizeof(Tcl_ObjectMetadataType));
+ infoPtr->class_meta_type->version = TCL_OO_METADATA_VERSION_CURRENT;
+ infoPtr->class_meta_type->name = "ItclClass";
+ infoPtr->class_meta_type->deleteProc = ItclDeleteClassMetadata;
+ infoPtr->class_meta_type->cloneProc = NULL;
+
+ infoPtr->object_meta_type = &objMDT;
+
+ Tcl_InitHashTable(&infoPtr->objects, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&infoPtr->objectCmds, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&infoPtr->classes, TCL_ONE_WORD_KEYS);
+ Tcl_InitObjHashTable(&infoPtr->nameClasses);
+ Tcl_InitHashTable(&infoPtr->namespaceClasses, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&infoPtr->procMethods, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&infoPtr->instances, TCL_STRING_KEYS);
+ Tcl_InitHashTable(&infoPtr->frameContext, TCL_ONE_WORD_KEYS);
+ Tcl_InitObjHashTable(&infoPtr->classTypes);
+ infoPtr->ensembleInfo = (EnsembleInfo *)ckalloc(sizeof(EnsembleInfo));
+ memset(infoPtr->ensembleInfo, 0, sizeof(EnsembleInfo));
+ Tcl_InitHashTable(&infoPtr->ensembleInfo->ensembles, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&infoPtr->ensembleInfo->subEnsembles, TCL_ONE_WORD_KEYS);
+ infoPtr->ensembleInfo->numEnsembles = 0;
+ infoPtr->protection = ITCL_DEFAULT_PROTECT;
+ infoPtr->currClassFlags = 0;
+ infoPtr->buildingWidget = 0;
+ infoPtr->typeDestructorArgumentPtr = Tcl_NewStringObj("", -1);
+ Tcl_IncrRefCount(infoPtr->typeDestructorArgumentPtr);
+ infoPtr->lastIoPtr = NULL;
+
+ Tcl_SetVar(interp, ITCL_NAMESPACE"::internal::dicts::classes", "", 0);
+ Tcl_SetVar(interp, ITCL_NAMESPACE"::internal::dicts::objects", "", 0);
+ Tcl_SetVar(interp, ITCL_NAMESPACE"::internal::dicts::classOptions", "", 0);
+ Tcl_SetVar(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedOptions", "", 0);
+ Tcl_SetVar(interp,
+ ITCL_NAMESPACE"::internal::dicts::classComponents", "", 0);
+ Tcl_SetVar(interp,
+ ITCL_NAMESPACE"::internal::dicts::classVariables", "", 0);
+ Tcl_SetVar(interp,
+ ITCL_NAMESPACE"::internal::dicts::classFunctions", "", 0);
+ Tcl_SetVar(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedFunctions", "", 0);
+
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classTypes,
+ (char *)Tcl_NewStringObj("class", -1), &isNew);
+ Tcl_SetHashValue(hPtr, ITCL_CLASS);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classTypes,
+ (char *)Tcl_NewStringObj("type", -1), &isNew);
+ Tcl_SetHashValue(hPtr, ITCL_TYPE);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classTypes,
+ (char *)Tcl_NewStringObj("widget", -1), &isNew);
+ Tcl_SetHashValue(hPtr, ITCL_WIDGET);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classTypes,
+ (char *)Tcl_NewStringObj("widgetadaptor", -1), &isNew);
+ Tcl_SetHashValue(hPtr, ITCL_WIDGETADAPTOR);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classTypes,
+ (char *)Tcl_NewStringObj("extendedclass", -1), &isNew);
+ Tcl_SetHashValue(hPtr, ITCL_ECLASS);
+
+ res_option = getenv("ITCL_USE_OLD_RESOLVERS");
+ if (res_option == NULL) {
+ opt = 1;
+ } else {
+ opt = atoi(res_option);
+ }
+ infoPtr->useOldResolvers = opt;
+ Itcl_InitStack(&infoPtr->clsStack);
+
+ Tcl_SetAssocData(interp, ITCL_INTERP_DATA,
+ (Tcl_InterpDeleteProc*)FreeItclObjectInfo, (ClientData)infoPtr);
+
+ Itcl_PreserveData((ClientData)infoPtr);
+
+#ifdef NEW_PROTO_RESOLVER
+ ItclVarsAndCommandResolveInit(interp);
+#endif
+
+ objPtr = Tcl_NewStringObj("::oo::class", -1);
+ root = Tcl_NewObjectInstance(interp, Tcl_GetObjectAsClass(
+ Tcl_GetObjectFromObj(interp, objPtr)), "::itcl::Root",
+ NULL, 0, NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+
+ Tcl_NewMethod(interp, Tcl_GetObjectAsClass(root),
+ Tcl_NewStringObj("unknown", -1), 0, &itclRootMethodType,
+ ItclUnknownGuts);
+ Tcl_NewMethod(interp, Tcl_GetObjectAsClass(root),
+ Tcl_NewStringObj("ItclConstructBase", -1), 0,
+ &itclRootMethodType, ItclConstructGuts);
+ Tcl_NewMethod(interp, Tcl_GetObjectAsClass(root),
+ Tcl_NewStringObj("info", -1), 1,
+ &itclRootMethodType, ItclInfoGuts);
+
+ /* first create the Itcl base class as root of itcl classes */
+ if (Tcl_EvalEx(interp, clazzClassScript, -1, 0) != TCL_OK) {
+ Tcl_Panic("cannot create Itcl root class ::itcl::clazz");
+ }
+ clazzObjectPtr = Tcl_GetObjectFromObj(interp, Tcl_GetObjResult(interp));
+
+
+ if (clazzObjectPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "ITCL: cannot get Object for ::itcl::clazz for class \"",
+ "::itcl::clazz", "\"", NULL);
+ return TCL_ERROR;
+ }
+
+ /* work around for SF bug #254 needed because of problem in TclOO 1.0.2 !! */
+ if (Tcl_PkgPresent(interp, "TclOO", "1.0.2", 1) != NULL) {
+ Itcl_IncrObjectRefCount(clazzObjectPtr);
+ }
+
+ infoPtr->clazzClassPtr = Tcl_GetObjectAsClass(clazzObjectPtr);
+
+ /*
+ * Initialize the ensemble package first, since we need this
+ * for other parts of [incr Tcl].
+ */
+
+ if (Itcl_EnsembleInit(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Itcl_ParseInit(interp, infoPtr);
+
+ /*
+ * Create "itcl::builtin" namespace for commands that
+ * are automatically built into class definitions.
+ */
+ if (Itcl_BiInit(interp, infoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Export all commands in the "itcl" namespace so that they
+ * can be imported with something like "namespace import itcl::*"
+ */
+ itclNs = Tcl_FindNamespace(interp, "::itcl", (Tcl_Namespace*)NULL,
+ TCL_LEAVE_ERR_MSG);
+
+ /*
+ * This was changed from a glob export (itcl::*) to explicit
+ * command exports, so that the itcl::is command can *not* be
+ * exported. This is done for concern that the itcl::is command
+ * imported might be confusing ("is").
+ */
+ if (!itclNs ||
+ (Tcl_Export(interp, itclNs, "body", /* reset */ 1) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "class", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "code", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "configbody", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "delete", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "delete_helper", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "ensemble", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "filter", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "find", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "forward", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "local", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "mixin", 0) != TCL_OK) ||
+ (Tcl_Export(interp, itclNs, "scope", 0) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+
+ Tcl_CreateObjCommand(interp,
+ ITCL_NAMESPACE"::internal::commands::sethullwindowname",
+ ItclSetHullWindowName, infoPtr, NULL);
+ Tcl_CreateObjCommand(interp,
+ ITCL_NAMESPACE"::internal::commands::checksetitclhull",
+ ItclCheckSetItclHull, infoPtr, NULL);
+
+ /*
+ * Set up the variables containing version info.
+ */
+
+ Tcl_SetVar(interp, "::itcl::version", ITCL_VERSION, TCL_NAMESPACE_ONLY);
+ Tcl_SetVar(interp, "::itcl::patchLevel", ITCL_PATCH_LEVEL,
+ TCL_NAMESPACE_ONLY);
+
+
+#ifdef ITCL_DEBUG_C_INTERFACE
+ RegisterDebugCFunctions(interp);
+#endif
+ /*
+ * Package is now loaded.
+ */
+
+ Tcl_PkgProvideEx(interp, "Itcl", ITCL_PATCH_LEVEL, &itclStubs);
+ return Tcl_PkgProvideEx(interp, "itcl", ITCL_PATCH_LEVEL, &itclStubs);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_Init()
+ *
+ * Invoked whenever a new INTERPRETER is created to install the
+ * [incr Tcl] package. Usually invoked within Tcl_AppInit() at
+ * the start of execution.
+ *
+ * Creates the "::itcl" namespace and installs access commands for
+ * creating classes and querying info.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+
+int
+Itcl_Init (
+ Tcl_Interp *interp)
+{
+ if (Initialize(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ return Tcl_EvalEx(interp, initScript, -1, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_SafeInit()
+ *
+ * Invoked whenever a new SAFE INTERPRETER is created to install
+ * the [incr Tcl] package.
+ *
+ * Creates the "::itcl" namespace and installs access commands for
+ * creating classes and querying info.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+
+int
+Itcl_SafeInit (
+ Tcl_Interp *interp)
+{
+ if (Initialize(interp) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return Tcl_EvalEx(interp, safeInitScript, -1, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclSetHullWindowName()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclSetHullWindowName(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ if (infoPtr->currIoPtr != NULL) {
+ infoPtr->currIoPtr->hullWindowNamePtr = objv[1];
+ Tcl_IncrRefCount(infoPtr->currIoPtr->hullWindowNamePtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCheckSetItclHull()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclCheckSetItclHull(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ ItclObject *ioPtr;
+ ItclVariable *ivPtr;
+ ItclObjectInfo *infoPtr;
+ const char *valueStr;
+
+ if (objc < 3) {
+ Tcl_AppendResult(interp, "ItclCheckSetItclHull wrong # args should be ",
+ "<objectName> <value>", NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * This is an internal command, and is never called with an
+ * objectName value other than the empty list. Check that with
+ * an assertion so alternative handling can be removed.
+ */
+ assert( strlen(Tcl_GetString(objv[1])) == 0);
+ infoPtr = (ItclObjectInfo *)clientData;
+ {
+ ioPtr = infoPtr->currIoPtr;
+ if (ioPtr == NULL) {
+ Tcl_AppendResult(interp, "ItclCheckSetItclHull cannot find object",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+ objPtr = Tcl_NewStringObj("itcl_hull", -1);
+ hPtr = Tcl_FindHashEntry(&ioPtr->iclsPtr->variables, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "ItclCheckSetItclHull cannot find itcl_hull",
+ " variable for object \"", Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ ivPtr = Tcl_GetHashValue(hPtr);
+ valueStr = Tcl_GetString(objv[2]);
+ if (strcmp(valueStr, "2") == 0) {
+ ivPtr->initted = 2;
+ } else {
+ if (strcmp(valueStr, "0") == 0) {
+ ivPtr->initted = 0;
+ } else {
+ Tcl_AppendResult(interp, "ItclCheckSetItclHull bad value \"",
+ valueStr, "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclFinishCmd()
+ *
+ * called when an interp is deleted to free up memory or called explicitly
+ * to check memory leaks
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclFinishCmd(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch place;
+ Tcl_Namespace *nsPtr;
+ Tcl_Obj **newObjv;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *ensObjPtr;
+ Tcl_Command cmdPtr;
+ Tcl_Obj *mapDict;
+ ItclObjectInfo *infoPtr;
+ ItclCmdsInfo *iciPtr;
+ int checkMemoryLeaks;
+ int i;
+ int result;
+
+ ItclShowArgs(1, "ItclFinishCmd", objc, objv);
+ result = TCL_OK;
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ if (infoPtr == NULL) {
+ infoPtr = (ItclObjectInfo *)clientData;
+ }
+ checkMemoryLeaks = 0;
+ if (objc > 1) {
+ if (strcmp(Tcl_GetString(objv[1]), "checkmemoryleaks") == 0) {
+ /* if we have that option, the namespace of the Tcl ensembles
+ * is not teared down, so we have to simulate it here to
+ * have the correct reference counts for infoPtr->infoVars2Ptr
+ * infoPtr->infoVars3Ptr and infoPtr->infoVars4Ptr
+ */
+ checkMemoryLeaks = 1;
+ }
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * 2);
+ newObjv[0] = Tcl_NewStringObj("my", -1);;
+ for (i = 0; ;i++) {
+ iciPtr = &itclCmds[i];
+ if (iciPtr->name == NULL) {
+ break;
+ }
+ if ((iciPtr->flags & ITCL_IS_ENSEMBLE) == 0) {
+ result = Itcl_RenameCommand(interp, iciPtr->name, "");
+ } else {
+ objPtr = Tcl_NewStringObj(iciPtr->name, -1);
+ newObjv[1] = objPtr;
+ Itcl_EnsembleDeleteCmd(infoPtr, infoPtr->interp, 2, newObjv);
+ Tcl_DecrRefCount(objPtr);
+ }
+ iciPtr++;
+ }
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+
+ /* remove the unknow handler, to free the reference to the
+ * Tcl_Obj with the name of it */
+ ensObjPtr = Tcl_NewStringObj("::itcl::builtin::Info::delegated", -1);
+ cmdPtr = Tcl_FindEnsemble(interp, ensObjPtr, TCL_LEAVE_ERR_MSG);
+ if (cmdPtr != NULL) {
+ Tcl_SetEnsembleUnknownHandler(NULL, cmdPtr, NULL);
+ }
+ Tcl_DecrRefCount(ensObjPtr);
+
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&infoPtr->instances, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteHashTable(&infoPtr->instances);
+
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&infoPtr->classTypes, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteHashTable(&infoPtr->classTypes);
+
+ Tcl_DeleteHashTable(&infoPtr->procMethods);
+
+ Tcl_DeleteHashTable(&infoPtr->objectCmds);
+ Tcl_DeleteHashTable(&infoPtr->classes);
+ Tcl_DeleteHashTable(&infoPtr->nameClasses);
+ Tcl_DeleteHashTable(&infoPtr->namespaceClasses);
+
+ nsPtr = Tcl_FindNamespace(interp, "::itcl::parser", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+
+ mapDict = NULL;
+ ensObjPtr = Tcl_NewStringObj("::itcl::builtin::Info", -1);
+ if (Tcl_FindNamespace(interp, Tcl_GetString(ensObjPtr), NULL, 0) != NULL) {
+ Tcl_SetEnsembleUnknownHandler(NULL,
+ Tcl_FindEnsemble(interp, ensObjPtr, TCL_LEAVE_ERR_MSG),
+ NULL);
+ }
+ Tcl_DecrRefCount(ensObjPtr);
+
+ /* remove the vars entry from the info dict */
+ /* and replace it by the original one */
+ cmdPtr = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY);
+ if (cmdPtr != NULL && Tcl_IsEnsemble(cmdPtr)) {
+ Tcl_GetEnsembleMappingDict(NULL, cmdPtr, &mapDict);
+ if (mapDict != NULL) {
+
+ objPtr = Tcl_NewStringObj("vars", -1);
+ Tcl_DictObjRemove(interp, mapDict, objPtr);
+ Tcl_DictObjPut(interp, mapDict, objPtr, infoPtr->infoVars4Ptr);
+ Tcl_DecrRefCount(objPtr);
+ Tcl_SetEnsembleMappingDict(interp, cmdPtr, mapDict);
+ }
+ }
+ /* FIXME have to figure out why the refCount of
+ * ::itcl::builtin::Info
+ * and ::itcl::builtin::Info::vars and vars is 2 here !! */
+ /* seems to be as the tclOO commands are not yet deleted ?? */
+ Tcl_DecrRefCount(infoPtr->infoVars3Ptr);
+ Tcl_DecrRefCount(infoPtr->infoVars4Ptr);
+ if (checkMemoryLeaks) {
+ Tcl_DecrRefCount(infoPtr->infoVars3Ptr);
+ Tcl_DecrRefCount(infoPtr->infoVars4Ptr);
+ /* see comment above */
+ }
+
+ Tcl_DecrRefCount(infoPtr->typeDestructorArgumentPtr);
+
+ Tcl_EvalEx(infoPtr->interp,
+ "::oo::define ::itcl::clazz deletemethod unknown", -1, 0);
+
+ /* first have to look for the remaining memory leaks, then remove the next ifdef */
+ Itcl_RenameCommand(infoPtr->interp, "::itcl::clazz", "");
+
+ /* tear down ::itcl namespace (this includes ::itcl::parser namespace) */
+ nsPtr = Tcl_FindNamespace(infoPtr->interp, "::itcl::parser", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+ nsPtr = Tcl_FindNamespace(infoPtr->interp, "::itcl::import", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+ nsPtr = Tcl_FindNamespace(infoPtr->interp, "::itcl::internal", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+ nsPtr = Tcl_FindNamespace(infoPtr->interp, "::itcl::builtin", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+ nsPtr = Tcl_FindNamespace(infoPtr->interp, "::itcl", NULL, 0);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+
+ /* cleanup ensemble info */
+ ItclFinishEnsemble(infoPtr);
+
+ ckfree((char *)infoPtr->class_meta_type);
+
+ Itcl_DeleteStack(&infoPtr->clsStack);
+ /* clean up list pool */
+ Itcl_FinishList();
+
+ Itcl_ReleaseData((ClientData)infoPtr);
+ return result;
+}
+
+#ifdef OBJ_REF_COUNT_DEBUG
+void Tcl_DbDumpRefCountInfo(const char *fileName, int noDeleted);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDumpRefCountInfo()
+ *
+ * debugging routine to check for memory leaks in use of Tcl_Obj's
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclDumpRefCountInfo(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int noDeleted;
+
+ noDeleted = 0;
+ if (objc > 1) {
+ if (strcmp(Tcl_GetString(objv[1]), "-nodeleted") == 0) {
+ noDeleted = 1;
+ }
+ }
+ ItclShowArgs(0, "ItclDumpRefCountInfo", objc, objv);
+ Tcl_DbDumpRefCountInfo(NULL, noDeleted);
+ return TCL_OK;
+}
+#endif
+
+#ifdef ITCL_PRESERVE_DEBUG
+void Itcl_DbDumpPreserveInfo(const char *fileName);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDumpPreserveInfo()
+ *
+ * debugging routine to check for memory leaks in use of Itcl_PreserveData
+ * and Itcl_ReleaseData
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclDumpPreserveInfo(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(0, "ItclDumpPreserveInfo", objc, objv);
+ Itcl_DbDumpPreserveInfo(NULL);
+ return TCL_OK;
+}
+#endif
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclBuiltin.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclBuiltin.c
new file mode 100644
index 0000000..e605762
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclBuiltin.c
@@ -0,0 +1,3783 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * These procedures handle built-in class methods, including the
+ * "isa" method (to query hierarchy info) and the "info" method
+ * (to query class/object data).
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+static char initHullCmdsScript[] =
+"namespace eval ::itcl {\n"
+" proc _find_hull_init {} {\n"
+" global env tcl_library\n"
+" variable library\n"
+" variable patchLevel\n"
+" rename _find_hull_init {}\n"
+" if {[info exists library]} {\n"
+" lappend dirs $library\n"
+" } else {\n"
+" if {[catch {uplevel #0 source -rsrc itcl}] == 0} {\n"
+" return\n"
+" }\n"
+" set dirs {}\n"
+" if {[info exists env(ITCL_LIBRARY)]} {\n"
+" lappend dirs $env(ITCL_LIBRARY)\n"
+" }\n"
+" lappend dirs [file join [file dirname $tcl_library] itcl$patchLevel]\n"
+" set bindir [file dirname [info nameofexecutable]]\n"
+" lappend dirs [file join . library]\n"
+" lappend dirs [file join $bindir .. lib itcl$patchLevel]\n"
+" lappend dirs [file join $bindir .. library]\n"
+" lappend dirs [file join $bindir .. .. library]\n"
+" lappend dirs [file join $bindir .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. itcl-ng itcl library]\n"
+" # On MacOSX, check the directories in the tcl_pkgPath\n"
+" if {[string equal $::tcl_platform(platform) \"unix\"] && "
+" [string equal $::tcl_platform(os) \"Darwin\"]} {\n"
+" foreach d $::tcl_pkgPath {\n"
+" lappend dirs [file join $d itcl$patchLevel]\n"
+" }\n"
+" }\n"
+" # On *nix, check the directories in the tcl_pkgPath\n"
+" if {[string equal $::tcl_platform(platform) \"unix\"]} {\n"
+" foreach d $::tcl_pkgPath {\n"
+" lappend dirs $d\n"
+" lappend dirs [file join $d itcl$patchLevel]\n"
+" }\n"
+" }\n"
+" }\n"
+" foreach i $dirs {\n"
+" set library $i\n"
+" set itclfile [file join $i itclHullCmds.tcl]\n"
+" if {![catch {uplevel #0 [list source $itclfile]} msg]} {\n"
+" return\n"
+" }\n"
+"puts stderr \"MSG!$msg!\"\n"
+" }\n"
+" set msg \"Can't find a usable itclHullCmds.tcl in the following directories:\n\"\n"
+" append msg \" $dirs\n\"\n"
+" append msg \"This probably means that Itcl/Tcl weren't installed properly.\n\"\n"
+" append msg \"If you know where the Itcl library directory was installed,\n\"\n"
+" append msg \"you can set the environment variable ITCL_LIBRARY to point\n\"\n"
+" append msg \"to the library directory.\n\"\n"
+" error $msg\n"
+" }\n"
+" _find_hull_init\n"
+"}";
+
+static Tcl_ObjCmdProc Itcl_BiDestroyCmd;
+static Tcl_ObjCmdProc ItclExtendedConfigure;
+static Tcl_ObjCmdProc ItclExtendedCget;
+static Tcl_ObjCmdProc ItclExtendedSetGet;
+static Tcl_ObjCmdProc Itcl_BiCreateHullCmd;
+static Tcl_ObjCmdProc Itcl_BiSetupComponentCmd;
+static Tcl_ObjCmdProc Itcl_BiKeepComponentOptionCmd;
+static Tcl_ObjCmdProc Itcl_BiIgnoreComponentOptionCmd;
+static Tcl_ObjCmdProc Itcl_BiInitOptionsCmd;
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static Tcl_Obj* ItclReportPublicOpt(Tcl_Interp *interp,
+ ItclVariable *ivPtr, ItclObject *contextIoPtr);
+
+static Tcl_ObjCmdProc ItclBiClassUnknownCmd;
+/*
+ * Standard list of built-in methods for all objects.
+ */
+typedef struct BiMethod {
+ const char* name; /* method name */
+ const char* usage; /* string describing usage */
+ const char* registration;/* registration name for C proc */
+ Tcl_ObjCmdProc *proc; /* implementation C proc */
+ int flags; /* flag for which type of class to be used */
+} BiMethod;
+
+static const BiMethod BiMethodList[] = {
+ { "callinstance",
+ "<instancename>",
+ "@itcl-builtin-callinstance",
+ Itcl_BiCallInstanceCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "getinstancevar",
+ "<instancename>",
+ "@itcl-builtin-getinstancevar",
+ Itcl_BiGetInstanceVarCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "cget",
+ "-option",
+ "@itcl-builtin-cget",
+ Itcl_BiCgetCmd,
+ ITCL_CLASS|ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "configure",
+ "?-option? ?value -option value...?",
+ "@itcl-builtin-configure",
+ Itcl_BiConfigureCmd,
+ ITCL_CLASS|ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ {"createhull",
+ "widgetType widgetPath ?-class className? ?optionName value ...?",
+ "@itcl-builtin-createhull",
+ Itcl_BiCreateHullCmd,
+ ITCL_ECLASS
+ },
+ { "destroy",
+ "",
+ "@itcl-builtin-destroy",
+ Itcl_BiDestroyCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "installcomponent",
+ "<componentName> using <classname> <winpath> ?-option value...?",
+ "@itcl-builtin-installcomponent",
+ Itcl_BiInstallComponentCmd,
+ ITCL_WIDGET
+ },
+ { "itcl_hull",
+ "",
+ "@itcl-builtin-itcl_hull",
+ Itcl_BiItclHullCmd,
+ ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "isa",
+ "className",
+ "@itcl-builtin-isa",
+ Itcl_BiIsaCmd,
+ ITCL_CLASS|ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET
+ },
+ {"itcl_initoptions",
+ "?optionName value ...?",
+ "@itcl-builtin-initoptions",
+ Itcl_BiInitOptionsCmd,
+ ITCL_ECLASS
+ },
+ { "mymethod",
+ "",
+ "@itcl-builtin-mymethod",
+ Itcl_BiMyMethodCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "myvar",
+ "",
+ "@itcl-builtin-myvar",
+ Itcl_BiMyVarCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "myproc",
+ "",
+ "@itcl-builtin-myproc",
+ Itcl_BiMyProcCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "mytypemethod",
+ "",
+ "@itcl-builtin-mytypemethod",
+ Itcl_BiMyTypeMethodCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "mytypevar",
+ "",
+ "@itcl-builtin-mytypevar",
+ Itcl_BiMyTypeVarCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ { "setget",
+ "varName ?value?",
+ "@itcl-builtin-setget",
+ ItclExtendedSetGet,
+ ITCL_ECLASS
+ },
+ { "unknown",
+ "",
+ "@itcl-builtin-classunknown",
+ ItclBiClassUnknownCmd,
+ ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR
+ },
+ {"keepcomponentoption",
+ "componentName optionName ?optionName ...?",
+ "@itcl-builtin-keepcomponentoption",
+ Itcl_BiKeepComponentOptionCmd,
+ ITCL_ECLASS
+ },
+ {"ignorecomponentoption",
+ "componentName optionName ?optionName ...?",
+ "@itcl-builtin-ignorecomponentoption",
+ Itcl_BiIgnoreComponentOptionCmd,
+ ITCL_ECLASS
+ },
+ /* the next 3 are defined in library/itclHullCmds.tcl */
+ {"addoptioncomponent",
+ "componentName optionName ?optionName ...?",
+ "@itcl-builtin-addoptioncomponent",
+ NULL,
+ ITCL_ECLASS
+ },
+ {"ignoreoptioncomponent",
+ "componentName optionName ?optionName ...?",
+ "@itcl-builtin-ignoreoptioncomponent",
+ NULL,
+ ITCL_ECLASS
+ },
+ {"renameoptioncomponent",
+ "componentName optionName ?optionName ...?",
+ "@itcl-builtin-renameoptioncomponent",
+ NULL,
+ ITCL_ECLASS
+ },
+ {"setupcomponent",
+ "componentName using widgetType widgetPath ?optionName value ...?",
+ "@itcl-builtin-setupcomponent",
+ Itcl_BiSetupComponentCmd,
+ ITCL_ECLASS
+ },
+};
+static int BiMethodListLen = sizeof(BiMethodList)/sizeof(BiMethod);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInit()
+ *
+ * Creates a namespace full of built-in methods/procs for [incr Tcl]
+ * classes. This includes things like the "isa" method and "info"
+ * for querying class info. Usually invoked by Itcl_Init() when
+ * [incr Tcl] is first installed into an interpreter.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_BiInit(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclObjectInfo *infoPtr)
+{
+ Tcl_Namespace *itclBiNs;
+ Tcl_DString buffer;
+ Tcl_Obj *mapDict;
+ Tcl_Command infoCmd;
+ int result;
+ int i;
+
+ /*
+ * "::itcl::builtin" commands.
+ * These commands are imported into each class
+ * just before the class definition is parsed.
+ */
+ Tcl_DStringInit(&buffer);
+ for (i=0; i < BiMethodListLen; i++) {
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, "::itcl::builtin::", -1);
+ Tcl_DStringAppend(&buffer, BiMethodList[i].name, -1);
+ Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
+ BiMethodList[i].proc, (ClientData)infoPtr,
+ (Tcl_CmdDeleteProc*)NULL);
+ }
+ Tcl_DStringFree(&buffer);
+
+ Tcl_CreateObjCommand(interp, "::itcl::builtin::chain", Itcl_BiChainCmd,
+ NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itcl::builtin::classunknown",
+ ItclBiClassUnknownCmd, infoPtr, (Tcl_CmdDeleteProc*)NULL);
+
+ ItclInfoInit(interp, infoPtr);
+ /*
+ * Export all commands in the built-in namespace so we can
+ * import them later on.
+ */
+ itclBiNs = Tcl_FindNamespace(interp, "::itcl::builtin",
+ (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);
+
+ if ((itclBiNs == NULL) ||
+ Tcl_Export(interp, itclBiNs, "[a-z]*", /* resetListFirst */ 1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Install into the master [info] ensemble.
+ */
+
+ infoCmd = Tcl_FindCommand(interp, "info", NULL, TCL_GLOBAL_ONLY);
+ if (infoCmd != NULL && Tcl_IsEnsemble(infoCmd)) {
+ Tcl_GetEnsembleMappingDict(NULL, infoCmd, &mapDict);
+ if (mapDict != NULL) {
+ infoPtr->infoVars4Ptr =
+ Tcl_NewStringObj("vars", -1);
+ Tcl_IncrRefCount(infoPtr->infoVars4Ptr);
+ result = Tcl_DictObjGet(interp, mapDict, infoPtr->infoVars4Ptr,
+ &infoPtr->infoVarsPtr);
+ if(result != TCL_OK) {
+ /* FIXME need code here!! */
+ }
+
+ infoPtr->infoVars3Ptr =
+ Tcl_NewStringObj("::itcl::builtin::Info::vars", -1);
+ /* FIXME see comment in itclBase.c ItclFinishCmd */
+ Tcl_IncrRefCount(infoPtr->infoVars3Ptr);
+ Tcl_DictObjPut(NULL, mapDict, infoPtr->infoVars4Ptr,
+ infoPtr->infoVars3Ptr);
+ Tcl_SetEnsembleMappingDict(interp, infoCmd, mapDict);
+ }
+ }
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InstallBiMethods()
+ *
+ * Invoked when a class is first created, just after the class
+ * definition has been parsed, to add definitions for built-in
+ * methods to the class. If a method already exists in the class
+ * with the same name as the built-in, then the built-in is skipped.
+ * Otherwise, a method definition for the built-in method is added.
+ *
+ * Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_InstallBiMethods(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclClass *iclsPtr) /* class definition to be updated */
+{
+ int result = TCL_OK;
+
+ int i;
+ ItclHierIter hier;
+ ItclClass *superPtr;
+
+ /*
+ * Scan through all of the built-in methods and see if
+ * that method already exists in the class. If not, add
+ * it in.
+ *
+ * TRICKY NOTE: The virtual tables haven't been built yet,
+ * so look for existing methods the hard way--by scanning
+ * through all classes.
+ */
+ Tcl_Obj *objPtr = Tcl_NewStringObj("", 0);
+ for (i=0; i < BiMethodListLen; i++) {
+ Tcl_HashEntry *hPtr = NULL;
+
+ Itcl_InitHierIter(&hier, iclsPtr);
+ Tcl_SetStringObj(objPtr, BiMethodList[i].name, -1);
+ superPtr = Itcl_AdvanceHierIter(&hier);
+ while (superPtr) {
+ hPtr = Tcl_FindHashEntry(&superPtr->functions, (char *)objPtr);
+ if (hPtr) {
+ break;
+ }
+ superPtr = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ if (!hPtr) {
+ if (iclsPtr->flags & BiMethodList[i].flags) {
+ result = Itcl_CreateMethod(interp, iclsPtr,
+ Tcl_NewStringObj(BiMethodList[i].name, -1),
+ BiMethodList[i].usage, BiMethodList[i].registration);
+
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * Every Itcl class gets an info method installed so that each has
+ * a proper context for the subcommands to do their context senstive
+ * work.
+ */
+
+ if (result == TCL_OK
+ && (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ result = Itcl_CreateMethod(interp, iclsPtr,
+ Tcl_NewStringObj("info", -1), NULL, "@itcl-builtin-info");
+ }
+
+ Tcl_DecrRefCount(objPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiIsaCmd()
+ *
+ * Invoked whenever the user issues the "isa" method for an object.
+ * Handles the following syntax:
+ *
+ * <objName> isa <className>
+ *
+ * Checks to see if the object has the given <className> anywhere
+ * in its heritage. Returns 1 if so, and 0 otherwise.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiIsaCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+ const char *token;
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be \"object isa className\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (objc != 2) {
+ token = Tcl_GetString(objv[0]);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"object ", token, " className\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Look for the requested class. If it is not found, then
+ * try to autoload it. If it absolutely cannot be found,
+ * signal an error.
+ */
+ token = Tcl_GetString(objv[1]);
+ iclsPtr = Itcl_FindClass(interp, token, /* autoload */ 1);
+ if (iclsPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_ObjectIsa(contextIoPtr, iclsPtr)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
+ } else {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiConfigureCmd()
+ *
+ * Invoked whenever the user issues the "configure" method for an object.
+ * Handles the following syntax:
+ *
+ * <objName> configure ?-<option>? ?<value> -<option> <value>...?
+ *
+ * Allows access to public variables as if they were configuration
+ * options. With no arguments, this command returns the current
+ * list of public variable options. If -<option> is specified,
+ * this returns the information for just one option:
+ *
+ * -<optionName> <initVal> <currentVal>
+ *
+ * Otherwise, the list of arguments is parsed, and values are
+ * assigned to the various public variable options. When each
+ * option changes, a big of "config" code associated with the option
+ * is executed, to bring the object up to date.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiConfigureCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_DString buffer;
+ Tcl_DString buffer2;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ Tcl_Namespace *saveNsPtr;
+ Tcl_Obj * const *unparsedObjv;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ ItclVarLookup *vlookup;
+ ItclMemberCode *mcode;
+ ItclHierIter hier;
+ ItclObjectInfo *infoPtr;
+ const char *lastval;
+ const char *token;
+ char *varName;
+ int i;
+ int unparsedObjc;
+ int result;
+
+ ItclShowArgs(1, "Itcl_BiConfigureCmd", objc, objv);
+ vlookup = NULL;
+ token = NULL;
+ hPtr = NULL;
+ unparsedObjc = objc;
+ unparsedObjv = objv;
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringInit(&buffer2);
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be ",
+ "\"object configure ?-option? ?value -option value...?\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * BE CAREFUL: work in the virtual scope!
+ */
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ infoPtr = contextIclsPtr->infoPtr;
+ if (!(contextIclsPtr->flags & ITCL_CLASS)) {
+ /* first check if it is an option */
+ if (objc > 1) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->options,
+ (char *) objv[1]);
+ }
+ result = ItclExtendedConfigure(contextIclsPtr, interp, objc, objv);
+ if (result != TCL_CONTINUE) {
+ return result;
+ }
+ if (infoPtr->unparsedObjc > 0) {
+ unparsedObjc = infoPtr->unparsedObjc;
+ unparsedObjv = infoPtr->unparsedObjv;
+ } else {
+ unparsedObjc = objc;
+ }
+ }
+ /*
+ * HANDLE: configure
+ */
+ if (unparsedObjc == 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->variables, &place);
+ while (hPtr) {
+ ivPtr = (ItclVariable*)Tcl_GetHashValue(hPtr);
+ if (ivPtr->protection == ITCL_PUBLIC) {
+ objPtr = ItclReportPublicOpt(interp, ivPtr, contextIoPtr);
+
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+ } else {
+
+ /*
+ * HANDLE: configure -option
+ */
+ if (unparsedObjc == 2) {
+ token = Tcl_GetStringFromObj(unparsedObjv[1], (int*)NULL);
+ if (*token != '-') {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be ",
+ "\"object configure ?-option? ?value -option value...?\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ vlookup = NULL;
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, token+1);
+ if (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+
+ if (vlookup->ivPtr->protection != ITCL_PUBLIC) {
+ vlookup = NULL;
+ }
+ }
+ if (!vlookup) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "unknown option \"", token, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ resultPtr = ItclReportPublicOpt(interp,
+ vlookup->ivPtr, contextIoPtr);
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * HANDLE: configure -option value -option value...
+ *
+ * Be careful to work in the virtual scope. If this "configure"
+ * method was defined in a base class, the current namespace
+ * (from Itcl_ExecMethod()) will be that base class. Activate
+ * the derived class namespace here, so that instance variables
+ * are accessed properly.
+ */
+ result = TCL_OK;
+
+ for (i=1; i < unparsedObjc; i+=2) {
+ if (i+1 >= unparsedObjc) {
+ Tcl_AppendResult(interp, "need option value pair", NULL);
+ result = TCL_ERROR;
+ goto configureDone;
+ }
+ vlookup = NULL;
+ token = Tcl_GetString(unparsedObjv[i]);
+ if (*token == '-') {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, token+1);
+ if (hPtr == NULL) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, token);
+ }
+ if (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ }
+ }
+
+ if (!vlookup || (vlookup->ivPtr->protection != ITCL_PUBLIC)) {
+ Tcl_AppendResult(interp, "unknown option \"", token, "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto configureDone;
+ }
+ if (i == unparsedObjc-1) {
+ Tcl_AppendResult(interp, "value for \"", token, "\" missing",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto configureDone;
+ }
+
+ ivPtr = vlookup->ivPtr;
+ Tcl_DStringSetLength(&buffer2, 0);
+ if (!(ivPtr->flags & ITCL_COMMON)) {
+ Tcl_DStringAppend(&buffer2,
+ Tcl_GetString(contextIoPtr->varNsNamePtr), -1);
+ }
+ Tcl_DStringAppend(&buffer2,
+ Tcl_GetString(ivPtr->iclsPtr->fullNamePtr), -1);
+ Tcl_DStringAppend(&buffer2, "::", 2);
+ Tcl_DStringAppend(&buffer2,
+ Tcl_GetString(ivPtr->namePtr), -1);
+ varName = Tcl_DStringValue(&buffer2);
+ lastval = Tcl_GetVar2(interp, varName, (char*)NULL, 0);
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, (lastval) ? lastval : "", -1);
+
+ token = Tcl_GetString(unparsedObjv[i+1]);
+ if (Tcl_SetVar2(interp, varName, (char*)NULL, token,
+ TCL_LEAVE_ERR_MSG) == NULL) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (error in configuration of public variable \"%s\")",
+ Tcl_GetString(ivPtr->fullNamePtr)));
+ result = TCL_ERROR;
+ goto configureDone;
+ }
+
+ /*
+ * If this variable has some "config" code, invoke it now.
+ *
+ * TRICKY NOTE: Be careful to evaluate the code one level
+ * up in the call stack, so that it's executed in the
+ * calling context, and not in the context that we've
+ * set up for public variable access.
+ */
+ mcode = ivPtr->codePtr;
+ if (mcode && Itcl_IsMemberCodeImplemented(mcode)) {
+ if (!ivPtr->iclsPtr->infoPtr->useOldResolvers) {
+ Itcl_SetCallFrameResolver(interp, contextIoPtr->resolvePtr);
+ }
+ saveNsPtr = Tcl_GetCurrentNamespace(interp);
+ Itcl_SetCallFrameNamespace(interp, ivPtr->iclsPtr->nsPtr);
+ result = Tcl_EvalObjEx(interp, mcode->bodyPtr, 0);
+ Itcl_SetCallFrameNamespace(interp, saveNsPtr);
+ if (result == TCL_OK) {
+ Tcl_ResetResult(interp);
+ } else {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (error in configuration of public variable \"%s\")",
+ Tcl_GetString(ivPtr->fullNamePtr)));
+ Tcl_SetVar2(interp, varName,(char*)NULL,
+ Tcl_DStringValue(&buffer), 0);
+
+ goto configureDone;
+ }
+ }
+ }
+
+configureDone:
+ if (infoPtr->unparsedObjc > 0) {
+ ckfree ((char *)infoPtr->unparsedObjv);
+ infoPtr->unparsedObjv = NULL;
+ infoPtr->unparsedObjc = 0;
+ }
+ Tcl_DStringFree(&buffer2);
+ Tcl_DStringFree(&buffer);
+
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiCgetCmd()
+ *
+ * Invoked whenever the user issues the "cget" method for an object.
+ * Handles the following syntax:
+ *
+ * <objName> cget -<option>
+ *
+ * Allows access to public variables as if they were configuration
+ * options. Mimics the behavior of the usual "cget" method for
+ * Tk widgets. Returns the current value of the public variable
+ * with name <option>.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiCgetCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+ const char *name;
+ const char *val;
+ int result;
+
+ ItclShowArgs(1,"Itcl_BiCgetCmd", objc, objv);
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((contextIoPtr == NULL) || objc != 2) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be \"object cget -option\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * BE CAREFUL: work in the virtual scope!
+ */
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ if (!(contextIclsPtr->flags & ITCL_CLASS)) {
+ result = ItclExtendedCget(contextIclsPtr, interp, objc, objv);
+ if (result != TCL_CONTINUE) {
+ return result;
+ }
+ }
+ name = Tcl_GetString(objv[1]);
+
+ vlookup = NULL;
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, name+1);
+ if (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ }
+
+ if ((vlookup == NULL) || (vlookup->ivPtr->protection != ITCL_PUBLIC)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "unknown option \"", name, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ val = Itcl_GetInstanceVar(interp,
+ Tcl_GetString(vlookup->ivPtr->namePtr),
+ contextIoPtr, vlookup->ivPtr->iclsPtr);
+
+ if (val) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(val, -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("<undefined>", -1));
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclReportPublicOpt()
+ *
+ * Returns information about a public variable formatted as a
+ * configuration option:
+ *
+ * -<varName> <initVal> <currentVal>
+ *
+ * Used by Itcl_BiConfigureCmd() to report configuration options.
+ * Returns a Tcl_Obj containing the information.
+ * ------------------------------------------------------------------------
+ */
+static Tcl_Obj*
+ItclReportPublicOpt(
+ Tcl_Interp *interp, /* interpreter containing the object */
+ ItclVariable *ivPtr, /* public variable to be reported */
+ ItclObject *contextIoPtr) /* object containing this variable */
+{
+ const char *val;
+ ItclClass *iclsPtr;
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+ Tcl_DString optName;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ /*
+ * Determine how the option name should be reported.
+ * If the simple name can be used to find it in the virtual
+ * data table, then use the simple name. Otherwise, this
+ * is a shadowed variable; use the full name.
+ */
+ Tcl_DStringInit(&optName);
+ Tcl_DStringAppend(&optName, "-", -1);
+
+ iclsPtr = (ItclClass*)contextIoPtr->iclsPtr;
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars,
+ Tcl_GetString(ivPtr->fullNamePtr));
+ assert(hPtr != NULL);
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ Tcl_DStringAppend(&optName, vlookup->leastQualName, -1);
+
+ objPtr = Tcl_NewStringObj(Tcl_DStringValue(&optName), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+ Tcl_DStringFree(&optName);
+
+
+ if (ivPtr->init) {
+ objPtr = ivPtr->init;
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+
+ val = Itcl_GetInstanceVar(interp, Tcl_GetString(ivPtr->namePtr),
+ contextIoPtr, ivPtr->iclsPtr);
+
+ if (val) {
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+
+ return listPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclReportOption()
+ *
+ * Returns information about an option formatted as a
+ * configuration option:
+ *
+ * <optionName> <initVal> <currentVal>
+ *
+ * Used by ItclExtendedConfigure() to report configuration options.
+ * Returns a Tcl_Obj containing the information.
+ * ------------------------------------------------------------------------
+ */
+static Tcl_Obj*
+ItclReportOption(
+ Tcl_Interp *interp, /* interpreter containing the object */
+ ItclOption *ioptPtr, /* option to be reported */
+ ItclObject *contextIoPtr) /* object containing this variable */
+{
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *val;
+
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ idoPtr = ioptPtr->iclsPtr->infoPtr->currIdoPtr;
+ if (idoPtr != NULL) {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, idoPtr->namePtr);
+ if (idoPtr->resourceNamePtr == NULL) {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ Tcl_NewStringObj("", -1));
+ /* FIXME possible memory leak */
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ idoPtr->resourceNamePtr);
+ }
+ if (idoPtr->classNamePtr == NULL) {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ Tcl_NewStringObj("", -1));
+ /* FIXME possible memory leak */
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ idoPtr->classNamePtr);
+ }
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, ioptPtr->namePtr);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ ioptPtr->resourceNamePtr);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr,
+ ioptPtr->classNamePtr);
+ }
+ if (ioptPtr->defaultValuePtr) {
+ objPtr = ioptPtr->defaultValuePtr;
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+ val = ItclGetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr),
+ contextIoPtr, ioptPtr->iclsPtr);
+ if (val) {
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+ return listPtr;
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiChainCmd()
+ *
+ * Invoked to handle the "chain" command, to access the version of
+ * a method or proc that exists in a base class. Handles the
+ * following syntax:
+ *
+ * chain ?<arg> <arg>...?
+ *
+ * Looks up the inheritance hierarchy for another implementation
+ * of the method/proc that is currently executing. If another
+ * implementation is found, it is invoked with the specified
+ * <arg> arguments. If it is not found, this command does nothing.
+ * This allows a base class method to be called out in a generic way,
+ * so the code will not have to change if the base class changes.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+NRBiChainCmd(
+ ClientData dummy, /* not used */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result = TCL_OK;
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ const char *cmd;
+ char *cmd1;
+ const char *head;
+ ItclClass *iclsPtr;
+ ItclHierIter hier;
+ Tcl_HashEntry *hPtr;
+ ItclMemberFunc *imPtr;
+ Tcl_DString buffer;
+ Tcl_Obj *cmdlinePtr;
+ Tcl_Obj **newobjv;
+ Tcl_Obj * const *cObjv;
+ int cObjc;
+ int idx;
+ Tcl_Obj *objPtr;
+
+ ItclShowArgs(1, "Itcl_BiChainCmd", objc, objv);
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot chain functions outside of a class context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Try to get the command name from the current call frame.
+ * If it cannot be determined, do nothing. Otherwise, trim
+ * off any leading path names.
+ */
+ cObjv = Itcl_GetCallVarFrameObjv(interp);
+ if (cObjv == NULL) {
+ return TCL_OK;
+ }
+ cObjc = Itcl_GetCallVarFrameObjc(interp);
+
+ if ((Itcl_GetCallFrameClientData(interp) == NULL) || (objc == 1)) {
+ /* that has been a direct call, so no object in front !! */
+ if (objc == 1 && cObjc >= 2) {
+ idx = 1;
+ } else {
+ idx = 0;
+ }
+ } else {
+ idx = 1;
+ }
+ cmd1 = (char *)ckalloc(strlen(Tcl_GetString(cObjv[idx]))+1);
+ strcpy(cmd1, Tcl_GetString(cObjv[idx]));
+ Itcl_ParseNamespPath(cmd1, &buffer, &head, &cmd);
+
+ /*
+ * Look for the specified command in one of the base classes.
+ * If we have an object context, then start from the most-specific
+ * class and walk up the hierarchy to the current context. If
+ * there is multiple inheritance, having the entire inheritance
+ * hierarchy will allow us to jump over to another branch of
+ * the inheritance tree.
+ *
+ * If there is no object context, just start with the current
+ * class context.
+ */
+ if (contextIoPtr != NULL) {
+ Itcl_InitHierIter(&hier, contextIoPtr->iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ if (iclsPtr == contextIclsPtr) {
+ break;
+ }
+ }
+ } else {
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ Itcl_AdvanceHierIter(&hier); /* skip the current class */
+ }
+
+ /*
+ * Now search up the class hierarchy for the next implementation.
+ * If found, execute it. Otherwise, do nothing.
+ */
+ objPtr = Tcl_NewStringObj(cmd, -1);
+ ckfree(cmd1);
+ Tcl_IncrRefCount(objPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->functions, (char *)objPtr);
+ if (hPtr) {
+ int my_objc;
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(hPtr);
+
+ /*
+ * NOTE: Avoid the usual "virtual" behavior of
+ * methods by passing the full name as
+ * the command argument.
+ */
+
+ cmdlinePtr = Itcl_CreateArgs(interp,
+ Tcl_GetString(imPtr->fullNamePtr), objc-1, objv+1);
+
+ (void) Tcl_ListObjGetElements((Tcl_Interp*)NULL, cmdlinePtr,
+ &my_objc, &newobjv);
+
+ if (imPtr->flags & ITCL_CONSTRUCTOR) {
+ contextIoPtr = imPtr->iclsPtr->infoPtr->currIoPtr;
+ }
+ ItclShowArgs(1, "___chain", objc-1, newobjv+1);
+ result = Itcl_EvalMemberCode(interp, imPtr, contextIoPtr,
+ my_objc-1, newobjv+1);
+ Tcl_DecrRefCount(cmdlinePtr);
+ break;
+ }
+ }
+ Tcl_DecrRefCount(objPtr);
+
+ Tcl_DStringFree(&buffer);
+ Itcl_DeleteHierIter(&hier);
+ return result;
+}
+/* ARGSUSED */
+int
+Itcl_BiChainCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRBiChainCmd, clientData, objc, objv);
+}
+
+static int
+CallCreateObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_CallFrame frame;
+ Tcl_Namespace *nsPtr;
+ ItclClass *iclsPtr = data[0];
+ int objc = PTR2INT(data[1]);
+ Tcl_Obj *const *objv = data[2];
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ nsPtr = Itcl_GetUplevelNamespace(interp, 1);
+ if (Itcl_PushCallFrame(interp, &frame, nsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ result = ItclClassCreateObject(iclsPtr->infoPtr, interp, objc, objv);
+ Itcl_PopCallFrame(interp);
+ Tcl_DecrRefCount(objv[2]);
+ Tcl_DecrRefCount(objv[1]);
+ Tcl_DecrRefCount(objv[0]);
+ return result;
+}
+
+static int
+PrepareCreateObject(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ int objc,
+ Tcl_Obj * const *objv)
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj **newObjv;
+ void *callbackPtr;
+ const char *funcName;
+ int result;
+ int offset;
+
+ offset = 1;
+ funcName = Tcl_GetString(objv[1]);
+ if (strcmp(funcName, "itcl_hull") == 0) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR ",
+ "cannot find itcl_hull method", NULL);
+ return TCL_ERROR;
+ }
+ result = Itcl_ExecProc(Tcl_GetHashValue(hPtr), interp, objc, objv);
+ return result;
+ }
+ if (strcmp(funcName, "create") == 0) {
+ /* allow typeClassName create objectName */
+ offset++;
+ } else {
+ /* allow typeClassName objectName */
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc+3-offset));
+ newObjv[0] = objv[0];
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = iclsPtr->namePtr;
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = Tcl_NewStringObj(iclsPtr->nsPtr->fullName, -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ memcpy(newObjv+3, objv+offset, (objc-offset) * sizeof(Tcl_Obj *));
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ ItclShowArgs(1, "CREATE", objc+3-offset, newObjv);
+ Tcl_NRAddCallback(interp, CallCreateObject, iclsPtr,
+ INT2PTR(objc+3-offset), (ClientData)newObjv, NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (result != TCL_OK) {
+ if (iclsPtr->infoPtr->currIoPtr != NULL) {
+ /* we are in a constructor call */
+ if (iclsPtr->infoPtr->currIoPtr->hadConstructorError == 0) {
+ iclsPtr->infoPtr->currIoPtr->hadConstructorError = 1;
+ }
+ }
+ }
+ ckfree((char *)newObjv);
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * ItclBiClassUnknownCmd()
+ *
+ * Invoked to handle the "classunknown" command
+ * this is called whenever an object is called with an unknown method/proc
+ * following syntax:
+ *
+ * classunknown <object> <methodname> ?<arg> <arg>...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ItclBiClassUnknownCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj **newObjv;
+ Tcl_Obj **lObjv;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *resPtr;
+ Tcl_DString buffer;
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclDelegatedFunction *idmPtr2;
+ ItclDelegatedFunction *starIdmPtr;
+ const char *resStr;
+ const char *val;
+ const char *funcName;
+ int lObjc;
+ int result;
+ int offset;
+ int useComponent;
+ int isItclHull;
+ int isTypeMethod;
+ int isStar;
+ int isNew;
+ int idx;
+
+ ItclShowArgs(1, "ItclBiClassUnknownCmd", objc, objv);
+ listPtr = NULL;
+ useComponent = 1;
+ isStar = 0;
+ isTypeMethod = 0;
+ isItclHull = 0;
+ starIdmPtr = NULL;
+ infoPtr = (ItclObjectInfo *)clientData;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses,
+ (char *)Tcl_GetCurrentNamespace(interp));
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR: ItclBiClassUnknownCmd ",
+ "cannot find class\n", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ funcName = Tcl_GetString(objv[1]);
+ if (strcmp(funcName, "create") == 0) {
+ /* check if we have a user method create. If not, it is the builtin
+ * create method and we don't need to check for delegation
+ * and components with ITCL_COMPONENT_INHERIT
+ */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objv[1]);
+ if (hPtr == NULL) {
+ return PrepareCreateObject(interp, iclsPtr, objc, objv);
+ }
+ }
+ if (strcmp(funcName, "itcl_hull") == 0) {
+ isItclHull = 1;
+ }
+ if (!isItclHull) {
+ FOREACH_HASH_VALUE(icPtr, &iclsPtr->components) {
+ if (icPtr->flags & ITCL_COMPONENT_INHERIT) {
+ val = Tcl_GetVar2(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, 0);
+ if ((val != NULL) && (strlen(val) > 0)) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv+1, objv+1, sizeof(Tcl_Obj *) * (objc-1));
+ ItclShowArgs(1, "UK EVAL1", objc, newObjv);
+ result = Tcl_EvalObjv(interp, objc, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ return result;
+ }
+ }
+ }
+ }
+ /* from a class object only typemethods can be called directly
+ * if delegated, so check for that, otherwise create an object
+ * for ITCL_ECLASS we allow calling too
+ */
+ hPtr = NULL;
+ isTypeMethod = 0;
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), funcName) == 0) {
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ isTypeMethod = 1;
+ }
+ if (iclsPtr->flags & ITCL_ECLASS) {
+ isTypeMethod = 1;
+ }
+ break;
+ }
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), "*") == 0) {
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ isTypeMethod = 1;
+ }
+ starIdmPtr = idmPtr;
+ break;
+ }
+ }
+ idmPtr = NULL;
+ if (isTypeMethod) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions, (char *)objv[1]);
+ if (hPtr == NULL) {
+ objPtr = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(objPtr);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ idmPtr = Tcl_GetHashValue(hPtr);
+ isStar = 1;
+ }
+ }
+ if (isStar) {
+ /* check if the function is in the exceptions */
+ hPtr2 = Tcl_FindHashEntry(&starIdmPtr->exceptions, (char *)objv[1]);
+ if (hPtr2 != NULL) {
+ const char *sep = "";
+ objPtr = Tcl_NewStringObj("unknown subcommand \"", -1);
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ Tcl_AppendToObj(objPtr, "\": must be ", -1);
+ FOREACH_HASH_VALUE(idmPtr,
+ &iclsPtr->delegatedFunctions) {
+ funcName = Tcl_GetString(idmPtr->namePtr);
+ if (strcmp(funcName, "*") != 0) {
+ if (strlen(sep) > 0) {
+ Tcl_AppendToObj(objPtr, sep, -1);
+ }
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ sep = " or ";
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+ }
+ if (hPtr != NULL) {
+ idmPtr = Tcl_GetHashValue(hPtr);
+ val = NULL;
+ if (idmPtr->icPtr != NULL) {
+ if (idmPtr->icPtr->ivPtr->flags & ITCL_COMMON) {
+ val = Tcl_GetVar2(interp,
+ Tcl_GetString(idmPtr->icPtr->namePtr), NULL, 0);
+ } else {
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ contextIclsPtr = NULL;
+ contextIoPtr = NULL;
+ Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr);
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(contextIoPtr->varNsNamePtr), -1);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(idmPtr->icPtr->ivPtr->fullNamePtr),
+ -1);
+ val = Tcl_GetVar2(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ Tcl_DStringFree(&buffer);
+ }
+ if (val == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR: ",
+ "ItclBiClassUnknownCmd contents ",
+ "of component == NULL\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+ offset = 1;
+ lObjc = 0;
+ if ((idmPtr->asPtr != NULL) || (idmPtr->usingPtr != NULL)) {
+ offset++;
+ listPtr = Tcl_NewListObj(0, NULL);
+ result = ExpandDelegateAs(interp, NULL, iclsPtr,
+ idmPtr, funcName, listPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ result = Tcl_ListObjGetElements(interp, listPtr,
+ &lObjc, &lObjv);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(listPtr);
+ return result;
+ }
+ if (idmPtr->usingPtr != NULL) {
+ useComponent = 0;
+ }
+ }
+ if (useComponent) {
+ if ((val == NULL) || (strlen(val) == 0)) {
+ Tcl_AppendResult(interp, "component \"",
+ Tcl_GetString(idmPtr->icPtr->namePtr),
+ "\" is not initialized", NULL);
+ return TCL_ERROR;
+ }
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) *
+ (objc + lObjc - offset + useComponent));
+ if (useComponent) {
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ }
+ for (idx = 0; idx < lObjc; idx++) {
+ newObjv[useComponent+idx] = lObjv[idx];
+ }
+ if (objc-offset > 0) {
+ memcpy(newObjv+useComponent+lObjc, objv+offset,
+ sizeof(Tcl_Obj *) * (objc-offset));
+ }
+ ItclShowArgs(1, "OBJ UK EVAL", objc+lObjc-offset+useComponent,
+ newObjv);
+ result = Tcl_EvalObjv(interp,
+ objc+lObjc-offset+useComponent, newObjv, 0);
+ if (isStar && (result == TCL_OK)) {
+ if (Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)newObjv[1]) == NULL) {
+ result = ItclCreateDelegatedFunction(interp, iclsPtr,
+ newObjv[1], idmPtr->icPtr, NULL, NULL,
+ NULL, &idmPtr2);
+ if (result == TCL_OK) {
+ if (isTypeMethod) {
+ idmPtr2->flags |= ITCL_TYPE_METHOD;
+ } else {
+ idmPtr2->flags |= ITCL_METHOD;
+ }
+ hPtr2 = Tcl_CreateHashEntry(
+ &iclsPtr->delegatedFunctions,
+ (char *)newObjv[1], &isNew);
+ Tcl_SetHashValue(hPtr2, idmPtr2);
+ }
+ }
+ }
+ if (useComponent) {
+ Tcl_DecrRefCount(newObjv[0]);
+ }
+ ckfree((char *)newObjv);
+ if (listPtr != NULL) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (result == TCL_ERROR) {
+ resStr = Tcl_GetStringResult(interp);
+ /* FIXME ugly hack at the moment !! */
+ if (strncmp(resStr, "wrong # args: should be ", 24) == 0) {
+ resPtr = Tcl_NewStringObj("", -1);
+ Tcl_AppendToObj(resPtr, resStr, 25);
+ resStr += 25;
+ Tcl_AppendToObj(resPtr, Tcl_GetString(iclsPtr->namePtr),
+ -1);
+ resStr += strlen(val);
+ Tcl_AppendToObj(resPtr, resStr, -1);
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, resPtr);
+ }
+ }
+ return result;
+ }
+ }
+ return PrepareCreateObject(interp, iclsPtr, objc, objv);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclUnknownGuts()
+ *
+ * The unknown method handler of the itcl::Root class -- all Itcl
+ * objects land here when they cannot find a method.
+ *
+ * ------------------------------------------------------------------------
+ */
+
+int
+ItclUnknownGuts(
+ ItclObject *ioPtr, /* The ItclObject seeking method */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj **newObjv;
+ Tcl_Obj **lObjv;
+ Tcl_Obj *listPtr = NULL;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *resPtr;
+ Tcl_DString buffer;
+ ItclClass *iclsPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclDelegatedFunction *idmPtr2;
+ const char *resStr;
+ const char *val;
+ const char *funcName;
+ int lObjc;
+ int result;
+ int offset;
+ int useComponent;
+ int found;
+ int isItclHull;
+ int isStar;
+ int isTypeMethod;
+ int isNew;
+ int idx;
+
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "wrong # args: should be one of...",
+ (char*)NULL);
+ ItclReportObjectUsage(interp, ioPtr, NULL, NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = ioPtr->iclsPtr;
+ lObjc = 0;
+ offset = 1;
+ isStar = 0;
+ found = 0;
+ isItclHull = 0;
+ useComponent = 1;
+ result = TCL_OK;
+ idmPtr = NULL;
+ funcName = Tcl_GetString(objv[1]);
+ if (strcmp(funcName, "itcl_hull") == 0) {
+ isItclHull = 1;
+ }
+ icPtr = NULL;
+ if (!isItclHull) {
+ FOREACH_HASH_VALUE(icPtr, &ioPtr->objectComponents) {
+ if (icPtr->flags & ITCL_COMPONENT_INHERIT) {
+ val = Itcl_GetInstanceVar(interp,
+ Tcl_GetString(icPtr->namePtr), ioPtr,
+ icPtr->ivPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) > 0)) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) *
+ (objc));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv+1, objv+1, sizeof(Tcl_Obj *) * (objc-1));
+ result = Tcl_EvalObjv(interp, objc, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ return result;
+ }
+ }
+ }
+ }
+ isTypeMethod = 0;
+ found = 0;
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), funcName) == 0) {
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ isTypeMethod = 1;
+ }
+ found = 1;
+ break;
+ }
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), "*") == 0) {
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ isTypeMethod = 1;
+ }
+ found = 1;
+ break;
+ }
+ }
+ if (! found) {
+ idmPtr = NULL;
+ }
+ iclsPtr = ioPtr->iclsPtr;
+ found = 0;
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions, (char *)objv[1]);
+ if (hPtr == NULL) {
+ objPtr = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(objPtr);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ idmPtr = Tcl_GetHashValue(hPtr);
+ isStar = 1;
+ }
+ } else {
+ found = 1;
+ idmPtr = Tcl_GetHashValue(hPtr);
+ }
+ if (isStar) {
+ /* check if the function is in the exceptions */
+ hPtr2 = Tcl_FindHashEntry(&idmPtr->exceptions, (char *)objv[1]);
+ if (hPtr2 != NULL) {
+ const char *sep = "";
+ objPtr = Tcl_NewStringObj("unknown subcommand \"", -1);
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ Tcl_AppendToObj(objPtr, "\": must be ", -1);
+ FOREACH_HASH_VALUE(idmPtr,
+ &iclsPtr->delegatedFunctions) {
+ funcName = Tcl_GetString(idmPtr->namePtr);
+ if (strcmp(funcName, "*") != 0) {
+ if (strlen(sep) > 0) {
+ Tcl_AppendToObj(objPtr, sep, -1);
+ }
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ sep = " or ";
+ }
+ }
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+ }
+ val = NULL;
+ if ((idmPtr != NULL) && (idmPtr->icPtr != NULL)) {
+ Tcl_Obj *objPtr;
+ /* we cannot use Itcl_GetInstanceVar here as the object is not
+ * yet completely built. So use the varNsNamePtr
+ */
+ if (idmPtr->icPtr->ivPtr->flags & ITCL_COMMON) {
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr,
+ (Tcl_GetObjectNamespace(iclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr,
+ Tcl_GetString(idmPtr->icPtr->namePtr), -1);
+ val = Tcl_GetVar2(interp, Tcl_GetString(objPtr), NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+ } else {
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(ioPtr->varNsNamePtr), -1);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(idmPtr->icPtr->ivPtr->fullNamePtr), -1);
+ val = Tcl_GetVar2(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ Tcl_DStringFree(&buffer);
+ }
+
+ if (val == NULL) {
+ Tcl_AppendResult(interp, "ItclBiObjectUnknownCmd contents of ",
+ "component == NULL\n", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ offset = 1;
+ if (isStar) {
+ hPtr = Tcl_FindHashEntry(&idmPtr->exceptions, (char *)objv[1]);
+ /* we have no method name in that case in the caller */
+ if (hPtr != NULL) {
+ const char *sep = "";
+ objPtr = Tcl_NewStringObj("unknown subcommand \"", -1);
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ Tcl_AppendToObj(objPtr, "\": must be ", -1);
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ funcName = Tcl_GetString(idmPtr->namePtr);
+ if (strcmp(funcName, "*") != 0) {
+ if (strlen(sep) > 0) {
+ Tcl_AppendToObj(objPtr, sep, -1);
+ }
+ Tcl_AppendToObj(objPtr, funcName, -1);
+ sep = " or ";
+ }
+ }
+ }
+ }
+ if (idmPtr == NULL) {
+ Tcl_AppendResult(interp, "bad option \"", Tcl_GetString(objv[1]),
+ "\": should be one of...", (char*)NULL);
+ ItclReportObjectUsage(interp, ioPtr, NULL, NULL);
+ return TCL_ERROR;
+ }
+ lObjc = 0;
+ if ((idmPtr != NULL) && ((idmPtr->asPtr != NULL) ||
+ (idmPtr->usingPtr != NULL))) {
+ offset++;
+ listPtr = Tcl_NewListObj(0, NULL);
+ result = ExpandDelegateAs(interp, NULL, iclsPtr,
+ idmPtr, funcName, listPtr);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(listPtr);
+ return result;
+ }
+ result = Tcl_ListObjGetElements(interp, listPtr,
+ &lObjc, &lObjv);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(listPtr);
+ return result;
+ }
+ if (idmPtr->usingPtr != NULL) {
+ useComponent = 0;
+ }
+ }
+ if (useComponent) {
+ if ((val == NULL) || (strlen(val) == 0)) {
+ Tcl_AppendResult(interp, "component \"",
+ Tcl_GetString(idmPtr->icPtr->namePtr),
+ "\" is not initialized", NULL);
+ return TCL_ERROR;
+ }
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) *
+ (objc + lObjc - offset + useComponent));
+ if (useComponent) {
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ }
+ for (idx = 0; idx < lObjc; idx++) {
+ newObjv[useComponent+idx] = lObjv[idx];
+ }
+ if (objc-offset > 0) {
+ memcpy(newObjv+useComponent+lObjc, objv+offset,
+ sizeof(Tcl_Obj *) * (objc-offset));
+ }
+ ItclShowArgs(1, "UK EVAL2", objc+lObjc-offset+useComponent,
+ newObjv);
+ result = Tcl_EvalObjv(interp, objc+lObjc-offset+useComponent,
+ newObjv, 0);
+ if (isStar && (result == TCL_OK)) {
+ if (Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)newObjv[1]) == NULL) {
+ result = ItclCreateDelegatedFunction(interp, iclsPtr,
+ newObjv[1], idmPtr->icPtr, NULL, NULL,
+ NULL, &idmPtr2);
+ if (result == TCL_OK) {
+ if (isTypeMethod) {
+ idmPtr2->flags |= ITCL_TYPE_METHOD;
+ } else {
+ idmPtr2->flags |= ITCL_METHOD;
+ }
+ hPtr2 = Tcl_CreateHashEntry(
+ &iclsPtr->delegatedFunctions, (char *)newObjv[1],
+ &isNew);
+ Tcl_SetHashValue(hPtr2, idmPtr2);
+ }
+ }
+ }
+ if (useComponent) {
+ Tcl_DecrRefCount(newObjv[0]);
+ }
+ if (listPtr != NULL) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ ckfree((char *)newObjv);
+ if (result == TCL_OK) {
+ return TCL_OK;
+ }
+ resStr = Tcl_GetStringResult(interp);
+ /* FIXME ugly hack at the moment !! */
+ if (strncmp(resStr, "wrong # args: should be ", 24) == 0) {
+ resPtr = Tcl_NewStringObj("", -1);
+ Tcl_AppendToObj(resPtr, resStr, 25);
+ resStr += 25;
+ Tcl_AppendToObj(resPtr, Tcl_GetString(iclsPtr->namePtr), -1);
+ resStr += strlen(val);
+ Tcl_AppendToObj(resPtr, resStr, -1);
+ Tcl_ResetResult(interp);
+ Tcl_SetObjResult(interp, resPtr);
+ }
+ return result;
+}
+
+static Tcl_Obj *makeAsOptionInfo(
+ Tcl_Interp *interp,
+ Tcl_Obj *optNamePtr,
+ ItclDelegatedOption *idoPtr,
+ int lObjc2,
+ Tcl_Obj * const *lObjv2)
+{
+ Tcl_Obj *objPtr;
+ int j;
+
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(
+ Tcl_GetString(optNamePtr), -1));
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(
+ Tcl_GetString(idoPtr->resourceNamePtr), -1));
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(
+ Tcl_GetString(idoPtr->classNamePtr), -1));
+ for (j = 3; j < lObjc2; j++) {
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(
+ Tcl_GetString(lObjv2[j]), -1));
+ }
+ return objPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclExtendedConfigure()
+ *
+ * Invoked whenever the user issues the "configure" method for an object.
+ * If the class is not ITCL_CLASS
+ * Handles the following syntax:
+ *
+ * <objName> configure ?-<option>? ?<value> -<option> <value>...?
+ *
+ * Allows access to public variables as if they were configuration
+ * options. With no arguments, this command returns the current
+ * list of public variable options. If -<option> is specified,
+ * this returns the information for just one option:
+ *
+ * -<optionName> <initVal> <currentVal>
+ *
+ * Otherwise, the list of arguments is parsed, and values are
+ * assigned to the various public variable options. When each
+ * option changes, a big of "config" code associated with the option
+ * is executed, to bring the object up to date.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ItclExtendedConfigure(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashTable unique;
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashEntry *hPtr3;
+ Tcl_Object oPtr;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *listPtr2;
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *optNamePtr;
+ Tcl_Obj *methodNamePtr;
+ Tcl_Obj *configureMethodPtr;
+ Tcl_Obj **lObjv;
+ Tcl_Obj **newObjv;
+ Tcl_Obj *lObjvOne[1];
+ Tcl_Obj **lObjv2;
+ Tcl_Obj **lObjv3;
+ Tcl_Namespace *saveNsPtr;
+ Tcl_Namespace *evalNsPtr;
+ ItclClass *contextIclsPtr;
+ ItclClass *iclsPtr2;
+ ItclComponent *componentIcPtr;
+ ItclObject *contextIoPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclDelegatedOption *idoPtr;
+ ItclDelegatedOption *saveIdoPtr;
+ ItclObject *ioPtr;
+ ItclComponent *icPtr;
+ ItclOption *ioptPtr;
+ ItclObjectInfo *infoPtr;
+ const char *val;
+ int lObjc;
+ int lObjc2;
+ int lObjc3;
+ int i;
+ int j;
+ int isNew;
+ int result;
+ int isOneOption;
+
+ ItclShowArgs(1, "ItclExtendedConfigure", objc, objv);
+ ioptPtr = NULL;
+ optNamePtr = NULL;
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be ",
+ "\"object configure ?-option? ?value -option value...?\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * BE CAREFUL: work in the virtual scope!
+ */
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ if (infoPtr->currContextIclsPtr != NULL) {
+ contextIclsPtr = infoPtr->currContextIclsPtr;
+ }
+
+ hPtr = NULL;
+ /* first check if method configure is delegated */
+ methodNamePtr = Tcl_NewStringObj("*", -1);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions, (char *)
+ methodNamePtr);
+ if (hPtr != NULL) {
+ /* all methods are delegated */
+ idmPtr = (ItclDelegatedFunction *)Tcl_GetHashValue(hPtr);
+ Tcl_SetStringObj(methodNamePtr, "configure", -1);
+ hPtr = Tcl_FindHashEntry(&idmPtr->exceptions, (char *)methodNamePtr);
+ if (hPtr == NULL) {
+ icPtr = idmPtr->icPtr;
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, contextIclsPtr);
+ if (val != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+5));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("configure", -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ for(i=1;i<objc;i++) {
+ newObjv[i+1] = objv[i];
+ }
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ oPtr = Tcl_GetObjectFromObj(interp, objPtr);
+ if (oPtr != NULL) {
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ infoPtr->currContextIclsPtr = ioPtr->iclsPtr;
+ }
+ ItclShowArgs(1, "EXTENDED CONFIGURE EVAL1", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ ckfree((char *)newObjv);
+ Tcl_DecrRefCount(objPtr);
+ if (oPtr != NULL) {
+ infoPtr->currContextIclsPtr = NULL;
+ }
+ Tcl_DecrRefCount(methodNamePtr);
+ return result;
+ }
+ } else {
+ /* configure is not delegated, so reset hPtr for checks later on! */
+ hPtr = NULL;
+ }
+ }
+ Tcl_DecrRefCount(methodNamePtr);
+ /* now do the hard work */
+ if (objc == 1) {
+ Tcl_InitObjHashTable(&unique);
+ /* plain configure */
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (contextIclsPtr->flags & ITCL_ECLASS) {
+ result = Tcl_EvalEx(interp, "::itcl::builtin::getEclassOptions", -1, 0);
+ return result;
+ }
+ FOREACH_HASH_VALUE(ioptPtr, &contextIoPtr->objectOptions) {
+ hPtr2 = Tcl_CreateHashEntry(&unique,
+ (char *)ioptPtr->namePtr, &isNew);
+ if (!isNew) {
+ continue;
+ }
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(Tcl_GetString(ioptPtr->namePtr), -1));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->resourceNamePtr), -1));
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(Tcl_GetString(ioptPtr->classNamePtr), -1));
+ if (ioptPtr->defaultValuePtr != NULL) {
+ Tcl_ListObjAppendElement(interp, objPtr, Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->defaultValuePtr), -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj("", -1));
+ }
+ val = ItclGetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr), contextIoPtr,
+ contextIclsPtr);
+ if (val == NULL) {
+ val = "<undefined>";
+ }
+ Tcl_ListObjAppendElement(interp, objPtr,
+ Tcl_NewStringObj(val, -1));
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ /* now check for delegated options */
+ FOREACH_HASH_VALUE(idoPtr, &contextIoPtr->objectDelegatedOptions) {
+
+ if (idoPtr->icPtr != NULL) {
+ icPtr = idoPtr->icPtr;
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, icPtr->ivPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) != 0)) {
+
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ Tcl_AppendToObj(objPtr, " configure ", -1);
+ isOneOption = 0;
+ if (strcmp(Tcl_GetString(idoPtr->namePtr), "*") != 0) {
+ Tcl_AppendToObj(objPtr, " ", -1);
+ if (idoPtr->asPtr != NULL) {
+ Tcl_AppendToObj(objPtr, Tcl_GetString(
+ idoPtr->asPtr), -1);
+ } else {
+ Tcl_AppendToObj(objPtr, Tcl_GetString(
+ idoPtr->namePtr), -1);
+ }
+ isOneOption = 1;
+ }
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ listPtr2 = Tcl_GetObjResult(interp);
+ if (isOneOption) {
+ lObjc = 1;
+ lObjvOne[0] = listPtr2;
+ lObjv = &lObjvOne[0];
+ } else {
+ Tcl_ListObjGetElements(interp, listPtr2,
+ &lObjc, &lObjv);
+ }
+ for (i = 0; i < lObjc; i++) {
+ objPtr = lObjv[i];
+ Tcl_ListObjGetElements(interp, objPtr,
+ &lObjc2, &lObjv2);
+ optNamePtr = idoPtr->namePtr;
+ if (lObjc2 == 0) {
+ hPtr = NULL;
+ } else {
+ hPtr = Tcl_FindHashEntry(&idoPtr->exceptions,
+ (char *)lObjv2[0]);
+ if (isOneOption) {
+ /* avoid wrong name where asPtr != NULL */
+ optNamePtr = idoPtr->namePtr;
+ } else {
+ optNamePtr = lObjv2[0];
+ }
+ }
+ if ((hPtr == NULL) && (lObjc2 > 0)) {
+ if (icPtr->haveKeptOptions) {
+ hPtr = Tcl_FindHashEntry(&icPtr->keptOptions,
+ (char *)optNamePtr);
+ if (hPtr == NULL) {
+ if (idoPtr->asPtr != NULL) {
+ if (strcmp(Tcl_GetString(idoPtr->asPtr),
+ Tcl_GetString(lObjv2[0])) == 0) {
+ hPtr = Tcl_FindHashEntry(
+ &icPtr->keptOptions,
+ (char *)optNamePtr);
+ if (hPtr == NULL) {
+ /* not in kept list, so ignore */
+ continue;
+ }
+ objPtr = makeAsOptionInfo(interp,
+ optNamePtr, idoPtr, lObjc2,
+ lObjv2);
+ }
+ }
+ }
+ if (hPtr != NULL) {
+ hPtr2 = Tcl_CreateHashEntry(&unique,
+ (char *)optNamePtr, &isNew);
+ if (!isNew) {
+ continue;
+ }
+ /* add the option */
+ if (idoPtr->asPtr != NULL) {
+ objPtr = makeAsOptionInfo(interp,
+ optNamePtr, idoPtr, lObjc2,
+ lObjv2);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr,
+ objPtr);
+ }
+ } else {
+ Tcl_ListObjGetElements(interp, lObjv2[i],
+ &lObjc3, &lObjv3);
+ hPtr2 = Tcl_CreateHashEntry(&unique,
+ (char *)lObjv3[0], &isNew);
+ if (!isNew) {
+ continue;
+ }
+ /* add the option */
+ if (idoPtr->asPtr != NULL) {
+ objPtr = makeAsOptionInfo(interp,
+ optNamePtr, idoPtr, lObjc2,
+ lObjv2);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr,
+ objPtr);
+ }
+ }
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ Tcl_DeleteHashTable(&unique);
+ return TCL_OK;
+ }
+ hPtr2 = NULL;
+ /* first handle delegated options */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions, (char *)
+ objv[1]);
+ if (hPtr == NULL) {
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj("*",1);
+ Tcl_IncrRefCount(objPtr);
+ /* check if all options are delegated */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions,
+ (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ /* now check the exceptions */
+ idoPtr = (ItclDelegatedOption *)Tcl_GetHashValue(hPtr);
+ hPtr2 = Tcl_FindHashEntry(&idoPtr->exceptions, (char *)objv[1]);
+ if (hPtr2 != NULL) {
+ /* found in exceptions, so no delegation for this option */
+ hPtr = NULL;
+ }
+ }
+ }
+ componentIcPtr = NULL;
+ /* check if it is not a local option defined before delegate option "*"
+ */
+ hPtr2 = Tcl_FindHashEntry(&contextIoPtr->objectOptions,
+ (char *)objv[1]);
+ if (hPtr != NULL) {
+ idoPtr = (ItclDelegatedOption *)Tcl_GetHashValue(hPtr);
+ icPtr = idoPtr->icPtr;
+ if (icPtr != NULL) {
+ if (icPtr->haveKeptOptions) {
+ hPtr3 = Tcl_FindHashEntry(&icPtr->keptOptions, (char *)objv[1]);
+ if (hPtr3 != NULL) {
+ /* ignore if it is an object option only */
+ ItclHierIter hier;
+ int found;
+
+ found = 0;
+ Itcl_InitHierIter(&hier, contextIoPtr->iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ if (Tcl_FindHashEntry(&iclsPtr2->options,
+ (char *)objv[1]) != NULL) {
+ found = 1;
+ break;
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+ if (! found) {
+ hPtr2 = NULL;
+ componentIcPtr = icPtr;
+ }
+ }
+ }
+ }
+ }
+ if ((objc <= 3) && (hPtr != NULL) && (hPtr2 == NULL)) {
+ /* the option is delegated */
+ idoPtr = (ItclDelegatedOption *)Tcl_GetHashValue(hPtr);
+ if (componentIcPtr != NULL) {
+ icPtr = componentIcPtr;
+ } else {
+ icPtr = idoPtr->icPtr;
+ }
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, icPtr->ivPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) > 0)) {
+ if (idoPtr->asPtr != NULL) {
+ icPtr->ivPtr->iclsPtr->infoPtr->currIdoPtr = idoPtr;
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+2));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("configure", 9);
+ Tcl_IncrRefCount(newObjv[1]);
+ if (idoPtr->asPtr != NULL) {
+ newObjv[2] = idoPtr->asPtr;
+ } else {
+ newObjv[2] = objv[1];
+ }
+ Tcl_IncrRefCount(newObjv[2]);
+ for(i=2;i<objc;i++) {
+ newObjv[i+1] = objv[i];
+ }
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ oPtr = Tcl_GetObjectFromObj(interp, objPtr);
+ if (oPtr != NULL) {
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ infoPtr->currContextIclsPtr = ioPtr->iclsPtr;
+ }
+ Tcl_DecrRefCount(objPtr);
+ ItclShowArgs(1, "extended eval delegated option", objc + 1,
+ newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ icPtr->ivPtr->iclsPtr->infoPtr->currIdoPtr = NULL;
+ if (oPtr != NULL) {
+ infoPtr->currContextIclsPtr = NULL;
+ }
+ return result;
+ } else {
+ Tcl_AppendResult(interp, "INTERNAL ERROR component \"",
+ Tcl_GetString(icPtr->namePtr), "\" not found",
+ " or not set in ItclExtendedConfigure delegated option",
+ NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ if (objc == 2) {
+ saveIdoPtr = infoPtr->currIdoPtr;
+ /* now look if it is an option at all */
+ if (hPtr2 == NULL) {
+ hPtr2 = Tcl_FindHashEntry(&contextIclsPtr->options,
+ (char *) objv[1]);
+ if (hPtr2 == NULL) {
+ hPtr2 = Tcl_FindHashEntry(&contextIoPtr->objectOptions,
+ (char *) objv[1]);
+ } else {
+ infoPtr->currIdoPtr = NULL;
+ }
+ }
+ if (hPtr2 == NULL) {
+ if (contextIclsPtr->flags & ITCL_ECLASS) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc));
+ newObjv[0] = Tcl_NewStringObj("::itcl::builtin::eclassConfigure", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ for (j = 1; j < objc; j++) {
+ newObjv[j] = objv[j];
+ Tcl_IncrRefCount(newObjv[j]);
+ }
+ result = Tcl_EvalObjv(interp, objc, newObjv, TCL_EVAL_DIRECT);
+ for (j = 0; j < objc; j++) {
+ Tcl_DecrRefCount(newObjv[j]);
+ }
+ ckfree((char *)newObjv);
+ if (result == TCL_OK) {
+ return TCL_OK;
+ }
+ }
+ /* no option at all, let the normal configure do the job */
+ infoPtr->currIdoPtr = saveIdoPtr;
+ return TCL_CONTINUE;
+ }
+ ioptPtr = (ItclOption *)Tcl_GetHashValue(hPtr2);
+ resultPtr = ItclReportOption(interp, ioptPtr, contextIoPtr);
+ infoPtr->currIdoPtr = saveIdoPtr;
+ Tcl_SetResult(interp, Tcl_GetString(resultPtr), TCL_VOLATILE);
+ Tcl_DecrRefCount(resultPtr);
+ return TCL_OK;
+ }
+ result = TCL_OK;
+ /* set one or more options */
+ for (i=1; i < objc; i+=2) {
+ if (i+1 >= objc) {
+ Tcl_AppendResult(interp, "need option value pair", NULL);
+ result = TCL_ERROR;
+ break;
+ }
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectOptions,
+ (char *) objv[i]);
+ if (hPtr == NULL) {
+ if (contextIclsPtr->flags & ITCL_ECLASS) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc));
+ newObjv[0] = Tcl_NewStringObj("::itcl::builtin::eclassConfigure", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ for (j = 1; j < objc; j++) {
+ newObjv[j] = objv[j];
+ Tcl_IncrRefCount(newObjv[j]);
+ }
+ result = Tcl_EvalObjv(interp, objc, newObjv, TCL_EVAL_DIRECT);
+ for (j = 0; j < objc; j++) {
+ Tcl_DecrRefCount(newObjv[j]);
+ }
+ ckfree((char *)newObjv);
+ if (result == TCL_OK) {
+ continue;
+ }
+ }
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions,
+ (char *) objv[i]);
+ if (hPtr != NULL) {
+ /* the option is delegated */
+ idoPtr = (ItclDelegatedOption *)Tcl_GetHashValue(hPtr);
+ icPtr = idoPtr->icPtr;
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(icPtr->ivPtr->namePtr),
+ NULL, contextIoPtr, icPtr->ivPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) > 0)) {
+ if (idoPtr->asPtr != NULL) {
+ icPtr->ivPtr->iclsPtr->infoPtr->currIdoPtr = idoPtr;
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+2));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("configure", 9);
+ Tcl_IncrRefCount(newObjv[1]);
+ if (idoPtr->asPtr != NULL) {
+ newObjv[2] = idoPtr->asPtr;
+ } else {
+ newObjv[2] = objv[i];
+ }
+ Tcl_IncrRefCount(newObjv[2]);
+ newObjv[3] = objv[i+1];
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ oPtr = Tcl_GetObjectFromObj(interp, objPtr);
+ if (oPtr != NULL) {
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ infoPtr->currContextIclsPtr = ioPtr->iclsPtr;
+ }
+ Tcl_DecrRefCount(objPtr);
+ ItclShowArgs(1, "extended eval delegated option", 4,
+ newObjv);
+ result = Tcl_EvalObjv(interp, 4, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ icPtr->ivPtr->iclsPtr->infoPtr->currIdoPtr = NULL;
+ if (oPtr != NULL) {
+ infoPtr->currContextIclsPtr = NULL;
+ }
+ continue;
+ } else {
+ Tcl_AppendResult(interp, "INTERNAL ERROR component not ",
+ "found or not set in ItclExtendedConfigure ",
+ "delegated option", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (hPtr == NULL) {
+ infoPtr->unparsedObjc += 2;
+ if (infoPtr->unparsedObjv == NULL) {
+ infoPtr->unparsedObjc++; /* keep the first slot for
+ correct working !! */
+ infoPtr->unparsedObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)
+ *(infoPtr->unparsedObjc));
+ infoPtr->unparsedObjv[0] = objv[0];
+ } else {
+ infoPtr->unparsedObjv = (Tcl_Obj **)ckrealloc(
+ (char *)infoPtr->unparsedObjv, sizeof(Tcl_Obj *)
+ *(infoPtr->unparsedObjc));
+ }
+ infoPtr->unparsedObjv[infoPtr->unparsedObjc-2] = objv[i];
+ Tcl_IncrRefCount(infoPtr->unparsedObjv[infoPtr->unparsedObjc-2]);
+ infoPtr->unparsedObjv[infoPtr->unparsedObjc-1] = objv[i+1];
+ /* check if normal public variable/common ? */
+ /* FIXME !!! temporary */
+ continue;
+ }
+ ioptPtr = (ItclOption *)Tcl_GetHashValue(hPtr);
+ if (ioptPtr->flags & ITCL_OPTION_READONLY) {
+ if (infoPtr->currIoPtr == NULL) {
+ /* allow only setting during instance creation
+ * infoPtr->currIoPtr != NULL during instance creation
+ */
+ Tcl_AppendResult(interp, "option \"",
+ Tcl_GetString(ioptPtr->namePtr),
+ "\" can only be set at instance creation", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->validateMethodPtr != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * 3);
+ newObjv[0] = ioptPtr->validateMethodPtr;
+ newObjv[1] = objv[i];
+ newObjv[2] = objv[i+1];
+ infoPtr->inOptionHandling = 1;
+ saveNsPtr = Tcl_GetCurrentNamespace(interp);
+ Itcl_SetCallFrameNamespace(interp, contextIclsPtr->nsPtr);
+ ItclShowArgs(1, "EVAL validatemethod", 3, newObjv);
+ result = Tcl_EvalObjv(interp, 3, newObjv, TCL_EVAL_DIRECT);
+ Itcl_SetCallFrameNamespace(interp, saveNsPtr);
+ infoPtr->inOptionHandling = 0;
+ ckfree((char *)newObjv);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ configureMethodPtr = NULL;
+ evalNsPtr = NULL;
+ if (ioptPtr->configureMethodPtr != NULL) {
+ configureMethodPtr = ioptPtr->configureMethodPtr;
+ Tcl_IncrRefCount(configureMethodPtr);
+ evalNsPtr = ioptPtr->iclsPtr->nsPtr;
+ }
+ if (ioptPtr->configureMethodVarPtr != NULL) {
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(ioptPtr->configureMethodVarPtr), NULL,
+ contextIoPtr, ioptPtr->iclsPtr);
+ if (val == NULL) {
+ Tcl_AppendResult(interp, "configure cannot get value for",
+ " configuremethodvar \"",
+ Tcl_GetString(ioptPtr->configureMethodVarPtr),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(val, -1);
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->iclsPtr->resolveCmds,
+ (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ ItclMemberFunc *imPtr;
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ evalNsPtr = imPtr->iclsPtr->nsPtr;
+ } else {
+ Tcl_AppendResult(interp, "cannot find method \"",
+ val, "\" found in configuremethodvar", NULL);
+ return TCL_ERROR;
+ }
+ configureMethodPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(configureMethodPtr);
+ }
+ if (configureMethodPtr != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*3);
+ newObjv[0] = configureMethodPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = objv[i];
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = objv[i+1];
+ Tcl_IncrRefCount(newObjv[2]);
+ saveNsPtr = Tcl_GetCurrentNamespace(interp);
+ Itcl_SetCallFrameNamespace(interp, evalNsPtr);
+ ItclShowArgs(1, "EVAL configuremethod", 3, newObjv);
+ result = Tcl_EvalObjv(interp, 3, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ ckfree((char *)newObjv);
+ Itcl_SetCallFrameNamespace(interp, saveNsPtr);
+ Tcl_DecrRefCount(configureMethodPtr);
+ if (result != TCL_OK) {
+ break;
+ }
+ } else {
+ if (ItclSetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(objv[i]), Tcl_GetString(objv[i+1]),
+ contextIoPtr, ioptPtr->iclsPtr) == NULL) {
+ result = TCL_ERROR;
+ break;
+ }
+ }
+ Tcl_ResetResult(interp);
+ result = TCL_OK;
+ }
+ if (infoPtr->unparsedObjc > 0) {
+ if (result == TCL_OK) {
+ return TCL_CONTINUE;
+ }
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclExtendedCget()
+ *
+ * Invoked whenever the user issues the "cget" method for an object.
+ * If the class is NOT ITCL_CLASS
+ * Handles the following syntax:
+ *
+ * <objName> cget -<option>
+ *
+ * Allows access to public variables as if they were configuration
+ * options. Mimics the behavior of the usual "cget" method for
+ * Tk widgets. Returns the current value of the public variable
+ * with name <option>.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ItclExtendedCget(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashEntry *hPtr3;
+ Tcl_Obj *objPtr2;
+ Tcl_Obj *objPtr;
+ Tcl_Object oPtr;
+ Tcl_Obj *methodNamePtr;
+ Tcl_Obj **newObjv;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclDelegatedOption *idoPtr;
+ ItclComponent *icPtr;
+ ItclObjectInfo *infoPtr;
+ ItclOption *ioptPtr;
+ ItclObject *ioPtr;
+ const char *val;
+ int i;
+ int result;
+
+ ItclShowArgs(1,"ItclExtendedCget", objc, objv);
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((contextIoPtr == NULL) || objc != 2) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be \"object cget -option\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * BE CAREFUL: work in the virtual scope!
+ */
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ if (infoPtr->currContextIclsPtr != NULL) {
+ contextIclsPtr = infoPtr->currContextIclsPtr;
+ }
+
+ hPtr = NULL;
+ /* first check if method cget is delegated */
+ methodNamePtr = Tcl_NewStringObj("*", -1);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions, (char *)
+ methodNamePtr);
+ if (hPtr != NULL) {
+ idmPtr = (ItclDelegatedFunction *)Tcl_GetHashValue(hPtr);
+ Tcl_SetStringObj(methodNamePtr, "cget", -1);
+ hPtr = Tcl_FindHashEntry(&idmPtr->exceptions, (char *)methodNamePtr);
+ if (hPtr == NULL) {
+ icPtr = idmPtr->icPtr;
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, contextIclsPtr);
+ if (val != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+1));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("cget", 4);
+ Tcl_IncrRefCount(newObjv[1]);
+ for(i=1;i<objc;i++) {
+ newObjv[i+1] = objv[i];
+ }
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ oPtr = Tcl_GetObjectFromObj(interp, objPtr);
+ if (oPtr != NULL) {
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ infoPtr->currContextIclsPtr = ioPtr->iclsPtr;
+ }
+ ItclShowArgs(1, "DELEGATED EVAL", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(objPtr);
+ if (oPtr != NULL) {
+ infoPtr->currContextIclsPtr = NULL;
+ }
+ Tcl_DecrRefCount(methodNamePtr);
+ return result;
+ }
+ }
+ }
+ Tcl_DecrRefCount(methodNamePtr);
+ if (objc == 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, "option");
+ return TCL_ERROR;
+ }
+ /* now do the hard work */
+ /* first handle delegated options */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions, (char *)
+ objv[1]);
+ hPtr3 = Tcl_FindHashEntry(&contextIoPtr->objectOptions, (char *)
+ objv[1]);
+ hPtr2 = NULL;
+ if (hPtr == NULL) {
+ objPtr2 = Tcl_NewStringObj("*", -1);
+ /* check for "*" option delegated */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions, (char *)
+ objPtr2);
+ Tcl_DecrRefCount(objPtr2);
+ hPtr2 = Tcl_FindHashEntry(&contextIoPtr->objectOptions, (char *)
+ objv[1]);
+ }
+ if ((hPtr != NULL) && (hPtr2 == NULL) && (hPtr3 == NULL)) {
+ /* the option is delegated */
+ idoPtr = (ItclDelegatedOption *)Tcl_GetHashValue(hPtr);
+ /* if the option is in the exceptions, do nothing */
+ hPtr = Tcl_FindHashEntry(&idoPtr->exceptions, (char *)
+ objv[1]);
+ if (hPtr) {
+ return TCL_CONTINUE;
+ }
+ icPtr = idoPtr->icPtr;
+ if (icPtr->ivPtr->flags & ITCL_COMMON) {
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, icPtr->ivPtr->iclsPtr);
+ } else {
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, contextIoPtr, icPtr->ivPtr->iclsPtr);
+ }
+ if ((val != NULL) && (strlen(val) > 0)) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+1));
+ newObjv[0] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("cget", 4);
+ Tcl_IncrRefCount(newObjv[1]);
+ for(i=1;i<objc;i++) {
+ if (strcmp(Tcl_GetString(idoPtr->namePtr),
+ Tcl_GetString(objv[i])) == 0) {
+ if (idoPtr->asPtr != NULL) {
+ newObjv[i+1] = idoPtr->asPtr;
+ } else {
+ newObjv[i+1] = objv[i];
+ }
+ } else {
+ newObjv[i+1] = objv[i];
+ }
+ }
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(objPtr);
+ oPtr = Tcl_GetObjectFromObj(interp, objPtr);
+ if (oPtr != NULL) {
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ infoPtr->currContextIclsPtr = ioPtr->iclsPtr;
+ }
+ ItclShowArgs(1, "ExtendedCget delegated option", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(objPtr);
+ if (oPtr != NULL) {
+ infoPtr->currContextIclsPtr = NULL;
+ }
+ ckfree((char *)newObjv);
+ return result;
+ } else {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "component \"",
+ Tcl_GetString(icPtr->namePtr),
+ "\" is undefined, needed for option \"",
+ Tcl_GetString(objv[1]),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /* now look if it is an option at all */
+ if ((hPtr2 == NULL) && (hPtr3 == NULL)) {
+ /* no option at all, let the normal configure do the job */
+ return TCL_CONTINUE;
+ }
+ if (hPtr3 != NULL) {
+ ioptPtr = (ItclOption *)Tcl_GetHashValue(hPtr3);
+ } else {
+ ioptPtr = (ItclOption *)Tcl_GetHashValue(hPtr2);
+ }
+ result = TCL_CONTINUE;
+ if (ioptPtr->cgetMethodPtr != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*2);
+ newObjv[0] = ioptPtr->cgetMethodPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = objv[1];
+ Tcl_IncrRefCount(newObjv[1]);
+ ItclShowArgs(1, "eval cget method", objc, newObjv);
+ result = Tcl_EvalObjv(interp, objc, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ } else {
+ val = ItclGetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr),
+ contextIoPtr, ioptPtr->iclsPtr);
+ if (val) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(val, -1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("<undefined>", -1));
+ }
+ result = TCL_OK;
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclExtendedSetGet()
+ *
+ * Invoked whenever the user writes to a methodvariable or calls the method
+ * with the same name as the variable.
+ * only for not ITCL_CLASS classes
+ * Handles the following syntax:
+ *
+ * <objName> setget varName ?<value>?
+ *
+ * Allows access to methodvariables as if they hat a setter and getter
+ * method
+ * With no arguments, this command returns the current
+ * value of the variable. If <value> is specified,
+ * this sets the variable to the value calling a callback if exists:
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+ItclExtendedSetGet(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj **newObjv;
+ ItclMethodVariable *imvPtr;
+ ItclObjectInfo *infoPtr;
+ const char *usageStr;
+ const char *val;
+ int result;
+ int setValue;
+
+ ItclShowArgs(1, "ItclExtendedSetGet", objc, objv);
+ imvPtr = NULL;
+ result = TCL_OK;
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ usageStr = "improper usage: should be \"object setget varName ?value?\"";
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ usageStr, (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * BE CAREFUL: work in the virtual scope!
+ */
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ if (infoPtr->currContextIclsPtr != NULL) {
+ contextIclsPtr = infoPtr->currContextIclsPtr;
+ }
+
+ hPtr = NULL;
+ if (objc < 2) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ usageStr, (char*)NULL);
+ return TCL_ERROR;
+ }
+ /* look if it is an methodvariable at all */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectMethodVariables,
+ (char *) objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "no such methodvariable \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ imvPtr = (ItclMethodVariable *)Tcl_GetHashValue(hPtr);
+ if (objc == 2) {
+ val = ItclGetInstanceVar(interp, Tcl_GetString(objv[1]), NULL,
+ contextIoPtr, imvPtr->iclsPtr);
+ if (val == NULL) {
+ result = TCL_ERROR;
+ } else {
+ Tcl_SetResult(interp, (char *)val, TCL_VOLATILE);
+ }
+ return result;
+ }
+ imvPtr = (ItclMethodVariable *)Tcl_GetHashValue(hPtr);
+ result = TCL_OK;
+ setValue = 1;
+ if (imvPtr->callbackPtr != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*3);
+ newObjv[0] = imvPtr->callbackPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = objv[1];
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = objv[2];
+ Tcl_IncrRefCount(newObjv[2]);
+ result = Tcl_EvalObjv(interp, 3, newObjv, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ ckfree((char *)newObjv);
+ }
+ if (result == TCL_OK) {
+ Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &setValue);
+ /* if setValue != 0 set the new value of the variable here */
+ if (setValue) {
+ if (ItclSetInstanceVar(interp, Tcl_GetString(objv[1]), NULL,
+ Tcl_GetString(objv[2]), contextIoPtr,
+ imvPtr->iclsPtr) == NULL) {
+ result = TCL_ERROR;
+ }
+ }
+ }
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInstallComponentCmd()
+ *
+ * Invoked whenever the user issues the "installcomponent" method for an
+ * object.
+ * Handles the following syntax:
+ *
+ * installcomponent <componentName> using <widgetClassName> <widgetPathName>
+ * ?-option value -option value ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInstallComponentCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj ** newObjv;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *usageStr;
+ const char *componentName;
+ const char *componentValue;
+ const char *token;
+ int numOpts;
+ int result;
+
+
+ ItclShowArgs(1, "Itcl_BiInstallComponentCmd", objc, objv);
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "improper usage: should be \"object installcomponent \"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (objc < 5) {
+ /* FIXME strip off the :: parts here properly*/
+ token = Tcl_GetString(objv[0])+2;
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"", token, " <componentName> using",
+ " <widgetClassName> <widgetPathName>",
+ " ?-option value -option value ...?\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /* get component name and check, if it exists */
+ token = Tcl_GetString(objv[1]);
+ if (contextIclsPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find context class for object \"",
+ Tcl_GetCommandName(interp, contextIoPtr->accessCmd), "\"",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (!(contextIclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ Tcl_AppendResult(interp, "no such method \"installcomponent\"", NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->components, (char *)objv[1]);
+ if (hPtr == NULL) {
+ numOpts = 0;
+ FOREACH_HASH_VALUE(idoPtr, &contextIoPtr->objectDelegatedOptions) {
+ if (idoPtr == NULL) {
+ /* FIXME need code here !! */
+ }
+ numOpts++;
+ }
+ if (numOpts == 0) {
+ /* there are no delegated options, so no problem that the
+ * component does not exist. We have nothing to do */
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "class \"",
+ Tcl_GetString(contextIclsPtr->namePtr),
+ "\" has no component \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ if (contextIclsPtr->flags & ITCL_TYPE) {
+ Tcl_Obj *objPtr;
+ usageStr = "usage: installcomponent <componentName> using <widgetType> <widgetPath> ?-option value ...?";
+ if (objc < 4) {
+ Tcl_AppendResult(interp, usageStr, NULL);
+ return TCL_ERROR;
+ }
+ if (strcmp(Tcl_GetString(objv[2]), "using") != 0) {
+ Tcl_AppendResult(interp, usageStr, NULL);
+ return TCL_ERROR;
+ }
+ componentName = Tcl_GetString(objv[1]);
+ /* as it is no widget, we don't need to check for delegated option */
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc - 3));
+ memcpy(newObjv, objv + 3, sizeof(Tcl_Obj *) * ((objc - 3)));
+ ItclShowArgs(1, "BiInstallComponent", objc - 3, newObjv);
+ result = Tcl_EvalObjv(interp, objc - 3, newObjv, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ componentValue = Tcl_GetStringResult(interp);
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr,
+ (Tcl_GetObjectNamespace(contextIclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr, componentName, -1);
+
+ Tcl_SetVar2(interp, Tcl_GetString(objPtr), NULL, componentValue, 0);
+
+ } else {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 1));
+ newObjv[0] = Tcl_NewStringObj("::itcl::builtin::installcomponent", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv, objv + 1, sizeof(Tcl_Obj *) * ((objc - 1)));
+ result = Tcl_EvalObjv(interp, objc, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ return result;
+ }
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiDestroyCmd()
+ *
+ * Invoked whenever the user issues the "destroy" method for an
+ * object.
+ * Handles the following syntax:
+ *
+ * destroy
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiDestroyCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj **newObjv;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ int result;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiDestroyCmd", objc, objv);
+ contextIoPtr = NULL;
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIclsPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find context class for object \"",
+ Tcl_GetCommandName(interp, contextIoPtr->accessCmd), "\"",
+ NULL);
+ return TCL_ERROR;
+ }
+ if ((objc > 1) || !(contextIclsPtr->flags &
+ (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ /* try to execute destroy in uplevel namespace */
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 2));
+ newObjv[0] = Tcl_NewStringObj("uplevel", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("#0", -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = Tcl_NewStringObj("destroy", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ memcpy(newObjv + 3, objv + 1, sizeof(Tcl_Obj *) * (objc - 1));
+ ItclShowArgs(1, "DESTROY", objc + 2, newObjv);
+ result = Tcl_EvalObjv(interp, objc + 2, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ return result;
+ }
+ if (objc != 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"", Tcl_GetString(objv[0]), (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr != NULL) {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, contextIoPtr->accessCmd, objPtr);
+ Itcl_RenameCommand(interp, Tcl_GetString(objPtr), "");
+ Tcl_DecrRefCount(objPtr);
+ result = TCL_OK;
+ } else {
+ result = Itcl_DeleteClass(interp, contextIclsPtr);
+ }
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiCallInstanceCmd()
+ *
+ * Invoked whenever the a script generated by mytypemethod, mymethod or
+ * myproc is evauated later on:
+ * Handles the following syntax:
+ *
+ * callinstance <instanceName> ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiCallInstanceCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj **newObjv;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObject *ioPtr;
+ const char *token;
+ int result;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiCallInstanceCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc < 2) {
+ token = Tcl_GetString(objv[0]);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"", token, " <instanceName>",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->infoPtr->instances,
+ Tcl_GetString(objv[1]));
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "no such instanceName \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ ioPtr = Tcl_GetHashValue(hPtr);
+ objPtr =Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*) * (objc - 1));
+ newObjv[0] = objPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv + 1, objv + 2, sizeof(Tcl_Obj *) * (objc - 2));
+ result = Tcl_EvalObjv(interp, objc - 1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiGetInstanceVarCmd()
+ *
+ * Invoked whenever the a script generated by mytypevar, myvar or
+ * mycommon is evauated later on:
+ * Handles the following syntax:
+ *
+ * getinstancevar <instanceName> ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiGetInstanceVarCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj **newObjv;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObject *ioPtr;
+ const char *token;
+ int result;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiGetInstanceVarCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (objc < 2) {
+ token = Tcl_GetString(objv[0]);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"", token, " <instanceName>",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->infoPtr->instances,
+ Tcl_GetString(objv[1]));
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "no such instanceName \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ ioPtr = Tcl_GetHashValue(hPtr);
+ objPtr =Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*) * (objc - 1));
+ newObjv[0] = objPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv + 1, objv + 2, sizeof(Tcl_Obj *) * (objc - 2));
+ result = Tcl_EvalObjv(interp, objc - 1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiMyTypeMethodCmd()
+ *
+ * Invoked when a user calls mytypemethod
+ *
+ * Handles the following syntax:
+ *
+ * mytypemethod ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiMyTypeMethodCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr;
+ Tcl_Obj *resultPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ int i;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiMyTypeMethodCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "usage: mytypemethod <name>", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(contextIclsPtr->nsPtr->fullName, -1);
+ resultPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
+
+ for (i = 1; i < objc; i++) {
+ Tcl_ListObjAppendElement(interp, resultPtr, objv[i]);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiMyMethodCmd()
+ *
+ * Invoked when a user calls mymethod
+ *
+ * Handles the following syntax:
+ *
+ * mymethod ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiMyMethodCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ int i;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiMyMethodCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ resultPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, resultPtr,
+ Tcl_NewStringObj("::itcl::builtin::callinstance", -1));
+ Tcl_ListObjAppendElement(interp, resultPtr, Tcl_NewStringObj(
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr))->fullName, -1));
+ for (i = 1; i < objc; i++) {
+ Tcl_ListObjAppendElement(interp, resultPtr, objv[i]);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+ }
+
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiMyProcCmd()
+ *
+ * Invoked when a user calls myproc
+ *
+ * Handles the following syntax:
+ *
+ * myproc ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiMyProcCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr;
+ Tcl_Obj *resultPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ int i;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiMyProcCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "usage: myproc <name>", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(contextIclsPtr->nsPtr->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(objv[1]), -1);
+ resultPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
+
+ for (i = 2; i < objc; i++) {
+ Tcl_ListObjAppendElement(interp, resultPtr, objv[i]);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiMyTypeVarCmd()
+ *
+ * Invoked when a user calls mytypevar
+ *
+ * Handles the following syntax:
+ *
+ * mytypevar ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiMyTypeVarCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr;
+ Tcl_Obj *resultPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ int i;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiMyTypeVarCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "usage: mytypevar <name>", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(contextIclsPtr->nsPtr->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(objv[1]), -1);
+ resultPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, resultPtr, objPtr);
+
+ for (i = 2; i < objc; i++) {
+ Tcl_ListObjAppendElement(interp, resultPtr, objv[i]);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiMyVarCmd()
+ *
+ * Invoked when a user calls myvar
+ *
+ * Handles the following syntax:
+ *
+ * myvar ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiMyVarCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiMyVarCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ resultPtr = Tcl_NewStringObj(Tcl_GetString(contextIoPtr->varNsNamePtr),
+ -1);
+ Tcl_AppendToObj(resultPtr, "::", -1);
+ Tcl_AppendToObj(resultPtr, Tcl_GetString(contextIclsPtr->namePtr), -1);
+ Tcl_AppendToObj(resultPtr, "::", -1);
+ Tcl_AppendToObj(resultPtr, Tcl_GetString(objv[1]), -1);
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiItclHullCmd()
+ *
+ * Invoked when a user calls itcl_hull
+ *
+ * Handles the following syntax:
+ *
+ * itcl_hull ?arg arg ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiItclHullCmd(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ const char *val;
+
+ /*
+ * Make sure that this command is being invoked in the proper
+ * context.
+ */
+ ItclShowArgs(1, "Itcl_BiItclHullCmd", objc, objv);
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ val = ItclGetInstanceVar(interp, "itcl_hull", NULL,
+ contextIoPtr, contextIclsPtr);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(val, -1));
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiCreateHullCmd()
+ *
+ * Invoked by Tcl normally during evaluating constructor
+ * the "createhull" command is invoked to install and setup an
+ * ::itcl::extendedclass itcl_hull
+ * for an object. Handles the following syntax:
+ *
+ * createhull <widget_type> <widget_path> ?-class <widgetClassName>?
+ * ?<optionName> <optionValue> <optionName> <optionValue> ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_BiCreateHullCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+
+ ItclShowArgs(1, "Itcl_BiCreateHullCmd", objc, objv);
+ if (!infoPtr->itclHullCmdsInitted) {
+ result = Tcl_EvalEx(interp, initHullCmdsScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclHullCmdsInitted = 1;
+ }
+ return Tcl_EvalObjv(interp, objc, objv, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiSetupComponentCmd()
+ *
+ * Invoked by Tcl during evaluating constructor whenever
+ * the "setupcomponent" command is invoked to install and setup an
+ * ::itcl::extendedclass component
+ * for an object. Handles the following syntax:
+ *
+ * setupcomponent <componentName> using <widgetType> <widget_path>
+ * ?<optionName> <optionValue> <optionName> <optionValue> ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_BiSetupComponentCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+
+ ItclShowArgs(1, "Itcl_BiSetupComponentCmd", objc, objv);
+ if (!infoPtr->itclHullCmdsInitted) {
+ result = Tcl_EvalEx(interp, initHullCmdsScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclHullCmdsInitted = 1;
+ }
+ return Tcl_EvalObjv(interp, objc, objv, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInitOptionsCmd()
+ *
+ * Invoked by Tcl during evaluating constructor whenever
+ * the "itcl_initoptions" command is invoked to install and setup an
+ * ::itcl::extendedclass options
+ * for an object. Handles the following syntax:
+ *
+ * itcl_initoptions
+ * ?<optionName> <optionValue> <optionName> <optionValue> ...?
+ * FIXME !!!! seems no longer been used !!!
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_BiInitOptionsCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+ ItclDelegatedOption *idoptPtr;
+ ItclOption *ioptPtr;
+ FOREACH_HASH_DECLS;
+
+ /* instead ::itcl::builtin::initoptions in ../library/itclHullCmds.tcl is used !! */
+ ItclShowArgs(1, "Itcl_BiInitOptionsCmd", objc, objv);
+ if (!infoPtr->itclHullCmdsInitted) {
+ result = Tcl_EvalEx(interp, initHullCmdsScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclHullCmdsInitted = 1;
+ }
+ result = Tcl_EvalObjv(interp, objc, objv, 0);
+ iclsPtr = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /* first handle delegated options */
+ FOREACH_HASH_VALUE(idoptPtr, &ioPtr->objectDelegatedOptions) {
+fprintf(stderr, "delopt!%s!\n", Tcl_GetString(idoptPtr->namePtr));
+ }
+ FOREACH_HASH_VALUE(ioptPtr, &ioPtr->objectOptions) {
+fprintf(stderr, "opt!%s!\n", Tcl_GetString(ioptPtr->namePtr));
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiKeepComponentOptionCmd()
+ *
+ * Invoked by Tcl during evaluating constructor whenever
+ * the "keepcomponentoption" command is invoked to list the options
+ * to be kept when and ::itcl::extendedclass component has been setup
+ * for an object. Handles the following syntax:
+ *
+ * keepcomponentoption <componentName> <optionName> ?<optionName> ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_BiKeepComponentOptionCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+
+ ItclShowArgs(1, "Itcl_BiKeepComponentOptionCmd", objc, objv);
+ if (!infoPtr->itclHullCmdsInitted) {
+ result = Tcl_EvalEx(interp, initHullCmdsScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclHullCmdsInitted = 1;
+ }
+ result = Tcl_EvalObjv(interp, objc, objv, 0);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiIgnoreComponentOptionCmd()
+ *
+ * Invoked by Tcl during evaluating constructor whenever
+ * the "keepcomponentoption" command is invoked to list the options
+ * to be kept when and ::itcl::extendedclass component has been setup
+ * for an object. Handles the following syntax:
+ *
+ * ignorecomponentoption <componentName> <optionName> ?<optionName> ...?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_BiIgnoreComponentOptionCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj *objPtr;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+ ItclDelegatedOption *idoPtr;
+ ItclComponent *icPtr;
+ const char *val;
+ int idx;
+ int isNew;
+ int result;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+
+ ItclShowArgs(0, "Itcl_BiIgnoreComponentOptionCmd", objc, objv);
+ if (!infoPtr->itclHullCmdsInitted) {
+ result = Tcl_Eval(interp, initHullCmdsScript);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclHullCmdsInitted = 1;
+ }
+ iclsPtr = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc < 3) {
+ Tcl_AppendResult(interp, "wrong # args, should be: ",
+ "ignorecomponentoption component option ?option ...?", NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectComponents, (char *)objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "ignorecomponentoption cannot find component \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ icPtr = Tcl_GetHashValue(hPtr);
+ icPtr->haveKeptOptions = 1;
+ for (idx = 2; idx < objc; idx++) {
+ hPtr = Tcl_CreateHashEntry(&icPtr->keptOptions, (char *)objv[idx],
+ &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, objv[idx]);
+ }
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectDelegatedOptions,
+ (char *)objv[idx], &isNew);
+ if (isNew) {
+ idoPtr = (ItclDelegatedOption *)ckalloc(sizeof(
+ ItclDelegatedOption));
+ memset(idoPtr, 0, sizeof(ItclDelegatedOption));
+ Tcl_InitObjHashTable(&idoPtr->exceptions);
+ idoPtr->namePtr = objv[idx];
+ Tcl_IncrRefCount(idoPtr->namePtr);
+ idoPtr->resourceNamePtr = NULL;
+ if (idoPtr->resourceNamePtr != NULL) {
+ Tcl_IncrRefCount(idoPtr->resourceNamePtr);
+ }
+ idoPtr->classNamePtr = NULL;
+ if (idoPtr->classNamePtr != NULL) {
+ Tcl_IncrRefCount(idoPtr->classNamePtr);
+ }
+ idoPtr->icPtr = icPtr;
+ idoPtr->ioptPtr = NULL;
+ Tcl_SetHashValue(hPtr2, idoPtr);
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr),
+ NULL, ioPtr, iclsPtr);
+ if (val != NULL) {
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_AppendToObj(objPtr, " cget ", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(objv[idx]), -1);
+ Tcl_IncrRefCount(objPtr);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ Tcl_DecrRefCount(objPtr);
+ if (result == TCL_OK) {
+ ItclSetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(objv[idx]),
+ Tcl_GetStringResult(interp), ioPtr, iclsPtr);
+ }
+ }
+ }
+ }
+ ItclAddClassComponentDictInfo(interp, iclsPtr, icPtr);
+ }
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclClass.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclClass.c
new file mode 100644
index 0000000..af02d6e
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclClass.c
@@ -0,0 +1,2640 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * These procedures handle class definitions. Classes are composed of
+ * data members (public/protected/common) and the member functions
+ * (methods/procs) that operate on them. Each class has its own
+ * namespace which manages the class scope.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann Copyright (c) 2007
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+static Tcl_NamespaceDeleteProc* _TclOONamespaceDeleteProc = NULL;
+static void ItclDeleteOption(char *cdata);
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static void ItclDestroyClass(ClientData cdata);
+static void ItclFreeClass (char* cdata);
+static void ItclDeleteFunction(ItclMemberFunc *imPtr);
+static void ItclDeleteComponent(ItclComponent *icPtr);
+static void ItclDeleteOption(char *cdata);
+
+void
+ItclPreserveClass(
+ ItclClass *iclsPtr)
+{
+ iclsPtr->refCount++;
+}
+
+void
+ItclReleaseClass(
+ ClientData clientData)
+{
+ ItclClass *iclsPtr = (ItclClass *)clientData;
+
+ if (--iclsPtr->refCount == 0) {
+ ItclFreeClass((char *) clientData);
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteMemberFunc()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+void Itcl_DeleteMemberFunc (
+ char *cdata)
+{
+ /* needed for stubs compatibility */
+ ItclMemberFunc *imPtr;
+
+ imPtr = (ItclMemberFunc *)cdata;
+ if (imPtr == NULL) {
+ /* FIXME need code here */
+ }
+ ItclDeleteFunction((ItclMemberFunc *)cdata);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDestroyClass2()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static void
+ItclDestroyClass2(
+ ClientData clientData) /* The class being deleted. */
+{
+ ItclClass *iclsPtr;
+
+ iclsPtr = clientData;
+ ItclDestroyClassNamesp(iclsPtr);
+ ItclReleaseClass(iclsPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ClassCmdDeleteTrace()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static void
+ClassCmdDeleteTrace(
+ ClientData clientData, /* The class being deleted. */
+ Tcl_Interp *interp, /* The interpreter containing the object. */
+ const char *oldName, /* What the object was (last) called. */
+ const char *newName, /* Always NULL. */
+ int flags) /* Why was the object deleted? */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_DString buffer;
+ Tcl_Namespace *nsPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr = clientData;
+
+ /*
+ * How is it decided what cleanup is done here tracing the access command deletion,
+ * versus what cleanup is done by the Tcl_CmdDeleteProc tied to the access command?
+ */
+
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr);
+ if (hPtr == NULL) {
+ return;
+ }
+ if (iclsPtr->flags & ITCL_CLASS_IS_RENAMED) { /* DUMB! name for this flag */
+ return; /* Flag very likely serves no purpose as well. */
+ }
+ iclsPtr->flags |= ITCL_CLASS_IS_RENAMED; /* DUMB! name for this flag */
+ ItclPreserveClass(iclsPtr);
+ /* delete the namespace for the common variables */
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(iclsPtr->oPtr))->fullName, -1);
+ nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ if (nsPtr != NULL) {
+ Tcl_DeleteNamespace(nsPtr);
+ }
+ if (!(iclsPtr->flags & ITCL_CLASS_NS_IS_DESTROYED)) {
+ ItclDestroyClassNamesp(iclsPtr);
+ }
+ ItclReleaseClass(iclsPtr);
+ return;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteClassMetadata()
+ *
+ * Delete the metadata data if any
+ *-------------------------------------------------------------------------
+ */
+void
+ItclDeleteClassMetadata(
+ ClientData clientData)
+{
+ /*
+ * This is how we get alerted from TclOO that the object corresponding
+ * to an Itcl class (or its namespace...) is being torn down.
+ */
+
+ ItclClass *iclsPtr = clientData;
+ Tcl_Object oPtr = iclsPtr->oPtr;
+ Tcl_Namespace *ooNsPtr = Tcl_GetObjectNamespace(oPtr);
+
+ if (ooNsPtr != iclsPtr->nsPtr) {
+ /*
+ * Itcl's idea of the class namespace is different from that of TclOO.
+ * Make sure both get torn down and pulled from tables.
+ */
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->namespaceClasses,
+ (char *)ooNsPtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteNamespace(iclsPtr->nsPtr);
+ } else {
+ ItclDestroyClass2(iclsPtr);
+ }
+ ItclReleaseClass(iclsPtr);
+}
+
+static int
+CallNewObjectInstance(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ItclObjectInfo *infoPtr = data[0];
+ const char* path = data[1];
+ Tcl_Object *oPtr = data[2];
+ Tcl_Obj *nameObjPtr = data[3];
+
+ *oPtr = Tcl_NewObjectInstance(interp, infoPtr->clazzClassPtr,
+ path, path, 0, NULL, 0);
+ if (*oPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "ITCL: cannot create Tcl_NewObjectInstance for class \"",
+ Tcl_GetString(nameObjPtr), "\"", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateClass()
+ *
+ * Creates a namespace and its associated class definition data.
+ * If a namespace already exists with that name, then this routine
+ * returns TCL_ERROR, along with an error message in the interp.
+ * If successful, it returns TCL_OK and a pointer to the new class
+ * definition.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateClass(
+ Tcl_Interp* interp, /* interpreter that will contain new class */
+ const char* path, /* name of new class */
+ ItclObjectInfo *infoPtr, /* info for all known objects */
+ ItclClass **rPtr) /* returns: pointer to class definition */
+{
+ const char *head;
+ const char *tail;
+ Tcl_DString buffer;
+ Tcl_Command cmd;
+ Tcl_CmdInfo cmdInfo;
+ Tcl_Namespace *classNs, *ooNs;
+ Tcl_Object oPtr;
+ Tcl_Obj *nameObjPtr;
+ Tcl_Obj *namePtr;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ Tcl_HashEntry *hPtr;
+ void *callbackPtr;
+ int result;
+ int newEntry;
+ ItclResolveInfo *resolveInfoPtr;
+ Tcl_Obj *cmdNamePtr;
+
+ /*
+ * check for an empty class name to avoid a crash
+ */
+ if (strlen(path) == 0) {
+ Tcl_AppendResult(interp, "invalid class name \"\"", NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure that a class with the given name does not
+ * already exist in the current namespace context. If a
+ * namespace exists, that's okay. It may have been created
+ * to contain stubs during a "namespace import" operation.
+ * We'll just replace the namespace data below with the
+ * proper class data.
+ */
+ classNs = Tcl_FindNamespace(interp, (const char *)path,
+ (Tcl_Namespace*)NULL, /* flags */ 0);
+
+ if (classNs != NULL && Itcl_IsClassNamespace(classNs)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "class \"", path, "\" already exists",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ oPtr = NULL;
+ /*
+ * Make sure that a command with the given class name does not
+ * already exist in the current namespace. This prevents the
+ * usual Tcl commands from being clobbered when a programmer
+ * makes a bogus call like "class info".
+ */
+ cmd = Tcl_FindCommand(interp, (const char *)path,
+ (Tcl_Namespace*)NULL, /* flags */ TCL_NAMESPACE_ONLY);
+
+ if (cmd != NULL && !Itcl_IsStub(cmd)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "command \"", path, "\" already exists",
+ (char*)NULL);
+
+ if (strstr(path,"::") == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ " in namespace \"",
+ Tcl_GetCurrentNamespace(interp)->fullName, "\"",
+ (char*)NULL);
+ }
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that the class name does not have any goofy
+ * characters:
+ *
+ * . => reserved for member access like: class.publicVar
+ */
+ Itcl_ParseNamespPath(path, &buffer, &head, &tail);
+
+ if (strstr(tail,".")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad class name \"", tail, "\"",
+ (char*)NULL);
+ Tcl_DStringFree(&buffer);
+ return TCL_ERROR;
+ }
+ Tcl_DStringFree(&buffer);
+
+ /*
+ * Allocate class definition data.
+ */
+ iclsPtr = (ItclClass*)ckalloc(sizeof(ItclClass));
+ memset(iclsPtr, 0, sizeof(ItclClass));
+ iclsPtr->interp = interp;
+ iclsPtr->infoPtr = infoPtr;
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_InitObjHashTable(&iclsPtr->variables);
+ Tcl_InitObjHashTable(&iclsPtr->functions);
+ Tcl_InitObjHashTable(&iclsPtr->options);
+ Tcl_InitObjHashTable(&iclsPtr->components);
+ Tcl_InitObjHashTable(&iclsPtr->delegatedOptions);
+ Tcl_InitObjHashTable(&iclsPtr->delegatedFunctions);
+ Tcl_InitObjHashTable(&iclsPtr->methodVariables);
+ Tcl_InitObjHashTable(&iclsPtr->resolveCmds);
+
+ iclsPtr->numInstanceVars = 0;
+ Tcl_InitHashTable(&iclsPtr->classCommons, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iclsPtr->resolveVars, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iclsPtr->contextCache, TCL_ONE_WORD_KEYS);
+
+ Itcl_InitList(&iclsPtr->bases);
+ Itcl_InitList(&iclsPtr->derived);
+
+ resolveInfoPtr = (ItclResolveInfo *) ckalloc(sizeof(ItclResolveInfo));
+ memset (resolveInfoPtr, 0, sizeof(ItclResolveInfo));
+ resolveInfoPtr->flags = ITCL_RESOLVE_CLASS;
+ resolveInfoPtr->iclsPtr = iclsPtr;
+ iclsPtr->resolvePtr = (Tcl_Resolve *)ckalloc(sizeof(Tcl_Resolve));
+ iclsPtr->resolvePtr->cmdProcPtr = Itcl_CmdAliasProc;
+ iclsPtr->resolvePtr->varProcPtr = Itcl_VarAliasProc;
+ iclsPtr->resolvePtr->clientData = resolveInfoPtr;
+ iclsPtr->flags = infoPtr->currClassFlags;
+
+ /*
+ * Initialize the heritage info--each class starts with its
+ * own class definition in the heritage. Base classes are
+ * added to the heritage from the "inherit" statement.
+ */
+ Tcl_InitHashTable(&iclsPtr->heritage, TCL_ONE_WORD_KEYS);
+ (void) Tcl_CreateHashEntry(&iclsPtr->heritage, (char*)iclsPtr, &newEntry);
+
+ /*
+ * Create a namespace to represent the class. Add the class
+ * definition info as client data for the namespace. If the
+ * namespace already exists, then replace any existing client
+ * data with the class data.
+ */
+
+ ItclPreserveClass(iclsPtr);
+
+ nameObjPtr = Tcl_NewStringObj("", 0);
+ Tcl_IncrRefCount(nameObjPtr);
+ if ((path[0] != ':') || (path[1] != ':')) {
+ Tcl_Namespace *currNsPtr = Tcl_GetCurrentNamespace(interp);
+ Tcl_AppendToObj(nameObjPtr, currNsPtr->fullName, -1);
+ if (currNsPtr->parentPtr != NULL) {
+ Tcl_AppendToObj(nameObjPtr, "::", 2);
+ }
+ }
+ Tcl_AppendToObj(nameObjPtr, path, -1);
+ {
+ /*
+ * TclOO machinery will refuse to overwrite an existing command
+ * with creation of a new object. However, Itcl has a legacy
+ * "stubs" auto-importing mechanism that explicitly needs such
+ * overwriting. So, check whether we have a stub, and if so,
+ * delete it before TclOO has a chance to object.
+ */
+ Tcl_Command oldCmd = Tcl_FindCommand(interp, path, NULL, 0);
+
+ if (Itcl_IsStub(oldCmd)) {
+ Tcl_DeleteCommandFromToken(interp, oldCmd);
+ }
+ }
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ /*
+ * Create a command in the current namespace to manage the class:
+ * <className>
+ * <className> <objName> ?<constructor-args>?
+ */
+ Tcl_NRAddCallback(interp, CallNewObjectInstance, infoPtr,
+ (ClientData)path, &oPtr, nameObjPtr);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (result == TCL_ERROR) {
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ iclsPtr->clsPtr = Tcl_GetObjectAsClass(oPtr);
+ iclsPtr->oPtr = oPtr;
+ ItclPreserveClass(iclsPtr);
+ Tcl_ObjectSetMetadata(iclsPtr->oPtr, infoPtr->class_meta_type, iclsPtr);
+ cmd = Tcl_GetObjectCommand(iclsPtr->oPtr);
+ Tcl_GetCommandInfoFromToken(cmd, &cmdInfo);
+ cmdInfo.deleteProc = ItclDestroyClass;
+ cmdInfo.deleteData = iclsPtr;
+ Tcl_SetCommandInfoFromToken(cmd, &cmdInfo);
+ ooNs = Tcl_GetObjectNamespace(oPtr);
+ classNs = Tcl_FindNamespace(interp, Tcl_GetString(nameObjPtr),
+ (Tcl_Namespace*)NULL, /* flags */ 0);
+ if (_TclOONamespaceDeleteProc == NULL) {
+ _TclOONamespaceDeleteProc = ooNs->deleteProc;
+ }
+
+ if (classNs == NULL) {
+ Tcl_AppendResult(interp,
+ "ITCL: cannot create/get class namespace for class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"", NULL);
+ return TCL_ERROR;
+ }
+
+ if (iclsPtr->infoPtr->useOldResolvers) {
+#ifdef NEW_PROTO_RESOLVER
+ Itcl_SetNamespaceResolvers(ooNs,
+ (Tcl_ResolveCmdProc*)Itcl_ClassCmdResolver2,
+ (Tcl_ResolveVarProc*)Itcl_ClassVarResolver2,
+ (Tcl_ResolveCompiledVarProc*)Itcl_ClassCompiledVarResolver2);
+ Itcl_SetNamespaceResolvers(classNs,
+ (Tcl_ResolveCmdProc*)Itcl_ClassCmdResolver2,
+ (Tcl_ResolveVarProc*)Itcl_ClassVarResolver2,
+ (Tcl_ResolveCompiledVarProc*)Itcl_ClassCompiledVarResolver2);
+#else
+ Itcl_SetNamespaceResolvers(ooNs,
+ (Tcl_ResolveCmdProc*)Itcl_ClassCmdResolver,
+ (Tcl_ResolveVarProc*)Itcl_ClassVarResolver,
+ (Tcl_ResolveCompiledVarProc*)Itcl_ClassCompiledVarResolver);
+ Itcl_SetNamespaceResolvers(classNs,
+ (Tcl_ResolveCmdProc*)Itcl_ClassCmdResolver,
+ (Tcl_ResolveVarProc*)Itcl_ClassVarResolver,
+ (Tcl_ResolveCompiledVarProc*)Itcl_ClassCompiledVarResolver);
+#endif
+ } else {
+ Tcl_SetNamespaceResolver(ooNs, iclsPtr->resolvePtr);
+ Tcl_SetNamespaceResolver(classNs, iclsPtr->resolvePtr);
+ }
+ iclsPtr->nsPtr = classNs;
+
+
+ iclsPtr->namePtr = Tcl_NewStringObj(classNs->name, -1);
+ Tcl_IncrRefCount(iclsPtr->namePtr);
+
+ iclsPtr->fullNamePtr = Tcl_NewStringObj(classNs->fullName, -1);
+ Tcl_IncrRefCount(iclsPtr->fullNamePtr);
+
+ hPtr = Tcl_CreateHashEntry(&infoPtr->nameClasses,
+ (char *)iclsPtr->fullNamePtr, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)iclsPtr);
+
+
+ hPtr = Tcl_CreateHashEntry(&infoPtr->namespaceClasses, (char *)classNs,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)iclsPtr);
+ if (classNs != ooNs) {
+ hPtr = Tcl_CreateHashEntry(&infoPtr->namespaceClasses, (char *)ooNs,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)iclsPtr);
+
+ if (classNs->clientData && classNs->deleteProc) {
+ (*classNs->deleteProc)(classNs->clientData);
+ }
+ classNs->clientData = (ClientData)iclsPtr;
+ classNs->deleteProc = ItclDestroyClass2;
+}
+
+ hPtr = Tcl_CreateHashEntry(&infoPtr->classes, (char *)iclsPtr, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)iclsPtr);
+
+ /*
+ * now build the namespace for the common private and protected variables
+ * public variables go directly to the class namespace
+ */
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(iclsPtr->oPtr))->fullName, -1);
+ if ((NULL == Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL,
+ TCL_GLOBAL_ONLY)) && (NULL == Tcl_CreateNamespace(interp,
+ Tcl_DStringValue(&buffer), NULL, 0))) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "ITCL: cannot create variables namespace \"",
+ Tcl_DStringValue(&buffer), "\"", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+
+ /*
+ * Add the built-in "this" command to the list of function members.
+ */
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_DStringAppend(&buffer, "::this", -1);
+ iclsPtr->thisCmd = Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
+ Itcl_ThisCmd, iclsPtr, NULL);
+
+ /*
+ * Add the built-in "type" variable to the list of data members.
+ */
+ if (iclsPtr->flags & ITCL_TYPE) {
+ namePtr = Tcl_NewStringObj("type", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_TYPE_VAR; /* mark as "type" variable */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+ }
+
+ if (iclsPtr->flags & (ITCL_ECLASS)) {
+ namePtr = Tcl_NewStringObj("win", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_WIN_VAR; /* mark as "win" variable */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ namePtr = Tcl_NewStringObj("self", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_SELF_VAR; /* mark as "self" variable */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+
+ namePtr = Tcl_NewStringObj("selfns", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_SELFNS_VAR; /* mark as "selfns" variable */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+
+ namePtr = Tcl_NewStringObj("win", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_WIN_VAR; /* mark as "win" variable */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+ }
+ namePtr = Tcl_NewStringObj("this", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_THIS_VAR; /* mark as "this" variable */
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+
+ if (infoPtr->currClassFlags &
+ (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET)) {
+ /*
+ * Add the built-in "itcl_options" variable to the list of
+ * data members.
+ */
+ namePtr = Tcl_NewStringObj("itcl_options", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_OPTIONS_VAR; /* mark as "itcl_options"
+ * variable */
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+
+ }
+ if (infoPtr->currClassFlags &
+ ITCL_ECLASS) {
+ /*
+ * Add the built-in "itcl_option_components" variable to the list of
+ * data members.
+ */
+ namePtr = Tcl_NewStringObj("itcl_option_components", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_OPTION_COMP_VAR; /* mark as "itcl_option_components"
+ * variable */
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+
+ }
+ if (infoPtr->currClassFlags & (ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ /*
+ * Add the built-in "thiswin" variable to the list of data members.
+ */
+ namePtr = Tcl_NewStringObj("thiswin", -1);
+ (void) Itcl_CreateVariable(interp, iclsPtr, namePtr, (char*)NULL,
+ (char*)NULL, &ivPtr);
+
+ ivPtr->protection = ITCL_PROTECTED; /* always "protected" */
+ ivPtr->flags |= ITCL_THIS_VAR; /* mark as "thiswin" variable */
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr,
+ &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+ }
+ if (infoPtr->currClassFlags & (ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ /* create the itcl_hull component */
+ ItclComponent *icPtr;
+ namePtr = Tcl_NewStringObj("itcl_hull", 9);
+ /* itcl_hull must not be an ITCL_COMMON!! */
+ if (ItclCreateComponent(interp, iclsPtr, namePtr, 0, &icPtr) !=
+ TCL_OK) {
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ }
+
+ ItclPreserveClass(iclsPtr);
+ iclsPtr->accessCmd = Tcl_GetObjectCommand(oPtr);
+
+ cmdNamePtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, iclsPtr->accessCmd, cmdNamePtr);
+
+ Tcl_TraceCommand(interp, Tcl_GetString(cmdNamePtr),
+ TCL_TRACE_DELETE, ClassCmdDeleteTrace, iclsPtr);
+
+ Tcl_DecrRefCount(cmdNamePtr);
+ /* FIXME should set the class objects unknown command to Itcl_HandleClass */
+
+ *rPtr = iclsPtr;
+ result = TCL_OK;
+errorOut:
+ Tcl_DecrRefCount(nameObjPtr);
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteClassVariablesNamespace()
+ *
+ * ------------------------------------------------------------------------
+ */
+void
+ItclDeleteClassVariablesNamespace(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr)
+{
+ /* TODO: why is this being skipped? */
+ return;
+}
+
+static int
+CallDeleteOneObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch place;
+ ItclClass *iclsPtr2 = NULL;
+ ItclObject *contextIoPtr;
+ ItclClass *iclsPtr = data[0];
+ ItclObjectInfo *infoPtr = data[1];
+ void *callbackPtr;
+ int classIsDeleted;
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ classIsDeleted = 0;
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr);
+ if (hPtr == NULL) {
+ classIsDeleted = 1;
+ }
+ if (classIsDeleted) {
+ return result;
+ }
+ /*
+ * Fix 227804: Whenever an object to delete was found we
+ * have to reset the search to the beginning as the
+ * current entry in the search was deleted and accessing it
+ * is therefore not allowed anymore.
+ */
+
+ hPtr = Tcl_FirstHashEntry(&infoPtr->objects, &place);
+ if (hPtr) {
+ contextIoPtr = (ItclObject*)Tcl_GetHashValue(hPtr);
+
+ while (contextIoPtr->iclsPtr != iclsPtr) {
+ hPtr = Tcl_NextHashEntry(&place);
+ if (hPtr == NULL) {
+ break;
+ }
+ }
+ if (hPtr) {
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ if (Itcl_DeleteObject(interp, contextIoPtr) != TCL_OK) {
+ iclsPtr2 = iclsPtr;
+ goto deleteClassFail;
+ }
+
+ Tcl_NRAddCallback(interp, CallDeleteOneObject, iclsPtr,
+ infoPtr, NULL, NULL);
+ return Itcl_NRRunCallbacks(interp, callbackPtr);
+ }
+
+ }
+
+ return TCL_OK;
+
+deleteClassFail:
+ /* check if class is not yet deleted */
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr2);
+ if (hPtr != NULL) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while deleting class \"%s\")",
+ iclsPtr2->nsPtr->fullName));
+ }
+ return TCL_ERROR;
+}
+
+static int
+CallDeleteOneClass(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_HashEntry *hPtr;
+ ItclClass *iclsPtr = data[0];
+ ItclObjectInfo *infoPtr = data[1];
+ int isDerivedReleased;
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ isDerivedReleased = iclsPtr->flags & ITCL_CLASS_DERIVED_RELEASED;
+ result = Itcl_DeleteClass(interp, iclsPtr);
+ if (!isDerivedReleased) {
+ if (result == TCL_OK) {
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr);
+ if (hPtr != NULL) {
+ /* release from derived reference */
+ ItclReleaseClass(iclsPtr);
+ }
+ }
+ }
+ if (result == TCL_OK) {
+ return TCL_OK;
+ }
+
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while deleting class \"%s\")",
+ iclsPtr->nsPtr->fullName));
+ return TCL_ERROR;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteClass()
+ *
+ * Deletes a class by deleting all derived classes and all objects in
+ * that class, and finally, by destroying the class namespace. This
+ * procedure provides a friendly way of doing this. If any errors
+ * are detected along the way, the process is aborted.
+ *
+ * Returns TCL_OK if successful, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_DeleteClass(
+ Tcl_Interp *interp, /* interpreter managing this class */
+ ItclClass *iclsPtr) /* class */
+{
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr2 = NULL;
+ Itcl_ListElem *elem;
+ void *callbackPtr;
+ int result;
+
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr);
+ if (hPtr == NULL) {
+ /* class has already been deleted */
+ return TCL_OK;
+ }
+ if (iclsPtr->flags & ITCL_CLASS_IS_DELETED) {
+ return TCL_OK;
+ }
+ iclsPtr->flags |= ITCL_CLASS_IS_DELETED;
+ /*
+ * Destroy all derived classes, since these lose their meaning
+ * when the base class goes away. If anything goes wrong,
+ * abort with an error.
+ *
+ * TRICKY NOTE: When a derived class is destroyed, it
+ * automatically deletes itself from the "derived" list.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->derived);
+ while (elem) {
+ iclsPtr2 = (ItclClass*)Itcl_GetListValue(elem);
+ elem = Itcl_NextListElem(elem); /* advance here--elem will go away */
+
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, CallDeleteOneClass, iclsPtr2,
+ iclsPtr2->infoPtr, NULL, NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+
+ /*
+ * Scan through and find all objects that belong to this class.
+ * Note that more specialized objects have already been
+ * destroyed above, when derived classes were destroyed.
+ * Destroy objects and report any errors.
+ */
+ /*
+ * we have to enroll the while loop to fit for NRE
+ * so we add a callback to delete the first element
+ * and run this callback. At the end of the execution of that callback
+ * we add eventually a callback for the next element and run that etc ...
+ * if an error occurs we terminate the enrolled loop and return
+ * otherwise we return at the end of the enrolled loop.
+ */
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, CallDeleteOneObject, iclsPtr,
+ iclsPtr->infoPtr, NULL, NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ /*
+ * Destroy the namespace associated with this class.
+ *
+ * TRICKY NOTE:
+ * The cleanup procedure associated with the namespace is
+ * invoked automatically. It does all of the same things
+ * above, but it also disconnects this class from its
+ * base-class lists, and removes the class access command.
+ */
+ ItclDeleteClassVariablesNamespace(interp, iclsPtr);
+ Tcl_DeleteNamespace(iclsPtr->nsPtr);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDestroyClass()
+ *
+ * Invoked whenever the access command for a class is destroyed.
+ * Destroys the namespace associated with the class, which also
+ * destroys all objects in the class and all derived classes.
+ * Disconnects this class from the "derived" class lists of its
+ * base classes, and releases any claim to the class definition
+ * data. If this is the last use of that data, the class will
+ * completely vanish at this point.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDestroyClass(
+ ClientData cdata) /* class definition to be destroyed */
+{
+ ItclClass *iclsPtr = (ItclClass*)cdata;
+
+ if (iclsPtr->flags & ITCL_CLASS_IS_DESTROYED) {
+ return;
+ }
+ iclsPtr->flags |= ITCL_CLASS_IS_DESTROYED;
+ if (!(iclsPtr->flags & ITCL_CLASS_NS_IS_DESTROYED)) {
+ if (iclsPtr->accessCmd) {
+ Tcl_DeleteCommandFromToken(iclsPtr->interp, iclsPtr->accessCmd);
+ iclsPtr->accessCmd = NULL;
+ }
+ Tcl_DeleteNamespace(iclsPtr->nsPtr);
+ }
+ ItclReleaseClass(iclsPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDestroyClassNamesp()
+ *
+ * Invoked whenever the namespace associated with a class is destroyed.
+ * Destroys all objects associated with this class and all derived
+ * classes. Disconnects this class from the "derived" class lists
+ * of its base classes, and removes the class access command. Releases
+ * any claim to the class definition data. If this is the last use
+ * of that data, the class will completely vanish at this point.
+ * ------------------------------------------------------------------------
+ */
+void
+ItclDestroyClassNamesp(
+ ClientData cdata) /* class definition to be destroyed */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch place;
+ Tcl_Command cmdPtr;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+ Itcl_ListElem *elem;
+ Itcl_ListElem *belem;
+ ItclClass *iclsPtr2;
+ ItclClass *basePtr;
+ ItclClass *derivedPtr;
+
+
+ iclsPtr = (ItclClass*)cdata;
+ if (iclsPtr->flags & ITCL_CLASS_NS_IS_DESTROYED) {
+ return;
+ }
+ iclsPtr->flags |= ITCL_CLASS_NS_IS_DESTROYED;
+ /*
+ * Destroy all derived classes, since these lose their meaning
+ * when the base class goes away.
+ *
+ * TRICKY NOTE: When a derived class is destroyed, it
+ * automatically deletes itself from the "derived" list.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->derived);
+ while (elem) {
+ iclsPtr2 = (ItclClass*)Itcl_GetListValue(elem);
+ if (iclsPtr2->nsPtr != NULL) {
+ Tcl_DeleteNamespace(iclsPtr2->nsPtr);
+ }
+
+ /* As the first namespace is now destroyed we have to get the
+ * new first element of the hash table. We cannot go to the
+ * next element from the current one, because the current one
+ * is deleted. itcl Patch #593112, for Bug #577719.
+ */
+
+ elem = Itcl_FirstListElem(&iclsPtr->derived);
+ }
+
+ /*
+ * Scan through and find all objects that belong to this class.
+ * Destroy them quietly by deleting their access command.
+ */
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->infoPtr->objects, &place);
+ while (hPtr) {
+ ioPtr = (ItclObject*)Tcl_GetHashValue(hPtr);
+ if (ioPtr->iclsPtr == iclsPtr) {
+ if ((ioPtr->accessCmd != NULL) && (!(ioPtr->flags &
+ (ITCL_OBJECT_IS_DESTRUCTED)))) {
+ ItclPreserveObject(ioPtr);
+ Tcl_DeleteCommandFromToken(iclsPtr->interp, ioPtr->accessCmd);
+ ioPtr->accessCmd = NULL;
+ ItclReleaseObject(ioPtr);
+ /*
+ * Fix 227804: Whenever an object to delete was found we
+ * have to reset the search to the beginning as the
+ * current entry in the search was deleted and accessing it
+ * is therefore not allowed anymore.
+ */
+
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->infoPtr->objects, &place);
+ continue;
+ }
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+
+ /*
+ * Next, remove this class from the "derived" list in
+ * all base classes.
+ */
+ belem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (belem) {
+ basePtr = (ItclClass*)Itcl_GetListValue(belem);
+
+ elem = Itcl_FirstListElem(&basePtr->derived);
+ while (elem) {
+ derivedPtr = (ItclClass*)Itcl_GetListValue(elem);
+ if (derivedPtr == iclsPtr) {
+ derivedPtr->flags |= ITCL_CLASS_DERIVED_RELEASED;
+ ItclReleaseClass(derivedPtr);
+ elem = Itcl_DeleteListElem(elem);
+ } else {
+ elem = Itcl_NextListElem(elem);
+ }
+ }
+ belem = Itcl_NextListElem(belem);
+ }
+
+ /*
+ * Next, destroy the access command associated with the class.
+ */
+ iclsPtr->flags |= ITCL_CLASS_NS_TEARDOWN;
+ if (iclsPtr->accessCmd) {
+ cmdPtr = iclsPtr->accessCmd;
+ iclsPtr->accessCmd = NULL;
+ Tcl_DeleteCommandFromToken(iclsPtr->interp, cmdPtr);
+ }
+
+ /*
+ * Release the namespace's claim on the class definition.
+ */
+ ItclReleaseClass(iclsPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclFreeClass()
+ *
+ * Frees all memory associated with a class definition. This is
+ * usually invoked automatically by Itcl_ReleaseData(), when class
+ * data is no longer being used.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclFreeClass(
+ char *cdata) /* class definition to be destroyed */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashSearch place;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclVariable *ivPtr;
+ ItclOption *ioptPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedOption *idoPtr;
+ ItclDelegatedFunction *idmPtr;
+ Itcl_ListElem *elem;
+ ItclVarLookup *vlookup;
+ ItclCmdLookup *clookupPtr;
+ Tcl_Var var;
+
+ iclsPtr = (ItclClass*)cdata;
+ if (iclsPtr->flags & ITCL_CLASS_IS_FREED) {
+ return;
+ }
+ ItclDeleteClassesDictInfo(iclsPtr->interp, iclsPtr);
+ iclsPtr->flags |= ITCL_CLASS_IS_FREED;
+
+ /*
+ * Tear down the list of derived classes. This list should
+ * really be empty if everything is working properly, but
+ * release it here just in case.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->derived);
+ while (elem) {
+ ItclReleaseClass( Itcl_GetListValue(elem) );
+ elem = Itcl_NextListElem(elem);
+ }
+ Itcl_DeleteList(&iclsPtr->derived);
+
+ /*
+ * Tear down the variable resolution table. Some records
+ * appear multiple times in the table (for x, foo::x, etc.)
+ * so each one has a reference count.
+ */
+/* Tcl_InitHashTable(&varTable, TCL_STRING_KEYS); */
+
+ FOREACH_HASH_VALUE(vlookup, &iclsPtr->resolveVars) {
+ if (--vlookup->usage == 0) {
+ /*
+ * If this is a common variable owned by this class,
+ * then release the class's hold on it. FIXME !!!
+ */
+ ckfree((char*)vlookup);
+ }
+ }
+
+ Tcl_DeleteHashTable(&iclsPtr->resolveVars);
+
+ /*
+ * Tear down the virtual method table...
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->resolveCmds, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ clookupPtr = Tcl_GetHashValue(hPtr);
+ ckfree((char *)clookupPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->resolveCmds);
+
+ /*
+ * Delete all option definitions.
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->options, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ ioptPtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ Itcl_ReleaseData(ioptPtr);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->options);
+
+ /*
+ * Delete all function definitions.
+ */
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ imPtr->iclsPtr = NULL;
+ ItclReleaseIMF(imPtr);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->functions);
+
+ /*
+ * Delete all delegated options.
+ */
+ FOREACH_HASH_VALUE(idoPtr, &iclsPtr->delegatedOptions) {
+ Itcl_ReleaseData(idoPtr);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->delegatedOptions);
+
+ /*
+ * Delete all delegated functions.
+ */
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (idmPtr->icPtr != NULL) {
+ if (idmPtr->icPtr->ivPtr->iclsPtr == iclsPtr) {
+ ItclDeleteDelegatedFunction(idmPtr);
+ }
+ }
+ }
+ Tcl_DeleteHashTable(&iclsPtr->delegatedFunctions);
+
+ /*
+ * Delete all components
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->components, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ icPtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ if (icPtr != NULL) {
+ ItclDeleteComponent(icPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&iclsPtr->components);
+
+ /*
+ * Delete all variable definitions.
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->variables, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ ivPtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ if (ivPtr != NULL) {
+ Itcl_ReleaseData(ivPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&iclsPtr->variables);
+
+ /*
+ * Release the claim on all base classes.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (elem) {
+ ItclReleaseClass( Itcl_GetListValue(elem) );
+ elem = Itcl_NextListElem(elem);
+ }
+ Itcl_DeleteList(&iclsPtr->bases);
+ Tcl_DeleteHashTable(&iclsPtr->heritage);
+
+ /* remove owerself from the all classes entry */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->nameClasses,
+ (char *)iclsPtr->fullNamePtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /* remove owerself from the all namespaceClasses entry */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->namespaceClasses,
+ (char *)iclsPtr->nsPtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /* remove owerself from the all classes entry */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->classes, (char *)iclsPtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /* FIXME !!!
+ free contextCache
+ free resolvePtr -- this is only needed for CallFrame Resolvers
+ -- not used at the moment
+ */
+
+ FOREACH_HASH_VALUE(var, &iclsPtr->classCommons) {
+ Itcl_ReleaseVar(var);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->classCommons);
+
+ /*
+ * Free up the widget class name
+ */
+ if (iclsPtr->widgetClassPtr != NULL) {
+ Tcl_DecrRefCount(iclsPtr->widgetClassPtr);
+ }
+
+ /*
+ * Free up the widget hulltype name
+ */
+ if (iclsPtr->hullTypePtr != NULL) {
+ Tcl_DecrRefCount(iclsPtr->hullTypePtr);
+ }
+
+ /*
+ * Free up the type typeconstrutor code
+ */
+
+ if (iclsPtr->typeConstructorPtr != NULL) {
+ Tcl_DecrRefCount(iclsPtr->typeConstructorPtr);
+ }
+
+ /*
+ * Free up the object initialization code.
+ */
+ if (iclsPtr->initCode) {
+ Tcl_DecrRefCount(iclsPtr->initCode);
+ }
+
+ Itcl_ReleaseData((ClientData)iclsPtr->infoPtr);
+
+ Tcl_DecrRefCount(iclsPtr->namePtr);
+ Tcl_DecrRefCount(iclsPtr->fullNamePtr);
+
+ if (iclsPtr->resolvePtr != NULL) {
+ ckfree((char *)iclsPtr->resolvePtr->clientData);
+ ckfree((char *)iclsPtr->resolvePtr);
+ }
+ ckfree((char*)iclsPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsClassNamespace()
+ *
+ * Checks to see whether or not the given namespace represents an
+ * [incr Tcl] class. Returns non-zero if so, and zero otherwise.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsClassNamespace(
+ Tcl_Namespace *nsPtr) /* namespace being tested */
+{
+ ItclClass *iclsPtr = ItclNamespace2Class(nsPtr);
+ return iclsPtr != NULL;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsClass()
+ *
+ * Checks the given Tcl command to see if it represents an itcl class.
+ * Returns non-zero if the command is associated with a class.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsClass(
+ Tcl_Command cmd) /* command being tested */
+{
+ Tcl_CmdInfo cmdInfo;
+
+ if (Tcl_GetCommandInfoFromToken(cmd, &cmdInfo) == 0) {
+ return 0;
+ }
+ if (cmdInfo.deleteProc == ItclDestroyClass) {
+ return 1;
+ }
+
+ /*
+ * This may be an imported command. Try to get the real
+ * command and see if it represents a class.
+ */
+ cmd = Tcl_GetOriginalCommand(cmd);
+ if (cmd != NULL) {
+ if (Tcl_GetCommandInfoFromToken(cmd, &cmdInfo) == 0) {
+ return 0;
+ }
+ if (cmdInfo.deleteProc == ItclDestroyClass) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindClass()
+ *
+ * Searches for the specified class in the active namespace. If the
+ * class is found, this procedure returns a pointer to the class
+ * definition. Otherwise, if the autoload flag is non-zero, an
+ * attempt will be made to autoload the class definition. If it
+ * still can't be found, this procedure returns NULL, along with an
+ * error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+ItclClass*
+Itcl_FindClass(
+ Tcl_Interp* interp, /* interpreter containing class */
+ const char* path, /* path name for class */
+ int autoload)
+{
+ /*
+ * Search for a namespace with the specified name, and if
+ * one is found, see if it is a class namespace.
+ */
+
+ Tcl_Namespace* classNs = Itcl_FindClassNamespace(interp, path);
+
+ if (classNs) {
+ ItclObjectInfo *infoPtr
+ = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses,
+ (char *) classNs);
+ if (hPtr) {
+ return (ItclClass *) Tcl_GetHashValue(hPtr);
+ }
+ }
+
+ /*
+ * If the autoload flag is set, try to autoload the class
+ * definition, then search again.
+ */
+ if (autoload) {
+ Tcl_DString buf;
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, "::auto_load ", -1);
+ Tcl_DStringAppend(&buf, path, -1);
+ if (Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0) != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while attempting to autoload class \"%s\")",
+ path));
+ Tcl_DStringFree(&buf);
+ return NULL;
+ }
+ Tcl_ResetResult(interp);
+ Tcl_DStringFree(&buf);
+
+ return Itcl_FindClass(interp, path, 0);
+ }
+
+ Tcl_AppendResult(interp, "class \"", path, "\" not found in context \"",
+ Tcl_GetCurrentNamespace(interp)->fullName, "\"",
+ (char*)NULL);
+
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindClassNamespace()
+ *
+ * Searches for the specified class namespace. The normal Tcl procedure
+ * Tcl_FindNamespace also searches for namespaces, but only in the
+ * current namespace context. This makes it hard to find one class
+ * from within another. For example, suppose. you have two namespaces
+ * Foo and Bar. If you're in the context of Foo and you look for
+ * Bar, you won't find it with Tcl_FindNamespace. This behavior is
+ * okay for namespaces, but wrong for classes.
+ *
+ * This procedure search for a class namespace. If the name is
+ * absolute (i.e., starts with "::"), then that one name is checked,
+ * and the class is either found or not. But if the name is relative,
+ * it is sought in the current namespace context and in the global
+ * context, just like the normal command lookup.
+ *
+ * This procedure returns a pointer to the desired namespace, or
+ * NULL if the namespace was not found.
+ * ------------------------------------------------------------------------
+ */
+Tcl_Namespace*
+Itcl_FindClassNamespace(interp, path)
+ Tcl_Interp* interp; /* interpreter containing class */
+ const char* path; /* path name for class */
+{
+ Tcl_Namespace* contextNs = Tcl_GetCurrentNamespace(interp);
+ Tcl_Namespace *classNs = Tcl_FindNamespace(interp, path, NULL, 0);
+
+ if ( !classNs /* We didn't find it... */
+ && contextNs->parentPtr != NULL /* context is not global */
+ && (*path != ':' || *(path+1) != ':') /* path not FQ */
+ ) {
+
+ if (strcmp(contextNs->name, path) == 0) {
+ classNs = contextNs;
+ } else {
+ classNs = Tcl_FindNamespace(interp, path, NULL, TCL_GLOBAL_ONLY);
+ }
+ }
+ return classNs;
+}
+
+
+static int
+FinalizeCreateObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Obj *objNamePtr = data[0];
+ ItclClass *iclsPtr = data[1];
+ if (result == TCL_OK) {
+ if (!(iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, Tcl_GetString(objNamePtr), NULL);
+ }
+ }
+ Tcl_DecrRefCount(objNamePtr);
+ return result;
+}
+
+static int
+CallCreateObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Obj *objNamePtr = data[0];
+ ItclClass *iclsPtr = data[1];
+ int objc = PTR2INT(data[2]);
+ Tcl_Obj **objv = data[3];
+
+ if (result == TCL_OK) {
+ result = ItclCreateObject(interp, Tcl_GetString(objNamePtr), iclsPtr,
+ objc, objv);
+ }
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_HandleClass()
+ *
+ * first argument is ::itcl::parser::handleClass
+ * Invoked by Tcl whenever the user issues the command associated with
+ * a class name. Handles the following syntax:
+ *
+ * <className>
+ * <className> <objName> ?<args>...?
+ *
+ * Without any arguments, the command does nothing. In the olden days,
+ * this allowed the class name to be invoked by itself to prompt the
+ * autoloader to load the class definition. Today, this behavior is
+ * retained for backward compatibility with old releases.
+ *
+ * If arguments are specified, then this procedure creates a new
+ * object named <objName> in the appropriate class. Note that if
+ * <objName> contains "#auto", that part is automatically replaced
+ * by a unique string built from the class name.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_HandleClass(
+ ClientData clientData, /* class definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ if (objc > 3) {
+ const char *token = Tcl_GetString(objv[3]);
+ const char *nsEnd = NULL;
+ const char *pos = token;
+ const char *tail = pos;
+ int fq = 0;
+ int code = TCL_OK;
+ Tcl_Obj *nsObj, *fqObj;
+
+ while ((pos = strstr(pos, "::"))) {
+ if (pos == token) {
+ fq = 1;
+ nsEnd = token;
+ } else if (pos[-1] != ':') {
+ nsEnd = pos - 1;
+ }
+ tail = pos + 2; pos++;
+ }
+
+ if (fq) {
+ nsObj = Tcl_NewStringObj(token, nsEnd-token);
+ } else {
+ Tcl_Namespace *nsPtr = Tcl_GetCurrentNamespace(interp);
+
+ nsObj = Tcl_NewStringObj(nsPtr->fullName, -1);
+ if (nsEnd) {
+ Tcl_AppendToObj(nsObj, "::", 2);
+ Tcl_AppendToObj(nsObj, token, nsEnd-token);
+ }
+ }
+
+ fqObj = Tcl_DuplicateObj(nsObj);
+ Tcl_AppendToObj(fqObj, "::", 2);
+ Tcl_AppendToObj(fqObj, tail, -1);
+
+ if (Tcl_GetCommandFromObj(interp, fqObj)) {
+ Tcl_AppendResult(interp, "command \"", tail,
+ "\" already exists in namespace \"", Tcl_GetString(nsObj),
+ "\"", NULL);
+ code = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(fqObj);
+ Tcl_DecrRefCount(nsObj);
+ if (code != TCL_OK) {
+ return code;
+ }
+ }
+ return ItclClassCreateObject(clientData, interp, objc, objv);
+}
+
+int
+ItclClassCreateObject(
+ ClientData clientData, /* IclObjectInfo */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_DString buffer; /* buffer used to build object names */
+ Tcl_Obj *objNamePtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj **newObjv;
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ void *callbackPtr;
+ char unique[256]; /* buffer used for unique part of object names */
+ char *token;
+ char *objName;
+ char tmp;
+ char *start;
+ char *pos;
+ const char *match;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ Tcl_ResetResult(interp);
+ ItclShowArgs(1, "ItclClassCreateObject", objc, objv);
+ /*
+ * If the command is invoked without an object name, then do nothing.
+ * This used to support autoloading--that the class name could be
+ * invoked as a command by itself, prompting the autoloader to
+ * load the class definition. We retain the behavior here for
+ * backward-compatibility with earlier releases.
+ */
+ if (objc <= 3) {
+ return TCL_OK;
+ }
+
+ hPtr = Tcl_FindHashEntry(&infoPtr->nameClasses, (char *)objv[2]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "no such class: \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * If the object name is "::", and if this is an old-style class
+ * definition, then treat the remaining arguments as a command
+ * in the class namespace. This used to be the way of invoking
+ * a class proc, but the new syntax is "class::proc" (without
+ * spaces).
+ */
+ token = Tcl_GetString(objv[3]);
+ if ((*token == ':') && (strcmp(token,"::") == 0) && (objc > 4)) {
+ /*
+ * If this is not an old-style class, then return an error
+ * describing the syntax change.
+ */
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "syntax \"class :: proc\" is an anachronism\n",
+ "[incr Tcl] no longer supports this syntax.\n",
+ "Instead, remove the spaces from your procedure invocations:\n",
+ " ",
+ Tcl_GetString(objv[1]), "::",
+ Tcl_GetString(objv[4]), " ?args?",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Otherwise, we have a proper object name. Create a new instance
+ * with that name. If the name contains "#auto", replace this with
+ * a uniquely generated string based on the class name.
+ */
+ Tcl_DStringInit(&buffer);
+ objName = NULL;
+
+ match = "#auto";
+ start = token;
+ for (pos=start; *pos != '\0'; pos++) {
+ if (*pos == *match) {
+ if (*(++match) == '\0') {
+ tmp = *start;
+ *start = '\0'; /* null-terminate first part */
+
+ /*
+ * Substitute a unique part in for "#auto", and keep
+ * incrementing a counter until a valid name is found.
+ */
+ do {
+ Tcl_CmdInfo dummy;
+
+ sprintf(unique,"%.200s%d", Tcl_GetString(iclsPtr->namePtr),
+ iclsPtr->unique++);
+ unique[0] = tolower(UCHAR(unique[0]));
+
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, token, -1);
+ Tcl_DStringAppend(&buffer, unique, -1);
+ Tcl_DStringAppend(&buffer, start+5, -1);
+
+ objName = Tcl_DStringValue(&buffer);
+
+ /*
+ * [Fix 227811] Check for any command with the
+ * given name, not only objects.
+ */
+
+ if (Tcl_GetCommandInfo (interp, objName, &dummy) == 0) {
+ break; /* if an error is found, bail out! */
+ }
+ } while (1);
+
+ *start = tmp; /* undo null-termination */
+ objName = Tcl_DStringValue(&buffer);
+ break; /* object name is ready to go! */
+ }
+ }
+ else {
+ match = "#auto";
+ pos = start++;
+ }
+ }
+
+ /*
+ * If "#auto" was not found, then just use object name as-is.
+ */
+ if (objName == NULL) {
+ objName = token;
+ }
+
+ /*
+ * Try to create a new object. If successful, return the
+ * object name as the result of this command.
+ */
+ objNamePtr = Tcl_NewStringObj(objName, -1);
+ Tcl_IncrRefCount(objNamePtr);
+ Tcl_DStringFree(&buffer);
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ newObjv = (Tcl_Obj **)(objv+4);
+ Tcl_NRAddCallback(interp, FinalizeCreateObject, objNamePtr, iclsPtr,
+ NULL, NULL);
+ Tcl_NRAddCallback(interp, CallCreateObject, objNamePtr, iclsPtr,
+ INT2PTR(objc-4), newObjv);
+ return Itcl_NRRunCallbacks(interp, callbackPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BuildVirtualTables()
+ *
+ * Invoked whenever the class heritage changes or members are added or
+ * removed from a class definition to rebuild the member lookup
+ * tables. There are two tables:
+ *
+ * METHODS: resolveCmds
+ * Used primarily in Itcl_ClassCmdResolver() to resolve all
+ * command references in a namespace.
+ *
+ * DATA MEMBERS: resolveVars
+ * Used primarily in Itcl_ClassVarResolver() to quickly resolve
+ * variable references in each class scope.
+ *
+ * These tables store every possible name for each command/variable
+ * (member, class::member, namesp::class::member, etc.). Members
+ * in a derived class may shadow members with the same name in a
+ * base class. In that case, the simple name in the resolution
+ * table will point to the most-specific member.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_BuildVirtualTables(
+ ItclClass* iclsPtr) /* class definition being updated */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch place;
+ Tcl_Namespace* nsPtr;
+ Tcl_DString buffer, buffer2;
+ Tcl_Obj *objPtr;
+ ItclVarLookup *vlookup;
+ ItclVariable *ivPtr;
+ ItclMemberFunc *imPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr2;
+ ItclCmdLookup *clookupPtr;
+#ifdef NEW_PROTO_RESOLVER
+ ItclClassVarInfo *icviPtr;
+ ItclClassCmdInfo *icciPtr;
+#endif
+ int newEntry;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringInit(&buffer2);
+
+ /*
+ * Clear the variable resolution table.
+ */
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->resolveVars, &place);
+ while (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ if (--vlookup->usage == 0) {
+ ckfree((char*)vlookup);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->resolveVars);
+ Tcl_InitHashTable(&iclsPtr->resolveVars, TCL_STRING_KEYS);
+ iclsPtr->numInstanceVars = 0;
+
+ /*
+ * Set aside the first object-specific slot for the built-in
+ * "this" variable. Only allocate one of these, even though
+ * there is a definition for "this" in each class scope.
+ * Set aside the second and third object-specific slot for the built-in
+ * "itcl_options" and "itcl_option_components" variable.
+ */
+ iclsPtr->numInstanceVars++;
+ iclsPtr->numInstanceVars++;
+ iclsPtr->numInstanceVars++;
+
+ /*
+ * Scan through all classes in the hierarchy, from most to
+ * least specific. Add a lookup entry for each variable
+ * into the table.
+ */
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->variables, &place);
+ while (hPtr) {
+#ifdef NEW_PROTO_RESOLVER
+ int type = VAR_TYPE_VARIABLE;
+#endif
+ ivPtr = (ItclVariable*)Tcl_GetHashValue(hPtr);
+
+ vlookup = (ItclVarLookup *)ckalloc(sizeof(ItclVarLookup));
+ vlookup->ivPtr = ivPtr;
+ vlookup->usage = 0;
+ vlookup->leastQualName = NULL;
+
+ /*
+ * If this variable is PRIVATE to another class scope,
+ * then mark it as "inaccessible".
+ */
+ vlookup->accessible = (ivPtr->protection != ITCL_PRIVATE ||
+ ivPtr->iclsPtr == iclsPtr);
+
+ if (ivPtr->flags & ITCL_COMMON) {
+#ifdef NEW_PROTO_RESOLVER
+ type = VAR_TYPE_COMMON;
+#endif
+ }
+ /*
+ * If this is a reference to the built-in "this"
+ * variable, then its index is "0". Otherwise,
+ * add another slot to the end of the table.
+ */
+ if ((ivPtr->flags & ITCL_THIS_VAR) != 0) {
+ vlookup->varNum = 0;
+ } else {
+ if ((ivPtr->flags & ITCL_OPTIONS_VAR) != 0) {
+ vlookup->varNum = 1;
+ } else {
+ vlookup->varNum = iclsPtr->numInstanceVars++;
+ }
+ }
+#ifdef NEW_PROTO_RESOLVER
+ icviPtr = (ItclClassVarInfo *)ckalloc(
+ sizeof(ItclClassVarInfo));
+ icviPtr->type = type;
+ icviPtr->protection = ivPtr->protection;
+ icviPtr->nsPtr = iclsPtr->nsPtr;
+ icviPtr->declaringNsPtr = iclsPtr2->nsPtr;
+ icviPtr->varNum = vlookup->varNum;
+ ClientData clientData2;
+ clientData2 = Itcl_RegisterClassVariable(
+ iclsPtr->infoPtr->interp, iclsPtr2->nsPtr,
+ Tcl_GetString(ivPtr->namePtr), icviPtr);
+ vlookup->classVarInfoPtr = clientData2;
+#endif
+/* FIXME !!! should use for var lookup !! */
+
+ /*
+ * Create all possible names for this variable and enter
+ * them into the variable resolution table:
+ * var
+ * class::var
+ * namesp1::class::var
+ * namesp2::namesp1::class::var
+ * ...
+ */
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(ivPtr->namePtr), -1);
+ nsPtr = iclsPtr2->nsPtr;
+
+ while (1) {
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->resolveVars,
+ Tcl_DStringValue(&buffer), &newEntry);
+
+ if (newEntry) {
+ Tcl_SetHashValue(hPtr, (ClientData)vlookup);
+ vlookup->usage++;
+
+ if (!vlookup->leastQualName) {
+ vlookup->leastQualName =
+ Tcl_GetHashKey(&iclsPtr->resolveVars, hPtr);
+ }
+#ifdef NEW_PROTO_RESOLVER
+ Itcl_RegisterClassVariable(iclsPtr->infoPtr->interp,
+ iclsPtr->nsPtr, Tcl_DStringValue(&buffer),
+ vlookup->classVarInfoPtr);
+#endif
+ }
+
+ if (nsPtr == NULL) {
+ break;
+ }
+ Tcl_DStringSetLength(&buffer2, 0);
+ Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer), -1);
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, nsPtr->name, -1);
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, Tcl_DStringValue(&buffer2), -1);
+
+ nsPtr = nsPtr->parentPtr;
+ }
+
+ /*
+ * If this record is not needed, free it now.
+ */
+ if (vlookup->usage == 0) {
+ ckfree((char*)vlookup);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ /*
+ * Clear the command resolution table.
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->resolveCmds, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ clookupPtr = Tcl_GetHashValue(hPtr);
+ ckfree((char *)clookupPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_DeleteHashTable(&iclsPtr->resolveCmds);
+ Tcl_InitObjHashTable(&iclsPtr->resolveCmds);
+
+ /*
+ * Scan through all classes in the hierarchy, from most to
+ * least specific. Look for the first (most-specific) definition
+ * of each member function, and enter it into the table.
+ */
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->functions, &place);
+ while (hPtr) {
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(hPtr);
+
+ /*
+ * Create all possible names for this function and enter
+ * them into the command resolution table:
+ * func
+ * class::func
+ * namesp1::class::func
+ * namesp2::namesp1::class::func
+ * ...
+ */
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(imPtr->namePtr), -1);
+ nsPtr = iclsPtr2->nsPtr;
+
+ while (1) {
+ objPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->resolveCmds,
+ (char *)objPtr, &newEntry);
+
+ if (newEntry) {
+ clookupPtr = (ItclCmdLookup *)ckalloc(sizeof(ItclCmdLookup));
+ memset(clookupPtr, 0, sizeof(ItclCmdLookup));
+ clookupPtr->imPtr = imPtr;
+ Tcl_SetHashValue(hPtr, (ClientData)clookupPtr);
+#ifdef NEW_PROTO_RESOLVER
+ int type = CMD_TYPE_METHOD;
+ if (imPtr->flags & ITCL_COMMON) {
+ type = CMD_TYPE_PROC;
+ }
+ icciPtr = (ItclClassCmdInfo *)ckalloc(
+ sizeof(ItclClassCmdInfo));
+ icciPtr->type = type;
+ icciPtr->protection = imPtr->protection;
+ icciPtr->nsPtr = iclsPtr->nsPtr;
+ icciPtr->declaringNsPtr = iclsPtr2->nsPtr;
+ ClientData clientData2;
+ clientData2 = Itcl_RegisterClassCommand(
+ iclsPtr->infoPtr->interp, iclsPtr->nsPtr,
+ Tcl_GetString(imPtr->namePtr), icciPtr);
+ clookupPtr->classCmdInfoPtr = clientData2;
+ clookupPtr->cmdPtr = imPtr->accessCmd;
+#endif
+ } else {
+ Tcl_DecrRefCount(objPtr);
+ }
+
+ if (nsPtr == NULL) {
+ break;
+ }
+ Tcl_DStringSetLength(&buffer2, 0);
+ Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer), -1);
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, nsPtr->name, -1);
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, Tcl_DStringValue(&buffer2), -1);
+
+ nsPtr = nsPtr->parentPtr;
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ /*
+ * Scan through all classes in the hierarchy, from most to
+ * least specific. Look for the first (most-specific) definition
+ * of each delegated member function, and enter it into the table.
+ */
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->delegatedFunctions, &place);
+ while (hPtr) {
+ idmPtr = (ItclDelegatedFunction *)Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)idmPtr->namePtr);
+ if (hPtr == NULL) {
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)idmPtr->namePtr, &newEntry);
+ Tcl_SetHashValue(hPtr, idmPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_DStringFree(&buffer);
+ Tcl_DStringFree(&buffer2);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateVariable()
+ *
+ * Creates a new class variable definition. If this is a public
+ * variable, it may have a bit of "config" code that is used to
+ * update the object whenever the variable is modified via the
+ * built-in "configure" method.
+ *
+ * Returns TCL_ERROR along with an error message in the specified
+ * interpreter if anything goes wrong. Otherwise, this returns
+ * TCL_OK and a pointer to the new variable definition in "ivPtr".
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateVariable(
+ Tcl_Interp *interp, /* interpreter managing this transaction */
+ ItclClass* iclsPtr, /* class containing this variable */
+ Tcl_Obj* namePtr, /* variable name */
+ char* init, /* initial value */
+ char* config, /* code invoked when variable is configured */
+ ItclVariable** ivPtrPtr) /* returns: new variable definition */
+{
+ int newEntry;
+ ItclVariable *ivPtr;
+ ItclMemberCode *mCodePtr;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Add this variable to the variable table for the class.
+ * Make sure that the variable name does not already exist.
+ */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->variables, (char *)namePtr, &newEntry);
+ if (!newEntry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "variable name \"", Tcl_GetString(namePtr),
+ "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this variable has some "config" code, try to capture
+ * its implementation.
+ */
+ if (config) {
+ if (Itcl_CreateMemberCode(interp, iclsPtr, (char*)NULL, config,
+ &mCodePtr) != TCL_OK) {
+ Tcl_DeleteHashEntry(hPtr);
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)mCodePtr);
+ Itcl_EventuallyFree((ClientData)mCodePtr, Itcl_DeleteMemberCode);
+ } else {
+ mCodePtr = NULL;
+ }
+
+
+ /*
+ * If everything looks good, create the variable definition.
+ */
+ ivPtr = (ItclVariable*)ckalloc(sizeof(ItclVariable));
+ memset(ivPtr, 0, sizeof(ItclVariable));
+ ivPtr->iclsPtr = iclsPtr;
+ ivPtr->infoPtr = iclsPtr->infoPtr;
+ ivPtr->protection = Itcl_Protection(interp, 0);
+ ivPtr->codePtr = mCodePtr;
+ ivPtr->namePtr = namePtr;
+ Tcl_IncrRefCount(ivPtr->namePtr);
+ ivPtr->fullNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_AppendToObj(ivPtr->fullNamePtr, "::", 2);
+ Tcl_AppendToObj(ivPtr->fullNamePtr, Tcl_GetString(namePtr), -1);
+ Tcl_IncrRefCount(ivPtr->fullNamePtr);
+
+ if (ivPtr->protection == ITCL_DEFAULT_PROTECT) {
+ ivPtr->protection = ITCL_PROTECTED;
+ }
+
+ if (init != NULL) {
+ ivPtr->init = Tcl_NewStringObj(init, -1);
+ Tcl_IncrRefCount(ivPtr->init);
+ } else {
+ ivPtr->init = NULL;
+ }
+
+ Tcl_SetHashValue(hPtr, (ClientData)ivPtr);
+ Itcl_PreserveData((ClientData)ivPtr);
+ Itcl_EventuallyFree((ClientData)ivPtr, Itcl_DeleteVariable);
+
+ *ivPtrPtr = ivPtr;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateOption()
+ *
+ * Creates a new class option definition. If this is a public
+ * option, it may have a bit of "config" code that is used to
+ * update the object whenever the option is modified via the
+ * built-in "configure" method.
+ *
+ * Returns TCL_ERROR along with an error message in the specified
+ * interpreter if anything goes wrong. Otherwise, this returns
+ * TCL_OK and a pointer to the new option definition in "ioptPtr".
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateOption(
+ Tcl_Interp *interp, /* interpreter managing this transaction */
+ ItclClass* iclsPtr, /* class containing this variable */
+ ItclOption* ioptPtr) /* new option definition */
+{
+ int newEntry;
+ ItclMemberCode *mCodePtr;
+ Tcl_HashEntry *hPtr;
+
+ mCodePtr = NULL;
+ /*
+ * Add this option to the options table for the class.
+ * Make sure that the option name does not already exist.
+ */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->options,
+ (char *)ioptPtr->namePtr, &newEntry);
+ if (!newEntry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "option name \"", Tcl_GetString(ioptPtr->namePtr),
+ "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ iclsPtr->numOptions++;
+ ioptPtr->iclsPtr = iclsPtr;
+ ioptPtr->codePtr = mCodePtr;
+ ioptPtr->fullNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_AppendToObj(ioptPtr->fullNamePtr, "::", 2);
+ Tcl_AppendToObj(ioptPtr->fullNamePtr, Tcl_GetString(ioptPtr->namePtr), -1);
+ Tcl_IncrRefCount(ioptPtr->fullNamePtr);
+ Tcl_SetHashValue(hPtr, (ClientData)ioptPtr);
+ Itcl_PreserveData((ClientData)ioptPtr);
+ Itcl_EventuallyFree((ClientData)ioptPtr, ItclDeleteOption);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateMethodVariable()
+ *
+ * Creates a new class methdovariable definition. If this is a public
+ * methodvariable,
+ *
+ * Returns TCL_ERROR along with an error message in the specified
+ * interpreter if anything goes wrong. Otherwise, this returns
+ * TCL_OK and a pointer to the new option definition in "imvPtr".
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateMethodVariable(
+ Tcl_Interp *interp, /* interpreter managing this transaction */
+ ItclClass* iclsPtr, /* class containing this variable */
+ Tcl_Obj* namePtr, /* variable name */
+ Tcl_Obj* defaultPtr, /* initial value */
+ Tcl_Obj* callbackPtr, /* code invoked when variable is set */
+ ItclMethodVariable** imvPtrPtr)
+ /* returns: new methdovariable definition */
+{
+ int isNew;
+ ItclMethodVariable *imvPtr;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Add this methodvariable to the options table for the class.
+ * Make sure that the methodvariable name does not already exist.
+ */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->methodVariables,
+ (char *)namePtr, &isNew);
+ if (!isNew) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "methdovariable name \"", Tcl_GetString(namePtr),
+ "\" already defined in class \"",
+ Tcl_GetString (iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ Tcl_IncrRefCount(namePtr);
+
+ /*
+ * If everything looks good, create the option definition.
+ */
+ imvPtr = (ItclMethodVariable*)ckalloc(sizeof(ItclMethodVariable));
+ memset(imvPtr, 0, sizeof(ItclMethodVariable));
+ imvPtr->iclsPtr = iclsPtr;
+ imvPtr->protection = Itcl_Protection(interp, 0);
+ imvPtr->namePtr = namePtr;
+ Tcl_IncrRefCount(imvPtr->namePtr);
+ imvPtr->fullNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_AppendToObj(imvPtr->fullNamePtr, "::", 2);
+ Tcl_AppendToObj(imvPtr->fullNamePtr, Tcl_GetString(namePtr), -1);
+ Tcl_IncrRefCount(imvPtr->fullNamePtr);
+ imvPtr->defaultValuePtr = defaultPtr;
+ if (defaultPtr != NULL) {
+ Tcl_IncrRefCount(imvPtr->defaultValuePtr);
+ }
+ imvPtr->callbackPtr = callbackPtr;
+ if (callbackPtr != NULL) {
+ Tcl_IncrRefCount(imvPtr->callbackPtr);
+ }
+
+ if (imvPtr->protection == ITCL_DEFAULT_PROTECT) {
+ imvPtr->protection = ITCL_PROTECTED;
+ }
+
+ Tcl_SetHashValue(hPtr, (ClientData)imvPtr);
+
+ *imvPtrPtr = imvPtr;
+ return TCL_OK;
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetCommonVar()
+ *
+ * Returns the current value for a common class variable. The member
+ * name is interpreted with respect to the given class scope. That
+ * scope is installed as the current context before querying the
+ * variable. This by-passes the protection level in case the variable
+ * is "private".
+ *
+ * If successful, this procedure returns a pointer to a string value
+ * which remains alive until the variable changes it value. If
+ * anything goes wrong, this returns NULL.
+ * ------------------------------------------------------------------------
+ */
+const char*
+Itcl_GetCommonVar(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name, /* name of desired instance variable */
+ ItclClass *contextIclsPtr) /* name is interpreted in this scope */
+{
+ const char *val = NULL;
+ Tcl_HashEntry *hPtr;
+ Tcl_DString buffer;
+ Tcl_Obj *namePtr;
+ ItclVariable *ivPtr;
+ const char *cp;
+ const char *lastCp;
+ Tcl_Object oPtr = NULL;
+
+ lastCp = name;
+ cp = name;
+ while (cp != NULL) {
+ cp = strstr(lastCp, "::");
+ if (cp != NULL) {
+ lastCp = cp + 2;
+ }
+ }
+ namePtr = Tcl_NewStringObj(lastCp, -1);
+ Tcl_IncrRefCount(namePtr);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->variables, (char *)namePtr);
+ Tcl_DecrRefCount(namePtr);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ ivPtr = Tcl_GetHashValue(hPtr);
+ /*
+ * Activate the namespace for the given class. That installs
+ * the appropriate name resolution rules and by-passes any
+ * security restrictions.
+ */
+
+ if (lastCp == name) {
+ /* 'name' is a simple name (this is untested!!!!) */
+
+ /* Use the context class passed in */
+ oPtr = contextIclsPtr->oPtr;
+
+ } else {
+ int code = TCL_ERROR;
+ Tcl_Obj *classObjPtr = Tcl_NewStringObj(name, lastCp - name - 2);
+ oPtr = Tcl_GetObjectFromObj(interp, classObjPtr);
+
+ if (oPtr) {
+ ItclClass *iclsPtr = Tcl_ObjectGetMetadata(oPtr,
+ contextIclsPtr->infoPtr->class_meta_type);
+ if (iclsPtr) {
+
+ code = TCL_OK;
+ assert(oPtr == iclsPtr->oPtr);
+
+ /*
+ * If the caller gave us a qualified name into
+ * somewhere other than the context class, then
+ * things are really weird. Consider an assertion
+ * to prevent, but for now keep the functioning
+ * unchanged.
+ *
+ * assert(iclsPtr == contextIclsPtr);
+ */
+
+ }
+
+ }
+ Tcl_DecrRefCount(classObjPtr);
+ if (code != TCL_OK) {
+ return NULL;
+ }
+
+ }
+
+ Tcl_DStringInit(&buffer);
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ }
+ Tcl_DStringAppend(&buffer, (Tcl_GetObjectNamespace(oPtr))->fullName, -1);
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, lastCp, -1);
+
+ val = Tcl_GetVar2(interp, (const char *)Tcl_DStringValue(&buffer),
+ (char*)NULL, 0);
+ Tcl_DStringFree(&buffer);
+ return val;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InitHierIter()
+ *
+ * Initializes an iterator for traversing the hierarchy of the given
+ * class. Subsequent calls to Itcl_AdvanceHierIter() will return
+ * the base classes in order from most-to-least specific.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_InitHierIter(iter,iclsPtr)
+ ItclHierIter *iter; /* iterator used for traversal */
+ ItclClass *iclsPtr; /* class definition for start of traversal */
+{
+ Itcl_InitStack(&iter->stack);
+ Itcl_PushStack((ClientData)iclsPtr, &iter->stack);
+ iter->current = iclsPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteHierIter()
+ *
+ * Destroys an iterator for traversing class hierarchies, freeing
+ * all memory associated with it.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DeleteHierIter(iter)
+ ItclHierIter *iter; /* iterator used for traversal */
+{
+ Itcl_DeleteStack(&iter->stack);
+ iter->current = NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AdvanceHierIter()
+ *
+ * Moves a class hierarchy iterator forward to the next base class.
+ * Returns a pointer to the current class definition, or NULL when
+ * the end of the hierarchy has been reached.
+ * ------------------------------------------------------------------------
+ */
+ItclClass*
+Itcl_AdvanceHierIter(
+ ItclHierIter *iter) /* iterator used for traversal */
+{
+ register Itcl_ListElem *elem;
+ ItclClass *iclsPtr;
+
+ iter->current = (ItclClass*)Itcl_PopStack(&iter->stack);
+
+ /*
+ * Push classes onto the stack in reverse order, so that
+ * they will be popped off in the proper order.
+ */
+ if (iter->current) {
+ iclsPtr = (ItclClass*)iter->current;
+ elem = Itcl_LastListElem(&iclsPtr->bases);
+ while (elem) {
+ Itcl_PushStack(Itcl_GetListValue(elem), &iter->stack);
+ elem = Itcl_PrevListElem(elem);
+ }
+ }
+ return iter->current;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteVariable()
+ *
+ * Destroys a variable definition created by Itcl_CreateVariable(),
+ * freeing all resources associated with it.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DeleteVariable(
+ char *cdata) /* variable definition to be destroyed */
+{
+ Tcl_HashEntry *hPtr;
+ ItclVariable *ivPtr;
+
+ ivPtr = (ItclVariable *)cdata;
+if (ivPtr->arrayInitPtr != NULL) {
+}
+ hPtr = Tcl_FindHashEntry(&ivPtr->infoPtr->classes, (char *)ivPtr->iclsPtr);
+ if (hPtr != NULL) {
+ /* unlink owerself from list of class variables */
+ hPtr = Tcl_FindHashEntry(&ivPtr->iclsPtr->variables,
+ (char *)ivPtr->namePtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ if (ivPtr->codePtr != NULL) {
+ Itcl_ReleaseData(ivPtr->codePtr);
+ }
+ Tcl_DecrRefCount(ivPtr->namePtr);
+ Tcl_DecrRefCount(ivPtr->fullNamePtr);
+ if (ivPtr->init) {
+ Tcl_DecrRefCount(ivPtr->init);
+ }
+ if (ivPtr->arrayInitPtr) {
+ Tcl_DecrRefCount(ivPtr->arrayInitPtr);
+ }
+ ckfree((char*)ivPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteOption()
+ *
+ * Destroys a option definition created by Itcl_CreateOption(),
+ * freeing all resources associated with it.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDeleteOption(
+ char *cdata) /* option definition to be destroyed */
+{
+ ItclOption *ioptPtr;
+
+ ioptPtr = (ItclOption *)cdata;
+ Tcl_DecrRefCount(ioptPtr->namePtr);
+ Tcl_DecrRefCount(ioptPtr->fullNamePtr);
+ if (ioptPtr->resourceNamePtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->resourceNamePtr);
+ }
+ if (ioptPtr->resourceNamePtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->classNamePtr);
+ }
+
+ Itcl_ReleaseData(ioptPtr->codePtr);
+ if (ioptPtr->defaultValuePtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->defaultValuePtr);
+ }
+ if (ioptPtr->cgetMethodPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->cgetMethodPtr);
+ }
+ if (ioptPtr->cgetMethodVarPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->cgetMethodVarPtr);
+ }
+ if (ioptPtr->configureMethodPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->configureMethodPtr);
+ }
+ if (ioptPtr->configureMethodVarPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->configureMethodVarPtr);
+ }
+ if (ioptPtr->validateMethodPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->validateMethodPtr);
+ }
+ if (ioptPtr->validateMethodVarPtr != NULL) {
+ Tcl_DecrRefCount(ioptPtr->validateMethodVarPtr);
+ }
+ Itcl_ReleaseData(ioptPtr->idoPtr);
+ ckfree((char*)ioptPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteFunction()
+ *
+ * fre data associated with a function
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDeleteFunction(
+ ItclMemberFunc *imPtr)
+{
+ Tcl_HashEntry *hPtr;
+
+if (imPtr->iclsPtr) {
+ hPtr = Tcl_FindHashEntry(&imPtr->iclsPtr->infoPtr->procMethods,
+ (char *) imPtr->tmPtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+}
+ hPtr = Tcl_FindHashEntry(&imPtr->infoPtr->classes, (char *)imPtr->iclsPtr);
+ if (hPtr != NULL) {
+ /* unlink owerself from list of class functions */
+ hPtr = Tcl_FindHashEntry(&imPtr->iclsPtr->functions,
+ (char *)imPtr->namePtr);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ if (imPtr->codePtr != NULL) {
+ Itcl_ReleaseData(imPtr->codePtr);
+ }
+ Tcl_DecrRefCount(imPtr->namePtr);
+ Tcl_DecrRefCount(imPtr->fullNamePtr);
+ if (imPtr->usagePtr != NULL) {
+ Tcl_DecrRefCount(imPtr->usagePtr);
+ }
+ if (imPtr->argumentPtr != NULL) {
+ Tcl_DecrRefCount(imPtr->argumentPtr);
+ }
+ if (imPtr->origArgsPtr != NULL) {
+ Tcl_DecrRefCount(imPtr->origArgsPtr);
+ }
+ if (imPtr->builtinArgumentPtr != NULL) {
+ Tcl_DecrRefCount(imPtr->builtinArgumentPtr);
+ }
+ if (imPtr->bodyPtr != NULL) {
+ Tcl_DecrRefCount(imPtr->bodyPtr);
+ }
+ if (imPtr->argListPtr != NULL) {
+ ItclDeleteArgList(imPtr->argListPtr);
+ }
+ ckfree((char*)imPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteComponent()
+ *
+ * free data associated with a component
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDeleteComponent(
+ ItclComponent *icPtr)
+{
+ Tcl_Obj *objPtr;
+ FOREACH_HASH_DECLS;
+
+ Tcl_DecrRefCount(icPtr->namePtr);
+ /* the variable and the command are freed when freeing variables,
+ * functions */
+ FOREACH_HASH_VALUE(objPtr, &icPtr->keptOptions) {
+ if (objPtr != NULL) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&icPtr->keptOptions);
+ ckfree((char*)icPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteDelegatedOption()
+ *
+ * free data associated with a delegated option
+ * ------------------------------------------------------------------------
+ */
+void
+ItclDeleteDelegatedOption(
+ char *cdata)
+{
+ Tcl_Obj *objPtr;
+ FOREACH_HASH_DECLS;
+ ItclDelegatedOption *idoPtr;
+
+ idoPtr = (ItclDelegatedOption *)cdata;
+ Tcl_DecrRefCount(idoPtr->namePtr);
+ if (idoPtr->resourceNamePtr != NULL) {
+ Tcl_DecrRefCount(idoPtr->resourceNamePtr);
+ }
+ if (idoPtr->classNamePtr != NULL) {
+ Tcl_DecrRefCount(idoPtr->classNamePtr);
+ }
+ if (idoPtr->asPtr != NULL) {
+ Tcl_DecrRefCount(idoPtr->asPtr);
+ }
+ FOREACH_HASH_VALUE(objPtr, &idoPtr->exceptions) {
+ if (objPtr != NULL) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&idoPtr->exceptions);
+ ckfree((char *)idoPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteDelegatedFunction()
+ *
+ * free data associated with a delegated function
+ * ------------------------------------------------------------------------
+ */
+void ItclDeleteDelegatedFunction(
+ ItclDelegatedFunction *idmPtr)
+{
+ Tcl_Obj *objPtr;
+ FOREACH_HASH_DECLS;
+
+ Tcl_DecrRefCount(idmPtr->namePtr);
+ if (idmPtr->asPtr != NULL) {
+ Tcl_DecrRefCount(idmPtr->asPtr);
+ }
+ if (idmPtr->usingPtr != NULL) {
+ Tcl_DecrRefCount(idmPtr->usingPtr);
+ }
+ FOREACH_HASH_VALUE(objPtr, &idmPtr->exceptions) {
+ if (objPtr != NULL) {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
+ Tcl_DeleteHashTable(&idmPtr->exceptions);
+ ckfree((char *)idmPtr);
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclCmd.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclCmd.c
new file mode 100644
index 0000000..1111953
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclCmd.c
@@ -0,0 +1,2182 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This file defines information that tracks classes and objects
+ * at a global level for a given interpreter.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "tclInt.h"
+#include "itclInt.h"
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ThisCmd()
+ *
+ * Invoked by Tcl for fast access to itcl methods
+ * syntax:
+ *
+ * this methodName args ....
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+NRThisCmd(
+ ClientData clientData, /* class info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ClientData clientData2;
+ Tcl_Object oPtr;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(1, "NRThisCmd", objc, objv);
+ iclsPtr = clientData;
+ clientData2 = Itcl_GetCallFrameClientData(interp);
+ oPtr = Tcl_ObjectContextObject(clientData2);
+ return Itcl_PublicObjectCmd(oPtr, interp, iclsPtr->clsPtr, objc, objv);
+}
+/* ARGSUSED */
+int
+Itcl_ThisCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ FOREACH_HASH_DECLS;
+ ClientData clientData2;
+ Tcl_Object oPtr;
+ Tcl_Obj **newObjv;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *funcName;
+ const char *val;
+ int result;
+
+ if (objc == 1) {
+ return Itcl_SelfCmd(clientData,interp, objc, objv);
+ }
+ ItclShowArgs(1, "Itcl_ThisCmd", objc, objv);
+ iclsPtr = clientData;
+ clientData2 = Itcl_GetCallFrameClientData(interp);
+ if (clientData2 == NULL) {
+ Tcl_AppendResult(interp,
+ "this cannot be invoked without an object context", NULL);
+ return TCL_ERROR;
+ }
+ oPtr = Tcl_ObjectContextObject(clientData2);
+ if (oPtr == NULL) {
+ Tcl_AppendResult(interp,
+ "this cannot be invoked without an object context", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 1) {
+ Tcl_Obj *namePtr = Tcl_NewObj();
+
+ Tcl_GetCommandFullName(interp, Tcl_GetObjectCommand(oPtr), namePtr);
+ Tcl_SetObjResult(interp, namePtr);
+ return TCL_OK;
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objv[1]);
+ funcName = Tcl_GetString(objv[1]);
+ if (!(iclsPtr->flags & ITCL_CLASS)) {
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), funcName) == 0) {
+ if (idmPtr->icPtr == NULL) {
+ if (idmPtr->usingPtr != NULL) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * objc);
+ newObjv[0] = idmPtr->usingPtr;
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv+1, objv+2, sizeof(Tcl_Obj *) *
+ (objc - 2));
+ItclShowArgs(1, "EVAL2", objc - 1, newObjv);
+ result = Tcl_EvalObjv(interp, objc - 1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ } else {
+ Tcl_AppendResult(interp,
+ "delegate has not yet been implemented in",
+ ": \"this\" method/command!", NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) *
+ (objc + 1));
+ newObjv[0] = Tcl_NewStringObj("this", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ val = Tcl_GetVar2(interp,
+ Tcl_GetString(idmPtr->icPtr->namePtr), NULL, 0);
+ newObjv[1] = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ memcpy(newObjv+2, objv+1, sizeof(Tcl_Obj *) * (objc -1));
+ItclShowArgs(1, "EVAL2", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ }
+ return result;
+ }
+ }
+ }
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "class \"", iclsPtr->nsPtr->fullName,
+ "\" has no method: \"", Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ return Tcl_NRCallObjProc(interp, NRThisCmd, clientData, objc, objv);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindClassesCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::find classes"
+ * command to query the list of known classes. Handles the following
+ * syntax:
+ *
+ * find classes ?<pattern>?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_FindClassesCmd(
+ ClientData clientData, /* class/object info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *activeNs = Tcl_GetCurrentNamespace(interp);
+ Tcl_Namespace *globalNs = Tcl_GetGlobalNamespace(interp);
+ Tcl_HashTable unique;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashSearch place;
+ Tcl_Command cmd;
+ Tcl_Command originalCmd;
+ Tcl_Namespace *nsPtr;
+ Tcl_Obj *objPtr;
+ Itcl_Stack search;
+ char *pattern;
+ const char *cmdName;
+ int newEntry;
+ int handledActiveNs;
+ int forceFullNames = 0;
+
+ ItclShowArgs(2, "Itcl_FindClassesCmd", objc, objv);
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?pattern?");
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ forceFullNames = (strstr(pattern, "::") != NULL);
+ } else {
+ pattern = NULL;
+ }
+
+ /*
+ * Search through all commands in the current namespace first,
+ * in the global namespace next, then in all child namespaces
+ * in this interpreter. If we find any commands that
+ * represent classes, report them.
+ */
+
+ Itcl_InitStack(&search);
+ Itcl_PushStack((ClientData)globalNs, &search);
+ Itcl_PushStack((ClientData)activeNs, &search); /* last in, first out! */
+
+ Tcl_InitHashTable(&unique, TCL_ONE_WORD_KEYS);
+
+ handledActiveNs = 0;
+ while (Itcl_GetStackSize(&search) > 0) {
+ nsPtr = Itcl_PopStack(&search);
+ if (nsPtr == activeNs && handledActiveNs) {
+ continue;
+ }
+
+ hPtr = Tcl_FirstHashEntry(Itcl_GetNamespaceCommandTable(nsPtr),
+ &place);
+ while (hPtr) {
+ cmd = (Tcl_Command)Tcl_GetHashValue(hPtr);
+ if (Itcl_IsClass(cmd)) {
+ originalCmd = Tcl_GetOriginalCommand(cmd);
+
+ /*
+ * Report full names if:
+ * - the pattern has namespace qualifiers
+ * - the class namespace is not in the current namespace
+ * - the class's object creation command is imported from
+ * another namespace.
+ *
+ * Otherwise, report short names.
+ */
+ if (forceFullNames || nsPtr != activeNs ||
+ originalCmd != NULL) {
+
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(interp, cmd, objPtr);
+ cmdName = Tcl_GetString(objPtr);
+ } else {
+ cmdName = Tcl_GetCommandName(interp, cmd);
+ objPtr = Tcl_NewStringObj((const char *)cmdName, -1);
+ }
+
+ if (originalCmd) {
+ cmd = originalCmd;
+ }
+ Tcl_CreateHashEntry(&unique, (char*)cmd, &newEntry);
+
+ if (newEntry &&
+ ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)cmdName, pattern))) {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ Tcl_GetObjResult(interp), objPtr);
+ } else {
+ /* if not appended to the result, free objPtr. */
+ Tcl_DecrRefCount(objPtr);
+ }
+
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ handledActiveNs = 1; /* don't process the active namespace twice */
+
+ /*
+ * Push any child namespaces onto the stack and continue
+ * the search in those namespaces.
+ */
+ hPtr = Tcl_FirstHashEntry(Itcl_GetNamespaceChildTable(nsPtr), &place);
+ while (hPtr != NULL) {
+ Itcl_PushStack(Tcl_GetHashValue(hPtr), &search);
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Tcl_DeleteHashTable(&unique);
+ Itcl_DeleteStack(&search);
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindObjectsCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::find objects"
+ * command to query the list of known objects. Handles the following
+ * syntax:
+ *
+ * find objects ?-class <className>? ?-isa <className>? ?<pattern>?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_FindObjectsCmd(
+ ClientData clientData, /* class/object info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *activeNs = Tcl_GetCurrentNamespace(interp);
+ Tcl_Namespace *globalNs = Tcl_GetGlobalNamespace(interp);
+ int forceFullNames = 0;
+
+ char *pattern = NULL;
+ ItclClass *iclsPtr = NULL;
+ ItclClass *isaDefn = NULL;
+
+ char *name = NULL;
+ char *token = NULL;
+ const char *cmdName = NULL;
+ int pos;
+ int newEntry;
+ int match;
+ int handledActiveNs;
+ ItclObject *contextIoPtr;
+ Tcl_HashTable unique;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ Itcl_Stack search;
+ Tcl_Command cmd;
+ Tcl_Command originalCmd;
+ Tcl_CmdInfo cmdInfo;
+ Tcl_Namespace *nsPtr;
+ Tcl_Obj *objPtr;
+
+ /*
+ * Parse arguments:
+ * objects ?-class <className>? ?-isa <className>? ?<pattern>?
+ */
+ pos = 0;
+ while (++pos < objc) {
+ token = Tcl_GetString(objv[pos]);
+ if (*token != '-') {
+ if (!pattern) {
+ pattern = token;
+ forceFullNames = (strstr(pattern, "::") != NULL);
+ } else {
+ break;
+ }
+ }
+ else if ((pos+1 < objc) && (strcmp(token,"-class") == 0)) {
+ name = Tcl_GetString(objv[pos+1]);
+ iclsPtr = Itcl_FindClass(interp, name, /* autoload */ 1);
+ if (iclsPtr == NULL) {
+ return TCL_ERROR;
+ }
+ pos++;
+ }
+ else if ((pos+1 < objc) && (strcmp(token,"-isa") == 0)) {
+ name = Tcl_GetString(objv[pos+1]);
+ isaDefn = Itcl_FindClass(interp, name, /* autoload */ 1);
+ if (isaDefn == NULL) {
+ return TCL_ERROR;
+ }
+ pos++;
+ } else {
+
+ /*
+ * Last token? Take it as the pattern, even if it starts
+ * with a "-". This allows us to match object names that
+ * start with "-".
+ */
+ if (pos == objc-1 && !pattern) {
+ pattern = token;
+ forceFullNames = (strstr(pattern, "::") != NULL);
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (pos < objc) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-class className? ?-isa className? ?pattern?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Search through all commands in the current namespace first,
+ * in the global namespace next, then in all child namespaces
+ * in this interpreter. If we find any commands that
+ * represent objects, report them.
+ */
+
+ Itcl_InitStack(&search);
+ Itcl_PushStack((ClientData)globalNs, &search);
+ Itcl_PushStack((ClientData)activeNs, &search); /* last in, first out! */
+
+ Tcl_InitHashTable(&unique, TCL_ONE_WORD_KEYS);
+
+ handledActiveNs = 0;
+ while (Itcl_GetStackSize(&search) > 0) {
+ nsPtr = Itcl_PopStack(&search);
+ if (nsPtr == activeNs && handledActiveNs) {
+ continue;
+ }
+
+ entry = Tcl_FirstHashEntry(Itcl_GetNamespaceCommandTable(nsPtr), &place);
+ while (entry) {
+ cmd = (Tcl_Command)Tcl_GetHashValue(entry);
+ if (Itcl_IsObject(cmd)) {
+ originalCmd = Tcl_GetOriginalCommand(cmd);
+ if (originalCmd) {
+ cmd = originalCmd;
+ }
+ Tcl_GetCommandInfoFromToken(cmd, &cmdInfo);
+ contextIoPtr = (ItclObject*)cmdInfo.deleteData;
+
+ /*
+ * Report full names if:
+ * - the pattern has namespace qualifiers
+ * - the class namespace is not in the current namespace
+ * - the class's object creation command is imported from
+ * another namespace.
+ *
+ * Otherwise, report short names.
+ */
+ if (forceFullNames || nsPtr != activeNs ||
+ originalCmd != NULL) {
+
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(interp, cmd, objPtr);
+ cmdName = Tcl_GetString(objPtr);
+ } else {
+ cmdName = Tcl_GetCommandName(interp, cmd);
+ objPtr = Tcl_NewStringObj((const char *)cmdName, -1);
+ }
+
+ Tcl_CreateHashEntry(&unique, (char*)cmd, &newEntry);
+
+ match = 0;
+ if (newEntry &&
+ (!pattern || Tcl_StringMatch((const char *)cmdName,
+ pattern))) {
+ if ((iclsPtr == NULL) ||
+ (contextIoPtr->iclsPtr == iclsPtr)) {
+ if (isaDefn == NULL) {
+ match = 1;
+ } else {
+ entry = Tcl_FindHashEntry(
+ &contextIoPtr->iclsPtr->heritage,
+ (char*)isaDefn);
+
+ if (entry) {
+ match = 1;
+ }
+ }
+ }
+ }
+
+ if (match) {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ Tcl_GetObjResult(interp), objPtr);
+ } else {
+ Tcl_DecrRefCount(objPtr); /* throw away the name */
+ }
+ }
+ entry = Tcl_NextHashEntry(&place);
+ }
+ handledActiveNs = 1; /* don't process the active namespace twice */
+
+ /*
+ * Push any child namespaces onto the stack and continue
+ * the search in those namespaces.
+ */
+ entry = Tcl_FirstHashEntry(Itcl_GetNamespaceChildTable(nsPtr), &place);
+ while (entry != NULL) {
+ Itcl_PushStack(Tcl_GetHashValue(entry), &search);
+ entry = Tcl_NextHashEntry(&place);
+ }
+ }
+ Tcl_DeleteHashTable(&unique);
+ Itcl_DeleteStack(&search);
+
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DelClassCmd()
+ *
+ * Part of the "delete" ensemble. Invoked by Tcl whenever the
+ * user issues a "delete class" command to delete classes.
+ * Handles the following syntax:
+ *
+ * delete class <name> ?<name>...?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+NRDelClassCmd(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int i;
+ char *name;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(1, "Itcl_DelClassCmd", objc, objv);
+ /*
+ * Since destroying a base class will destroy all derived
+ * classes, calls like "destroy class Base Derived" could
+ * fail. Break this into two passes: first check to make
+ * sure that all classes on the command line are valid,
+ * then delete them.
+ */
+ for (i=1; i < objc; i++) {
+ name = Tcl_GetString(objv[i]);
+ iclsPtr = Itcl_FindClass(interp, name, /* autoload */ 1);
+ if (iclsPtr == NULL) {
+ return TCL_ERROR;
+ }
+ }
+
+ for (i=1; i < objc; i++) {
+ name = Tcl_GetString(objv[i]);
+ iclsPtr = Itcl_FindClass(interp, name, /* autoload */ 0);
+
+ if (iclsPtr) {
+ Tcl_ResetResult(interp);
+ if (Itcl_DeleteClass(interp, iclsPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+}
+
+/* ARGSUSED */
+int
+Itcl_DelClassCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRDelClassCmd, clientData, objc, objv);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DelObjectCmd()
+ *
+ * Part of the "delete" ensemble. Invoked by Tcl whenever the user
+ * issues a "delete object" command to delete [incr Tcl] objects.
+ * Handles the following syntax:
+ *
+ * delete object <name> ?<name>...?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+static int
+CallDeleteObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ItclObject *contextIoPtr = data[0];
+ if (contextIoPtr->destructorHasBeenCalled) {
+ Tcl_AppendResult(interp, "can't delete an object while it is being ",
+ "destructed", NULL);
+ return TCL_ERROR;
+ }
+ if (result == TCL_OK) {
+ result = Itcl_DeleteObject(interp, contextIoPtr);
+ }
+ return result;
+}
+
+static int
+NRDelObjectCmd(
+ ClientData clientData, /* object management info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObject *contextIoPtr;
+ char *name;
+ void *callbackPtr;
+ int i;
+ int result;
+
+ ItclShowArgs(1, "Itcl_DelObjectCmd", objc, objv);
+ /*
+ * Scan through the list of objects and attempt to delete them.
+ * If anything goes wrong (i.e., destructors fail), then
+ * abort with an error.
+ */
+ for (i=1; i < objc; i++) {
+ name = Tcl_GetStringFromObj(objv[i], (int*)NULL);
+ contextIoPtr = NULL;
+ if (Itcl_FindObject(interp, name, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "object \"", name, "\" not found",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, CallDeleteObject, contextIoPtr,
+ NULL, NULL, NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+/* ARGSUSED */
+int
+Itcl_DelObjectCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRDelObjectCmd, clientData, objc, objv);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ScopeCmd()
+ *
+ * Invoked by Tcl whenever the user issues a "scope" command to
+ * create a fully qualified variable name. Handles the following
+ * syntax:
+ *
+ * scope <variable>
+ *
+ * If the input string is already fully qualified (starts with "::"),
+ * then this procedure does nothing. Otherwise, it looks for a
+ * data member called <variable> and returns its fully qualified
+ * name. If the <variable> is a common data member, this procedure
+ * returns a name of the form:
+ *
+ * ::namesp::namesp::class::variable
+ *
+ * If the <variable> is an instance variable, this procedure returns
+ * a name in a format that Tcl can use to find the same variable from
+ * any context.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ScopeCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNsPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Object oPtr;
+ Tcl_InterpDeleteProc *procPtr;
+ Tcl_Obj *objPtr2;
+ Tcl_Var var;
+ Tcl_HashEntry *entry;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObjectInfo *infoPtr;
+ ItclVarLookup *vlookup;
+ char *openParen;
+ register char *p;
+ char *token;
+ int doAppend;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ScopeCmd", objc, objv);
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "varname");
+ return TCL_ERROR;
+ }
+
+ contextNsPtr = Tcl_GetCurrentNamespace(interp);
+ openParen = NULL;
+ result = TCL_OK;
+ /*
+ * If this looks like a fully qualified name already,
+ * then return it as is.
+ */
+ token = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ if (*token == ':' && *(token+1) == ':') {
+ Tcl_SetObjResult(interp, objv[1]);
+ return TCL_OK;
+ }
+
+ /*
+ * If the variable name is an array reference, pick out
+ * the array name and use that for the lookup operations
+ * below.
+ */
+ for (p=token; *p != '\0'; p++) {
+ if (*p == '(') {
+ openParen = p;
+ }
+ else if (*p == ')' && openParen) {
+ *openParen = '\0';
+ break;
+ }
+ }
+
+ /*
+ * Figure out what context we're in. If this is a class,
+ * then look up the variable in the class definition.
+ * If this is a namespace, then look up the variable in its
+ * varTable. Note that the normal Itcl_GetContext function
+ * returns an error if we're not in a class context, so we
+ * perform a similar function here, the hard way.
+ *
+ * TRICKY NOTE: If this is an array reference, we'll get
+ * the array variable as the variable name. We must be
+ * careful to add the index (everything from openParen
+ * onward) as well.
+ */
+ contextIoPtr = NULL;
+ contextIclsPtr = NULL;
+ oPtr = NULL;
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)contextNsPtr);
+ if (hPtr != NULL) {
+ contextIclsPtr = (ItclClass *)Tcl_GetHashValue(hPtr);
+ }
+ if (Itcl_IsClassNamespace(contextNsPtr)) {
+ ClientData clientData;
+
+ entry = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, token);
+ if (!entry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "variable \"", token, "\" not found in class \"",
+ Tcl_GetString(contextIclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto scopeCmdDone;
+ }
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry);
+
+ if (vlookup->ivPtr->flags & ITCL_COMMON) {
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+ if (vlookup->ivPtr->protection != ITCL_PUBLIC) {
+ Tcl_AppendToObj(resultPtr, ITCL_VARIABLES_NAMESPACE, -1);
+ }
+ Tcl_AppendToObj(resultPtr,
+ Tcl_GetString(vlookup->ivPtr->fullNamePtr), -1);
+ if (openParen) {
+ *openParen = '(';
+ Tcl_AppendToObj(resultPtr, openParen, -1);
+ openParen = NULL;
+ }
+ result = TCL_OK;
+ goto scopeCmdDone;
+ }
+
+ /*
+ * If this is not a common variable, then we better have
+ * an object context. Return the name as a fully qualified name.
+ */
+ infoPtr = contextIclsPtr->infoPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject((Tcl_ObjectContext)clientData);
+ if (oPtr != NULL) {
+ contextIoPtr = (ItclObject*)Tcl_ObjectGetMetadata(
+ oPtr, infoPtr->object_meta_type);
+ }
+ }
+
+ if (contextIoPtr == NULL) {
+ if (infoPtr->currIoPtr != NULL) {
+ contextIoPtr = infoPtr->currIoPtr;
+ }
+ }
+ if (contextIoPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "can't scope variable \"", token,
+ "\": missing object context",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto scopeCmdDone;
+ }
+
+ doAppend = 1;
+ if (contextIclsPtr->flags & ITCL_ECLASS) {
+ if (strcmp(token, "itcl_options") == 0) {
+ doAppend = 0;
+ }
+ }
+
+ objPtr2 = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_IncrRefCount(objPtr2);
+ Tcl_AppendToObj(objPtr2, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr2,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr))->fullName, -1);
+
+ if (doAppend) {
+ Tcl_AppendToObj(objPtr2,
+ Tcl_GetString(vlookup->ivPtr->fullNamePtr), -1);
+ } else {
+ Tcl_AppendToObj(objPtr2, "::", -1);
+ Tcl_AppendToObj(objPtr2,
+ Tcl_GetString(vlookup->ivPtr->namePtr), -1);
+ }
+
+ if (openParen) {
+ *openParen = '(';
+ Tcl_AppendToObj(objPtr2, openParen, -1);
+ openParen = NULL;
+ }
+ /* fix for SF bug #238 use Tcl_AppendResult instead of Tcl_AppendElement */
+ Tcl_AppendResult(interp, Tcl_GetString(objPtr2), NULL);
+ Tcl_DecrRefCount(objPtr2);
+ } else {
+
+ /*
+ * We must be in an ordinary namespace context. Resolve
+ * the variable using Tcl_FindNamespaceVar.
+ *
+ * TRICKY NOTE: If this is an array reference, we'll get
+ * the array variable as the variable name. We must be
+ * careful to add the index (everything from openParen
+ * onward) as well.
+ */
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+
+ var = Itcl_FindNamespaceVar(interp, token, contextNsPtr,
+ TCL_NAMESPACE_ONLY);
+
+ if (!var) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "variable \"", token, "\" not found in namespace \"",
+ contextNsPtr->fullName, "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ goto scopeCmdDone;
+ }
+
+ Itcl_GetVariableFullName(interp, var, resultPtr);
+ if (openParen) {
+ *openParen = '(';
+ Tcl_AppendToObj(resultPtr, openParen, -1);
+ openParen = NULL;
+ }
+ }
+
+scopeCmdDone:
+ if (openParen) {
+ *openParen = '(';
+ }
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CodeCmd()
+ *
+ * Invoked by Tcl whenever the user issues a "code" command to
+ * create a scoped command string. Handles the following syntax:
+ *
+ * code ?-namespace foo? arg ?arg arg ...?
+ *
+ * Unlike the scope command, the code command DOES NOT look for
+ * scoping information at the beginning of the command. So scopes
+ * will nest in the code command.
+ *
+ * The code command is similar to the "namespace code" command in
+ * Tcl, but it preserves the list structure of the input arguments,
+ * so it is a lot more useful.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_CodeCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp);
+
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ const char *token;
+ int pos;
+
+ ItclShowArgs(1, "Itcl_CodeCmd", objc, objv);
+ /*
+ * Handle flags like "-namespace"...
+ */
+ for (pos=1; pos < objc; pos++) {
+ token = Tcl_GetStringFromObj(objv[pos], (int*)NULL);
+ if (*token != '-') {
+ break;
+ }
+
+ if (strcmp(token, "-namespace") == 0) {
+ if (objc == 2) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-namespace name? command ?arg arg...?");
+ return TCL_ERROR;
+ } else {
+ token = Tcl_GetString(objv[pos+1]);
+ contextNs = Tcl_FindNamespace(interp, token,
+ (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);
+
+ if (!contextNs) {
+ return TCL_ERROR;
+ }
+ pos++;
+ }
+ } else {
+ if (strcmp(token, "--") == 0) {
+ pos++;
+ break;
+ } else {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option \"", token, "\": should be -namespace or --",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "?-namespace name? command ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Now construct a scoped command by integrating the
+ * current namespace context, and appending the remaining
+ * arguments AS A LIST...
+ */
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("namespace", -1));
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("inscope", -1));
+
+ if (contextNs == Tcl_GetGlobalNamespace(interp)) {
+ objPtr = Tcl_NewStringObj("::", -1);
+ } else {
+ objPtr = Tcl_NewStringObj(contextNs->fullName, -1);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+
+ if (objc-pos == 1) {
+ objPtr = objv[pos];
+ } else {
+ objPtr = Tcl_NewListObj(objc-pos, &objv[pos]);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ Tcl_SetResult(interp, Tcl_GetString(listPtr), TCL_VOLATILE);
+ Tcl_DecrRefCount(listPtr);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsObjectCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::is object"
+ * command to test whether the argument is an object or not.
+ * syntax:
+ *
+ * itcl::is object ?-class classname? commandname
+ *
+ * Returns 1 if it is an object, 0 otherwise
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsObjectCmd(
+ ClientData clientData, /* class/object info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+
+ int classFlag = 0;
+ int idx = 0;
+ char *name = NULL;
+ char *cname;
+ char *cmdName;
+ char *token;
+ Tcl_Command cmd;
+ Tcl_Namespace *contextNs = NULL;
+ ItclClass *iclsPtr = NULL;
+
+ /*
+ * Handle the arguments.
+ * objc needs to be either:
+ * 2 itcl::is object commandname
+ * 4 itcl::is object -class classname commandname
+ */
+ if (objc != 2 && objc != 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "?-class classname? commandname");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the command args. Look for the -class
+ * keyword.
+ */
+ for (idx=1; idx < objc; idx++) {
+ token = Tcl_GetString(objv[idx]);
+
+ if (strcmp(token,"-class") == 0) {
+ cname = Tcl_GetString(objv[idx+1]);
+ iclsPtr = Itcl_FindClass(interp, cname, /* no autoload */ 0);
+
+ if (iclsPtr == NULL) {
+ return TCL_ERROR;
+ }
+
+ idx++;
+ classFlag = 1;
+ } else {
+ name = Tcl_GetString(objv[idx]);
+ }
+
+ } /* end for objc loop */
+
+
+ /*
+ * The object name may be a scoped value of the form
+ * "namespace inscope <namesp> <command>". If it is,
+ * decode it.
+ */
+ if (Itcl_DecodeScopedCommand(interp, name, &contextNs, &cmdName)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ cmd = Tcl_FindCommand(interp, cmdName, contextNs, /* flags */ 0);
+
+ /*
+ * Need the NULL test, or the test will fail if cmd is NULL
+ */
+ if (cmd == NULL || ! Itcl_IsObject(cmd)) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+ ckfree((char *)cmdName);
+ return TCL_OK;
+ }
+
+ /*
+ * Handle the case when the -class flag is given
+ */
+ if (classFlag) {
+ ItclObject *contextIoPtr;
+ if (Itcl_FindObject(interp, cmdName, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr == NULL) {
+ /* seems that we are in constructor, so look for currIoPtr in info structure */
+ contextIoPtr = iclsPtr->infoPtr->currIoPtr;
+ }
+ if (! Itcl_ObjectIsa(contextIoPtr, iclsPtr)) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+ ckfree((char *)cmdName);
+ return TCL_OK;
+ }
+
+ }
+
+ /*
+ * Got this far, so assume that it is a valid object
+ */
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
+ ckfree(cmdName);
+
+ return TCL_OK;
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsClassCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::is class"
+ * command to test whether the argument is an itcl class or not
+ * syntax:
+ *
+ * itcl::is class commandname
+ *
+ * Returns 1 if it is a class, 0 otherwise
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsClassCmd(
+ ClientData clientData, /* class/object info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+
+ char *cname;
+ char *name;
+ ItclClass *iclsPtr = NULL;
+ Tcl_Namespace *contextNs = NULL;
+
+ /*
+ * Need itcl::is class classname
+ */
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "commandname");
+ return TCL_ERROR;
+ }
+
+ name = Tcl_GetString(objv[1]);
+
+ /*
+ * The object name may be a scoped value of the form
+ * "namespace inscope <namesp> <command>". If it is,
+ * decode it.
+ */
+ if (Itcl_DecodeScopedCommand(interp, name, &contextNs, &cname) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ iclsPtr = Itcl_FindClass(interp, cname, /* no autoload */ 0);
+
+ /*
+ * If classDefn is NULL, then it wasn't found, hence it
+ * isn't a class
+ */
+ if (iclsPtr != NULL) {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(1));
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewBooleanObj(0));
+ }
+
+ ckfree(cname);
+
+ return TCL_OK;
+
+} /* end Itcl_IsClassCmd function */
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FilterCmd()
+ *
+ * Used to add a filter command to an object which is called just before
+ * a method/proc of a class is executed
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_FilterAddCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj **newObjv;
+ int result;
+
+ ItclShowArgs(1, "Itcl_FilterCmd", objc, objv);
+/* Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp); */
+/* FIXME need to change the chain command to do the same here as the TclOO next command !! */
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "<className> <filterName> ?<filterName> ...?");
+ return TCL_ERROR;
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+1));
+ newObjv[0] = Tcl_NewStringObj("::oo::define", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = objv[1];
+ newObjv[2] = Tcl_NewStringObj("filter", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ memcpy(newObjv+3, objv+2, sizeof(Tcl_Obj *)*(objc-2));
+ ItclShowArgs(1, "Itcl_FilterAddCmd2", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[2]);
+
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FilterDeleteCmd()
+ *
+ * used to delete filter commands of a class or object
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_FilterDeleteCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(1, "Itcl_FilterDeleteCmd", objc, objv);
+/* Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp); */
+
+ Tcl_AppendResult(interp, "::itcl::filter delete command not yet implemented", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ForwardAddCmd()
+ *
+ * Used to similar to iterp alias to forward the call of a method
+ * to another method within the class
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ForwardAddCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *prefixObj;
+ Tcl_Method mPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(1, "Itcl_ForwardAddCmd", objc, objv);
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "<forwardName> <targetName> ?<arg> ...?");
+ return TCL_ERROR;
+ }
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_HashEntry *hPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->nameClasses, (char *)objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "class: \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ }
+ prefixObj = Tcl_NewListObj(objc-2, objv+2);
+ mPtr = Itcl_NewForwardClassMethod(interp, iclsPtr->clsPtr, 1,
+ objv[1], prefixObj);
+ if (mPtr == NULL) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ForwardDeleteCmd()
+ *
+ * used to delete forwarded commands of a class or object
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ForwardDeleteCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(1, "Itcl_ForwardDeleteCmd", objc, objv);
+/* Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp); */
+
+ Tcl_AppendResult(interp, "::itcl::forward delete command not yet implemented", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_MixinAddCmd()
+ *
+ * Used to add the methods of a class to another class without heritance
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_MixinAddCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj **newObjv;
+ int result;
+
+ ItclShowArgs(1, "Itcl_MixinAddCmd", objc, objv);
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "<className> <mixinName> ?<mixinName> ...?");
+ return TCL_ERROR;
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+1));
+ newObjv[0] = Tcl_NewStringObj("::oo::define", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = objv[1];
+ newObjv[2] = Tcl_NewStringObj("mixin", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ memcpy(newObjv+3, objv+2, sizeof(Tcl_Obj *)*(objc-2));
+ ItclShowArgs(1, "Itcl_MixinAddCmd2", objc+1, newObjv);
+ result = Tcl_EvalObjv(interp, objc+1, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[2]);
+
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_MixinDeleteCmd()
+ *
+ * Used to delete the methods of a class to another class without heritance
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_MixinDeleteCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(1, "Itcl_MixinDeleteCmd", objc, objv);
+/* Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp); */
+
+ Tcl_AppendResult(interp, "::itcl::mixin delete command not yet implemented", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_NWidgetCmd()
+ *
+ * Used to build an [incr Tcl] nwidget
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_NWidgetCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+ int result;
+
+ iclsPtr = NULL;
+ ItclShowArgs(0, "Itcl_NWidgetCmd", objc-1, objv);
+ result = ItclClassBaseCmd(clientData, interp, ITCL_ECLASS|ITCL_NWIDGET, objc, objv,
+ &iclsPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Itcl_NWidgetCmd!iclsPtr == NULL\n", NULL);
+ result = TCL_ERROR;
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AddOptionCmd()
+ *
+ * Used to build an option to an [incr Tcl] nwidget/eclass
+ *
+ * Syntax: ::itcl::addoption <nwidget class> <protection> <optionName> <defaultValue>
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_AddOptionCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ const char *protectionStr;
+ int pLevel;
+ int result;
+
+ result = TCL_OK;
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclShowArgs(1, "Itcl_AddOptionCmd", objc, objv);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "className protection option optionName ...");
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->nameClasses, (char *)objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "class \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ protectionStr = Tcl_GetString(objv[2]);
+ pLevel = -1;
+ if (strcmp(protectionStr, "public") == 0) {
+ pLevel = ITCL_PUBLIC;
+ }
+ if (strcmp(protectionStr, "protected") == 0) {
+ pLevel = ITCL_PROTECTED;
+ }
+ if (strcmp(protectionStr, "private") == 0) {
+ pLevel = ITCL_PRIVATE;
+ }
+ if (pLevel == -1) {
+ Tcl_AppendResult(interp, "bad protection \"", protectionStr, "\"",
+ NULL);
+ return TCL_ERROR;
+ }
+ Itcl_PushStack((ClientData)iclsPtr, &infoPtr->clsStack);
+ result = Itcl_ClassOptionCmd(clientData, interp, objc-2, objv+2);
+ Itcl_PopStack(&infoPtr->clsStack);
+ if (result != TCL_OK) {
+ return result;
+ }
+ result = DelegatedOptionsInstall(interp, iclsPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AddObjectOptionCmd()
+ *
+ * Used to build an option for an [incr Tcl] object
+ *
+ * Syntax: ::itcl::addobjectoption <object> <protection> option <optionSpec>
+ * ?-default <defaultValue>?
+ * ?-configuremethod <configuremethod>?
+ * ?-validatemethod <validatemethod>?
+ * ?-cgetmethod <cgetmethod>?
+ * ?-configuremethodvar <configuremethodvar>?
+ * ?-validatemethodvar <validatemethodvar>?
+ * ?-cgetmethodvar <cgetmethodvar>?
+ * ?-readonly?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_AddObjectOptionCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Command cmd;
+ Tcl_Obj *objPtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclOption *ioptPtr;
+ const char *protectionStr;
+ int pLevel;
+ int isNew;
+
+ ioptPtr = NULL;
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclShowArgs(1, "Itcl_AddObjectOptionCmd", objc, objv);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "objectName protection option optionName ...");
+ return TCL_ERROR;
+ }
+
+ cmd = Tcl_FindCommand(interp, Tcl_GetString(objv[1]), NULL, 0);
+ if (cmd == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->objectCmds, (char *)cmd);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ ioPtr = Tcl_GetHashValue(hPtr);
+ protectionStr = Tcl_GetString(objv[2]);
+ pLevel = -1;
+ if (strcmp(protectionStr, "public") == 0) {
+ pLevel = ITCL_PUBLIC;
+ }
+ if (strcmp(protectionStr, "protected") == 0) {
+ pLevel = ITCL_PROTECTED;
+ }
+ if (strcmp(protectionStr, "private") == 0) {
+ pLevel = ITCL_PRIVATE;
+ }
+ if (pLevel == -1) {
+ Tcl_AppendResult(interp, "bad protection \"", protectionStr, "\"",
+ NULL);
+ return TCL_ERROR;
+ }
+ infoPtr->protection = pLevel;
+ if (ItclParseOption(infoPtr, interp, objc-3, objv+3, NULL, ioPtr,
+ &ioptPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ ioptPtr->fullNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(ioPtr->namePtr), -1);
+ Tcl_AppendToObj(ioptPtr->fullNamePtr, "::", 2);
+ Tcl_AppendToObj(ioptPtr->fullNamePtr, Tcl_GetString(ioptPtr->namePtr), -1);
+ Tcl_IncrRefCount(ioptPtr->fullNamePtr);
+ hPtr = Tcl_CreateHashEntry(&ioPtr->objectOptions,
+ (char *)ioptPtr->namePtr, &isNew);
+ Tcl_SetHashValue(hPtr, ioptPtr);
+ ItclSetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr),
+ Tcl_GetString(ioptPtr->defaultValuePtr), ioPtr, NULL);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AddDelegatedOptionCmd()
+ *
+ * Used to build an option to an [incr Tcl] nwidget/eclass
+ *
+ * Syntax: ::itcl::adddelegatedoption <nwidget object> <optionName> <defaultValue>
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_AddDelegatedOptionCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Command cmd;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclDelegatedOption *idoPtr;
+ int isNew;
+ int result;
+
+ result = TCL_OK;
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclShowArgs(1, "Itcl_AddDelegatedOptionCmd", objc, objv);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "className protection option optionName ...");
+ return TCL_ERROR;
+ }
+
+ cmd = Tcl_FindCommand(interp, Tcl_GetString(objv[1]), NULL, 0);
+ if (cmd == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->objectCmds, (char *)cmd);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ ioPtr = Tcl_GetHashValue(hPtr);
+ result = Itcl_HandleDelegateOptionCmd(interp, ioPtr, NULL, &idoPtr,
+ objc-3, objv+3);
+ if (result != TCL_OK) {
+ return result;
+ }
+ hPtr = Tcl_CreateHashEntry(&ioPtr->objectDelegatedOptions,
+ (char *)idoPtr->namePtr, &isNew);
+ Tcl_SetHashValue(hPtr, idoPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AddDelegatedFunctionCmd()
+ *
+ * Used to build an function to an [incr Tcl] nwidget/eclass
+ *
+ * Syntax: ::itcl::adddelegatedfunction <nwidget object> <fucntionName> ...
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_AddDelegatedFunctionCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Command cmd;
+ Tcl_Obj *componentNamePtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclHierIter hier;
+ const char *val;
+ int isNew;
+ int result;
+
+ result = TCL_OK;
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclShowArgs(1, "Itcl_AddDelegatedFunctionCmd", objc, objv);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "className protection method/proc functionName ...");
+ return TCL_ERROR;
+ }
+
+ cmd = Tcl_FindCommand(interp, Tcl_GetString(objv[1]), NULL, 0);
+ if (cmd == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->objectCmds, (char *)cmd);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" not found", NULL);
+ return TCL_ERROR;
+ }
+ ioPtr = Tcl_GetHashValue(hPtr);
+ result = Itcl_HandleDelegateMethodCmd(interp, ioPtr, NULL, &idmPtr,
+ objc-3, objv+3);
+ if (result != TCL_OK) {
+ return result;
+ }
+ componentNamePtr = idmPtr->icPtr->namePtr;
+ Itcl_InitHierIter(&hier, ioPtr->iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components, (char *)
+ componentNamePtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ val = Itcl_GetInstanceVar(interp,
+ Tcl_GetString(componentNamePtr), ioPtr, iclsPtr);
+ componentNamePtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(componentNamePtr);
+ DelegateFunction(interp, ioPtr, ioPtr->iclsPtr, componentNamePtr, idmPtr);
+ hPtr = Tcl_CreateHashEntry(&ioPtr->objectDelegatedFunctions,
+ (char *)idmPtr->namePtr, &isNew);
+ Tcl_DecrRefCount(componentNamePtr);
+ Tcl_SetHashValue(hPtr, idmPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AddComponentCmd()
+ *
+ * Used to add a component to an [incr Tcl] nwidget/eclass
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_AddComponentCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_DString buffer;
+ Tcl_DString buffer2;
+ Tcl_Namespace *varNsPtr;
+ Tcl_Namespace *nsPtr;
+ Tcl_CallFrame frame;
+ Tcl_Var varPtr;
+ ItclVarLookup *vlookup;
+ ItclObject *contextIoPtr;
+ ItclClass *contextIclsPtr;
+ ItclComponent *icPtr;
+ ItclVariable *ivPtr;
+ const char *varName;
+ int isNew;
+ int result;
+
+ result = TCL_OK;
+ contextIoPtr = NULL;
+ ItclShowArgs(1, "Itcl_AddComponentCmd", objc, objv);
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "objectName componentName");
+ return TCL_ERROR;
+ }
+ if (Itcl_FindObject(interp, Tcl_GetString(objv[1]), &contextIoPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr == NULL) {
+ Tcl_AppendResult(interp, "Itcl_AddComponentCmd contextIoPtr "
+ "for \"", Tcl_GetString(objv[1]), "\" == NULL", NULL);
+ return TCL_ERROR;
+ }
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ hPtr = Tcl_CreateHashEntry(&contextIoPtr->objectComponents, (char *)objv[2],
+ &isNew);
+ if (!isNew) {
+ Tcl_AppendResult(interp, "Itcl_AddComponentCmd component \"",
+ Tcl_GetString(objv[2]), "\" already exists for object \"",
+ Tcl_GetString(objv[1]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ if (ItclCreateComponent(interp, contextIclsPtr, objv[2], /* not common */0,
+ &icPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ ItclAddClassComponentDictInfo(interp, contextIclsPtr, icPtr);
+ contextIclsPtr->numVariables++;
+ Tcl_SetHashValue(hPtr, icPtr);
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr))->fullName, -1);
+ Tcl_DStringAppend(&buffer, contextIclsPtr->nsPtr->fullName, -1);
+ varNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->variables, (char *)objv[2]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "Itcl_AddComponentCmd cannot find component",
+ " \"", Tcl_GetString(objv[2]), "\"in class variables", NULL);
+ return TCL_ERROR;
+ }
+ ivPtr = Tcl_GetHashValue(hPtr);
+ /* add entry to the virtual tables */
+ vlookup = (ItclVarLookup *)ckalloc(sizeof(ItclVarLookup));
+ vlookup->ivPtr = ivPtr;
+ vlookup->usage = 0;
+ vlookup->leastQualName = NULL;
+
+ /*
+ * If this variable is PRIVATE to another class scope,
+ * then mark it as "inaccessible".
+ */
+ vlookup->accessible = (ivPtr->protection != ITCL_PRIVATE ||
+ ivPtr->iclsPtr == contextIclsPtr);
+
+ vlookup->varNum = contextIclsPtr->numInstanceVars++;
+ /*
+ * Create all possible names for this variable and enter
+ * them into the variable resolution table:
+ * var
+ * class::var
+ * namesp1::class::var
+ * namesp2::namesp1::class::var
+ * ...
+ */
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(ivPtr->namePtr), -1);
+ nsPtr = contextIclsPtr->nsPtr;
+
+ Tcl_DStringInit(&buffer2);
+ while (1) {
+ hPtr = Tcl_CreateHashEntry(&contextIclsPtr->resolveVars,
+ Tcl_DStringValue(&buffer), &isNew);
+
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, (ClientData)vlookup);
+ vlookup->usage++;
+
+ if (!vlookup->leastQualName) {
+ vlookup->leastQualName =
+ Tcl_GetHashKey(&contextIclsPtr->resolveVars, hPtr);
+ }
+#ifdef NEW_PROTO_RESOLVER
+ Itcl_RegisterClassVariable(contextIclsPtr->infoPtr->interp,
+ contextIclsPtr->nsPtr, Tcl_DStringValue(&buffer),
+ vlookup->classVarInfoPtr);
+#endif
+ }
+
+ if (nsPtr == NULL) {
+ break;
+ }
+ Tcl_DStringSetLength(&buffer2, 0);
+ Tcl_DStringAppend(&buffer2, Tcl_DStringValue(&buffer), -1);
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, nsPtr->name, -1);
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, Tcl_DStringValue(&buffer2), -1);
+
+ nsPtr = nsPtr->parentPtr;
+ }
+ Tcl_DStringFree(&buffer2);
+ Tcl_DStringFree(&buffer);
+
+
+
+ varName = Tcl_GetString(ivPtr->namePtr);
+ /* now initialize the variable */
+ if (Itcl_PushCallFrame(interp, &frame, varNsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_SetVar2(interp, varName, NULL,
+ "", TCL_NAMESPACE_ONLY) == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR cannot set",
+ " variable \"", varName, "\"\n", NULL);
+ result = TCL_ERROR;
+ }
+ Itcl_PopCallFrame(interp);
+ varPtr = Tcl_NewNamespaceVar(interp, varNsPtr,
+ Tcl_GetString(ivPtr->namePtr));
+ hPtr = Tcl_CreateHashEntry(&contextIoPtr->objectVariables,
+ (char *)ivPtr, &isNew);
+ if (isNew) {
+ Itcl_PreserveVar(varPtr);
+ Tcl_SetHashValue(hPtr, varPtr);
+ } else {
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_SetComponentCmd()
+ *
+ * Used to set a component for an [incr Tcl] nwidget/eclass
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_SetComponentCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ ItclClass *iclsPtr;
+ ItclObject *contextIoPtr;
+ ItclClass *contextIclsPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedOption *idoPtr;
+ ItclHierIter hier;
+ const char *name;
+ const char *val;
+ int result;
+
+ result = TCL_OK;
+ contextIoPtr = NULL;
+ ItclShowArgs(1, "Itcl_SetComponentCmd", objc, objv);
+ if (objc < 4) {
+ Tcl_WrongNumArgs(interp, 1, objv,
+ "objectName componentName value");
+ return TCL_ERROR;
+ }
+ name = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+ if (Itcl_FindObject(interp, name, &contextIoPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (contextIoPtr == NULL) {
+ Tcl_AppendResult(interp, "Itcl_SetComponentCmd contextIoPtr "
+ "for \"", Tcl_GetString(objv[1]), "\" == NULL", NULL);
+ return TCL_ERROR;
+ }
+ Itcl_InitHierIter(&hier, contextIoPtr->iclsPtr);
+ hPtr = NULL;
+ while ((contextIclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->components, (char *)objv[2]);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "object \"", Tcl_GetString(objv[1]),
+ "\" has no component \"", Tcl_GetString(objv[2]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ icPtr = Tcl_GetHashValue(hPtr);
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr), NULL,
+ contextIoPtr, contextIclsPtr);
+ if ((val != NULL) && (strlen(val) != 0)) {
+ /* delete delegated options to the old component here !! */
+ Itcl_InitHierIter(&hier, contextIoPtr->iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ FOREACH_HASH_VALUE(idoPtr, &iclsPtr->delegatedOptions) {
+ if (strcmp(Tcl_GetString(idoPtr->icPtr->namePtr),
+ Tcl_GetString(objv[2])) == 0) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ }
+ if (ItclSetInstanceVar(interp, Tcl_GetString(icPtr->namePtr), NULL,
+ Tcl_GetString(objv[3]), contextIoPtr, contextIclsPtr) == NULL) {
+ return TCL_ERROR;
+ }
+ val = ItclGetInstanceVar(interp, Tcl_GetString(icPtr->namePtr), NULL,
+ contextIoPtr, contextIclsPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ExtendedClassCmd()
+ *
+ * Used to create an [incr Tcl] extended class.
+ * An extended class is like a class with additional functionality/
+ * commands
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ExtendedClassCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ExtendedClassCmd", objc-1, objv);
+ result = ItclClassBaseCmd(clientData, interp, ITCL_ECLASS, objc, objv,
+ &iclsPtr);
+ if ((iclsPtr == NULL) && (result == TCL_OK)) {
+ ItclShowArgs(0, "Itcl_ExtendedClassCmd iclsPtr == NULL", objc-1, objv);
+ return TCL_ERROR;
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_TypeClassCmd()
+ *
+ * Used to create an [incr Tcl] type class.
+ * An type class is like a class with additional functionality/
+ * commands. it has no methods and vars but only the equivalent
+ * of proc and common namely typemethod and typevariable
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_TypeClassCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr;
+ ItclClass *iclsPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_TypeClassCmd", objc-1, objv);
+ result = ItclClassBaseCmd(clientData, interp, ITCL_TYPE, objc, objv,
+ &iclsPtr);
+ if ((iclsPtr == NULL) && (result == TCL_OK)) {
+ ItclShowArgs(0, "Itcl_TypeClassCmd iclsPtr == NULL", objc-1, objv);
+ return TCL_ERROR;
+ }
+ if (result != TCL_OK) {
+ return result;
+ }
+ /* we handle create by ourself !! */
+ objPtr = Tcl_NewStringObj("oo::objdefine ", -1);
+ Tcl_AppendToObj(objPtr, iclsPtr->nsPtr->fullName, -1);
+ Tcl_AppendToObj(objPtr, " unexport create", -1);
+ Tcl_IncrRefCount(objPtr);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ Tcl_DecrRefCount(objPtr);
+ objPtr = Tcl_NewStringObj(iclsPtr->nsPtr->fullName, -1);
+ Tcl_SetResult(interp, Tcl_GetString(objPtr), TCL_VOLATILE);
+ Tcl_DecrRefCount(objPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassHullTypeCmd()
+ *
+ * Used to set a hulltype for a widget
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ClassHullTypeCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ const char *hullTypeName;
+ int correctArg;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ ItclShowArgs(1, "Itcl_ClassHullTypeCmd", objc-1, objv);
+ if (iclsPtr->flags & ITCL_TYPE) {
+ Tcl_AppendResult(interp, "can't set hulltype for ::itcl::type",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ Tcl_AppendResult(interp, "can't set hulltype for ",
+ "::itcl::widgetadaptor", NULL);
+ return TCL_ERROR;
+ }
+ if (objc != 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: hulltype ",
+ "<hullTypeName>", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_WIDGET) {
+ hullTypeName = Tcl_GetString(objv[1]);
+ if (iclsPtr->hullTypePtr != NULL) {
+ Tcl_AppendResult(interp, "too many hulltype statements", NULL);
+ return TCL_ERROR;
+ }
+ correctArg = 0;
+ if (strcmp(hullTypeName, "frame") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_FRAME;
+ correctArg = 1;
+ }
+ if (strcmp(hullTypeName, "labelframe") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_LABEL_FRAME;
+ correctArg = 1;
+ }
+ if (strcmp(hullTypeName, "toplevel") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_TOPLEVEL;
+ correctArg = 1;
+ }
+ if (strcmp(hullTypeName, "ttk::frame") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_TTK_FRAME;
+ correctArg = 1;
+ }
+ if (strcmp(hullTypeName, "ttk::labelframe") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_TTK_LABEL_FRAME;
+ correctArg = 1;
+ }
+ if (strcmp(hullTypeName, "ttk::toplevel") == 0) {
+ iclsPtr->flags |= ITCL_WIDGET_TTK_TOPLEVEL;
+ correctArg = 1;
+ }
+ if (!correctArg) {
+ Tcl_AppendResult(interp,
+ "syntax: must be hulltype frame|toplevel|labelframe|",
+ "ttk::frame|ttk::toplevel|ttk::labelframe", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr->hullTypePtr = Tcl_NewStringObj(hullTypeName, -1);
+ Tcl_IncrRefCount(iclsPtr->hullTypePtr);
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "invalid command name \"hulltype\"", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassWidgetClassCmd()
+ *
+ * Used to set a widgetclass for a widget
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ClassWidgetClassCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ const char *widgetClassName;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ ItclShowArgs(1, "Itcl_ClassWidgetClassCmd", objc-1, objv);
+ if (iclsPtr->flags & ITCL_TYPE) {
+ Tcl_AppendResult(interp, "can't set widgetclass for ::itcl::type",
+ NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ Tcl_AppendResult(interp, "can't set widgetclass for ",
+ "::itcl::widgetadaptor", NULL);
+ return TCL_ERROR;
+ }
+ if (objc != 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: widgetclass ",
+ "<widgetClassName>", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_WIDGET) {
+ widgetClassName = Tcl_GetString(objv[1]);
+ if (!isupper(UCHAR(*widgetClassName))) {
+ Tcl_AppendResult(interp, "widgetclass \"", widgetClassName,
+ "\" does not begin with an uppercase letter", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->widgetClassPtr != NULL) {
+ Tcl_AppendResult(interp, "too many widgetclass statements", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr->widgetClassPtr = Tcl_NewStringObj(widgetClassName, -1);
+ Tcl_IncrRefCount(iclsPtr->widgetClassPtr);
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "invalid command name \"widgetclass\"", NULL);
+ return TCL_ERROR;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclDecls.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclDecls.h
new file mode 100644
index 0000000..4af4200
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclDecls.h
@@ -0,0 +1,201 @@
+/*
+ * This file is (mostly) automatically generated from itcl.decls.
+ */
+
+#ifndef _ITCLDECLS
+#define _ITCLDECLS
+
+#if defined(USE_ITCL_STUBS)
+
+ITCLAPI const char *Itcl_InitStubs(
+ Tcl_Interp *, const char *version, int exact);
+#else
+
+#define Itcl_InitStubs(interp, version, exact) Tcl_PkgRequire(interp,"itcl",version,exact)
+
+#endif
+
+
+/* !BEGIN!: Do not edit below this line. */
+
+#define ITCL_STUBS_EPOCH 0
+#define ITCL_STUBS_REVISION 150
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+/* Slot 0 is reserved */
+/* Slot 1 is reserved */
+/* 2 */
+ITCLAPI int Itcl_RegisterC(Tcl_Interp *interp, const char *name,
+ Tcl_CmdProc *proc, ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc);
+/* 3 */
+ITCLAPI int Itcl_RegisterObjC(Tcl_Interp *interp,
+ const char *name, Tcl_ObjCmdProc *proc,
+ ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc);
+/* 4 */
+ITCLAPI int Itcl_FindC(Tcl_Interp *interp, const char *name,
+ Tcl_CmdProc **argProcPtr,
+ Tcl_ObjCmdProc **objProcPtr,
+ ClientData *cDataPtr);
+/* 5 */
+ITCLAPI void Itcl_InitStack(Itcl_Stack *stack);
+/* 6 */
+ITCLAPI void Itcl_DeleteStack(Itcl_Stack *stack);
+/* 7 */
+ITCLAPI void Itcl_PushStack(ClientData cdata, Itcl_Stack *stack);
+/* 8 */
+ITCLAPI ClientData Itcl_PopStack(Itcl_Stack *stack);
+/* 9 */
+ITCLAPI ClientData Itcl_PeekStack(Itcl_Stack *stack);
+/* 10 */
+ITCLAPI ClientData Itcl_GetStackValue(Itcl_Stack *stack, int pos);
+/* 11 */
+ITCLAPI void Itcl_InitList(Itcl_List *listPtr);
+/* 12 */
+ITCLAPI void Itcl_DeleteList(Itcl_List *listPtr);
+/* 13 */
+ITCLAPI Itcl_ListElem * Itcl_CreateListElem(Itcl_List *listPtr);
+/* 14 */
+ITCLAPI Itcl_ListElem * Itcl_DeleteListElem(Itcl_ListElem *elemPtr);
+/* 15 */
+ITCLAPI Itcl_ListElem * Itcl_InsertList(Itcl_List *listPtr, ClientData val);
+/* 16 */
+ITCLAPI Itcl_ListElem * Itcl_InsertListElem(Itcl_ListElem *pos,
+ ClientData val);
+/* 17 */
+ITCLAPI Itcl_ListElem * Itcl_AppendList(Itcl_List *listPtr, ClientData val);
+/* 18 */
+ITCLAPI Itcl_ListElem * Itcl_AppendListElem(Itcl_ListElem *pos,
+ ClientData val);
+/* 19 */
+ITCLAPI void Itcl_SetListValue(Itcl_ListElem *elemPtr,
+ ClientData val);
+/* 20 */
+ITCLAPI void Itcl_EventuallyFree(ClientData cdata,
+ Tcl_FreeProc *fproc);
+/* 21 */
+ITCLAPI void Itcl_PreserveData(ClientData cdata);
+/* 22 */
+ITCLAPI void Itcl_ReleaseData(ClientData cdata);
+/* 23 */
+ITCLAPI Itcl_InterpState Itcl_SaveInterpState(Tcl_Interp *interp, int status);
+/* 24 */
+ITCLAPI int Itcl_RestoreInterpState(Tcl_Interp *interp,
+ Itcl_InterpState state);
+/* 25 */
+ITCLAPI void Itcl_DiscardInterpState(Itcl_InterpState state);
+
+typedef struct {
+ const struct ItclIntStubs *itclIntStubs;
+} ItclStubHooks;
+
+typedef struct ItclStubs {
+ int magic;
+ int epoch;
+ int revision;
+ const ItclStubHooks *hooks;
+
+ void (*reserved0)(void);
+ void (*reserved1)(void);
+ int (*itcl_RegisterC) (Tcl_Interp *interp, const char *name, Tcl_CmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 2 */
+ int (*itcl_RegisterObjC) (Tcl_Interp *interp, const char *name, Tcl_ObjCmdProc *proc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 3 */
+ int (*itcl_FindC) (Tcl_Interp *interp, const char *name, Tcl_CmdProc **argProcPtr, Tcl_ObjCmdProc **objProcPtr, ClientData *cDataPtr); /* 4 */
+ void (*itcl_InitStack) (Itcl_Stack *stack); /* 5 */
+ void (*itcl_DeleteStack) (Itcl_Stack *stack); /* 6 */
+ void (*itcl_PushStack) (ClientData cdata, Itcl_Stack *stack); /* 7 */
+ ClientData (*itcl_PopStack) (Itcl_Stack *stack); /* 8 */
+ ClientData (*itcl_PeekStack) (Itcl_Stack *stack); /* 9 */
+ ClientData (*itcl_GetStackValue) (Itcl_Stack *stack, int pos); /* 10 */
+ void (*itcl_InitList) (Itcl_List *listPtr); /* 11 */
+ void (*itcl_DeleteList) (Itcl_List *listPtr); /* 12 */
+ Itcl_ListElem * (*itcl_CreateListElem) (Itcl_List *listPtr); /* 13 */
+ Itcl_ListElem * (*itcl_DeleteListElem) (Itcl_ListElem *elemPtr); /* 14 */
+ Itcl_ListElem * (*itcl_InsertList) (Itcl_List *listPtr, ClientData val); /* 15 */
+ Itcl_ListElem * (*itcl_InsertListElem) (Itcl_ListElem *pos, ClientData val); /* 16 */
+ Itcl_ListElem * (*itcl_AppendList) (Itcl_List *listPtr, ClientData val); /* 17 */
+ Itcl_ListElem * (*itcl_AppendListElem) (Itcl_ListElem *pos, ClientData val); /* 18 */
+ void (*itcl_SetListValue) (Itcl_ListElem *elemPtr, ClientData val); /* 19 */
+ void (*itcl_EventuallyFree) (ClientData cdata, Tcl_FreeProc *fproc); /* 20 */
+ void (*itcl_PreserveData) (ClientData cdata); /* 21 */
+ void (*itcl_ReleaseData) (ClientData cdata); /* 22 */
+ Itcl_InterpState (*itcl_SaveInterpState) (Tcl_Interp *interp, int status); /* 23 */
+ int (*itcl_RestoreInterpState) (Tcl_Interp *interp, Itcl_InterpState state); /* 24 */
+ void (*itcl_DiscardInterpState) (Itcl_InterpState state); /* 25 */
+} ItclStubs;
+
+extern const ItclStubs *itclStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_ITCL_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+/* Slot 0 is reserved */
+/* Slot 1 is reserved */
+#define Itcl_RegisterC \
+ (itclStubsPtr->itcl_RegisterC) /* 2 */
+#define Itcl_RegisterObjC \
+ (itclStubsPtr->itcl_RegisterObjC) /* 3 */
+#define Itcl_FindC \
+ (itclStubsPtr->itcl_FindC) /* 4 */
+#define Itcl_InitStack \
+ (itclStubsPtr->itcl_InitStack) /* 5 */
+#define Itcl_DeleteStack \
+ (itclStubsPtr->itcl_DeleteStack) /* 6 */
+#define Itcl_PushStack \
+ (itclStubsPtr->itcl_PushStack) /* 7 */
+#define Itcl_PopStack \
+ (itclStubsPtr->itcl_PopStack) /* 8 */
+#define Itcl_PeekStack \
+ (itclStubsPtr->itcl_PeekStack) /* 9 */
+#define Itcl_GetStackValue \
+ (itclStubsPtr->itcl_GetStackValue) /* 10 */
+#define Itcl_InitList \
+ (itclStubsPtr->itcl_InitList) /* 11 */
+#define Itcl_DeleteList \
+ (itclStubsPtr->itcl_DeleteList) /* 12 */
+#define Itcl_CreateListElem \
+ (itclStubsPtr->itcl_CreateListElem) /* 13 */
+#define Itcl_DeleteListElem \
+ (itclStubsPtr->itcl_DeleteListElem) /* 14 */
+#define Itcl_InsertList \
+ (itclStubsPtr->itcl_InsertList) /* 15 */
+#define Itcl_InsertListElem \
+ (itclStubsPtr->itcl_InsertListElem) /* 16 */
+#define Itcl_AppendList \
+ (itclStubsPtr->itcl_AppendList) /* 17 */
+#define Itcl_AppendListElem \
+ (itclStubsPtr->itcl_AppendListElem) /* 18 */
+#define Itcl_SetListValue \
+ (itclStubsPtr->itcl_SetListValue) /* 19 */
+#define Itcl_EventuallyFree \
+ (itclStubsPtr->itcl_EventuallyFree) /* 20 */
+#define Itcl_PreserveData \
+ (itclStubsPtr->itcl_PreserveData) /* 21 */
+#define Itcl_ReleaseData \
+ (itclStubsPtr->itcl_ReleaseData) /* 22 */
+#define Itcl_SaveInterpState \
+ (itclStubsPtr->itcl_SaveInterpState) /* 23 */
+#define Itcl_RestoreInterpState \
+ (itclStubsPtr->itcl_RestoreInterpState) /* 24 */
+#define Itcl_DiscardInterpState \
+ (itclStubsPtr->itcl_DiscardInterpState) /* 25 */
+
+#endif /* defined(USE_ITCL_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#endif /* _ITCLDECLS */
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclEnsemble.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclEnsemble.c
new file mode 100644
index 0000000..1d5ac19
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclEnsemble.c
@@ -0,0 +1,2243 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This part handles ensembles, which support compound commands in Tcl.
+ * The usual "info" command is an ensemble with parts like "info body"
+ * and "info globals". Extension developers can extend commands like
+ * "info" by adding their own parts to the ensemble.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+#define ITCL_ENSEMBLE_CUSTOM 0x01
+#define ITCL_ENSEMBLE_ENSEMBLE 0x02
+
+/*
+ * Data used to represent an ensemble:
+ */
+struct Ensemble;
+typedef struct EnsemblePart {
+ char *name; /* name of this part */
+ Tcl_Obj *namePtr;
+ Tcl_Command cmdPtr; /* command handling this part */
+ char *usage; /* usage string describing syntax */
+ struct Ensemble* ensemble; /* ensemble containing this part */
+ ItclArgList *arglistPtr; /* the parsed argument list */
+ Tcl_ObjCmdProc *objProc; /* handling procedure for part */
+ ClientData *clientData; /* the procPtr for the part */
+ Tcl_CmdDeleteProc *deleteProc;
+ /* procedure used to destroy client data */
+ int minChars; /* chars needed to uniquely identify part */
+ int flags;
+ Tcl_Interp *interp;
+ Tcl_Obj *mapNamePtr;
+ Tcl_Obj *subEnsemblePtr;
+ Tcl_Obj *newMapDict;
+} EnsemblePart;
+
+#define ENSEMBLE_DELETE_STARTED 0x1
+#define ENSEMBLE_PART_DELETE_STARTED 0x2
+
+/*
+ * Data used to represent an ensemble:
+ */
+typedef struct Ensemble {
+ Tcl_Interp *interp; /* interpreter containing this ensemble */
+ EnsemblePart **parts; /* list of parts in this ensemble */
+ int numParts; /* number of parts in part list */
+ int maxParts; /* current size of parts list */
+ int ensembleId; /* this ensembles id */
+ Tcl_Command cmdPtr; /* command representing this ensemble */
+ EnsemblePart* parent; /* parent part for sub-ensembles
+ * NULL => toplevel ensemble */
+ Tcl_Namespace *nsPtr; /* namespace for ensemble part commands */
+ int flags;
+ Tcl_Obj *namePtr;
+} Ensemble;
+
+/*
+ * Data shared by ensemble access commands and ensemble parser:
+ */
+typedef struct EnsembleParser {
+ Tcl_Interp* master; /* master interp containing ensembles */
+ Tcl_Interp* parser; /* slave interp for parsing */
+ Ensemble* ensData; /* add parts to this ensemble */
+} EnsembleParser;
+
+static int EnsembleSubCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+static int EnsembleUnknownCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+
+/*
+ * Forward declarations for the procedures used in this file.
+ */
+static void GetEnsembleUsage (Tcl_Interp *interp,
+ Ensemble *ensData, Tcl_Obj *objPtr);
+static void GetEnsemblePartUsage (Tcl_Interp *interp,
+ Ensemble *ensData, EnsemblePart *ensPart, Tcl_Obj *objPtr);
+static int CreateEnsemble (Tcl_Interp *interp,
+ Ensemble *parentEnsData, const char *ensName);
+static int AddEnsemblePart (Tcl_Interp *interp,
+ Ensemble* ensData, const char* partName, const char* usageInfo,
+ Tcl_ObjCmdProc *objProc, ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc, int flags, EnsemblePart **rVal);
+static int FindEnsemble (Tcl_Interp *interp, const char **nameArgv,
+ int nameArgc, Ensemble** ensDataPtr);
+static int CreateEnsemblePart (Tcl_Interp *interp,
+ Ensemble *ensData, const char* partName, EnsemblePart **ensPartPtr);
+static void DeleteEnsemblePart (ClientData clientData);
+static int FindEnsemblePart (Tcl_Interp *interp,
+ Ensemble *ensData, const char* partName, EnsemblePart **rensPart);
+static void DeleteEnsemble(ClientData clientData);
+static int FindEnsemblePartIndex (Ensemble *ensData,
+ const char *partName, int *posPtr);
+static void ComputeMinChars (Ensemble *ensData, int pos);
+static EnsembleParser* GetEnsembleParser (Tcl_Interp *interp);
+static void DeleteEnsParser (ClientData clientData, Tcl_Interp* interp);
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_EnsembleInit --
+ *
+ * Called when any interpreter is created to make sure that
+ * things are properly set up for ensembles.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes
+ * wrong.
+ *
+ * Side effects:
+ * On the first call, the "ensemble" object type is registered
+ * with the Tcl compiler. If an error is encountered, an error
+ * is left as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+int
+Itcl_EnsembleInit(
+ Tcl_Interp *interp) /* interpreter being initialized */
+{
+ Tcl_DString buffer;
+ Tcl_InterpDeleteProc *procPtr;
+ ItclObjectInfo *infoPtr;
+
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ Tcl_CreateObjCommand(interp, "::itcl::ensemble",
+ Itcl_EnsembleCmd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_COMMANDS_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer, "::ensembles", -1);
+ infoPtr->ensembleInfo->ensembleNsPtr = Tcl_CreateNamespace(interp,
+ Tcl_DStringValue(&buffer), NULL, NULL);
+ Tcl_DStringFree(&buffer);
+ if (infoPtr->ensembleInfo->ensembleNsPtr == NULL) {
+ Tcl_AppendResult(interp, "error in creating namespace: ",
+ Tcl_DStringValue(&buffer), NULL);
+ return TCL_ERROR;
+ }
+ Tcl_CreateObjCommand(interp,
+ ITCL_COMMANDS_NAMESPACE "::ensembles::unknown",
+ EnsembleUnknownCmd, NULL, NULL);
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_CreateEnsemble --
+ *
+ * Creates an ensemble command, or adds a sub-ensemble to an
+ * existing ensemble command. The ensemble name is a space-
+ * separated list. The first word in the list is the command
+ * name for the top-level ensemble. Other names do not have
+ * commands associated with them; they are merely sub-ensembles
+ * within the ensemble. So a name like "a::b::foo bar baz"
+ * represents an ensemble command called "foo" in the namespace
+ * "a::b" that has a sub-ensemble "bar", that has a sub-ensemble
+ * "baz".
+ *
+ * If the name is a single word, then this procedure creates
+ * a top-level ensemble and installs an access command for it.
+ * If a command already exists with that name, it is deleted.
+ *
+ * If the name has more than one word, then the leading words
+ * are treated as a path name for an existing ensemble. The
+ * last word is treated as the name for a new sub-ensemble.
+ * If an part already exists with that name, it is an error.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes
+ * wrong.
+ *
+ * Side effects:
+ * If an error is encountered, an error is left as the result
+ * in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_CreateEnsemble(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ const char* ensName) /* name of the new ensemble */
+{
+ const char **nameArgv = NULL;
+ int nameArgc;
+ Ensemble *parentEnsData;
+
+ /*
+ * Split the ensemble name into its path components.
+ */
+ if (Tcl_SplitList(interp, (const char *)ensName, &nameArgc,
+ &nameArgv) != TCL_OK) {
+ goto ensCreateFail;
+ }
+ if (nameArgc < 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid ensemble name \"", ensName, "\"",
+ (char*)NULL);
+ goto ensCreateFail;
+ }
+
+ /*
+ * If there is more than one path component, then follow
+ * the path down to the last component, to find the containing
+ * ensemble.
+ */
+ parentEnsData = NULL;
+ if (nameArgc > 1) {
+ if (FindEnsemble(interp, nameArgv, nameArgc-1, &parentEnsData)
+ != TCL_OK) {
+ goto ensCreateFail;
+ }
+
+ if (parentEnsData == NULL) {
+ char *pname = Tcl_Merge(nameArgc-1, nameArgv);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid ensemble name \"", pname, "\"",
+ (char*)NULL);
+ ckfree(pname);
+ goto ensCreateFail;
+ }
+ }
+
+ /*
+ * Create the ensemble.
+ */
+ if (CreateEnsemble(interp, parentEnsData, nameArgv[nameArgc-1])
+ != TCL_OK) {
+ goto ensCreateFail;
+ }
+
+ ckfree((char*)nameArgv);
+ return TCL_OK;
+
+ensCreateFail:
+ if (nameArgv) {
+ ckfree((char*)nameArgv);
+ }
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while creating ensemble \"%s\")",
+ ensName));
+
+ return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_AddEnsemblePart --
+ *
+ * Adds a part to an ensemble which has been created by
+ * Itcl_CreateEnsemble. Ensembles are addressed by name, as
+ * described in Itcl_CreateEnsemble.
+ *
+ * If the ensemble already has a part with the specified name,
+ * this procedure returns an error. Otherwise, it adds a new
+ * part to the ensemble.
+ *
+ * Any client data specified is automatically passed to the
+ * handling procedure whenever the part is invoked. It is
+ * automatically destroyed by the deleteProc when the part is
+ * deleted.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes
+ * wrong.
+ *
+ * Side effects:
+ * If an error is encountered, an error is left as the result
+ * in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_AddEnsemblePart(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ const char* ensName, /* ensemble containing this part */
+ const char* partName, /* name of the new part */
+ const char* usageInfo, /* usage info for argument list */
+ Tcl_ObjCmdProc *objProc, /* handling procedure for part */
+ ClientData clientData, /* client data associated with part */
+ Tcl_CmdDeleteProc *deleteProc) /* procedure used to destroy client data */
+{
+ const char **nameArgv = NULL;
+ int nameArgc;
+ Ensemble *ensData;
+ EnsemblePart *ensPart;
+
+ /*
+ * Parse the ensemble name and look for a containing ensemble.
+ */
+ if (Tcl_SplitList(interp, (const char *)ensName, &nameArgc,
+ &nameArgv) != TCL_OK) {
+ goto ensPartFail;
+ }
+ if (FindEnsemble(interp, nameArgv, nameArgc, &ensData) != TCL_OK) {
+ goto ensPartFail;
+ }
+
+ if (ensData == NULL) {
+ char *pname = Tcl_Merge(nameArgc, nameArgv);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid ensemble name \"", pname, "\"",
+ (char*)NULL);
+ ckfree(pname);
+ goto ensPartFail;
+ }
+
+ /*
+ * Install the new part into the part list.
+ */
+ if (AddEnsemblePart(interp, ensData, partName, usageInfo,
+ objProc, clientData, deleteProc, ITCL_ENSEMBLE_CUSTOM,
+ &ensPart) != TCL_OK) {
+ goto ensPartFail;
+ }
+
+ ckfree((char*)nameArgv);
+ return TCL_OK;
+
+ensPartFail:
+ if (nameArgv) {
+ ckfree((char*)nameArgv);
+ }
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while adding to ensemble \"%s\")",
+ ensName));
+
+ return TCL_ERROR;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_GetEnsemblePart --
+ *
+ * Looks for a part within an ensemble, and returns information
+ * about it.
+ *
+ * Results:
+ * If the ensemble and its part are found, this procedure
+ * loads information about the part into the "infoPtr" structure
+ * and returns 1. Otherwise, it returns 0.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_GetEnsemblePart(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ const char *ensName, /* ensemble containing the part */
+ const char *partName, /* name of the desired part */
+ Tcl_CmdInfo *infoPtr) /* returns: info associated with part */
+{
+ const char **nameArgv = NULL;
+ int nameArgc;
+ Ensemble *ensData;
+ EnsemblePart *ensPart;
+ Itcl_InterpState state;
+
+ /*
+ * Parse the ensemble name and look for a containing ensemble.
+ * Save the interpreter state before we do this. If we get any
+ * errors, we don't want them to affect the interpreter.
+ */
+ state = Itcl_SaveInterpState(interp, TCL_OK);
+
+ if (Tcl_SplitList(interp, (const char *)ensName, &nameArgc,
+ &nameArgv) != TCL_OK) {
+ goto ensGetFail;
+ }
+ if (FindEnsemble(interp, nameArgv, nameArgc, &ensData) != TCL_OK) {
+ goto ensGetFail;
+ }
+ if (ensData == NULL) {
+ goto ensGetFail;
+ }
+
+ /*
+ * Look for a part with the desired name. If found, load
+ * its data into the "infoPtr" structure.
+ */
+ if (FindEnsemblePart(interp, ensData, partName, &ensPart)
+ != TCL_OK || ensPart == NULL) {
+ goto ensGetFail;
+ }
+
+ if (Tcl_GetCommandInfoFromToken(ensPart->cmdPtr, infoPtr) != 1) {
+ goto ensGetFail;
+ }
+
+ Itcl_DiscardInterpState(state);
+ ckfree((char *)nameArgv);
+ return 1;
+
+ensGetFail:
+ if (nameArgv) {
+ ckfree((char *)nameArgv);
+ }
+ Itcl_RestoreInterpState(interp, state);
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_IsEnsemble --
+ *
+ * Determines whether or not an existing command is an ensemble.
+ *
+ * Results:
+ * Returns non-zero if the command is an ensemble, and zero
+ * otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_IsEnsemble(
+ Tcl_CmdInfo* infoPtr) /* command info from Tcl_GetCommandInfo() */
+{
+ if (infoPtr) {
+/* FIXME use CMD and Tcl_IsEnsemble!! */
+ return (infoPtr->deleteProc == DeleteEnsemble);
+ }
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_GetEnsembleUsage --
+ *
+ * Returns a summary of all of the parts of an ensemble and
+ * the meaning of their arguments. Each part is listed on
+ * a separate line. Having this summary is sometimes useful
+ * when building error messages for the "@error" handler in
+ * an ensemble.
+ *
+ * Ensembles are accessed by name, as described in
+ * Itcl_CreateEnsemble.
+ *
+ * Results:
+ * If the ensemble is found, its usage information is appended
+ * onto the object "objPtr", and this procedure returns
+ * non-zero. It is the responsibility of the caller to
+ * initialize and free the object. If anything goes wrong,
+ * this procedure returns 0.
+ *
+ * Side effects:
+ * Object passed in is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_GetEnsembleUsage(
+ Tcl_Interp *interp, /* interpreter containing the ensemble */
+ const char *ensName, /* name of the ensemble */
+ Tcl_Obj *objPtr) /* returns: summary of usage info */
+{
+ const char **nameArgv = NULL;
+ int nameArgc;
+ Ensemble *ensData;
+ Itcl_InterpState state;
+
+ /*
+ * Parse the ensemble name and look for the ensemble.
+ * Save the interpreter state before we do this. If we get
+ * any errors, we don't want them to affect the interpreter.
+ */
+ state = Itcl_SaveInterpState(interp, TCL_OK);
+
+ if (Tcl_SplitList(interp, (const char *)ensName, &nameArgc,
+ &nameArgv) != TCL_OK) {
+ goto ensUsageFail;
+ }
+ if (FindEnsemble(interp, nameArgv, nameArgc, &ensData) != TCL_OK) {
+ goto ensUsageFail;
+ }
+ if (ensData == NULL) {
+ goto ensUsageFail;
+ }
+
+ /*
+ * Add a summary of usage information to the return buffer.
+ */
+ GetEnsembleUsage(interp, ensData, objPtr);
+
+ Itcl_DiscardInterpState(state);
+ ckfree((char *)nameArgv);
+ return 1;
+
+ensUsageFail:
+ if (nameArgv) {
+ ckfree((char *)nameArgv);
+ }
+ Itcl_RestoreInterpState(interp, state);
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_GetEnsembleUsageForObj --
+ *
+ * Returns a summary of all of the parts of an ensemble and
+ * the meaning of their arguments. This procedure is just
+ * like Itcl_GetEnsembleUsage, but it determines the desired
+ * ensemble from a command line argument. The argument should
+ * be the first argument on the command line--the ensemble
+ * command or one of its parts.
+ *
+ * Results:
+ * If the ensemble is found, its usage information is appended
+ * onto the object "objPtr", and this procedure returns
+ * non-zero. It is the responsibility of the caller to
+ * initialize and free the object. If anything goes wrong,
+ * this procedure returns 0.
+ *
+ * Side effects:
+ * Object passed in is modified.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_GetEnsembleUsageForObj(
+ Tcl_Interp *interp, /* interpreter containing the ensemble */
+ Tcl_Obj *ensObjPtr, /* argument representing ensemble */
+ Tcl_Obj *objPtr) /* returns: summary of usage info */
+{
+ Ensemble *ensData;
+ Tcl_Obj *chainObj;
+ Tcl_Command cmd;
+ Tcl_CmdInfo infoPtr;
+
+ /*
+ * If the argument is an ensemble part, then follow the chain
+ * back to the command word for the entire ensemble.
+ */
+ chainObj = ensObjPtr;
+
+ if (chainObj) {
+ cmd = Tcl_GetCommandFromObj(interp, chainObj);
+ if (Tcl_GetCommandInfoFromToken(cmd, &infoPtr) != 1) {
+ return 0;
+ }
+ if (infoPtr.deleteProc == DeleteEnsemble) {
+ ensData = (Ensemble*)infoPtr.objClientData;
+ GetEnsembleUsage(interp, ensData, objPtr);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEnsembleUsage --
+ *
+ *
+ * Returns a summary of all of the parts of an ensemble and
+ * the meaning of their arguments. Each part is listed on
+ * a separate line. This procedure is used internally to
+ * generate usage information for error messages.
+ *
+ * Results:
+ * Appends usage information onto the object in "objPtr".
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+GetEnsembleUsage(
+ Tcl_Interp *interp,
+ Ensemble *ensData, /* ensemble data */
+ Tcl_Obj *objPtr) /* returns: summary of usage info */
+{
+ const char *spaces = " ";
+ int isOpenEnded = 0;
+
+ int i;
+ EnsemblePart *ensPart;
+
+ for (i=0; i < ensData->numParts; i++) {
+ ensPart = ensData->parts[i];
+
+ if ((*ensPart->name == '@') && (strcmp(ensPart->name,"@error") == 0)) {
+ isOpenEnded = 1;
+ } else {
+ if ((*ensPart->name == '@') &&
+ (strcmp(ensPart->name,"@itcl-builtin_info") == 0)) {
+ /* the builtin info command is not reported in [incr tcl] */
+ continue;
+ }
+ Tcl_AppendToObj(objPtr, spaces, -1);
+ GetEnsemblePartUsage(interp, ensData, ensPart, objPtr);
+ spaces = "\n ";
+ }
+ }
+ if (isOpenEnded) {
+ Tcl_AppendToObj(objPtr,
+ "\n...and others described on the man page", -1);
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEnsemblePartUsage --
+ *
+ * Determines the usage for a single part within an ensemble,
+ * and appends a summary onto a dynamic string. The usage
+ * is a combination of the part name and the argument summary.
+ * It is the caller's responsibility to initialize and free
+ * the dynamic string.
+ *
+ * Results:
+ * Returns usage information in the object "objPtr".
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+GetEnsemblePartUsage(
+ Tcl_Interp *interp,
+ Ensemble *ensData,
+ EnsemblePart *ensPart, /* ensemble part for usage info */
+ Tcl_Obj *objPtr) /* returns: usage information */
+{
+ EnsemblePart *part;
+ Tcl_Command cmdPtr;
+ const char *name;
+ Itcl_List trail;
+ Itcl_ListElem *elem;
+ Tcl_DString buffer;
+
+ /*
+ * Build the trail of ensemble names leading to this part.
+ */
+ Tcl_DStringInit(&buffer);
+ Itcl_InitList(&trail);
+ for (part=ensPart; part; part=part->ensemble->parent) {
+ Itcl_InsertList(&trail, (ClientData)part);
+ }
+
+ while (ensData->parent != NULL) {
+ ensData = ensData->parent->ensemble;
+ }
+ cmdPtr = ensData->cmdPtr;
+ name = Tcl_GetCommandName(interp, cmdPtr);
+ Tcl_DStringAppendElement(&buffer, name);
+
+ for (elem=Itcl_FirstListElem(&trail); elem; elem=Itcl_NextListElem(elem)) {
+ part = (EnsemblePart*)Itcl_GetListValue(elem);
+ Tcl_DStringAppendElement(&buffer, part->name);
+ }
+ Itcl_DeleteList(&trail);
+
+ /*
+ * If the part has usage info, use it directly.
+ */
+ if (ensPart->usage && *ensPart->usage != '\0') {
+ Tcl_DStringAppend(&buffer, " ", 1);
+ Tcl_DStringAppend(&buffer, ensPart->usage, -1);
+ } else {
+
+ /*
+ * If the part is itself an ensemble, summarize its usage.
+ */
+ if (ensPart->cmdPtr != NULL) {
+ if (Tcl_IsEnsemble(ensPart->cmdPtr)) {
+ Tcl_DStringAppend(&buffer, " option ?arg arg ...?", 21);
+ }
+ }
+ }
+
+ Tcl_AppendToObj(objPtr, Tcl_DStringValue(&buffer),
+ Tcl_DStringLength(&buffer));
+
+ Tcl_DStringFree(&buffer);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateEnsemble --
+ *
+ * Creates an ensemble command, or adds a sub-ensemble to an
+ * existing ensemble command. Works like Itcl_CreateEnsemble,
+ * except that the ensemble name is a single name, not a path.
+ * If a parent ensemble is specified, then a new ensemble is
+ * added to that parent. If a part already exists with the
+ * same name, it is an error. If a parent ensemble is not
+ * specified, then a top-level ensemble is created. If a
+ * command already exists with the same name, it is deleted.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything goes
+ * wrong.
+ *
+ * Side effects:
+ * If an error is encountered, an error is left as the result
+ * in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+CreateEnsemble(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ Ensemble *parentEnsData, /* parent ensemble or NULL */
+ const char *ensName) /* name of the new ensemble */
+{
+ Tcl_Obj *objPtr;
+ Tcl_DString buffer;
+ Tcl_HashEntry *hPtr;
+ Tcl_InterpDeleteProc *procPtr;
+ Tcl_Obj *mapDict;
+ Tcl_Obj *toObjPtr;
+ ItclObjectInfo *infoPtr;
+ Ensemble *ensData;
+ EnsemblePart *ensPart;
+ int result;
+ int isNew;
+ char buf[20];
+ Tcl_Obj *unkObjPtr;
+
+ /*
+ * Create the data associated with the ensemble.
+ */
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ infoPtr->ensembleInfo->numEnsembles++;
+ ensData = (Ensemble*)ckalloc(sizeof(Ensemble));
+ memset(ensData, 0, sizeof(Ensemble));
+ ensData->namePtr = Tcl_NewStringObj(ensName, -1);
+ Tcl_IncrRefCount(ensData->namePtr);
+ ensData->interp = interp;
+ ensData->numParts = 0;
+ ensData->maxParts = 10;
+ ensData->ensembleId = infoPtr->ensembleInfo->numEnsembles;
+ ensData->parts = (EnsemblePart**)ckalloc(
+ (unsigned)(ensData->maxParts*sizeof(EnsemblePart*))
+ );
+ memset(ensData->parts, 0, ensData->maxParts*sizeof(EnsemblePart*));
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_COMMANDS_NAMESPACE "::ensembles::", -1);
+ sprintf(buf, "%d", ensData->ensembleId);
+ Tcl_DStringAppend(&buffer, buf, -1);
+ ensData->nsPtr = Tcl_CreateNamespace(interp, Tcl_DStringValue(&buffer),
+ ensData, DeleteEnsemble);
+ if (ensData->nsPtr == NULL) {
+ Tcl_AppendResult(interp, "error in creating namespace: ",
+ Tcl_DStringValue(&buffer), NULL);
+ result = TCL_ERROR;
+ goto finish;
+ }
+
+ /*
+ * If there is no parent data, then this is a top-level
+ * ensemble. Create the ensemble by installing its access
+ * command.
+ */
+ if (parentEnsData == NULL) {
+ Tcl_Obj *unkObjPtr;
+ ensData->cmdPtr = Tcl_CreateEnsemble(interp, ensName,
+ Tcl_GetCurrentNamespace(interp), TCL_ENSEMBLE_PREFIX);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->ensembleInfo->ensembles,
+ (char *)ensData->cmdPtr, &isNew);
+ if (!isNew) {
+ result = TCL_ERROR;
+ goto finish;
+ }
+ Tcl_SetHashValue(hPtr, (ClientData)ensData);
+ unkObjPtr = Tcl_NewStringObj(ITCL_COMMANDS_NAMESPACE, -1);
+ Tcl_AppendToObj(unkObjPtr, "::ensembles::unknown", -1);
+ if (Tcl_SetEnsembleUnknownHandler(NULL, ensData->cmdPtr,
+ unkObjPtr) != TCL_OK) {
+ Tcl_DecrRefCount(unkObjPtr);
+ result = TCL_ERROR;
+ goto finish;
+ }
+
+ Tcl_SetResult(interp, Tcl_DStringValue(&buffer), TCL_VOLATILE);
+ result = TCL_OK;
+ goto finish;
+ }
+
+ /*
+ * Otherwise, this ensemble is contained within another parent.
+ * Install the new ensemble as a part within its parent.
+ */
+ if (CreateEnsemblePart(interp, parentEnsData, ensName, &ensPart)
+ != TCL_OK) {
+ DeleteEnsemble((ClientData)ensData);
+ result = TCL_ERROR;
+ goto finish;
+ }
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, infoPtr->ensembleInfo->ensembleNsPtr->fullName, -1);
+ Tcl_DStringAppend(&buffer, "::subensembles::", -1);
+ sprintf(buf, "%d", parentEnsData->ensembleId);
+ Tcl_DStringAppend(&buffer, buf, -1);
+ Tcl_DStringAppend(&buffer, "::", 2);
+ Tcl_DStringAppend(&buffer, ensName, -1);
+ objPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->ensembleInfo->subEnsembles,
+ (char *)objPtr, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, ensData);
+ }
+
+ ensPart->subEnsemblePtr = objPtr;
+ Tcl_IncrRefCount(ensPart->subEnsemblePtr);
+ ensPart->cmdPtr = Tcl_CreateEnsemble(interp, Tcl_DStringValue(&buffer),
+ Tcl_GetCurrentNamespace(interp), TCL_ENSEMBLE_PREFIX);
+ hPtr = Tcl_CreateHashEntry(&infoPtr->ensembleInfo->ensembles,
+ (char *)ensPart->cmdPtr, &isNew);
+ if (!isNew) {
+ result = TCL_ERROR;
+ goto finish;
+ }
+ Tcl_SetHashValue(hPtr, (ClientData)ensData);
+ unkObjPtr = Tcl_NewStringObj(ITCL_COMMANDS_NAMESPACE, -1);
+ Tcl_AppendToObj(unkObjPtr, "::ensembles::unknown", -1);
+ if (Tcl_SetEnsembleUnknownHandler(NULL, ensPart->cmdPtr,
+ unkObjPtr) != TCL_OK) {
+ result = TCL_ERROR;
+ goto finish;
+ }
+
+ Tcl_GetEnsembleMappingDict(NULL, parentEnsData->cmdPtr, &mapDict);
+ if (mapDict == NULL) {
+ mapDict = Tcl_NewObj();
+ }
+ toObjPtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
+ Tcl_DictObjPut(NULL, mapDict, ensData->namePtr, toObjPtr);
+ Tcl_SetEnsembleMappingDict(NULL, parentEnsData->cmdPtr, mapDict);
+ ensData->cmdPtr = ensPart->cmdPtr;
+ ensData->parent = ensPart;
+ result = TCL_OK;
+
+finish:
+ Tcl_DStringFree(&buffer);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * AddEnsemblePart --
+ *
+ * Adds a part to an existing ensemble. Works like
+ * Itcl_AddEnsemblePart, but the part name is a single word,
+ * not a path.
+ *
+ * If the ensemble already has a part with the specified name,
+ * this procedure returns an error. Otherwise, it adds a new
+ * part to the ensemble.
+ *
+ * Any client data specified is automatically passed to the
+ * handling procedure whenever the part is invoked. It is
+ * automatically destroyed by the deleteProc when the part is
+ * deleted.
+ *
+ * Results:
+ * Returns TCL_OK if successful, along with a pointer to the
+ * new part. Returns TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * If an error is encountered, an error is left as the result
+ * in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+AddEnsemblePart(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ Ensemble* ensData, /* ensemble that will contain this part */
+ const char* partName, /* name of the new part */
+ const char* usageInfo, /* usage info for argument list */
+ Tcl_ObjCmdProc *objProc, /* handling procedure for part */
+ ClientData clientData, /* client data associated with part */
+ Tcl_CmdDeleteProc *deleteProc, /* procedure used to destroy client data */
+ int flags,
+ EnsemblePart **rVal) /* returns: new ensemble part */
+{
+ Tcl_Obj *mapDict;
+ Tcl_Command cmd;
+ EnsemblePart *ensPart;
+
+ /*
+ * Install the new part into the part list.
+ */
+ if (CreateEnsemblePart(interp, ensData, partName, &ensPart) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (usageInfo) {
+ ensPart->usage = ckalloc((unsigned)(strlen(usageInfo)+1));
+ strcpy(ensPart->usage, usageInfo);
+ }
+ ensPart->objProc = objProc;
+ ensPart->clientData = clientData;
+ ensPart->deleteProc = deleteProc;
+ ensPart->flags = flags;
+
+ mapDict = NULL;
+ Tcl_GetEnsembleMappingDict(NULL, ensData->cmdPtr, &mapDict);
+ if (mapDict == NULL) {
+ mapDict = Tcl_NewObj();
+ ensPart->newMapDict = mapDict;
+ }
+ ensPart->mapNamePtr = Tcl_NewStringObj(ensData->nsPtr->fullName, -1);
+ Tcl_AppendToObj(ensPart->mapNamePtr, "::", 2);
+ Tcl_AppendToObj(ensPart->mapNamePtr, partName, -1);
+ Tcl_IncrRefCount(ensPart->namePtr);
+ Tcl_IncrRefCount(ensPart->mapNamePtr);
+ Tcl_DictObjPut(NULL, mapDict, ensPart->namePtr, ensPart->mapNamePtr);
+ cmd = Tcl_CreateObjCommand(interp, Tcl_GetString(ensPart->mapNamePtr),
+ EnsembleSubCmd, ensPart, DeleteEnsemblePart);
+ if (cmd == NULL) {
+ Tcl_DictObjRemove(NULL, mapDict, ensPart->namePtr);
+ Tcl_DecrRefCount(ensPart->namePtr);
+ Tcl_DecrRefCount(ensPart->mapNamePtr);
+ return TCL_ERROR;
+ }
+ Tcl_SetEnsembleMappingDict(interp, ensData->cmdPtr, mapDict);
+ *rVal = ensPart;
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteEnsemble --
+ *
+ * Invoked when the command associated with an ensemble is
+ * destroyed, to delete the ensemble. Destroys all parts
+ * included in the ensemble, and frees all memory associated
+ * with it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+DeleteEnsemble(
+ ClientData clientData) /* ensemble data */
+{
+ FOREACH_HASH_DECLS;
+ ItclObjectInfo *infoPtr;
+ Ensemble* ensData;
+ Ensemble* ensData2;
+
+ ensData = (Ensemble*)clientData;
+ /* remove the unknown handler if set to release the Tcl_Obj of the name */
+ if (Tcl_FindCommand(ensData->interp, Tcl_GetString(ensData->namePtr),
+ NULL, 0) != NULL) {
+ Tcl_SetEnsembleUnknownHandler(NULL, ensData->cmdPtr, NULL);
+ }
+ /*
+ * BE CAREFUL: Each ensemble part removes itself from the list.
+ * So keep deleting the first part until all parts are gone.
+ */
+ while (ensData->numParts > 0) {
+ DeleteEnsemblePart(ensData->parts[0]);
+ }
+ Tcl_DecrRefCount(ensData->namePtr);
+ ckfree((char*)ensData->parts);
+ ensData->parts = NULL;
+ ensData->numParts = 0;
+ infoPtr = Tcl_GetAssocData(ensData->interp, ITCL_INTERP_DATA, NULL);
+ FOREACH_HASH_VALUE(ensData2, &infoPtr->ensembleInfo->ensembles) {
+ if (ensData2 == ensData) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ ckfree((char*)ensData);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindEnsemble --
+ *
+ * Searches for an ensemble command and follows a path to
+ * sub-ensembles.
+ *
+ * Results:
+ * Returns TCL_OK if the ensemble was found, along with a
+ * pointer to the ensemble data in "ensDataPtr". Returns
+ * TCL_ERROR if anything goes wrong.
+ *
+ * Side effects:
+ * If anything goes wrong, this procedure returns an error
+ * message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+FindEnsemble(
+ Tcl_Interp *interp, /* interpreter containing the ensemble */
+ const char **nameArgv, /* path of names leading to ensemble */
+ int nameArgc, /* number of strings in nameArgv */
+ Ensemble** ensDataPtr) /* returns: ensemble data */
+{
+ int i;
+ Tcl_Command cmdPtr;
+ Ensemble *ensData;
+ EnsemblePart *ensPart;
+ Tcl_Obj *objPtr;
+ Tcl_CmdInfo cmdInfo;
+ Tcl_InterpDeleteProc *procPtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+
+ *ensDataPtr = NULL; /* assume that no data will be found */
+
+ /*
+ * If there are no names in the path, then return an error.
+ */
+ if (nameArgc < 1) {
+ Tcl_AppendToObj(Tcl_GetObjResult(interp),
+ "invalid ensemble name \"\"", -1);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Use the first name to find the command for the top-level
+ * ensemble.
+ */
+ objPtr = Tcl_NewStringObj(nameArgv[0], -1);
+ cmdPtr = Tcl_FindEnsemble(interp, objPtr, 0);
+ Tcl_DecrRefCount(objPtr);
+
+ if (cmdPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "command \"", nameArgv[0], "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles, (char *)cmdPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "command \"", nameArgv[0], "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ ensData = (Ensemble *)Tcl_GetHashValue(hPtr);
+
+ /*
+ * Follow the trail of sub-ensemble names.
+ */
+ for (i=1; i < nameArgc; i++) {
+ if (FindEnsemblePart(interp, ensData, nameArgv[i], &ensPart)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ensPart == NULL) {
+ char *pname = Tcl_Merge(i, nameArgv);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid ensemble name \"", pname, "\"",
+ (char*)NULL);
+ ckfree(pname);
+ return TCL_ERROR;
+ }
+
+ cmdPtr = ensPart->cmdPtr;
+ if (cmdPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "part \"", nameArgv[i], "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (!Tcl_IsEnsemble(cmdPtr)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "part \"", nameArgv[i], "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_GetCommandInfoFromToken(cmdPtr, &cmdInfo) != 1) {
+ return TCL_ERROR;
+ }
+ ensData = (Ensemble*)cmdInfo.objClientData;
+ }
+ *ensDataPtr = ensData;
+
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * CreateEnsemblePart --
+ *
+ * Creates a new part within an ensemble.
+ *
+ * Results:
+ * If successful, this procedure returns TCL_OK, along with a
+ * pointer to the new part in "ensPartPtr". If a part with the
+ * same name already exists, this procedure returns TCL_ERROR.
+ *
+ * Side effects:
+ * If anything goes wrong, this procedure returns an error
+ * message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+CreateEnsemblePart(
+ Tcl_Interp *interp, /* interpreter containing the ensemble */
+ Ensemble *ensData, /* ensemble being modified */
+ const char* partName, /* name of the new part */
+ EnsemblePart **ensPartPtr) /* returns: new ensemble part */
+{
+ int i;
+ int pos;
+ int size;
+ EnsemblePart** partList;
+ EnsemblePart* ensPart;
+
+ /*
+ * If a matching entry was found, then return an error.
+ */
+ if (FindEnsemblePartIndex(ensData, partName, &pos)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "part \"", partName, "\" already exists in ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Otherwise, make room for a new entry. Keep the parts in
+ * lexicographical order, so we can search them quickly
+ * later.
+ */
+ if (ensData->numParts >= ensData->maxParts) {
+ size = ensData->maxParts*sizeof(EnsemblePart*);
+ partList = (EnsemblePart**)ckalloc((unsigned)2*size);
+ memcpy(partList, ensData->parts, (size_t)size);
+ ckfree((char*)ensData->parts);
+
+ ensData->parts = partList;
+ ensData->maxParts *= 2;
+ }
+
+ for (i=ensData->numParts; i > pos; i--) {
+ ensData->parts[i] = ensData->parts[i-1];
+ }
+ ensData->numParts++;
+
+ ensPart = (EnsemblePart*)ckalloc(sizeof(EnsemblePart));
+ memset(ensPart, 0, sizeof(EnsemblePart));
+ ensPart->name = (char*)ckalloc((unsigned)(strlen(partName)+1));
+ strcpy(ensPart->name, partName);
+ ensPart->namePtr = Tcl_NewStringObj(ensPart->name, -1);
+ ensPart->ensemble = ensData;
+ ensPart->interp = interp;
+
+ ensData->parts[pos] = ensPart;
+
+ /*
+ * Compare the new part against the one on either side of
+ * it. Determine how many letters are needed in each part
+ * to guarantee that an abbreviated form is unique. Update
+ * the parts on either side as well, since they are influenced
+ * by the new part.
+ */
+ ComputeMinChars(ensData, pos);
+ ComputeMinChars(ensData, pos-1);
+ ComputeMinChars(ensData, pos+1);
+
+ *ensPartPtr = ensPart;
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteEnsemblePart --
+ *
+ * Deletes a single part from an ensemble. The part must have
+ * been created previously by CreateEnsemblePart.
+ *
+ * If the part has a delete proc, then it is called to free the
+ * associated client data.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Delete proc is called.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+DeleteEnsemblePart(
+ ClientData clientData) /* part being destroyed */
+{
+ Tcl_Obj *mapDict;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ Ensemble *ensData;
+ Ensemble *ensData2;
+ EnsemblePart *ensPart;
+ int i;
+ int pos;
+
+ mapDict = NULL;
+ ensPart = (EnsemblePart *)clientData;
+ if (ensPart == NULL) {
+ return;
+ }
+ ensData = ensPart->ensemble;
+
+ /*
+ * If this part has a delete proc, then call it to free
+ * up the client data.
+ */
+ if ((ensPart->deleteProc != NULL) && (ensPart->clientData != NULL)) {
+ (*ensPart->deleteProc)(ensPart->clientData);
+ }
+
+ /* if it is a subensemble remove the command to free the data */
+ if (ensPart->subEnsemblePtr != NULL) {
+ infoPtr = Tcl_GetAssocData(ensData->interp, ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->subEnsembles,
+ (char *)ensPart->subEnsemblePtr);
+ if (hPtr != NULL) {
+ ensData2 = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteNamespace(ensData2->nsPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ Tcl_SetEnsembleUnknownHandler(NULL, ensPart->cmdPtr, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles,
+ (char *)ensPart->ensemble->cmdPtr);
+ if (hPtr != NULL) {
+ ensData2 = Tcl_GetHashValue(hPtr);
+ Tcl_GetEnsembleMappingDict(NULL, ensData2->cmdPtr, &mapDict);
+ if (mapDict != NULL) {
+ Tcl_DictObjRemove(ensPart->interp, mapDict,
+ ensPart->namePtr);
+ Tcl_SetEnsembleMappingDict(NULL, ensData2->cmdPtr, mapDict);
+ }
+ }
+ Tcl_DecrRefCount(ensPart->subEnsemblePtr);
+ if (ensPart->newMapDict != NULL) {
+ Tcl_DecrRefCount(ensPart->newMapDict);
+ }
+ }
+ /*
+ * Find this part within its ensemble, and remove it from
+ * the list of parts.
+ */
+ if (FindEnsemblePartIndex(ensPart->ensemble, ensPart->name, &pos)) {
+ ensData = ensPart->ensemble;
+ for (i=pos; i < ensData->numParts-1; i++) {
+ ensData->parts[i] = ensData->parts[i+1];
+ }
+ ensData->numParts--;
+ }
+
+ /*
+ * Free the memory associated with the part.
+ */
+ mapDict = NULL;
+ if (Tcl_FindCommand(ensData->interp, Tcl_GetString(ensData->namePtr),
+ NULL, 0) != NULL) {
+ Tcl_GetEnsembleMappingDict(ensData->interp, ensData->cmdPtr, &mapDict);
+ if (mapDict != NULL) {
+ if (!Tcl_IsShared(mapDict)) {
+ Tcl_DictObjRemove(ensPart->interp, mapDict, ensPart->namePtr);
+ Tcl_SetEnsembleMappingDict(ensPart->interp, ensData->cmdPtr,
+ mapDict);
+ }
+ }
+ }
+ /* this is the map !!! */
+ if (ensPart->mapNamePtr != NULL) {
+ Tcl_DecrRefCount(ensPart->mapNamePtr);
+ }
+ Tcl_DecrRefCount(ensPart->namePtr);
+ if (ensPart->usage != NULL) {
+ ckfree(ensPart->usage);
+ }
+ ckfree(ensPart->name);
+ ckfree((char*)ensPart);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindEnsemblePart --
+ *
+ * Searches for a part name within an ensemble. Recognizes
+ * unique abbreviations for part names.
+ *
+ * Results:
+ * If the part name is not a unique abbreviation, this procedure
+ * returns TCL_ERROR. Otherwise, it returns TCL_OK. If the
+ * part can be found, "rensPart" returns a pointer to the part.
+ * Otherwise, it returns NULL.
+ *
+ * Side effects:
+ * If anything goes wrong, this procedure returns an error
+ * message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+FindEnsemblePart(
+ Tcl_Interp *interp, /* interpreter containing the ensemble */
+ Ensemble *ensData, /* ensemble being searched */
+ const char* partName, /* name of the desired part */
+ EnsemblePart **rensPart) /* returns: pointer to the desired part */
+{
+ int pos = 0;
+ int first, last, nlen;
+ int i, cmp;
+
+ *rensPart = NULL;
+
+ /*
+ * Search for the desired part name.
+ * All parts are in lexicographical order, so use a
+ * binary search to find the part quickly. Match only
+ * as many characters as are included in the specified
+ * part name.
+ */
+ first = 0;
+ last = ensData->numParts-1;
+ nlen = strlen(partName);
+
+ while (last >= first) {
+ pos = (first+last)/2;
+ if (*partName == *ensData->parts[pos]->name) {
+ cmp = strncmp(partName, ensData->parts[pos]->name, nlen);
+ if (cmp == 0) {
+ break; /* found it! */
+ }
+ }
+ else if (*partName < *ensData->parts[pos]->name) {
+ cmp = -1;
+ }
+ else {
+ cmp = 1;
+ }
+
+ if (cmp > 0) {
+ first = pos+1;
+ } else {
+ last = pos-1;
+ }
+ }
+
+ /*
+ * If a matching entry could not be found, then quit.
+ */
+ if (last < first) {
+ return TCL_OK;
+ }
+
+ /*
+ * If a matching entry was found, there may be some ambiguity
+ * if the user did not specify enough characters. Find the
+ * top-most match in the list, and see if the part name has
+ * enough characters. If there are two parts like "foo"
+ * and "food", this allows us to match "foo" exactly.
+ */
+ if (nlen < ensData->parts[pos]->minChars) {
+ while (pos > 0) {
+ pos--;
+ if (strncmp(partName, ensData->parts[pos]->name, nlen) != 0) {
+ pos++;
+ break;
+ }
+ }
+ }
+ if (nlen < ensData->parts[pos]->minChars) {
+ Tcl_Obj *resultPtr = Tcl_NewStringObj((char*)NULL, 0);
+
+ Tcl_AppendStringsToObj(resultPtr,
+ "ambiguous option \"", partName, "\": should be one of...",
+ (char*)NULL);
+
+ for (i=pos; i < ensData->numParts; i++) {
+ if (strncmp(partName, ensData->parts[i]->name, nlen) != 0) {
+ break;
+ }
+ Tcl_AppendToObj(resultPtr, "\n ", 3);
+ GetEnsemblePartUsage(interp, ensData, ensData->parts[i], resultPtr);
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Found a match. Return the desired part.
+ */
+ *rensPart = ensData->parts[pos];
+ return TCL_OK;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * FindEnsemblePartIndex --
+ *
+ * Searches for a part name within an ensemble. The part name
+ * must be an exact match for an existing part name in the
+ * ensemble. This procedure is useful for managing (i.e.,
+ * creating and deleting) parts in an ensemble.
+ *
+ * Results:
+ * If an exact match is found, this procedure returns
+ * non-zero, along with the index of the part in posPtr.
+ * Otherwise, it returns zero, along with an index in posPtr
+ * indicating where the part should be.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+static int
+FindEnsemblePartIndex(
+ Ensemble *ensData, /* ensemble being searched */
+ const char *partName, /* name of desired part */
+ int *posPtr) /* returns: index for part */
+{
+ int pos = 0;
+ int first, last;
+ int cmp;
+
+ /*
+ * Search for the desired part name.
+ * All parts are in lexicographical order, so use a
+ * binary search to find the part quickly.
+ */
+ first = 0;
+ last = ensData->numParts-1;
+
+ while (last >= first) {
+ pos = (first+last)/2;
+ if (*partName == *ensData->parts[pos]->name) {
+ cmp = strcmp(partName, ensData->parts[pos]->name);
+ if (cmp == 0) {
+ break; /* found it! */
+ }
+ }
+ else if (*partName < *ensData->parts[pos]->name) {
+ cmp = -1;
+ }
+ else {
+ cmp = 1;
+ }
+
+ if (cmp > 0) {
+ first = pos+1;
+ } else {
+ last = pos-1;
+ }
+ }
+
+ if (last >= first) {
+ *posPtr = pos;
+ return 1;
+ }
+ *posPtr = first;
+ return 0;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * ComputeMinChars --
+ *
+ * Compares part names on an ensemble's part list and
+ * determines the minimum number of characters needed for a
+ * unique abbreviation. The parts on either side of a
+ * particular part index are compared. As long as there is
+ * a part on one side or the other, this procedure updates
+ * the parts to have the proper minimum abbreviations.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Updates three parts within the ensemble to remember
+ * the minimum abbreviations.
+ *
+ *----------------------------------------------------------------------
+ */
+static void
+ComputeMinChars(
+ Ensemble *ensData, /* ensemble being modified */
+ int pos) /* index of part being updated */
+{
+ int min, max;
+ char *p, *q;
+
+ /*
+ * If the position is invalid, do nothing.
+ */
+ if (pos < 0 || pos >= ensData->numParts) {
+ return;
+ }
+
+ /*
+ * Start by assuming that only the first letter is required
+ * to uniquely identify this part. Then compare the name
+ * against each neighboring part to determine the real minimum.
+ */
+ ensData->parts[pos]->minChars = 1;
+
+ if (pos-1 >= 0) {
+ p = ensData->parts[pos]->name;
+ q = ensData->parts[pos-1]->name;
+ for (min=1; *p == *q && *p != '\0' && *q != '\0'; min++) {
+ p++;
+ q++;
+ }
+ if (min > ensData->parts[pos]->minChars) {
+ ensData->parts[pos]->minChars = min;
+ }
+ }
+
+ if (pos+1 < ensData->numParts) {
+ p = ensData->parts[pos]->name;
+ q = ensData->parts[pos+1]->name;
+ for (min=1; *p == *q && *p != '\0' && *q != '\0'; min++) {
+ p++;
+ q++;
+ }
+ if (min > ensData->parts[pos]->minChars) {
+ ensData->parts[pos]->minChars = min;
+ }
+ }
+
+ max = strlen(ensData->parts[pos]->name);
+ if (ensData->parts[pos]->minChars > max) {
+ ensData->parts[pos]->minChars = max;
+ }
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_EnsembleCmd --
+ *
+ * Invoked by Tcl whenever the user issues the "ensemble"
+ * command to manipulate an ensemble. Handles the following
+ * syntax:
+ *
+ * ensemble <ensName> ?<command> <arg> <arg>...?
+ * ensemble <ensName> {
+ * part <partName> <args> <body>
+ * ensemble <ensName> {
+ * ...
+ * }
+ * }
+ *
+ * Finds or creates the ensemble <ensName>, and then executes
+ * the commands to add parts.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything
+ * goes wrong.
+ *
+ * Side effects:
+ * If anything goes wrong, this procedure returns an error
+ * message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_EnsembleCmd(
+ ClientData clientData, /* ensemble data */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int status;
+ char *ensName;
+ EnsembleParser *ensInfo;
+ Ensemble *ensData;
+ Ensemble *savedEnsData;
+ EnsemblePart *ensPart;
+ Tcl_Command cmd;
+ Tcl_Obj *objPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_InterpDeleteProc *procPtr;
+ ItclObjectInfo *infoPtr;
+
+ ItclShowArgs(1, "Itcl_EnsembleCmd", objc, objv);
+ /*
+ * Make sure that an ensemble name was specified.
+ */
+ if (objc < 2) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], (int*)NULL),
+ " name ?command arg arg...?\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this is the "ensemble" command in the main interpreter,
+ * then the client data will be null. Otherwise, it is
+ * the "ensemble" command in the ensemble body parser, and
+ * the client data indicates which ensemble we are modifying.
+ */
+ if (clientData) {
+ ensInfo = (EnsembleParser*)clientData;
+ } else {
+ ensInfo = GetEnsembleParser(interp);
+ }
+ ensData = ensInfo->ensData;
+
+ /*
+ * Find or create the desired ensemble. If an ensemble is
+ * being built, then this "ensemble" command is enclosed in
+ * another "ensemble" command. Use the current ensemble as
+ * the parent, and find or create an ensemble part within it.
+ */
+ ensName = Tcl_GetString(objv[1]);
+
+ if (ensData) {
+ if (FindEnsemblePart(ensInfo->master, ensData, ensName, &ensPart) != TCL_OK) {
+ ensPart = NULL;
+ }
+ if (ensPart == NULL) {
+ if (CreateEnsemble(ensInfo->master, ensData, ensName) != TCL_OK) {
+ Tcl_TransferResult(ensInfo->master, TCL_ERROR, interp);
+ return TCL_ERROR;
+ }
+ if (FindEnsemblePart(ensInfo->master, ensData, ensName, &ensPart)
+ != TCL_OK) {
+ Tcl_Panic("Itcl_EnsembleCmd: can't create ensemble");
+ }
+ }
+
+ cmd = ensPart->cmdPtr;
+ infoPtr = Tcl_GetAssocData(ensInfo->master, ITCL_INTERP_DATA, &procPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles,
+ (char *)ensPart->cmdPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "part \"", Tcl_GetStringFromObj(objv[1], (int*)NULL),
+ "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ ensData = (Ensemble *)Tcl_GetHashValue(hPtr);
+ } else {
+
+ /*
+ * Otherwise, the desired ensemble is a top-level ensemble.
+ * Find or create the access command for the ensemble, and
+ * then get its data.
+ */
+ cmd = Tcl_FindCommand(interp, ensName, (Tcl_Namespace*)NULL, 0);
+ if (cmd == NULL) {
+ if (CreateEnsemble(interp, (Ensemble*)NULL, ensName)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cmd = Tcl_FindCommand(interp, ensName, (Tcl_Namespace*)NULL, 0);
+ }
+
+ if (cmd == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "command \"", Tcl_GetStringFromObj(objv[1], (int*)NULL),
+ "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles, (char *)cmd);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "command \"", Tcl_GetStringFromObj(objv[1], (int*)NULL),
+ "\" is not an ensemble",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ ensData = (Ensemble *)Tcl_GetHashValue(hPtr);
+ }
+
+ /*
+ * At this point, we have the data for the ensemble that is
+ * being manipulated. Plug this into the parser, and then
+ * interpret the rest of the arguments in the ensemble parser.
+ */
+ status = TCL_OK;
+ savedEnsData = ensInfo->ensData;
+ ensInfo->ensData = ensData;
+
+ if (objc == 3) {
+ status = Tcl_EvalObjEx(ensInfo->parser, objv[2], 0);
+ } else {
+ if (objc > 3) {
+ objPtr = Tcl_NewListObj(objc-2, objv+2);
+ Tcl_IncrRefCount(objPtr); /* stop Eval trashing it */
+ status = Tcl_EvalObjEx(ensInfo->parser, objPtr, 0);
+ Tcl_DecrRefCount(objPtr); /* we're done with the object */
+ }
+ }
+
+ /*
+ * Copy the result from the parser interpreter to the
+ * master interpreter. If an error was encountered,
+ * copy the error info first, and then set the result.
+ * Otherwise, the offending command is reported twice.
+ */
+ if (status == TCL_ERROR) {
+ /* no longer needed, no extra interpreter !! */
+ const char *errInfo = Tcl_GetVar2(ensInfo->parser, "::errorInfo",
+ (char*)NULL, TCL_GLOBAL_ONLY);
+
+ if (errInfo) {
+ Tcl_AddObjErrorInfo(interp, (const char *)errInfo, -1);
+ }
+
+ if (objc == 3) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (\"ensemble\" body line %d)",
+ Tcl_GetErrorLine(ensInfo->parser)));
+ }
+ }
+ Tcl_SetObjResult(interp, Tcl_GetObjResult(ensInfo->parser));
+
+ ensInfo->ensData = savedEnsData;
+ return status;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * GetEnsembleParser --
+ *
+ * Returns the slave interpreter that acts as a parser for
+ * the body of an "ensemble" definition. The first time that
+ * this is called for an interpreter, the parser is created
+ * and registered as associated data. After that, it is
+ * simply returned.
+ *
+ * Results:
+ * Returns a pointer to the ensemble parser data structure.
+ *
+ * Side effects:
+ * On the first call, the ensemble parser is created and
+ * registered as "itcl_ensembleParser" with the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+static EnsembleParser*
+GetEnsembleParser(
+ Tcl_Interp *interp) /* interpreter handling the ensemble */
+{
+ EnsembleParser *ensInfo;
+
+ /*
+ * Look for an existing ensemble parser. If it is found,
+ * return it immediately.
+ */
+ ensInfo = (EnsembleParser*) Tcl_GetAssocData(interp,
+ "itcl_ensembleParser", NULL);
+
+ if (ensInfo) {
+ return ensInfo;
+ }
+
+ /*
+ * Create a slave interpreter that can be used to parse
+ * the body of an ensemble definition.
+ */
+ ensInfo = (EnsembleParser*)ckalloc(sizeof(EnsembleParser));
+ ensInfo->master = interp;
+ ensInfo->parser = Tcl_CreateInterp();
+ ensInfo->ensData = NULL;
+
+ Tcl_DeleteNamespace(Tcl_GetGlobalNamespace(ensInfo->parser));
+ /*
+ * Add the allowed commands to the parser interpreter:
+ * part, delete, ensemble
+ */
+ Tcl_CreateObjCommand(ensInfo->parser, "part", Itcl_EnsPartCmd,
+ (ClientData)ensInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(ensInfo->parser, "option", Itcl_EnsPartCmd,
+ (ClientData)ensInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(ensInfo->parser, "ensemble", Itcl_EnsembleCmd,
+ (ClientData)ensInfo, (Tcl_CmdDeleteProc*)NULL);
+
+ /*
+ * Install the parser data, so we'll have it the next time
+ * we call this procedure.
+ */
+ (void) Tcl_SetAssocData(interp, "itcl_ensembleParser",
+ DeleteEnsParser, (ClientData)ensInfo);
+
+ return ensInfo;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * DeleteEnsParser --
+ *
+ * Called when an interpreter is destroyed to clean up the
+ * ensemble parser within it. Destroys the slave interpreter
+ * and frees up the data associated with it.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+static void
+DeleteEnsParser(
+ ClientData clientData, /* client data for ensemble-related commands */
+ Tcl_Interp *interp) /* interpreter containing the data */
+{
+ EnsembleParser* ensInfo = (EnsembleParser*)clientData;
+ Tcl_DeleteInterp(ensInfo->parser);
+ ckfree((char*)ensInfo);
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_EnsPartCmd --
+ *
+ * Invoked by Tcl whenever the user issues the "part" command
+ * to manipulate an ensemble. This command can only be used
+ * inside the "ensemble" command, which handles ensembles.
+ * Handles the following syntax:
+ *
+ * ensemble <ensName> {
+ * part <partName> <args> <body>
+ * }
+ *
+ * Adds a new part called <partName> to the ensemble. If a
+ * part already exists with that name, it is an error. The
+ * new part is handled just like an ordinary Tcl proc, with
+ * a list of <args> and a <body> of code to execute.
+ *
+ * Results:
+ * Returns TCL_OK if successful, and TCL_ERROR if anything
+ * goes wrong.
+ *
+ * Side effects:
+ * If anything goes wrong, this procedure returns an error
+ * message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_EnsPartCmd(
+ ClientData clientData, /* ensemble data */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *usagePtr;
+ Tcl_Proc procPtr;
+ EnsembleParser *ensInfo = (EnsembleParser*)clientData;
+ Ensemble *ensData = (Ensemble*)ensInfo->ensData;
+ EnsemblePart *ensPart;
+ ItclArgList *arglistPtr;
+ char *partName;
+ char *usage;
+ int result;
+ int argc;
+ int maxArgc;
+ Tcl_CmdInfo cmdInfo;
+
+ ItclShowArgs(1, "Itcl_EnsPartCmd", objc, objv);
+ if (objc != 4) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], (int*)NULL),
+ " name args body\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create a Tcl-style proc definition using the specified args
+ * and body. This is not a proc in the usual sense. It belongs
+ * to the namespace that contains the ensemble, but it is
+ * accessed through the ensemble, not through a Tcl command.
+ */
+ partName = Tcl_GetStringFromObj(objv[1], (int*)NULL);
+
+ if (ItclCreateArgList(interp, Tcl_GetString(objv[2]), &argc, &maxArgc,
+ &usagePtr, &arglistPtr, NULL, partName) != TCL_OK) {
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if (Tcl_GetCommandInfoFromToken(ensData->cmdPtr, &cmdInfo) != 1) {
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if (Tcl_CreateProc(ensInfo->master, cmdInfo.namespacePtr, partName, objv[2], objv[3],
+ &procPtr) != TCL_OK) {
+ Tcl_TransferResult(ensInfo->master, TCL_ERROR, interp);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+
+ usage = Tcl_GetString(usagePtr);
+
+ /*
+ * Create a new part within the ensemble. If successful,
+ * plug the command token into the proc; we'll need it later
+ * if we try to compile the Tcl code for the part. If
+ * anything goes wrong, clean up before bailing out.
+ */
+ result = AddEnsemblePart(ensInfo->master, ensData, partName, usage,
+ Tcl_GetObjInterpProc(), (ClientData)procPtr, _Tcl_ProcDeleteProc,
+ ITCL_ENSEMBLE_ENSEMBLE, &ensPart);
+ Tcl_TransferResult(ensInfo->master, result, interp);
+
+errorOut:
+ Tcl_DecrRefCount(usagePtr);
+ ItclDeleteArgList(arglistPtr);
+ return result;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_EnsembleErrorCmd --
+ *
+ * Invoked when the user tries to access an unknown part for
+ * an ensemble. Acts as the default handler for the "@error"
+ * part. Generates an error message like:
+ *
+ * bad option "foo": should be one of...
+ * info args procname
+ * info body procname
+ * info cmdcount
+ * ...
+ *
+ * Results:
+ * Always returns TCL_OK.
+ *
+ * Side effects:
+ * Returns the error message as the result in the interpreter.
+ *
+ *----------------------------------------------------------------------
+ */
+ /* ARGSUSED */
+int
+Itcl_EnsembleErrorCmd(
+ ClientData clientData, /* ensemble info */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Ensemble *ensData = (Ensemble*)clientData;
+
+ char *cmdName;
+ Tcl_Obj *objPtr;
+
+ cmdName = Tcl_GetString(objv[0]);
+
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_AppendStringsToObj(objPtr,
+ "bad option \"", cmdName, "\": should be one of...\n",
+ (char*)NULL);
+ GetEnsembleUsage(interp, ensData, objPtr);
+
+ Tcl_SetResult(interp, Tcl_GetString(objPtr), TCL_VOLATILE);
+ Tcl_DecrRefCount(objPtr);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * EnsembleSubCmd --
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+CallInvokeEnsembleMethod(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Namespace *nsPtr = data[0];
+ EnsemblePart *ensPart = data[1];
+ int objc = PTR2INT(data[2]);
+ Tcl_Obj *const*objv = data[3];
+
+ result = Itcl_InvokeEnsembleMethod(interp, nsPtr, ensPart->namePtr,
+ (Tcl_Proc *)ensPart->clientData, objc, objv);
+ return result;
+}
+
+static int
+CallInvokeEnsembleMethod2(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ EnsemblePart *ensPart = data[0];
+ int objc = PTR2INT(data[1]);
+ Tcl_Obj *const*objv = data[2];
+ result = (*ensPart->objProc)(ensPart->clientData, interp, objc, objv);
+ return result;
+}
+
+static int
+EnsembleSubCmd(
+ ClientData clientData, /* ensPart struct pointer */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int result;
+ Tcl_Namespace *nsPtr;
+ EnsemblePart *ensPart;
+ void *callbackPtr;
+
+ ItclShowArgs(1, "EnsembleSubCmd", objc, objv);
+ result = TCL_OK;
+ ensPart = (EnsemblePart *)clientData;
+ nsPtr = Tcl_GetCurrentNamespace(interp);
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ if (ensPart->flags & ITCL_ENSEMBLE_ENSEMBLE) {
+ /* FIXME !!! */
+ if (ensPart->clientData == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_NRAddCallback(interp, CallInvokeEnsembleMethod, nsPtr, ensPart, INT2PTR(objc), (ClientData)objv);
+ } else {
+ Tcl_NRAddCallback(interp, CallInvokeEnsembleMethod2, ensPart, INT2PTR(objc), (ClientData)objv, NULL);
+ }
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * EnsembleUnknownCmd()
+ *
+ * the unknown handler for the ensemble commands
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+EnsembleUnknownCmd(
+ ClientData dummy, /* not used */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Command cmd;
+ Tcl_HashEntry *hPtr;
+ Tcl_InterpDeleteProc *procPtr;
+ ItclObjectInfo *infoPtr;
+ EnsemblePart *ensPart;
+ Ensemble *ensData;
+
+ ItclShowArgs(2, "EnsembleUnknownCmd", objc, objv);
+ cmd = Tcl_GetCommandFromObj(interp, objv[1]);
+ if (cmd == NULL) {
+ Tcl_AppendResult(interp, "EnsembleUnknownCmd, ensemble not found!",
+ Tcl_GetString(objv[1]), NULL);
+ return TCL_ERROR;
+ }
+ infoPtr = Tcl_GetAssocData(interp, ITCL_INTERP_DATA, &procPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles, (char *)cmd);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "EnsembleUnknownCmd, ensemble struct not ",
+ "found!", Tcl_GetString(objv[1]), NULL);
+ return TCL_ERROR;
+ }
+ ensData = (Ensemble *)Tcl_GetHashValue(hPtr);
+ if (objc < 3) {
+ /* produce usage message */
+ Tcl_Obj *objPtr = Tcl_NewStringObj(
+ "wrong # args: should be one of...\n", -1);
+ GetEnsembleUsage(interp, ensData, objPtr);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+ if (FindEnsemblePart(interp, ensData, "@error", &ensPart) != TCL_OK) {
+ Tcl_AppendResult(interp, "FindEnsemblePart error", NULL);
+ return TCL_ERROR;
+ }
+ if (ensPart != NULL) {
+ Tcl_Obj *listPtr;
+
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_ListObjAppendElement(NULL, listPtr, objv[1]);
+ Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj("@error", -1));
+ Tcl_ListObjAppendElement(NULL, listPtr, objv[2]);
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+
+ return Itcl_EnsembleErrorCmd(ensData, interp, objc-2, objv+2);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_EnsembleDeleteCmd --
+ *
+ * Invoked when the user tries to delet an ensemble
+ *----------------------------------------------------------------------
+ */
+int
+Itcl_EnsembleDeleteCmd(
+ ClientData clientData, /* infoPtr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Command cmdPtr;
+ Ensemble *ensData;
+ ItclObjectInfo *infoPtr;
+ int i;
+
+ infoPtr = (ItclObjectInfo *)clientData;
+ ItclShowArgs(1, "Itcl_EnsembleDeleteCmd", objc, objv);
+ for (i = 1; i < objc; i++) {
+ cmdPtr = Tcl_FindCommand(interp, Tcl_GetString(objv[i]), NULL, 0);
+ if (cmdPtr == NULL) {
+ Tcl_AppendResult(interp, "no such ensemble \"",
+ Tcl_GetString(objv[i]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->ensembleInfo->ensembles, (char *)cmdPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "no such ensemble \"",
+ Tcl_GetString(objv[i]), "\"", NULL);
+ return TCL_ERROR;
+ }
+ ensData = Tcl_GetHashValue(hPtr);
+ Itcl_RenameCommand(ensData->interp, Tcl_GetString(ensData->namePtr), "");
+ if (Tcl_FindNamespace(interp, ensData->nsPtr->fullName, NULL, 0)
+ != NULL) {
+ Tcl_DeleteNamespace(ensData->nsPtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_FinishEnsemble --
+ *
+ * Invoked when itcl package is finished or ItclFinishCmd is called
+ *----------------------------------------------------------------------
+ */
+void
+ItclFinishEnsemble(
+ ItclObjectInfo *infoPtr)
+{
+ EnsembleParser *ensInfo;
+
+ ensInfo = (EnsembleParser*) Tcl_GetAssocData(infoPtr->interp,
+ "itcl_ensembleParser", NULL);
+ ckfree((char *)ensInfo);
+ /* FIXME have to cleanup contents of infoPtr->ensembleInfo */
+ ckfree((char *)infoPtr->ensembleInfo);
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclHelpers.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclHelpers.c
new file mode 100644
index 0000000..a3f136b
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclHelpers.c
@@ -0,0 +1,1510 @@
+/*
+ * itclHelpers.c --
+ *
+ * This file contains the C-implemeted part of
+ * Itcl
+ *
+ * Copyright (c) 2007 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "itclInt.h"
+
+void ItclDeleteArgList(ItclArgList *arglistPtr);
+#ifdef ITCL_DEBUG
+int _itcl_debug_level = 0;
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclShowArgs()
+ * ------------------------------------------------------------------------
+ */
+
+void
+ItclShowArgs(
+ int level,
+ const char *str,
+ int objc,
+ Tcl_Obj * const* objv)
+{
+ int i;
+
+ if (level > _itcl_debug_level) {
+ return;
+ }
+ fprintf(stderr, "%s", str);
+ for (i = 0; i < objc; i++) {
+ fprintf(stderr, "!%s", objv[i] == NULL ? "??" :
+ Tcl_GetString(objv[i]));
+ }
+ fprintf(stderr, "!\n");
+}
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ProtectionStr()
+ *
+ * Converts an integer protection code (ITCL_PUBLIC, ITCL_PROTECTED,
+ * or ITCL_PRIVATE) into a human-readable character string. Returns
+ * a pointer to this string.
+ * ------------------------------------------------------------------------
+ */
+const char*
+Itcl_ProtectionStr(
+ int pLevel) /* protection level */
+{
+ switch (pLevel) {
+ case ITCL_PUBLIC:
+ return "public";
+ case ITCL_PROTECTED:
+ return "protected";
+ case ITCL_PRIVATE:
+ return "private";
+ }
+ return "<bad-protection-code>";
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateArgList()
+ * ------------------------------------------------------------------------
+ */
+
+int
+ItclCreateArgList(
+ Tcl_Interp *interp, /* interpreter managing this function */
+ const char *str, /* string representing argument list */
+ int *argcPtr, /* number of mandatory arguments */
+ int *maxArgcPtr, /* number of arguments parsed */
+ Tcl_Obj **usagePtr, /* store usage message for arguments here */
+ ItclArgList **arglistPtrPtr,
+ /* returns pointer to parsed argument list */
+ ItclMemberFunc *mPtr,
+ const char *commandName)
+{
+ int argc;
+ int defaultArgc;
+ const char **argv;
+ const char **defaultArgv;
+ ItclArgList *arglistPtr;
+ ItclArgList *lastArglistPtr;
+ int i;
+ int hadArgsArgument;
+ int result;
+
+ *arglistPtrPtr = NULL;
+ lastArglistPtr = NULL;
+ argc = 0;
+ hadArgsArgument = 0;
+ result = TCL_OK;
+ *maxArgcPtr = 0;
+ *argcPtr = 0;
+ *usagePtr = Tcl_NewStringObj("", -1);
+ if (str) {
+ if (Tcl_SplitList(interp, (const char *)str, &argc, &argv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ i = 0;
+ if (argc == 0) {
+ /* signal there are 0 arguments */
+ arglistPtr = (ItclArgList *)ckalloc(sizeof(ItclArgList));
+ memset(arglistPtr, 0, sizeof(ItclArgList));
+ *arglistPtrPtr = arglistPtr;
+ }
+ while (i < argc) {
+ if (Tcl_SplitList(interp, argv[i], &defaultArgc, &defaultArgv)
+ != TCL_OK) {
+ result = TCL_ERROR;
+ break;
+ }
+ arglistPtr = NULL;
+ if (defaultArgc == 0 || defaultArgv[0][0] == '\0') {
+ if (commandName != NULL) {
+ Tcl_AppendResult(interp, "procedure \"",
+ commandName,
+ "\" has argument with no name", NULL);
+ } else {
+ char buf[10];
+ sprintf(buf, "%d", i);
+ Tcl_AppendResult(interp, "argument #", buf,
+ " has no name", NULL);
+ }
+ result = TCL_ERROR;
+ break;
+ }
+ if (defaultArgc > 2) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "too many fields in argument specifier \"",
+ argv[i], "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ break;
+ }
+ if (strstr(defaultArgv[0],"::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad argument name \"", defaultArgv[0], "\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ break;
+ }
+ arglistPtr = (ItclArgList *)ckalloc(sizeof(ItclArgList));
+ memset(arglistPtr, 0, sizeof(ItclArgList));
+ if (*arglistPtrPtr == NULL) {
+ *arglistPtrPtr = arglistPtr;
+ } else {
+ lastArglistPtr->nextPtr = arglistPtr;
+ Tcl_AppendToObj(*usagePtr, " ", 1);
+ }
+ arglistPtr->namePtr =
+ Tcl_NewStringObj(defaultArgv[0], -1);
+ Tcl_IncrRefCount(arglistPtr->namePtr);
+ (*maxArgcPtr)++;
+ if (defaultArgc == 1) {
+ (*argcPtr)++;
+ arglistPtr->defaultValuePtr = NULL;
+ if ((strcmp(defaultArgv[0], "args") == 0) && (i == argc-1)) {
+ hadArgsArgument = 1;
+ (*argcPtr)--;
+ Tcl_AppendToObj(*usagePtr, "?arg arg ...?", -1);
+ } else {
+ Tcl_AppendToObj(*usagePtr, defaultArgv[0], -1);
+ }
+ } else {
+ arglistPtr->defaultValuePtr =
+ Tcl_NewStringObj(defaultArgv[1], -1);
+ Tcl_IncrRefCount(arglistPtr->defaultValuePtr);
+ Tcl_AppendToObj(*usagePtr, "?", 1);
+ Tcl_AppendToObj(*usagePtr, defaultArgv[0], -1);
+ Tcl_AppendToObj(*usagePtr, "?", 1);
+ }
+ lastArglistPtr = arglistPtr;
+ i++;
+ ckfree((char *) defaultArgv);
+ }
+ ckfree((char *) argv);
+ }
+ /*
+ * If anything went wrong, destroy whatever arguments were
+ * created and return an error.
+ */
+ if (result != TCL_OK) {
+ ItclDeleteArgList(*arglistPtrPtr);
+ *arglistPtrPtr = NULL;
+ }
+ if (hadArgsArgument) {
+ *maxArgcPtr = -1;
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteArgList()
+ * ------------------------------------------------------------------------
+ */
+
+void
+ItclDeleteArgList(
+ ItclArgList *arglistPtr) /* first argument in arg list chain */
+{
+ ItclArgList *currPtr;
+ ItclArgList *nextPtr;
+
+ for (currPtr=arglistPtr; currPtr; currPtr=nextPtr) {
+ if (currPtr->defaultValuePtr != NULL) {
+ Tcl_DecrRefCount(currPtr->defaultValuePtr);
+ }
+ if (currPtr->namePtr != NULL) {
+ Tcl_DecrRefCount(currPtr->namePtr);
+ }
+ nextPtr = currPtr->nextPtr;
+ ckfree((char *)currPtr);
+ }
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_EvalArgs()
+ *
+ * This procedure invokes a list of (objc,objv) arguments as a
+ * single command. It is similar to Tcl_EvalObj, but it doesn't
+ * do any parsing or compilation. It simply treats the first
+ * argument as a command and invokes that command in the current
+ * context.
+ *
+ * Returns TCL_OK if successful. Otherwise, this procedure returns
+ * TCL_ERROR along with an error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_EvalArgs(
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result;
+ Tcl_Command cmd;
+ int cmdlinec;
+ Tcl_Obj **cmdlinev;
+ Tcl_Obj *cmdlinePtr = NULL;
+ Tcl_CmdInfo infoPtr;
+
+ /*
+ * Resolve the command by converting it to a CmdName object.
+ * This caches a pointer to the Command structure for the
+ * command, so if we need it again, it's ready to use.
+ */
+ cmd = Tcl_GetCommandFromObj(interp, objv[0]);
+
+ cmdlinec = objc;
+ cmdlinev = (Tcl_Obj **) objv;
+
+ /*
+ * If the command is still not found, handle it with the
+ * "unknown" proc.
+ */
+ if (cmd == NULL) {
+ cmd = Tcl_FindCommand(interp, "unknown",
+ (Tcl_Namespace *) NULL, /*flags*/ TCL_GLOBAL_ONLY);
+
+ if (cmd == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid command name \"",
+ Tcl_GetStringFromObj(objv[0], NULL), "\"", NULL);
+ return TCL_ERROR;
+ }
+
+ cmdlinePtr = Itcl_CreateArgs(interp, "unknown", objc, objv);
+ Tcl_ListObjGetElements(NULL, cmdlinePtr, &cmdlinec, &cmdlinev);
+ }
+
+ /*
+ * Finally, invoke the command's Tcl_ObjCmdProc. Be careful
+ * to pass in the proper client data.
+ */
+ Tcl_ResetResult(interp);
+ result = Tcl_GetCommandInfoFromToken(cmd, &infoPtr);
+ if (result == 1) {
+ result = (infoPtr.objProc)(infoPtr.objClientData, interp,
+ cmdlinec, cmdlinev);
+ }
+
+ if (cmdlinePtr) {
+ Tcl_DecrRefCount(cmdlinePtr);
+ }
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateArgs()
+ *
+ * This procedure takes a string and a list of (objc,objv) arguments,
+ * and glues them together in a single list. This is useful when
+ * a command word needs to be prepended or substituted into a command
+ * line before it is executed. The arguments are returned in a single
+ * list object, and they can be retrieved by calling
+ * Tcl_ListObjGetElements. When the arguments are no longer needed,
+ * they should be discarded by decrementing the reference count for
+ * the list object.
+ *
+ * Returns a pointer to the list object containing the arguments.
+ * ------------------------------------------------------------------------
+ */
+Tcl_Obj*
+Itcl_CreateArgs(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *string, /* first command word */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int i;
+ Tcl_Obj *listPtr;
+
+ ItclShowArgs(1, "Itcl_CreateArgs", objc, objv);
+ listPtr = Tcl_NewListObj(objc+2, NULL);
+ Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj("my", -1));
+ Tcl_ListObjAppendElement(NULL, listPtr, Tcl_NewStringObj(string, -1));
+
+ for (i=0; i < objc; i++) {
+ Tcl_ListObjAppendElement(NULL, listPtr, objv[i]);
+ }
+ return listPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclEnsembleSubCmd()
+ * ------------------------------------------------------------------------
+ */
+
+int
+ItclEnsembleSubCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *ensembleName,
+ int objc,
+ Tcl_Obj *const *objv,
+ const char *functionName)
+{
+ int result;
+ Tcl_Obj **newObjv;
+ int isRootEnsemble;
+ ItclShowArgs(2, functionName, objc, objv);
+
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc));
+ isRootEnsemble = Itcl_InitRewriteEnsemble(interp, 1, 1, objc, objv);
+ newObjv[0] = Tcl_NewStringObj("::itcl::builtin::Info", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ if (objc > 1) {
+ memcpy(newObjv+1, objv+1, sizeof(Tcl_Obj *) * (objc-1));
+ }
+ result = Tcl_EvalObjv(interp, objc, newObjv, TCL_EVAL_INVOKE);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ Itcl_ResetRewriteEnsemble(interp, isRootEnsemble);
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCapitalize()
+ * ------------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+ItclCapitalize(
+ const char *str)
+{
+ Tcl_Obj *objPtr;
+ char buf[2];
+
+ sprintf(buf, "%c", toupper(UCHAR(*str)));
+ buf[1] = '\0';
+ objPtr = Tcl_NewStringObj(buf, -1);
+ Tcl_AppendToObj(objPtr, str+1, -1);
+ return objPtr;
+}
+/*
+ * ------------------------------------------------------------------------
+ * DeleteClassDictInfo()
+ * ------------------------------------------------------------------------
+ */
+static int
+DeleteClassDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ const char *varName)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+
+ dictPtr = Tcl_GetVar2Ex(interp, varName, NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", varName, NULL);
+ return TCL_ERROR;
+ }
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjRemove(interp, dictPtr, keyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetVar2Ex(interp, varName, NULL, dictPtr, 0);
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * AddDictEntry()
+ * ------------------------------------------------------------------------
+ */
+static int
+AddDictEntry(
+ Tcl_Interp *interp,
+ Tcl_Obj *dictPtr,
+ const char *keyStr,
+ Tcl_Obj *valuePtr)
+{
+ Tcl_Obj *keyPtr;
+
+ if (valuePtr == NULL) {
+ return TCL_OK;
+ }
+ keyPtr = Tcl_NewStringObj(keyStr, -1);
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr) != TCL_OK) {
+ Tcl_DecrRefCount(keyPtr);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddClassesDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddClassesDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *keyPtr1;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ FOREACH_HASH_DECLS;
+ ItclHierIter hier;
+ ItclClass *iclsPtr2;
+ void *value;
+ int found;
+ int newValue1;
+ int haveHierarchy;
+
+ found = 0;
+ FOREACH_HASH(keyPtr1, value, &iclsPtr->infoPtr->classTypes) {
+ if (iclsPtr->flags & PTR2INT(value)) {
+ found = 1;
+ break;
+ }
+ }
+ if (! found) {
+ Tcl_AppendResult(interp, "ItclAddClassesDictInfo bad class ",
+ "type for class \"", Tcl_GetString(iclsPtr->fullNamePtr),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classes", NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classes", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr1, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ newValue1 = 1;
+ valuePtr1 = Tcl_NewDictObj();
+ }
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 != NULL) {
+ if (Tcl_DictObjRemove(interp, valuePtr1, keyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ valuePtr2 = Tcl_NewDictObj();
+ if (AddDictEntry(interp, valuePtr2, "-name", iclsPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-fullname", iclsPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ haveHierarchy = 0;
+ listPtr = Tcl_NewListObj(0, NULL);
+ while (iclsPtr2 != NULL) {
+ haveHierarchy = 1;
+ if (Tcl_ListObjAppendElement(interp, listPtr, iclsPtr2->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+ if (haveHierarchy) {
+ if (AddDictEntry(interp, valuePtr2, "-heritage", listPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (iclsPtr->widgetClassPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-widget", iclsPtr->widgetClassPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (iclsPtr->hullTypePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-hulltype", iclsPtr->hullTypePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (iclsPtr->typeConstructorPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-typeconstructor",
+ iclsPtr->typeConstructorPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr1, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp, ITCL_NAMESPACE"::internal::dicts::classes",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteClassesDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclDeleteClassesDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr;
+ FOREACH_HASH_DECLS;
+ void* value;
+ int found;
+
+ found = 0;
+ FOREACH_HASH(keyPtr, value, &iclsPtr->infoPtr->classTypes) {
+ if (iclsPtr->flags & PTR2INT(value)) {
+ found = 1;
+ break;
+ }
+ }
+ if (! found) {
+ Tcl_AppendResult(interp, "ItclDeleteClassesDictInfo bad class ",
+ "type for class \"", Tcl_GetString(iclsPtr->fullNamePtr),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classes", NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classes", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr == NULL) {
+ /* there seems to have been an error during construction
+ * and no class has been created so ignore silently */
+ return TCL_OK;
+ }
+ if (Tcl_DictObjRemove(interp, valuePtr, iclsPtr->fullNamePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetVar2Ex(interp, ITCL_NAMESPACE"::internal::dicts::classes",
+ NULL, dictPtr, 0);
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classOptions");
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedOptions");
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classVariables");
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classComponents");
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classFunctions");
+ DeleteClassDictInfo(interp, iclsPtr,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedFunctions");
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddObjectsDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddObjectsDictInfo(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *keyPtr1;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *objPtr;
+ int newValue1;
+
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::objects", NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::objects", NULL);
+ return TCL_ERROR;
+ }
+ keyPtr1 = Tcl_NewStringObj("instances", -1);
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr1, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ newValue1 = 1;
+ valuePtr1 = Tcl_NewDictObj();
+ }
+ keyPtr = ioPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ if (Tcl_DictObjRemove(interp, valuePtr1, keyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ valuePtr2 = Tcl_NewDictObj();
+ if (AddDictEntry(interp, valuePtr2, "-name", ioPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-origname", ioPtr->namePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-class", ioPtr->iclsPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr->hullWindowNamePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-hullwindow",
+ ioPtr->hullWindowNamePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (AddDictEntry(interp, valuePtr2, "-varns", ioPtr->varNsNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ if (AddDictEntry(interp, valuePtr2, "-command", objPtr) != TCL_OK) {
+ Tcl_DecrRefCount(objPtr);
+ return TCL_ERROR;
+ }
+ keyPtr = ioPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ /* Cannot fail. Screened non-dicts earlier. */
+ Tcl_DictObjPut(interp, dictPtr, keyPtr1, valuePtr1);
+ } else {
+ /* Don't leak the key val... */
+ Tcl_DecrRefCount(keyPtr1);
+ }
+ Tcl_SetVar2Ex(interp, ITCL_NAMESPACE"::internal::dicts::objects",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteObjectsDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclDeleteObjectsDictInfo(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *keyPtr1;
+ Tcl_Obj *valuePtr;
+ Tcl_Obj *valuePtr1;
+
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::objects", NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::objects", NULL);
+ return TCL_ERROR;
+ }
+ keyPtr1 = Tcl_NewStringObj("instances", -1);
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr1, &valuePtr) != TCL_OK) {
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_ERROR;
+ }
+ if (valuePtr == NULL) {
+ /* looks like no object has been registered yet
+ * so ignore and return OK */
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_OK;
+ }
+ keyPtr = ioPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr, keyPtr, &valuePtr1) != TCL_OK) {
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_ERROR;
+ }
+ if (valuePtr1 == NULL) {
+ /* looks like the object has not been constructed successfully
+ * so ignore and return OK */
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_OK;
+ }
+ if (Tcl_DictObjRemove(interp, valuePtr, keyPtr) != TCL_OK) {
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr1, valuePtr) != TCL_OK) {
+ /* This is very likely impossible. non-dict already screened. */
+ Tcl_DecrRefCount(keyPtr1);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(keyPtr1);
+ Tcl_SetVar2Ex(interp, ITCL_NAMESPACE"::internal::dicts::objects",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddOptionDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddOptionDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclOption *ioptPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ int newValue1;
+
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classOptions", NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classOptions", NULL);
+ return TCL_ERROR;
+ }
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = ioptPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ valuePtr2 = Tcl_NewDictObj();
+ }
+ if (AddDictEntry(interp, valuePtr2, "-name", ioptPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioptPtr->fullNamePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-fullname", ioptPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (AddDictEntry(interp, valuePtr2, "-resource", ioptPtr->resourceNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-class", ioptPtr->classNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioptPtr->defaultValuePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-default",
+ ioptPtr->defaultValuePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->flags & ITCL_OPTION_READONLY) {
+ if (AddDictEntry(interp, valuePtr2, "-readonly",
+ Tcl_NewStringObj("1", -1)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->cgetMethodPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-cgetmethod",
+ ioptPtr->cgetMethodPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->cgetMethodVarPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-cgetmethodvar",
+ ioptPtr->cgetMethodVarPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->configureMethodPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-configuremethod",
+ ioptPtr->cgetMethodPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->configureMethodVarPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-configuremethodvar",
+ ioptPtr->configureMethodVarPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->validateMethodPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-validatemethod",
+ ioptPtr->validateMethodPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ioptPtr->validateMethodVarPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-validatemethodvar",
+ ioptPtr->validateMethodVarPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ keyPtr = ioptPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp, ITCL_NAMESPACE"::internal::dicts::classOptions",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddDelegatedOptionDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddDelegatedOptionDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclDelegatedOption *idoPtr)
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ void *value;
+ int haveExceptions;
+ int newValue1;
+
+ keyPtr = iclsPtr->fullNamePtr;
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedOptions",
+ NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classDelegatedOptions", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = idoPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ valuePtr2 = Tcl_NewDictObj();
+ }
+ if (AddDictEntry(interp, valuePtr2, "-name", idoPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (idoPtr->resourceNamePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-resource",
+ idoPtr->resourceNamePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (idoPtr->classNamePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-class", idoPtr->classNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (idoPtr->icPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-component",
+ idoPtr->icPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (idoPtr->asPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-as", idoPtr->asPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ haveExceptions = 0;
+ FOREACH_HASH(keyPtr, value, &idoPtr->exceptions) {
+ if (value == NULL) {
+ /* FIXME need code here */
+ }
+ haveExceptions = 1;
+ Tcl_ListObjAppendElement(interp, listPtr, keyPtr);
+ }
+ if (haveExceptions) {
+ if (AddDictEntry(interp, valuePtr2, "-except", listPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ keyPtr = idoPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedOptions",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddClassComponentDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddClassComponentDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclComponent *icPtr)
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ void *value;
+ int newValue1;
+
+ keyPtr = iclsPtr->fullNamePtr;
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classComponents",
+ NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classComponents", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = icPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ valuePtr2 = Tcl_NewDictObj();
+ }
+ if (AddDictEntry(interp, valuePtr2, "-name", icPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-variable", icPtr->ivPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (icPtr->flags & ITCL_COMPONENT_INHERIT) {
+ if (AddDictEntry(interp, valuePtr2, "-inherit",
+ Tcl_NewStringObj("1", -1)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (icPtr->flags & ITCL_COMPONENT_PUBLIC) {
+ if (AddDictEntry(interp, valuePtr2, "-public",
+ Tcl_NewStringObj("1", -1)) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (icPtr->haveKeptOptions) {
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH(keyPtr, value, &icPtr->keptOptions) {
+ if (value == NULL) {
+ /* FIXME need code here */
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, keyPtr);
+ }
+ if (AddDictEntry(interp, valuePtr2, "-keptoptions", listPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ keyPtr = icPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classComponents",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddClassVariableDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddClassVariableDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclVariable *ivPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ const char *cp;
+ int haveFlags;
+ int newValue1;
+
+ keyPtr = iclsPtr->fullNamePtr;
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classVariables",
+ NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classVariables", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = ivPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ valuePtr2 = Tcl_NewDictObj();
+ }
+ if (AddDictEntry(interp, valuePtr2, "-name", ivPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-fullname", ivPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ivPtr->init != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-init", ivPtr->init)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (ivPtr->arrayInitPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-arrayinit", ivPtr->arrayInitPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ cp = Itcl_ProtectionStr(ivPtr->protection);
+ if (AddDictEntry(interp, valuePtr2, "-protection", Tcl_NewStringObj(cp, -1))
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cp = "variable";
+ if (ivPtr->flags & ITCL_COMMON) {
+ cp = "common";
+ }
+ if (ivPtr->flags & ITCL_VARIABLE) {
+ cp = "variable";
+ }
+ if (ivPtr->flags & ITCL_TYPE_VARIABLE) {
+ cp = "typevariable";
+ }
+ if (AddDictEntry(interp, valuePtr2, "-type", Tcl_NewStringObj(cp, -1))
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ haveFlags = 0;
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (ivPtr->flags & ITCL_THIS_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj("this", -1));
+ }
+ if (ivPtr->flags & ITCL_SELF_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj("self", -1));
+ }
+ if (ivPtr->flags & ITCL_SELFNS_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("selfns", -1));
+ }
+ if (ivPtr->flags & ITCL_WIN_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj("win", -1));
+ }
+ if (ivPtr->flags & ITCL_COMPONENT_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("component", -1));
+ }
+ if (ivPtr->flags & ITCL_OPTIONS_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("itcl_options", -1));
+ }
+ if (ivPtr->flags & ITCL_HULL_VAR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("itcl_hull", -1));
+ }
+ if (ivPtr->flags & ITCL_OPTION_READONLY) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("option_read_only", -1));
+ }
+ if (haveFlags) {
+ if (AddDictEntry(interp, valuePtr2, "-flags", listPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (ivPtr->codePtr != NULL) {
+ if (ivPtr->codePtr->bodyPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-code",
+ ivPtr->codePtr->bodyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+ keyPtr = ivPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classVariables",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddClassFunctionDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddClassFunctionDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclMemberFunc *imPtr)
+{
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ const char *cp;
+ int haveFlags;
+ int newValue1;
+
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classFunctions",
+ NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classFunctions", NULL);
+ return TCL_ERROR;
+ }
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = imPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 != NULL) {
+ Tcl_DictObjRemove(interp, valuePtr1, keyPtr);
+ }
+ valuePtr2 = Tcl_NewDictObj();
+ if (AddDictEntry(interp, valuePtr2, "-name", imPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (AddDictEntry(interp, valuePtr2, "-fullname", imPtr->fullNamePtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cp = "";
+ if (imPtr->protection == ITCL_PUBLIC) {
+ cp = "public";
+ }
+ if (imPtr->protection == ITCL_PROTECTED) {
+ cp = "protected";
+ }
+ if (imPtr->protection == ITCL_PRIVATE) {
+ cp = "private";
+ }
+ if (AddDictEntry(interp, valuePtr2, "-protection", Tcl_NewStringObj(cp, -1))
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ cp = "";
+ if (imPtr->flags & ITCL_COMMON) {
+ cp = "common";
+ }
+ if (imPtr->flags & ITCL_METHOD) {
+ cp = "method";
+ }
+ if (imPtr->flags & ITCL_TYPE_METHOD) {
+ cp = "typemethod";
+ }
+ if (AddDictEntry(interp, valuePtr2, "-type", Tcl_NewStringObj(cp, -1))
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ haveFlags = 0;
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (imPtr->flags & ITCL_CONSTRUCTOR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("constructor", -1));
+ }
+ if (imPtr->flags & ITCL_DESTRUCTOR) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("destructor", -1));
+ }
+ if (imPtr->flags & ITCL_ARG_SPEC) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("have_args", -1));
+ }
+ if (imPtr->flags & ITCL_BODY_SPEC) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("have_body", -1));
+ }
+ if (haveFlags) {
+ if (AddDictEntry(interp, valuePtr2, "-flags", listPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ if (imPtr->codePtr != NULL) {
+ if (imPtr->codePtr->bodyPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-body",
+ imPtr->codePtr->bodyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (imPtr->codePtr->argumentPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-args",
+ imPtr->codePtr->argumentPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (imPtr->codePtr->usagePtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-usage",
+ imPtr->codePtr->usagePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ haveFlags = 0;
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (imPtr->codePtr->flags & ITCL_BUILTIN) {
+ haveFlags = 1;
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("builtin", -1));
+ }
+ if (haveFlags) {
+ if (AddDictEntry(interp, valuePtr2, "-codeflags", listPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ }
+ keyPtr = imPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classFunctions",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAddClassDelegatedFunctionDictInfo()
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAddClassDelegatedFunctionDictInfo(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclDelegatedFunction *idmPtr)
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr1;
+ Tcl_Obj *valuePtr2;
+ Tcl_Obj *listPtr;
+ void *value;
+ int haveExceptions;
+ int newValue1;
+
+ keyPtr = iclsPtr->fullNamePtr;
+ dictPtr = Tcl_GetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedFunctions",
+ NULL, 0);
+ if (dictPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get dict ", ITCL_NAMESPACE,
+ "::internal::dicts::classDelegatedFunctions", NULL);
+ return TCL_ERROR;
+ }
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ newValue1 = 0;
+ if (valuePtr1 == NULL) {
+ valuePtr1 = Tcl_NewDictObj();
+ newValue1 = 1;
+ }
+ keyPtr = idmPtr->namePtr;
+ if (Tcl_DictObjGet(interp, valuePtr1, keyPtr, &valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (valuePtr2 == NULL) {
+ valuePtr2 = Tcl_NewDictObj();
+ }
+ if (AddDictEntry(interp, valuePtr2, "-name", idmPtr->namePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (idmPtr->icPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-component",
+ idmPtr->icPtr->ivPtr->fullNamePtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (idmPtr->asPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-as", idmPtr->asPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ if (idmPtr->usingPtr != NULL) {
+ if (AddDictEntry(interp, valuePtr2, "-using", idmPtr->usingPtr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ haveExceptions = 0;
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH(keyPtr, value, &idmPtr->exceptions) {
+ if (value == NULL) {
+ /* FIXME need code here */
+ }
+ haveExceptions = 1;
+ if (Tcl_ListObjAppendElement(interp, listPtr, keyPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ if (haveExceptions) {
+ if (AddDictEntry(interp, valuePtr2, "-except", listPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_DecrRefCount(listPtr);
+ }
+ keyPtr = idmPtr->namePtr;
+ if (Tcl_DictObjPut(interp, valuePtr1, keyPtr, valuePtr2) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (newValue1) {
+ keyPtr = iclsPtr->fullNamePtr;
+ if (Tcl_DictObjPut(interp, dictPtr, keyPtr, valuePtr1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ Tcl_SetVar2Ex(interp,
+ ITCL_NAMESPACE"::internal::dicts::classDelegatedFunctions",
+ NULL, dictPtr, 0);
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclInfo.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclInfo.c
new file mode 100644
index 0000000..bbd7513
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclInfo.c
@@ -0,0 +1,5327 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * These procedures handle built-in class methods, including the
+ * "isa" method (to query hierarchy info) and the "info" method
+ * (to query class/object data).
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+static Tcl_ObjCmdProc Itcl_BiInfoClassOptionsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoComponentsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDefaultCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoExtendedClassCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoInstancesCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoHullTypeCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoMethodCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoMethodsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoOptionsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypeCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypeMethodCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypeMethodsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypesCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypeVarsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoTypeVariableCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoVariablesCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoWidgetadaptorCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoWidgetCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedOptionsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedMethodsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedTypeMethodsCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedOptionCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedMethodCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedTypeMethodCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoDelegatedUnknownCmd;
+static Tcl_ObjCmdProc Itcl_BiInfoContextCmd;
+
+typedef struct InfoMethod {
+ const char* name; /* method name */
+ const char* usage; /* string describing usage */
+ Tcl_ObjCmdProc *proc; /* implementation C proc */
+ int flags; /* which class commands have it */
+} InfoMethod;
+
+static const InfoMethod InfoMethodList[] = {
+ { "args",
+ "procname",
+ Itcl_BiInfoArgsCmd,
+ ITCL_CLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "body",
+ "procname",
+ Itcl_BiInfoBodyCmd,
+ ITCL_CLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "class",
+ "",
+ Itcl_BiInfoClassCmd,
+ ITCL_CLASS|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "classoptions",
+ "?pattern?",
+ Itcl_BiInfoClassOptionsCmd,
+ ITCL_ECLASS
+ },
+ { "component",
+ "?name? ?-inherit? ?-value?",
+ Itcl_BiInfoComponentCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "context",
+ "",
+ Itcl_BiInfoContextCmd,
+ ITCL_ECLASS
+ },
+ { "components",
+ "?pattern?",
+ Itcl_BiInfoComponentsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "default",
+ "method aname varname",
+ Itcl_BiInfoDefaultCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "delegated",
+ "?name? ?-inherit? ?-value?",
+ Itcl_BiInfoDelegatedCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "extendedclass",
+ "",
+ Itcl_BiInfoExtendedClassCmd,
+ ITCL_ECLASS
+ },
+ { "function",
+ "?name? ?-protection? ?-type? ?-name? ?-args? ?-body?",
+ Itcl_BiInfoFunctionCmd,
+ ITCL_CLASS|ITCL_ECLASS
+ },
+ { "heritage",
+ "",
+ Itcl_BiInfoHeritageCmd,
+ ITCL_CLASS|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "hulltype",
+ "",
+ Itcl_BiInfoHullTypeCmd,
+ ITCL_WIDGET
+ },
+ { "hulltypes",
+ "?pattern?",
+ Itcl_BiInfoUnknownCmd,
+ ITCL_WIDGETADAPTOR|ITCL_WIDGET
+ },
+ { "inherit",
+ "",
+ Itcl_BiInfoInheritCmd,
+ ITCL_CLASS|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "instances",
+ "?pattern?",
+ Itcl_BiInfoInstancesCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET
+ },
+ { "method",
+ "?name? ?-protection? ?-type? ?-name? ?-args? ?-body?",
+ Itcl_BiInfoMethodCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "methods",
+ "?pattern?",
+ Itcl_BiInfoMethodsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "option",
+ "?name? ?-protection? ?-resource? ?-class? ?-name? ?-default? \
+?-cgetmethod? ?-configuremethod? ?-validatemethod? \
+?-cgetmethodvar? ?-configuremethodvar? ?-validatemethodvar? \
+?-value?",
+ Itcl_BiInfoOptionCmd,
+ ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "options",
+ "?pattern?",
+ Itcl_BiInfoOptionsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "type",
+ "",
+ Itcl_BiInfoTypeCmd,
+ ITCL_TYPE|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "typemethod",
+ "?name? ?-protection? ?-type? ?-name? ?-args? ?-body?",
+ Itcl_BiInfoTypeMethodCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "typemethods",
+ "?pattern?",
+ Itcl_BiInfoTypeMethodsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "types",
+ "?pattern?",
+ Itcl_BiInfoTypesCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "typevariable",
+ "?name? ?-protection? ?-type? ?-name? ?-init? ?-value?",
+ Itcl_BiInfoTypeVariableCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "typevars",
+ "?pattern?",
+ Itcl_BiInfoTypeVarsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "variable",
+ "?name? ?-protection? ?-type? ?-name? ?-init? ?-value? ?-config?",
+ Itcl_BiInfoVariableCmd,
+ ITCL_CLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "variables",
+ "?pattern?",
+ Itcl_BiInfoVariablesCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "vars",
+ "?pattern?",
+ Itcl_BiInfoVarsCmd,
+ ITCL_CLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "widget",
+ "",
+ Itcl_BiInfoWidgetCmd,
+ ITCL_WIDGET
+ },
+ { "widgets",
+ "?pattern?",
+ Itcl_BiInfoUnknownCmd,
+ ITCL_WIDGET
+ },
+ { "widgetclasses",
+ "?pattern?",
+ Itcl_BiInfoUnknownCmd,
+ ITCL_WIDGET
+ },
+ { "widgetadaptor",
+ "",
+ Itcl_BiInfoWidgetadaptorCmd,
+ ITCL_WIDGETADAPTOR
+ },
+ { "widgetadaptors",
+ "?pattern?",
+ Itcl_BiInfoUnknownCmd,
+ ITCL_WIDGETADAPTOR
+ },
+ { NULL,
+ NULL,
+ NULL,
+ 0
+ }
+};
+
+struct NameProcMap2 {
+ const char* name; /* method name */
+ const char* usage; /* string describing usage */
+ Tcl_ObjCmdProc *proc; /* implementation C proc */
+ int flags; /* which class commands have it */
+};
+
+static const struct NameProcMap2 infoCmdsDelegated2[] = {
+ { "::itcl::builtin::Info::delegated::methods",
+ "?pattern?",
+ Itcl_BiInfoDelegatedMethodsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::typemethods",
+ "?pattern?",
+ Itcl_BiInfoDelegatedTypeMethodsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::options",
+ "?pattern?",
+ Itcl_BiInfoDelegatedOptionsCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::method",
+ "methodName",
+ Itcl_BiInfoDelegatedMethodCmd,
+ ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::typemethod",
+ "methodName",
+ Itcl_BiInfoDelegatedTypeMethodCmd,
+ ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::option",
+ "methodName",
+ Itcl_BiInfoDelegatedOptionCmd,
+ ITCL_ECLASS
+ },
+ { "::itcl::builtin::Info::delegated::unknown",
+ "",
+ Itcl_BiInfoDelegatedUnknownCmd,
+ ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS
+ },
+ { NULL, NULL, NULL, 0 }
+};
+
+static void ItclGetInfoUsage(Tcl_Interp *interp, Tcl_Obj*objPtr,
+ ItclObjectInfo *infoPtr, ItclClass *iclsPtr);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInfoInit()
+ *
+ * Creates a namespace full of built-in methods/procs for [incr Tcl]
+ * classes. This includes things like the "info"
+ * for querying class info. Usually invoked by Itcl_Init() when
+ * [incr Tcl] is first installed into an interpreter.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+
+static int
+InfoGutsFinish(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_CallFrame *framePtr = (Tcl_CallFrame *) data[0];
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *) data[1];
+ ItclCallContext *cPtr = (ItclCallContext *) data[2];
+ ItclCallContext *popped;
+
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&infoPtr->frameContext,
+ (char *) framePtr);
+
+ Itcl_Stack *stackPtr = (Itcl_Stack *) Tcl_GetHashValue(hPtr);
+
+ popped = Itcl_PopStack(stackPtr);
+
+ if (Itcl_GetStackSize(stackPtr) == 0) {
+ Itcl_DeleteStack(stackPtr);
+ ckfree((char *)stackPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ if (cPtr != popped) {
+ Tcl_Panic("Context stack mismatch!");
+ }
+ ckfree((char *) cPtr);
+
+ return result;
+}
+
+int
+ItclInfoGuts(
+ ItclObject *ioPtr,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ ItclObjectInfo *infoPtr = ioPtr->infoPtr;
+ Tcl_CmdInfo info;
+ ItclCallContext *cPtr;
+ Tcl_CallFrame *framePtr;
+ Tcl_HashEntry *hPtr;
+ Itcl_Stack *stackPtr;
+ int new;
+
+ if (objc == 2) {
+ /*
+ * No subcommand passed. Give good usage message. NOT the
+ * default message of a Tcl ensemble.
+ */
+
+ Tcl_Obj *objPtr = Tcl_NewStringObj(
+ "wrong # args: should be one of...\n", -1);
+ ItclGetInfoUsage(interp, objPtr, infoPtr, ioPtr->iclsPtr);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+
+ framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+
+ hPtr = Tcl_CreateHashEntry(&infoPtr->frameContext, (char *)framePtr, &new);
+ if (new) {
+ stackPtr = (Itcl_Stack *) ckalloc(sizeof(Itcl_Stack));
+ Itcl_InitStack(stackPtr);
+ Tcl_SetHashValue(hPtr, stackPtr);
+ } else {
+ stackPtr = (Itcl_Stack *) Tcl_GetHashValue(hPtr);
+ }
+
+ cPtr = (ItclCallContext *) ckalloc(sizeof(ItclCallContext));
+ cPtr->objectFlags = ITCL_OBJECT_ROOT_METHOD;
+ cPtr->nsPtr = NULL;
+ cPtr->ioPtr = ioPtr;
+ cPtr->imPtr = NULL;
+ cPtr->refCount = 1;
+
+ Itcl_PushStack(cPtr, stackPtr);
+
+ Tcl_NRAddCallback(interp, InfoGutsFinish, framePtr, infoPtr, cPtr, NULL);
+ Tcl_GetCommandInfoFromToken(infoPtr->infoCmd, &info);
+ return Tcl_NRCallObjProc(interp, info.objProc, info.objClientData,
+ objc-1, objv+1);
+}
+
+static int
+NRInfoWrap(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ Tcl_CmdInfo info;
+ Tcl_Command token = (Tcl_Command) clientData;
+
+ if (objc == 1) {
+ /*
+ * No subcommand passed. Give good usage message. NOT the
+ * default message of a Tcl ensemble.
+ */
+
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ Tcl_Obj *objPtr = Tcl_NewStringObj(
+ "wrong # args: should be one of...\n", -1);
+ ItclGetInfoUsage(interp, objPtr, infoPtr, NULL);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+
+ /* Have a subcommand. Pass on to the ensemble */
+
+ /*
+ * WARNING! WARNING! WARNING!
+ * We are doing NOTHING to guarantee that the command corresponding to
+ * token has not been deleted. If it is deleted, this will fail very
+ * badly. Another pass to plug up dependencies like this is in order.
+ * I'm not bothering now because the code is already overflowing with
+ * worse uncontrolled dependencies. I'll clean the windows sometime
+ * later when the cracks in the foundation are filled in.
+ */
+ Tcl_GetCommandInfoFromToken(token, &info);
+ return Tcl_NRCallObjProc(interp, info.objProc, info.objClientData,
+ objc, objv);
+}
+
+static int
+InfoWrap(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ return Tcl_NRCallObjProc(interp, NRInfoWrap, clientData, objc, objv);
+}
+
+static void
+InfoCmdDelete(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ const char *oldName,
+ const char *newName,
+ int flags)
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *)clientData;
+
+ infoPtr->infoCmd = NULL;
+}
+
+int
+ItclInfoInit(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclObjectInfo *infoPtr)
+{
+ Tcl_Namespace *nsPtr;
+ Tcl_Command token;
+ Tcl_CmdInfo info;
+ Tcl_Obj *unkObjPtr;
+ Tcl_Obj *ensObjPtr;
+ int result;
+ int i;
+
+ /*
+ * Build the ensemble used to implement [info].
+ */
+
+ nsPtr = Tcl_CreateNamespace(interp, "::itcl::builtin::Info", NULL, NULL);
+ if (nsPtr == NULL) {
+ Tcl_Panic("ITCL: error in creating namespace: ::itcl::builtin::Info \n");
+ }
+ if (infoPtr->infoCmd) {
+ Tcl_Panic("Double init of info ensemble");
+ }
+ token = Tcl_CreateEnsemble(interp, nsPtr->fullName, nsPtr,
+ TCL_ENSEMBLE_PREFIX);
+ Tcl_TraceCommand(interp, nsPtr->fullName, TCL_TRACE_DELETE,
+ InfoCmdDelete, (ClientData) infoPtr);
+ infoPtr->infoCmd = token;
+ token = Tcl_NRCreateCommand(interp, "::itcl::builtin::info", InfoWrap,
+ NRInfoWrap, token, NULL);
+ Tcl_GetCommandInfoFromToken(token, &info);
+
+ /*
+ * Make the C implementation of the "info" ensemble available as
+ * a method body. This makes all [$object info] become the
+ * equivalent of [::itcl::builtin::Info] without any need for
+ * tailcall to restore the right frame [87a1bc6e82].
+ */
+ Itcl_RegisterObjC(interp, "itcl-builtin-info", info.objProc,
+ info.objClientData, NULL);
+
+ Tcl_Export(interp, nsPtr, "[a-z]*", 1);
+ ensObjPtr = Tcl_NewStringObj("::itcl::builtin::Info", -1);
+
+ for (i=0 ; InfoMethodList[i].name!=NULL ; i++) {
+ Tcl_Obj *cmdObjPtr = Tcl_DuplicateObj(ensObjPtr);
+
+ Tcl_AppendToObj(cmdObjPtr, "::", 2);
+ Tcl_AppendToObj(cmdObjPtr, InfoMethodList[i].name, -1);
+ Tcl_CreateObjCommand(interp, Tcl_GetString(cmdObjPtr),
+ InfoMethodList[i].proc, infoPtr, NULL);
+ Tcl_DecrRefCount(cmdObjPtr);
+ }
+ unkObjPtr = Tcl_NewStringObj("::itcl::builtin::Info::unknown", -1);
+ Tcl_CreateObjCommand(interp, Tcl_GetString(unkObjPtr),
+ Itcl_BiInfoUnknownCmd, infoPtr, NULL);
+ if (Tcl_SetEnsembleUnknownHandler(NULL,
+ Tcl_FindEnsemble(interp, ensObjPtr, TCL_LEAVE_ERR_MSG),
+ unkObjPtr) != TCL_OK) {
+ Tcl_DecrRefCount(unkObjPtr);
+ Tcl_DecrRefCount(ensObjPtr);
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(ensObjPtr);
+
+ /*
+ * Build the ensemble used to implement [info delegated].
+ */
+
+ nsPtr = Tcl_CreateNamespace(interp, "::itcl::builtin::Info::delegated",
+ NULL, NULL);
+ if (nsPtr == NULL) {
+ Tcl_Panic("ITCL: error in creating namespace: ::itcl::builtin::Info::delegated \n");
+ }
+ Tcl_CreateEnsemble(interp, nsPtr->fullName, nsPtr,
+ TCL_ENSEMBLE_PREFIX);
+ Tcl_Export(interp, nsPtr, "[a-z]*", 1);
+ for (i=0 ; infoCmdsDelegated2[i].name!=NULL ; i++) {
+ Tcl_CreateObjCommand(interp, infoCmdsDelegated2[i].name,
+ infoCmdsDelegated2[i].proc, infoPtr, NULL);
+ }
+ ensObjPtr = Tcl_NewStringObj("::itcl::builtin::Info::delegated",
+ -1);
+ unkObjPtr = Tcl_NewStringObj(
+ "::itcl::builtin::Info::delegated::unknown", -1);
+ result = TCL_OK;
+ if (Tcl_SetEnsembleUnknownHandler(NULL,
+ Tcl_FindEnsemble(interp, ensObjPtr, TCL_LEAVE_ERR_MSG),
+ unkObjPtr) != TCL_OK) {
+ result = TCL_ERROR;
+ }
+ Tcl_DecrRefCount(ensObjPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclGetInfoUsage()
+ *
+ * ------------------------------------------------------------------------
+ */
+void
+ItclGetInfoUsage(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr, /* returns: summary of usage info */
+ ItclObjectInfo *infoPtr,
+ ItclClass *iclsPtr)
+{
+ const char *spaces = " ";
+ int i;
+
+ ItclObject *ioPtr;
+ if (iclsPtr == NULL) {
+ if (TCL_ERROR == Itcl_GetContext(interp, &iclsPtr, &ioPtr)) {
+ return;
+ }
+ }
+ for (i=0; InfoMethodList[i].name != NULL; i++) {
+ if (strcmp(InfoMethodList[i].name, "vars") == 0) {
+ /* we don't report that, as it is a special case
+ * it is only adding the protected and private commons
+ * to the ::info vars command */
+ continue;
+ }
+ if (iclsPtr->flags & InfoMethodList[i].flags) {
+ Tcl_AppendToObj(objPtr, spaces, -1);
+ Tcl_AppendToObj(objPtr, "info ", -1);
+ Tcl_AppendToObj(objPtr, InfoMethodList[i].name, -1);
+ if (strlen(InfoMethodList[i].usage) > 0) {
+ Tcl_AppendToObj(objPtr, " ", -1);
+ Tcl_AppendToObj(objPtr, InfoMethodList[i].usage, -1);
+ }
+ spaces = "\n ";
+ }
+ }
+ Tcl_AppendToObj(objPtr,
+ "\n...and others described on the man page", -1);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclGetInfoDelegatedUsage()
+ *
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclGetInfoDelegatedUsage(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr, /* returns: summary of usage info */
+ ItclObjectInfo *infoPtr)
+{
+ ItclClass *iclsPtr;
+ const char *name;
+ const char *lastName;
+ const char *spaces = " ";
+
+ int i;
+
+ ItclObject *ioPtr;
+ if (TCL_ERROR == Itcl_GetContext(interp, &iclsPtr, &ioPtr)) {
+ return;
+ }
+ for (i=0; infoCmdsDelegated2[i].name != NULL; i++) {
+ name = infoCmdsDelegated2[i].name;
+ lastName = name;
+ while (name != NULL) {
+ name = strstr(name, "::");
+ if (name == NULL) {
+ break;
+ }
+ name += 2;
+ lastName = name;
+ }
+ name = lastName;
+ if (strcmp(name, "unknown") == 0) {
+ /* we don't report that, as it is a special case */
+ continue;
+ }
+ if (iclsPtr->flags & infoCmdsDelegated2[i].flags) {
+ Tcl_AppendToObj(objPtr, spaces, -1);
+ Tcl_AppendToObj(objPtr, "info ", -1);
+ Tcl_AppendToObj(objPtr, name, -1);
+ if (strlen(infoCmdsDelegated2[i].usage) > 0) {
+ Tcl_AppendToObj(objPtr, " ", -1);
+ Tcl_AppendToObj(objPtr, infoCmdsDelegated2[i].usage, -1);
+ }
+ spaces = "\n ";
+ }
+ }
+ Tcl_AppendToObj(objPtr,
+ "\n...and others described on the man page", -1);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoClassCmd()
+ *
+ * Returns information regarding the class for an object. This command
+ * can be invoked with or without an object context:
+ *
+ * <objName> info class <= returns most-specific class name
+ * info class <= returns active namespace name
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoClassCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNs = NULL;
+ ItclClass *contextIclsPtr = NULL;
+ ItclObject *contextIoPtr;
+
+ char *name;
+
+ ItclShowArgs(1, "Itcl_BiInfoClassCmd", objc, objv);
+ if (objc != 1) {
+ /* TODO: convert to NR-enabled fallback to [::info] */
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ /* try it the hard way */
+ ClientData clientData;
+ ItclObjectInfo *infoPtr;
+ Tcl_Object oPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject(clientData);
+ contextIoPtr = Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ if ((contextIoPtr == NULL) || (contextIclsPtr == NULL)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: " \
+ "\n namespace eval className { info class }", -1));
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * If there is an object context, then return the most-specific
+ * class for the object. Otherwise, return the class namespace
+ * name. Use normal class names when possible.
+ */
+ if (contextIoPtr) {
+ contextNs = contextIoPtr->iclsPtr->nsPtr;
+ } else {
+ assert(contextIclsPtr != NULL);
+ assert(contextIclsPtr->nsPtr != NULL);
+ contextNs = contextIclsPtr->nsPtr;
+ }
+
+ assert(contextNs);
+
+ name = contextNs->fullName;
+
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(name, -1));
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoClassOptionsCmd()
+ *
+ * Returns information regarding the options for a class. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoClassOptionsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *listPtr2;
+ Tcl_Obj *objPtr;
+ Tcl_Obj **lObjv;
+ Tcl_HashTable *tablePtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclOption *ioptPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *name;
+ const char *val;
+ const char *pattern;
+ int lObjc;
+ int result;
+ int i;
+
+ ItclShowArgs(1, "Itcl_BiInfoClassOptionsCmd", objc, objv);
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info options ",
+ "?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ tablePtr = &iclsPtr->options;
+ FOREACH_HASH_VALUE(ioptPtr, tablePtr) {
+ name = Tcl_GetString(ioptPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(ioptPtr->namePtr), -1));
+ }
+ }
+ tablePtr = &iclsPtr->delegatedOptions;
+ FOREACH_HASH_VALUE(idoPtr, tablePtr) {
+ name = Tcl_GetString(idoPtr->namePtr);
+ if (strcmp(name, "*") != 0) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(idoPtr->namePtr), -1));
+ }
+ } else {
+ if (idoPtr->icPtr == NULL) {
+ Tcl_AppendResult(interp, "component \"",
+ Tcl_GetString(idoPtr->namePtr),
+ "\" is not initialized", NULL);
+ return TCL_ERROR;
+ }
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(idoPtr->icPtr->namePtr),
+ NULL, ioPtr, ioPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) != 0)) {
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_AppendToObj(objPtr, " configure", -1);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ listPtr2 = Tcl_GetObjResult(interp);
+ Tcl_ListObjGetElements(interp, listPtr2, &lObjc, &lObjv);
+ for (i = 0; i < lObjc; i++) {
+ Tcl_ListObjIndex(interp, lObjv[i], 0, &objPtr);
+ hPtr2 = Tcl_FindHashEntry(&idoPtr->exceptions,
+ (char *)objPtr);
+ if (hPtr2 == NULL) {
+ name = Tcl_GetString(objPtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoContextCmd()
+ *
+ * Returns information regarding the context object and class. This command
+ * can only be invoked with an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoContextCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ ItclObject *ioPtr = NULL;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(1, "Itcl_BiInfoContextCmd", objc, objv);
+ iclsPtr = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot get object context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ objPtr = Tcl_NewStringObj(Tcl_GetString(iclsPtr->namePtr), -1);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ objPtr = Tcl_NewStringObj(Tcl_GetString(ioPtr->namePtr), -1);
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoInheritCmd()
+ *
+ * Returns the list of base classes for the current class context.
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoInheritCmd(
+ ClientData clientdata, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr = NULL;
+ ItclObject *contextIoPtr = NULL;
+ Itcl_ListElem *elem;
+ Tcl_Obj *listPtr;
+
+ ItclShowArgs(2, "Itcl_BiInfoInheritCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info inherit }", -1));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Return the list of base classes.
+ */
+
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ elem = Itcl_FirstListElem(&contextIclsPtr->bases);
+ while (elem) {
+ Tcl_Obj *objPtr;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_GetListValue(elem);
+ objPtr = Tcl_NewStringObj(iclsPtr->nsPtr->fullName, -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+ elem = Itcl_NextListElem(elem);
+ }
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoHeritageCmd()
+ *
+ * Returns the entire derivation hierarchy for this class, presented
+ * in the order that classes are traversed for finding data members
+ * and member functions.
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoHeritageCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr = NULL;
+ ItclObject *contextIoPtr = NULL;
+ ItclHierIter hier;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(2, "Itcl_BiInfoHeritageCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_WrongNumArgs(interp, 1, objv, NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info heritage }", -1));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Traverse through the derivation hierarchy and return
+ * base class names.
+ */
+ listPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ if (iclsPtr->nsPtr == NULL) {
+ Tcl_AppendResult(interp, "ITCL: iclsPtr->nsPtr == NULL",
+ Tcl_GetString(iclsPtr->fullNamePtr), NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(iclsPtr->nsPtr->fullName, -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, listPtr, objPtr);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoFunctionCmd()
+ *
+ * Returns information regarding class member functions (methods/procs).
+ * Handles the following syntax:
+ *
+ * info function ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
+ *
+ * If the ?cmdName? is not specified, then a list of all known
+ * command members is returned. Otherwise, the information for
+ * a specific command is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoFunctionCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ char *cmdName = NULL;
+ Tcl_Obj *resultPtr = NULL;
+ Tcl_Obj *objPtr = NULL;
+
+ static const char *options[] = {
+ "-args", "-body", "-name", "-protection", "-type",
+ (char*)NULL
+ };
+ enum BIfIdx {
+ BIfArgsIdx, BIfBodyIdx, BIfNameIdx, BIfProtectIdx, BIfTypeIdx
+ } *iflist, iflistStorage[5];
+
+ static enum BIfIdx DefInfoFunction[5] = {
+ BIfProtectIdx,
+ BIfTypeIdx,
+ BIfNameIdx,
+ BIfArgsIdx,
+ BIfBodyIdx
+ };
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ ItclClass *iclsPtr;
+ int i;
+ int result;
+ const char *val;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *entry;
+ ItclMemberFunc *imPtr;
+ ItclMemberCode *mcode;
+ ItclHierIter hier;
+
+ ItclShowArgs(2, "Itcl_InfoFunctionCmd", objc, objv);
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info function ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ cmdName = Tcl_GetString(*objv);
+ objc--; objv++;
+ }
+
+ /*
+ * Return info for a specific command.
+ */
+ if (cmdName) {
+ ItclCmdLookup *clookup;
+ objPtr = Tcl_NewStringObj(cmdName, -1);
+ entry = Tcl_FindHashEntry(&contextIclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ objPtr = NULL;
+ if (entry == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a member function in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ imPtr = clookup->imPtr;
+ mcode = imPtr->codePtr;
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ objc = 5;
+ iflist = DefInfoFunction;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ iflist = &iflistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&iflist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (iflist[i]) {
+ case BIfArgsIdx:
+ if (mcode && mcode->argListPtr) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ if ((imPtr->flags & ITCL_ARG_SPEC) != 0) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ }
+ break;
+
+ case BIfBodyIdx:
+ if (mcode && Itcl_IsMemberCodeImplemented(mcode)) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->bodyPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ break;
+
+ case BIfNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ break;
+
+ case BIfProtectIdx:
+ val = Itcl_ProtectionStr(imPtr->protection);
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+
+ case BIfTypeIdx:
+ val = ((imPtr->flags & ITCL_COMMON) != 0)
+ ? "proc" : "method";
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available commands.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ entry = Tcl_FirstHashEntry(&iclsPtr->functions, &place);
+ while (entry) {
+ int useIt = 1;
+
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(entry);
+ if (imPtr->codePtr && (imPtr->codePtr->flags & ITCL_BUILTIN)) {
+ if (strcmp(Tcl_GetString(imPtr->namePtr), "info") == 0) {
+ useIt = 0;
+ }
+ if (strcmp(Tcl_GetString(imPtr->namePtr), "setget") == 0) {
+ if (!(imPtr->iclsPtr->flags & ITCL_ECLASS)) {
+ useIt = 0;
+ }
+ }
+ if (strcmp(Tcl_GetString(imPtr->namePtr),
+ "installcomponent") == 0) {
+ if (!(imPtr->iclsPtr->flags &
+ (ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ useIt = 0;
+ }
+ }
+ }
+ if (useIt) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+
+ entry = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoVariableCmd()
+ *
+ * Returns information regarding class data members (variables and
+ * commons). Handles the following syntax:
+ *
+ * info variable ?varName? ?-protection? ?-type? ?-name?
+ * ?-init? ?-config? ?-value?
+ *
+ * If the ?varName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoVariableCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *entry;
+ ItclClass *iclsPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclVariable *ivPtr;
+ ItclVarLookup *vlookup;
+ ItclHierIter hier;
+ char *varName;
+ const char *val;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-config", "-init", "-name", "-protection", "-type",
+ "-value", (char*)NULL
+ };
+ enum BIvIdx {
+ BIvConfigIdx, BIvInitIdx, BIvNameIdx, BIvProtectIdx,
+ BIvTypeIdx, BIvValueIdx
+ } *ivlist, ivlistStorage[6];
+
+ static enum BIvIdx DefInfoVariable[5] = {
+ BIvProtectIdx,
+ BIvTypeIdx,
+ BIvNameIdx,
+ BIvInitIdx,
+ BIvValueIdx
+ };
+
+ static enum BIvIdx DefInfoPubVariable[6] = {
+ BIvProtectIdx,
+ BIvTypeIdx,
+ BIvNameIdx,
+ BIvInitIdx,
+ BIvConfigIdx,
+ BIvValueIdx
+ };
+
+
+ ItclShowArgs(1, "Itcl_BiInfoVariableCmd", objc, objv);
+ resultPtr = NULL;
+ objPtr = NULL;
+ varName = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info variable ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?varName? ?-protection? ?-type? ?-name? ?-init? ?-config? ?-value?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ varName = Tcl_GetString(*objv);
+ objc--; objv++;
+ }
+
+ /*
+ * Return info for a specific variable.
+ */
+ if (varName) {
+ entry = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, varName);
+ if (entry == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", varName, "\" isn't a variable in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry);
+ ivPtr = vlookup->ivPtr;
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ if (ivPtr->protection == ITCL_PUBLIC &&
+ ((ivPtr->flags & ITCL_COMMON) == 0)) {
+ ivlist = DefInfoPubVariable;
+ objc = 6;
+ } else {
+ ivlist = DefInfoVariable;
+ objc = 5;
+ }
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ivlist = &ivlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ivlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ivlist[i]) {
+ case BIvConfigIdx:
+ if (ivPtr->codePtr &&
+ Itcl_IsMemberCodeImplemented(ivPtr->codePtr)) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->codePtr->bodyPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BIvInitIdx:
+ /*
+ * If this is the built-in "this" variable, then
+ * report the object name as its initialization string.
+ */
+ if ((ivPtr->flags & ITCL_THIS_VAR) != 0) {
+ if ((contextIoPtr != NULL) &&
+ (contextIoPtr->accessCmd != NULL)) {
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(
+ contextIoPtr->iclsPtr->interp,
+ contextIoPtr->accessCmd, objPtr);
+ } else {
+ objPtr = Tcl_NewStringObj("<objectName>", -1);
+ }
+ } else {
+ if (vlookup->ivPtr->init) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(vlookup->ivPtr->init), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ }
+ break;
+
+ case BIvNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ break;
+
+ case BIvProtectIdx:
+ val = Itcl_ProtectionStr(ivPtr->protection);
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BIvTypeIdx:
+ val = ((ivPtr->flags & ITCL_COMMON) != 0)
+ ? "common" : "variable";
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BIvValueIdx:
+ if ((ivPtr->flags & ITCL_COMMON) != 0) {
+ val = Itcl_GetCommonVar(interp,
+ Tcl_GetString(ivPtr->fullNamePtr),
+ ivPtr->iclsPtr);
+ } else {
+ if (contextIoPtr == NULL) {
+ if (objc > 1) {
+ Tcl_DecrRefCount(resultPtr);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "cannot access object-specific info ",
+ "without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ } else {
+ val = Itcl_GetInstanceVar(interp,
+ Tcl_GetString(ivPtr->namePtr),
+ contextIoPtr, ivPtr->iclsPtr);
+ }
+ }
+ if (val == NULL) {
+ val = "<undefined>";
+ }
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ }
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, Tcl_GetString(resultPtr), NULL);
+ Tcl_DecrRefCount(resultPtr);
+ } else {
+
+ /*
+ * Return the list of available variables. Report the built-in
+ * "this" variable only once, for the most-specific class.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ entry = Tcl_FirstHashEntry(&iclsPtr->variables, &place);
+ while (entry) {
+ ivPtr = (ItclVariable*)Tcl_GetHashValue(entry);
+ if ((ivPtr->flags & ITCL_THIS_VAR) != 0) {
+ if (iclsPtr == contextIclsPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+ entry = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoVarsCmd()
+ *
+ * Returns information regarding variables
+ *
+ * info vars ?pattern?
+ * uses ::info vars and adds Itcl common variables!!
+ *
+ * Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoVarsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ Tcl_Obj **newObjv;
+ Tcl_Namespace *nsPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr = NULL;
+ ItclVariable *ivPtr;
+ const char *pattern;
+ const char *name;
+ int useGlobalInfo;
+ int result;
+ ItclObject *ioPtr;
+
+ ItclShowArgs(1, "Itcl_BiInfoVars", objc, objv);
+ result = TCL_OK;
+ useGlobalInfo = 1;
+ pattern = NULL;
+ infoPtr = (ItclObjectInfo *)clientData;
+
+ if (objc > 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, " ?pattern?");
+ return TCL_ERROR;
+ }
+
+ if (TCL_OK != Itcl_GetContext(interp, &iclsPtr, &ioPtr)) {
+ if (objc == 2) {
+ /* Give pattern a chance to determine context */
+ Tcl_ResetResult(interp);
+ } else {
+ return TCL_ERROR;
+ }
+ }
+ if (iclsPtr) {
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET)) {
+ /* don't use the ::tcl::info::vars command */
+ useGlobalInfo = 0;
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ }
+ }
+ if (useGlobalInfo) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc));
+ newObjv[0] = Tcl_NewStringObj("::tcl::info::vars", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ memcpy(newObjv+1, objv+1, sizeof(Tcl_Obj *)*(objc-1));
+ result = Tcl_EvalObjv(interp, objc, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ } else {
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(ivPtr, &iclsPtr->variables) {
+ if ((ivPtr->flags & ITCL_VARIABLE) != 0) {
+ name = Tcl_GetString(ivPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, ivPtr->namePtr);
+ }
+ }
+ }
+ /* always add the itcl_options variable */
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj("itcl_options", -1));
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+ }
+ if (objc < 2) {
+ return result;
+ }
+ if (result == TCL_OK) {
+ Tcl_DString buffer;
+ const char *head;
+ const char *tail;
+ /* check if the pattern contains a class namespace
+ * and if yes add the common private and protected vars
+ * and remove the ___DO_NOT_DELETE_THIS_VARIABLE var
+ */
+ Itcl_ParseNamespPath(Tcl_GetString(objv[1]), &buffer, &head, &tail);
+ if (head == NULL) {
+ nsPtr = Tcl_GetCurrentNamespace(interp);
+ } else {
+ nsPtr = Tcl_FindNamespace(interp, head, NULL, 0);
+ }
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses,
+ (char *)nsPtr);
+ if (hPtr != NULL) {
+ Itcl_List varList;
+ Tcl_Obj *resultListPtr;
+ Tcl_Obj *namePtr;
+ int numElems;
+
+ Itcl_InitList(&varList);
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ resultListPtr = Tcl_GetObjResult(interp);
+ numElems = 0;
+/* FIXME !! should perhaps skip ___DO_NOT_DELETE_THIS_VARIABLE here !! */
+ FOREACH_HASH_VALUE(ivPtr, &iclsPtr->variables) {
+ if ((ivPtr->flags & ITCL_VARIABLE) != 0) {
+ if (head != NULL) {
+ namePtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ } else {
+ namePtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->namePtr), -1);
+ }
+ Tcl_ListObjAppendElement(interp, resultListPtr,
+ namePtr);
+ numElems++;
+ }
+ if ((ivPtr->flags & ITCL_COMMON) != 0) {
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ if (head != NULL) {
+ namePtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ } else {
+ namePtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->namePtr), -1);
+ }
+ Tcl_ListObjAppendElement(interp, resultListPtr,
+ namePtr);
+ numElems++;
+ }
+ }
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoUnknownCmd()
+ *
+ * the unknown handler for the ::itcl::builtin::Info ensemble
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoUnknownCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr, *listObj;
+ int usage = 1;
+ int code = TCL_ERROR;
+
+ ItclShowArgs(1, "Itcl_BiInfoUnknownCmd", objc, objv);
+
+ if (objc < 2) {
+ /* Namespace ensemble unknown callbacks never do this. */
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unknown callback should not be called directly", -1));
+ return TCL_ERROR;
+ }
+
+ /* Redirect to the [::info] command. */
+ objPtr = Tcl_NewStringObj("::info", -1);
+ listObj = Tcl_NewListObj(1, &objPtr);
+ Tcl_IncrRefCount(listObj);
+ if (Tcl_GetCommandFromObj(interp, objPtr)) {
+ usage = 0;
+ Tcl_ListObjReplace(NULL, listObj, 1, 0, objc-2, objv+2);
+ code = Tcl_EvalObj(interp, listObj);
+ if (code == TCL_ERROR) {
+ /* Redirection to [::info] failed, but why? */
+ Tcl_Obj *optDict = Tcl_GetReturnOptions(interp, code);
+ Tcl_Obj *key = Tcl_NewStringObj("-errorcode", -1);
+ Tcl_Obj *val, *elem;
+
+ Tcl_DictObjGet(NULL, optDict, key, &val);
+ Tcl_DecrRefCount(key);
+ Tcl_ListObjIndex(NULL, val, 0, &elem);
+ if (elem && !strcmp(Tcl_GetString(elem), "TCL")) {
+ Tcl_ListObjIndex(NULL, val, 1, &elem);
+ if (elem && !strcmp(Tcl_GetString(elem), "LOOKUP")) {
+ Tcl_ListObjIndex(NULL, val, 2, &elem);
+ if (elem && !strcmp(Tcl_GetString(elem), "SUBCOMMAND")) {
+
+ /* [::info didn't have that subcommand] */
+ usage = 1;
+ Tcl_ResetResult(interp);
+ }
+ }
+ }
+ }
+ }
+ Tcl_DecrRefCount(listObj);
+
+ if (usage) {
+ /* produce usage message */
+ Tcl_Obj *objPtr = Tcl_NewStringObj(
+ "wrong # args: should be one of...\n", -1);
+ ItclGetInfoUsage(interp, objPtr, (ItclObjectInfo *)clientData, NULL);
+ Tcl_SetObjResult(interp, objPtr);
+ }
+ if (code == TCL_ERROR) {
+ return TCL_ERROR;
+ }
+
+ /* Return a command to replicate the non-error redirect outcome */
+ listObj = Tcl_NewStringObj(
+ "::apply {{o m args} {::tailcall ::return -options $o $m}}", -1);
+ Tcl_ListObjAppendElement(NULL, listObj, Tcl_GetReturnOptions(interp,code));
+ Tcl_ListObjAppendElement(NULL, listObj, Tcl_GetObjResult(interp));
+ Tcl_SetObjResult(interp, listObj);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoBodyCmd()
+ *
+ * Handles the usual "info body" request, returning the body for a
+ * specific proc. Included here for backward compatibility, since
+ * otherwise Tcl would complain that class procs are not real "procs".
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoBodyCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ ItclClass *contextIclsPtr = NULL;
+ ItclObject *contextIoPtr;
+ const char *what = "procedure";
+
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ int code;
+ Tcl_Obj *script;
+
+ /*
+ * We lack the context for any specialized Itcl meaning for
+ * [info body], so fallback to Tcl's.
+ */
+
+ fallback:
+ script = Tcl_NewStringObj("::info body", -1);
+ if (objc == 2) {
+ Tcl_ListObjAppendElement(NULL, script, objv[1]);
+ }
+ Tcl_IncrRefCount(script);
+ code = Tcl_EvalObjEx(interp, script, 0);
+ Tcl_DecrRefCount(script);
+ if (code == TCL_ERROR && what) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" isn't a %s", Tcl_GetString(objv[1]), what));
+ }
+ return code;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ what = "function";
+ if (contextIclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ what = "method";
+ }
+ if (objc != 2) {
+ Tcl_AppendResult(interp,
+ "wrong # args: should be \"info body ", what, "\"",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveCmds, (char *)objv[1]);
+ if (hPtr) {
+ ItclCmdLookup *clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ ItclMemberFunc *imPtr = clookup->imPtr;
+ ItclMemberCode *mcode = imPtr->codePtr;
+
+ /*
+ * Return a string describing the implementation.
+ */
+ if (mcode && Itcl_IsMemberCodeImplemented(mcode)) {
+ Tcl_SetObjResult(interp, mcode->bodyPtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("<undefined>", -1));
+ }
+ return TCL_OK;
+ }
+
+ if (contextIclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions,
+ (char *)objv[1]);
+ }
+
+ if (hPtr) {
+ ItclDelegatedFunction *idmPtr = Tcl_GetHashValue(hPtr);
+ Tcl_Obj *objPtr = Tcl_NewStringObj("delegated ", -1);
+
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ what = "typemethod";
+ }
+ Tcl_AppendToObj(objPtr, what, -1);
+ Tcl_AppendToObj(objPtr, " \"", -1);
+ Tcl_AppendObjToObj(objPtr, objv[1]);
+ Tcl_AppendToObj(objPtr, "\"", -1);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+ goto fallback;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoArgsCmd()
+ *
+ * Handles the usual "info args" request, returning the argument list
+ * for a specific proc. Included here for backward compatibility, since
+ * otherwise Tcl would complain that class procs are not real "procs".
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoArgsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr = NULL;
+ ItclClass *contextIclsPtr = NULL;
+ ItclObject *contextIoPtr;
+ const char *what = NULL;
+
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK
+ && objc > 1) {
+ int code;
+ Tcl_Obj *script;
+
+ /*
+ * We lack the context for any specialized Itcl meaning for
+ * [info args], so fallback to Tcl's.
+ */
+
+ fallback:
+ script = Tcl_NewStringObj("::info args", -1);
+ if (objc == 2) {
+ Tcl_ListObjAppendElement(NULL, script, objv[1]);
+ }
+ Tcl_IncrRefCount(script);
+ code = Tcl_EvalObjEx(interp, script, 0);
+ Tcl_DecrRefCount(script);
+ if (code == TCL_ERROR && what) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "\"%s\" isn't a %s", Tcl_GetString(objv[1]), what));
+ }
+ return code;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ what = "function";
+ if ((contextIclsPtr != NULL) && (contextIclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET))) {
+ what = "method";
+ }
+ if (objc != 2) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "wrong # args: should be \"info args %s\"", what));
+ return TCL_ERROR;
+ }
+
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveCmds, (char *)objv[1]);
+ if (hPtr) {
+ ItclCmdLookup *clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ ItclMemberFunc *imPtr = clookup->imPtr;
+ ItclMemberCode *mcode = imPtr->codePtr;
+
+ /*
+ * Return a string describing the argument list.
+ */
+ if ((mcode && mcode->argListPtr != NULL)
+ || ((imPtr->flags & ITCL_ARG_SPEC) != 0)) {
+ Tcl_SetObjResult(interp, imPtr->usagePtr);
+ } else {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj("<undefined>", -1));
+ }
+ return TCL_OK;
+ }
+
+ if (contextIclsPtr->flags
+ & (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions,
+ (char *)objv[1]);
+ }
+
+ if (hPtr) {
+ ItclDelegatedFunction *idmPtr = Tcl_GetHashValue(hPtr);
+ Tcl_Obj *objPtr = Tcl_NewStringObj("delegated ", -1);
+
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ what = "typemethod";
+ }
+ Tcl_AppendToObj(objPtr, what, -1);
+ Tcl_AppendToObj(objPtr, " \"", -1);
+ Tcl_AppendObjToObj(objPtr, objv[1]);
+ Tcl_AppendToObj(objPtr, "\"", -1);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+ }
+ goto fallback;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoOptionCmd()
+ *
+ * Returns information regarding class options.
+ * Handles the following syntax:
+ *
+ * info option ?optionName? ?-protection? ?-name? ?-resource? ?-class?
+ * ?-default? ?-configmethod? ?-cgetmethod? ?-validatemethod? ?-value?
+ *
+ * If the ?optionName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoOptionCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ char *optionName = NULL;
+ Tcl_Obj *resultPtr = NULL;
+ Tcl_Obj *objPtr = NULL;
+ Tcl_Obj *optionNamePtr;
+
+ static const char *options[] = {
+ "-cgetmethod", "-cgetmethodvar","-class",
+ "-configuremethod", "-configuremethodvar",
+ "-default",
+ "-name", "-protection", "-resource",
+ "-validatemethod", "-validatemethodvar",
+ "-value", (char*)NULL
+ };
+ enum BOptIdx {
+ BOptCgetMethodIdx,
+ BOptCgetMethodVarIdx,
+ BOptClassIdx,
+ BOptConfigureMethodIdx,
+ BOptConfigureMethodVarIdx,
+ BOptDefaultIdx,
+ BOptNameIdx,
+ BOptProtectIdx,
+ BOptResourceIdx,
+ BOptValidateMethodIdx,
+ BOptValidateMethodVarIdx,
+ BOptValueIdx
+ } *ioptlist, ioptlistStorage[12];
+
+ static enum BOptIdx DefInfoOption[12] = {
+ BOptProtectIdx,
+ BOptNameIdx,
+ BOptResourceIdx,
+ BOptClassIdx,
+ BOptDefaultIdx,
+ BOptCgetMethodIdx,
+ BOptCgetMethodVarIdx,
+ BOptConfigureMethodIdx,
+ BOptConfigureMethodVarIdx,
+ BOptValidateMethodIdx,
+ BOptValidateMethodVarIdx,
+ BOptValueIdx
+ };
+
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclOption *ioptPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ const char *val;
+ int i;
+ int result;
+
+ ItclShowArgs(1, "Itcl_BiInfoOptionCmd", objc, objv);
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info option ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?optionName? ?-protection? ?-name? ?-resource? ?-class?
+ * ?-default? ?-cgetmethod? ?-cgetmethodvar? ?-configuremethod?
+ * ?-configuremethodvar? ?-validatemethod? ?-validatemethodvar? ?-value?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ optionName = Tcl_GetString(*objv);
+ objc--;
+ objv++;
+ }
+
+ /*
+ * Return info for a specific option.
+ */
+ if (optionName) {
+ optionNamePtr = Tcl_NewStringObj(optionName, -1);
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectOptions,
+ (char *)optionNamePtr);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", optionName, "\" isn't a option in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ ioptPtr = (ItclOption*)Tcl_GetHashValue(hPtr);
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ ioptlist = DefInfoOption;
+ objc = 9;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ioptlist = &ioptlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ioptlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ioptlist[i]) {
+ case BOptCgetMethodIdx:
+ if (ioptPtr->cgetMethodPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->cgetMethodPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptCgetMethodVarIdx:
+ if (ioptPtr->cgetMethodVarPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->cgetMethodVarPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptConfigureMethodIdx:
+ if (ioptPtr->configureMethodPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->configureMethodPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptConfigureMethodVarIdx:
+ if (ioptPtr->configureMethodVarPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->configureMethodVarPtr),
+ -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptValidateMethodIdx:
+ if (ioptPtr->validateMethodPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->validateMethodPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptValidateMethodVarIdx:
+ if (ioptPtr->validateMethodVarPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->validateMethodVarPtr),
+ -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptResourceIdx:
+ if (ioptPtr->resourceNamePtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->resourceNamePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptClassIdx:
+ if (ioptPtr->classNamePtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->classNamePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptDefaultIdx:
+ if (ioptPtr->defaultValuePtr != NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->defaultValuePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ break;
+
+ case BOptNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ioptPtr->fullNamePtr), -1);
+ break;
+
+ case BOptProtectIdx:
+ val = Itcl_ProtectionStr(ioptPtr->protection);
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BOptValueIdx:
+ if (contextIoPtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "cannot access object-specific info ",
+ "without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ } else {
+ val = ItclGetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr),
+ contextIoPtr, ioptPtr->iclsPtr);
+ }
+ if (val == NULL) {
+ val = "<undefined>";
+ }
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ Tcl_IncrRefCount(objPtr);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available options.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_IncrRefCount(resultPtr);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->options, &place);
+ while (hPtr) {
+ ioptPtr = (ItclOption*)Tcl_GetHashValue(hPtr);
+ objPtr = ioptPtr->namePtr;
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoComponentCmd()
+ *
+ * Returns information regarding class components.
+ * Handles the following syntax:
+ *
+ * info component ?componentName? ?-inherit? ?-name? ?-value?
+ *
+ * If the ?componentName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_BiInfoComponentCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ char *componentName = NULL;
+ Tcl_Obj *resultPtr = NULL;
+ Tcl_Obj *objPtr = NULL;
+ Tcl_Obj *componentNamePtr;
+
+ static const char *components[] = {
+ "-name", "-inherit", "-value", (char*)NULL
+ };
+ enum BCompIdx {
+ BCompNameIdx, BCompInheritIdx, BCompValueIdx
+ } *icomplist, icomplistStorage[3];
+
+ static enum BCompIdx DefInfoComponent[3] = {
+ BCompNameIdx,
+ BCompInheritIdx,
+ BCompValueIdx
+ };
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObjectInfo *infoPtr;
+
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ Tcl_Namespace *nsPtr;
+ ItclComponent *icPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ const char *val;
+ int i;
+ int result;
+
+ ItclShowArgs(1, "Itcl_BiInfoComponentCmd", objc, objv);
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info component ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ nsPtr = Itcl_GetUplevelNamespace(interp, 1);
+ if (nsPtr->parentPtr == NULL) {
+ /* :: namespace */
+ nsPtr = contextIclsPtr->nsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find class name for namespace \"",
+ nsPtr->fullName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ contextIclsPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Process args:
+ * ?componentName? ?-inherit? ?-name? ?-value?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ componentName = Tcl_GetString(*objv);
+ objc--;
+ objv++;
+ }
+
+ /*
+ * Return info for a specific component.
+ */
+ if (componentName) {
+ componentNamePtr = Tcl_NewStringObj(componentName, -1);
+ if (contextIoPtr != NULL) {
+ Itcl_InitHierIter(&hier, contextIoPtr->iclsPtr);
+ } else {
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ }
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components,
+ (char *)componentNamePtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", componentName, "\" isn't a component in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ icPtr = (ItclComponent *)Tcl_GetHashValue(hPtr);
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ icomplist = DefInfoComponent;
+ objc = 3;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ icomplist = &icomplistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ components, "component", 0, (int*)(&icomplist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (icomplist[i]) {
+ case BCompNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(icPtr->ivPtr->fullNamePtr), -1);
+ break;
+
+ case BCompInheritIdx:
+ if (icPtr->flags & ITCL_COMPONENT_INHERIT) {
+ val = "1";
+ } else {
+ val = "0";
+ }
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BCompValueIdx:
+ if (contextIoPtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "cannot access object-specific info ",
+ "without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ } else {
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(icPtr->namePtr), NULL,
+ contextIoPtr, icPtr->ivPtr->iclsPtr);
+ }
+ if (val == NULL) {
+ val = "<undefined>";
+ }
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ Tcl_IncrRefCount(objPtr);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available components.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_IncrRefCount(resultPtr);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->components, &place);
+ while (hPtr) {
+ icPtr = (ItclComponent *)Tcl_GetHashValue(hPtr);
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(icPtr->ivPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoWidgetCmd()
+ *
+ * Returns information regarding widget classes.
+ * Handles the following syntax:
+ *
+ * info widget ?widgetName?
+ *
+ * If the ?widgetName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoWidgetCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNs = NULL;
+ Tcl_Obj *objPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ char *name;
+
+ ItclShowArgs(1, "Itcl_BiInfoWidgetCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"info widget\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ /* try it the hard way */
+ ClientData clientData;
+ ItclObjectInfo *infoPtr;
+ Tcl_Object oPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject(clientData);
+ contextIoPtr = Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ if ((contextIoPtr == NULL) || (contextIclsPtr == NULL)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info widget ... }", -1));
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * If there is an object context, then return the most-specific
+ * class for the object. Otherwise, return the class namespace
+ * name. Use normal class names when possible.
+ */
+ if (contextIoPtr) {
+ contextNs = contextIoPtr->iclsPtr->nsPtr;
+ } else {
+ assert(contextIclsPtr != NULL);
+ assert(contextIclsPtr->nsPtr != NULL);
+#ifdef NEW_PROTO_RESOLVER
+ contextNs = contextIclsPtr->nsPtr;
+#else
+ if (contextIclsPtr->infoPtr->useOldResolvers) {
+ contextNs = contextIclsPtr->nsPtr;
+ } else {
+ contextNs = contextIclsPtr->nsPtr;
+ }
+#endif
+ }
+
+ name = contextNs->fullName;
+ if (!(contextIclsPtr->flags & ITCL_WIDGET)) {
+ Tcl_AppendResult(interp, "object or class is no widget", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(name, -1);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoExtendedClassCmd()
+ *
+ * Returns information regarding extendedclasses.
+ * Handles the following syntax:
+ *
+ * info extendedclass ?className?
+ *
+ * If the ?className? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoExtendedClassCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+#ifdef NOTYET
+ static const char *components[] = {
+ "-name", "-inherit", "-value", (char*)NULL
+ };
+ enum BCompIdx {
+ BCompNameIdx, BCompInheritIdx, BCompValueIdx
+ } *icomplist, icomplistStorage[3];
+
+ static enum BCompIdx DefInfoComponent[3] = {
+ BCompNameIdx,
+ BCompInheritIdx,
+ BCompValueIdx
+ };
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObjectInfo *infoPtr;
+
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ Tcl_Namespace *nsPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ const char *name;
+ int result;
+
+ ItclShowArgs(1, "Itcl_BiInfoExtendedClassCmd", objc, objv);
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info extendedclass ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ nsPtr = Itcl_GetUplevelNamespace(interp, 1);
+ if (nsPtr->parentPtr == NULL) {
+ /* :: namespace */
+ nsPtr = contextIclsPtr->nsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find class name for namespace \"",
+ nsPtr->fullName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ contextIclsPtr = Tcl_GetHashValue(hPtr);
+
+#endif
+
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedCmd()
+ *
+ * Returns information regarding extendedclasses.
+ * Handles the following syntax:
+ *
+ * info extendedclass ?className?
+ *
+ * If the ?className? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+#ifdef NOTYET
+ static const char *components[] = {
+ "-name", "-inherit", "-value", (char*)NULL
+ };
+ enum BCompIdx {
+ BCompNameIdx, BCompInheritIdx, BCompValueIdx
+ } *icomplist, icomplistStorage[3];
+
+ static enum BCompIdx DefInfoComponent[3] = {
+ BCompNameIdx,
+ BCompInheritIdx,
+ BCompValueIdx
+ };
+
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObjectInfo *infoPtr;
+
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ Tcl_Namespace *nsPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ const char *name;
+ int result;
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedCmd", objc, objv);
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info delegated ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ nsPtr = Itcl_GetUplevelNamespace(interp, 1);
+ if (nsPtr->parentPtr == NULL) {
+ /* :: namespace */
+ nsPtr = contextIclsPtr->nsPtr;
+ }
+ infoPtr = contextIclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find class name for namespace \"",
+ nsPtr->fullName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ contextIclsPtr = Tcl_GetHashValue(hPtr);
+
+#endif
+
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypeCmd()
+ *
+ * Returns information regarding the Type for an object. This command
+ * can be invoked with or without an object context:
+ *
+ * <objName> info type <= returns most-specific class name
+ * info type <= returns active namespace name
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypeCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNs = NULL;
+ Tcl_Obj *objPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ char *name;
+
+ ItclShowArgs(1, "Itcl_BiInfoTypeCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"info type\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ /* try it the hard way */
+ ClientData clientData;
+ ItclObjectInfo *infoPtr;
+ Tcl_Object oPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject(clientData);
+ contextIoPtr = Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ if ((contextIoPtr == NULL) || (contextIclsPtr == NULL)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info type ...}", -1));
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * If there is an object context, then return the most-specific
+ * class for the object. Otherwise, return the class namespace
+ * name. Use normal class names when possible.
+ */
+ if (contextIoPtr) {
+ contextNs = contextIoPtr->iclsPtr->nsPtr;
+ } else {
+ assert(contextIclsPtr != NULL);
+ assert(contextIclsPtr->nsPtr != NULL);
+#ifdef NEW_PROTO_RESOLVER
+ contextNs = contextIclsPtr->nsPtr;
+#else
+ if (contextIclsPtr->infoPtr->useOldResolvers) {
+ contextNs = contextIclsPtr->nsPtr;
+ } else {
+ contextNs = contextIclsPtr->nsPtr;
+ }
+#endif
+ }
+
+ name = contextNs->fullName;
+ if (!(contextIclsPtr->flags & ITCL_TYPE)) {
+ Tcl_AppendResult(interp, "object or class is no type", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(name, -1);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoHullTypeCmd()
+ *
+ * Returns information regarding the hulltype for an object. This command
+ * can be invoked with or without an object context:
+ *
+ * <objName> info hulltype returns the hulltype name
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoHullTypeCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+
+ ItclShowArgs(1, "Itcl_BiInfoHullTypeCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"info hulltype\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ /* try it the hard way */
+ ClientData clientData;
+ ItclObjectInfo *infoPtr;
+ Tcl_Object oPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject(clientData);
+ contextIoPtr = Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ if ((contextIoPtr == NULL) || (contextIclsPtr == NULL)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info hulltype ... }", -1));
+ return TCL_ERROR;
+ }
+ }
+
+ if (!(contextIclsPtr->flags & ITCL_WIDGET)) {
+ Tcl_AppendResult(interp, "object or class is no widget.",
+ " Only ::itcl::widget has a hulltype.", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, contextIclsPtr->hullTypePtr);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDefaultCmd()
+ *
+ * Returns information regarding the Type for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDefaultCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclArgList *argListPtr;
+ const char *methodName;
+ const char *argName;
+ const char *what;
+ int found;
+
+ ItclShowArgs(1, "Itcl_BiInfoDefaultCmd", objc, objv);
+ iclsPtr = NULL;
+ found = 0;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc != 4) {
+ Tcl_AppendResult(interp, "wrong # args, should be info default ",
+ "<method> <argName> <varName>", NULL);
+ return TCL_ERROR;
+ }
+ methodName = Tcl_GetString(objv[1]);
+ argName = Tcl_GetString(objv[2]);
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ if (strcmp(methodName, Tcl_GetString(imPtr->namePtr)) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found) {
+ argListPtr = imPtr->argListPtr;
+ while (argListPtr != NULL) {
+ if (strcmp(argName, Tcl_GetString(argListPtr->namePtr)) == 0) {
+ if (argListPtr->defaultValuePtr != NULL) {
+ if (NULL == Tcl_ObjSetVar2(interp, objv[3], NULL,
+ argListPtr->defaultValuePtr, TCL_LEAVE_ERR_MSG)) {
+ return TCL_ERROR;
+ }
+ Tcl_SetResult(interp, "1", NULL);
+ return TCL_OK;
+ } else {
+ Tcl_AppendResult(interp, "method \"", methodName,
+ "\" has no default value for argument \"",
+ argName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ argListPtr = argListPtr->nextPtr;
+ }
+ }
+ if (! found) {
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(methodName, Tcl_GetString(idmPtr->namePtr)) == 0) {
+ what = "method";
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ what = "typemethod";
+ }
+ Tcl_AppendResult(interp, "delegated ", what, " \"", methodName,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (! found) {
+ Tcl_AppendResult(interp, "unknown method \"", methodName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendResult(interp, "method \"", methodName, "\" has no argument \"",
+ argName, "\"", NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoMethodCmd()
+ *
+ * Returns information regarding a method for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoMethodCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclMemberCode *mcode;
+ ItclHierIter hier;
+ const char *val;
+ char *cmdName;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-args", "-body", "-name", "-protection", "-type",
+ (char*)NULL
+ };
+ enum BIfIdx {
+ BIfArgsIdx, BIfBodyIdx, BIfNameIdx, BIfProtectIdx, BIfTypeIdx
+ } *iflist, iflistStorage[5];
+
+ static enum BIfIdx DefInfoFunction[5] = {
+ BIfProtectIdx,
+ BIfTypeIdx,
+ BIfNameIdx,
+ BIfArgsIdx,
+ BIfBodyIdx
+ };
+
+ ItclShowArgs(1, "Itcl_BiInfoMethodCmd", objc, objv);
+ cmdName = NULL;
+ objPtr = NULL;
+ resultPtr = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info method ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ cmdName = Tcl_GetString(*objv);
+ objc--; objv++;
+ }
+
+ /*
+ * Return info for a specific command.
+ */
+ if (cmdName) {
+ ItclCmdLookup *clookup;
+ objPtr = Tcl_NewStringObj(cmdName, -1);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ objPtr = NULL;
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a method in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ mcode = imPtr->codePtr;
+ if (imPtr->flags & ITCL_COMMON) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a method in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ objc = 5;
+ iflist = DefInfoFunction;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ iflist = &iflistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&iflist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (iflist[i]) {
+ case BIfArgsIdx:
+ if (mcode && mcode->argListPtr) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ if ((imPtr->flags & ITCL_ARG_SPEC) != 0) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ }
+ break;
+
+ case BIfBodyIdx:
+ if (mcode && Itcl_IsMemberCodeImplemented(mcode)) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->bodyPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ break;
+
+ case BIfNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ break;
+
+ case BIfProtectIdx:
+ val = Itcl_ProtectionStr(imPtr->protection);
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+
+ case BIfTypeIdx:
+ val = "method";
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available commands.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->functions, &place);
+ while (hPtr) {
+ int useIt = 1;
+
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(hPtr);
+ if (!(imPtr->flags & ITCL_METHOD)) {
+ useIt = 0;
+ }
+ if (useIt) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoMethodsCmd()
+ *
+ * Returns information regarding the methods for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoMethodsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoMethodsCmd", objc, objv);
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ name = "destroy";
+ if ((pattern == NULL) || Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ name = "info";
+ if ((pattern == NULL) || Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ name = Tcl_GetString(imPtr->namePtr);
+ if (strcmp(name, "*") == 0) {
+ continue;
+ }
+ if (strcmp(name, "destroy") == 0) {
+ continue;
+ }
+ if (strcmp(name, "info") == 0) {
+ continue;
+ }
+ if ((imPtr->flags & ITCL_METHOD) &&
+ !(imPtr->flags & ITCL_CONSTRUCTOR) &&
+ !(imPtr->flags & ITCL_DESTRUCTOR) &&
+ !(imPtr->flags & ITCL_COMMON) &&
+ !(imPtr->codePtr->flags & ITCL_BUILTIN)) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(imPtr->namePtr), -1));
+ }
+ }
+ }
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ name = Tcl_GetString(idmPtr->namePtr);
+ if (strcmp(name, "*") == 0) {
+ continue;
+ }
+ if (strcmp(name, "destroy") == 0) {
+ continue;
+ }
+ if (strcmp(name, "info") == 0) {
+ continue;
+ }
+ if (idmPtr->flags & ITCL_METHOD) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(idmPtr->namePtr), -1));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoOptionsCmd()
+ *
+ * Returns information regarding the Type for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoOptionsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *listPtr2;
+ Tcl_Obj *objPtr;
+ Tcl_Obj **lObjv;
+ Tcl_HashTable *tablePtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclOption *ioptPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *name;
+ const char *val;
+ const char *pattern;
+ int lObjc;
+ int result;
+ int i;
+
+ ItclShowArgs(1, "Itcl_BiInfoOptionsCmd", objc, objv);
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info options ",
+ "?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (ioPtr == NULL) {
+ tablePtr = &iclsPtr->options;
+ } else {
+ tablePtr = &ioPtr->objectOptions;
+ }
+ FOREACH_HASH_VALUE(ioptPtr, tablePtr) {
+ name = Tcl_GetString(ioptPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(ioptPtr->namePtr), -1));
+ }
+ }
+ if (ioPtr == NULL) {
+ tablePtr = &iclsPtr->delegatedOptions;
+ } else {
+ tablePtr = &ioPtr->objectDelegatedOptions;
+ }
+ FOREACH_HASH_VALUE(idoPtr, tablePtr) {
+ name = Tcl_GetString(idoPtr->namePtr);
+ if (strcmp(name, "*") != 0) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(idoPtr->namePtr), -1));
+ }
+ } else {
+ if (idoPtr->icPtr == NULL) {
+ Tcl_AppendResult(interp, "component \"",
+ Tcl_GetString(idoPtr->namePtr),
+ "\" is not initialized", NULL);
+ return TCL_ERROR;
+ }
+ val = ItclGetInstanceVar(interp,
+ Tcl_GetString(idoPtr->icPtr->namePtr),
+ NULL, ioPtr, ioPtr->iclsPtr);
+ if ((val != NULL) && (strlen(val) != 0)) {
+ objPtr = Tcl_NewStringObj(val, -1);
+ Tcl_AppendToObj(objPtr, " configure", -1);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ listPtr2 = Tcl_GetObjResult(interp);
+ Tcl_ListObjGetElements(interp, listPtr2, &lObjc, &lObjv);
+ for (i = 0; i < lObjc; i++) {
+ Tcl_ListObjIndex(interp, lObjv[i], 0, &objPtr);
+ hPtr2 = Tcl_FindHashEntry(&idoPtr->exceptions,
+ (char *)objPtr);
+ if (hPtr2 == NULL) {
+ name = Tcl_GetString(objPtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypesCmd()
+ *
+ * Returns information regarding the Type for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypesCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoTypesCmd", objc, objv);
+ infoPtr = (ItclObjectInfo *)clientData;
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info types ",
+ "?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(iclsPtr, &infoPtr->nameClasses) {
+ if (iclsPtr->flags & ITCL_TYPE) {
+ name = Tcl_GetString(iclsPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(iclsPtr->namePtr), -1));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoComponentsCmd()
+ *
+ * Returns information regarding the Components for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoComponentsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclComponent *icPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr2;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoComponentsCmd", objc, objv);
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR in Itcl_BiInfoComponentsCmd",
+ " iclsPtr == NULL", NULL);
+ return TCL_ERROR;
+ }
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info components ",
+ "?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ FOREACH_HASH_VALUE(icPtr, &iclsPtr2->components) {
+ name = Tcl_GetString(icPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(icPtr->namePtr), -1));
+ }
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypeMethodCmd()
+ *
+ * Returns information regarding a typemethod for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypeMethodCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclMemberCode *mcode;
+ ItclHierIter hier;
+ const char *val;
+ char *cmdName;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-args", "-body", "-name", "-protection", "-type",
+ (char*)NULL
+ };
+ enum BIfIdx {
+ BIfArgsIdx, BIfBodyIdx, BIfNameIdx, BIfProtectIdx, BIfTypeIdx
+ } *iflist, iflistStorage[5];
+
+ static enum BIfIdx DefInfoFunction[5] = {
+ BIfProtectIdx,
+ BIfTypeIdx,
+ BIfNameIdx,
+ BIfArgsIdx,
+ BIfBodyIdx
+ };
+
+
+ ItclShowArgs(1, "Itcl_BiInfoTypeMethodCmd", objc, objv);
+ resultPtr = NULL;
+ objPtr = NULL;
+ cmdName = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info function ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?cmdName? ?-protection? ?-type? ?-name? ?-args? ?-body?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ cmdName = Tcl_GetString(*objv);
+ objc--; objv++;
+ }
+
+ /*
+ * Return info for a specific command.
+ */
+ if (cmdName) {
+ ItclCmdLookup *clookup;
+ objPtr = Tcl_NewStringObj(cmdName, -1);
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ objPtr = NULL;
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a typemethod in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ mcode = imPtr->codePtr;
+ if (!(imPtr->flags & ITCL_TYPE_METHOD)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a typemethod in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ objc = 5;
+ iflist = DefInfoFunction;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ iflist = &iflistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&iflist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (iflist[i]) {
+ case BIfArgsIdx:
+ if (mcode && mcode->argListPtr) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ if ((imPtr->flags & ITCL_ARG_SPEC) != 0) {
+ if (imPtr->usagePtr == NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->usagePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->usagePtr), -1);
+ }
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ }
+ break;
+
+ case BIfBodyIdx:
+ if (mcode && Itcl_IsMemberCodeImplemented(mcode)) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(mcode->bodyPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ break;
+
+ case BIfNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ break;
+
+ case BIfProtectIdx:
+ val = Itcl_ProtectionStr(imPtr->protection);
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+
+ case BIfTypeIdx:
+ val = "typemethod";
+ objPtr = Tcl_NewStringObj(val, -1);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available commands.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->functions, &place);
+ while (hPtr) {
+ int useIt = 1;
+
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(hPtr);
+ if (!(imPtr->flags & ITCL_TYPE_METHOD)) {
+ useIt = 0;
+ }
+ if (useIt) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(imPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoMethodsCmd()
+ *
+ * Returns information regarding the methods for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypeMethodsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoTypeMethodsCmd", objc, objv);
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc > 1) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ name = "create";
+ if ((pattern == NULL) || Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ name = "destroy";
+ if ((pattern == NULL) || Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ name = "info";
+ if ((pattern == NULL) || Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(name, -1));
+ }
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ name = Tcl_GetString(imPtr->namePtr);
+ if (strcmp(name, "*") == 0) {
+ continue;
+ }
+ if (strcmp(name, "create") == 0) {
+ continue;
+ }
+ if (strcmp(name, "destroy") == 0) {
+ continue;
+ }
+ if (strcmp(name, "info") == 0) {
+ continue;
+ }
+ if (imPtr->flags & ITCL_TYPE_METHOD) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(imPtr->namePtr), -1));
+ }
+ }
+ }
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ name = Tcl_GetString(idmPtr->namePtr);
+ if (strcmp(name, "*") == 0) {
+ continue;
+ }
+ if (strcmp(name, "create") == 0) {
+ continue;
+ }
+ if (strcmp(name, "destroy") == 0) {
+ continue;
+ }
+ if (strcmp(name, "info") == 0) {
+ continue;
+ }
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch((const char *)name, pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(Tcl_GetString(idmPtr->namePtr), -1));
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypeVarsCmd()
+ *
+ * Returns information regarding variables for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypeVarsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoTypeVarsCmd", objc, objv);
+ if (objc > 2) {
+ Tcl_AppendResult(interp,
+ "wrong # args should be: info typevars ?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(ivPtr, &iclsPtr->variables) {
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(Tcl_GetString(ivPtr->namePtr), pattern)) {
+ if (ivPtr->flags & ITCL_TYPE_VARIABLE) {
+ Tcl_ListObjAppendElement(interp, listPtr, ivPtr->fullNamePtr);
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypeVariableCmd()
+ *
+ * Returns information regarding a typevariable for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoTypeVariableCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ ItclClass *iclsPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclVariable *ivPtr;
+ ItclVarLookup *vlookup;
+ ItclHierIter hier;
+ char *varName;
+ const char *val;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-init", "-name", "-protection", "-type",
+ "-value", (char*)NULL
+ };
+ enum BIvIdx {
+ BIvInitIdx,
+ BIvNameIdx,
+ BIvProtectIdx,
+ BIvTypeIdx,
+ BIvValueIdx
+ } *ivlist, ivlistStorage[5];
+
+ static enum BIvIdx DefInfoVariable[5] = {
+ BIvProtectIdx,
+ BIvTypeIdx,
+ BIvNameIdx,
+ BIvInitIdx,
+ BIvValueIdx
+ };
+
+ ItclShowArgs(1, "Itcl_BiInfoTypeVariableCmd", objc, objv);
+ resultPtr = NULL;
+ objPtr = NULL;
+ varName = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info typevariable ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?varName? ?-protection? ?-type? ?-name? ?-init? ?-config? ?-value?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ varName = Tcl_GetString(*objv);
+ objc--; objv++;
+ }
+
+ /*
+ * Return info for a specific variable.
+ */
+ if (varName) {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->resolveVars, varName);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", varName, "\" isn't a typevariable in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ ivPtr = vlookup->ivPtr;
+ if (!(ivPtr->flags & ITCL_TYPE_VARIABLE)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", varName, "\" isn't a typevariable in class \"",
+ contextIclsPtr->nsPtr->fullName, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ ivlist = DefInfoVariable;
+ objc = 5;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ivlist = &ivlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ivlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ivlist[i]) {
+ case BIvInitIdx:
+ /*
+ * If this is the built-in "this" variable, then
+ * report the object name as its initialization string.
+ */
+ if ((ivPtr->flags & ITCL_THIS_VAR) != 0) {
+ if ((contextIoPtr != NULL) &&
+ (contextIoPtr->accessCmd != NULL)) {
+ objPtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_GetCommandFullName(
+ contextIoPtr->iclsPtr->interp,
+ contextIoPtr->accessCmd, objPtr);
+ } else {
+ objPtr = Tcl_NewStringObj("<objectName>", -1);
+ }
+ } else {
+ if (vlookup->ivPtr->init) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(vlookup->ivPtr->init), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("<undefined>", -1);
+ }
+ }
+ break;
+
+ case BIvNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ break;
+
+ case BIvProtectIdx:
+ val = Itcl_ProtectionStr(ivPtr->protection);
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BIvTypeIdx:
+ val = ((ivPtr->flags & ITCL_COMMON) != 0)
+ ? "common" : "variable";
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+
+ case BIvValueIdx:
+ if ((ivPtr->flags & ITCL_COMMON) != 0) {
+ val = Itcl_GetCommonVar(interp,
+ Tcl_GetString(ivPtr->fullNamePtr),
+ ivPtr->iclsPtr);
+ } else {
+ if (contextIoPtr == NULL) {
+ if (objc > 1) {
+ Tcl_DecrRefCount(resultPtr);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp,
+ "cannot access object-specific info ",
+ "without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ } else {
+ val = Itcl_GetInstanceVar(interp,
+ Tcl_GetString(ivPtr->namePtr),
+ contextIoPtr, ivPtr->iclsPtr);
+ }
+ }
+ if (val == NULL) {
+ val = "<undefined>";
+ }
+ objPtr = Tcl_NewStringObj((const char *)val, -1);
+ break;
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ }
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, Tcl_GetString(resultPtr), NULL);
+ Tcl_DecrRefCount(resultPtr);
+ } else {
+
+ /*
+ * Return the list of available variables. Report the built-in
+ * "this" variable only once, for the most-specific class.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->variables, &place);
+ while (hPtr) {
+ ivPtr = (ItclVariable*)Tcl_GetHashValue(hPtr);
+ if (ivPtr->flags & ITCL_TYPE_VAR) {
+ if ((ivPtr->flags & ITCL_THIS_VAR) != 0) {
+ if (iclsPtr == contextIclsPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+ } else {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL,
+ resultPtr, objPtr);
+ }
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoVariablesCmd()
+ *
+ * Returns information regarding typevariables for an object. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoVariablesCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(1, "Itcl_BiInfoVariablesCmd", objc, objv);
+ Tcl_AppendResult(interp, "Itcl_BiInfoVariablesCmd not yet implemented\n",
+ NULL);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoWidgetadaptorCmd()
+ *
+ * Returns information regarding a widgetadaptor. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoWidgetadaptorCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Namespace *contextNs = NULL;
+ Tcl_Obj *objPtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ char *name;
+
+ ItclShowArgs(1, "Itcl_BiInfoWidgetadaptorCmd", objc, objv);
+ if (objc != 1) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"info widgetadaptor\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ contextIclsPtr = NULL;
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ /* try it the hard way */
+ ClientData clientData;
+ ItclObjectInfo *infoPtr;
+ Tcl_Object oPtr;
+ clientData = Itcl_GetCallFrameClientData(interp);
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ if (clientData != NULL) {
+ oPtr = Tcl_ObjectContextObject(clientData);
+ contextIoPtr = Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ if ((contextIoPtr == NULL) || (contextIclsPtr == NULL)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info widgetadaptor ... }", -1));
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * If there is an object context, then return the most-specific
+ * class for the object. Otherwise, return the class namespace
+ * name. Use normal class names when possible.
+ */
+ if (contextIoPtr) {
+ contextNs = contextIoPtr->iclsPtr->nsPtr;
+ } else {
+ assert(contextIclsPtr != NULL);
+ assert(contextIclsPtr->nsPtr != NULL);
+#ifdef NEW_PROTO_RESOLVER
+ contextNs = contextIclsPtr->nsPtr;
+#else
+ if (contextIclsPtr->infoPtr->useOldResolvers) {
+ contextNs = contextIclsPtr->nsPtr;
+ } else {
+ contextNs = contextIclsPtr->nsPtr;
+ }
+#endif
+ }
+
+ name = contextNs->fullName;
+ if (!(contextIclsPtr->flags & ITCL_WIDGETADAPTOR)) {
+ Tcl_AppendResult(interp, "object or class is no widgetadaptor", NULL);
+ return TCL_ERROR;
+ }
+ objPtr = Tcl_NewStringObj(name, -1);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoInstancesCmd()
+ *
+ * Returns information regarding instances. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoInstancesCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoInstancesCmd", objc, objv);
+ if (objc > 2) {
+ Tcl_AppendResult(interp,
+ "wrong # args should be: info instances ?pattern?", NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = NULL;
+ pattern = NULL;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "cannot get context ", (char*)NULL);
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ infoPtr = (ItclObjectInfo *)clientData;
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(ioPtr, &infoPtr->objects) {
+ /* FIXME need to scan the inheritance too */
+ if (ioPtr->iclsPtr == iclsPtr) {
+ if (ioPtr->iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ objPtr = Tcl_NewStringObj(Tcl_GetCommandName(interp,
+ ioPtr->accessCmd), -1);
+ } else {
+ objPtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ }
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(Tcl_GetString(objPtr), pattern)) {
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ } else {
+ Tcl_DecrRefCount(objPtr);
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedOptionsCmd()
+ *
+ * Returns information regarding delegated options. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedOptionsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *objPtr2;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedOptionsCmd", objc, objv);
+ pattern = NULL;
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info delegated ",
+ "options ?pattern?", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(idoPtr, &iclsPtr->delegatedOptions) {
+ if (iclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ name = Tcl_GetString(idoPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idoPtr->namePtr);
+ if (idoPtr->icPtr != NULL) {
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idoPtr->icPtr->namePtr);
+ } else {
+ objPtr2 = Tcl_NewStringObj("", -1);
+ Tcl_IncrRefCount(objPtr2);
+ Tcl_ListObjAppendElement(interp, objPtr, objPtr2);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedMethodsCmd()
+ *
+ * Returns information regarding delegated methods. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedMethodsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *objPtr2;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedMethodsCmd", objc, objv);
+ pattern = NULL;
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info delegated ",
+ "methods ?pattern?", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (iclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ name = Tcl_GetString(idmPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ if ((idmPtr->flags & ITCL_TYPE_METHOD) == 0) {
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idmPtr->namePtr);
+ if (idmPtr->icPtr != NULL) {
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idmPtr->icPtr->namePtr);
+ } else {
+ objPtr2 = Tcl_NewStringObj("", -1);
+ Tcl_IncrRefCount(objPtr2);
+ Tcl_ListObjAppendElement(interp, objPtr, objPtr2);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoTypeMethodsCmd()
+ *
+ * Returns information regarding delegated type methods. This command
+ * can be invoked with or without an object context:
+ *
+ *
+ * Returns a status TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedTypeMethodsCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *listPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *objPtr2;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *name;
+ const char *pattern;
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedTypeMethodsCmd", objc, objv);
+ pattern = NULL;
+ if (objc > 2) {
+ Tcl_AppendResult(interp, "wrong # args should be: info delegated ",
+ "typemethods ?pattern?", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc == 2) {
+ pattern = Tcl_GetString(objv[1]);
+ }
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr != NULL) {
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ listPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (iclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|ITCL_WIDGET|ITCL_ECLASS)) {
+ name = Tcl_GetString(idmPtr->namePtr);
+ if ((pattern == NULL) ||
+ Tcl_StringMatch(name, pattern)) {
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ objPtr = Tcl_NewListObj(0, NULL);
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idmPtr->namePtr);
+ if (idmPtr->icPtr != NULL) {
+ Tcl_ListObjAppendElement(interp, objPtr,
+ idmPtr->icPtr->namePtr);
+ } else {
+ objPtr2 = Tcl_NewStringObj("", -1);
+ Tcl_IncrRefCount(objPtr2);
+ Tcl_ListObjAppendElement(interp, objPtr, objPtr2);
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, objPtr);
+ }
+ }
+ }
+ }
+ Tcl_SetObjResult(interp, listPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedUnknownCmd()
+ *
+ * the unknown handler for the ::itcl::builtin::Info::delagted ensemble
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedUnknownCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *objPtr;
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedUnknownCmd", objc, objv);
+ /* produce usage message */
+ objPtr = Tcl_NewStringObj(
+ "wrong # args: should be one of...\n", -1);
+ ItclGetInfoDelegatedUsage(interp, objPtr, (ItclObjectInfo *)clientData);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedOptionCmd()
+ *
+ * Returns information regarding class options.
+ * Handles the following syntax:
+ *
+ * info delegated option ?optionName? ?-name? ?-resource? ?-class?
+ * ?-component? ?-as? ?-exceptions?
+ *
+ * If the ?optionName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedOptionCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashSearch place;
+ Tcl_Namespace *nsPtr;
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *optionNamePtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclObjectInfo *infoPtr;
+ ItclDelegatedOption *idoptPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ char *optionName;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-as", "-class", "-component", "-exceptions",
+ "-name", "-resource", (char*)NULL
+ };
+ enum BOptIdx {
+ BOptAsIdx, BOptClassIdx, BOptComponentIdx, BOptExceptionsIdx,
+ BOptNameIdx, BOptResourceIdx
+ } *ioptlist, ioptlistStorage[6];
+
+ static enum BOptIdx DefInfoOption[6] = {
+ BOptNameIdx,
+ BOptResourceIdx,
+ BOptClassIdx,
+ BOptComponentIdx,
+ BOptAsIdx,
+ BOptExceptionsIdx
+ };
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedOptionCmd", objc, objv);
+ optionName = NULL;
+ objPtr = NULL;
+ resultPtr = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info delegated option ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+ nsPtr = Itcl_GetUplevelNamespace(interp, 1);
+ infoPtr = contextIclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "cannot find class name for namespace \"",
+ nsPtr->fullName, "\"", NULL);
+ return TCL_ERROR;
+ }
+ contextIclsPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * Process args:
+ * ?optionName? ?-name? ?-resource? ?-class?
+ * ?-as? ?-exceptions?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ optionName = Tcl_GetString(*objv);
+ objc--;
+ objv++;
+ }
+
+ /*
+ * Return info for a specific option.
+ */
+ if (optionName) {
+ optionNamePtr = Tcl_NewStringObj(optionName, -1);
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedOptions,
+ (char *)optionNamePtr);
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", optionName, "\" isn't an option in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ idoptPtr = (ItclDelegatedOption*)Tcl_GetHashValue(hPtr);
+
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ ioptlist = DefInfoOption;
+ objc = 6;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ioptlist = &ioptlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ioptlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ioptlist[i]) {
+ case BOptAsIdx:
+ if (idoptPtr->asPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idoptPtr->asPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptExceptionsIdx:
+ {
+ Tcl_Obj *entryObj;
+ int hadEntries;
+ hadEntries = 0;
+ objPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(entryObj, &idoptPtr->exceptions) {
+ Tcl_ListObjAppendElement(interp, objPtr, entryObj);
+ }
+ if (!hadEntries) {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ }
+ break;
+ case BOptResourceIdx:
+ if (idoptPtr->resourceNamePtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idoptPtr->resourceNamePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptClassIdx:
+ if (idoptPtr->classNamePtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idoptPtr->classNamePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptComponentIdx:
+ if (idoptPtr->icPtr != NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idoptPtr->icPtr->namePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idoptPtr->namePtr), -1);
+ break;
+
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available options.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_IncrRefCount(resultPtr);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->delegatedOptions, &place);
+ while (hPtr) {
+ idoptPtr = (ItclDelegatedOption*)Tcl_GetHashValue(hPtr);
+ objPtr = idoptPtr->namePtr;
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr, objPtr);
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedMethodCmd()
+ *
+ * Returns information regarding class options.
+ * Handles the following syntax:
+ *
+ * info delegated method ?methodName? ?-name?
+ * ?-component? ?-as? ?-using? ?-exceptions?
+ *
+ * If the ?optionName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedMethodCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashSearch place;
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *cmdNamePtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ char *cmdName;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-as", "-component", "-exceptions",
+ "-name", "-using", (char*)NULL
+ };
+ enum BOptIdx {
+ BOptAsIdx,
+ BOptComponentIdx,
+ BOptExceptionsIdx,
+ BOptNameIdx,
+ BOptUsingIdx
+ } *ioptlist, ioptlistStorage[5];
+
+ static enum BOptIdx DefInfoOption[5] = {
+ BOptNameIdx,
+ BOptComponentIdx,
+ BOptAsIdx,
+ BOptUsingIdx,
+ BOptExceptionsIdx
+ };
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedMethodCmd", objc, objv);
+ cmdName = NULL;
+ objPtr = NULL;
+ resultPtr = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info delegated method ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?methodName? ?-name? ?-using?
+ * ?-as? ?-component? ?-exceptions?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ cmdName = Tcl_GetString(*objv);
+ objc--;
+ objv++;
+ }
+
+ /*
+ * Return info for a specific option.
+ */
+ if (cmdName) {
+ cmdNamePtr = Tcl_NewStringObj(cmdName, -1);
+ if (contextIoPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedFunctions,
+ (char *)cmdNamePtr);
+ } else {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions,
+ (char *)cmdNamePtr);
+ }
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a delegated method in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ idmPtr = (ItclDelegatedFunction*)Tcl_GetHashValue(hPtr);
+ if (!(idmPtr->flags & ITCL_METHOD)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a delegated method in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ ioptlist = DefInfoOption;
+ objc = 5;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ioptlist = &ioptlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ioptlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ioptlist[i]) {
+ case BOptAsIdx:
+ if (idmPtr->asPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->asPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptExceptionsIdx:
+ {
+ Tcl_Obj *entryObj;
+ int hadEntries;
+ hadEntries = 0;
+ objPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(entryObj, &idmPtr->exceptions) {
+ Tcl_ListObjAppendElement(interp, objPtr, entryObj);
+ }
+ if (!hadEntries) {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ }
+ break;
+ case BOptUsingIdx:
+ if (idmPtr->usingPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->usingPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptComponentIdx:
+ if (idmPtr->icPtr != NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->icPtr->namePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->namePtr), -1);
+ break;
+
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available options.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_IncrRefCount(resultPtr);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->delegatedFunctions, &place);
+ while (hPtr) {
+ idmPtr = (ItclDelegatedFunction *)Tcl_GetHashValue(hPtr);
+ if (idmPtr->flags & ITCL_METHOD) {
+ objPtr = idmPtr->namePtr;
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BiInfoDelegatedTypeMethodCmd()
+ *
+ * Returns information regarding class options.
+ * Handles the following syntax:
+ *
+ * info delegated typemethod ?methodName? ?-name?
+ * ?-component? ?-as? ?-exceptions?
+ *
+ * If the ?optionName? is not specified, then a list of all known
+ * data members is returned. Otherwise, the information for a
+ * specific member is returned. Returns a status TCL_OK/TCL_ERROR
+ * to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_BiInfoDelegatedTypeMethodCmd(
+ ClientData clientData, /* ItclObjectInfo Ptr */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+
+ FOREACH_HASH_DECLS;
+ Tcl_HashSearch place;
+ Tcl_Obj *resultPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *cmdNamePtr;
+ ItclClass *contextIclsPtr;
+ ItclObject *contextIoPtr;
+ ItclDelegatedFunction *idmPtr;
+ ItclHierIter hier;
+ ItclClass *iclsPtr;
+ char *cmdName;
+ int i;
+ int result;
+
+ static const char *options[] = {
+ "-as", "-component", "-exceptions",
+ "-name", "-using", (char*)NULL
+ };
+ enum BOptIdx {
+ BOptAsIdx,
+ BOptComponentIdx,
+ BOptExceptionsIdx,
+ BOptNameIdx,
+ BOptUsingIdx
+ } *ioptlist, ioptlistStorage[5];
+
+ static enum BOptIdx DefInfoOption[5] = {
+ BOptNameIdx,
+ BOptComponentIdx,
+ BOptAsIdx,
+ BOptUsingIdx,
+ BOptExceptionsIdx
+ };
+
+ ItclShowArgs(1, "Itcl_BiInfoDelegatedTypeMethodCmd", objc, objv);
+ cmdName = NULL;
+ objPtr = NULL;
+ resultPtr = NULL;
+ contextIclsPtr = NULL;
+ /*
+ * If this command is not invoked within a class namespace,
+ * signal an error.
+ */
+ if (Itcl_GetContext(interp, &contextIclsPtr, &contextIoPtr) != TCL_OK) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\nget info like this instead: "
+ "\n namespace eval className { info delegated type method ... }", -1));
+ return TCL_ERROR;
+ }
+ if (contextIoPtr != NULL) {
+ contextIclsPtr = contextIoPtr->iclsPtr;
+ }
+
+ /*
+ * Process args:
+ * ?methodName? ?-name? ?-using?
+ * ?-as? ?-component? ?-exceptions?
+ */
+ objv++; /* skip over command name */
+ objc--;
+
+ if (objc > 0) {
+ cmdName = Tcl_GetString(*objv);
+ objc--;
+ objv++;
+ }
+
+ /*
+ * Return info for a specific option.
+ */
+ if (cmdName) {
+ cmdNamePtr = Tcl_NewStringObj(cmdName, -1);
+ if (contextIoPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectDelegatedFunctions,
+ (char *)cmdNamePtr);
+ } else {
+ hPtr = Tcl_FindHashEntry(&contextIclsPtr->delegatedFunctions,
+ (char *)cmdNamePtr);
+ }
+ if (hPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a delegated typemethod in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ idmPtr = (ItclDelegatedFunction*)Tcl_GetHashValue(hPtr);
+ if (!(idmPtr->flags & ITCL_TYPE_METHOD)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", cmdName, "\" isn't a delegated typemethod in object \"",
+ Tcl_GetString(contextIoPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * By default, return everything.
+ */
+ if (objc == 0) {
+ ioptlist = DefInfoOption;
+ objc = 5;
+ } else {
+
+ /*
+ * Otherwise, scan through all remaining flags and
+ * figure out what to return.
+ */
+ ioptlist = &ioptlistStorage[0];
+ for (i=0 ; i < objc; i++) {
+ result = Tcl_GetIndexFromObj(interp, objv[i],
+ options, "option", 0, (int*)(&ioptlist[i]));
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ if (objc > 1) {
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ }
+
+ for (i=0 ; i < objc; i++) {
+ switch (ioptlist[i]) {
+ case BOptAsIdx:
+ if (idmPtr->asPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->asPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptExceptionsIdx:
+ {
+ Tcl_Obj *entryObj;
+ int hadEntries;
+ hadEntries = 0;
+ objPtr = Tcl_NewListObj(0, NULL);
+ FOREACH_HASH_VALUE(entryObj, &idmPtr->exceptions) {
+ Tcl_ListObjAppendElement(interp, objPtr, entryObj);
+ }
+ if (!hadEntries) {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ }
+ break;
+ case BOptUsingIdx:
+ if (idmPtr->usingPtr) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->usingPtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptComponentIdx:
+ if (idmPtr->icPtr != NULL) {
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->icPtr->namePtr), -1);
+ } else {
+ objPtr = Tcl_NewStringObj("", -1);
+ }
+ break;
+
+ case BOptNameIdx:
+ objPtr = Tcl_NewStringObj(
+ Tcl_GetString(idmPtr->namePtr), -1);
+ break;
+
+ }
+
+ if (objc == 1) {
+ resultPtr = objPtr;
+ } else {
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ } else {
+
+ /*
+ * Return the list of available options.
+ */
+ resultPtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);
+ Tcl_IncrRefCount(resultPtr);
+ Itcl_InitHierIter(&hier, contextIclsPtr);
+ while ((iclsPtr=Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr->delegatedFunctions, &place);
+ while (hPtr) {
+ idmPtr = (ItclDelegatedFunction *)Tcl_GetHashValue(hPtr);
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ objPtr = idmPtr->namePtr;
+ Tcl_ListObjAppendElement((Tcl_Interp*)NULL, resultPtr,
+ objPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ Tcl_SetObjResult(interp, resultPtr);
+ }
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclInt.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclInt.h
new file mode 100644
index 0000000..5134023
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclInt.h
@@ -0,0 +1,854 @@
+/*
+ * itclInt.h --
+ *
+ * This file contains internal definitions for the C-implemented part of a
+ * Itcl
+ *
+ * Copyright (c) 2007 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+
+/*
+ * Used to tag functions that are only to be visible within the module being
+ * built and not outside it (where this is supported by the linker).
+ */
+
+#ifndef MODULE_SCOPE
+# ifdef __cplusplus
+# define MODULE_SCOPE extern "C"
+# else
+# define MODULE_SCOPE extern
+# endif
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <tclOO.h>
+#include "itcl.h"
+#include "itclMigrate2TclCore.h"
+#include "itclTclIntStubsFcn.h"
+
+/*
+ * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
+ * quotation marks).
+ */
+
+#ifndef STRINGIFY
+# define STRINGIFY(x) STRINGIFY1(x)
+# define STRINGIFY1(x) #x
+#endif
+
+/*
+ * Since the Tcl/Tk distribution doesn't perform any asserts,
+ * dynamic loading can fail to find the __assert function.
+ * As a workaround, we'll include our own.
+ */
+
+#undef assert
+#define DEBUG 1
+#ifndef DEBUG
+#define assert(EX) ((void)0)
+#else
+#define assert(EX) (void)((EX) || (Itcl_Assert(STRINGIFY(EX), __FILE__, __LINE__), 0))
+#endif /* DEBUG */
+
+#define ITCL_INTERP_DATA "itcl_data"
+#define ITCL_TK_VERSION "8.6"
+
+/*
+ * Convenience macros for iterating through hash tables. FOREACH_HASH_DECLS
+ * sets up the declarations needed for the main macro, FOREACH_HASH, which
+ * does the actual iteration. FOREACH_HASH_VALUE is a restricted version that
+ * only iterates over values.
+ */
+
+#define FOREACH_HASH_DECLS \
+ Tcl_HashEntry *hPtr;Tcl_HashSearch search
+#define FOREACH_HASH(key,val,tablePtr) \
+ for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \
+ ((key)=(void *)Tcl_GetHashKey((tablePtr),hPtr),\
+ (val)=Tcl_GetHashValue(hPtr),1):0; hPtr=Tcl_NextHashEntry(&search))
+#define FOREACH_HASH_VALUE(val,tablePtr) \
+ for(hPtr=Tcl_FirstHashEntry((tablePtr),&search); hPtr!=NULL ? \
+ ((val)=Tcl_GetHashValue(hPtr),1):0;hPtr=Tcl_NextHashEntry(&search))
+
+/*
+ * What sort of size of things we like to allocate.
+ */
+
+#define ALLOC_CHUNK 8
+
+#define ITCL_VARIABLES_NAMESPACE "::itcl::internal::variables"
+#define ITCL_COMMANDS_NAMESPACE "::itcl::internal::commands"
+
+#ifdef ITCL_PRESERVE_DEBUG
+#define ITCL_PRESERVE_BUCKET_SIZE 50
+#define ITCL_PRESERVE_INCR 1
+#define ITCL_PRESERVE_DECR -1
+#define ITCL_PRESERVE_DELETED 0
+
+typedef struct ItclPreserveInfoEntry {
+ int type;
+ int line;
+ const char * fileName;
+} ItclPreserveInfoEntry;
+
+typedef struct ItclPreserveInfo {
+ size_t refCount;
+ ClientData clientData;
+ size_t size;
+ size_t numEntries;
+ ItclPreserveInfoEntry *entries;
+} ItclPreserveInfo;
+
+#endif
+
+
+typedef struct ItclFoundation {
+ Itcl_Stack methodCallStack;
+ Tcl_Command dispatchCommand;
+} ItclFoundation;
+
+typedef struct ItclArgList {
+ struct ItclArgList *nextPtr; /* pointer to next argument */
+ Tcl_Obj *namePtr; /* name of the argument */
+ Tcl_Obj *defaultValuePtr; /* default value or NULL if none */
+} ItclArgList;
+
+/*
+ * Common info for managing all known objects.
+ * Each interpreter has one of these data structures stored as
+ * clientData in the "itcl" namespace. It is also accessible
+ * as associated data via the key ITCL_INTERP_DATA.
+ */
+struct ItclClass;
+struct ItclObject;
+struct ItclMemberFunc;
+struct EnsembleInfo;
+struct ItclDelegatedOption;
+struct ItclDelegatedFunction;
+
+typedef struct ItclObjectInfo {
+ Tcl_Interp *interp; /* interpreter that manages this info */
+ Tcl_HashTable objects; /* list of all known objects key is
+ * ioPtr */
+ Tcl_HashTable objectCmds; /* list of known objects using accessCmd */
+ Tcl_HashTable unused5; /* list of known objects using namePtr */
+ Tcl_HashTable classes; /* list of all known classes,
+ * key is iclsPtr */
+ Tcl_HashTable nameClasses; /* maps from fullNamePtr to iclsPtr */
+ Tcl_HashTable namespaceClasses; /* maps from nsPtr to iclsPtr */
+ Tcl_HashTable procMethods; /* maps from procPtr to mFunc */
+ Tcl_HashTable instances; /* maps from instanceNumber to ioPtr */
+ Tcl_HashTable unused8; /* maps from ioPtr to instanceNumber */
+ Tcl_HashTable frameContext; /* maps frame to context stack */
+ Tcl_HashTable classTypes; /* maps from class type i.e. "widget"
+ * to define value i.e. ITCL_WIDGET */
+ int protection; /* protection level currently in effect */
+ int useOldResolvers; /* whether to use the "old" style
+ * resolvers or the CallFrame resolvers */
+ Itcl_Stack clsStack; /* stack of class definitions currently
+ * being parsed */
+ Itcl_Stack unused; /* Removed */
+ Itcl_Stack unused6; /* obsolete field */
+ struct ItclObject *currIoPtr; /* object currently being constructed
+ * set only during calling of constructors
+ * otherwise NULL */
+ Tcl_ObjectMetadataType *class_meta_type;
+ /* type for getting the Itcl class info
+ * from a TclOO Tcl_Object */
+ const Tcl_ObjectMetadataType *object_meta_type;
+ /* type for getting the Itcl object info
+ * from a TclOO Tcl_Object */
+ Tcl_Object unused1; /* the root object of Itcl */
+ Tcl_Class clazzClassPtr; /* the root class of Itcl */
+ struct EnsembleInfo *ensembleInfo;
+ struct ItclClass *currContextIclsPtr;
+ /* context class for delegated option
+ * handling */
+ int currClassFlags; /* flags for the class just in creation */
+ int buildingWidget; /* set if in construction of a widget */
+ int unparsedObjc; /* number options not parsed by
+ ItclExtendedConfigure/-Cget function */
+ Tcl_Obj **unparsedObjv; /* options not parsed by
+ ItclExtendedConfigure/-Cget function */
+ int functionFlags; /* used for creating of ItclMemberCode */
+ int unused7; /* used for having a unique key for objects
+ * for use in mytypemethod etc. */
+ struct ItclDelegatedOption *currIdoPtr;
+ /* the current delegated option info */
+ int inOptionHandling; /* used to indicate for type/widget ...
+ * that there is an option processing
+ * and methods are allowed to be called */
+ /* these are the Tcl_Obj Ptrs for the clazz unknown procedure */
+ /* need to store them to be able to free them at the end */
+ int itclWidgetInitted; /* set to 1 if itclWidget.tcl has already
+ * been called
+ */
+ int itclHullCmdsInitted; /* set to 1 if itclHullCmds.tcl has already
+ * been called
+ */
+ Tcl_Obj *unused2;
+ Tcl_Obj *unused3;
+ Tcl_Obj *unused4;
+ Tcl_Obj *infoVarsPtr;
+ Tcl_Obj *infoVars3Ptr;
+ Tcl_Obj *infoVars4Ptr;
+ Tcl_Obj *typeDestructorArgumentPtr;
+ struct ItclObject *lastIoPtr; /* last object constructed */
+ Tcl_Command infoCmd;
+} ItclObjectInfo;
+
+typedef struct EnsembleInfo {
+ Tcl_HashTable ensembles; /* list of all known ensembles */
+ Tcl_HashTable subEnsembles; /* list of all known subensembles */
+ int numEnsembles;
+ Tcl_Namespace *ensembleNsPtr;
+} EnsembleInfo;
+/*
+ * Representation for each [incr Tcl] class.
+ */
+#define ITCL_CLASS 0x1
+#define ITCL_TYPE 0x2
+#define ITCL_WIDGET 0x4
+#define ITCL_WIDGETADAPTOR 0x8
+#define ITCL_ECLASS 0x10
+#define ITCL_NWIDGET 0x20
+#define ITCL_WIDGET_FRAME 0x40
+#define ITCL_WIDGET_LABEL_FRAME 0x80
+#define ITCL_WIDGET_TOPLEVEL 0x100
+#define ITCL_WIDGET_TTK_FRAME 0x200
+#define ITCL_WIDGET_TTK_LABEL_FRAME 0x400
+#define ITCL_WIDGET_TTK_TOPLEVEL 0x800
+#define ITCL_CLASS_IS_DELETED 0x1000
+#define ITCL_CLASS_IS_DESTROYED 0x2000
+#define ITCL_CLASS_NS_IS_DESTROYED 0x4000
+#define ITCL_CLASS_IS_RENAMED 0x8000
+#define ITCL_CLASS_IS_FREED 0x10000
+#define ITCL_CLASS_DERIVED_RELEASED 0x20000
+#define ITCL_CLASS_NS_TEARDOWN 0x40000
+#define ITCL_CLASS_NO_VARNS_DELETE 0x80000
+#define ITCL_CLASS_SHOULD_VARNS_DELETE 0x100000
+#define ITCL_CLASS_DESTRUCTOR_CALLED 0x400000
+
+
+typedef struct ItclClass {
+ Tcl_Obj *namePtr; /* class name */
+ Tcl_Obj *fullNamePtr; /* fully qualified class name */
+ Tcl_Interp *interp; /* interpreter that manages this info */
+ Tcl_Namespace *nsPtr; /* namespace representing class scope */
+ Tcl_Command accessCmd; /* access command for creating instances */
+ Tcl_Command thisCmd; /* needed for deletion of class */
+
+ struct ItclObjectInfo *infoPtr;
+ /* info about all known objects
+ * and other stuff like stacks */
+ Itcl_List bases; /* list of base classes */
+ Itcl_List derived; /* list of all derived classes */
+ Tcl_HashTable heritage; /* table of all base classes. Look up
+ * by pointer to class definition. This
+ * provides fast lookup for inheritance
+ * tests. */
+ Tcl_Obj *initCode; /* initialization code for new objs */
+ Tcl_HashTable variables; /* definitions for all data members
+ in this class. Look up simple string
+ names and get back ItclVariable* ptrs */
+ Tcl_HashTable options; /* definitions for all option members
+ in this class. Look up simple string
+ names and get back ItclOption* ptrs */
+ Tcl_HashTable components; /* definitions for all component members
+ in this class. Look up simple string
+ names and get back ItclComponent* ptrs */
+ Tcl_HashTable functions; /* definitions for all member functions
+ in this class. Look up simple string
+ names and get back ItclMemberFunc* ptrs */
+ Tcl_HashTable delegatedOptions; /* definitions for all delegated options
+ in this class. Look up simple string
+ names and get back
+ ItclDelegatedOption * ptrs */
+ Tcl_HashTable delegatedFunctions; /* definitions for all delegated methods
+ or procs in this class. Look up simple
+ string names and get back
+ ItclDelegatedFunction * ptrs */
+ Tcl_HashTable methodVariables; /* definitions for all methodvariable members
+ in this class. Look up simple string
+ names and get back
+ ItclMethodVariable* ptrs */
+ int numInstanceVars; /* number of instance vars in variables
+ table */
+ Tcl_HashTable classCommons; /* used for storing variable namespace
+ * string for Tcl_Resolve */
+ Tcl_HashTable resolveVars; /* all possible names for variables in
+ * this class (e.g., x, foo::x, etc.) */
+ Tcl_HashTable resolveCmds; /* all possible names for functions in
+ * this class (e.g., x, foo::x, etc.) */
+ Tcl_HashTable contextCache; /* cache for function contexts */
+ struct ItclMemberFunc *unused2;
+ /* the class constructor or NULL */
+ struct ItclMemberFunc *unused3;
+ /* the class destructor or NULL */
+ struct ItclMemberFunc *unused1;
+ Tcl_Resolve *resolvePtr;
+ Tcl_Obj *widgetClassPtr; /* class name for widget if class is a
+ * ::itcl::widget */
+ Tcl_Obj *hullTypePtr; /* hulltype name for widget if class is a
+ * ::itcl::widget */
+ Tcl_Object oPtr; /* TclOO class object */
+ Tcl_Class clsPtr; /* TclOO class */
+ int numCommons; /* number of commons in this class */
+ int numVariables; /* number of variables in this class */
+ int numOptions; /* number of options in this class */
+ int unique; /* unique number for #auto generation */
+ int flags; /* maintains class status */
+ int callRefCount; /* prevent deleting of class if refcount>1 */
+ Tcl_Obj *typeConstructorPtr; /* initialization for types */
+ int destructorHasBeenCalled; /* prevent multiple invocations of destrcutor */
+ int refCount;
+} ItclClass;
+
+typedef struct ItclHierIter {
+ ItclClass *current; /* current position in hierarchy */
+ Itcl_Stack stack; /* stack used for traversal */
+} ItclHierIter;
+
+#define ITCL_OBJECT_IS_DELETED 0x01
+#define ITCL_OBJECT_IS_DESTRUCTED 0x02
+#define ITCL_OBJECT_IS_DESTROYED 0x04
+#define ITCL_OBJECT_IS_RENAMED 0x08
+#define ITCL_OBJECT_CLASS_DESTRUCTED 0x10
+#define ITCL_TCLOO_OBJECT_IS_DELETED 0x20
+#define ITCL_OBJECT_DESTRUCT_ERROR 0x40
+#define ITCL_OBJECT_SHOULD_VARNS_DELETE 0x80
+#define ITCL_OBJECT_ROOT_METHOD 0x8000
+
+/*
+ * Representation for each [incr Tcl] object.
+ */
+typedef struct ItclObject {
+ ItclClass *iclsPtr; /* most-specific class */
+ Tcl_Command accessCmd; /* object access command */
+
+ Tcl_HashTable* constructed; /* temp storage used during construction */
+ Tcl_HashTable* destructed; /* temp storage used during destruction */
+ Tcl_HashTable objectVariables;
+ /* used for storing Tcl_Var entries for
+ * variable resolving, key is ivPtr of
+ * variable, value is varPtr */
+ Tcl_HashTable objectOptions; /* definitions for all option members
+ in this object. Look up option namePtr
+ names and get back ItclOption* ptrs */
+ Tcl_HashTable objectComponents; /* definitions for all component members
+ in this object. Look up component namePtr
+ names and get back ItclComponent* ptrs */
+ Tcl_HashTable objectMethodVariables;
+ /* definitions for all methodvariable members
+ in this object. Look up methodvariable
+ namePtr names and get back
+ ItclMethodVariable* ptrs */
+ Tcl_HashTable objectDelegatedOptions;
+ /* definitions for all delegated option
+ members in this object. Look up option
+ namePtr names and get back
+ ItclOption* ptrs */
+ Tcl_HashTable objectDelegatedFunctions;
+ /* definitions for all delegated function
+ members in this object. Look up function
+ namePtr names and get back
+ ItclMemberFunc * ptrs */
+ Tcl_HashTable contextCache; /* cache for function contexts */
+ Tcl_Obj *namePtr;
+ Tcl_Obj *origNamePtr; /* the original name before any rename */
+ Tcl_Obj *createNamePtr; /* the temp name before any rename
+ * mostly used for widgetadaptor
+ * because that hijackes the name
+ * often when installing the hull */
+ Tcl_Interp *interp;
+ ItclObjectInfo *infoPtr;
+ Tcl_Obj *varNsNamePtr;
+ Tcl_Object oPtr; /* the TclOO object */
+ Tcl_Resolve *resolvePtr;
+ int flags;
+ int callRefCount; /* prevent deleting of object if refcount > 1 */
+ Tcl_Obj *hullWindowNamePtr; /* the window path name for the hull
+ * (before renaming in installhull) */
+ int destructorHasBeenCalled; /* is set when the destructor is called
+ * to avoid callin destructor twice */
+ int noComponentTrace; /* don't call component traces if
+ * setting components in DelegationInstall */
+ int hadConstructorError; /* needed for multiple calls of CallItclObjectCmd */
+ int refCount;
+} ItclObject;
+
+#define ITCL_IGNORE_ERRS 0x002 /* useful for construction/destruction */
+
+typedef struct ItclResolveInfo {
+ int flags;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+} ItclResolveInfo;
+
+#define ITCL_RESOLVE_CLASS 0x01
+#define ITCL_RESOLVE_OBJECT 0x02
+
+/*
+ * Implementation for any code body in an [incr Tcl] class.
+ */
+typedef struct ItclMemberCode {
+ int flags; /* flags describing implementation */
+ int argcount; /* number of args in arglist */
+ int maxargcount; /* max number of args in arglist */
+ Tcl_Obj *usagePtr; /* usage string for error messages */
+ Tcl_Obj *argumentPtr; /* the function arguments */
+ Tcl_Obj *bodyPtr; /* the function body */
+ ItclArgList *argListPtr; /* the parsed arguments */
+ union {
+ Tcl_CmdProc *argCmd; /* (argc,argv) C implementation */
+ Tcl_ObjCmdProc *objCmd; /* (objc,objv) C implementation */
+ } cfunc;
+ ClientData clientData; /* client data for C implementations */
+} ItclMemberCode;
+
+/*
+ * Flag bits for ItclMemberCode:
+ */
+#define ITCL_IMPLEMENT_NONE 0x001 /* no implementation */
+#define ITCL_IMPLEMENT_TCL 0x002 /* Tcl implementation */
+#define ITCL_IMPLEMENT_ARGCMD 0x004 /* (argc,argv) C implementation */
+#define ITCL_IMPLEMENT_OBJCMD 0x008 /* (objc,objv) C implementation */
+#define ITCL_IMPLEMENT_C 0x00c /* either kind of C implementation */
+
+#define Itcl_IsMemberCodeImplemented(mcode) \
+ (((mcode)->flags & ITCL_IMPLEMENT_NONE) == 0)
+
+/*
+ * Flag bits for ItclMember: functions and variables
+ */
+#define ITCL_COMMON 0x010 /* non-zero => is a "proc" or common
+ * variable */
+
+/*
+ * Flag bits for ItclMember: functions
+ */
+#define ITCL_CONSTRUCTOR 0x020 /* non-zero => is a constructor */
+#define ITCL_DESTRUCTOR 0x040 /* non-zero => is a destructor */
+#define ITCL_ARG_SPEC 0x080 /* non-zero => has an argument spec */
+#define ITCL_BODY_SPEC 0x100 /* non-zero => has an body spec */
+#define ITCL_BUILTIN 0x400 /* non-zero => built-in method */
+#define ITCL_COMPONENT 0x800 /* non-zero => component */
+#define ITCL_TYPE_METHOD 0x1000 /* non-zero => typemethod */
+#define ITCL_METHOD 0x2000 /* non-zero => method */
+
+/*
+ * Flag bits for ItclMember: variables
+ */
+#define ITCL_THIS_VAR 0x20 /* non-zero => built-in "this" variable */
+#define ITCL_OPTIONS_VAR 0x40 /* non-zero => built-in "itcl_options"
+ * variable */
+#define ITCL_TYPE_VAR 0x80 /* non-zero => built-in "type" variable */
+ /* no longer used ??? */
+#define ITCL_SELF_VAR 0x100 /* non-zero => built-in "self" variable */
+#define ITCL_SELFNS_VAR 0x200 /* non-zero => built-in "selfns"
+ * variable */
+#define ITCL_WIN_VAR 0x400 /* non-zero => built-in "win" variable */
+#define ITCL_COMPONENT_VAR 0x800 /* non-zero => component variable */
+#define ITCL_HULL_VAR 0x1000 /* non-zero => built-in "itcl_hull"
+ * variable */
+#define ITCL_OPTION_READONLY 0x2000 /* non-zero => readonly */
+#define ITCL_VARIABLE 0x4000 /* non-zero => normal variable */
+#define ITCL_TYPE_VARIABLE 0x8000 /* non-zero => typevariable */
+#define ITCL_OPTION_INITTED 0x10000 /* non-zero => option has been initialized */
+#define ITCL_OPTION_COMP_VAR 0x20000 /* variable to collect option components of extendedclass */
+
+/*
+ * Instance components.
+ */
+struct ItclVariable;
+typedef struct ItclComponent {
+ Tcl_Obj *namePtr; /* member name */
+ struct ItclVariable *ivPtr; /* variable for this component */
+ int flags;
+ int haveKeptOptions;
+ Tcl_HashTable keptOptions; /* table of options to keep */
+} ItclComponent;
+
+#define ITCL_COMPONENT_INHERIT 0x01
+#define ITCL_COMPONENT_PUBLIC 0x02
+
+typedef struct ItclDelegatedFunction {
+ Tcl_Obj *namePtr;
+ ItclComponent *icPtr;
+ Tcl_Obj *asPtr;
+ Tcl_Obj *usingPtr;
+ Tcl_HashTable exceptions;
+ int flags;
+} ItclDelegatedFunction;
+
+/*
+ * Representation of member functions in an [incr Tcl] class.
+ */
+typedef struct ItclMemberFunc {
+ Tcl_Obj* namePtr; /* member name */
+ Tcl_Obj* fullNamePtr; /* member name with "class::" qualifier */
+ ItclClass* iclsPtr; /* class containing this member */
+ int protection; /* protection level */
+ int flags; /* flags describing member (see above) */
+ ItclObjectInfo *infoPtr;
+ ItclMemberCode *codePtr; /* code associated with member */
+ Tcl_Command accessCmd; /* Tcl command installed for this function */
+ int argcount; /* number of args in arglist */
+ int maxargcount; /* max number of args in arglist */
+ Tcl_Obj *usagePtr; /* usage string for error messages */
+ Tcl_Obj *argumentPtr; /* the function arguments */
+ Tcl_Obj *builtinArgumentPtr; /* the function arguments for builtin functions */
+ Tcl_Obj *origArgsPtr; /* the argument string of the original definition */
+ Tcl_Obj *bodyPtr; /* the function body */
+ ItclArgList *argListPtr; /* the parsed arguments */
+ ItclClass *declaringClassPtr; /* the class which declared the method/proc */
+ ClientData tmPtr; /* TclOO methodPtr */
+ ItclDelegatedFunction *idmPtr;
+ /* if the function is delegated != NULL */
+ int refCount;
+} ItclMemberFunc;
+
+/*
+ * Instance variables.
+ */
+typedef struct ItclVariable {
+ Tcl_Obj *namePtr; /* member name */
+ Tcl_Obj *fullNamePtr; /* member name with "class::" qualifier */
+ ItclClass *iclsPtr; /* class containing this member */
+ ItclObjectInfo *infoPtr;
+ ItclMemberCode *codePtr; /* code associated with member */
+ Tcl_Obj *init; /* initial value */
+ Tcl_Obj *arrayInitPtr; /* initial value if variable should be array */
+ int protection; /* protection level */
+ int flags; /* flags describing member (see below) */
+ int initted; /* is set when first time initted, to check
+ * for example itcl_hull var, which can be only
+ * initialized once */
+} ItclVariable;
+
+
+struct ItclOption;
+
+typedef struct ItclDelegatedOption {
+ Tcl_Obj *namePtr;
+ Tcl_Obj *resourceNamePtr;
+ Tcl_Obj *classNamePtr;
+ struct ItclOption *ioptPtr; /* the option name or null for "*" */
+ ItclComponent *icPtr; /* the component where the delegation goes
+ * to */
+ Tcl_Obj *asPtr;
+ Tcl_HashTable exceptions; /* exceptions from delegation */
+} ItclDelegatedOption;
+
+/*
+ * Instance options.
+ */
+typedef struct ItclOption {
+ /* within a class hierarchy there must be only
+ * one option with the same name !! */
+ Tcl_Obj *namePtr; /* member name */
+ Tcl_Obj *fullNamePtr; /* member name with "class::" qualifier */
+ Tcl_Obj *resourceNamePtr;
+ Tcl_Obj *classNamePtr;
+ ItclClass *iclsPtr; /* class containing this member */
+ int protection; /* protection level */
+ int flags; /* flags describing member (see below) */
+ ItclMemberCode *codePtr; /* code associated with member */
+ Tcl_Obj *defaultValuePtr; /* initial value */
+ Tcl_Obj *cgetMethodPtr;
+ Tcl_Obj *cgetMethodVarPtr;
+ Tcl_Obj *configureMethodPtr;
+ Tcl_Obj *configureMethodVarPtr;
+ Tcl_Obj *validateMethodPtr;
+ Tcl_Obj *validateMethodVarPtr;
+ ItclDelegatedOption *idoPtr;
+ /* if the option is delegated != NULL */
+} ItclOption;
+
+/*
+ * Instance methodvariables.
+ */
+typedef struct ItclMethodVariable {
+ Tcl_Obj *namePtr; /* member name */
+ Tcl_Obj *fullNamePtr; /* member name with "class::" qualifier */
+ ItclClass *iclsPtr; /* class containing this member */
+ int protection; /* protection level */
+ int flags; /* flags describing member (see below) */
+ Tcl_Obj *defaultValuePtr;
+ Tcl_Obj *callbackPtr;
+} ItclMethodVariable;
+
+#define VAR_TYPE_VARIABLE 1
+#define VAR_TYPE_COMMON 2
+
+typedef struct ItclClassVarInfo {
+ int type;
+ int protection;
+ int varNum;
+ Tcl_Namespace *nsPtr;
+ Tcl_Namespace *declaringNsPtr;
+} ItclClassVarInfo;
+
+#define CMD_TYPE_METHOD 1
+#define CMD_TYPE_PROC 2
+
+typedef struct ItclClassCmdInfo {
+ int type;
+ int protection;
+ int cmdNum;
+ Tcl_Namespace *nsPtr;
+ Tcl_Namespace *declaringNsPtr;
+} ItclClassCmdInfo;
+
+/*
+ * Instance variable lookup entry.
+ */
+typedef struct ItclVarLookup {
+ ItclVariable* ivPtr; /* variable definition */
+ int usage; /* number of uses for this record */
+ int accessible; /* non-zero => accessible from class with
+ * this lookup record in its resolveVars */
+ char *leastQualName; /* simplist name for this variable, with
+ * the fewest qualifiers. This string is
+ * taken from the resolveVars table, so
+ * it shouldn't be freed. */
+ int varNum;
+ ItclClassVarInfo *classVarInfoPtr;
+ Tcl_Var varPtr;
+} ItclVarLookup;
+
+/*
+ * Instance command lookup entry.
+ */
+typedef struct ItclCmdLookup {
+ ItclMemberFunc* imPtr; /* function definition */
+ int cmdNum;
+ ItclClassCmdInfo *classCmdInfoPtr;
+ Tcl_Command cmdPtr;
+} ItclCmdLookup;
+
+typedef struct ItclCallContext {
+ int objectFlags;
+ Tcl_Namespace *nsPtr;
+ ItclObject *ioPtr;
+ ItclMemberFunc *imPtr;
+ int refCount;
+} ItclCallContext;
+
+/*
+ * The macro below is used to modify a "char" value (e.g. by casting
+ * it to an unsigned character) so that it can be used safely with
+ * macros such as isspace.
+ */
+
+#define UCHAR(c) ((unsigned char) (c))
+/*
+ * Macros used to cast between pointers and integers (e.g. when storing an int
+ * in ClientData), on 64-bit architectures they avoid gcc warning about "cast
+ * to/from pointer from/to integer of different size".
+ */
+
+#if !defined(INT2PTR) && !defined(PTR2INT)
+# if defined(HAVE_INTPTR_T) || defined(intptr_t)
+# define INT2PTR(p) ((void*)(intptr_t)(p))
+# define PTR2INT(p) ((int)(intptr_t)(p))
+# else
+# define INT2PTR(p) ((void*)(p))
+# define PTR2INT(p) ((int)(p))
+# endif
+#endif
+
+#ifdef ITCL_DEBUG
+MODULE_SCOPE int _itcl_debug_level;
+MODULE_SCOPE void ItclShowArgs(int level, const char *str, int objc,
+ Tcl_Obj * const* objv);
+#else
+#define ItclShowArgs(a,b,c,d)
+#endif
+
+MODULE_SCOPE Tcl_ObjCmdProc ItclCallCCommand;
+MODULE_SCOPE Tcl_ObjCmdProc ItclObjectUnknownCommand;
+MODULE_SCOPE int ItclCheckCallProc(ClientData clientData, Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr, Tcl_CallFrame *framePtr, int *isFinished);
+
+MODULE_SCOPE void ItclPreserveIMF(ItclMemberFunc *imPtr);
+MODULE_SCOPE void ItclReleaseIMF(ClientData imPtr);
+
+MODULE_SCOPE void ItclPreserveClass(ItclClass *iclsPtr);
+MODULE_SCOPE void ItclReleaseClass(ClientData iclsPtr);
+
+MODULE_SCOPE void ItclPreserveObject(ItclObject *ioPtr);
+MODULE_SCOPE void ItclReleaseObject(ClientData ioPtr);
+
+MODULE_SCOPE ItclFoundation *ItclGetFoundation(Tcl_Interp *interp);
+MODULE_SCOPE Tcl_ObjCmdProc ItclClassCommandDispatcher;
+MODULE_SCOPE Tcl_Command Itcl_CmdAliasProc(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *cmdName, ClientData clientData);
+MODULE_SCOPE Tcl_Var Itcl_VarAliasProc(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *VarName, ClientData clientData);
+MODULE_SCOPE int ItclIsClass(Tcl_Interp *interp, Tcl_Command cmd);
+MODULE_SCOPE int ItclCheckCallMethod(ClientData clientData, Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr, Tcl_CallFrame *framePtr, int *isFinished);
+MODULE_SCOPE int ItclAfterCallMethod(ClientData clientData, Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr, Tcl_Namespace *nsPtr, int result);
+MODULE_SCOPE void ItclReportObjectUsage(Tcl_Interp *interp,
+ ItclObject *contextIoPtr, Tcl_Namespace *callerNsPtr,
+ Tcl_Namespace *contextNsPtr);
+MODULE_SCOPE int ItclMapMethodNameProc(Tcl_Interp *interp, Tcl_Object oPtr,
+ Tcl_Class *startClsPtr, Tcl_Obj *methodObj);
+MODULE_SCOPE int ItclCreateArgList(Tcl_Interp *interp, const char *str,
+ int *argcPtr, int *maxArgcPtr, Tcl_Obj **usagePtr,
+ ItclArgList **arglistPtrPtr, ItclMemberFunc *imPtr,
+ const char *commandName);
+MODULE_SCOPE int ItclObjectCmd(ClientData clientData, Tcl_Interp *interp,
+ Tcl_Object oPtr, Tcl_Class clsPtr, int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE int ItclCreateObject (Tcl_Interp *interp, const char* name,
+ ItclClass *iclsPtr, int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE void ItclDeleteObjectVariablesNamespace(Tcl_Interp *interp,
+ ItclObject *ioPtr);
+MODULE_SCOPE void ItclDeleteClassVariablesNamespace(Tcl_Interp *interp,
+ ItclClass *iclsPtr);
+MODULE_SCOPE int ItclInfoInit(Tcl_Interp *interp, ItclObjectInfo *infoPtr);
+
+struct Tcl_ResolvedVarInfo;
+MODULE_SCOPE int Itcl_ClassCmdResolver(Tcl_Interp *interp, const char* name,
+ Tcl_Namespace *nsPtr, int flags, Tcl_Command *rPtr);
+MODULE_SCOPE int Itcl_ClassVarResolver(Tcl_Interp *interp, const char* name,
+ Tcl_Namespace *nsPtr, int flags, Tcl_Var *rPtr);
+MODULE_SCOPE int Itcl_ClassCompiledVarResolver(Tcl_Interp *interp,
+ const char* name, int length, Tcl_Namespace *nsPtr,
+ struct Tcl_ResolvedVarInfo **rPtr);
+MODULE_SCOPE int Itcl_ClassCmdResolver2(Tcl_Interp *interp, const char* name,
+ Tcl_Namespace *nsPtr, int flags, Tcl_Command *rPtr);
+MODULE_SCOPE int Itcl_ClassVarResolver2(Tcl_Interp *interp, const char* name,
+ Tcl_Namespace *nsPtr, int flags, Tcl_Var *rPtr);
+MODULE_SCOPE int Itcl_ClassCompiledVarResolver2(Tcl_Interp *interp,
+ const char* name, int length, Tcl_Namespace *nsPtr,
+ struct Tcl_ResolvedVarInfo **rPtr);
+MODULE_SCOPE int ItclSetParserResolver(Tcl_Namespace *nsPtr);
+MODULE_SCOPE void ItclProcErrorProc(Tcl_Interp *interp, Tcl_Obj *procNameObj);
+MODULE_SCOPE int Itcl_CreateOption (Tcl_Interp *interp, ItclClass *iclsPtr,
+ ItclOption *ioptPtr);
+MODULE_SCOPE int Itcl_CreateMethodVariable (Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *name, Tcl_Obj *defaultPtr,
+ Tcl_Obj *callbackPtr, ItclMethodVariable **imvPtr);
+MODULE_SCOPE int DelegationInstall(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr);
+MODULE_SCOPE ItclClass *ItclNamespace2Class(Tcl_Namespace *nsPtr);
+MODULE_SCOPE const char* ItclGetCommonInstanceVar(Tcl_Interp *interp,
+ const char *name, const char *name2, ItclObject *contextIoPtr,
+ ItclClass *contextIclsPtr);
+MODULE_SCOPE int ItclCreateMethod(Tcl_Interp* interp, ItclClass *iclsPtr,
+ Tcl_Obj *namePtr, const char* arglist, const char* body,
+ ItclMemberFunc **imPtrPtr);
+MODULE_SCOPE int Itcl_WidgetParseInit(Tcl_Interp *interp,
+ ItclObjectInfo *infoPtr);
+MODULE_SCOPE void ItclDeleteObjectMetadata(ClientData clientData);
+MODULE_SCOPE void ItclDeleteClassMetadata(ClientData clientData);
+MODULE_SCOPE void ItclDeleteArgList(ItclArgList *arglistPtr);
+MODULE_SCOPE int Itcl_ClassOptionCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int DelegatedOptionsInstall(Tcl_Interp *interp,
+ ItclClass *iclsPtr);
+MODULE_SCOPE int Itcl_HandleDelegateOptionCmd(Tcl_Interp *interp,
+ ItclObject *ioPtr, ItclClass *iclsPtr, ItclDelegatedOption **idoPtrPtr,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int Itcl_HandleDelegateMethodCmd(Tcl_Interp *interp,
+ ItclObject *ioPtr, ItclClass *iclsPtr,
+ ItclDelegatedFunction **idmPtrPtr, int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int DelegateFunction(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr, Tcl_Obj *componentNamePtr,
+ ItclDelegatedFunction *idmPtr);
+MODULE_SCOPE int ItclInitObjectMethodVariables(Tcl_Interp *interp,
+ ItclObject *ioPtr, ItclClass *iclsPtr, const char *name);
+MODULE_SCOPE int InitTclOOFunctionPointers(Tcl_Interp *interp);
+MODULE_SCOPE ItclOption* ItclNewOption(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr, Tcl_Obj *namePtr, const char *resourceName,
+ const char *className, char *init, ItclMemberCode *mCodePtr);
+MODULE_SCOPE int ItclParseOption(ItclObjectInfo *infoPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[], ItclClass *iclsPtr,
+ ItclObject *ioPtr, ItclOption **ioptPtrPtr);
+MODULE_SCOPE void ItclDestroyClassNamesp(ClientData cdata);
+MODULE_SCOPE int ExpandDelegateAs(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr, ItclDelegatedFunction *idmPtr,
+ const char *funcName, Tcl_Obj *listPtr);
+MODULE_SCOPE int ItclCheckForInitializedComponents(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclObject *ioPtr);
+MODULE_SCOPE int ItclCreateDelegatedFunction(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *methodNamePtr, ItclComponent *icPtr,
+ Tcl_Obj *targetPtr, Tcl_Obj *usingPtr, Tcl_Obj *exceptionsPtr,
+ ItclDelegatedFunction **idmPtrPtr);
+MODULE_SCOPE void ItclDeleteDelegatedOption(char *cdata);
+MODULE_SCOPE void Itcl_FinishList();
+MODULE_SCOPE void ItclDeleteDelegatedFunction(ItclDelegatedFunction *idmPtr);
+MODULE_SCOPE void ItclFinishEnsemble(ItclObjectInfo *infoPtr);
+MODULE_SCOPE int Itcl_EnsembleDeleteCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE int ItclAddClassesDictInfo(Tcl_Interp *interp, ItclClass *iclsPtr);
+MODULE_SCOPE int ItclDeleteClassesDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr);
+MODULE_SCOPE int ItclAddObjectsDictInfo(Tcl_Interp *interp, ItclObject *ioPtr);
+MODULE_SCOPE int ItclDeleteObjectsDictInfo(Tcl_Interp *interp,
+ ItclObject *ioPtr);
+MODULE_SCOPE int ItclAddOptionDictInfo(Tcl_Interp *interp, ItclClass *iclsPtr,
+ ItclOption *ioptPtr);
+MODULE_SCOPE int ItclAddDelegatedOptionDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclDelegatedOption *idoPtr);
+MODULE_SCOPE int ItclAddClassComponentDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclComponent *icPtr);
+MODULE_SCOPE int ItclAddClassVariableDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclVariable *ivPtr);
+MODULE_SCOPE int ItclAddClassFunctionDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclMemberFunc *imPtr);
+MODULE_SCOPE int ItclAddClassDelegatedFunctionDictInfo(Tcl_Interp *interp,
+ ItclClass *iclsPtr, ItclDelegatedFunction *idmPtr);
+MODULE_SCOPE int ItclClassCreateObject(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiMyProcCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiInstallComponentCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiCallInstanceCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiGetInstanceVarCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiMyTypeMethodCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiMyMethodCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiMyTypeVarCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiMyVarCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_BiItclHullCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_ThisCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_ExtendedClassCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_TypeClassCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_AddObjectOptionCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_AddDelegatedOptionCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_AddDelegatedFunctionCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_SetComponentCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_ClassHullTypeCmd;
+MODULE_SCOPE Tcl_ObjCmdProc Itcl_ClassWidgetClassCmd;
+
+typedef int (ItclRootMethodProc)(ItclObject *ioPtr, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+
+MODULE_SCOPE const Tcl_MethodType itclRootMethodType;
+MODULE_SCOPE ItclRootMethodProc ItclUnknownGuts;
+MODULE_SCOPE ItclRootMethodProc ItclConstructGuts;
+MODULE_SCOPE ItclRootMethodProc ItclInfoGuts;
+
+#include "itcl2TclOO.h"
+#ifdef NEW_PROTO_RESOLVER
+#include "itclVarsAndCmds.h"
+#endif
+
+/*
+ * Include all the private API, generated from itcl.decls.
+ */
+
+#include "itclIntDecls.h"
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclIntDecls.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclIntDecls.h
new file mode 100644
index 0000000..5c68fb3
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclIntDecls.h
@@ -0,0 +1,1046 @@
+/*
+ * This file is (mostly) automatically generated from itcl.decls.
+ */
+
+#ifndef _ITCLINTDECLS
+#define _ITCLINTDECLS
+
+/* !BEGIN!: Do not edit below this line. */
+
+#define ITCLINT_STUBS_EPOCH 0
+#define ITCLINT_STUBS_REVISION 150
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Exported function declarations:
+ */
+
+/* 0 */
+ITCLAPI int Itcl_IsClassNamespace(Tcl_Namespace *namesp);
+/* 1 */
+ITCLAPI int Itcl_IsClass(Tcl_Command cmd);
+/* 2 */
+ITCLAPI ItclClass * Itcl_FindClass(Tcl_Interp *interp, const char *path,
+ int autoload);
+/* 3 */
+ITCLAPI int Itcl_FindObject(Tcl_Interp *interp, const char *name,
+ ItclObject **roPtr);
+/* 4 */
+ITCLAPI int Itcl_IsObject(Tcl_Command cmd);
+/* 5 */
+ITCLAPI int Itcl_ObjectIsa(ItclObject *contextObj,
+ ItclClass *cdefn);
+/* 6 */
+ITCLAPI int Itcl_Protection(Tcl_Interp *interp, int newLevel);
+/* 7 */
+ITCLAPI const char * Itcl_ProtectionStr(int pLevel);
+/* 8 */
+ITCLAPI int Itcl_CanAccess(ItclMemberFunc *memberPtr,
+ Tcl_Namespace *fromNsPtr);
+/* 9 */
+ITCLAPI int Itcl_CanAccessFunc(ItclMemberFunc *mfunc,
+ Tcl_Namespace *fromNsPtr);
+/* Slot 10 is reserved */
+/* 11 */
+ITCLAPI void Itcl_ParseNamespPath(const char *name,
+ Tcl_DString *buffer, const char **head,
+ const char **tail);
+/* 12 */
+ITCLAPI int Itcl_DecodeScopedCommand(Tcl_Interp *interp,
+ const char *name, Tcl_Namespace **rNsPtr,
+ char **rCmdPtr);
+/* 13 */
+ITCLAPI int Itcl_EvalArgs(Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 14 */
+ITCLAPI Tcl_Obj * Itcl_CreateArgs(Tcl_Interp *interp,
+ const char *string, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 15 is reserved */
+/* Slot 16 is reserved */
+/* 17 */
+ITCLAPI int Itcl_GetContext(Tcl_Interp *interp,
+ ItclClass **iclsPtrPtr,
+ ItclObject **ioPtrPtr);
+/* 18 */
+ITCLAPI void Itcl_InitHierIter(ItclHierIter *iter,
+ ItclClass *iclsPtr);
+/* 19 */
+ITCLAPI void Itcl_DeleteHierIter(ItclHierIter *iter);
+/* 20 */
+ITCLAPI ItclClass * Itcl_AdvanceHierIter(ItclHierIter *iter);
+/* 21 */
+ITCLAPI int Itcl_FindClassesCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 22 */
+ITCLAPI int Itcl_FindObjectsCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 23 is reserved */
+/* 24 */
+ITCLAPI int Itcl_DelClassCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 25 */
+ITCLAPI int Itcl_DelObjectCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 26 */
+ITCLAPI int Itcl_ScopeCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 27 */
+ITCLAPI int Itcl_CodeCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 28 */
+ITCLAPI int Itcl_StubCreateCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 29 */
+ITCLAPI int Itcl_StubExistsCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 30 */
+ITCLAPI int Itcl_IsStub(Tcl_Command cmd);
+/* 31 */
+ITCLAPI int Itcl_CreateClass(Tcl_Interp *interp,
+ const char *path, ItclObjectInfo *info,
+ ItclClass **rPtr);
+/* 32 */
+ITCLAPI int Itcl_DeleteClass(Tcl_Interp *interp,
+ ItclClass *iclsPtr);
+/* 33 */
+ITCLAPI Tcl_Namespace * Itcl_FindClassNamespace(Tcl_Interp *interp,
+ const char *path);
+/* 34 */
+ITCLAPI int Itcl_HandleClass(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 35 is reserved */
+/* Slot 36 is reserved */
+/* Slot 37 is reserved */
+/* 38 */
+ITCLAPI void Itcl_BuildVirtualTables(ItclClass *iclsPtr);
+/* 39 */
+ITCLAPI int Itcl_CreateVariable(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *name,
+ char *init, char *config,
+ ItclVariable **ivPtr);
+/* 40 */
+ITCLAPI void Itcl_DeleteVariable(char *cdata);
+/* 41 */
+ITCLAPI const char * Itcl_GetCommonVar(Tcl_Interp *interp,
+ const char *name, ItclClass *contextClass);
+/* Slot 42 is reserved */
+/* Slot 43 is reserved */
+/* 44 */
+ITCLAPI int Itcl_CreateObject(Tcl_Interp *interp,
+ const char*name, ItclClass *iclsPtr,
+ int objc, Tcl_Obj *const objv[],
+ ItclObject **rioPtr);
+/* 45 */
+ITCLAPI int Itcl_DeleteObject(Tcl_Interp *interp,
+ ItclObject *contextObj);
+/* 46 */
+ITCLAPI int Itcl_DestructObject(Tcl_Interp *interp,
+ ItclObject *contextObj, int flags);
+/* Slot 47 is reserved */
+/* 48 */
+ITCLAPI const char * Itcl_GetInstanceVar(Tcl_Interp *interp,
+ const char *name, ItclObject *contextIoPtr,
+ ItclClass *contextIclsPtr);
+/* Slot 49 is reserved */
+/* 50 */
+ITCLAPI int Itcl_BodyCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+/* 51 */
+ITCLAPI int Itcl_ConfigBodyCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 52 */
+ITCLAPI int Itcl_CreateMethod(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *namePtr,
+ const char *arglist, const char *body);
+/* 53 */
+ITCLAPI int Itcl_CreateProc(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *namePtr,
+ const char *arglist, const char *body);
+/* 54 */
+ITCLAPI int Itcl_CreateMemberFunc(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *name,
+ const char *arglist, const char *body,
+ ItclMemberFunc **mfuncPtr);
+/* 55 */
+ITCLAPI int Itcl_ChangeMemberFunc(Tcl_Interp *interp,
+ ItclMemberFunc *mfunc, const char *arglist,
+ const char *body);
+/* 56 */
+ITCLAPI void Itcl_DeleteMemberFunc(char *cdata);
+/* 57 */
+ITCLAPI int Itcl_CreateMemberCode(Tcl_Interp *interp,
+ ItclClass *iclsPtr, const char *arglist,
+ const char *body, ItclMemberCode **mcodePtr);
+/* 58 */
+ITCLAPI void Itcl_DeleteMemberCode(char *cdata);
+/* 59 */
+ITCLAPI int Itcl_GetMemberCode(Tcl_Interp *interp,
+ ItclMemberFunc *mfunc);
+/* Slot 60 is reserved */
+/* 61 */
+ITCLAPI int Itcl_EvalMemberCode(Tcl_Interp *interp,
+ ItclMemberFunc *mfunc,
+ ItclObject *contextObj, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 62 is reserved */
+/* Slot 63 is reserved */
+/* Slot 64 is reserved */
+/* Slot 65 is reserved */
+/* Slot 66 is reserved */
+/* 67 */
+ITCLAPI void Itcl_GetMemberFuncUsage(ItclMemberFunc *mfunc,
+ ItclObject *contextObj, Tcl_Obj *objPtr);
+/* 68 */
+ITCLAPI int Itcl_ExecMethod(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 69 */
+ITCLAPI int Itcl_ExecProc(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 70 is reserved */
+/* 71 */
+ITCLAPI int Itcl_ConstructBase(Tcl_Interp *interp,
+ ItclObject *contextObj,
+ ItclClass *contextClass);
+/* 72 */
+ITCLAPI int Itcl_InvokeMethodIfExists(Tcl_Interp *interp,
+ const char *name, ItclClass *contextClass,
+ ItclObject *contextObj, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 73 is reserved */
+/* 74 */
+ITCLAPI int Itcl_ReportFuncErrors(Tcl_Interp *interp,
+ ItclMemberFunc *mfunc,
+ ItclObject *contextObj, int result);
+/* 75 */
+ITCLAPI int Itcl_ParseInit(Tcl_Interp *interp,
+ ItclObjectInfo *info);
+/* 76 */
+ITCLAPI int Itcl_ClassCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 77 */
+ITCLAPI int Itcl_ClassInheritCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 78 */
+ITCLAPI int Itcl_ClassProtectionCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 79 */
+ITCLAPI int Itcl_ClassConstructorCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 80 */
+ITCLAPI int Itcl_ClassDestructorCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 81 */
+ITCLAPI int Itcl_ClassMethodCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 82 */
+ITCLAPI int Itcl_ClassProcCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 83 */
+ITCLAPI int Itcl_ClassVariableCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 84 */
+ITCLAPI int Itcl_ClassCommonCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 85 */
+ITCLAPI int Itcl_ParseVarResolver(Tcl_Interp *interp,
+ const char *name, Tcl_Namespace *contextNs,
+ int flags, Tcl_Var *rPtr);
+/* 86 */
+ITCLAPI int Itcl_BiInit(Tcl_Interp *interp,
+ ItclObjectInfo *infoPtr);
+/* 87 */
+ITCLAPI int Itcl_InstallBiMethods(Tcl_Interp *interp,
+ ItclClass *cdefn);
+/* 88 */
+ITCLAPI int Itcl_BiIsaCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 89 */
+ITCLAPI int Itcl_BiConfigureCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 90 */
+ITCLAPI int Itcl_BiCgetCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 91 */
+ITCLAPI int Itcl_BiChainCmd(ClientData dummy, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+/* 92 */
+ITCLAPI int Itcl_BiInfoClassCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 93 */
+ITCLAPI int Itcl_BiInfoInheritCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 94 */
+ITCLAPI int Itcl_BiInfoHeritageCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 95 */
+ITCLAPI int Itcl_BiInfoFunctionCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 96 */
+ITCLAPI int Itcl_BiInfoVariableCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 97 */
+ITCLAPI int Itcl_BiInfoBodyCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 98 */
+ITCLAPI int Itcl_BiInfoArgsCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 99 is reserved */
+/* 100 */
+ITCLAPI int Itcl_EnsembleInit(Tcl_Interp *interp);
+/* 101 */
+ITCLAPI int Itcl_CreateEnsemble(Tcl_Interp *interp,
+ const char *ensName);
+/* 102 */
+ITCLAPI int Itcl_AddEnsemblePart(Tcl_Interp *interp,
+ const char *ensName, const char *partName,
+ const char *usageInfo,
+ Tcl_ObjCmdProc *objProc,
+ ClientData clientData,
+ Tcl_CmdDeleteProc *deleteProc);
+/* 103 */
+ITCLAPI int Itcl_GetEnsemblePart(Tcl_Interp *interp,
+ const char *ensName, const char *partName,
+ Tcl_CmdInfo *infoPtr);
+/* 104 */
+ITCLAPI int Itcl_IsEnsemble(Tcl_CmdInfo *infoPtr);
+/* 105 */
+ITCLAPI int Itcl_GetEnsembleUsage(Tcl_Interp *interp,
+ const char *ensName, Tcl_Obj *objPtr);
+/* 106 */
+ITCLAPI int Itcl_GetEnsembleUsageForObj(Tcl_Interp *interp,
+ Tcl_Obj *ensObjPtr, Tcl_Obj *objPtr);
+/* 107 */
+ITCLAPI int Itcl_EnsembleCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 108 */
+ITCLAPI int Itcl_EnsPartCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 109 */
+ITCLAPI int Itcl_EnsembleErrorCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 110 is reserved */
+/* Slot 111 is reserved */
+/* Slot 112 is reserved */
+/* Slot 113 is reserved */
+/* Slot 114 is reserved */
+/* 115 */
+ITCLAPI void Itcl_Assert(const char *testExpr,
+ const char *fileName, int lineNum);
+/* 116 */
+ITCLAPI int Itcl_IsObjectCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 117 */
+ITCLAPI int Itcl_IsClassCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 118 is reserved */
+/* Slot 119 is reserved */
+/* Slot 120 is reserved */
+/* Slot 121 is reserved */
+/* Slot 122 is reserved */
+/* Slot 123 is reserved */
+/* Slot 124 is reserved */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+/* Slot 129 is reserved */
+/* Slot 130 is reserved */
+/* Slot 131 is reserved */
+/* Slot 132 is reserved */
+/* Slot 133 is reserved */
+/* Slot 134 is reserved */
+/* Slot 135 is reserved */
+/* Slot 136 is reserved */
+/* Slot 137 is reserved */
+/* Slot 138 is reserved */
+/* Slot 139 is reserved */
+/* 140 */
+ITCLAPI int Itcl_FilterAddCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 141 */
+ITCLAPI int Itcl_FilterDeleteCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 142 */
+ITCLAPI int Itcl_ForwardAddCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 143 */
+ITCLAPI int Itcl_ForwardDeleteCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 144 */
+ITCLAPI int Itcl_MixinAddCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 145 */
+ITCLAPI int Itcl_MixinDeleteCmd(ClientData clientData,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* Slot 146 is reserved */
+/* Slot 147 is reserved */
+/* Slot 148 is reserved */
+/* Slot 149 is reserved */
+/* Slot 150 is reserved */
+/* 151 */
+ITCLAPI int Itcl_BiInfoUnknownCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 152 */
+ITCLAPI int Itcl_BiInfoVarsCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 153 */
+ITCLAPI int Itcl_CanAccess2(ItclClass *iclsPtr, int protection,
+ Tcl_Namespace *fromNsPtr);
+/* Slot 154 is reserved */
+/* Slot 155 is reserved */
+/* Slot 156 is reserved */
+/* Slot 157 is reserved */
+/* Slot 158 is reserved */
+/* Slot 159 is reserved */
+/* 160 */
+ITCLAPI int Itcl_SetCallFrameResolver(Tcl_Interp *interp,
+ Tcl_Resolve *resolvePtr);
+/* 161 */
+ITCLAPI int ItclEnsembleSubCmd(ClientData clientData,
+ Tcl_Interp *interp, const char *ensembleName,
+ int objc, Tcl_Obj *const *objv,
+ const char *functionName);
+/* 162 */
+ITCLAPI Tcl_Namespace * Itcl_GetUplevelNamespace(Tcl_Interp *interp,
+ int level);
+/* 163 */
+ITCLAPI ClientData Itcl_GetCallFrameClientData(Tcl_Interp *interp);
+/* Slot 164 is reserved */
+/* 165 */
+ITCLAPI int Itcl_SetCallFrameNamespace(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr);
+/* 166 */
+ITCLAPI int Itcl_GetCallFrameObjc(Tcl_Interp *interp);
+/* 167 */
+ITCLAPI Tcl_Obj *const * Itcl_GetCallFrameObjv(Tcl_Interp *interp);
+/* 168 */
+ITCLAPI int Itcl_NWidgetCmd(ClientData infoPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 169 */
+ITCLAPI int Itcl_AddOptionCmd(ClientData infoPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 170 */
+ITCLAPI int Itcl_AddComponentCmd(ClientData infoPtr,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 171 */
+ITCLAPI int Itcl_BiInfoOptionCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 172 */
+ITCLAPI int Itcl_BiInfoComponentCmd(ClientData dummy,
+ Tcl_Interp *interp, int objc,
+ Tcl_Obj *const objv[]);
+/* 173 */
+ITCLAPI int Itcl_RenameCommand(Tcl_Interp *interp,
+ const char *oldName, const char *newName);
+/* 174 */
+ITCLAPI int Itcl_PushCallFrame(Tcl_Interp *interp,
+ Tcl_CallFrame *framePtr,
+ Tcl_Namespace *nsPtr, int isProcCallFrame);
+/* 175 */
+ITCLAPI void Itcl_PopCallFrame(Tcl_Interp *interp);
+/* 176 */
+ITCLAPI Tcl_CallFrame * Itcl_GetUplevelCallFrame(Tcl_Interp *interp,
+ int level);
+/* 177 */
+ITCLAPI Tcl_CallFrame * Itcl_ActivateCallFrame(Tcl_Interp *interp,
+ Tcl_CallFrame *framePtr);
+/* 178 */
+ITCLAPI const char* ItclSetInstanceVar(Tcl_Interp *interp,
+ const char *name, const char *name2,
+ const char *value, ItclObject *contextIoPtr,
+ ItclClass *contextIclsPtr);
+/* 179 */
+ITCLAPI Tcl_Obj * ItclCapitalize(const char *str);
+/* 180 */
+ITCLAPI int ItclClassBaseCmd(ClientData clientData,
+ Tcl_Interp *interp, int flags, int objc,
+ Tcl_Obj *const objv[],
+ ItclClass **iclsPtrPtr);
+/* 181 */
+ITCLAPI int ItclCreateComponent(Tcl_Interp *interp,
+ ItclClass *iclsPtr, Tcl_Obj *componentPtr,
+ int type, ItclComponent **icPtrPtr);
+/* 182 */
+ITCLAPI void Itcl_SetContext(Tcl_Interp *interp,
+ ItclObject *ioPtr);
+/* 183 */
+ITCLAPI void Itcl_UnsetContext(Tcl_Interp *interp);
+/* 184 */
+ITCLAPI const char * ItclGetInstanceVar(Tcl_Interp *interp,
+ const char *name, const char *name2,
+ ItclObject *ioPtr, ItclClass *iclsPtr);
+
+typedef struct ItclIntStubs {
+ int magic;
+ int epoch;
+ int revision;
+ void *hooks;
+
+ int (*itcl_IsClassNamespace) (Tcl_Namespace *namesp); /* 0 */
+ int (*itcl_IsClass) (Tcl_Command cmd); /* 1 */
+ ItclClass * (*itcl_FindClass) (Tcl_Interp *interp, const char *path, int autoload); /* 2 */
+ int (*itcl_FindObject) (Tcl_Interp *interp, const char *name, ItclObject **roPtr); /* 3 */
+ int (*itcl_IsObject) (Tcl_Command cmd); /* 4 */
+ int (*itcl_ObjectIsa) (ItclObject *contextObj, ItclClass *cdefn); /* 5 */
+ int (*itcl_Protection) (Tcl_Interp *interp, int newLevel); /* 6 */
+ const char * (*itcl_ProtectionStr) (int pLevel); /* 7 */
+ int (*itcl_CanAccess) (ItclMemberFunc *memberPtr, Tcl_Namespace *fromNsPtr); /* 8 */
+ int (*itcl_CanAccessFunc) (ItclMemberFunc *mfunc, Tcl_Namespace *fromNsPtr); /* 9 */
+ void (*reserved10)(void);
+ void (*itcl_ParseNamespPath) (const char *name, Tcl_DString *buffer, const char **head, const char **tail); /* 11 */
+ int (*itcl_DecodeScopedCommand) (Tcl_Interp *interp, const char *name, Tcl_Namespace **rNsPtr, char **rCmdPtr); /* 12 */
+ int (*itcl_EvalArgs) (Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 13 */
+ Tcl_Obj * (*itcl_CreateArgs) (Tcl_Interp *interp, const char *string, int objc, Tcl_Obj *const objv[]); /* 14 */
+ void (*reserved15)(void);
+ void (*reserved16)(void);
+ int (*itcl_GetContext) (Tcl_Interp *interp, ItclClass **iclsPtrPtr, ItclObject **ioPtrPtr); /* 17 */
+ void (*itcl_InitHierIter) (ItclHierIter *iter, ItclClass *iclsPtr); /* 18 */
+ void (*itcl_DeleteHierIter) (ItclHierIter *iter); /* 19 */
+ ItclClass * (*itcl_AdvanceHierIter) (ItclHierIter *iter); /* 20 */
+ int (*itcl_FindClassesCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 21 */
+ int (*itcl_FindObjectsCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 22 */
+ void (*reserved23)(void);
+ int (*itcl_DelClassCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 24 */
+ int (*itcl_DelObjectCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 25 */
+ int (*itcl_ScopeCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 26 */
+ int (*itcl_CodeCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 27 */
+ int (*itcl_StubCreateCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 28 */
+ int (*itcl_StubExistsCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 29 */
+ int (*itcl_IsStub) (Tcl_Command cmd); /* 30 */
+ int (*itcl_CreateClass) (Tcl_Interp *interp, const char *path, ItclObjectInfo *info, ItclClass **rPtr); /* 31 */
+ int (*itcl_DeleteClass) (Tcl_Interp *interp, ItclClass *iclsPtr); /* 32 */
+ Tcl_Namespace * (*itcl_FindClassNamespace) (Tcl_Interp *interp, const char *path); /* 33 */
+ int (*itcl_HandleClass) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 34 */
+ void (*reserved35)(void);
+ void (*reserved36)(void);
+ void (*reserved37)(void);
+ void (*itcl_BuildVirtualTables) (ItclClass *iclsPtr); /* 38 */
+ int (*itcl_CreateVariable) (Tcl_Interp *interp, ItclClass *iclsPtr, Tcl_Obj *name, char *init, char *config, ItclVariable **ivPtr); /* 39 */
+ void (*itcl_DeleteVariable) (char *cdata); /* 40 */
+ const char * (*itcl_GetCommonVar) (Tcl_Interp *interp, const char *name, ItclClass *contextClass); /* 41 */
+ void (*reserved42)(void);
+ void (*reserved43)(void);
+ int (*itcl_CreateObject) (Tcl_Interp *interp, const char*name, ItclClass *iclsPtr, int objc, Tcl_Obj *const objv[], ItclObject **rioPtr); /* 44 */
+ int (*itcl_DeleteObject) (Tcl_Interp *interp, ItclObject *contextObj); /* 45 */
+ int (*itcl_DestructObject) (Tcl_Interp *interp, ItclObject *contextObj, int flags); /* 46 */
+ void (*reserved47)(void);
+ const char * (*itcl_GetInstanceVar) (Tcl_Interp *interp, const char *name, ItclObject *contextIoPtr, ItclClass *contextIclsPtr); /* 48 */
+ void (*reserved49)(void);
+ int (*itcl_BodyCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 50 */
+ int (*itcl_ConfigBodyCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 51 */
+ int (*itcl_CreateMethod) (Tcl_Interp *interp, ItclClass *iclsPtr, Tcl_Obj *namePtr, const char *arglist, const char *body); /* 52 */
+ int (*itcl_CreateProc) (Tcl_Interp *interp, ItclClass *iclsPtr, Tcl_Obj *namePtr, const char *arglist, const char *body); /* 53 */
+ int (*itcl_CreateMemberFunc) (Tcl_Interp *interp, ItclClass *iclsPtr, Tcl_Obj *name, const char *arglist, const char *body, ItclMemberFunc **mfuncPtr); /* 54 */
+ int (*itcl_ChangeMemberFunc) (Tcl_Interp *interp, ItclMemberFunc *mfunc, const char *arglist, const char *body); /* 55 */
+ void (*itcl_DeleteMemberFunc) (char *cdata); /* 56 */
+ int (*itcl_CreateMemberCode) (Tcl_Interp *interp, ItclClass *iclsPtr, const char *arglist, const char *body, ItclMemberCode **mcodePtr); /* 57 */
+ void (*itcl_DeleteMemberCode) (char *cdata); /* 58 */
+ int (*itcl_GetMemberCode) (Tcl_Interp *interp, ItclMemberFunc *mfunc); /* 59 */
+ void (*reserved60)(void);
+ int (*itcl_EvalMemberCode) (Tcl_Interp *interp, ItclMemberFunc *mfunc, ItclObject *contextObj, int objc, Tcl_Obj *const objv[]); /* 61 */
+ void (*reserved62)(void);
+ void (*reserved63)(void);
+ void (*reserved64)(void);
+ void (*reserved65)(void);
+ void (*reserved66)(void);
+ void (*itcl_GetMemberFuncUsage) (ItclMemberFunc *mfunc, ItclObject *contextObj, Tcl_Obj *objPtr); /* 67 */
+ int (*itcl_ExecMethod) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 68 */
+ int (*itcl_ExecProc) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 69 */
+ void (*reserved70)(void);
+ int (*itcl_ConstructBase) (Tcl_Interp *interp, ItclObject *contextObj, ItclClass *contextClass); /* 71 */
+ int (*itcl_InvokeMethodIfExists) (Tcl_Interp *interp, const char *name, ItclClass *contextClass, ItclObject *contextObj, int objc, Tcl_Obj *const objv[]); /* 72 */
+ void (*reserved73)(void);
+ int (*itcl_ReportFuncErrors) (Tcl_Interp *interp, ItclMemberFunc *mfunc, ItclObject *contextObj, int result); /* 74 */
+ int (*itcl_ParseInit) (Tcl_Interp *interp, ItclObjectInfo *info); /* 75 */
+ int (*itcl_ClassCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 76 */
+ int (*itcl_ClassInheritCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 77 */
+ int (*itcl_ClassProtectionCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 78 */
+ int (*itcl_ClassConstructorCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 79 */
+ int (*itcl_ClassDestructorCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 80 */
+ int (*itcl_ClassMethodCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 81 */
+ int (*itcl_ClassProcCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 82 */
+ int (*itcl_ClassVariableCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 83 */
+ int (*itcl_ClassCommonCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 84 */
+ int (*itcl_ParseVarResolver) (Tcl_Interp *interp, const char *name, Tcl_Namespace *contextNs, int flags, Tcl_Var *rPtr); /* 85 */
+ int (*itcl_BiInit) (Tcl_Interp *interp, ItclObjectInfo *infoPtr); /* 86 */
+ int (*itcl_InstallBiMethods) (Tcl_Interp *interp, ItclClass *cdefn); /* 87 */
+ int (*itcl_BiIsaCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 88 */
+ int (*itcl_BiConfigureCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 89 */
+ int (*itcl_BiCgetCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 90 */
+ int (*itcl_BiChainCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 91 */
+ int (*itcl_BiInfoClassCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 92 */
+ int (*itcl_BiInfoInheritCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 93 */
+ int (*itcl_BiInfoHeritageCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 94 */
+ int (*itcl_BiInfoFunctionCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 95 */
+ int (*itcl_BiInfoVariableCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 96 */
+ int (*itcl_BiInfoBodyCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 97 */
+ int (*itcl_BiInfoArgsCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 98 */
+ void (*reserved99)(void);
+ int (*itcl_EnsembleInit) (Tcl_Interp *interp); /* 100 */
+ int (*itcl_CreateEnsemble) (Tcl_Interp *interp, const char *ensName); /* 101 */
+ int (*itcl_AddEnsemblePart) (Tcl_Interp *interp, const char *ensName, const char *partName, const char *usageInfo, Tcl_ObjCmdProc *objProc, ClientData clientData, Tcl_CmdDeleteProc *deleteProc); /* 102 */
+ int (*itcl_GetEnsemblePart) (Tcl_Interp *interp, const char *ensName, const char *partName, Tcl_CmdInfo *infoPtr); /* 103 */
+ int (*itcl_IsEnsemble) (Tcl_CmdInfo *infoPtr); /* 104 */
+ int (*itcl_GetEnsembleUsage) (Tcl_Interp *interp, const char *ensName, Tcl_Obj *objPtr); /* 105 */
+ int (*itcl_GetEnsembleUsageForObj) (Tcl_Interp *interp, Tcl_Obj *ensObjPtr, Tcl_Obj *objPtr); /* 106 */
+ int (*itcl_EnsembleCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 107 */
+ int (*itcl_EnsPartCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 108 */
+ int (*itcl_EnsembleErrorCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 109 */
+ void (*reserved110)(void);
+ void (*reserved111)(void);
+ void (*reserved112)(void);
+ void (*reserved113)(void);
+ void (*reserved114)(void);
+ void (*itcl_Assert) (const char *testExpr, const char *fileName, int lineNum); /* 115 */
+ int (*itcl_IsObjectCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 116 */
+ int (*itcl_IsClassCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 117 */
+ void (*reserved118)(void);
+ void (*reserved119)(void);
+ void (*reserved120)(void);
+ void (*reserved121)(void);
+ void (*reserved122)(void);
+ void (*reserved123)(void);
+ void (*reserved124)(void);
+ void (*reserved125)(void);
+ void (*reserved126)(void);
+ void (*reserved127)(void);
+ void (*reserved128)(void);
+ void (*reserved129)(void);
+ void (*reserved130)(void);
+ void (*reserved131)(void);
+ void (*reserved132)(void);
+ void (*reserved133)(void);
+ void (*reserved134)(void);
+ void (*reserved135)(void);
+ void (*reserved136)(void);
+ void (*reserved137)(void);
+ void (*reserved138)(void);
+ void (*reserved139)(void);
+ int (*itcl_FilterAddCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 140 */
+ int (*itcl_FilterDeleteCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 141 */
+ int (*itcl_ForwardAddCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 142 */
+ int (*itcl_ForwardDeleteCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 143 */
+ int (*itcl_MixinAddCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 144 */
+ int (*itcl_MixinDeleteCmd) (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 145 */
+ void (*reserved146)(void);
+ void (*reserved147)(void);
+ void (*reserved148)(void);
+ void (*reserved149)(void);
+ void (*reserved150)(void);
+ int (*itcl_BiInfoUnknownCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 151 */
+ int (*itcl_BiInfoVarsCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 152 */
+ int (*itcl_CanAccess2) (ItclClass *iclsPtr, int protection, Tcl_Namespace *fromNsPtr); /* 153 */
+ void (*reserved154)(void);
+ void (*reserved155)(void);
+ void (*reserved156)(void);
+ void (*reserved157)(void);
+ void (*reserved158)(void);
+ void (*reserved159)(void);
+ int (*itcl_SetCallFrameResolver) (Tcl_Interp *interp, Tcl_Resolve *resolvePtr); /* 160 */
+ int (*itclEnsembleSubCmd) (ClientData clientData, Tcl_Interp *interp, const char *ensembleName, int objc, Tcl_Obj *const *objv, const char *functionName); /* 161 */
+ Tcl_Namespace * (*itcl_GetUplevelNamespace) (Tcl_Interp *interp, int level); /* 162 */
+ ClientData (*itcl_GetCallFrameClientData) (Tcl_Interp *interp); /* 163 */
+ void (*reserved164)(void);
+ int (*itcl_SetCallFrameNamespace) (Tcl_Interp *interp, Tcl_Namespace *nsPtr); /* 165 */
+ int (*itcl_GetCallFrameObjc) (Tcl_Interp *interp); /* 166 */
+ Tcl_Obj *const * (*itcl_GetCallFrameObjv) (Tcl_Interp *interp); /* 167 */
+ int (*itcl_NWidgetCmd) (ClientData infoPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 168 */
+ int (*itcl_AddOptionCmd) (ClientData infoPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 169 */
+ int (*itcl_AddComponentCmd) (ClientData infoPtr, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 170 */
+ int (*itcl_BiInfoOptionCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 171 */
+ int (*itcl_BiInfoComponentCmd) (ClientData dummy, Tcl_Interp *interp, int objc, Tcl_Obj *const objv[]); /* 172 */
+ int (*itcl_RenameCommand) (Tcl_Interp *interp, const char *oldName, const char *newName); /* 173 */
+ int (*itcl_PushCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr, Tcl_Namespace *nsPtr, int isProcCallFrame); /* 174 */
+ void (*itcl_PopCallFrame) (Tcl_Interp *interp); /* 175 */
+ Tcl_CallFrame * (*itcl_GetUplevelCallFrame) (Tcl_Interp *interp, int level); /* 176 */
+ Tcl_CallFrame * (*itcl_ActivateCallFrame) (Tcl_Interp *interp, Tcl_CallFrame *framePtr); /* 177 */
+ const char* (*itclSetInstanceVar) (Tcl_Interp *interp, const char *name, const char *name2, const char *value, ItclObject *contextIoPtr, ItclClass *contextIclsPtr); /* 178 */
+ Tcl_Obj * (*itclCapitalize) (const char *str); /* 179 */
+ int (*itclClassBaseCmd) (ClientData clientData, Tcl_Interp *interp, int flags, int objc, Tcl_Obj *const objv[], ItclClass **iclsPtrPtr); /* 180 */
+ int (*itclCreateComponent) (Tcl_Interp *interp, ItclClass *iclsPtr, Tcl_Obj *componentPtr, int type, ItclComponent **icPtrPtr); /* 181 */
+ void (*itcl_SetContext) (Tcl_Interp *interp, ItclObject *ioPtr); /* 182 */
+ void (*itcl_UnsetContext) (Tcl_Interp *interp); /* 183 */
+ const char * (*itclGetInstanceVar) (Tcl_Interp *interp, const char *name, const char *name2, ItclObject *ioPtr, ItclClass *iclsPtr); /* 184 */
+} ItclIntStubs;
+
+extern const ItclIntStubs *itclIntStubsPtr;
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(USE_ITCL_STUBS)
+
+/*
+ * Inline function declarations:
+ */
+
+#define Itcl_IsClassNamespace \
+ (itclIntStubsPtr->itcl_IsClassNamespace) /* 0 */
+#define Itcl_IsClass \
+ (itclIntStubsPtr->itcl_IsClass) /* 1 */
+#define Itcl_FindClass \
+ (itclIntStubsPtr->itcl_FindClass) /* 2 */
+#define Itcl_FindObject \
+ (itclIntStubsPtr->itcl_FindObject) /* 3 */
+#define Itcl_IsObject \
+ (itclIntStubsPtr->itcl_IsObject) /* 4 */
+#define Itcl_ObjectIsa \
+ (itclIntStubsPtr->itcl_ObjectIsa) /* 5 */
+#define Itcl_Protection \
+ (itclIntStubsPtr->itcl_Protection) /* 6 */
+#define Itcl_ProtectionStr \
+ (itclIntStubsPtr->itcl_ProtectionStr) /* 7 */
+#define Itcl_CanAccess \
+ (itclIntStubsPtr->itcl_CanAccess) /* 8 */
+#define Itcl_CanAccessFunc \
+ (itclIntStubsPtr->itcl_CanAccessFunc) /* 9 */
+/* Slot 10 is reserved */
+#define Itcl_ParseNamespPath \
+ (itclIntStubsPtr->itcl_ParseNamespPath) /* 11 */
+#define Itcl_DecodeScopedCommand \
+ (itclIntStubsPtr->itcl_DecodeScopedCommand) /* 12 */
+#define Itcl_EvalArgs \
+ (itclIntStubsPtr->itcl_EvalArgs) /* 13 */
+#define Itcl_CreateArgs \
+ (itclIntStubsPtr->itcl_CreateArgs) /* 14 */
+/* Slot 15 is reserved */
+/* Slot 16 is reserved */
+#define Itcl_GetContext \
+ (itclIntStubsPtr->itcl_GetContext) /* 17 */
+#define Itcl_InitHierIter \
+ (itclIntStubsPtr->itcl_InitHierIter) /* 18 */
+#define Itcl_DeleteHierIter \
+ (itclIntStubsPtr->itcl_DeleteHierIter) /* 19 */
+#define Itcl_AdvanceHierIter \
+ (itclIntStubsPtr->itcl_AdvanceHierIter) /* 20 */
+#define Itcl_FindClassesCmd \
+ (itclIntStubsPtr->itcl_FindClassesCmd) /* 21 */
+#define Itcl_FindObjectsCmd \
+ (itclIntStubsPtr->itcl_FindObjectsCmd) /* 22 */
+/* Slot 23 is reserved */
+#define Itcl_DelClassCmd \
+ (itclIntStubsPtr->itcl_DelClassCmd) /* 24 */
+#define Itcl_DelObjectCmd \
+ (itclIntStubsPtr->itcl_DelObjectCmd) /* 25 */
+#define Itcl_ScopeCmd \
+ (itclIntStubsPtr->itcl_ScopeCmd) /* 26 */
+#define Itcl_CodeCmd \
+ (itclIntStubsPtr->itcl_CodeCmd) /* 27 */
+#define Itcl_StubCreateCmd \
+ (itclIntStubsPtr->itcl_StubCreateCmd) /* 28 */
+#define Itcl_StubExistsCmd \
+ (itclIntStubsPtr->itcl_StubExistsCmd) /* 29 */
+#define Itcl_IsStub \
+ (itclIntStubsPtr->itcl_IsStub) /* 30 */
+#define Itcl_CreateClass \
+ (itclIntStubsPtr->itcl_CreateClass) /* 31 */
+#define Itcl_DeleteClass \
+ (itclIntStubsPtr->itcl_DeleteClass) /* 32 */
+#define Itcl_FindClassNamespace \
+ (itclIntStubsPtr->itcl_FindClassNamespace) /* 33 */
+#define Itcl_HandleClass \
+ (itclIntStubsPtr->itcl_HandleClass) /* 34 */
+/* Slot 35 is reserved */
+/* Slot 36 is reserved */
+/* Slot 37 is reserved */
+#define Itcl_BuildVirtualTables \
+ (itclIntStubsPtr->itcl_BuildVirtualTables) /* 38 */
+#define Itcl_CreateVariable \
+ (itclIntStubsPtr->itcl_CreateVariable) /* 39 */
+#define Itcl_DeleteVariable \
+ (itclIntStubsPtr->itcl_DeleteVariable) /* 40 */
+#define Itcl_GetCommonVar \
+ (itclIntStubsPtr->itcl_GetCommonVar) /* 41 */
+/* Slot 42 is reserved */
+/* Slot 43 is reserved */
+#define Itcl_CreateObject \
+ (itclIntStubsPtr->itcl_CreateObject) /* 44 */
+#define Itcl_DeleteObject \
+ (itclIntStubsPtr->itcl_DeleteObject) /* 45 */
+#define Itcl_DestructObject \
+ (itclIntStubsPtr->itcl_DestructObject) /* 46 */
+/* Slot 47 is reserved */
+#define Itcl_GetInstanceVar \
+ (itclIntStubsPtr->itcl_GetInstanceVar) /* 48 */
+/* Slot 49 is reserved */
+#define Itcl_BodyCmd \
+ (itclIntStubsPtr->itcl_BodyCmd) /* 50 */
+#define Itcl_ConfigBodyCmd \
+ (itclIntStubsPtr->itcl_ConfigBodyCmd) /* 51 */
+#define Itcl_CreateMethod \
+ (itclIntStubsPtr->itcl_CreateMethod) /* 52 */
+#define Itcl_CreateProc \
+ (itclIntStubsPtr->itcl_CreateProc) /* 53 */
+#define Itcl_CreateMemberFunc \
+ (itclIntStubsPtr->itcl_CreateMemberFunc) /* 54 */
+#define Itcl_ChangeMemberFunc \
+ (itclIntStubsPtr->itcl_ChangeMemberFunc) /* 55 */
+#define Itcl_DeleteMemberFunc \
+ (itclIntStubsPtr->itcl_DeleteMemberFunc) /* 56 */
+#define Itcl_CreateMemberCode \
+ (itclIntStubsPtr->itcl_CreateMemberCode) /* 57 */
+#define Itcl_DeleteMemberCode \
+ (itclIntStubsPtr->itcl_DeleteMemberCode) /* 58 */
+#define Itcl_GetMemberCode \
+ (itclIntStubsPtr->itcl_GetMemberCode) /* 59 */
+/* Slot 60 is reserved */
+#define Itcl_EvalMemberCode \
+ (itclIntStubsPtr->itcl_EvalMemberCode) /* 61 */
+/* Slot 62 is reserved */
+/* Slot 63 is reserved */
+/* Slot 64 is reserved */
+/* Slot 65 is reserved */
+/* Slot 66 is reserved */
+#define Itcl_GetMemberFuncUsage \
+ (itclIntStubsPtr->itcl_GetMemberFuncUsage) /* 67 */
+#define Itcl_ExecMethod \
+ (itclIntStubsPtr->itcl_ExecMethod) /* 68 */
+#define Itcl_ExecProc \
+ (itclIntStubsPtr->itcl_ExecProc) /* 69 */
+/* Slot 70 is reserved */
+#define Itcl_ConstructBase \
+ (itclIntStubsPtr->itcl_ConstructBase) /* 71 */
+#define Itcl_InvokeMethodIfExists \
+ (itclIntStubsPtr->itcl_InvokeMethodIfExists) /* 72 */
+/* Slot 73 is reserved */
+#define Itcl_ReportFuncErrors \
+ (itclIntStubsPtr->itcl_ReportFuncErrors) /* 74 */
+#define Itcl_ParseInit \
+ (itclIntStubsPtr->itcl_ParseInit) /* 75 */
+#define Itcl_ClassCmd \
+ (itclIntStubsPtr->itcl_ClassCmd) /* 76 */
+#define Itcl_ClassInheritCmd \
+ (itclIntStubsPtr->itcl_ClassInheritCmd) /* 77 */
+#define Itcl_ClassProtectionCmd \
+ (itclIntStubsPtr->itcl_ClassProtectionCmd) /* 78 */
+#define Itcl_ClassConstructorCmd \
+ (itclIntStubsPtr->itcl_ClassConstructorCmd) /* 79 */
+#define Itcl_ClassDestructorCmd \
+ (itclIntStubsPtr->itcl_ClassDestructorCmd) /* 80 */
+#define Itcl_ClassMethodCmd \
+ (itclIntStubsPtr->itcl_ClassMethodCmd) /* 81 */
+#define Itcl_ClassProcCmd \
+ (itclIntStubsPtr->itcl_ClassProcCmd) /* 82 */
+#define Itcl_ClassVariableCmd \
+ (itclIntStubsPtr->itcl_ClassVariableCmd) /* 83 */
+#define Itcl_ClassCommonCmd \
+ (itclIntStubsPtr->itcl_ClassCommonCmd) /* 84 */
+#define Itcl_ParseVarResolver \
+ (itclIntStubsPtr->itcl_ParseVarResolver) /* 85 */
+#define Itcl_BiInit \
+ (itclIntStubsPtr->itcl_BiInit) /* 86 */
+#define Itcl_InstallBiMethods \
+ (itclIntStubsPtr->itcl_InstallBiMethods) /* 87 */
+#define Itcl_BiIsaCmd \
+ (itclIntStubsPtr->itcl_BiIsaCmd) /* 88 */
+#define Itcl_BiConfigureCmd \
+ (itclIntStubsPtr->itcl_BiConfigureCmd) /* 89 */
+#define Itcl_BiCgetCmd \
+ (itclIntStubsPtr->itcl_BiCgetCmd) /* 90 */
+#define Itcl_BiChainCmd \
+ (itclIntStubsPtr->itcl_BiChainCmd) /* 91 */
+#define Itcl_BiInfoClassCmd \
+ (itclIntStubsPtr->itcl_BiInfoClassCmd) /* 92 */
+#define Itcl_BiInfoInheritCmd \
+ (itclIntStubsPtr->itcl_BiInfoInheritCmd) /* 93 */
+#define Itcl_BiInfoHeritageCmd \
+ (itclIntStubsPtr->itcl_BiInfoHeritageCmd) /* 94 */
+#define Itcl_BiInfoFunctionCmd \
+ (itclIntStubsPtr->itcl_BiInfoFunctionCmd) /* 95 */
+#define Itcl_BiInfoVariableCmd \
+ (itclIntStubsPtr->itcl_BiInfoVariableCmd) /* 96 */
+#define Itcl_BiInfoBodyCmd \
+ (itclIntStubsPtr->itcl_BiInfoBodyCmd) /* 97 */
+#define Itcl_BiInfoArgsCmd \
+ (itclIntStubsPtr->itcl_BiInfoArgsCmd) /* 98 */
+/* Slot 99 is reserved */
+#define Itcl_EnsembleInit \
+ (itclIntStubsPtr->itcl_EnsembleInit) /* 100 */
+#define Itcl_CreateEnsemble \
+ (itclIntStubsPtr->itcl_CreateEnsemble) /* 101 */
+#define Itcl_AddEnsemblePart \
+ (itclIntStubsPtr->itcl_AddEnsemblePart) /* 102 */
+#define Itcl_GetEnsemblePart \
+ (itclIntStubsPtr->itcl_GetEnsemblePart) /* 103 */
+#define Itcl_IsEnsemble \
+ (itclIntStubsPtr->itcl_IsEnsemble) /* 104 */
+#define Itcl_GetEnsembleUsage \
+ (itclIntStubsPtr->itcl_GetEnsembleUsage) /* 105 */
+#define Itcl_GetEnsembleUsageForObj \
+ (itclIntStubsPtr->itcl_GetEnsembleUsageForObj) /* 106 */
+#define Itcl_EnsembleCmd \
+ (itclIntStubsPtr->itcl_EnsembleCmd) /* 107 */
+#define Itcl_EnsPartCmd \
+ (itclIntStubsPtr->itcl_EnsPartCmd) /* 108 */
+#define Itcl_EnsembleErrorCmd \
+ (itclIntStubsPtr->itcl_EnsembleErrorCmd) /* 109 */
+/* Slot 110 is reserved */
+/* Slot 111 is reserved */
+/* Slot 112 is reserved */
+/* Slot 113 is reserved */
+/* Slot 114 is reserved */
+#define Itcl_Assert \
+ (itclIntStubsPtr->itcl_Assert) /* 115 */
+#define Itcl_IsObjectCmd \
+ (itclIntStubsPtr->itcl_IsObjectCmd) /* 116 */
+#define Itcl_IsClassCmd \
+ (itclIntStubsPtr->itcl_IsClassCmd) /* 117 */
+/* Slot 118 is reserved */
+/* Slot 119 is reserved */
+/* Slot 120 is reserved */
+/* Slot 121 is reserved */
+/* Slot 122 is reserved */
+/* Slot 123 is reserved */
+/* Slot 124 is reserved */
+/* Slot 125 is reserved */
+/* Slot 126 is reserved */
+/* Slot 127 is reserved */
+/* Slot 128 is reserved */
+/* Slot 129 is reserved */
+/* Slot 130 is reserved */
+/* Slot 131 is reserved */
+/* Slot 132 is reserved */
+/* Slot 133 is reserved */
+/* Slot 134 is reserved */
+/* Slot 135 is reserved */
+/* Slot 136 is reserved */
+/* Slot 137 is reserved */
+/* Slot 138 is reserved */
+/* Slot 139 is reserved */
+#define Itcl_FilterAddCmd \
+ (itclIntStubsPtr->itcl_FilterAddCmd) /* 140 */
+#define Itcl_FilterDeleteCmd \
+ (itclIntStubsPtr->itcl_FilterDeleteCmd) /* 141 */
+#define Itcl_ForwardAddCmd \
+ (itclIntStubsPtr->itcl_ForwardAddCmd) /* 142 */
+#define Itcl_ForwardDeleteCmd \
+ (itclIntStubsPtr->itcl_ForwardDeleteCmd) /* 143 */
+#define Itcl_MixinAddCmd \
+ (itclIntStubsPtr->itcl_MixinAddCmd) /* 144 */
+#define Itcl_MixinDeleteCmd \
+ (itclIntStubsPtr->itcl_MixinDeleteCmd) /* 145 */
+/* Slot 146 is reserved */
+/* Slot 147 is reserved */
+/* Slot 148 is reserved */
+/* Slot 149 is reserved */
+/* Slot 150 is reserved */
+#define Itcl_BiInfoUnknownCmd \
+ (itclIntStubsPtr->itcl_BiInfoUnknownCmd) /* 151 */
+#define Itcl_BiInfoVarsCmd \
+ (itclIntStubsPtr->itcl_BiInfoVarsCmd) /* 152 */
+#define Itcl_CanAccess2 \
+ (itclIntStubsPtr->itcl_CanAccess2) /* 153 */
+/* Slot 154 is reserved */
+/* Slot 155 is reserved */
+/* Slot 156 is reserved */
+/* Slot 157 is reserved */
+/* Slot 158 is reserved */
+/* Slot 159 is reserved */
+#define Itcl_SetCallFrameResolver \
+ (itclIntStubsPtr->itcl_SetCallFrameResolver) /* 160 */
+#define ItclEnsembleSubCmd \
+ (itclIntStubsPtr->itclEnsembleSubCmd) /* 161 */
+#define Itcl_GetUplevelNamespace \
+ (itclIntStubsPtr->itcl_GetUplevelNamespace) /* 162 */
+#define Itcl_GetCallFrameClientData \
+ (itclIntStubsPtr->itcl_GetCallFrameClientData) /* 163 */
+/* Slot 164 is reserved */
+#define Itcl_SetCallFrameNamespace \
+ (itclIntStubsPtr->itcl_SetCallFrameNamespace) /* 165 */
+#define Itcl_GetCallFrameObjc \
+ (itclIntStubsPtr->itcl_GetCallFrameObjc) /* 166 */
+#define Itcl_GetCallFrameObjv \
+ (itclIntStubsPtr->itcl_GetCallFrameObjv) /* 167 */
+#define Itcl_NWidgetCmd \
+ (itclIntStubsPtr->itcl_NWidgetCmd) /* 168 */
+#define Itcl_AddOptionCmd \
+ (itclIntStubsPtr->itcl_AddOptionCmd) /* 169 */
+#define Itcl_AddComponentCmd \
+ (itclIntStubsPtr->itcl_AddComponentCmd) /* 170 */
+#define Itcl_BiInfoOptionCmd \
+ (itclIntStubsPtr->itcl_BiInfoOptionCmd) /* 171 */
+#define Itcl_BiInfoComponentCmd \
+ (itclIntStubsPtr->itcl_BiInfoComponentCmd) /* 172 */
+#define Itcl_RenameCommand \
+ (itclIntStubsPtr->itcl_RenameCommand) /* 173 */
+#define Itcl_PushCallFrame \
+ (itclIntStubsPtr->itcl_PushCallFrame) /* 174 */
+#define Itcl_PopCallFrame \
+ (itclIntStubsPtr->itcl_PopCallFrame) /* 175 */
+#define Itcl_GetUplevelCallFrame \
+ (itclIntStubsPtr->itcl_GetUplevelCallFrame) /* 176 */
+#define Itcl_ActivateCallFrame \
+ (itclIntStubsPtr->itcl_ActivateCallFrame) /* 177 */
+#define ItclSetInstanceVar \
+ (itclIntStubsPtr->itclSetInstanceVar) /* 178 */
+#define ItclCapitalize \
+ (itclIntStubsPtr->itclCapitalize) /* 179 */
+#define ItclClassBaseCmd \
+ (itclIntStubsPtr->itclClassBaseCmd) /* 180 */
+#define ItclCreateComponent \
+ (itclIntStubsPtr->itclCreateComponent) /* 181 */
+#define Itcl_SetContext \
+ (itclIntStubsPtr->itcl_SetContext) /* 182 */
+#define Itcl_UnsetContext \
+ (itclIntStubsPtr->itcl_UnsetContext) /* 183 */
+#define ItclGetInstanceVar \
+ (itclIntStubsPtr->itclGetInstanceVar) /* 184 */
+
+#endif /* defined(USE_ITCL_STUBS) */
+
+/* !END!: Do not edit above this line. */
+
+#endif /* _ITCLINTDECLS */
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclLinkage.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclLinkage.c
new file mode 100644
index 0000000..b0e87d8
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclLinkage.c
@@ -0,0 +1,326 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This part adds a mechanism for integrating C procedures into
+ * [incr Tcl] classes as methods and procs. Each C procedure must
+ * either be declared via Itcl_RegisterC() or dynamically loaded.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+/*
+ * These records store the pointers for all "RegisterC" functions.
+ */
+typedef struct ItclCfunc {
+ Tcl_CmdProc *argCmdProc; /* old-style (argc,argv) command handler */
+ Tcl_ObjCmdProc *objCmdProc; /* new (objc,objv) command handler */
+ ClientData clientData; /* client data passed into this function */
+ Tcl_CmdDeleteProc *deleteProc; /* proc called to free clientData */
+} ItclCfunc;
+
+static Tcl_HashTable* ItclGetRegisteredProcs(Tcl_Interp *interp);
+static void ItclFreeC(ClientData clientData, Tcl_Interp *interp);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_RegisterC()
+ *
+ * Used to associate a symbolic name with an (argc,argv) C procedure
+ * that handles a Tcl command. Procedures that are registered in this
+ * manner can be referenced in the body of an [incr Tcl] class
+ * definition to specify C procedures to acting as methods/procs.
+ * Usually invoked in an initialization routine for an extension,
+ * called out in Tcl_AppInit() at the start of an application.
+ *
+ * Each symbolic procedure can have an arbitrary client data value
+ * associated with it. This value is passed into the command
+ * handler whenever it is invoked.
+ *
+ * A symbolic procedure name can be used only once for a given style
+ * (arg/obj) handler. If the name is defined with an arg-style
+ * handler, it can be redefined with an obj-style handler; or if
+ * the name is defined with an obj-style handler, it can be redefined
+ * with an arg-style handler. In either case, any previous client
+ * data is discarded and the new client data is remembered. However,
+ * if a name is redefined to a different handler of the same style,
+ * this procedure returns an error.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error message
+ * in interp->result) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_RegisterC(interp, name, proc, clientData, deleteProc)
+ Tcl_Interp *interp; /* interpreter handling this registration */
+ const char *name; /* symbolic name for procedure */
+ Tcl_CmdProc *proc; /* procedure handling Tcl command */
+ ClientData clientData; /* client data associated with proc */
+ Tcl_CmdDeleteProc *deleteProc; /* proc called to free up client data */
+{
+ int newEntry;
+ Tcl_HashEntry *entry;
+ Tcl_HashTable *procTable;
+ ItclCfunc *cfunc;
+
+ /*
+ * Make sure that a proc was specified.
+ */
+ if (!proc) {
+ Tcl_AppendResult(interp, "initialization error: null pointer for ",
+ "C procedure \"", name, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Add a new entry for the given procedure. If an entry with
+ * this name already exists, then make sure that it was defined
+ * with the same proc.
+ */
+ procTable = ItclGetRegisteredProcs(interp);
+ entry = Tcl_CreateHashEntry(procTable, name, &newEntry);
+ if (!newEntry) {
+ cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);
+ if (cfunc->argCmdProc != NULL && cfunc->argCmdProc != proc) {
+ Tcl_AppendResult(interp, "initialization error: C procedure ",
+ "with name \"", name, "\" already defined",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ if (cfunc->deleteProc != NULL) {
+ (*cfunc->deleteProc)(cfunc->clientData);
+ }
+ } else {
+ cfunc = (ItclCfunc*)ckalloc(sizeof(ItclCfunc));
+ cfunc->objCmdProc = NULL;
+ }
+
+ cfunc->argCmdProc = proc;
+ cfunc->clientData = clientData;
+ cfunc->deleteProc = deleteProc;
+
+ Tcl_SetHashValue(entry, (ClientData)cfunc);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_RegisterObjC()
+ *
+ * Used to associate a symbolic name with an (objc,objv) C procedure
+ * that handles a Tcl command. Procedures that are registered in this
+ * manner can be referenced in the body of an [incr Tcl] class
+ * definition to specify C procedures to acting as methods/procs.
+ * Usually invoked in an initialization routine for an extension,
+ * called out in Tcl_AppInit() at the start of an application.
+ *
+ * Each symbolic procedure can have an arbitrary client data value
+ * associated with it. This value is passed into the command
+ * handler whenever it is invoked.
+ *
+ * A symbolic procedure name can be used only once for a given style
+ * (arg/obj) handler. If the name is defined with an arg-style
+ * handler, it can be redefined with an obj-style handler; or if
+ * the name is defined with an obj-style handler, it can be redefined
+ * with an arg-style handler. In either case, any previous client
+ * data is discarded and the new client data is remembered. However,
+ * if a name is redefined to a different handler of the same style,
+ * this procedure returns an error.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error message
+ * in interp->result) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_RegisterObjC(interp, name, proc, clientData, deleteProc)
+ Tcl_Interp *interp; /* interpreter handling this registration */
+ const char *name; /* symbolic name for procedure */
+ Tcl_ObjCmdProc *proc; /* procedure handling Tcl command */
+ ClientData clientData; /* client data associated with proc */
+ Tcl_CmdDeleteProc *deleteProc; /* proc called to free up client data */
+{
+ int newEntry;
+ Tcl_HashEntry *entry;
+ Tcl_HashTable *procTable;
+ ItclCfunc *cfunc;
+
+ /*
+ * Make sure that a proc was specified.
+ */
+ if (!proc) {
+ Tcl_AppendResult(interp, "initialization error: null pointer for ",
+ "C procedure \"", name, "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Add a new entry for the given procedure. If an entry with
+ * this name already exists, then make sure that it was defined
+ * with the same proc.
+ */
+ procTable = ItclGetRegisteredProcs(interp);
+ entry = Tcl_CreateHashEntry(procTable, name, &newEntry);
+ if (!newEntry) {
+ cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);
+ if (cfunc->objCmdProc != NULL && cfunc->objCmdProc != proc) {
+ Tcl_AppendResult(interp, "initialization error: C procedure ",
+ "with name \"", name, "\" already defined",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ if (cfunc->deleteProc != NULL) {
+ (*cfunc->deleteProc)(cfunc->clientData);
+ }
+ }
+ else {
+ cfunc = (ItclCfunc*)ckalloc(sizeof(ItclCfunc));
+ cfunc->argCmdProc = NULL;
+ }
+
+ cfunc->objCmdProc = proc;
+ cfunc->clientData = clientData;
+ cfunc->deleteProc = deleteProc;
+
+ Tcl_SetHashValue(entry, (ClientData)cfunc);
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindC()
+ *
+ * Used to query a C procedure via its symbolic name. Looks at the
+ * list of procedures registered previously by either Itcl_RegisterC
+ * or Itcl_RegisterObjC and returns pointers to the appropriate
+ * (argc,argv) or (objc,objv) handlers. Returns non-zero if the
+ * name is recognized and pointers are returned; returns zero
+ * otherwise.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_FindC(
+ Tcl_Interp *interp, /* interpreter handling this registration */
+ const char *name, /* symbolic name for procedure */
+ Tcl_CmdProc **argProcPtr, /* returns (argc,argv) command handler */
+ Tcl_ObjCmdProc **objProcPtr, /* returns (objc,objv) command handler */
+ ClientData *cDataPtr) /* returns client data */
+{
+ Tcl_HashEntry *entry;
+ Tcl_HashTable *procTable;
+ ItclCfunc *cfunc;
+
+ *argProcPtr = NULL; /* assume info won't be found */
+ *objProcPtr = NULL;
+ *cDataPtr = NULL;
+
+ if (interp) {
+ procTable = (Tcl_HashTable*)Tcl_GetAssocData(interp,
+ "itcl_RegC", (Tcl_InterpDeleteProc**)NULL);
+
+ if (procTable) {
+ entry = Tcl_FindHashEntry(procTable, name);
+ if (entry) {
+ cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);
+ *argProcPtr = cfunc->argCmdProc;
+ *objProcPtr = cfunc->objCmdProc;
+ *cDataPtr = cfunc->clientData;
+ }
+ }
+ }
+ return (*argProcPtr != NULL || *objProcPtr != NULL);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclGetRegisteredProcs()
+ *
+ * Returns a pointer to a hash table containing the list of registered
+ * procs in the specified interpreter. If the hash table does not
+ * already exist, it is created.
+ * ------------------------------------------------------------------------
+ */
+static Tcl_HashTable*
+ItclGetRegisteredProcs(interp)
+ Tcl_Interp *interp; /* interpreter handling this registration */
+{
+ Tcl_HashTable* procTable;
+
+ /*
+ * If the registration table does not yet exist, then create it.
+ */
+ procTable = (Tcl_HashTable*)Tcl_GetAssocData(interp, "itcl_RegC",
+ (Tcl_InterpDeleteProc**)NULL);
+
+ if (!procTable) {
+ procTable = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(procTable, TCL_STRING_KEYS);
+ Tcl_SetAssocData(interp, "itcl_RegC", ItclFreeC,
+ (ClientData)procTable);
+ }
+ return procTable;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclFreeC()
+ *
+ * When an interpreter is deleted, this procedure is called to
+ * free up the associated data created by Itcl_RegisterC and
+ * Itcl_RegisterObjC.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclFreeC(clientData, interp)
+ ClientData clientData; /* associated data */
+ Tcl_Interp *interp; /* intepreter being deleted */
+{
+ Tcl_HashTable *tablePtr = (Tcl_HashTable*)clientData;
+ Tcl_HashSearch place;
+ Tcl_HashEntry *entry;
+ ItclCfunc *cfunc;
+
+ entry = Tcl_FirstHashEntry(tablePtr, &place);
+ while (entry) {
+ cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);
+
+ if (cfunc->deleteProc != NULL) {
+ (*cfunc->deleteProc)(cfunc->clientData);
+ }
+ ckfree ( (char*)cfunc );
+ entry = Tcl_NextHashEntry(&place);
+ }
+
+ Tcl_DeleteHashTable(tablePtr);
+ ckfree((char*)tablePtr);
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclMethod.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclMethod.c
new file mode 100644
index 0000000..e33e62b
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclMethod.c
@@ -0,0 +1,2721 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * These procedures handle commands available within a class scope.
+ * In [incr Tcl], the term "method" is used for a procedure that has
+ * access to object-specific data, while the term "proc" is used for
+ * a procedure that has access only to common class data.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+static int EquivArgLists(Tcl_Interp *interp, ItclArgList *origArgs,
+ ItclArgList *realArgs);
+static int ItclCreateMemberCode(Tcl_Interp* interp, ItclClass *iclsPtr,
+ const char* arglist, const char* body, ItclMemberCode** mcodePtr,
+ Tcl_Obj *namePtr, int flags);
+static int ItclCreateMemberFunc(Tcl_Interp* interp, ItclClass *iclsPtr,
+ Tcl_Obj *namePtr, const char* arglist, const char* body,
+ ItclMemberFunc** imPtrPtr, int flags);
+
+void
+ItclPreserveIMF(
+ ItclMemberFunc *imPtr)
+{
+ imPtr->refCount++;
+}
+
+void
+ItclReleaseIMF(
+ ClientData clientData)
+{
+ ItclMemberFunc *imPtr = (ItclMemberFunc *)clientData;
+
+ if (--imPtr->refCount == 0) {
+ Itcl_DeleteMemberFunc(clientData);
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_BodyCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::body" command to
+ * define or redefine the implementation for a class method/proc.
+ * Handles the following syntax:
+ *
+ * itcl::body <class>::<func> <arglist> <body>
+ *
+ * Looks for an existing class member function with the name <func>,
+ * and if found, tries to assign the implementation. If an argument
+ * list was specified in the original declaration, it must match
+ * <arglist> or an error is flagged. If <body> has the form "@name"
+ * then it is treated as a reference to a C handling procedure;
+ * otherwise, it is taken as a body of Tcl statements.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+static int
+NRBodyCmd(
+ ClientData clientData, /* */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const *objv) /* argument objects */
+{
+ Tcl_HashEntry *entry;
+ Tcl_DString buffer;
+ Tcl_Obj *objPtr;
+ ItclClass *iclsPtr;
+ ItclMemberFunc *imPtr;
+ const char *head;
+ const char *tail;
+ const char *token;
+ char *arglist;
+ char *body;
+ int status = TCL_OK;
+
+ ItclShowArgs(2, "Itcl_BodyCmd", objc, objv);
+ if (objc != 4) {
+ token = Tcl_GetString(objv[0]);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "wrong # args: should be \"",
+ token, " class::func arglist body\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the member name "namesp::namesp::class::func".
+ * Make sure that a class name was specified, and that the
+ * class exists.
+ */
+ token = Tcl_GetString(objv[1]);
+ Itcl_ParseNamespPath(token, &buffer, &head, &tail);
+
+ if (!head || *head == '\0') {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "missing class specifier for body declaration \"", token, "\"",
+ (char*)NULL);
+ status = TCL_ERROR;
+ goto bodyCmdDone;
+ }
+
+ iclsPtr = Itcl_FindClass(interp, head, /* autoload */ 1);
+ if (iclsPtr == NULL) {
+ status = TCL_ERROR;
+ goto bodyCmdDone;
+ }
+
+ /*
+ * Find the function and try to change its implementation.
+ * Note that command resolution table contains *all* functions,
+ * even those in a base class. Make sure that the class
+ * containing the method definition is the requested class.
+ */
+
+ imPtr = NULL;
+ objPtr = Tcl_NewStringObj(tail, -1);
+ entry = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (entry) {
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ imPtr = clookup->imPtr;
+ if (imPtr->iclsPtr != iclsPtr) {
+ imPtr = NULL;
+ }
+ }
+
+ if (imPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "function \"", tail, "\" is not defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ status = TCL_ERROR;
+ goto bodyCmdDone;
+ }
+
+ arglist = Tcl_GetString(objv[2]);
+ body = Tcl_GetString(objv[3]);
+
+ if (Itcl_ChangeMemberFunc(interp, imPtr, arglist, body) != TCL_OK) {
+ status = TCL_ERROR;
+ goto bodyCmdDone;
+ }
+
+bodyCmdDone:
+ Tcl_DStringFree(&buffer);
+ return status;
+}
+
+/* ARGSUSED */
+int
+Itcl_BodyCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRBodyCmd, clientData, objc, objv);
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ConfigBodyCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::configbody" command
+ * to define or redefine the configuration code associated with a
+ * public variable. Handles the following syntax:
+ *
+ * itcl::configbody <class>::<publicVar> <body>
+ *
+ * Looks for an existing public variable with the name <publicVar>,
+ * and if found, tries to assign the implementation. If <body> has
+ * the form "@name" then it is treated as a reference to a C handling
+ * procedure; otherwise, it is taken as a body of Tcl statements.
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+NRConfigBodyCmd(
+ ClientData dummy, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int status = TCL_OK;
+
+ const char *head;
+ const char *tail;
+ const char *token;
+ Tcl_DString buffer;
+ ItclClass *iclsPtr;
+ ItclVarLookup *vlookup;
+ ItclVariable *ivPtr;
+ ItclMemberCode *mcode;
+ Tcl_HashEntry *entry;
+
+ ItclShowArgs(2, "Itcl_ConfigBodyCmd", objc, objv);
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "class::option body");
+ return TCL_ERROR;
+ }
+
+ /*
+ * Parse the member name "namesp::namesp::class::option".
+ * Make sure that a class name was specified, and that the
+ * class exists.
+ */
+ token = Tcl_GetString(objv[1]);
+ Itcl_ParseNamespPath(token, &buffer, &head, &tail);
+
+ if ((head == NULL) || (*head == '\0')) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "missing class specifier for body declaration \"", token, "\"",
+ (char*)NULL);
+ status = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ iclsPtr = Itcl_FindClass(interp, head, /* autoload */ 1);
+ if (iclsPtr == NULL) {
+ status = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ /*
+ * Find the variable and change its implementation.
+ * Note that variable resolution table has *all* variables,
+ * even those in a base class. Make sure that the class
+ * containing the variable definition is the requested class.
+ */
+ vlookup = NULL;
+ entry = Tcl_FindHashEntry(&iclsPtr->resolveVars, tail);
+ if (entry) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry);
+ if (vlookup->ivPtr->iclsPtr != iclsPtr) {
+ vlookup = NULL;
+ }
+ }
+
+ if (vlookup == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "option \"", tail, "\" is not defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ status = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+ ivPtr = vlookup->ivPtr;
+
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "option \"", Tcl_GetString(ivPtr->fullNamePtr),
+ "\" is not a public configuration option",
+ (char*)NULL);
+ status = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ token = Tcl_GetString(objv[2]);
+
+ if (Itcl_CreateMemberCode(interp, iclsPtr, (char*)NULL, token,
+ &mcode) != TCL_OK) {
+ status = TCL_ERROR;
+ goto configBodyCmdDone;
+ }
+
+ Itcl_PreserveData((ClientData)mcode);
+ Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode);
+
+ if (ivPtr->codePtr) {
+ Itcl_ReleaseData((ClientData)ivPtr->codePtr);
+ }
+ ivPtr->codePtr = mcode;
+
+configBodyCmdDone:
+ Tcl_DStringFree(&buffer);
+ return status;
+}
+
+/* ARGSUSED */
+int
+Itcl_ConfigBodyCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRConfigBodyCmd, clientData, objc, objv);
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateMethod()
+ *
+ * Installs a method into the namespace associated with a class.
+ * If another command with the same name is already installed, then
+ * it is overwritten.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error message
+ * in the specified interp) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateMethod(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class definition */
+ Tcl_Obj *namePtr, /* name of new method */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body) /* body of commands for the method */
+{
+ ItclMemberFunc *imPtr;
+
+ return ItclCreateMethod(interp, iclsPtr, namePtr, arglist, body, &imPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateMethod()
+ *
+ * Installs a method into the namespace associated with a class.
+ * If another command with the same name is already installed, then
+ * it is overwritten.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error message
+ * in the specified interp) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCreateMethod(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class definition */
+ Tcl_Obj *namePtr, /* name of new method */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body, /* body of commands for the method */
+ ItclMemberFunc **imPtrPtr)
+{
+ ItclMemberFunc *imPtr;
+
+ /*
+ * Make sure that the method name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ if (strstr(Tcl_GetString(namePtr),"::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad method name \"", Tcl_GetString(namePtr), "\"",
+ (char*)NULL);
+ Tcl_DecrRefCount(namePtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the method definition.
+ */
+ if (ItclCreateMemberFunc(interp, iclsPtr, namePtr, arglist, body,
+ &imPtr, 0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ imPtr->flags |= ITCL_METHOD;
+ if (imPtrPtr != NULL) {
+ *imPtrPtr = imPtr;
+ }
+ ItclAddClassFunctionDictInfo(interp, iclsPtr, imPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateProc()
+ *
+ * Installs a class proc into the namespace associated with a class.
+ * If another command with the same name is already installed, then
+ * it is overwritten. Returns TCL_OK on success, or TCL_ERROR (along
+ * with an error message in the specified interp) if anything goes
+ * wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateProc(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class definition */
+ Tcl_Obj* namePtr, /* name of new proc */
+ const char *arglist, /* space-separated list of arg names */
+ const char *body) /* body of commands for the proc */
+{
+ ItclMemberFunc *imPtr;
+
+ /*
+ * Make sure that the proc name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ if (strstr(Tcl_GetString(namePtr),"::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad proc name \"", Tcl_GetString(namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Create the proc definition.
+ */
+ if (ItclCreateMemberFunc(interp, iclsPtr, namePtr, arglist,
+ body, &imPtr, ITCL_COMMON) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Mark procs as "common". This distinguishes them from methods.
+ */
+ imPtr->flags |= ITCL_COMMON;
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateMemberFunc()
+ *
+ * Creates the data record representing a member function. This
+ * includes the argument list and the body of the function. If the
+ * body is of the form "@name", then it is treated as a label for
+ * a C procedure registered by Itcl_RegisterC().
+ *
+ * If any errors are encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK, and "imPtr" returns a pointer to the new
+ * member function.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclCreateMemberFunc(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class definition */
+ Tcl_Obj *namePtr, /* name of new member */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body, /* body of commands for the method */
+ ItclMemberFunc** imPtrPtr, /* returns: pointer to new method defn */
+ int flags)
+{
+ int newEntry;
+ char *name;
+ ItclMemberFunc *imPtr;
+ ItclMemberCode *mcode;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * Add the member function to the list of functions for
+ * the class. Make sure that a member function with the
+ * same name doesn't already exist.
+ */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->functions, (char *)namePtr, &newEntry);
+ if (!newEntry) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", Tcl_GetString(namePtr), "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Try to create the implementation for this command member.
+ */
+ if (ItclCreateMemberCode(interp, iclsPtr, arglist, body,
+ &mcode, namePtr, flags) != TCL_OK) {
+
+ Tcl_DeleteHashEntry(hPtr);
+ return TCL_ERROR;
+ }
+
+ Itcl_PreserveData((ClientData)mcode);
+ Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode);
+
+ /*
+ * Allocate a member function definition and return.
+ */
+ imPtr = (ItclMemberFunc*)ckalloc(sizeof(ItclMemberFunc));
+ memset(imPtr, 0, sizeof(ItclMemberFunc));
+ imPtr->iclsPtr = iclsPtr;
+ imPtr->infoPtr = iclsPtr->infoPtr;
+ imPtr->protection = Itcl_Protection(interp, 0);
+ imPtr->namePtr = Tcl_NewStringObj(Tcl_GetString(namePtr), -1);
+ Tcl_IncrRefCount(imPtr->namePtr);
+ imPtr->fullNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_AppendToObj(imPtr->fullNamePtr, "::", 2);
+ Tcl_AppendToObj(imPtr->fullNamePtr, Tcl_GetString(namePtr), -1);
+ Tcl_IncrRefCount(imPtr->fullNamePtr);
+ if (arglist != NULL) {
+ imPtr->origArgsPtr = Tcl_NewStringObj(arglist, -1);
+ Tcl_IncrRefCount(imPtr->origArgsPtr);
+ }
+ imPtr->codePtr = mcode;
+
+ if (imPtr->protection == ITCL_DEFAULT_PROTECT) {
+ imPtr->protection = ITCL_PUBLIC;
+ }
+
+ imPtr->declaringClassPtr = iclsPtr;
+
+ if (arglist) {
+ imPtr->flags |= ITCL_ARG_SPEC;
+ }
+ if (mcode->argListPtr) {
+ ItclCreateArgList(interp, arglist, &imPtr->argcount,
+ &imPtr->maxargcount, &imPtr->usagePtr,
+ &imPtr->argListPtr, imPtr, NULL);
+ Tcl_IncrRefCount(imPtr->usagePtr);
+ }
+
+ name = Tcl_GetString(namePtr);
+ if ((body != NULL) && (body[0] == '@')) {
+ /* check for builtin cget isa and configure and mark them for
+ * use of a different arglist "args" for TclOO !! */
+ imPtr->codePtr->flags |= ITCL_BUILTIN;
+ if (strcmp(name, "cget") == 0) {
+ }
+ if (strcmp(name, "configure") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "isa") == 0) {
+ }
+ if (strcmp(name, "createhull") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "keepcomponentoption") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "ignorecomponentoption") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "renamecomponentoption") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "addoptioncomponent") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "ignoreoptioncomponent") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "renameoptioncomponent") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "setupcomponent") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "itcl_initoptions") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "mytypemethod") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ imPtr->flags |= ITCL_COMMON;
+ }
+ if (strcmp(name, "mymethod") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "mytypevar") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ imPtr->flags |= ITCL_COMMON;
+ }
+ if (strcmp(name, "myvar") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "itcl_hull") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ imPtr->flags |= ITCL_COMPONENT;
+ }
+ if (strcmp(name, "callinstance") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "getinstancevar") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "myproc") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ imPtr->flags |= ITCL_COMMON;
+ }
+ if (strcmp(name, "installhull") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "destroy") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "installcomponent") == 0) {
+ imPtr->argcount = 0;
+ imPtr->maxargcount = -1;
+ }
+ if (strcmp(name, "info") == 0) {
+ imPtr->flags |= ITCL_COMMON;
+ }
+ }
+ if (strcmp(name, "constructor") == 0) {
+ /*
+ * REVISE mcode->bodyPtr here!
+ * Include a [my ItclConstructBase $iclsPtr] method call.
+ * Inherited from itcl::Root
+ */
+
+ Tcl_Obj *newBody = Tcl_NewStringObj("", -1);
+ Tcl_AppendToObj(newBody,
+ "[::info object namespace ${this}]::my ItclConstructBase ", -1);
+ Tcl_AppendObjToObj(newBody, iclsPtr->fullNamePtr);
+ Tcl_AppendToObj(newBody, "\n", -1);
+
+ Tcl_AppendObjToObj(newBody, mcode->bodyPtr);
+ Tcl_DecrRefCount(mcode->bodyPtr);
+ mcode->bodyPtr = newBody;
+ Tcl_IncrRefCount(mcode->bodyPtr);
+ imPtr->flags |= ITCL_CONSTRUCTOR;
+ }
+ if (strcmp(name, "destructor") == 0) {
+ imPtr->flags |= ITCL_DESTRUCTOR;
+ }
+
+ Tcl_SetHashValue(hPtr, (ClientData)imPtr);
+ imPtr->refCount = 1;
+
+ *imPtrPtr = imPtr;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateMemberFunc()
+ *
+ * Creates the data record representing a member function. This
+ * includes the argument list and the body of the function. If the
+ * body is of the form "@name", then it is treated as a label for
+ * a C procedure registered by Itcl_RegisterC().
+ *
+ * If any errors are encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK, and "imPtr" returns a pointer to the new
+ * member function.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateMemberFunc(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class definition */
+ Tcl_Obj *namePtr, /* name of new member */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body, /* body of commands for the method */
+ ItclMemberFunc** imPtrPtr) /* returns: pointer to new method defn */
+{
+ return ItclCreateMemberFunc(interp, iclsPtr, namePtr, arglist,
+ body, imPtrPtr, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ChangeMemberFunc()
+ *
+ * Modifies the data record representing a member function. This
+ * is usually the body of the function, but can include the argument
+ * list if it was not defined when the member was first created.
+ * If the body is of the form "@name", then it is treated as a label
+ * for a C procedure registered by Itcl_RegisterC().
+ *
+ * If any errors are encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK, and "imPtr" returns a pointer to the new
+ * member function.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ChangeMemberFunc(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclMemberFunc* imPtr, /* command member being changed */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body) /* body of commands for the method */
+{
+ Tcl_HashEntry *hPtr;
+ ItclMemberCode *mcode = NULL;
+ int isNewEntry;
+
+ /*
+ * Try to create the implementation for this command member.
+ */
+ if (ItclCreateMemberCode(interp, imPtr->iclsPtr,
+ arglist, body, &mcode, imPtr->namePtr, 0) != TCL_OK) {
+
+ return TCL_ERROR;
+ }
+
+ /*
+ * If the argument list was defined when the function was
+ * created, compare the arg lists or usage strings to make sure
+ * that the interface is not being redefined.
+ */
+ if ((imPtr->flags & ITCL_ARG_SPEC) != 0 &&
+ (imPtr->argListPtr != NULL) &&
+ !EquivArgLists(interp, imPtr->argListPtr, mcode->argListPtr)) {
+ const char *argsStr;
+ if (imPtr->origArgsPtr != NULL) {
+ argsStr = Tcl_GetString(imPtr->origArgsPtr);
+ } else {
+ argsStr = "";
+ }
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "argument list changed for function \"",
+ Tcl_GetString(imPtr->fullNamePtr), "\": should be \"",
+ argsStr, "\"",
+ (char*)NULL);
+
+ Itcl_DeleteMemberCode((char*)mcode);
+ return TCL_ERROR;
+ }
+
+ if (imPtr->flags & ITCL_CONSTRUCTOR) {
+ /*
+ * REVISE mcode->bodyPtr here!
+ * Include a [my ItclConstructBase $iclsPtr] method call.
+ * Inherited from itcl::Root
+ */
+
+ Tcl_Obj *newBody = Tcl_NewStringObj("", -1);
+ Tcl_AppendToObj(newBody,
+ "[::info object namespace ${this}]::my ItclConstructBase ", -1);
+ Tcl_AppendObjToObj(newBody, imPtr->iclsPtr->fullNamePtr);
+ Tcl_AppendToObj(newBody, "\n", -1);
+
+ Tcl_AppendObjToObj(newBody, mcode->bodyPtr);
+ Tcl_DecrRefCount(mcode->bodyPtr);
+ mcode->bodyPtr = newBody;
+ Tcl_IncrRefCount(mcode->bodyPtr);
+ }
+
+ /*
+ * Free up the old implementation and install the new one.
+ */
+ Itcl_PreserveData((ClientData)mcode);
+ Itcl_EventuallyFree((ClientData)mcode, Itcl_DeleteMemberCode);
+
+ Itcl_ReleaseData((ClientData)imPtr->codePtr);
+ imPtr->codePtr = mcode;
+ if (mcode->flags & ITCL_IMPLEMENT_TCL) {
+ ClientData pmPtr;
+ imPtr->tmPtr = (ClientData)Itcl_NewProcClassMethod(interp,
+ imPtr->iclsPtr->clsPtr, ItclCheckCallMethod, ItclAfterCallMethod,
+ ItclProcErrorProc, imPtr, imPtr->namePtr, mcode->argumentPtr,
+ mcode->bodyPtr, &pmPtr);
+ hPtr = Tcl_CreateHashEntry(&imPtr->iclsPtr->infoPtr->procMethods,
+ (char *)imPtr->tmPtr, &isNewEntry);
+ if (isNewEntry) {
+ Tcl_SetHashValue(hPtr, imPtr);
+ }
+ }
+ ItclAddClassFunctionDictInfo(interp, imPtr->iclsPtr, imPtr);
+ return TCL_OK;
+}
+
+static const char * type_reserved_words [] = {
+ "type",
+ "self",
+ "selfns",
+ NULL
+};
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateMemberCode()
+ *
+ * Creates the data record representing the implementation behind a
+ * class member function. This includes the argument list and the body
+ * of the function. If the body is of the form "@name", then it is
+ * treated as a label for a C procedure registered by Itcl_RegisterC().
+ *
+ * The implementation is kept by the member function definition, and
+ * controlled by a preserve/release paradigm. That way, if it is in
+ * use while it is being redefined, it will stay around long enough
+ * to avoid a core dump.
+ *
+ * If any errors are encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK, and "mcodePtr" returns a pointer to the new
+ * implementation.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclCreateMemberCode(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class containing this member */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body, /* body of commands for the method */
+ ItclMemberCode** mcodePtr, /* returns: pointer to new implementation */
+ Tcl_Obj *namePtr,
+ int flags)
+{
+ int argc;
+ int maxArgc;
+ Tcl_Obj *usagePtr;
+ ItclArgList *argListPtr;
+ ItclMemberCode *mcode;
+ const char **cPtrPtr;
+ int haveError;
+
+ /*
+ * Allocate some space to hold the implementation.
+ */
+ mcode = (ItclMemberCode*)ckalloc(sizeof(ItclMemberCode));
+ memset(mcode, 0, sizeof(ItclMemberCode));
+
+ if (arglist) {
+ if (ItclCreateArgList(interp, arglist, &argc, &maxArgc, &usagePtr,
+ &argListPtr, NULL, NULL) != TCL_OK) {
+ Itcl_DeleteMemberCode((char*)mcode);
+ return TCL_ERROR;
+ }
+ mcode->argcount = argc;
+ mcode->maxargcount = maxArgc;
+ mcode->argListPtr = argListPtr;
+ mcode->usagePtr = usagePtr;
+ Tcl_IncrRefCount(mcode->usagePtr);
+ mcode->argumentPtr = Tcl_NewStringObj((const char *)arglist, -1);
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ haveError = 0;
+ while (argListPtr != NULL) {
+ cPtrPtr = &type_reserved_words[0];
+ while (*cPtrPtr != NULL) {
+ if ((argListPtr->namePtr != NULL) &&
+ (strcmp(Tcl_GetString(argListPtr->namePtr),
+ *cPtrPtr) == 0)) {
+ haveError = 1;
+ }
+ if ((flags & ITCL_COMMON) != 0) {
+ if (! (iclsPtr->infoPtr->functionFlags &
+ ITCL_TYPE_METHOD)) {
+ haveError = 0;
+ }
+ }
+ if (haveError) {
+ const char *startStr = "method ";
+ if (iclsPtr->infoPtr->functionFlags &
+ ITCL_TYPE_METHOD) {
+ startStr = "typemethod ";
+ }
+ /* FIXME should use iclsPtr->infoPtr->functionFlags here */
+ if ((namePtr != NULL) &&
+ (strcmp(Tcl_GetString(namePtr),
+ "constructor") == 0)) {
+ startStr = "";
+ }
+ Tcl_AppendResult(interp, startStr,
+ namePtr == NULL ? "??" :
+ Tcl_GetString(namePtr),
+ "'s arglist may not contain \"",
+ *cPtrPtr, "\" explicitly", NULL);
+ Itcl_DeleteMemberCode((char*)mcode);
+ return TCL_ERROR;
+ }
+ cPtrPtr++;
+ }
+ argListPtr = argListPtr->nextPtr;
+ }
+ }
+ Tcl_IncrRefCount(mcode->argumentPtr);
+ mcode->flags |= ITCL_ARG_SPEC;
+ } else {
+ argc = 0;
+ argListPtr = NULL;
+ }
+
+ if (body) {
+ mcode->bodyPtr = Tcl_NewStringObj((const char *)body, -1);
+ } else {
+ mcode->bodyPtr = Tcl_NewStringObj((const char *)"", -1);
+ mcode->flags |= ITCL_IMPLEMENT_NONE;
+ }
+ Tcl_IncrRefCount(mcode->bodyPtr);
+
+ /*
+ * If the body definition starts with '@', then treat the value
+ * as a symbolic name for a C procedure.
+ */
+ if (body == NULL) {
+ /* No-op */
+ } else {
+ if (*body == '@') {
+ Tcl_CmdProc *argCmdProc;
+ Tcl_ObjCmdProc *objCmdProc;
+ ClientData cdata;
+ int isDone;
+
+ isDone = 0;
+ if (strcmp(body, "@itcl-builtin-cget") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-configure") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-isa") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-createhull") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-keepcomponentoption") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-ignorecomponentoption") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-renamecomponentoption") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-addoptioncomponent") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-ignoreoptioncomponent") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-renameoptioncomponent") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-setupcomponent") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-initoptions") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-mytypemethod") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-mymethod") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-myproc") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-mytypevar") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-myvar") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-itcl_hull") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-callinstance") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-getinstancevar") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-installhull") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-installcomponent") == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-destroy") == 0) {
+ isDone = 1;
+ }
+ if (strncmp(body, "@itcl-builtin-setget", 20) == 0) {
+ isDone = 1;
+ }
+ if (strcmp(body, "@itcl-builtin-classunknown") == 0) {
+ isDone = 1;
+ }
+ if (!isDone) {
+ if (!Itcl_FindC(interp, body+1, &argCmdProc, &objCmdProc,
+ &cdata)) {
+ Tcl_AppendResult(interp,
+ "no registered C procedure with name \"",
+ body+1, "\"", (char*)NULL);
+ Itcl_DeleteMemberCode((char*)mcode);
+ return TCL_ERROR;
+ }
+
+ /*
+ * WARNING! WARNING! WARNING!
+ * This is a pretty dangerous approach. What's done here is
+ * to copy over the proc + clientData implementation that
+ * happens to be in place at the moment the method is
+ * (re-)defined. This denies any freedom for the clientData
+ * to be changed dynamically or for the implementation to
+ * shift from OBJCMD to ARGCMD or vice versa, which the
+ * Itcl_Register(Obj)C routines explicitly permit. The whole
+ * system also lacks any scheme to unregister.
+ */
+
+ if (objCmdProc != NULL) {
+ mcode->flags |= ITCL_IMPLEMENT_OBJCMD;
+ mcode->cfunc.objCmd = objCmdProc;
+ mcode->clientData = cdata;
+ } else {
+ if (argCmdProc != NULL) {
+ mcode->flags |= ITCL_IMPLEMENT_ARGCMD;
+ mcode->cfunc.argCmd = argCmdProc;
+ mcode->clientData = cdata;
+ }
+ }
+ } else {
+ mcode->flags |= ITCL_IMPLEMENT_TCL|ITCL_BUILTIN;
+ }
+ } else {
+
+ /*
+ * Otherwise, treat the body as a chunk of Tcl code.
+ */
+ mcode->flags |= ITCL_IMPLEMENT_TCL;
+ }
+ }
+
+ *mcodePtr = mcode;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateMemberCode()
+ *
+ * Creates the data record representing the implementation behind a
+ * class member function. This includes the argument list and the body
+ * of the function. If the body is of the form "@name", then it is
+ * treated as a label for a C procedure registered by Itcl_RegisterC().
+ *
+ * The implementation is kept by the member function definition, and
+ * controlled by a preserve/release paradigm. That way, if it is in
+ * use while it is being redefined, it will stay around long enough
+ * to avoid a core dump.
+ *
+ * If any errors are encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK, and "mcodePtr" returns a pointer to the new
+ * implementation.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CreateMemberCode(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclClass *iclsPtr, /* class containing this member */
+ const char* arglist, /* space-separated list of arg names */
+ const char* body, /* body of commands for the method */
+ ItclMemberCode** mcodePtr) /* returns: pointer to new implementation */
+{
+ return ItclCreateMemberCode(interp, iclsPtr, arglist, body, mcodePtr,
+ NULL, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteMemberCode()
+ *
+ * Destroys all data associated with the given command implementation.
+ * Invoked automatically by Itcl_ReleaseData() when the implementation
+ * is no longer being used.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DeleteMemberCode(
+ char* cdata) /* pointer to member code definition */
+{
+ ItclMemberCode* mCodePtr;
+
+ mCodePtr = (ItclMemberCode*)cdata;
+ if (mCodePtr == NULL) {
+ return;
+ }
+ if (mCodePtr->argListPtr != NULL) {
+ ItclDeleteArgList(mCodePtr->argListPtr);
+ }
+ if (mCodePtr->usagePtr != NULL) {
+ Tcl_DecrRefCount(mCodePtr->usagePtr);
+ }
+ if (mCodePtr->argumentPtr != NULL) {
+ Tcl_DecrRefCount(mCodePtr->argumentPtr);
+ }
+ if (mCodePtr->bodyPtr != NULL) {
+ Tcl_DecrRefCount(mCodePtr->bodyPtr);
+ }
+ /* do NOT free mCodePtr->bodyPtr here !! that is done in TclOO!! */
+ ckfree((char*)mCodePtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetMemberCode()
+ *
+ * Makes sure that the implementation for an [incr Tcl] code body is
+ * ready to run. Note that a member function can be declared without
+ * being defined. The class definition may contain a declaration of
+ * the member function, but its body may be defined in a separate file.
+ * If an undefined function is encountered, this routine automatically
+ * attempts to autoload it. If the body is implemented via Tcl code,
+ * then it is compiled here as well.
+ *
+ * Returns TCL_ERROR (along with an error message in the interpreter)
+ * if an error is encountered, or if the implementation is not defined
+ * and cannot be autoloaded. Returns TCL_OK if implementation is
+ * ready to use.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_GetMemberCode(
+ Tcl_Interp* interp, /* interpreter managing this action */
+ ItclMemberFunc* imPtr) /* member containing code body */
+{
+ int result;
+ ItclMemberCode *mcode = imPtr->codePtr;
+ assert(mcode != NULL);
+
+ /*
+ * If the implementation has not yet been defined, try to
+ * autoload it now.
+ */
+
+ if (!Itcl_IsMemberCodeImplemented(mcode)) {
+ Tcl_DString buf;
+
+ Tcl_DStringInit(&buf);
+ Tcl_DStringAppend(&buf, "::auto_load ", -1);
+ Tcl_DStringAppend(&buf, Tcl_GetString(imPtr->fullNamePtr), -1);
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buf), -1, 0);
+ Tcl_DStringFree(&buf);
+ if (result != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while autoloading code for \"%s\")",
+ Tcl_GetString(imPtr->fullNamePtr)));
+ return result;
+ }
+ Tcl_ResetResult(interp); /* get rid of 1/0 status */
+ }
+
+ /*
+ * If the implementation is still not available, then
+ * autoloading must have failed.
+ *
+ * TRICKY NOTE: If code has been autoloaded, then the
+ * old mcode pointer is probably invalid. Go back to
+ * the member and look at the current code pointer again.
+ */
+ mcode = imPtr->codePtr;
+ assert(mcode != NULL);
+
+ if (!Itcl_IsMemberCodeImplemented(mcode)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "member function \"", Tcl_GetString(imPtr->fullNamePtr),
+ "\" is not defined and cannot be autoloaded",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ return TCL_OK;
+}
+
+
+
+static int
+CallItclObjectCmd(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Object oPtr;
+ ItclMemberFunc *imPtr = data[0];
+ ItclObject *ioPtr = data[1];
+ int objc = PTR2INT(data[2]);
+ Tcl_Obj **objv = data[3];
+
+ ItclShowArgs(1, "CallItclObjectCmd", objc, objv);
+ if (ioPtr != NULL) {
+ ioPtr->hadConstructorError = 0;
+ }
+ if (imPtr->flags & (ITCL_CONSTRUCTOR|ITCL_DESTRUCTOR)) {
+ oPtr = ioPtr->oPtr;
+ } else {
+ oPtr = NULL;
+ }
+ if (oPtr != NULL) {
+ result = ItclObjectCmd(imPtr, interp, oPtr, imPtr->iclsPtr->clsPtr,
+ objc, objv);
+ } else {
+ result = ItclObjectCmd(imPtr, interp, NULL, NULL, objc, objv);
+ }
+ if (result != TCL_OK) {
+ if (ioPtr != NULL && ioPtr->hadConstructorError == 0) {
+ /* we are in a constructor call and did not yet have an error */
+ /* -1 means we are not in a constructor */
+ ioPtr->hadConstructorError = 1;
+ }
+ }
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_EvalMemberCode()
+ *
+ * Used to execute an ItclMemberCode representation of a code
+ * fragment. This code may be a body of Tcl commands, or a C handler
+ * procedure.
+ *
+ * Executes the command with the given arguments (objc,objv) and
+ * returns an integer status code (TCL_OK/TCL_ERROR). Returns the
+ * result string or an error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+
+int
+Itcl_EvalMemberCode(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclMemberFunc *imPtr, /* member func, or NULL (for error messages) */
+ ItclObject *contextIoPtr, /* object context, or NULL */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclMemberCode *mcode;
+ void *callbackPtr;
+ int result = TCL_OK;
+ int i;
+
+ ItclShowArgs(1, "Itcl_EvalMemberCode", objc, objv);
+ /*
+ * If this code does not have an implementation yet, then
+ * try to autoload one. Also, if this is Tcl code, make sure
+ * that it's compiled and ready to use.
+ */
+ if (Itcl_GetMemberCode(interp, imPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ mcode = imPtr->codePtr;
+
+ /*
+ * Bump the reference count on this code, in case it is
+ * redefined or deleted during execution.
+ */
+ Itcl_PreserveData((ClientData)mcode);
+
+ if ((imPtr->flags & ITCL_DESTRUCTOR) && (contextIoPtr != NULL)) {
+ contextIoPtr->destructorHasBeenCalled = 1;
+ }
+
+ /*
+ * Execute the code body...
+ */
+ if (((mcode->flags & ITCL_IMPLEMENT_OBJCMD) != 0) ||
+ ((mcode->flags & ITCL_IMPLEMENT_ARGCMD) != 0)) {
+
+ if ((mcode->flags & ITCL_IMPLEMENT_OBJCMD) != 0) {
+ result = (*mcode->cfunc.objCmd)(mcode->clientData,
+ interp, objc, objv);
+ } else {
+ if ((mcode->flags & ITCL_IMPLEMENT_ARGCMD) != 0) {
+ char **argv;
+ argv = (char**)ckalloc( (unsigned)(objc*sizeof(char*)) );
+ for (i=0; i < objc; i++) {
+ argv[i] = Tcl_GetStringFromObj(objv[i], (int*)NULL);
+ }
+
+ result = (*mcode->cfunc.argCmd)(mcode->clientData,
+ interp, objc, (const char **)argv);
+
+ ckfree((char*)argv);
+ }
+ }
+ } else {
+ if ((mcode->flags & ITCL_IMPLEMENT_TCL) != 0) {
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, CallItclObjectCmd, imPtr, contextIoPtr,
+ INT2PTR(objc), (void *)objv);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ }
+ }
+
+ Itcl_ReleaseData((ClientData)mcode);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclEquivArgLists()
+ *
+ * Compares two argument lists to see if they are equivalent. The
+ * first list is treated as a prototype, and the second list must
+ * match it. Argument names may be different, but they must match in
+ * meaning. If one argument is optional, the corresponding argument
+ * must also be optional. If the prototype list ends with the magic
+ * "args" argument, then it matches everything in the other list.
+ *
+ * Returns non-zero if the argument lists are equivalent.
+ * ------------------------------------------------------------------------
+ */
+
+static int
+EquivArgLists(
+ Tcl_Interp *interp,
+ ItclArgList *origArgs,
+ ItclArgList *realArgs)
+{
+ ItclArgList *currPtr;
+ char *argName;
+
+ for (currPtr=origArgs; currPtr != NULL; currPtr=currPtr->nextPtr) {
+ if ((realArgs != NULL) && (realArgs->namePtr == NULL)) {
+ if (currPtr->namePtr != NULL) {
+ if (strcmp(Tcl_GetString(currPtr->namePtr), "args") != 0) {
+ /* the definition has more arguments */
+ return 0;
+ }
+ }
+ }
+ if (realArgs == NULL) {
+ if (currPtr->defaultValuePtr != NULL) {
+ /* default args must be there ! */
+ return 0;
+ }
+ if (currPtr->namePtr != NULL) {
+ if (strcmp(Tcl_GetString(currPtr->namePtr), "args") != 0) {
+ /* the definition has more arguments */
+ return 0;
+ }
+ }
+ return 1;
+ }
+ if (currPtr->namePtr == NULL) {
+ /* no args defined */
+ if (realArgs->namePtr != NULL) {
+ return 0;
+ }
+ return 1;
+ }
+ argName = Tcl_GetString(currPtr->namePtr);
+ if (strcmp(argName, "args") == 0) {
+ if (currPtr->nextPtr == NULL) {
+ /* this is the last arument */
+ return 1;
+ }
+ }
+ if (currPtr->defaultValuePtr != NULL) {
+ if (realArgs->defaultValuePtr != NULL) {
+ /* default values must be the same */
+ if (strcmp(Tcl_GetString(currPtr->defaultValuePtr),
+ Tcl_GetString(realArgs->defaultValuePtr)) != 0) {
+ return 0;
+ }
+ }
+ }
+ realArgs = realArgs->nextPtr;
+ }
+ if ((currPtr == NULL) && (realArgs != NULL)) {
+ /* new definition has more args then the old one */
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetContext()
+ *
+ * Convenience routine for looking up the current object/class context.
+ * Useful in implementing methods/procs to see what class, and perhaps
+ * what object, is active.
+ *
+ * Returns TCL_OK if the current namespace is a class namespace.
+ * Also returns pointers to the class definition, and to object
+ * data if an object context is active. Returns TCL_ERROR (along
+ * with an error message in the interpreter) if a class namespace
+ * is not active.
+ * ------------------------------------------------------------------------
+ */
+
+void
+Itcl_SetContext(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr)
+{
+ int new;
+ Itcl_Stack *stackPtr;
+ Tcl_CallFrame *framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&infoPtr->frameContext,
+ (char *)framePtr, &new);
+ ItclCallContext *contextPtr
+ = (ItclCallContext *) ckalloc(sizeof(ItclCallContext));
+
+ memset(contextPtr, 0, sizeof(ItclCallContext));
+ contextPtr->ioPtr = ioPtr;
+ contextPtr->refCount = 1;
+
+ if (!new) {
+ Tcl_Panic("frame already has context?!");
+ }
+
+ stackPtr = (Itcl_Stack *) ckalloc(sizeof(Itcl_Stack));
+ Itcl_InitStack(stackPtr);
+ Tcl_SetHashValue(hPtr, stackPtr);
+
+ Itcl_PushStack(contextPtr, stackPtr);
+}
+
+void
+Itcl_UnsetContext(
+ Tcl_Interp *interp)
+{
+ Tcl_CallFrame *framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&infoPtr->frameContext,
+ (char *)framePtr);
+ Itcl_Stack *stackPtr = (Itcl_Stack *) Tcl_GetHashValue(hPtr);
+ ItclCallContext *contextPtr = Itcl_PopStack(stackPtr);
+
+ if (Itcl_GetStackSize(stackPtr) > 0) {
+ Tcl_Panic("frame context stack not empty!");
+ }
+ Itcl_DeleteStack(stackPtr);
+ ckfree((char *) stackPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ if (--contextPtr->refCount) {
+ Tcl_Panic("frame context ref count not zero!");
+ }
+ ckfree((char *)contextPtr);
+}
+
+int
+Itcl_GetContext(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclClass **iclsPtrPtr, /* returns: class definition or NULL */
+ ItclObject **ioPtrPtr) /* returns: object data or NULL */
+{
+ Tcl_Namespace *nsPtr;
+
+ /* Fetch the current call frame. That determines context. */
+ Tcl_CallFrame *framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+
+ /* Try to map it to a context stack. */
+ ItclObjectInfo *infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&infoPtr->frameContext,
+ (char *)framePtr);
+ if (hPtr) {
+ /* Frame maps to a context stack. */
+ Itcl_Stack *stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ ItclCallContext *contextPtr = Itcl_PeekStack(stackPtr);
+
+ assert(contextPtr);
+
+ if (contextPtr->objectFlags & ITCL_OBJECT_ROOT_METHOD) {
+ ItclObject *ioPtr = contextPtr->ioPtr;
+
+ *iclsPtrPtr = ioPtr->iclsPtr;
+ *ioPtrPtr = ioPtr;
+ return TCL_OK;
+ }
+
+ *iclsPtrPtr = contextPtr->imPtr ? contextPtr->imPtr->iclsPtr
+ : contextPtr->ioPtr->iclsPtr;
+ *ioPtrPtr = contextPtr->ioPtr ? contextPtr->ioPtr : infoPtr->currIoPtr;
+ return TCL_OK;
+ }
+
+ /* Frame has no Itcl context data. No way to get object context. */
+ *ioPtrPtr = NULL;
+
+ /* Fall back to namespace for possible class context info. */
+ nsPtr = Tcl_GetCurrentNamespace(interp);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr) {
+ *iclsPtrPtr = (ItclClass *)Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+
+ /* Cannot get any context. Record an error message. */
+ if (interp) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "namespace \"%s\" is not a class namespace", nsPtr->fullName));
+ }
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetMemberFuncUsage()
+ *
+ * Returns a string showing how a command member should be invoked.
+ * If the command member is a method, then the specified object name
+ * is reported as part of the invocation path:
+ *
+ * obj method arg ?arg arg ...?
+ *
+ * Otherwise, the "obj" pointer is ignored, and the class name is
+ * used as the invocation path:
+ *
+ * class::proc arg ?arg arg ...?
+ *
+ * Returns the string by appending it onto the Tcl_Obj passed in as
+ * an argument.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_GetMemberFuncUsage(
+ ItclMemberFunc *imPtr, /* command member being examined */
+ ItclObject *contextIoPtr, /* invoked with respect to this object */
+ Tcl_Obj *objPtr) /* returns: string showing usage */
+{
+ Tcl_HashEntry *entry;
+ ItclMemberFunc *mf;
+ ItclClass *iclsPtr;
+ char *name;
+ char *arglist;
+
+ /*
+ * If the command is a method and an object context was
+ * specified, then add the object context. If the method
+ * was a constructor, and if the object is being created,
+ * then report the invocation via the class creation command.
+ */
+ if ((imPtr->flags & ITCL_COMMON) == 0) {
+ if ((imPtr->flags & ITCL_CONSTRUCTOR) != 0 &&
+ contextIoPtr->constructed) {
+
+ iclsPtr = (ItclClass*)contextIoPtr->iclsPtr;
+ mf = NULL;
+ objPtr = Tcl_NewStringObj("constructor", -1);
+ entry = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (entry) {
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ mf = clookup->imPtr;
+ }
+
+ if (mf == imPtr) {
+ Tcl_GetCommandFullName(contextIoPtr->iclsPtr->interp,
+ contextIoPtr->iclsPtr->accessCmd, objPtr);
+ Tcl_AppendToObj(objPtr, " ", -1);
+ name = (char *) Tcl_GetCommandName(
+ contextIoPtr->iclsPtr->interp, contextIoPtr->accessCmd);
+ Tcl_AppendToObj(objPtr, name, -1);
+ } else {
+ Tcl_AppendToObj(objPtr, Tcl_GetString(imPtr->fullNamePtr), -1);
+ }
+ } else {
+ if (contextIoPtr && contextIoPtr->accessCmd) {
+ name = (char *) Tcl_GetCommandName(
+ contextIoPtr->iclsPtr->interp, contextIoPtr->accessCmd);
+ Tcl_AppendStringsToObj(objPtr, name, " ",
+ Tcl_GetString(imPtr->namePtr), (char*)NULL);
+ } else {
+ Tcl_AppendStringsToObj(objPtr, "<object> ",
+ Tcl_GetString(imPtr->namePtr), (char*)NULL);
+ }
+ }
+ } else {
+ Tcl_AppendToObj(objPtr, Tcl_GetString(imPtr->fullNamePtr), -1);
+ }
+
+ /*
+ * Add the argument usage info.
+ */
+ if (imPtr->codePtr) {
+ if (imPtr->codePtr->usagePtr != NULL) {
+ arglist = Tcl_GetString(imPtr->codePtr->usagePtr);
+ } else {
+ arglist = NULL;
+ }
+ } else {
+ if (imPtr->argListPtr != NULL) {
+ arglist = Tcl_GetString(imPtr->usagePtr);
+ } else {
+ arglist = NULL;
+ }
+ }
+ if (arglist) {
+ if (strlen(arglist) > 0) {
+ Tcl_AppendToObj(objPtr, " ", -1);
+ Tcl_AppendToObj(objPtr, arglist, -1);
+ }
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ExecMethod()
+ *
+ * Invoked by Tcl to handle the execution of a user-defined method.
+ * A method is similar to the usual Tcl proc, but has access to
+ * object-specific data. If for some reason there is no current
+ * object context, then a method call is inappropriate, and an error
+ * is returned.
+ *
+ * Methods are implemented either as Tcl code fragments, or as C-coded
+ * procedures. For Tcl code fragments, command arguments are parsed
+ * according to the argument list, and the body is executed in the
+ * scope of the class where it was defined. For C procedures, the
+ * arguments are passed in "as-is", and the procedure is executed in
+ * the most-specific class scope.
+ * ------------------------------------------------------------------------
+ */
+static int
+NRExecMethod(
+ ClientData clientData, /* method definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const *objv) /* argument objects */
+{
+ ItclMemberFunc *imPtr = (ItclMemberFunc*)clientData;
+ int result = TCL_OK;
+
+ const char *token;
+ Tcl_HashEntry *entry;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+
+ ItclShowArgs(1, "NRExecMethod", objc, objv);
+
+ /*
+ * Make sure that the current namespace context includes an
+ * object that is being manipulated. Methods can be executed
+ * only if an object context exists.
+ */
+ iclsPtr = imPtr->iclsPtr;
+ if (Itcl_GetContext(interp, &iclsPtr, &ioPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (ioPtr == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access object-specific info without an object context",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that this command member can be accessed from
+ * the current namespace context.
+ * That is now done in ItclMapMethodNameProc !!
+ */
+
+ /*
+ * All methods should be "virtual" unless they are invoked with
+ * a "::" scope qualifier.
+ *
+ * To implement the "virtual" behavior, find the most-specific
+ * implementation for the method by looking in the "resolveCmds"
+ * table for this class.
+ */
+ token = Tcl_GetString(objv[0]);
+ if (strstr(token, "::") == NULL) {
+ if (ioPtr != NULL) {
+ entry = Tcl_FindHashEntry(&ioPtr->iclsPtr->resolveCmds,
+ (char *)imPtr->namePtr);
+
+ if (entry) {
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ imPtr = clookup->imPtr;
+ }
+ }
+ }
+
+ /*
+ * Execute the code for the method. Be careful to protect
+ * the method in case it gets deleted during execution.
+ */
+ ItclPreserveIMF(imPtr);
+ result = Itcl_EvalMemberCode(interp, imPtr, ioPtr, objc, objv);
+ ItclReleaseIMF(imPtr);
+ return result;
+}
+
+/* ARGSUSED */
+int
+Itcl_ExecMethod(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRExecMethod, clientData, objc, objv);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ExecProc()
+ *
+ * Invoked by Tcl to handle the execution of a user-defined proc.
+ *
+ * Procs are implemented either as Tcl code fragments, or as C-coded
+ * procedures. For Tcl code fragments, command arguments are parsed
+ * according to the argument list, and the body is executed in the
+ * scope of the class where it was defined. For C procedures, the
+ * arguments are passed in "as-is", and the procedure is executed in
+ * the most-specific class scope.
+ * ------------------------------------------------------------------------
+ */
+static int
+NRExecProc(
+ ClientData clientData, /* proc definition */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclMemberFunc *imPtr = (ItclMemberFunc*)clientData;
+ int result = TCL_OK;
+
+ ItclShowArgs(1, "NRExecProc", objc, objv);
+
+ /*
+ * Make sure that this command member can be accessed from
+ * the current namespace context.
+ */
+ if (imPtr->protection != ITCL_PUBLIC) {
+ if (!Itcl_CanAccessFunc(imPtr, Tcl_GetCurrentNamespace(interp))) {
+ ItclMemberFunc *imPtr2 = NULL;
+ Tcl_HashEntry *hPtr;
+ Tcl_ObjectContext context;
+ context = Itcl_GetCallFrameClientData(interp);
+ if (context == NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "can't access \"", Tcl_GetString(imPtr->fullNamePtr),
+ "\": ", Itcl_ProtectionStr(imPtr->protection),
+ " function", (char*)NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&imPtr->iclsPtr->infoPtr->procMethods,
+ (char *)Tcl_ObjectContextMethod(context));
+ if (hPtr != NULL) {
+ imPtr2 = Tcl_GetHashValue(hPtr);
+ }
+ if ((imPtr->protection & ITCL_PRIVATE) && (imPtr2 != NULL) &&
+ (imPtr->iclsPtr->nsPtr != imPtr2->iclsPtr->nsPtr)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid command name \"",
+ Tcl_GetString(objv[0]),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "can't access \"", Tcl_GetString(imPtr->fullNamePtr),
+ "\": ", Itcl_ProtectionStr(imPtr->protection),
+ " function", (char*)NULL);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Execute the code for the proc. Be careful to protect
+ * the proc in case it gets deleted during execution.
+ */
+ ItclPreserveIMF(imPtr);
+
+ result = Itcl_EvalMemberCode(interp, imPtr, (ItclObject*)NULL,
+ objc, objv);
+ ItclReleaseIMF(imPtr);
+ return result;
+}
+
+/* ARGSUSED */
+int
+Itcl_ExecProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return Tcl_NRCallObjProc(interp, NRExecProc, clientData, objc, objv);
+}
+
+static int
+CallInvokeMethodIfExists(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ItclClass *iclsPtr = data[0];
+ ItclObject *contextObj = data[1];
+ int objc = PTR2INT(data[2]);
+ Tcl_Obj* const* objv = data[3];
+
+ result = Itcl_InvokeMethodIfExists(interp, "constructor",
+ iclsPtr, contextObj, objc, (Tcl_Obj* const*)objv);
+
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ConstructBase()
+ *
+ * Usually invoked just before executing the body of a constructor
+ * when an object is first created. This procedure makes sure that
+ * all base classes are properly constructed. If an "initCode" fragment
+ * was defined with the constructor for the class, then it is invoked.
+ * After that, the list of base classes is checked for constructors
+ * that are defined but have not yet been invoked. Each of these is
+ * invoked implicitly with no arguments.
+ *
+ * Assumes that a local call frame is already installed, and that
+ * constructor arguments have already been matched and are sitting in
+ * this frame. Returns TCL_OK on success; otherwise, this procedure
+ * returns TCL_ERROR, along with an error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+
+int
+Itcl_ConstructBase(
+ Tcl_Interp *interp, /* interpreter */
+ ItclObject *contextObj, /* object being constructed */
+ ItclClass *contextClass) /* current class being constructed */
+{
+ int result = TCL_OK;
+ Tcl_Obj *objPtr;
+ Itcl_ListElem *elem;
+
+ /*
+ * If the class has an "initCode", invoke it in the current context.
+ */
+
+ if (contextClass->initCode) {
+
+ /* TODO: NRE */
+ result = Tcl_EvalObj(interp, contextClass->initCode);
+ }
+
+ /*
+ * Scan through the list of base classes and see if any of these
+ * have not been constructed. Invoke base class constructors
+ * implicitly, as needed. Go through the list of base classes
+ * in reverse order, so that least-specific classes are constructed
+ * first.
+ */
+
+ objPtr = Tcl_NewStringObj("constructor", -1);
+ Tcl_IncrRefCount(objPtr);
+ for (elem = Itcl_LastListElem(&contextClass->bases);
+ result == TCL_OK && elem != NULL;
+ elem = Itcl_PrevListElem(elem)) {
+
+ Tcl_HashEntry *entry;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_GetListValue(elem);
+
+ if (Tcl_FindHashEntry(contextObj->constructed,
+ (char *)iclsPtr->namePtr)) {
+
+ /* Already constructed, nothing to do. */
+ continue;
+ }
+
+ entry = Tcl_FindHashEntry(&iclsPtr->functions, (char *)objPtr);
+ if (entry) {
+ void *callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, CallInvokeMethodIfExists, iclsPtr,
+ contextObj, INT2PTR(0), NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ } else {
+ result = Itcl_ConstructBase(interp, contextObj, iclsPtr);
+ }
+ }
+ Tcl_DecrRefCount(objPtr);
+ return result;
+}
+
+int
+ItclConstructGuts(
+ ItclObject *contextObj,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const objv[])
+{
+ ItclClass *contextClass;
+
+ /* Ignore syntax error */
+ if (objc != 3) {
+ return TCL_OK;
+ }
+
+ /* Object is fully constructed. This becomes no-op. */
+ if (contextObj->constructed == NULL) {
+ return TCL_OK;
+ }
+
+ contextClass = Itcl_FindClass(interp, Tcl_GetString(objv[2]), 0);
+ if (contextClass == NULL) {
+ return TCL_OK;
+ }
+
+
+ return Itcl_ConstructBase(interp, contextObj, contextClass);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InvokeMethodIfExists()
+ *
+ * Looks for a particular method in the specified class. If the
+ * method is found, it is invoked with the given arguments. Any
+ * protection level (protected/private) for the method is ignored.
+ * If the method does not exist, this procedure does nothing.
+ *
+ * This procedure is used primarily to invoke the constructor/destructor
+ * when an object is created/destroyed.
+ *
+ * Returns TCL_OK on success; otherwise, this procedure returns
+ * TCL_ERROR along with an error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_InvokeMethodIfExists(
+ Tcl_Interp *interp, /* interpreter */
+ const char *name, /* name of desired method */
+ ItclClass *contextClassPtr, /* current class being constructed */
+ ItclObject *contextObjectPtr, /* object being constructed */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *cmdlinePtr;
+ Tcl_Obj **cmdlinev;
+ Tcl_Obj **newObjv;
+ Tcl_CallFrame frame;
+ ItclMemberFunc *imPtr;
+ int cmdlinec;
+ int result = TCL_OK;
+ Tcl_Obj *objPtr = Tcl_NewStringObj(name, -1);
+
+ ItclShowArgs(1, "Itcl_InvokeMethodIfExists", objc, objv);
+ hPtr = Tcl_FindHashEntry(&contextClassPtr->functions, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr) {
+ imPtr = (ItclMemberFunc*)Tcl_GetHashValue(hPtr);
+
+ /*
+ * Prepend the method name to the list of arguments.
+ */
+ cmdlinePtr = Itcl_CreateArgs(interp, name, objc, objv);
+
+ (void) Tcl_ListObjGetElements((Tcl_Interp*)NULL, cmdlinePtr,
+ &cmdlinec, &cmdlinev);
+
+ ItclShowArgs(1, "EMC", cmdlinec, cmdlinev);
+ /*
+ * Execute the code for the method. Be careful to protect
+ * the method in case it gets deleted during execution.
+ */
+ ItclPreserveIMF(imPtr);
+
+ if (contextObjectPtr->oPtr == NULL) {
+ Tcl_DecrRefCount(cmdlinePtr);
+ return TCL_ERROR;
+ }
+ result = Itcl_EvalMemberCode(interp, imPtr, contextObjectPtr,
+ cmdlinec, cmdlinev);
+ ItclReleaseIMF(imPtr);
+ Tcl_DecrRefCount(cmdlinePtr);
+ } else {
+ if (contextClassPtr->flags &
+ (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ if (strcmp(name, "constructor") == 0) {
+ if (objc > 0) {
+ if (contextClassPtr->numOptions == 0) {
+ /* check if all options are delegeted */
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj("*", -1);
+ hPtr = Tcl_FindHashEntry(
+ &contextClassPtr->delegatedOptions,
+ (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "type \"",
+ Tcl_GetString(contextClassPtr->namePtr),
+ "\" has no options, but constructor has",
+ " option arguments", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (Itcl_PushCallFrame(interp, &frame,
+ contextClassPtr->nsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR in",
+ "Itcl_InvokeMethodIfExists Itcl_PushCallFrame",
+ NULL);
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc + 2));
+ newObjv[0] = Tcl_NewStringObj("my", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("configure", -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ memcpy(newObjv + 2, objv, (objc * sizeof(Tcl_Obj *)));
+ ItclShowArgs(1, "DEFAULT Constructor", objc + 2, newObjv);
+ result = Tcl_EvalObjv(interp, objc + 2, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[0]);
+ ckfree((char *)newObjv);
+ Itcl_PopCallFrame(interp);
+ }
+ }
+ }
+ }
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ReportFuncErrors()
+ *
+ * Used to interpret the status code returned when the body of a
+ * Tcl-style proc is executed. Handles the "errorInfo" and "errorCode"
+ * variables properly, and adds error information into the interpreter
+ * if anything went wrong. Returns a new status code that should be
+ * treated as the return status code for the command.
+ *
+ * This same operation is usually buried in the Tcl InterpProc()
+ * procedure. It is defined here so that it can be reused more easily.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ReportFuncErrors(
+ Tcl_Interp* interp, /* interpreter being modified */
+ ItclMemberFunc *imPtr, /* command member that was invoked */
+ ItclObject *contextObj, /* object context for this command */
+ int result) /* integer status code from proc body */
+{
+/* FIXME !!! */
+/* adapt to use of ItclProcErrorProc for stubs compatibility !! */
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CmdAliasProc()
+ *
+ * ------------------------------------------------------------------------
+ */
+Tcl_Command
+Itcl_CmdAliasProc(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *cmdName,
+ ClientData clientData)
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+ ItclMemberFunc *imPtr;
+ ItclResolveInfo *resolveInfoPtr;
+ ItclCmdLookup *clookup;
+
+ resolveInfoPtr = (ItclResolveInfo *)clientData;
+ if (resolveInfoPtr->flags & ITCL_RESOLVE_OBJECT) {
+ ioPtr = resolveInfoPtr->ioPtr;
+ iclsPtr = ioPtr->iclsPtr;
+ } else {
+ ioPtr = NULL;
+ iclsPtr = resolveInfoPtr->iclsPtr;
+ }
+ infoPtr = iclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ objPtr = Tcl_NewStringObj(cmdName, -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr == NULL) {
+ if (strcmp(cmdName, "@itcl-builtin-cget") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::cget", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-configure") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::configure", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-destroy") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::destroy", NULL, 0);
+ }
+ if (strncmp(cmdName, "@itcl-builtin-setget", 20) == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::setget", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-isa") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::isa", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-createhull") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::createhull", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-keepcomponentoption") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::keepcomponentoption", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-ignorecomponentoption") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::removecomponentoption", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-irgnorecomponentoption") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::ignorecomponentoption", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-setupcomponent") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::setupcomponent", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-initoptions") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::initoptions", NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-mytypemethod") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::mytypemethod",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-mymethod") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::mymethod",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-myproc") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::myproc",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-mytypevar") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::mytypevar",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-myvar") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::myvar",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-itcl_hull") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::itcl_hull",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-callinstance") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::callinstance",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-getinstancevar") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::getinstancevar",
+ NULL, 0);
+ }
+ if (strcmp(cmdName, "@itcl-builtin-classunknown") == 0) {
+ return Tcl_FindCommand(interp, "::itcl::builtin::classunknown", NULL, 0);
+ }
+ return NULL;
+ }
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ return imPtr->accessCmd;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_VarAliasProc()
+ *
+ * ------------------------------------------------------------------------
+ */
+Tcl_Var
+Itcl_VarAliasProc(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *varName,
+ ClientData clientData)
+{
+
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclObject *ioPtr;
+ ItclVarLookup *ivlPtr;
+ ItclResolveInfo *resolveInfoPtr;
+ ItclCallContext *callContextPtr;
+ Tcl_Var varPtr;
+
+ varPtr = NULL;
+ hPtr = NULL;
+ callContextPtr = NULL;
+ resolveInfoPtr = (ItclResolveInfo *)clientData;
+ if (resolveInfoPtr->flags & ITCL_RESOLVE_OBJECT) {
+ ioPtr = resolveInfoPtr->ioPtr;
+ iclsPtr = ioPtr->iclsPtr;
+ } else {
+ ioPtr = NULL;
+ iclsPtr = resolveInfoPtr->iclsPtr;
+ }
+ infoPtr = iclsPtr->infoPtr;
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr != NULL) {
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, varName);
+ if (hPtr == NULL) {
+ /* no class/object variable */
+ return NULL;
+ }
+ ivlPtr = Tcl_GetHashValue(hPtr);
+ if (ivlPtr == NULL) {
+ return NULL;
+ }
+ if (!ivlPtr->accessible) {
+ return NULL;
+ }
+
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectVariables,
+ (char *)ivlPtr->ivPtr);
+ } else {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->classCommons,
+ (char *)ivlPtr->ivPtr);
+ if (hPtr == NULL) {
+ if (callContextPtr != NULL) {
+ ioPtr = callContextPtr->ioPtr;
+ }
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectVariables,
+ (char *)ivlPtr->ivPtr);
+ }
+ }
+ }
+ if (hPtr != NULL) {
+ varPtr = Tcl_GetHashValue(hPtr);
+ }
+ return varPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCheckCallProc()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCheckCallProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr,
+ Tcl_CallFrame *framePtr,
+ int *isFinished)
+{
+ int result;
+ ItclMemberFunc *imPtr;
+
+ imPtr = (ItclMemberFunc *)clientData;
+ if (!imPtr->iclsPtr->infoPtr->useOldResolvers) {
+ Itcl_SetCallFrameResolver(interp, imPtr->iclsPtr->resolvePtr);
+ }
+ result = TCL_OK;
+
+ if (isFinished != NULL) {
+ *isFinished = 0;
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCheckCallMethod()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCheckCallMethod(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr,
+ Tcl_CallFrame *framePtr,
+ int *isFinished)
+{
+ Itcl_Stack *stackPtr;
+
+ Tcl_Object oPtr;
+ ItclObject *ioPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *const * cObjv;
+ Tcl_Namespace *currNsPtr;
+ ItclCallContext *callContextPtr;
+ ItclCallContext *callContextPtr2;
+ ItclMemberFunc *imPtr;
+ int result;
+ int isNew;
+ int cObjc;
+ int min_allowed_args;
+
+ ItclObjectInfo *infoPtr;
+
+ oPtr = NULL;
+ hPtr = NULL;
+ imPtr = (ItclMemberFunc *)clientData;
+ ItclPreserveIMF(imPtr);
+ if (imPtr->flags & ITCL_CONSTRUCTOR) {
+ ioPtr = imPtr->iclsPtr->infoPtr->currIoPtr;
+ } else {
+ if (contextPtr == NULL) {
+ if ((imPtr->flags & ITCL_COMMON) ||
+ (imPtr->codePtr->flags & ITCL_BUILTIN)) {
+ if (!imPtr->iclsPtr->infoPtr->useOldResolvers) {
+ Itcl_SetCallFrameResolver(interp,
+ imPtr->iclsPtr->resolvePtr);
+ }
+ if (isFinished != NULL) {
+ *isFinished = 0;
+ }
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp,
+ "ItclCheckCallMethod cannot get context object (NULL)",
+ " for ", Tcl_GetString(imPtr->fullNamePtr),
+ NULL);
+ result = TCL_ERROR;
+ goto finishReturn;
+ }
+ oPtr = Tcl_ObjectContextObject(contextPtr);
+ ioPtr = Tcl_ObjectGetMetadata(oPtr,
+ imPtr->iclsPtr->infoPtr->object_meta_type);
+ }
+ if ((imPtr->codePtr != NULL) &&
+ (imPtr->codePtr->flags & ITCL_IMPLEMENT_NONE)) {
+ Tcl_AppendResult(interp, "member function \"",
+ Tcl_GetString(imPtr->fullNamePtr),
+ "\" is not defined and cannot be autoloaded", NULL);
+ if (isFinished != NULL) {
+ *isFinished = 1;
+ }
+ result = TCL_ERROR;
+ goto finishReturn;
+ }
+ if (framePtr) {
+ /*
+ * This stanza is in place to seize control over usage error messages
+ * before TclOO examines the arguments and produces its own. This
+ * gives Itcl stability in its error messages at the cost of inconsistency
+ * with Tcl's evolving conventions.
+ */
+ cObjc = Itcl_GetCallFrameObjc(interp);
+ cObjv = Itcl_GetCallFrameObjv(interp);
+ min_allowed_args = cObjc-2;
+ if (strcmp(Tcl_GetString(cObjv[0]), "next") == 0) {
+ min_allowed_args++;
+ }
+ if (min_allowed_args < imPtr->argcount) {
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetString(cObjv[0]), " ", Tcl_GetString(imPtr->namePtr),
+ " ", Tcl_GetString(imPtr->usagePtr), "\"", NULL);
+ if (isFinished != NULL) {
+ *isFinished = 1;
+ }
+ result = TCL_ERROR;
+ goto finishReturn;
+ }
+ }
+ isNew = 0;
+ callContextPtr = NULL;
+ currNsPtr = Tcl_GetCurrentNamespace(interp);
+ if (ioPtr != NULL) {
+ hPtr = Tcl_CreateHashEntry(&ioPtr->contextCache, (char *)imPtr, &isNew);
+ if (!isNew) {
+ callContextPtr2 = Tcl_GetHashValue(hPtr);
+ if (callContextPtr2->refCount == 0) {
+ callContextPtr = callContextPtr2;
+ callContextPtr->objectFlags = ioPtr->flags;
+ callContextPtr->nsPtr = Tcl_GetCurrentNamespace(interp);
+ callContextPtr->ioPtr = ioPtr;
+ callContextPtr->imPtr = imPtr;
+ callContextPtr->refCount = 1;
+ } else {
+ if ((callContextPtr2->objectFlags == ioPtr->flags)
+ && (callContextPtr2->nsPtr == currNsPtr)) {
+ callContextPtr = callContextPtr2;
+ callContextPtr->refCount++;
+ }
+ }
+ }
+ }
+ if (callContextPtr == NULL) {
+ callContextPtr = (ItclCallContext *)ckalloc(
+ sizeof(ItclCallContext));
+ if (ioPtr == NULL) {
+ callContextPtr->objectFlags = 0;
+ callContextPtr->ioPtr = NULL;
+ } else {
+ callContextPtr->objectFlags = ioPtr->flags;
+ callContextPtr->ioPtr = ioPtr;
+ }
+ callContextPtr->nsPtr = Tcl_GetCurrentNamespace(interp);
+ callContextPtr->imPtr = imPtr;
+ callContextPtr->refCount = 1;
+ }
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, callContextPtr);
+ }
+
+ if (framePtr == NULL) {
+ framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+ }
+
+ isNew = 0;
+ infoPtr = imPtr->iclsPtr->infoPtr;
+ hPtr = Tcl_CreateHashEntry(&infoPtr->frameContext,
+ (char *)framePtr, &isNew);
+ if (isNew) {
+ stackPtr = (Itcl_Stack *)ckalloc(sizeof(Itcl_Stack));
+ Itcl_InitStack(stackPtr);
+ Tcl_SetHashValue(hPtr, stackPtr);
+ } else {
+ stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ }
+
+ assert (callContextPtr) ;
+ Itcl_PushStack(callContextPtr, stackPtr);
+
+ /* Ugly abuse alert. Two maps in one table */
+ hPtr = Tcl_CreateHashEntry(&infoPtr->frameContext,
+ (char *)contextPtr, &isNew);
+ if (isNew) {
+ stackPtr = (Itcl_Stack *)ckalloc(sizeof(Itcl_Stack));
+ Itcl_InitStack(stackPtr);
+ Tcl_SetHashValue(hPtr, stackPtr);
+ } else {
+ stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ }
+
+ Itcl_PushStack(framePtr, stackPtr);
+
+ if (ioPtr != NULL) {
+ ioPtr->callRefCount++;
+ ItclPreserveObject(ioPtr);
+ }
+ imPtr->iclsPtr->callRefCount++;
+ if (!imPtr->iclsPtr->infoPtr->useOldResolvers) {
+ Itcl_SetCallFrameResolver(interp, ioPtr->resolvePtr);
+ }
+ result = TCL_OK;
+
+ if (isFinished != NULL) {
+ *isFinished = 0;
+ }
+ return result;
+finishReturn:
+ ItclReleaseIMF(imPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclAfterCallMethod()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclAfterCallMethod(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext contextPtr,
+ Tcl_Namespace *nsPtr,
+ int call_result)
+{
+ Tcl_HashEntry *hPtr;
+ ItclObject *ioPtr;
+ ItclMemberFunc *imPtr;
+ ItclCallContext *callContextPtr;
+ int newEntry;
+ int result;
+
+ imPtr = (ItclMemberFunc *)clientData;
+ callContextPtr = NULL;
+ if (contextPtr != NULL) {
+ ItclObjectInfo *infoPtr = imPtr->infoPtr;
+ Tcl_CallFrame *framePtr;
+ Itcl_Stack *stackPtr;
+
+ hPtr = Tcl_FindHashEntry(&infoPtr->frameContext, (char *)contextPtr);
+ assert(hPtr);
+ stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ framePtr = Itcl_PopStack(stackPtr);
+ if (Itcl_GetStackSize(stackPtr) == 0) {
+ Itcl_DeleteStack(stackPtr);
+ ckfree((char *) stackPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ hPtr = Tcl_FindHashEntry(&infoPtr->frameContext, (char *)framePtr);
+ assert(hPtr);
+ stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ callContextPtr = Itcl_PopStack(stackPtr);
+ if (Itcl_GetStackSize(stackPtr) == 0) {
+ Itcl_DeleteStack(stackPtr);
+ ckfree((char *) stackPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ if (callContextPtr == NULL) {
+ if ((imPtr->flags & ITCL_COMMON) ||
+ (imPtr->codePtr->flags & ITCL_BUILTIN)) {
+ result = call_result;
+ goto finishReturn;
+ }
+ Tcl_AppendResult(interp,
+ "ItclAfterCallMethod cannot get context object (NULL)",
+ " for ", Tcl_GetString(imPtr->fullNamePtr), NULL);
+ result = TCL_ERROR;
+ goto finishReturn;
+ }
+ /*
+ * If this is a constructor or destructor, and if it is being
+ * invoked at the appropriate time, keep track of which methods
+ * have been called. This information is used to implicitly
+ * invoke constructors/destructors as needed.
+ */
+ ioPtr = callContextPtr->ioPtr;
+ if (ioPtr != NULL) {
+ if (imPtr->iclsPtr) {
+ imPtr->iclsPtr->callRefCount--;
+ if (imPtr->flags & (ITCL_CONSTRUCTOR | ITCL_DESTRUCTOR)) {
+ if ((imPtr->flags & ITCL_DESTRUCTOR) && ioPtr &&
+ ioPtr->destructed) {
+ Tcl_CreateHashEntry(ioPtr->destructed,
+ (char *)imPtr->iclsPtr->namePtr, &newEntry);
+ }
+ if ((imPtr->flags & ITCL_CONSTRUCTOR) && ioPtr &&
+ ioPtr->constructed) {
+ Tcl_CreateHashEntry(ioPtr->constructed,
+ (char *)imPtr->iclsPtr->namePtr, &newEntry);
+ }
+ }
+ }
+ ioPtr->callRefCount--;
+ if (ioPtr->flags & ITCL_OBJECT_SHOULD_VARNS_DELETE) {
+ ItclDeleteObjectVariablesNamespace(interp, ioPtr);
+ }
+ }
+
+ callContextPtr->refCount--;
+ if (callContextPtr->refCount == 0) {
+ if (callContextPtr->ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&callContextPtr->ioPtr->contextCache,
+ (char *)callContextPtr->imPtr);
+ if (hPtr == NULL) {
+ ckfree((char *)callContextPtr);
+ }
+ ItclReleaseObject(ioPtr);
+ } else {
+ ckfree((char *)callContextPtr);
+ }
+ }
+ result = call_result;
+finishReturn:
+ ItclReleaseIMF(imPtr);
+ return result;
+}
+
+void
+ItclProcErrorProc(
+ Tcl_Interp *interp,
+ Tcl_Obj *procNameObj)
+{
+ Tcl_Obj *objPtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclCallContext *callContextPtr;
+ ItclMemberFunc *imPtr;
+ ItclObject *contextIoPtr;
+ ItclClass *currIclsPtr;
+ char num[20];
+ Itcl_Stack *stackPtr;
+
+ /* Fetch the current call frame. That determines context. */
+ Tcl_CallFrame *framePtr = Itcl_GetUplevelCallFrame(interp, 0);
+
+ /* Try to map it to a context stack. */
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->frameContext, (char *)framePtr);
+ if (hPtr == NULL) {
+ /* Can this happen? */
+ return;
+ }
+
+ /* Frame maps to a context stack. */
+ stackPtr = (Itcl_Stack *)Tcl_GetHashValue(hPtr);
+ callContextPtr = Itcl_PeekStack(stackPtr);
+
+ if (callContextPtr == NULL) {
+ return;
+ }
+
+ currIclsPtr = NULL;
+ objPtr = NULL;
+ {
+ imPtr = callContextPtr->imPtr;
+ contextIoPtr = callContextPtr->ioPtr;
+ objPtr = Tcl_NewStringObj("\n ", -1);
+
+ if (imPtr->flags & ITCL_CONSTRUCTOR) {
+ currIclsPtr = imPtr->iclsPtr;
+ Tcl_AppendToObj(objPtr, "while constructing object \"", -1);
+ Tcl_GetCommandFullName(interp, contextIoPtr->accessCmd, objPtr);
+ Tcl_AppendToObj(objPtr, "\" in ", -1);
+ Tcl_AppendToObj(objPtr, currIclsPtr->nsPtr->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::constructor", -1);
+ if ((imPtr->codePtr->flags & ITCL_IMPLEMENT_TCL) != 0) {
+ Tcl_AppendToObj(objPtr, " (", -1);
+ }
+ }
+ if (imPtr->flags & ITCL_DESTRUCTOR) {
+ contextIoPtr->flags = 0;
+ Tcl_AppendToObj(objPtr, "while deleting object \"", -1);
+ Tcl_GetCommandFullName(interp, contextIoPtr->accessCmd, objPtr);
+ Tcl_AppendToObj(objPtr, "\" in ", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(imPtr->fullNamePtr), -1);
+ if ((imPtr->codePtr->flags & ITCL_IMPLEMENT_TCL) != 0) {
+ Tcl_AppendToObj(objPtr, " (", -1);
+ }
+ }
+ if (!(imPtr->flags & (ITCL_CONSTRUCTOR|ITCL_DESTRUCTOR))) {
+ Tcl_AppendToObj(objPtr, "(", -1);
+
+ hPtr = Tcl_FindHashEntry(&infoPtr->objects, (char *)contextIoPtr);
+ if (hPtr != NULL) {
+ if ((contextIoPtr != NULL) && (contextIoPtr->accessCmd)) {
+ Tcl_AppendToObj(objPtr, "object \"", -1);
+ Tcl_GetCommandFullName(interp, contextIoPtr->accessCmd, objPtr);
+ Tcl_AppendToObj(objPtr, "\" ", -1);
+ }
+ }
+
+ if ((imPtr->flags & ITCL_COMMON) != 0) {
+ Tcl_AppendToObj(objPtr, "procedure", -1);
+ } else {
+ Tcl_AppendToObj(objPtr, "method", -1);
+ }
+ Tcl_AppendToObj(objPtr, " \"", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(imPtr->fullNamePtr), -1);
+ Tcl_AppendToObj(objPtr, "\" ", -1);
+ }
+
+ if ((imPtr->codePtr->flags & ITCL_IMPLEMENT_TCL) != 0) {
+ Tcl_Obj *dictPtr;
+ Tcl_Obj *keyPtr;
+ Tcl_Obj *valuePtr;
+ int lineNo;
+
+ keyPtr = Tcl_NewStringObj("-errorline", -1);
+ dictPtr = Tcl_GetReturnOptions(interp, TCL_ERROR);
+ if (Tcl_DictObjGet(interp, dictPtr, keyPtr, &valuePtr) != TCL_OK) {
+ /* how should we handle an error ? */
+ Tcl_DecrRefCount(keyPtr);
+ Tcl_DecrRefCount(objPtr);
+ return;
+ }
+ if (valuePtr == NULL) {
+ /* how should we handle an error ? */
+ Tcl_DecrRefCount(keyPtr);
+ Tcl_DecrRefCount(objPtr);
+ return;
+ }
+ if (Tcl_GetIntFromObj(interp, valuePtr, &lineNo) != TCL_OK) {
+ /* how should we handle an error ? */
+ Tcl_DecrRefCount(keyPtr);
+ Tcl_DecrRefCount(valuePtr);
+ Tcl_DecrRefCount(objPtr);
+ return;
+ }
+ Tcl_DecrRefCount(keyPtr);
+ Tcl_DecrRefCount(valuePtr);
+ Tcl_AppendToObj(objPtr, "body line ", -1);
+ sprintf(num, "%d", lineNo);
+ Tcl_AppendToObj(objPtr, num, -1);
+ Tcl_AppendToObj(objPtr, ")", -1);
+ } else {
+ Tcl_AppendToObj(objPtr, ")", -1);
+ }
+
+ Tcl_AppendObjToErrorInfo(interp, objPtr);
+ objPtr = NULL;
+ }
+ if (objPtr != NULL) {
+ Tcl_DecrRefCount(objPtr);
+ }
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.c
new file mode 100644
index 0000000..9f035c8
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.c
@@ -0,0 +1,287 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * This file contains procedures that belong in the Tcl/Tk core.
+ * Hopefully, they'll migrate there soon.
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ *
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include <tclInt.h>
+#include "itclInt.h"
+
+int
+Itcl_SetCallFrameResolver(
+ Tcl_Interp *interp,
+ Tcl_Resolve *resolvePtr)
+{
+ CallFrame *framePtr = ((Interp *)interp)->framePtr;
+ if (framePtr != NULL) {
+#ifdef ITCL_USE_MODIFIED_TCL_H
+ framePtr->isProcCallFrame |= FRAME_HAS_RESOLVER;
+ framePtr->resolvePtr = resolvePtr;
+#endif
+ return TCL_OK;
+ }
+ return TCL_ERROR;
+}
+
+int
+_Tcl_SetNamespaceResolver(
+ Tcl_Namespace *nsPtr,
+ Tcl_Resolve *resolvePtr)
+{
+ if (nsPtr == NULL) {
+ return TCL_ERROR;
+ }
+#ifdef ITCL_USE_MODIFIED_TCL_H
+ ((Namespace *)nsPtr)->resolvePtr = resolvePtr;
+#endif
+ return TCL_OK;
+}
+
+Tcl_Var
+Tcl_NewNamespaceVar(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *varName)
+{
+ Var *varPtr = NULL;
+ int new;
+
+ if ((nsPtr == NULL) || (varName == NULL)) {
+ return NULL;
+ }
+
+ varPtr = TclVarHashCreateVar(&((Namespace *)nsPtr)->varTable,
+ varName, &new);
+ TclSetVarNamespaceVar(varPtr);
+ return (Tcl_Var)varPtr;
+}
+
+void
+Itcl_PreserveVar(
+ Tcl_Var var)
+{
+ Var *varPtr = (Var *)var;
+
+ VarHashRefCount(varPtr)++;
+}
+
+void
+Itcl_ReleaseVar(
+ Tcl_Var var)
+{
+ Var *varPtr = (Var *)var;
+
+ VarHashRefCount(varPtr)--;
+ TclCleanupVar(varPtr, NULL);
+}
+
+Tcl_CallFrame *
+Itcl_GetUplevelCallFrame(
+ Tcl_Interp *interp,
+ int level)
+{
+ CallFrame *framePtr;
+ if (level < 0) {
+ return NULL;
+ }
+ framePtr = ((Interp *)interp)->varFramePtr;
+ while ((framePtr != NULL) && (level-- > 0)) {
+ framePtr = framePtr->callerVarPtr;
+ }
+ if (framePtr == NULL) {
+ return NULL;
+ }
+ return (Tcl_CallFrame *)framePtr;
+}
+
+Tcl_CallFrame *
+Itcl_ActivateCallFrame(
+ Tcl_Interp *interp,
+ Tcl_CallFrame *framePtr)
+{
+ Interp *iPtr = (Interp*)interp;
+ CallFrame *oldFramePtr;
+
+ oldFramePtr = iPtr->varFramePtr;
+ iPtr->varFramePtr = (CallFrame *) framePtr;
+
+ return (Tcl_CallFrame *) oldFramePtr;
+}
+
+Tcl_Namespace *
+Itcl_GetUplevelNamespace(
+ Tcl_Interp *interp,
+ int level)
+{
+ CallFrame *framePtr;
+ if (level < 0) {
+ return NULL;
+ }
+ framePtr = ((Interp *)interp)->framePtr;
+ while ((framePtr != NULL) && (level-- > 0)) {
+ framePtr = framePtr->callerVarPtr;
+ }
+ if (framePtr == NULL) {
+ return NULL;
+ }
+ return (Tcl_Namespace *)framePtr->nsPtr;
+}
+
+ClientData
+Itcl_GetCallFrameClientData(
+ Tcl_Interp *interp)
+{
+ /* suggested fix for SF bug #250 use varFramePtr instead of framePtr
+ * seems to have no side effect concerning test suite, but does NOT fix the bug
+ */
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ if (framePtr == NULL) {
+ return NULL;
+ }
+ return framePtr->clientData;
+}
+
+int
+Itcl_SetCallFrameNamespace(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr)
+{
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ if (framePtr == NULL) {
+ return TCL_ERROR;
+ }
+ ((Interp *)interp)->varFramePtr->nsPtr = (Namespace *)nsPtr;
+ return TCL_OK;
+}
+
+int
+Itcl_GetCallVarFrameObjc(
+ Tcl_Interp *interp)
+{
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ if (framePtr == NULL) {
+ return 0;
+ }
+ return framePtr->objc;
+}
+
+Tcl_Obj * const *
+Itcl_GetCallVarFrameObjv(
+ Tcl_Interp *interp)
+{
+ CallFrame *framePtr = ((Interp *)interp)->varFramePtr;
+ if (framePtr == NULL) {
+ return NULL;
+ }
+ return framePtr->objv;
+}
+
+int
+Itcl_GetCallFrameObjc(
+ Tcl_Interp *interp)
+{
+ CallFrame *framePtr = ((Interp *)interp)->framePtr;
+ if (framePtr == NULL) {
+ return 0;
+ }
+ return ((Interp *)interp)->framePtr->objc;
+}
+
+Tcl_Obj * const *
+Itcl_GetCallFrameObjv(
+ Tcl_Interp *interp)
+{
+ CallFrame *framePtr = ((Interp *)interp)->framePtr;
+ if (framePtr == NULL) {
+ return NULL;
+ }
+ return ((Interp *)interp)->framePtr->objv;
+}
+
+int
+Itcl_IsCallFrameArgument(
+ Tcl_Interp *interp,
+ const char *name)
+{
+ CallFrame *varFramePtr = ((Interp *)interp)->framePtr;
+ Proc *procPtr;
+
+ if (varFramePtr == NULL) {
+ return 0;
+ }
+ if (!varFramePtr->isProcCallFrame) {
+ return 0;
+ }
+ procPtr = varFramePtr->procPtr;
+ /*
+ * Search through compiled locals first...
+ */
+ if (procPtr) {
+ CompiledLocal *localPtr = procPtr->firstLocalPtr;
+ int nameLen = strlen(name);
+
+ for (;localPtr != NULL; localPtr = localPtr->nextPtr) {
+ if (TclIsVarArgument(localPtr)) {
+ register char *localName = localPtr->name;
+ if ((name[0] == localName[0])
+ && (nameLen == localPtr->nameLength)
+ && (strcmp(name, localName) == 0)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+Itcl_IsCallFrameLinkVar(
+ Tcl_Interp *interp,
+ const char *name)
+{
+ CallFrame *varFramePtr = ((Interp *)interp)->framePtr;
+ Proc *procPtr;
+
+ if (varFramePtr == NULL) {
+ return 0;
+ }
+ if (!varFramePtr->isProcCallFrame) {
+ return 0;
+ }
+ procPtr = varFramePtr->procPtr;
+ /*
+ * Search through compiled locals first...
+ */
+ if (procPtr) {
+ CompiledLocal *localPtr = procPtr->firstLocalPtr;
+ int nameLen = strlen(name);
+
+ for (;localPtr != NULL; localPtr = localPtr->nextPtr) {
+ if (TclIsVarLink(localPtr)) {
+ register char *localName = localPtr->name;
+ if ((name[0] == localName[0])
+ && (nameLen == localPtr->nameLength)
+ && (strcmp(name, localName) == 0)) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+int
+Itcl_IsVarLink(Tcl_Var varPtr) {
+ return TclIsVarLink((Var *)varPtr);
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.h
new file mode 100644
index 0000000..012ea0b
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclMigrate2TclCore.h
@@ -0,0 +1,87 @@
+#ifndef ITCL_USE_MODIFIED_TCL_H
+/* this is just to provide the definition. This struct is only used if
+ * infoPtr->useOldResolvers == 0 which is not the default
+ */
+#define FRAME_HAS_RESOLVER 0x100
+typedef Tcl_Command (Tcl_CmdAliasProc)(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *cmdName,
+ ClientData clientData);
+typedef Tcl_Var (Tcl_VarAliasProc)(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *varName,
+ ClientData clientData);
+
+#ifndef _TCL_RESOLVE_DEFINED
+typedef struct Tcl_Resolve {
+ Tcl_VarAliasProc *varProcPtr;
+ Tcl_CmdAliasProc *cmdProcPtr;
+ ClientData clientData;
+} Tcl_Resolve;
+#define _TCL_RESOLVE_DEFINED 1
+#endif
+#endif
+
+#ifndef _TCLINT
+struct Tcl_ResolvedVarInfo;
+
+typedef Tcl_Var (Tcl_ResolveRuntimeVarProc)(Tcl_Interp *interp,
+ struct Tcl_ResolvedVarInfo *vinfoPtr);
+
+typedef void (Tcl_ResolveVarDeleteProc)(struct Tcl_ResolvedVarInfo *vinfoPtr);
+
+/*
+ * The following structure encapsulates the routines needed to resolve a
+ * variable reference at runtime. Any variable specific state will typically
+ * be appended to this structure.
+ */
+
+typedef struct Tcl_ResolvedVarInfo {
+ Tcl_ResolveRuntimeVarProc *fetchProc;
+ Tcl_ResolveVarDeleteProc *deleteProc;
+} Tcl_ResolvedVarInfo;
+
+typedef int (Tcl_ResolveCompiledVarProc) (Tcl_Interp *interp,
+ const char *name, int length, Tcl_Namespace *context,
+ Tcl_ResolvedVarInfo **rPtr);
+
+typedef int (Tcl_ResolveVarProc) (Tcl_Interp *interp, const char *name,
+ Tcl_Namespace *context, int flags, Tcl_Var *rPtr);
+
+typedef int (Tcl_ResolveCmdProc) (Tcl_Interp *interp, const char *name,
+ Tcl_Namespace *context, int flags, Tcl_Command *rPtr);
+
+typedef struct Tcl_ResolverInfo {
+ Tcl_ResolveCmdProc *cmdResProc;
+ /* Procedure handling command name
+ * resolution. */
+ Tcl_ResolveVarProc *varResProc;
+ /* Procedure handling variable name resolution
+ * for variables that can only be handled at
+ * runtime. */
+ Tcl_ResolveCompiledVarProc *compiledVarResProc;
+ /* Procedure handling variable name resolution
+ * at compile time. */
+} Tcl_ResolverInfo;
+#endif
+
+
+/* here come the definitions for code which should be migrated to Tcl core */
+/* these functions DO NOT exist and are not published */
+#ifndef _TCL_PROC_DEFINED
+typedef struct Tcl_Proc_ *Tcl_Proc;
+#define _TCL_PROC_DEFINED 1
+#endif
+
+#define Tcl_SetProcCmd _Tcl_SetProcCmd
+
+MODULE_SCOPE Tcl_Var Tcl_NewNamespaceVar(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ const char *varName);
+MODULE_SCOPE void Itcl_PreserveVar(Tcl_Var var);
+MODULE_SCOPE void Itcl_ReleaseVar(Tcl_Var var);
+MODULE_SCOPE int Itcl_IsCallFrameArgument(Tcl_Interp *interp, const char *name);
+MODULE_SCOPE int Itcl_GetCallVarFrameObjc(Tcl_Interp *interp);
+MODULE_SCOPE int Itcl_IsVarLink(Tcl_Var var);
+MODULE_SCOPE int Itcl_IsCallFrameLinkVar(Tcl_Interp *interp, const char *name);
+MODULE_SCOPE Tcl_Obj * const * Itcl_GetCallVarFrameObjv(Tcl_Interp *interp);
+#define Tcl_SetNamespaceResolver _Tcl_SetNamespaceResolver
+MODULE_SCOPE int _Tcl_SetNamespaceResolver(Tcl_Namespace *nsPtr,
+ struct Tcl_Resolve *resolvePtr);
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclObject.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclObject.c
new file mode 100644
index 0000000..2e60c97
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclObject.c
@@ -0,0 +1,3845 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This segment handles "objects" which are instantiated from class
+ * definitions. Objects contain public/protected/private data members
+ * from all classes in a derivation hierarchy.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann Copyright (c) 2007
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include <tclInt.h>
+#include "itclInt.h"
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static char* ItclTraceThisVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceTypeVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceSelfVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceSelfnsVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceWinVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceOptionVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceComponentVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+static char* ItclTraceItclHullVar(ClientData cdata, Tcl_Interp *interp,
+ const char *name1, const char *name2, int flags);
+
+static void ItclDestroyObject(ClientData clientData);
+static void ItclFreeObject(char * clientData);
+
+static int ItclDestructBase(Tcl_Interp *interp, ItclObject *contextObj,
+ ItclClass *contextClass, int flags);
+
+static int ItclInitObjectVariables(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr);
+static int ItclInitObjectCommands(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr, const char *name);
+static int ItclInitExtendedClassOptions(Tcl_Interp *interp, ItclObject *ioPtr);
+static int ItclInitObjectOptions(Tcl_Interp *interp, ItclObject *ioPtr,
+ ItclClass *iclsPtr);
+static const char * GetConstructorVar(Tcl_Interp *interp, ItclClass *iclsPtr,
+ const char *varName);
+static ItclClass * GetClassFromClassName(Tcl_Interp *interp,
+ const char *className, ItclClass *iclsPtr);
+
+void
+ItclPreserveObject(
+ ItclObject *ioPtr)
+{
+ ioPtr->refCount++;
+}
+
+void
+ItclReleaseObject(
+ ClientData clientData)
+{
+ ItclObject *ioPtr = (ItclObject *)clientData;
+
+ if (--ioPtr->refCount == 0) {
+ ItclFreeObject((char *) clientData);
+ }
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteObjectMetadata()
+ *
+ * Delete the metadata data if any
+ *-------------------------------------------------------------------------
+ */
+void
+ItclDeleteObjectMetadata(
+ ClientData clientData)
+{
+ ItclObject *ioPtr = (ItclObject *)clientData;
+ Tcl_HashEntry *hPtr;
+
+ if (ioPtr == NULL) return; /* Safety */
+ if (ioPtr->oPtr == NULL) return; /* Safety */
+
+ hPtr = Tcl_FindHashEntry(&ioPtr->infoPtr->instances,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr))->fullName);
+
+ if (hPtr == NULL) return;
+
+ if (clientData != Tcl_GetHashValue(hPtr)) {
+ Tcl_Panic("invalid instances entry");
+ }
+ Tcl_DeleteHashEntry(hPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ObjectRenamedTrace()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static void
+ObjectRenamedTrace(
+ ClientData clientData, /* The object being deleted. */
+ Tcl_Interp *interp, /* The interpreter containing the object. */
+ const char *oldName, /* What the object was (last) called. */
+ const char *newName, /* Always NULL ??. not for itk!! */
+ int flags) /* Why was the object deleted? */
+{
+ ItclObject *ioPtr = clientData;
+ Itcl_InterpState istate;
+
+ if (newName != NULL) {
+ /* FIXME should enter the new name in the hashtables for objects etc. */
+ return;
+ }
+ if (ioPtr->flags & ITCL_OBJECT_CLASS_DESTRUCTED) {
+ return;
+ }
+ ioPtr->flags |= ITCL_OBJECT_IS_RENAMED;
+ if (ioPtr->flags & ITCL_TCLOO_OBJECT_IS_DELETED) {
+ ioPtr->oPtr = NULL;
+ }
+ if (!(ioPtr->flags & ITCL_OBJECT_CLASS_DESTRUCTED)) {
+ /*
+ * Attempt to destruct the object, but ignore any errors.
+ */
+ istate = Itcl_SaveInterpState(ioPtr->interp, 0);
+ Itcl_DestructObject(ioPtr->interp, ioPtr, ITCL_IGNORE_ERRS);
+ Itcl_RestoreInterpState(ioPtr->interp, istate);
+ ioPtr->flags |= ITCL_OBJECT_CLASS_DESTRUCTED;
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateObject()
+ *
+ */
+int
+Itcl_CreateObject(
+ Tcl_Interp *interp, /* interpreter mananging new object */
+ const char* name, /* name of new object */
+ ItclClass *iclsPtr, /* class for new object */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[], /* argument objects */
+ ItclObject **rioPtr) /* the created object */
+{
+ int result;
+ ItclObjectInfo * infoPtr;
+
+ result = ItclCreateObject(interp, name, iclsPtr, objc, objv);
+ if (result == TCL_OK) {
+ if (!(iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, name, NULL);
+ }
+ }
+ if (rioPtr != NULL) {
+ if (result == TCL_OK) {
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ *rioPtr = infoPtr->lastIoPtr;
+ } else {
+ *rioPtr = NULL;
+ }
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateObject()
+ *
+ * Creates a new object instance belonging to the given class.
+ * Supports complex object names like "namesp::namesp::name" by
+ * following the namespace path and creating the object in the
+ * desired namespace.
+ *
+ * Automatically creates and initializes data members, including the
+ * built-in protected "this" variable containing the object name.
+ * Installs an access command in the current namespace, and invokes
+ * the constructor to initialize the object.
+ *
+ * If any errors are encountered, the object is destroyed and this
+ * procedure returns TCL_ERROR (along with an error message in the
+ * interpreter). Otherwise, it returns TCL_OK
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCreateObject(
+ Tcl_Interp *interp, /* interpreter mananging new object */
+ const char* name, /* name of new object */
+ ItclClass *iclsPtr, /* class for new object */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ int result = TCL_OK;
+
+ Tcl_DString buffer;
+ Tcl_CmdInfo cmdInfo;
+ Tcl_Command cmdPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj **newObjv;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *saveNsNamePtr = NULL;
+ ItclObjectInfo *infoPtr;
+ ItclObject *saveCurrIoPtr;
+ ItclObject *ioPtr;
+ Itcl_InterpState istate;
+ const char *nsName;
+ const char *objName;
+ char unique[256]; /* buffer used for unique part of object names */
+ int newEntry;
+ ItclResolveInfo *resolveInfoPtr;
+ /* objv[1]: class name */
+ /* objv[2]: class full name */
+ /* objv[3]: object name */
+
+ infoPtr = NULL;
+ ItclShowArgs(1, "ItclCreateObject", objc, objv);
+ saveCurrIoPtr = NULL;
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ /* check, if the object already exists and if yes delete it silently */
+ cmdPtr = Tcl_FindCommand(interp, name, NULL, 0);
+ if (cmdPtr != NULL) {
+ Tcl_GetCommandInfoFromToken(cmdPtr, &cmdInfo);
+ if (cmdInfo.deleteProc == ItclDestroyObject) {
+ Itcl_RenameCommand(interp, name, "");
+ }
+ }
+ }
+ /* just init for the case of none ItclWidget objects */
+ newObjv = (Tcl_Obj **)objv;
+ infoPtr = iclsPtr->infoPtr;
+
+ if (infoPtr != NULL) {
+ infoPtr->lastIoPtr = NULL;
+ }
+ /*
+ * Create a new object and initialize it.
+ */
+ ioPtr = (ItclObject*)ckalloc(sizeof(ItclObject));
+ memset(ioPtr, 0, sizeof(ItclObject));
+ ioPtr->iclsPtr = iclsPtr;
+ ioPtr->interp = interp;
+ ioPtr->infoPtr = infoPtr;
+ ItclPreserveClass(iclsPtr);
+
+ ioPtr->constructed = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitObjHashTable(ioPtr->constructed);
+
+ ioPtr->oPtr = Tcl_NewObjectInstance(interp, iclsPtr->clsPtr, NULL,
+ /* nsName */ NULL, /* objc */ -1, /* objv */ NULL, /* skip */ 0);
+ if (ioPtr->oPtr == NULL) {
+ ckfree(ioPtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Add a command to the current namespace with the object name.
+ * This is done before invoking the constructors so that the
+ * command can be used during construction to query info.
+ */
+ ItclPreserveObject(ioPtr);
+
+ ioPtr->namePtr = Tcl_NewStringObj(name, -1);
+ Tcl_IncrRefCount(ioPtr->namePtr);
+ nsName = Tcl_GetCurrentNamespace(interp)->fullName;
+ ioPtr->origNamePtr = Tcl_NewStringObj("", -1);
+ if ((name[0] != ':') && (name[1] != ':')) {
+ Tcl_AppendToObj(ioPtr->origNamePtr, nsName, -1);
+ if (strcmp(nsName, "::") != 0) {
+ Tcl_AppendToObj(ioPtr->origNamePtr, "::", -1);
+ }
+ }
+ Tcl_AppendToObj(ioPtr->origNamePtr, name, -1);
+ Tcl_IncrRefCount(ioPtr->origNamePtr);
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr))->fullName, -1);
+ ioPtr->varNsNamePtr = Tcl_NewStringObj(Tcl_DStringValue(&buffer), -1);
+ Tcl_IncrRefCount(ioPtr->varNsNamePtr);
+ Tcl_DStringFree(&buffer);
+
+ Tcl_InitHashTable(&ioPtr->objectVariables, TCL_ONE_WORD_KEYS);
+ Tcl_InitObjHashTable(&ioPtr->objectOptions);
+ Tcl_InitObjHashTable(&ioPtr->objectComponents);
+ Tcl_InitObjHashTable(&ioPtr->objectDelegatedOptions);
+ Tcl_InitObjHashTable(&ioPtr->objectDelegatedFunctions);
+ Tcl_InitObjHashTable(&ioPtr->objectMethodVariables);
+ Tcl_InitHashTable(&ioPtr->contextCache, TCL_ONE_WORD_KEYS);
+
+ ItclPreserveObject(ioPtr);
+
+ /*
+ * Install the class namespace and object context so that
+ * the object's data members can be initialized via simple
+ * "set" commands.
+ */
+
+ /* first create the object's class variables namespaces
+ * and set all the init values for variables
+ */
+
+ if (ItclInitObjectVariables(interp, ioPtr, iclsPtr) != TCL_OK) {
+ ioPtr->hadConstructorError = 11;
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ if (ItclInitObjectCommands(interp, ioPtr, iclsPtr, name) != TCL_OK) {
+ Tcl_AppendResult(interp, "error in ItclInitObjectCommands", NULL);
+ ioPtr->hadConstructorError = 12;
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ if (iclsPtr->flags & (ITCL_ECLASS|ITCL_NWIDGET|ITCL_WIDGET|
+ ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ if (iclsPtr->flags & (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|
+ ITCL_WIDGETADAPTOR)) {
+ ItclInitExtendedClassOptions(interp, ioPtr);
+ if (ItclInitObjectOptions(interp, ioPtr, iclsPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "error in ItclInitObjectOptions",
+ NULL);
+ ioPtr->hadConstructorError = 13;
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ }
+ if (ItclInitObjectMethodVariables(interp, ioPtr, iclsPtr, name)
+ != TCL_OK) {
+ Tcl_AppendResult(interp,
+ "error in ItclInitObjectMethodVariables", NULL);
+ ioPtr->hadConstructorError = 14;
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+
+ if (iclsPtr->flags & (ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ saveNsNamePtr = Tcl_GetVar2Ex(interp,
+ "::itcl::internal::varNsName", name, 0);
+ if (saveNsNamePtr) {
+ Tcl_IncrRefCount(saveNsNamePtr);
+ }
+ Tcl_SetVar2Ex(interp, "::itcl::internal::varNsName", name,
+ ioPtr->varNsNamePtr, 0);
+ }
+
+ }
+
+ saveCurrIoPtr = infoPtr->currIoPtr;
+ infoPtr->currIoPtr = ioPtr;
+ if (iclsPtr->flags & ITCL_WIDGET) {
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *) * (objc + 5));
+ newObjv[0] = Tcl_NewStringObj(
+ "::itcl::internal::commands::hullandoptionsinstall", -1);
+ newObjv[1] = ioPtr->namePtr;
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = ioPtr->iclsPtr->namePtr;
+ Tcl_IncrRefCount(newObjv[2]);
+ if (ioPtr->iclsPtr->widgetClassPtr != NULL) {
+ newObjv[3] = ioPtr->iclsPtr->widgetClassPtr;
+ } else {
+ newObjv[3] = Tcl_NewStringObj("", -1);
+ }
+ Tcl_IncrRefCount(newObjv[3]);
+ if (ioPtr->iclsPtr->hullTypePtr != NULL) {
+ newObjv[4] = ioPtr->iclsPtr->hullTypePtr;
+ } else {
+ newObjv[4] = Tcl_NewStringObj("", -1);
+ }
+ Tcl_IncrRefCount(newObjv[4]);
+ memcpy(newObjv + 5, objv, (objc * sizeof(Tcl_Obj *)));
+ result = Tcl_EvalObjv(interp, objc+5, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[3]);
+ Tcl_DecrRefCount(newObjv[4]);
+ ckfree((char *)newObjv);
+ if (result != TCL_OK) {
+ ioPtr->hadConstructorError = 15;
+ goto errorReturn;
+ }
+ }
+ objName = name;
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ /* use a temporary name here as widgetadaptors often hijack the
+ * name for use in installhull. Rename it after the constructor has
+ * been run to the wanted name
+ */
+ /*
+ * Add a unique part, and keep
+ * incrementing a counter until a valid name is found.
+ */
+ do {
+ Tcl_CmdInfo dummy;
+
+ sprintf(unique,"%.200s_%d", name, iclsPtr->unique++);
+ unique[0] = tolower(UCHAR(unique[0]));
+
+ Tcl_DStringSetLength(&buffer, 0);
+ Tcl_DStringAppend(&buffer, unique, -1);
+ objName = Tcl_DStringValue(&buffer);
+
+ /*
+ * [Fix 227811] Check for any command with the
+ * given name, not only objects.
+ */
+
+ if (Tcl_GetCommandInfo (interp, objName, &dummy) == 0) {
+ break; /* if an error is found, bail out! */
+ }
+ } while (1);
+ ioPtr->createNamePtr = Tcl_NewStringObj(objName, -1);
+ }
+
+ {
+ Tcl_Obj *tmp = Tcl_NewObj();
+
+ Tcl_GetCommandFullName(interp, Tcl_GetObjectCommand(ioPtr->oPtr), tmp);
+ Itcl_RenameCommand(interp, Tcl_GetString(tmp), objName);
+ Tcl_TraceCommand(interp, objName,
+ TCL_TRACE_RENAME|TCL_TRACE_DELETE, ObjectRenamedTrace, ioPtr);
+ Tcl_DecrRefCount(tmp);
+ }
+ Tcl_ObjectSetMethodNameMapper(ioPtr->oPtr, ItclMapMethodNameProc);
+
+ ioPtr->accessCmd = Tcl_GetObjectCommand(ioPtr->oPtr);
+ Tcl_GetCommandInfoFromToken(ioPtr->accessCmd, &cmdInfo);
+ cmdInfo.deleteProc = (void *)ItclDestroyObject;
+ cmdInfo.deleteData = ioPtr;
+ Tcl_SetCommandInfoFromToken(ioPtr->accessCmd, &cmdInfo);
+ ioPtr->resolvePtr = (Tcl_Resolve *)ckalloc(sizeof(Tcl_Resolve));
+ ioPtr->resolvePtr->cmdProcPtr = Itcl_CmdAliasProc;
+ ioPtr->resolvePtr->varProcPtr = Itcl_VarAliasProc;
+ resolveInfoPtr = (ItclResolveInfo *)ckalloc(sizeof(ItclResolveInfo));
+ memset (resolveInfoPtr, 0, sizeof(ItclResolveInfo));
+ resolveInfoPtr->flags = ITCL_RESOLVE_OBJECT;
+ resolveInfoPtr->ioPtr = ioPtr;
+ ioPtr->resolvePtr->clientData = resolveInfoPtr;
+
+ Tcl_ObjectSetMetadata(ioPtr->oPtr, iclsPtr->infoPtr->object_meta_type,
+ ioPtr);
+
+ /* make the object known, if it is used in the constructor already! */
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->infoPtr->objectCmds,
+ (char*)ioPtr->accessCmd, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ioPtr);
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->infoPtr->objects,
+ (char*)ioPtr, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ioPtr);
+
+ /* Use the TclOO object namespaces as a unique key in case the
+ * object is renamed. Used by mytypemethod, etc. */
+
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->infoPtr->instances,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr))->fullName, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ioPtr);
+
+ /*
+ * Now construct the object. Look for a constructor in the
+ * most-specific class, and if there is one, invoke it.
+ * This will cause a chain reaction, making sure that all
+ * base classes constructors are invoked as well, in order
+ * from least- to most-specific. Any constructors that are
+ * not called out explicitly in "initCode" code fragments are
+ * invoked implicitly without arguments.
+ */
+ ItclShowArgs(1, "OBJECTCONSTRUCTOR", objc, objv);
+ ioPtr->hadConstructorError = 0;
+ result = Itcl_InvokeMethodIfExists(interp, "constructor",
+ iclsPtr, ioPtr, objc, objv);
+ if (ioPtr->hadConstructorError) {
+ result = TCL_ERROR;
+ }
+ ioPtr->hadConstructorError = -1;
+ if (result != TCL_OK) {
+ istate = Itcl_SaveInterpState(interp, result);
+ ItclDeleteObjectVariablesNamespace(interp, ioPtr);
+ if (ioPtr->accessCmd != (Tcl_Command) NULL) {
+ Tcl_DeleteCommandFromToken(interp, ioPtr->accessCmd);
+ ioPtr->accessCmd = NULL;
+ }
+ result = Itcl_RestoreInterpState(interp, istate);
+ infoPtr->currIoPtr = saveCurrIoPtr;
+ /* need this for 2 ReleaseData at errorReturn!! */
+ ItclPreserveObject(ioPtr);
+ goto errorReturn;
+ } else {
+ /* a constructor cannot return a result as the object name
+ * is returned as result */
+ Tcl_ResetResult(interp);
+ }
+
+ /*
+ * If there is no constructor, construct the base classes
+ * in case they have constructors. This will cause the
+ * same chain reaction.
+ */
+ objPtr = Tcl_NewStringObj("constructor", -1);
+ if (Tcl_FindHashEntry(&iclsPtr->functions, (char *)objPtr) == NULL) {
+ result = Itcl_ConstructBase(interp, ioPtr, iclsPtr);
+ }
+ Tcl_DecrRefCount(objPtr);
+
+ if (iclsPtr->flags & ITCL_ECLASS) {
+ ItclInitExtendedClassOptions(interp, ioPtr);
+ if (ItclInitObjectOptions(interp, ioPtr, iclsPtr) != TCL_OK) {
+ Tcl_AppendResult(interp, "error in ItclInitObjectOptions",
+ NULL);
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ }
+ /*
+ * If construction failed, then delete the object access
+ * command. This will destruct the object and delete the
+ * object data. Be careful to save and restore the interpreter
+ * state, since the destructors may generate errors of their own.
+ */
+ if (result != TCL_OK) {
+ istate = Itcl_SaveInterpState(interp, result);
+
+ /* Bug 227824.
+ * The constructor may destroy the object, possibly indirectly
+ * through the destruction of the main widget in the iTk
+ * megawidget it tried to construct. If this happens we must
+ * not try to destroy the access command a second time.
+ */
+ if (ioPtr->accessCmd != (Tcl_Command) NULL) {
+ Tcl_DeleteCommandFromToken(interp, ioPtr->accessCmd);
+ ioPtr->accessCmd = NULL;
+ }
+ result = Itcl_RestoreInterpState(interp, istate);
+ /* need this for 2 ReleaseData at errorReturn!! */
+ ItclPreserveObject(ioPtr);
+ goto errorReturn;
+ }
+
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+
+ if (saveNsNamePtr) {
+ Tcl_SetVar2Ex(interp, "::itcl::internal::varNsName", name,
+ saveNsNamePtr, 0);
+ Tcl_DecrRefCount(saveNsNamePtr);
+ saveNsNamePtr = NULL;
+ }
+
+ Itcl_RenameCommand(interp, objName, name);
+ ioPtr->createNamePtr = NULL;
+ Tcl_TraceCommand(interp, Tcl_GetString(ioPtr->namePtr),
+ TCL_TRACE_RENAME|TCL_TRACE_DELETE, ObjectRenamedTrace, ioPtr);
+ }
+ if (iclsPtr->flags & (ITCL_WIDGETADAPTOR)) {
+ /*
+ * set all the init values for options
+ */
+
+ objPtr = Tcl_NewStringObj(
+ ITCL_NAMESPACE"::internal::commands::widgetinitobjectoptions ",
+ -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(ioPtr->varNsNamePtr), -1);
+ Tcl_AppendToObj(objPtr, " ", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(ioPtr->namePtr), -1);
+ Tcl_AppendToObj(objPtr, " ", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_IncrRefCount(objPtr);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ infoPtr->currIoPtr = saveCurrIoPtr;
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ }
+ if (iclsPtr->flags & (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ /* FIXME have to check for hierarchy if ITCL_ECLASS !! */
+ result = ItclCheckForInitializedComponents(interp, ioPtr->iclsPtr,
+ ioPtr);
+ if (result != TCL_OK) {
+ istate = Itcl_SaveInterpState(interp, result);
+ if (ioPtr->accessCmd != (Tcl_Command) NULL) {
+ Tcl_DeleteCommandFromToken(interp, ioPtr->accessCmd);
+ ioPtr->accessCmd = NULL;
+ }
+ result = Itcl_RestoreInterpState(interp, istate);
+ /* need this for 2 ReleaseData at errorReturn!! */
+ ItclPreserveObject(ioPtr);
+ goto errorReturn;
+ }
+ }
+
+ /*
+ * Add it to the list of all known objects. The only
+ * tricky thing to watch out for is the case where the
+ * object deleted itself inside its own constructor.
+ * In that case, we don't want to add the object to
+ * the list of valid objects. We can determine that
+ * the object deleted itself by checking to see if
+ * its accessCmd member is NULL.
+ */
+ if (result == TCL_OK && (ioPtr->accessCmd != NULL)) {
+
+ if (!(ioPtr->iclsPtr->flags & ITCL_CLASS)) {
+ result = DelegationInstall(interp, ioPtr, iclsPtr);
+ if (result != TCL_OK) {
+ goto errorReturn;
+ }
+ }
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->infoPtr->objectCmds,
+ (char*)ioPtr->accessCmd, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ioPtr);
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->infoPtr->objects,
+ (char*)ioPtr, &newEntry);
+ Tcl_SetHashValue(hPtr, (ClientData)ioPtr);
+
+ /*
+ * This is an inelegant hack, left behind until the need for it
+ * can be eliminated by getting the inheritance tree right.
+ */
+
+ if (iclsPtr->flags
+ & (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ Tcl_NewInstanceMethod(interp, ioPtr->oPtr,
+ Tcl_NewStringObj("unknown", -1), 0,
+ &itclRootMethodType, ItclUnknownGuts);
+ }
+
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ Tcl_Obj *objPtr = Tcl_NewObj();
+ Tcl_GetCommandFullName(interp, ioPtr->accessCmd, objPtr);
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ /* skip over the leading :: */
+ char *objName;
+ char *lastObjName;
+ lastObjName = Tcl_GetString(objPtr);
+ objName = lastObjName;
+ while (1) {
+ objName = strstr(objName, "::");
+ if (objName == NULL) {
+ break;
+ }
+ objName += 2;
+ lastObjName = objName;
+ }
+
+ Tcl_AppendResult(interp, lastObjName, NULL);
+ } else {
+ Tcl_AppendResult(interp, Tcl_GetString(objPtr), NULL);
+ }
+ Tcl_DecrRefCount(objPtr);
+ }
+ } else {
+ if (ioPtr->accessCmd != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->objectCmds,
+ (char*)ioPtr->accessCmd);
+ if (hPtr != NULL) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ }
+ }
+
+ /*
+ * Release the object. If it was destructed above, it will
+ * die at this point.
+ */
+ /*
+ * At this point, the object is fully constructed.
+ * Destroy the "constructed" table in the object data, since
+ * it is no longer needed.
+ */
+ if (infoPtr != NULL) {
+ infoPtr->currIoPtr = saveCurrIoPtr;
+ }
+ infoPtr->lastIoPtr = ioPtr;
+ Tcl_DeleteHashTable(ioPtr->constructed);
+ ckfree((char*)ioPtr->constructed);
+ ioPtr->constructed = NULL;
+ ItclAddObjectsDictInfo(interp, ioPtr);
+ ItclReleaseObject(ioPtr);
+ return result;
+
+errorReturn:
+ /*
+ * At this point, the object is not constructed as there was an error.
+ * Destroy the "constructed" table in the object data, since
+ * it is no longer needed.
+ */
+ if (saveNsNamePtr) {
+ Tcl_SetVar2Ex(interp, "::itcl::internal::varNsName", name,
+ saveNsNamePtr, 0);
+ Tcl_DecrRefCount(saveNsNamePtr);
+ saveNsNamePtr = NULL;
+ }
+ if (infoPtr != NULL) {
+ infoPtr->lastIoPtr = ioPtr;
+ infoPtr->currIoPtr = saveCurrIoPtr;
+ }
+ if (ioPtr->constructed != NULL) {
+ Tcl_DeleteHashTable(ioPtr->constructed);
+ ckfree((char*)ioPtr->constructed);
+ ioPtr->constructed = NULL;
+ }
+ ItclDeleteObjectVariablesNamespace(interp, ioPtr);
+ ItclReleaseObject(ioPtr);
+ ItclReleaseObject(ioPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitObjectCommands()
+ *
+ * Init all instance commands.
+ * This is usually invoked automatically
+ * by Itcl_CreateObject(), when an object is created.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclInitObjectCommands(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr,
+ const char *name)
+{
+#ifdef NEW_PROTO_RESOLVER
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ Tcl_Command cmdPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Namespace *nsPtr;
+ ItclClass *iclsPtr2;
+ ItclClass *lastIclsPtr;
+ ItclHierIter hier;
+ ItclMemberFunc *imPtr;
+ ItclCmdLookup *clookup;
+ ItclCmdLookup *info_clookup;
+
+ info_clookup = NULL;
+ lastIclsPtr = NULL;
+ Tcl_ResetResult(interp);
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ entry = Tcl_FirstHashEntry(&iclsPtr2->functions, &place);
+ while (entry) {
+ imPtr = (ItclMemberFunc *)Tcl_GetHashValue(entry);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds,
+ (char *)imPtr->namePtr);
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ cmdPtr = imPtr->accessCmd;
+ nsPtr = iclsPtr->nsPtr;
+ if ((imPtr->flags & ITCL_COMMON) == 0) {
+ cmdPtr = Itcl_RegisterObjectCommand(interp, ioPtr,
+ Tcl_GetString(imPtr->namePtr), clookup->classCmdInfoPtr,
+ cmdPtr, iclsPtr->nsPtr);
+ } else {
+ cmdPtr = Itcl_RegisterObjectCommand(interp, ioPtr,
+ Tcl_GetString(imPtr->namePtr), clookup->classCmdInfoPtr,
+ cmdPtr, iclsPtr->nsPtr);
+ }
+ entry = Tcl_NextHashEntry(&place);
+ }
+ lastIclsPtr = iclsPtr2;
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+
+ /* add some builtin functions to every class!! */
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ objPtr = Tcl_NewStringObj("info", -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->resolveCmds, objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ cmdPtr = Itcl_RegisterObjectCommand(interp, ioPtr, "info",
+ clookup->classCmdInfoPtr, cmdPtr, iclsPtr->nsPtr);
+ }
+ objPtr = Tcl_NewStringObj("isa", -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->resolveCmds, objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ cmdPtr = Itcl_RegisterObjectCommand(interp, ioPtr, "isa",
+ clookup->classCmdInfoPtr, cmdPtr, iclsPtr->nsPtr);
+ }
+ objPtr = Tcl_NewStringObj("setget", -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->resolveCmds, objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr != NULL) {
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ cmdPtr = Itcl_RegisterObjectCommand(interp, ioPtr, "setget",
+ clookup->classCmdInfoPtr, cmdPtr, iclsPtr->nsPtr);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+#endif
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitObjectVariables()
+ *
+ * Init all instance variables and create the necessary variable namespaces
+ * for the given object instance. This is usually invoked automatically
+ * by Itcl_CreateObject(), when an object is created.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclInitObjectVariables(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr)
+{
+ Tcl_DString buffer;
+ Tcl_DString buffer2;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashSearch place;
+ Tcl_Namespace *varNsPtr;
+ Tcl_Namespace *varNsPtr2;
+ Tcl_CallFrame frame;
+ Tcl_Var varPtr;
+ ItclClass *iclsPtr2;
+ ItclHierIter hier;
+ ItclVariable *ivPtr;
+ ItclComponent *icPtr;
+#ifdef NEW_PROTO_RESOLVER
+ ItclVarLookup *vlookup;
+#endif
+ const char *varName;
+ const char *inheritComponentName;
+ int itclOptionsIsSet;
+ int isNew;
+
+ ivPtr = NULL;
+ /*
+ * create all the variables for each class in the
+ * ::itcl::variables::<object namespace>::<class> namespace as an
+ * undefined variable using the Tcl "variable xx" command
+ */
+ itclOptionsIsSet = 0;
+ inheritComponentName = NULL;
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ Tcl_ResetResult(interp);
+ while (iclsPtr2 != NULL) {
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr))->fullName, -1);
+ Tcl_DStringAppend(&buffer, iclsPtr2->nsPtr->fullName, -1);
+ varNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ if (varNsPtr == NULL) {
+ varNsPtr = Tcl_CreateNamespace(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ }
+ /* now initialize the variables which have an init value */
+ if (Itcl_PushCallFrame(interp, &frame, varNsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ goto errorCleanup2;
+ }
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->variables, &place);
+ while (hPtr) {
+ ivPtr = (ItclVariable*)Tcl_GetHashValue(hPtr);
+ varName = Tcl_GetString(ivPtr->namePtr);
+ if ((ivPtr->flags & ITCL_OPTIONS_VAR) && !itclOptionsIsSet) {
+ /* this is the special code for the "itcl_options" variable */
+ itclOptionsIsSet = 1;
+ Tcl_DStringInit(&buffer2);
+ Tcl_DStringAppend(&buffer2, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr))->fullName, -1);
+ varNsPtr2 = Tcl_FindNamespace(interp,
+ Tcl_DStringValue(&buffer2), NULL, 0);
+ if (varNsPtr2 == NULL) {
+ varNsPtr2 = Tcl_CreateNamespace(interp,
+ Tcl_DStringValue(&buffer2), NULL, 0);
+ }
+ Tcl_DStringFree(&buffer2);
+ Itcl_PopCallFrame(interp);
+ /* now initialize the variables which have an init value */
+ if (Itcl_PushCallFrame(interp, &frame, varNsPtr2,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ goto errorCleanup2;
+ }
+ Tcl_TraceVar2(interp, "itcl_options",
+ NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES,
+ ItclTraceOptionVar, (ClientData)ioPtr);
+ Itcl_PopCallFrame(interp);
+ if (Itcl_PushCallFrame(interp, &frame, varNsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ goto errorCleanup2;
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ continue;
+ }
+ if (ivPtr->flags & ITCL_COMPONENT_VAR) {
+ hPtr2 = Tcl_FindHashEntry(&ivPtr->iclsPtr->components,
+ (char *)ivPtr->namePtr);
+ if (hPtr2 == NULL) {
+ Tcl_AppendResult(interp, "cannot find component \"",
+ Tcl_GetString(ivPtr->namePtr), "\" in class \"",
+ Tcl_GetString(ivPtr->iclsPtr->namePtr), NULL);
+ goto errorCleanup;
+ }
+ icPtr = Tcl_GetHashValue(hPtr2);
+ if (icPtr->flags & ITCL_COMPONENT_INHERIT) {
+ if (inheritComponentName != NULL) {
+ Tcl_AppendResult(interp, "object \"",
+ Tcl_GetString(ioPtr->namePtr),
+ "\" can only have one component with inherit.",
+ " Had already component \"",
+ inheritComponentName,
+ "\" now component \"",
+ Tcl_GetString(icPtr->namePtr), "\"", NULL);
+ goto errorCleanup;
+
+ } else {
+ inheritComponentName = Tcl_GetString(icPtr->namePtr);
+ }
+ }
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectComponents,
+ (char *)ivPtr->namePtr, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr2, icPtr);
+ }
+ /* this is a component variable */
+ /* FIXME initialize it to the empty string */
+ /* the initialization is arguable, should it be done? */
+ if (Tcl_SetVar2(interp, varName, NULL,
+ "", TCL_NAMESPACE_ONLY) == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR cannot set",
+ " variable \"", varName, "\"\n", NULL);
+ goto errorCleanup;
+ }
+ }
+ hPtr2 = Tcl_FindHashEntry(&ivPtr->iclsPtr->resolveVars, varName);
+ if (hPtr2 == NULL) {
+ hPtr = Tcl_NextHashEntry(&place);
+ continue;
+ }
+#ifdef NEW_PROTO_RESOLVER
+ vlookup = Tcl_GetHashValue(hPtr2);
+#endif
+ if ((ivPtr->flags & ITCL_COMMON) == 0) {
+#ifndef NEW_PROTO_RESOLVER
+ varPtr = Tcl_NewNamespaceVar(interp, varNsPtr,
+ Tcl_GetString(ivPtr->namePtr));
+#else
+ varPtr = Itcl_RegisterObjectVariable(interp, ioPtr,
+ Tcl_GetString(ivPtr->namePtr), vlookup->classVarInfoPtr,
+ NULL, varNsPtr);
+#endif
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectVariables,
+ (char *)ivPtr, &isNew);
+ if (isNew) {
+ Itcl_PreserveVar(varPtr);
+ Tcl_SetHashValue(hPtr2, varPtr);
+ } else {
+ }
+ if (ivPtr->flags & (ITCL_THIS_VAR|ITCL_TYPE_VAR|
+ ITCL_SELF_VAR|ITCL_SELFNS_VAR|ITCL_WIN_VAR)) {
+ int isDone = 0;
+ if (Tcl_SetVar2(interp, varName, NULL,
+ "", TCL_NAMESPACE_ONLY) == NULL) {
+ Tcl_AppendResult(interp, "INTERNAL ERROR cannot set",
+ " variable \"", varNsPtr->fullName, "::",
+ varName, "\"\n", NULL);
+ goto errorCleanup;
+ }
+ if (ivPtr->flags & ITCL_THIS_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES, ItclTraceThisVar,
+ (ClientData)ioPtr);
+ isDone = 1;
+ }
+ if (!isDone && ivPtr->flags & ITCL_TYPE_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES, ItclTraceTypeVar,
+ (ClientData)ioPtr);
+ isDone = 1;
+ }
+ if (!isDone && ivPtr->flags & ITCL_SELF_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES, ItclTraceSelfVar,
+ (ClientData)ioPtr);
+ isDone = 1;
+ }
+ if (!isDone && ivPtr->flags & ITCL_SELFNS_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES, ItclTraceSelfnsVar,
+ (ClientData)ioPtr);
+ isDone = 1;
+ }
+ if (!isDone && ivPtr->flags & ITCL_WIN_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES, ItclTraceWinVar,
+ (ClientData)ioPtr);
+ isDone = 1;
+ }
+ } else {
+ if (ivPtr->flags & ITCL_HULL_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES,
+ ItclTraceItclHullVar,
+ (ClientData)ioPtr);
+ } else {
+ if (ivPtr->init != NULL) {
+ if (Tcl_SetVar(interp,
+ Tcl_GetString(ivPtr->namePtr),
+ Tcl_GetString(ivPtr->init),
+ TCL_NAMESPACE_ONLY) == NULL) {
+ goto errorCleanup;
+ }
+ }
+ if (ivPtr->arrayInitPtr != NULL) {
+ Tcl_DString buffer3;
+ int i;
+ int argc;
+ const char **argv;
+ const char *val;
+
+ Tcl_DStringInit(&buffer3);
+ Tcl_DStringAppend(&buffer3, varNsPtr->fullName, -1);
+ Tcl_DStringAppend(&buffer3, "::", -1);
+ Tcl_DStringAppend(&buffer3,
+ Tcl_GetString(ivPtr->namePtr), -1);
+ Tcl_SplitList(interp,
+ Tcl_GetString(ivPtr->arrayInitPtr),
+ &argc, &argv);
+ for (i = 0; i < argc; i++) {
+ val = Tcl_SetVar2(interp,
+ Tcl_DStringValue(&buffer3), argv[i],
+ argv[i + 1], TCL_NAMESPACE_ONLY);
+ if (!val) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot initialize variable \"",
+ Tcl_GetString(ivPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ i++;
+ }
+ Tcl_DStringFree(&buffer3);
+ ckfree((char *)argv);
+ }
+ }
+ }
+ } else {
+ if (ivPtr->flags & ITCL_HULL_VAR) {
+ Tcl_TraceVar2(interp, varName, NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES,
+ ItclTraceItclHullVar,
+ (ClientData)ioPtr);
+ }
+ hPtr2 = Tcl_FindHashEntry(&iclsPtr2->classCommons,
+ (char *)ivPtr);
+ if (hPtr2 == NULL) {
+ goto errorCleanup;
+ }
+ varPtr = Tcl_GetHashValue(hPtr2);
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectVariables,
+ (char *)ivPtr, &isNew);
+ if (isNew) {
+ Itcl_PreserveVar(varPtr);
+ Tcl_SetHashValue(hPtr2, varPtr);
+ } else {
+#ifdef NEW_PROTO_RESOLVER
+ varPtr = Itcl_RegisterObjectVariable(interp, ioPtr,
+ Tcl_GetString(ivPtr->namePtr),
+ vlookup->classVarInfoPtr,
+ varPtr, varNsPtr);
+#endif
+ }
+ if (ivPtr->flags & ITCL_COMPONENT_VAR) {
+ if (ivPtr->flags & ITCL_COMMON) {
+ Tcl_Obj *objPtr2;
+ objPtr2 = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE,
+ -1);
+ Tcl_AppendToObj(objPtr2, (Tcl_GetObjectNamespace(
+ ivPtr->iclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr2, "::", -1);
+ Tcl_AppendToObj(objPtr2, varName, -1);
+ /* itcl_hull is traced in itclParse.c */
+ if (strcmp(varName, "itcl_hull") == 0) {
+ Tcl_TraceVar2(interp,
+ Tcl_GetString(objPtr2), NULL,
+ TCL_TRACE_WRITES, ItclTraceItclHullVar,
+ (ClientData)ioPtr);
+ } else {
+ Tcl_TraceVar2(interp,
+ Tcl_GetString(objPtr2), NULL,
+ TCL_TRACE_WRITES, ItclTraceComponentVar,
+ (ClientData)ioPtr);
+ }
+ Tcl_DecrRefCount(objPtr2);
+ } else {
+ Tcl_TraceVar2(interp,
+ varName, NULL,
+ TCL_TRACE_WRITES, ItclTraceComponentVar,
+ (ClientData)ioPtr);
+ }
+ }
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ Itcl_PopCallFrame(interp);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Tcl_DStringFree(&buffer);
+ Itcl_DeleteHierIter(&hier);
+ return TCL_OK;
+errorCleanup:
+ Itcl_PopCallFrame(interp);
+errorCleanup2:
+ varNsPtr = Tcl_FindNamespace(interp, Tcl_GetString(ioPtr->varNsNamePtr),
+ NULL, 0);
+ if (varNsPtr != NULL) {
+ Tcl_DeleteNamespace(varNsPtr);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitObjectOptions()
+ *
+ * Collect all instance options for the given object instance to allow
+ * faster runtime access to the options.
+ * if the same option name is used in more than one class the first one
+ * found is used (for initializing and for the class name)!!
+ * # It is assumed, that an option can only exist in one class??
+ * # So no duplicates allowed??
+ * This is usually invoked automatically by Itcl_CreateObject(),
+ * when an object is created.
+ * ------------------------------------------------------------------------
+ */
+int
+ItclInitObjectOptions(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr)
+{
+ Tcl_DString buffer;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashSearch place;
+ Tcl_CallFrame frame;
+ Tcl_Namespace *varNsPtr;
+ ItclClass *iclsPtr2;
+ ItclHierIter hier;
+ ItclOption *ioptPtr;
+ ItclDelegatedOption *idoPtr;
+ int isNew;
+
+ ioptPtr = NULL;
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ /* now initialize the options which have an init value */
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->options, &place);
+ while (hPtr) {
+ ioptPtr = (ItclOption*)Tcl_GetHashValue(hPtr);
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectOptions,
+ (char *)ioptPtr->namePtr, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr2, ioptPtr);
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(ioPtr->oPtr)->fullName), -1);
+ varNsPtr = Tcl_FindNamespace(interp,
+ Tcl_DStringValue(&buffer), NULL, 0);
+ if (varNsPtr == NULL) {
+ varNsPtr = Tcl_CreateNamespace(interp,
+ Tcl_DStringValue(&buffer), NULL, 0);
+ }
+ Tcl_DStringFree(&buffer);
+ /* now initialize the options which have an init value */
+ if (Itcl_PushCallFrame(interp, &frame, varNsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((ioptPtr != NULL) && (ioptPtr->namePtr != NULL) &&
+ (ioptPtr->defaultValuePtr != NULL)) {
+ if (Tcl_SetVar2(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr),
+ Tcl_GetString(ioptPtr->defaultValuePtr),
+ TCL_NAMESPACE_ONLY) == NULL) {
+ Itcl_PopCallFrame(interp);
+ return TCL_ERROR;
+ }
+ Tcl_TraceVar2(interp, "itcl_options",
+ NULL,
+ TCL_TRACE_READS|TCL_TRACE_WRITES,
+ ItclTraceOptionVar, (ClientData)ioPtr);
+ }
+ Itcl_PopCallFrame(interp);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ /* now check for options which are delegated */
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->delegatedOptions, &place);
+ while (hPtr) {
+ idoPtr = (ItclDelegatedOption*)Tcl_GetHashValue(hPtr);
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectDelegatedOptions,
+ (char *)idoPtr->namePtr, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr2, idoPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitObjectMethodVariables()
+ *
+ * Collect all instance methdovariables for the given object instance to allow
+ * faster runtime access to the methdovariables.
+ * This is usually invoked automatically by Itcl_CreateObject(),
+ * when an object is created.
+ * ------------------------------------------------------------------------
+ */
+int
+ItclInitObjectMethodVariables(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr,
+ const char *name)
+{
+ ItclClass *iclsPtr2;
+ ItclHierIter hier;
+ ItclMethodVariable *imvPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashSearch place;
+ int isNew;
+
+ imvPtr = NULL;
+ Itcl_InitHierIter(&hier, iclsPtr);
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ while (iclsPtr2 != NULL) {
+ hPtr = Tcl_FirstHashEntry(&iclsPtr2->methodVariables, &place);
+ while (hPtr) {
+ imvPtr = (ItclMethodVariable*)Tcl_GetHashValue(hPtr);
+ hPtr2 = Tcl_CreateHashEntry(&ioPtr->objectMethodVariables,
+ (char *)imvPtr->namePtr, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr2, imvPtr);
+ }
+ hPtr = Tcl_NextHashEntry(&place);
+ }
+ iclsPtr2 = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteObject()
+ *
+ * Attempts to delete an object by invoking its destructor.
+ *
+ * If the destructor is successful, then the object is deleted by
+ * removing its access command, and this procedure returns TCL_OK.
+ * Otherwise, the object will remain alive, and this procedure
+ * returns TCL_ERROR (along with an error message in the interpreter).
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_DeleteObject(
+ Tcl_Interp *interp, /* interpreter mananging object */
+ ItclObject *contextIoPtr) /* object to be deleted */
+{
+ Tcl_CmdInfo cmdInfo;
+ Tcl_HashEntry *hPtr;
+
+
+ Tcl_GetCommandInfoFromToken(contextIoPtr->accessCmd, &cmdInfo);
+
+ contextIoPtr->flags |= ITCL_OBJECT_IS_DELETED;
+ ItclPreserveObject(contextIoPtr);
+
+ /*
+ * Invoke the object's destructors.
+ */
+ if (Itcl_DestructObject(interp, contextIoPtr, 0) != TCL_OK) {
+ ItclReleaseObject(contextIoPtr);
+ contextIoPtr->flags |=
+ ITCL_TCLOO_OBJECT_IS_DELETED|ITCL_OBJECT_DESTRUCT_ERROR;
+ return TCL_ERROR;
+ }
+ /*
+ * Remove the object from the global list.
+ */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->infoPtr->objects,
+ (char*)contextIoPtr);
+
+ if (hPtr) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+
+ /*
+ * Change the object's access command so that it can be
+ * safely deleted without attempting to destruct the object
+ * again. Then delete the access command. If this is
+ * the last use of the object data, the object will die here.
+ */
+ if ((contextIoPtr->accessCmd != NULL) && (!(contextIoPtr->flags &
+ (ITCL_OBJECT_IS_RENAMED)))) {
+ if (Tcl_GetCommandInfoFromToken(contextIoPtr->accessCmd, &cmdInfo) == 1) {
+ cmdInfo.deleteProc = ItclReleaseObject;
+ Tcl_SetCommandInfoFromToken(contextIoPtr->accessCmd, &cmdInfo);
+
+ Tcl_DeleteCommandFromToken(interp, contextIoPtr->accessCmd);
+ }
+ }
+ contextIoPtr->oPtr = NULL;
+ contextIoPtr->accessCmd = NULL;
+
+ ItclReleaseObject(contextIoPtr);
+
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteObjectVariablesNamespace()
+ *
+ * ------------------------------------------------------------------------
+ */
+void
+ItclDeleteObjectVariablesNamespace(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr)
+{
+ Tcl_Namespace *varNsPtr;
+
+ if (ioPtr->callRefCount < 1) {
+ /* free the object's variables namespace and variables in it */
+ ioPtr->flags &= ~ITCL_OBJECT_SHOULD_VARNS_DELETE;
+ varNsPtr = Tcl_FindNamespace(interp, Tcl_GetString(ioPtr->varNsNamePtr),
+ NULL, 0);
+ if (varNsPtr != NULL) {
+ Tcl_DeleteNamespace(varNsPtr);
+ }
+ } else {
+ ioPtr->flags |= ITCL_OBJECT_SHOULD_VARNS_DELETE;
+ }
+}
+
+static int
+FinalizeDeleteObject(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ItclObject *contextIoPtr = data[0];
+ if (result == TCL_OK) {
+ ItclDeleteObjectVariablesNamespace(interp, contextIoPtr);
+ Tcl_ResetResult(interp);
+ }
+
+ Tcl_DeleteHashTable(contextIoPtr->destructed);
+ ckfree((char*)contextIoPtr->destructed);
+ contextIoPtr->destructed = NULL;
+ return result;
+}
+
+static int
+CallDestructBase(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Obj *objPtr;
+ ItclObject *contextIoPtr = data[0];
+ int flags = PTR2INT(data[1]);
+
+ if (result != TCL_OK) {
+ return result;
+ }
+ result = ItclDestructBase(interp, contextIoPtr, contextIoPtr->iclsPtr,
+ flags);
+ if (result != TCL_OK) {
+ return result;
+ }
+ /* destroy the hull */
+ if (contextIoPtr->hullWindowNamePtr != NULL) {
+ objPtr = Tcl_NewStringObj("destroy ", -1);
+ Tcl_AppendToObj(objPtr,
+ Tcl_GetString(contextIoPtr->hullWindowNamePtr), -1);
+ result = Tcl_EvalObjEx(interp, objPtr, 0);
+ }
+ return result;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DestructObject()
+ *
+ * Invokes the destructor for a particular object. Usually invoked
+ * by Itcl_DeleteObject() or Itcl_DestroyObject() as a part of the
+ * object destruction process. If the ITCL_IGNORE_ERRS flag is
+ * included, all destructors are invoked even if errors are
+ * encountered, and the result will always be TCL_OK.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error
+ * message in the interpreter) if anything goes wrong.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_DestructObject(
+ Tcl_Interp *interp, /* interpreter mananging new object */
+ ItclObject *contextIoPtr, /* object to be destructed */
+ int flags) /* flags: ITCL_IGNORE_ERRS */
+{
+ int result;
+
+ if ((contextIoPtr->flags & (ITCL_OBJECT_IS_DESTRUCTED))) {
+ return TCL_OK;
+ }
+ contextIoPtr->flags |= ITCL_OBJECT_IS_DESTRUCTED;
+ /*
+ * If there is a "destructed" table, then this object is already
+ * being destructed. Flag an error, unless errors are being
+ * ignored.
+ */
+ if (contextIoPtr->destructed) {
+ if ((flags & ITCL_IGNORE_ERRS) == 0) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "can't delete an object while it is being destructed",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+ }
+
+ result = TCL_OK;
+ if (contextIoPtr->oPtr != NULL) {
+ void *callbackPtr;
+ /*
+ * Create a "destructed" table to keep track of which destructors
+ * have been invoked. This is used in ItclDestructBase to make
+ * sure that all base class destructors have been called,
+ * explicitly or implicitly.
+ */
+ contextIoPtr->destructed = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitObjHashTable(contextIoPtr->destructed);
+
+ /*
+ * Destruct the object starting from the most-specific class.
+ * If all goes well, return the null string as the result.
+ */
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ Tcl_NRAddCallback(interp, FinalizeDeleteObject, contextIoPtr,
+ NULL, NULL, NULL);
+ Tcl_NRAddCallback(interp, CallDestructBase, contextIoPtr,
+ INT2PTR(flags), NULL, NULL);
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDestructBase()
+ *
+ * Invoked by Itcl_DestructObject() to recursively destruct an object
+ * from the specified class level. Finds and invokes the destructor
+ * for the specified class, and then recursively destructs all base
+ * classes. If the ITCL_IGNORE_ERRS flag is included, all destructors
+ * are invoked even if errors are encountered, and the result will
+ * always be TCL_OK.
+ *
+ * Returns TCL_OK on success, or TCL_ERROR (along with an error message
+ * in interp->result) on error.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclDestructBase(
+ Tcl_Interp *interp, /* interpreter */
+ ItclObject *contextIoPtr, /* object being destructed */
+ ItclClass *contextIclsPtr, /* current class being destructed */
+ int flags) /* flags: ITCL_IGNORE_ERRS */
+{
+ int result;
+ Itcl_ListElem *elem;
+ ItclClass *iclsPtr;
+
+ if (contextIoPtr->flags & ITCL_OBJECT_CLASS_DESTRUCTED) {
+ return TCL_OK;
+ }
+ /*
+ * Look for a destructor in this class, and if found,
+ * invoke it.
+ */
+ if (Tcl_FindHashEntry(contextIoPtr->destructed,
+ (char *)contextIclsPtr->namePtr) == NULL) {
+ result = Itcl_InvokeMethodIfExists(interp, "destructor",
+ contextIclsPtr, contextIoPtr, 0, (Tcl_Obj* const*)NULL);
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Scan through the list of base classes recursively and destruct
+ * them. Traverse the list in normal order, so that we destruct
+ * from most- to least-specific.
+ */
+ elem = Itcl_FirstListElem(&contextIclsPtr->bases);
+ while (elem) {
+ iclsPtr = (ItclClass*)Itcl_GetListValue(elem);
+
+ if (ItclDestructBase(interp, contextIoPtr, iclsPtr, flags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+
+ /*
+ * Throw away any result from the destructors and return.
+ */
+ Tcl_ResetResult(interp);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FindObject()
+ *
+ * Searches for an object with the specified name, which have
+ * namespace scope qualifiers like "namesp::namesp::name", or may
+ * be a scoped value such as "namespace inscope ::foo obj".
+ *
+ * If an error is encountered, this procedure returns TCL_ERROR
+ * along with an error message in the interpreter. Otherwise, it
+ * returns TCL_OK. If an object was found, "roPtr" returns a
+ * pointer to the object data. Otherwise, it returns NULL.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_FindObject(
+ Tcl_Interp *interp, /* interpreter containing this object */
+ const char *name, /* name of the object */
+ ItclObject **roPtr) /* returns: object data or NULL */
+{
+ Tcl_Command cmd;
+ Tcl_CmdInfo cmdInfo;
+ Tcl_Namespace *contextNs;
+ char *cmdName;
+
+ contextNs = NULL;
+ cmdName = NULL;
+ /*
+ * The object name may be a scoped value of the form
+ * "namespace inscope <namesp> <command>". If it is,
+ * decode it.
+ */
+ if (Itcl_DecodeScopedCommand(interp, name, &contextNs, &cmdName)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ /*
+ * Look for the object's access command, and see if it has
+ * the appropriate command handler.
+ */
+ cmd = Tcl_FindCommand(interp, cmdName, contextNs, /* flags */ 0);
+ if (cmd != NULL && Itcl_IsObject(cmd)) {
+ if (Tcl_GetCommandInfoFromToken(cmd, &cmdInfo) != 1) {
+ *roPtr = NULL;
+ }
+ *roPtr = cmdInfo.deleteData;
+ } else {
+ *roPtr = NULL;
+ }
+
+ ckfree(cmdName);
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsObject()
+ *
+ * Checks the given Tcl command to see if it represents an itcl object.
+ * Returns non-zero if the command is associated with an object.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsObject(
+ Tcl_Command cmd) /* command being tested */
+{
+ Tcl_CmdInfo cmdInfo;
+
+ if (Tcl_GetCommandInfoFromToken(cmd, &cmdInfo) != 1) {
+ return 0;
+ }
+
+ if ((void *)cmdInfo.deleteProc == (void *)ItclDestroyObject) {
+ return 1;
+ }
+
+ /*
+ * This may be an imported command. Try to get the real
+ * command and see if it represents an object.
+ */
+ cmd = Tcl_GetOriginalCommand(cmd);
+ if (cmd != NULL) {
+ if (Tcl_GetCommandInfoFromToken(cmd, &cmdInfo) != 1) {
+ return 0;
+ }
+
+ if ((void *)cmdInfo.deleteProc == (void *)ItclDestroyObject) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ObjectIsa()
+ *
+ * Checks to see if an object belongs to the given class. An object
+ * "is-a" member of the class if the class appears anywhere in its
+ * inheritance hierarchy. Returns non-zero if the object belongs to
+ * the class, and zero otherwise.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ObjectIsa(
+ ItclObject *contextIoPtr, /* object being tested */
+ ItclClass *iclsPtr) /* class to test for "is-a" relationship */
+{
+ Tcl_HashEntry *entry;
+
+ if (contextIoPtr == NULL) {
+ return 0;
+ }
+ entry = Tcl_FindHashEntry(&contextIoPtr->iclsPtr->heritage, (char*)iclsPtr);
+ return (entry != NULL);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclGetInstanceVar()
+ *
+ * Returns the current value for an object data member. The member
+ * name is interpreted with respect to the given class scope, which
+ * is usually the most-specific class for the object.
+ *
+ * If successful, this procedure returns a pointer to a string value
+ * which remains alive until the variable changes it value. If
+ * anything goes wrong, this returns NULL.
+ * ------------------------------------------------------------------------
+ */
+const char*
+ItclGetInstanceVar(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name1, /* name of desired instance variable */
+ const char *name2, /* array element or NULL */
+ ItclObject *contextIoPtr, /* current object */
+ ItclClass *contextIclsPtr) /* name is interpreted in this scope */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_CallFrame frame;
+ Tcl_CallFrame *framePtr;
+ Tcl_Namespace *nsPtr;
+ Tcl_DString buffer;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ ItclVarLookup *vlookup;
+ const char *val;
+ int isItclOptions;
+ int doAppend;
+
+ /*
+ * Make sure that the current namespace context includes an
+ * object that is being manipulated.
+ */
+ if (contextIoPtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access object-specific info without an object context",
+ (char*)NULL);
+ return NULL;
+ }
+
+ /* get the variable definition to check if that is an ITCL_COMMON */
+ if (contextIclsPtr == NULL) {
+ iclsPtr = contextIoPtr->iclsPtr;
+ } else {
+ iclsPtr = contextIclsPtr;
+ }
+ ivPtr = NULL;
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, (char *)name1);
+ if (hPtr != NULL) {
+ vlookup = Tcl_GetHashValue(hPtr);
+ ivPtr = vlookup->ivPtr;
+ /*
+ * Install the object context and access the data member
+ * like any other variable.
+ */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectVariables, (char *)ivPtr);
+ if (hPtr) {
+ Tcl_Obj *varName = Tcl_NewObj();
+ Tcl_Var varPtr = Tcl_GetHashValue(hPtr);
+ Tcl_GetVariableFullName(interp, varPtr, varName);
+
+ val = Tcl_GetVar2(interp, Tcl_GetString(varName), name2,
+ TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(varName);
+ if (val) {
+ return val;
+ }
+ }
+ }
+
+ isItclOptions = 0;
+ if (strcmp(name1, "itcl_options") == 0) {
+ isItclOptions = 1;
+ }
+ if (strcmp(name1, "itcl_option_components") == 0) {
+ isItclOptions = 1;
+ }
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(contextIoPtr->varNsNamePtr), -1);
+ doAppend = 1;
+ if ((contextIclsPtr == NULL) || (contextIclsPtr->flags &
+ (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ if (isItclOptions) {
+ doAppend = 0;
+ }
+ }
+ if ((ivPtr != NULL) && (ivPtr->flags & ITCL_COMMON)) {
+ if (!isItclOptions) {
+ Tcl_DStringSetLength(&buffer, 0);
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ }
+ doAppend = 1;
+ }
+ }
+ if (doAppend) {
+ Tcl_DStringAppend(&buffer, (Tcl_GetObjectNamespace(
+ contextIclsPtr->oPtr))->fullName, -1);
+ }
+ nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ val = NULL;
+ if (nsPtr != NULL) {
+ framePtr = &frame;
+ Itcl_PushCallFrame(interp, framePtr, nsPtr, /*isProcCallFrame*/0);
+ val = Tcl_GetVar2(interp, (const char *)name1, (char*)name2,
+ TCL_LEAVE_ERR_MSG);
+ Itcl_PopCallFrame(interp);
+ }
+
+ return val;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclGetCommonInstanceVar()
+ *
+ * Returns the current value for an object data member. The member
+ * name is interpreted with respect to the given class scope, which
+ * is usually the most-specific class for the object.
+ *
+ * If successful, this procedure returns a pointer to a string value
+ * which remains alive until the variable changes it value. If
+ * anything goes wrong, this returns NULL.
+ * ------------------------------------------------------------------------
+ */
+const char*
+ItclGetCommonInstanceVar(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name1, /* name of desired instance variable */
+ const char *name2, /* array element or NULL */
+ ItclObject *contextIoPtr, /* current object */
+ ItclClass *contextIclsPtr) /* name is interpreted in this scope */
+{
+ Tcl_CallFrame frame;
+ Tcl_CallFrame *framePtr;
+ Tcl_Namespace *nsPtr;
+ Tcl_DString buffer;
+ const char *val;
+ int doAppend;
+
+ /*
+ * Make sure that the current namespace context includes an
+ * object that is being manipulated.
+ */
+ if (contextIoPtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access object-specific info without an object context",
+ (char*)NULL);
+ return NULL;
+ }
+
+ /*
+ * Install the object context and access the data member
+ * like any other variable.
+ */
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ doAppend = 1;
+ if ((contextIclsPtr == NULL) || (contextIclsPtr->flags &
+ (ITCL_ECLASS|ITCL_TYPE|ITCL_WIDGETADAPTOR))) {
+ if (strcmp(name1, "itcl_options") == 0) {
+ doAppend = 0;
+ }
+ if (strcmp(name1, "itcl_option_components") == 0) {
+ doAppend = 0;
+ }
+ }
+ if (doAppend) {
+ Tcl_DStringAppend(&buffer, (Tcl_GetObjectNamespace(
+ contextIclsPtr->oPtr))->fullName, -1);
+ }
+ nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ val = NULL;
+ if (nsPtr != NULL) {
+ framePtr = &frame;
+ Itcl_PushCallFrame(interp, framePtr, nsPtr, /*isProcCallFrame*/0);
+ val = Tcl_GetVar2(interp, (const char *)name1, (char*)name2,
+ TCL_LEAVE_ERR_MSG);
+ Itcl_PopCallFrame(interp);
+ }
+
+ return val;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetInstanceVar()
+ *
+ * Returns the current value for an object data member. The member
+ * name is interpreted with respect to the given class scope, which
+ * is usually the most-specific class for the object.
+ *
+ * If successful, this procedure returns a pointer to a string value
+ * which remains alive until the variable changes it value. If
+ * anything goes wrong, this returns NULL.
+ * ------------------------------------------------------------------------
+ */
+const char*
+Itcl_GetInstanceVar(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name, /* name of desired instance variable */
+ ItclObject *contextIoPtr, /* current object */
+ ItclClass *contextIclsPtr) /* name is interpreted in this scope */
+{
+ return ItclGetInstanceVar(interp, name, NULL, contextIoPtr,
+ contextIclsPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclSetInstanceVar()
+ *
+ * Sets the current value for an object data member. The member
+ * name is interpreted with respect to the given class scope, which
+ * is usually the most-specific class for the object.
+ *
+ * If successful, this procedure returns a pointer to a string value
+ * which remains alive until the variable changes it value. If
+ * anything goes wrong, this returns NULL.
+ * ------------------------------------------------------------------------
+ */
+const char*
+ItclSetInstanceVar(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name1, /* name of desired instance variable */
+ const char *name2, /* array member or NULL */
+ const char *value, /* the value to set */
+ ItclObject *contextIoPtr, /* current object */
+ ItclClass *contextIclsPtr) /* name is interpreted in this scope */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_CallFrame frame;
+ Tcl_CallFrame *framePtr;
+ Tcl_Namespace *nsPtr;
+ Tcl_DString buffer;
+ ItclVariable *ivPtr;
+ ItclVarLookup *vlookup;
+ ItclClass *iclsPtr;
+ const char *val;
+ int isItclOptions;
+ int doAppend;
+
+ ivPtr = NULL;
+ /*
+ * Make sure that the current namespace context includes an
+ * object that is being manipulated.
+ */
+ if (contextIoPtr == NULL) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot access object-specific info without an object context",
+ (char*)NULL);
+ return NULL;
+ }
+ /* get the variable definition to check if that is an ITCL_COMMON */
+ if (contextIclsPtr == NULL) {
+ iclsPtr = contextIoPtr->iclsPtr;
+ } else {
+ iclsPtr = contextIclsPtr;
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, (char *)name1);
+ if (hPtr != NULL) {
+ vlookup = Tcl_GetHashValue(hPtr);
+ ivPtr = vlookup->ivPtr;
+ } else {
+ return NULL;
+ }
+ /*
+ * Install the object context and access the data member
+ * like any other variable.
+ */
+
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectVariables, (char *)ivPtr);
+ if (hPtr) {
+ Tcl_Obj *varName = Tcl_NewObj();
+ Tcl_Var varPtr = Tcl_GetHashValue(hPtr);
+ Tcl_GetVariableFullName(interp, varPtr, varName);
+
+ val = Tcl_SetVar2(interp, Tcl_GetString(varName), name2, value,
+ TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(varName);
+ return val;
+ }
+
+ isItclOptions = 0;
+ if (strcmp(name1, "itcl_options") == 0) {
+ isItclOptions = 1;
+ }
+ if (strcmp(name1, "itcl_option_components") == 0) {
+ isItclOptions = 1;
+ }
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(contextIoPtr->varNsNamePtr), -1);
+ doAppend = 1;
+ if ((contextIclsPtr == NULL) ||
+ (contextIclsPtr->flags & (ITCL_ECLASS|ITCL_TYPE|
+ ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ if (isItclOptions) {
+ doAppend = 0;
+ }
+ }
+ if (ivPtr->flags & ITCL_COMMON) {
+ if (!isItclOptions) {
+ Tcl_DStringSetLength(&buffer, 0);
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ }
+ doAppend = 1;
+ }
+ }
+ if (doAppend) {
+ Tcl_DStringAppend(&buffer, (Tcl_GetObjectNamespace(
+ contextIclsPtr->oPtr))->fullName, -1);
+ }
+ nsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ val = NULL;
+ if (nsPtr != NULL) {
+ framePtr = &frame;
+ Itcl_PushCallFrame(interp, framePtr, nsPtr, /*isProcCallFrame*/0);
+ val = Tcl_SetVar2(interp, (const char *)name1, (char*)name2,
+ value, TCL_LEAVE_ERR_MSG);
+ Itcl_PopCallFrame(interp);
+ }
+
+ return val;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclReportObjectUsage()
+ *
+ * Appends information to the given interp summarizing the usage
+ * for all of the methods available for this object. Useful when
+ * reporting errors in Itcl_HandleInstance().
+ * ------------------------------------------------------------------------
+ */
+void
+ItclReportObjectUsage(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclObject *contextIoPtr, /* current object */
+ Tcl_Namespace *callerNsPtr,
+ Tcl_Namespace *contextNsPtr) /* the context namespace */
+{
+ Tcl_Obj *namePtr;
+ Tcl_HashEntry *entry;
+ Tcl_HashSearch place;
+ Tcl_Obj *resultPtr;
+ ItclClass *iclsPtr = NULL;
+ Itcl_List cmdList;
+ Itcl_ListElem *elem;
+ ItclMemberFunc *imPtr;
+ ItclMemberFunc *cmpFunc;
+ ItclCmdLookup *clookup;
+ ItclObjectInfo * infoPtr = NULL;
+ char *name;
+ int ignore;
+ int cmp;
+
+ if (contextIoPtr == NULL) {
+ resultPtr = Tcl_GetObjResult(interp);
+ infoPtr = (ClientData)Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ if (infoPtr == NULL) {
+ Tcl_AppendResult(interp, " PANIC cannot get Itcl AssocData in ItclReportObjectUsage", NULL);
+ return;
+ }
+ if (contextNsPtr == NULL) {
+ Tcl_AppendResult(interp, " PANIC cannot get contextNsPtr in ItclReportObjectUsage", NULL);
+ return;
+ }
+
+ entry = Tcl_FindHashEntry(&infoPtr->namespaceClasses,
+ (char *)contextNsPtr);
+ if (entry) {
+ iclsPtr = Tcl_GetHashValue(entry);
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, " PANIC cannot get class from contextNsPtr ItclReportObjectUsage", NULL);
+ return;
+ }
+ } else {
+ iclsPtr = (ItclClass*)contextIoPtr->iclsPtr;
+ }
+ ignore = ITCL_CONSTRUCTOR | ITCL_DESTRUCTOR | ITCL_COMMON;
+ /*
+ * Scan through all methods in the virtual table and sort
+ * them in alphabetical order. Report only the methods
+ * that have simple names (no ::'s) and are accessible.
+ */
+ Itcl_InitList(&cmdList);
+ entry = Tcl_FirstHashEntry(&iclsPtr->resolveCmds, &place);
+ while (entry) {
+ namePtr = (Tcl_Obj *)Tcl_GetHashKey(&iclsPtr->resolveCmds, entry);
+ name = Tcl_GetString(namePtr);
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ imPtr = clookup->imPtr;
+
+ if (strstr(name,"::") || (imPtr->flags & ignore) != 0) {
+ imPtr = NULL;
+ } else {
+ if (imPtr->protection != ITCL_PUBLIC) {
+ if (contextNsPtr != NULL) {
+ if (!Itcl_CanAccessFunc(imPtr, contextNsPtr)) {
+ imPtr = NULL;
+ }
+ }
+ }
+ }
+ if ((imPtr != NULL) && (imPtr->codePtr != NULL)) {
+ if (imPtr->codePtr->flags & ITCL_BUILTIN) {
+ char *body;
+ if (imPtr->codePtr != NULL) {
+ body = Tcl_GetString(imPtr->codePtr->bodyPtr);
+ if (*body == '@') {
+ if (strcmp(body, "@itcl-builtin-setget") == 0) {
+ if (!(imPtr->iclsPtr->flags & ITCL_ECLASS)) {
+ imPtr = NULL;
+ }
+ }
+ if (strcmp(body, "@itcl-builtin-installcomponent")
+ == 0) {
+ if (!(imPtr->iclsPtr->flags &
+ (ITCL_WIDGET|ITCL_WIDGETADAPTOR))) {
+ imPtr = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (imPtr) {
+ elem = Itcl_FirstListElem(&cmdList);
+ while (elem) {
+ cmpFunc = (ItclMemberFunc*)Itcl_GetListValue(elem);
+ cmp = strcmp(Tcl_GetString(imPtr->namePtr),
+ Tcl_GetString(cmpFunc->namePtr));
+ if (cmp < 0) {
+ Itcl_InsertListElem(elem, (ClientData)imPtr);
+ imPtr = NULL;
+ break;
+ } else {
+ if (cmp == 0) {
+ imPtr = NULL;
+ break;
+ }
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+ if (imPtr) {
+ Itcl_AppendList(&cmdList, (ClientData)imPtr);
+ }
+ }
+ entry = Tcl_NextHashEntry(&place);
+ }
+
+ /*
+ * Add a series of statements showing usage info.
+ */
+ resultPtr = Tcl_GetObjResult(interp);
+ elem = Itcl_FirstListElem(&cmdList);
+ while (elem) {
+ imPtr = (ItclMemberFunc*)Itcl_GetListValue(elem);
+ Tcl_AppendToObj(resultPtr, "\n ", -1);
+ Itcl_GetMemberFuncUsage(imPtr, contextIoPtr, resultPtr);
+
+ elem = Itcl_NextListElem(elem);
+ }
+ Itcl_DeleteList(&cmdList);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceThisVar()
+ *
+ * Invoked to handle read/write traces on the "this" variable built
+ * into each object.
+ *
+ * On read, this procedure updates the "this" variable to contain the
+ * current object name. This is done dynamically, since an object's
+ * identity can change if its access command is renamed.
+ *
+ * On write, this procedure returns an error string, warning that
+ * the "this" variable cannot be set.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceThisVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_Obj *objPtr;
+ const char *objName;
+
+ /* because of SF bug #187 use a different trace handler for "this", "win", "type"
+ * *self" and "selfns"
+ */
+
+ /*
+ * Handle read traces on "this"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ if (contextIoPtr->accessCmd) {
+ Tcl_GetCommandFullName(contextIoPtr->iclsPtr->interp,
+ contextIoPtr->accessCmd, objPtr);
+ }
+ objName = Tcl_GetString(objPtr);
+ Tcl_SetVar(interp, (const char *)name1, objName, 0);
+
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+
+ /*
+ * Handle write traces on "this"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return "variable \"this\" cannot be modified";
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceWinVar()
+ *
+ * Invoked to handle read/write traces on the "win" variable built
+ * into each object.
+ *
+ * On read, this procedure updates the "win" variable to contain the
+ * current object name. This is done dynamically, since an object's
+ * identity can change if its access command is renamed.
+ *
+ * On write, this procedure returns an error string, warning that
+ * the "win" variable cannot be set.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceWinVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_DString buffer;
+ Tcl_Obj *objPtr;
+ const char *objName;
+ const char *head;
+ const char *tail;
+
+ /*
+ * Handle read traces on "win"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ /* a window path name must not contain namespace parts !! */
+ Itcl_ParseNamespPath(Tcl_GetString(contextIoPtr->origNamePtr), &buffer, &head, &tail);
+ if (tail == NULL) {
+ return " INTERNAL ERROR tail == NULL in ItclTraceThisVar for win";
+ }
+ Tcl_SetStringObj(objPtr, tail, -1);
+ objName = Tcl_GetString(objPtr);
+ Tcl_SetVar(interp, (const char *)name1, objName, 0);
+
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+
+ /*
+ * Handle write traces on "win"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ if (!(contextIoPtr->iclsPtr->flags & ITCL_ECLASS)) {
+ return "variable \"win\" cannot be modified";
+ }
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceTypeVar()
+ *
+ * Invoked to handle read/write traces on the "type" variable built
+ * into each object.
+ *
+ * On read, this procedure updates the "type" variable to contain the
+ * current object name. This is done dynamically, since an object's
+ * identity can change if its access command is renamed.
+ *
+ * On write, this procedure returns an error string, warning that
+ * the "type" variable cannot be set.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceTypeVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_Obj *objPtr;
+ const char *objName;
+
+ /*
+ * Handle read traces on "type"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ Tcl_SetStringObj(objPtr,
+ Tcl_GetCurrentNamespace(contextIoPtr->iclsPtr->interp)->fullName, -1);
+ objName = Tcl_GetString(objPtr);
+ Tcl_SetVar(interp, (const char *)name1, objName, 0);
+
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+
+ /*
+ * Handle write traces on "type"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return "variable \"type\" cannot be modified";
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceSelfVar()
+ *
+ * Invoked to handle read/write traces on the "self" variable built
+ * into each object.
+ *
+ * On read, this procedure updates the "self" variable to contain the
+ * current object name. This is done dynamically, since an object's
+ * identity can change if its access command is renamed.
+ *
+ * On write, this procedure returns an error string, warning that
+ * the "self" variable cannot be set.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceSelfVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_Obj *objPtr;
+ const char *objName;
+
+ /*
+ * Handle read traces on "self"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ if (contextIoPtr->iclsPtr->flags &
+ (ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ const char *objectName;
+
+ objectName = ItclGetInstanceVar(
+ contextIoPtr->iclsPtr->interp,
+ "itcl_hull", NULL, contextIoPtr,
+ contextIoPtr->iclsPtr);
+ if (strlen(objectName) == 0) {
+ objPtr = contextIoPtr->namePtr;
+ Tcl_IncrRefCount(objPtr);
+ } else {
+ Tcl_SetStringObj(objPtr, objectName, -1);
+ }
+ } else {
+ Tcl_GetCommandFullName(contextIoPtr->iclsPtr->interp,
+ contextIoPtr->accessCmd, objPtr);
+ }
+ objName = Tcl_GetString(objPtr);
+ Tcl_SetVar(interp, (const char *)name1, objName, 0);
+
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+
+ /*
+ * Handle write traces on "self"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return "variable \"self\" cannot be modified";
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceSelfnsVar()
+ *
+ * Invoked to handle read/write traces on the "selfns" variable built
+ * into each object.
+ *
+ * On read, this procedure updates the "selfns" variable to contain the
+ * current object name. This is done dynamically, since an object's
+ * identity can change if its access command is renamed.
+ *
+ * On write, this procedure returns an error string, warning that
+ * the "selfns" variable cannot be set.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceSelfnsVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_Obj *objPtr;
+ const char *objName;
+
+ /*
+ * Handle read traces on "selfns"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ objPtr = Tcl_NewStringObj("", -1);
+ Tcl_SetStringObj(objPtr, Tcl_GetString(contextIoPtr->varNsNamePtr), -1);
+ Tcl_AppendToObj(objPtr,
+ Tcl_GetString(contextIoPtr->iclsPtr->fullNamePtr), -1);
+ objName = Tcl_GetString(objPtr);
+ Tcl_SetVar(interp, (const char *)name1, objName, 0);
+
+ Tcl_DecrRefCount(objPtr);
+ return NULL;
+ }
+
+ /*
+ * Handle write traces on "selfns"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return "variable \"selfns\" cannot be modified";
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceOptionVar()
+ *
+ * Invoked to handle read/write traces on "option" variables
+ *
+ * On read, this procedure checks if there is a cgetMethodPtr and calls it
+ * On write, this procedure checks if there is a configureMethodPtr
+ * or validateMethodPtr and calls it
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceOptionVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ ItclObject *ioPtr;
+ ItclOption *ioptPtr;
+
+/* FIXME !!! */
+/* don't know yet if ItclTraceOptionVar is really needed !! */
+/* FIXME should free memory on unset or rename!! */
+ if (cdata != NULL) {
+ ioPtr = (ItclObject*)cdata;
+ if (ioPtr == NULL) {
+ }
+ } else {
+ ioptPtr = (ItclOption*)cdata;
+ if (ioptPtr == NULL) {
+ }
+ /*
+ * Handle read traces "itcl_options"
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ return NULL;
+ }
+
+ /*
+ * Handle write traces "itcl_options"
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceComponentVar()
+ *
+ * Invoked to handle read/write traces on "component" variables
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceComponentVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *namePtr;
+ Tcl_Obj *componentValuePtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *val;
+
+/* FIXME should free memory on unset or rename!! */
+ if (cdata != NULL) {
+ ioPtr = (ItclObject*)cdata;
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->objects, (char *)ioPtr);
+ if (hPtr == NULL) {
+ /* object does no longer exist or is being destructed */
+ return NULL;
+ }
+ objPtr = Tcl_NewStringObj(name1, -1);
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectComponents, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+
+ /*
+ * Handle write traces
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ if (ioPtr->noComponentTrace) {
+ return NULL;
+ }
+ /* need to redo the delegation for this component !! */
+ if (hPtr == NULL) {
+ return " INTERNAL ERROR cannot get component to write to";
+ }
+ icPtr = Tcl_GetHashValue(hPtr);
+ val = ItclGetInstanceVar(interp, name1, NULL, ioPtr,
+ ioPtr->iclsPtr);
+ if ((val == NULL) || (strlen(val) == 0)) {
+ return " INTERNAL ERROR cannot get value for component";
+ }
+ componentValuePtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(componentValuePtr);
+ namePtr = Tcl_NewStringObj(name1, -1);
+ FOREACH_HASH_VALUE(idmPtr, &ioPtr->iclsPtr->delegatedFunctions) {
+ if (idmPtr->icPtr == icPtr) {
+ hPtr2 = Tcl_FindHashEntry(&idmPtr->exceptions,
+ (char *)namePtr);
+ if (hPtr2 == NULL) {
+ DelegateFunction(interp, ioPtr, ioPtr->iclsPtr,
+ componentValuePtr, idmPtr);
+ }
+ }
+ }
+ Tcl_DecrRefCount(componentValuePtr);
+ Tcl_DecrRefCount(namePtr);
+ return NULL;
+ }
+ /*
+ * Handle read traces
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ }
+
+ } else {
+ icPtr = (ItclComponent *)cdata;
+ /*
+ * Handle read traces
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ return NULL;
+ }
+
+ /*
+ * Handle write traces
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return NULL;
+ }
+ }
+ return NULL;
+}
+/*
+ * ------------------------------------------------------------------------
+ * ItclTraceItclHullVar()
+ *
+ * Invoked to handle read/write traces on "itcl_hull" variables
+ *
+ * On write, this procedure returns an error as "itcl_hull" may not be modfied
+ * after the first initialization
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static char*
+ItclTraceItclHullVar(
+ ClientData cdata, /* object instance data */
+ Tcl_Interp *interp, /* interpreter managing this variable */
+ const char *name1, /* variable name */
+ const char *name2, /* unused */
+ int flags) /* flags indicating read/write */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *ioPtr;
+ ItclVariable *ivPtr;
+
+/* FIXME !!! */
+/* FIXME should free memory on unset or rename!! */
+ if (cdata != NULL) {
+ ioPtr = (ItclObject*)cdata;
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->objects, (char *)ioPtr);
+ if (hPtr == NULL) {
+ /* object does no longer exist or is being destructed */
+ return NULL;
+ }
+ objPtr = Tcl_NewStringObj(name1, -1);
+ hPtr = Tcl_FindHashEntry(&ioPtr->iclsPtr->variables, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr == NULL) {
+ return "INTERNAL ERROR cannot find itcl_hull variable in class definition!!";
+ }
+ ivPtr = Tcl_GetHashValue(hPtr);
+ /*
+ * Handle write traces
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ if (ivPtr->initted == 0) {
+ ivPtr->initted = 1;
+ return NULL;
+ } else {
+ return "The itcl_hull component cannot be redefined";
+ }
+ }
+
+ } else {
+ ivPtr = (ItclVariable *)cdata;
+ /*
+ * Handle read traces
+ */
+ if ((flags & TCL_TRACE_READS) != 0) {
+ return NULL;
+ }
+
+ /*
+ * Handle write traces
+ */
+ if ((flags & TCL_TRACE_WRITES) != 0) {
+ return NULL;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDestroyObject()
+ *
+ * Invoked when the object access command is deleted to implicitly
+ * destroy the object. Invokes the object's destructors, ignoring
+ * any errors encountered along the way. Removes the object from
+ * the list of all known objects and releases the access command's
+ * claim to the object data.
+ *
+ * Note that the usual way to delete an object is via Itcl_DeleteObject().
+ * This procedure is provided as a back-up, to handle the case when
+ * an object is deleted by removing its access command.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDestroyObject(
+ ClientData cdata) /* object instance data */
+{
+ ItclObject *contextIoPtr = (ItclObject*)cdata;
+ Tcl_HashEntry *hPtr;
+ Itcl_InterpState istate;
+
+ if (contextIoPtr->flags & ITCL_OBJECT_IS_DESTROYED) {
+ return;
+ }
+ contextIoPtr->flags |= ITCL_OBJECT_IS_DESTROYED;
+
+ if (!(contextIoPtr->flags & ITCL_OBJECT_IS_DESTRUCTED)) {
+ /*
+ * Attempt to destruct the object, but ignore any errors.
+ */
+ istate = Itcl_SaveInterpState(contextIoPtr->interp, 0);
+ Itcl_DestructObject(contextIoPtr->interp, contextIoPtr,
+ ITCL_IGNORE_ERRS);
+ Itcl_RestoreInterpState(contextIoPtr->interp, istate);
+ }
+
+ /*
+ * Now, remove the object from the global object list.
+ * We're careful to do this here, after calling the destructors.
+ * Once the access command is nulled out, the "this" variable
+ * won't work properly.
+ */
+ if (contextIoPtr->accessCmd != NULL) {
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->infoPtr->objects,
+ (char*)contextIoPtr);
+
+ if (hPtr) {
+ Tcl_DeleteHashEntry(hPtr);
+ }
+ contextIoPtr->accessCmd = NULL;
+ }
+ ItclReleaseObject(contextIoPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclFreeObject()
+ *
+ * Deletes all instance variables and frees all memory associated with
+ * the given object instance. This is usually invoked automatically
+ * by ItclReleaseObject(), when an object's data is no longer being used.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclFreeObject(
+ char * cdata) /* object instance data */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_HashSearch place;
+ ItclCallContext *callContextPtr;
+ ItclObject *ioPtr;
+ Tcl_Var var;
+
+ ioPtr = (ItclObject*)cdata;
+
+ /*
+ * Install the class namespace and object context so that
+ * the object's data members can be destroyed via simple
+ * "unset" commands. This makes sure that traces work properly
+ * and all memory gets cleaned up.
+ *
+ * NOTE: Be careful to save and restore the interpreter state.
+ * Data can get freed in the middle of any operation, and
+ * we can't affort to clobber the interpreter with any errors
+ * from below.
+ */
+
+ ItclReleaseClass(ioPtr->iclsPtr);
+ if (ioPtr->constructed) {
+ Tcl_DeleteHashTable(ioPtr->constructed);
+ ckfree((char*)ioPtr->constructed);
+ }
+ if (ioPtr->destructed) {
+ Tcl_DeleteHashTable(ioPtr->destructed);
+ ckfree((char*)ioPtr->destructed);
+ }
+ ItclDeleteObjectsDictInfo(ioPtr->interp, ioPtr);
+ /*
+ * Delete all context definitions.
+ */
+ while (1) {
+ hPtr = Tcl_FirstHashEntry(&ioPtr->contextCache, &place);
+ if (hPtr == NULL) {
+ break;
+ }
+ callContextPtr = Tcl_GetHashValue(hPtr);
+ Tcl_DeleteHashEntry(hPtr);
+ ckfree((char *)callContextPtr);
+ }
+ FOREACH_HASH_VALUE(var, &ioPtr->objectVariables) {
+ Itcl_ReleaseVar(var);
+ }
+
+ Tcl_DeleteHashTable(&ioPtr->contextCache);
+ Tcl_DeleteHashTable(&ioPtr->objectVariables);
+ Tcl_DeleteHashTable(&ioPtr->objectOptions);
+ Tcl_DeleteHashTable(&ioPtr->objectComponents);
+ Tcl_DeleteHashTable(&ioPtr->objectMethodVariables);
+ Tcl_DeleteHashTable(&ioPtr->objectDelegatedOptions);
+ Tcl_DeleteHashTable(&ioPtr->objectDelegatedFunctions);
+ Tcl_DecrRefCount(ioPtr->namePtr);
+ Tcl_DecrRefCount(ioPtr->origNamePtr);
+ if (ioPtr->createNamePtr != NULL) {
+ Tcl_DecrRefCount(ioPtr->createNamePtr);
+ }
+ if (ioPtr->hullWindowNamePtr != NULL) {
+ Tcl_DecrRefCount(ioPtr->hullWindowNamePtr);
+ }
+ Tcl_DecrRefCount(ioPtr->varNsNamePtr);
+ if (ioPtr->resolvePtr != NULL) {
+ ckfree((char *)ioPtr->resolvePtr->clientData);
+ ckfree((char*)ioPtr->resolvePtr);
+ }
+ ckfree((char*)ioPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclObjectCmd()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static int
+CallPublicObjectCmd(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ Tcl_Object *oPtr = data[0];
+ Tcl_Class clsPtr = data[1];
+ Tcl_Obj *const* objv = data[3];
+ int objc = PTR2INT(data[2]);
+
+ ItclShowArgs(1, "CallPublicObjectCmd", objc, objv);
+ result = Itcl_PublicObjectCmd(oPtr, interp, clsPtr, objc, objv);
+ ItclShowArgs(1, "CallPublicObjectCmd DONE", objc, objv);
+ return result;
+}
+
+int
+ItclObjectCmd(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_Object oPtr,
+ Tcl_Class clsPtr,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Obj *methodNamePtr;
+ Tcl_Obj **newObjv;
+ Tcl_DString buffer;
+ Tcl_Obj *myPtr;
+ ItclMemberFunc *imPtr;
+ ItclClass *iclsPtr;
+ Itcl_ListElem *elem;
+ ItclClass *basePtr;
+ void *callbackPtr;
+ const char *className;
+ const char *tail;
+ const char *cp;
+ int isDirectCall;
+ int incr;
+ int result;
+ int found;
+
+ ItclShowArgs(1, "ItclObjectCmd", objc, objv);
+
+ incr = 0;
+ found = 0;
+ isDirectCall = 0;
+ myPtr = NULL;
+ imPtr = (ItclMemberFunc *)clientData;
+ iclsPtr = imPtr->iclsPtr;
+ if (oPtr == NULL) {
+ ItclClass *icPtr = NULL;
+ ItclObject *ioPtr = NULL;
+
+ isDirectCall = (clsPtr == NULL);
+
+ if ((imPtr->flags & ITCL_COMMON)
+ && (imPtr->codePtr != NULL)
+ && !(imPtr->codePtr->flags & ITCL_BUILTIN)) {
+ result = Itcl_InvokeProcedureMethod(imPtr->tmPtr, interp,
+ objc, objv);
+ return result;
+ }
+
+ if (TCL_OK == Itcl_GetContext(interp, &icPtr, &ioPtr)) {
+ oPtr = ioPtr ? ioPtr->oPtr : icPtr->oPtr;
+ } else {
+ Tcl_Panic("No Context");
+ }
+ }
+ methodNamePtr = NULL;
+ if (objv[0] != NULL) {
+ Itcl_ParseNamespPath(Tcl_GetString(objv[0]), &buffer,
+ &className, &tail);
+ if (className != NULL) {
+ methodNamePtr = Tcl_NewStringObj(tail, -1);
+ /* look for the class in the hierarchy */
+ cp = className;
+ if ((*cp == ':') && (*(cp+1) == ':')) {
+ cp += 2;
+ }
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ if (elem == NULL) {
+ /* check the class itself */
+ if (strcmp((const char *)cp,
+ (const char *)Tcl_GetString(iclsPtr->namePtr)) == 0) {
+ found = 1;
+ clsPtr = iclsPtr->clsPtr;
+ }
+ }
+ while (elem != NULL) {
+ basePtr = (ItclClass*)Itcl_GetListValue(elem);
+ if (strcmp((const char *)cp,
+ (const char *)Tcl_GetString(basePtr->namePtr)) == 0) {
+ clsPtr = basePtr->clsPtr;
+ found = 1;
+ break;
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+ if (!found) {
+ found = 1;
+ clsPtr = iclsPtr->clsPtr;
+ }
+ }
+ Tcl_DStringFree(&buffer);
+ } else {
+ /* Can this happen? */
+ Tcl_Panic("objv[0] is NULL?!");
+ /* Panic above replaces obviously broken line below. Creating
+ * a string value from uninitialized memory cannot possibly be
+ * a correct thing to do.
+
+ methodNamePtr = Tcl_NewStringObj(tail, -1);
+ */
+ }
+ if (isDirectCall) {
+ if (!found) {
+ if (methodNamePtr != NULL) {
+ Tcl_DecrRefCount(methodNamePtr);
+ }
+ methodNamePtr = objv[0];
+ }
+ }
+ callbackPtr = Itcl_GetCurrentCallbackPtr(interp);
+ newObjv = NULL;
+ if (methodNamePtr != NULL) {
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ char *myName;
+ /* special handling for mytypemethod, mymethod, myproc */
+ myName = Tcl_GetString(methodNamePtr);
+ if (strcmp(myName, "mytypemethod") == 0) {
+ result = Itcl_BiMyTypeMethodCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "mymethod") == 0) {
+ result = Itcl_BiMyMethodCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "myproc") == 0) {
+ result = Itcl_BiMyProcCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "mytypevar") == 0) {
+ result = Itcl_BiMyTypeVarCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "myvar") == 0) {
+ result = Itcl_BiMyVarCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "itcl_hull") == 0) {
+ result = Itcl_BiItclHullCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "callinstance") == 0) {
+ result = Itcl_BiCallInstanceCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "getinstancevar") == 0) {
+ result = Itcl_BiGetInstanceVarCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ if (strcmp(myName, "installcomponent") == 0) {
+ result = Itcl_BiInstallComponentCmd(iclsPtr, interp, objc, objv);
+ return result;
+ }
+ }
+ incr = 1;
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+incr));
+ myPtr = Tcl_NewStringObj("my", 2);
+ Tcl_IncrRefCount(myPtr);
+ Tcl_IncrRefCount(methodNamePtr);
+ newObjv[0] = myPtr;
+ newObjv[1] = methodNamePtr;
+ memcpy(newObjv+incr+1, objv+1, (sizeof(Tcl_Obj*)*(objc-1)));
+ ItclShowArgs(1, "run CallPublicObjectCmd1", objc+incr, newObjv);
+ Tcl_NRAddCallback(interp, CallPublicObjectCmd, oPtr, clsPtr,
+ INT2PTR(objc+incr), newObjv);
+
+ } else {
+ ItclShowArgs(1, "run CallPublicObjectCmd2", objc, objv);
+ Tcl_NRAddCallback(interp, CallPublicObjectCmd, oPtr, clsPtr,
+ INT2PTR(objc), (ClientData)objv);
+ }
+
+ result = Itcl_NRRunCallbacks(interp, callbackPtr);
+ if (methodNamePtr != NULL) {
+ ckfree((char *)newObjv);
+ Tcl_DecrRefCount(methodNamePtr);
+ }
+ if (myPtr != NULL) {
+ Tcl_DecrRefCount(myPtr);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * GetClassFromClassName()
+ * ------------------------------------------------------------------------
+ */
+
+ItclClass *
+GetClassFromClassName(
+ Tcl_Interp *interp,
+ const char *className,
+ ItclClass *iclsPtr)
+{
+ Tcl_Obj *objPtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *basePtr;
+ Itcl_ListElem *elem;
+ const char *chkPtr;
+ int chkLgth;
+ int lgth;
+
+ /* look for the class in the hierarchy */
+ /* first check the class itself */
+ if (iclsPtr != NULL) {
+ if (strcmp(className,
+ (const char *)Tcl_GetString(iclsPtr->namePtr)) == 0) {
+ return iclsPtr;
+ }
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (elem != NULL) {
+ basePtr = (ItclClass*)Itcl_GetListValue(elem);
+ basePtr = GetClassFromClassName(interp, className, basePtr);
+ if (basePtr != NULL) {
+ return basePtr;
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+ /* now try to match the classes full name last part with the className */
+ lgth = strlen(className);
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (elem != NULL) {
+ basePtr = (ItclClass*)Itcl_GetListValue(elem);
+ chkPtr = basePtr->nsPtr->fullName;
+ chkLgth = strlen(chkPtr);
+ if (chkLgth >= lgth) {
+ chkPtr = chkPtr + chkLgth - lgth;
+ if (strcmp(chkPtr, className) == 0) {
+ return basePtr;
+ }
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+ infoPtr = iclsPtr->infoPtr;
+ } else {
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ }
+ /* as a last chance try with className in hash table */
+ objPtr = Tcl_NewStringObj(className, -1);
+ Tcl_IncrRefCount(objPtr);
+ hPtr = Tcl_FindHashEntry(&infoPtr->nameClasses, (char *)objPtr);
+ if (hPtr != NULL) {
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ } else {
+ iclsPtr = NULL;
+ }
+ Tcl_DecrRefCount(objPtr);
+ return iclsPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclMapMethodNameProc()
+ * ------------------------------------------------------------------------
+ */
+
+int
+ItclMapMethodNameProc(
+ Tcl_Interp *interp,
+ Tcl_Object oPtr,
+ Tcl_Class *startClsPtr,
+ Tcl_Obj *methodObj)
+{
+ Tcl_Obj *methodName;
+ Tcl_Obj *className;
+ Tcl_DString buffer;
+ Tcl_HashEntry *hPtr;
+ Tcl_Namespace * myNsPtr;
+ ItclObject *ioPtr;
+ ItclClass *iclsPtr;
+ ItclClass *iclsPtr2;
+ ItclObjectInfo *infoPtr;
+ const char *head;
+ const char *tail;
+ const char *sp;
+
+ iclsPtr = NULL;
+ iclsPtr2 = NULL;
+ methodName = NULL;
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ ioPtr = (ItclObject *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->object_meta_type);
+ hPtr = Tcl_FindHashEntry(&infoPtr->objects, (char *)ioPtr);
+ if ((hPtr == NULL) || (ioPtr == NULL)) {
+ /* try to get the class (if a class is creating an object) */
+ iclsPtr = (ItclClass *)Tcl_ObjectGetMetadata(oPtr,
+ infoPtr->class_meta_type);
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)iclsPtr);
+ if (hPtr == NULL) {
+ char str[20];
+ sprintf(str, "%p", iclsPtr);
+ Tcl_AppendResult(interp, "context class has vanished 1", str, NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ hPtr = Tcl_FindHashEntry(&infoPtr->classes, (char *)ioPtr->iclsPtr);
+ if (hPtr == NULL) {
+ char str[20];
+ sprintf(str, "%p", ioPtr->iclsPtr);
+ Tcl_AppendResult(interp, "context class has vanished 2", str, NULL);
+ return TCL_ERROR;
+ }
+ iclsPtr = ioPtr->iclsPtr;
+ }
+ sp = Tcl_GetString(methodObj);
+ Itcl_ParseNamespPath(sp, &buffer, &head, &tail);
+ if (head == NULL) {
+ /* itcl bug #3600923 call private method in class
+ * without namespace
+ */
+ myNsPtr = Tcl_GetCurrentNamespace(iclsPtr->interp);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *) myNsPtr);
+ if (hPtr) {
+ iclsPtr2 = (ItclClass *) Tcl_GetHashValue(hPtr);
+ if (Itcl_IsMethodCallFrame(iclsPtr->interp) > 0) {
+ iclsPtr = iclsPtr2;
+ }
+ }
+ }
+ if (head != NULL) {
+ className = NULL;
+ methodName = Tcl_NewStringObj(tail, -1);
+ Tcl_IncrRefCount(methodName);
+ className = Tcl_NewStringObj(head, -1);
+ Tcl_IncrRefCount(className);
+ if (strlen(head) > 0) {
+ iclsPtr2 = GetClassFromClassName(interp, head, iclsPtr);
+ } else {
+ iclsPtr2 = NULL;
+ }
+ if (iclsPtr2 != NULL) {
+ *startClsPtr = iclsPtr2->clsPtr;
+ Tcl_SetStringObj(methodObj, Tcl_GetString(methodName), -1);
+ }
+ Tcl_DecrRefCount(className);
+ Tcl_DecrRefCount(methodName);
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)methodObj);
+ if (hPtr == NULL) {
+ /* special case: we found the class for the class command,
+ * for a relative or absolute class path name
+ * but we have no method in that class that fits.
+ * Problem of Rene Zaumseil when having the object
+ * for a class in a child namespace of the class
+ * fossil ticket id: 36577626c340ad59615f0a0238d67872c009a8c9
+ */
+ *startClsPtr = NULL;
+ } else {
+ ItclMemberFunc *imPtr;
+ Tcl_Namespace *nsPtr;
+ ItclCmdLookup *clookup;
+
+ nsPtr = Tcl_GetCurrentNamespace(interp);
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ if (!Itcl_CanAccessFunc(imPtr, nsPtr)) {
+ char *token = Tcl_GetString(imPtr->namePtr);
+ if ((*token != 'i') || (strcmp(token, "info") != 0)) {
+ /* needed for test protect-2.5 */
+ ItclMemberFunc *imPtr2 = NULL;
+ Tcl_HashEntry *hPtr;
+ Tcl_ObjectContext context;
+ context = Itcl_GetCallFrameClientData(interp);
+ if (context != NULL) {
+ hPtr = Tcl_FindHashEntry(
+ &imPtr->iclsPtr->infoPtr->procMethods,
+ (char *)Tcl_ObjectContextMethod(context));
+ if (hPtr != NULL) {
+ imPtr2 = Tcl_GetHashValue(hPtr);
+ }
+ if ((imPtr->protection & ITCL_PRIVATE) &&
+ (imPtr2 != NULL) &&
+ (imPtr->iclsPtr->nsPtr != imPtr2->iclsPtr->nsPtr)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid command name \"",
+ token,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ /* END needed for test protect-2.5 */
+ if (ioPtr == NULL) {
+ /* itcl in fossil ticket: 2cd667f270b68ef66d668338e09d144e20405e23 */
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj * objPtr;
+ ItclMemberFunc *imPtr2 = NULL;
+ ItclCmdLookup *clookupPtr;
+
+ objPtr = Tcl_NewStringObj(token, -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ if (hPtr != NULL) {
+ clookupPtr = Tcl_GetHashValue(hPtr);
+ imPtr2 = clookupPtr->imPtr;
+ }
+ if ((imPtr->protection & ITCL_PRIVATE) &&
+ (imPtr2 != NULL) &&
+ (imPtr->iclsPtr->nsPtr == imPtr2->iclsPtr->nsPtr)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "invalid command name \"",
+ token,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ } else {
+ Tcl_AppendResult(interp,
+ "bad option \"", token, "\": should be one of...",
+ (char*)NULL);
+ ItclReportObjectUsage(interp, ioPtr, nsPtr, nsPtr);
+ return TCL_ERROR;
+
+ }
+ }
+ }
+ }
+ Tcl_DStringFree(&buffer);
+ return TCL_OK;
+}
+
+int
+ExpandDelegateAs(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr,
+ ItclDelegatedFunction *idmPtr,
+ const char *funcName,
+ Tcl_Obj *listPtr)
+{
+ Tcl_Obj *componentNamePtr;
+ Tcl_Obj *objPtr;
+ const char **argv;
+ const char *val;
+ int argc;
+ int j;
+
+
+ if (idmPtr->icPtr == NULL) {
+ componentNamePtr = NULL;
+ } else {
+ componentNamePtr = idmPtr->icPtr->namePtr;
+ }
+ if (idmPtr->asPtr != NULL) {
+ Tcl_SplitList(interp, Tcl_GetString(idmPtr->asPtr),
+ &argc, &argv);
+ for(j=0;j<argc;j++) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(argv[j], -1));
+ }
+ ckfree((char *)argv);
+ } else {
+ if (idmPtr->usingPtr != NULL) {
+ char *cp;
+ char *ep;
+ int hadDoublePercent;
+ Tcl_Obj *strPtr;
+
+ strPtr = NULL;
+ hadDoublePercent = 0;
+ cp = Tcl_GetString(idmPtr->usingPtr);
+ ep = cp;
+ strPtr = Tcl_NewStringObj("", -1);
+ while (*ep != '\0') {
+ if (*ep == '%') {
+ if (*(ep+1) == '%') {
+ cp++;
+ cp++;
+ ep++;
+ ep++;
+ hadDoublePercent = 1;
+ Tcl_AppendToObj(strPtr, "%", -1);
+ continue;
+ }
+ switch (*(ep+1)) {
+ case 'c':
+ if (componentNamePtr == NULL) {
+ ep++;
+ continue;
+ }
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr, (Tcl_GetObjectNamespace(
+ iclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr,
+ Tcl_GetString(componentNamePtr), -1);
+ val = Tcl_GetVar2(interp, Tcl_GetString(objPtr),
+ NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+ Tcl_AppendToObj(strPtr,
+ val, -1);
+ break;
+ case 'j':
+ case 'm':
+ case 'M':
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), "*") == 0) {
+ Tcl_AppendToObj(strPtr, funcName, -1);
+ } else {
+ Tcl_AppendToObj(strPtr,
+ Tcl_GetString(idmPtr->namePtr), -1);
+ }
+ break;
+ case 'n':
+ if (iclsPtr->flags & ITCL_TYPE) {
+ ep++;
+ continue;
+ } else {
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ Tcl_AppendToObj(strPtr, iclsPtr->nsPtr->name, -1);
+ }
+ break;
+ case 's':
+ if (iclsPtr->flags & ITCL_TYPE) {
+ ep++;
+ continue;
+ } else {
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ Tcl_AppendToObj(strPtr,
+ Tcl_GetString(ioPtr->namePtr), -1);
+ }
+ break;
+ case 't':
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ Tcl_AppendToObj(strPtr, iclsPtr->nsPtr->fullName, -1);
+ break;
+ case 'w':
+ if (iclsPtr->flags & ITCL_TYPE) {
+ ep++;
+ continue;
+ } else {
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ }
+ break;
+ case ':':
+ /* substitute with contents of variable after ':' */
+ if (iclsPtr->flags & ITCL_ECLASS) {
+ if (ep-cp-1 > 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ ep++;
+ cp = ep + 1;
+ while (*ep && (*ep != ' ')) {
+ ep++;
+ }
+ if (ep-cp > 0) {
+ Tcl_Obj *my_obj;
+ const char *cp2;
+
+ my_obj = Tcl_NewStringObj(cp, ep-cp);
+ if (iclsPtr->infoPtr->currIoPtr != NULL) {
+ cp2 = GetConstructorVar(interp, iclsPtr,
+ Tcl_GetString(my_obj));
+ } else {
+ cp2 = ItclGetInstanceVar(interp,
+ Tcl_GetString(my_obj), NULL, ioPtr,
+ iclsPtr);
+ }
+ if (cp2 != NULL) {
+ Tcl_AppendToObj(strPtr, cp2, -1);
+ }
+ ep -= 2; /* to fit for code after default !! */
+ }
+ break;
+ } else {
+ /* fall through */
+ }
+ default:
+ {
+ char buf[2];
+ buf[1] = '\0';
+ sprintf(buf, "%c", *(ep+1));
+ Tcl_AppendResult(interp,
+ "there is no %%", buf, " substitution",
+ NULL);
+ if (strPtr != NULL) {
+ Tcl_DecrRefCount(strPtr);
+ }
+ return TCL_ERROR;
+ }
+ }
+ Tcl_ListObjAppendElement(interp, listPtr, strPtr);
+ hadDoublePercent = 0;
+ strPtr = Tcl_NewStringObj("", -1);
+ ep +=2;
+ cp = ep;
+ } else {
+ if (*ep == ' ') {
+ if (strlen(Tcl_GetString(strPtr)) > 0) {
+ if (ep-cp == 0) {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ strPtr);
+ strPtr = Tcl_NewStringObj("", -1);
+ }
+ }
+ if (ep-cp > 0) {
+ Tcl_AppendToObj(strPtr, cp, ep-cp);
+ Tcl_ListObjAppendElement(interp, listPtr, strPtr);
+ strPtr = Tcl_NewStringObj("", -1);
+ }
+ while((*ep != '\0') && (*ep == ' ')) {
+ ep++;
+ }
+ cp = ep;
+ } else {
+ ep++;
+ }
+ }
+ }
+ if (hadDoublePercent) {
+ /* FIXME need code here */
+ }
+ if (cp != ep) {
+ if (*ep == '\0') {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp));
+ } else {
+ Tcl_ListObjAppendElement(interp, listPtr,
+ Tcl_NewStringObj(cp, ep-cp-1));
+ }
+ }
+ if (strPtr != NULL) {
+ Tcl_DecrRefCount(strPtr);
+ }
+ } else {
+ Tcl_ListObjAppendElement(interp, listPtr, idmPtr->namePtr);
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * DelegationFunction()
+ * ------------------------------------------------------------------------
+ */
+
+int
+DelegateFunction(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr,
+ Tcl_Obj *componentValuePtr,
+ ItclDelegatedFunction *idmPtr)
+{
+ Tcl_Obj *listPtr;
+ const char *val;
+ int result;
+ Tcl_Method mPtr;
+
+ listPtr = Tcl_NewListObj(0, NULL);
+ if (componentValuePtr != NULL) {
+ if (idmPtr->usingPtr == NULL) {
+ Tcl_ListObjAppendElement(interp, listPtr, componentValuePtr);
+ }
+ }
+ result = ExpandDelegateAs(interp, ioPtr, iclsPtr, idmPtr,
+ Tcl_GetString(idmPtr->namePtr), listPtr);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(listPtr);
+ return result;
+ }
+ val = Tcl_GetString(listPtr);
+ if (val == NULL) {
+ /* FIXME need code here */
+ }
+ if (componentValuePtr != NULL) {
+ mPtr = Itcl_NewForwardClassMethod(interp, iclsPtr->clsPtr, 1,
+ idmPtr->namePtr, listPtr);
+ if (mPtr != NULL) {
+ return TCL_OK;
+ }
+ }
+ if (idmPtr->usingPtr != NULL) {
+ mPtr = Itcl_NewForwardClassMethod(interp, iclsPtr->clsPtr, 1,
+ idmPtr->namePtr, listPtr);
+ if (mPtr != NULL) {
+ return TCL_OK;
+ }
+ }
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * DelegatedOptionsInstall()
+ * ------------------------------------------------------------------------
+ */
+
+int
+DelegatedOptionsInstall(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr)
+{
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashSearch search2;
+ ItclDelegatedOption *idoPtr;
+ ItclOption *ioptPtr;
+ FOREACH_HASH_DECLS;
+ char *optionName;
+
+ FOREACH_HASH_VALUE(idoPtr, &iclsPtr->delegatedOptions) {
+ optionName = Tcl_GetString(idoPtr->namePtr);
+ if (*optionName == '*') {
+ /* allow nested FOREACH */
+ search2 = search;
+ FOREACH_HASH_VALUE(ioptPtr, &iclsPtr->options) {
+ if (Tcl_FindHashEntry(&idoPtr->exceptions,
+ (char *)idoPtr->namePtr) == NULL) {
+ ioptPtr->idoPtr = idoPtr;
+ Itcl_PreserveData(ioptPtr->idoPtr);
+ }
+ }
+ search = search2;
+ } else {
+ hPtr2 = Tcl_FindHashEntry(&iclsPtr->options,
+ (char *)idoPtr->namePtr);
+ if (hPtr2 == NULL) {
+ ioptPtr = NULL;
+ } else {
+ ioptPtr = Tcl_GetHashValue(hPtr2);
+ ioptPtr->idoPtr = idoPtr;
+ }
+ idoPtr->ioptPtr = ioptPtr;
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * GetConstructorVar()
+ * get an object variable when in executing the constructor
+ * ------------------------------------------------------------------------
+ */
+
+static const char *
+GetConstructorVar(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ const char *varName)
+
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ Tcl_DString buffer;
+ ItclVarLookup *vlookup;
+ ItclVariable *ivPtr;
+ const char *val;
+
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, (char *)varName);
+ if (hPtr == NULL) {
+ /* no such variable */
+ return NULL;
+ }
+ vlookup = (ItclVarLookup *)Tcl_GetHashValue(hPtr);
+ if (vlookup == NULL) {
+ return NULL;
+ }
+ ivPtr = vlookup->ivPtr;
+ if (ivPtr == NULL) {
+ return NULL;
+ }
+ if (ivPtr->flags & ITCL_COMMON) {
+ /* look for a common variable */
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr, (Tcl_GetObjectNamespace(
+ iclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr, varName, -1);
+ val = Tcl_GetVar2(interp, Tcl_GetString(objPtr), NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+ } else {
+ /* look for a normal variable */
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(iclsPtr->infoPtr->currIoPtr->varNsNamePtr), -1);
+ Tcl_DStringAppend(&buffer, ivPtr->iclsPtr->nsPtr->fullName, -1);
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, varName, -1);
+ val = Tcl_GetVar2(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ }
+ return val;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * DelegationInstall()
+ * ------------------------------------------------------------------------
+ */
+
+int
+DelegationInstall(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ ItclClass *iclsPtr)
+{
+ Tcl_HashEntry *hPtr2;
+ Tcl_HashSearch search2;
+ Tcl_Obj *componentValuePtr;
+ Tcl_DString buffer;
+ ItclDelegatedFunction *idmPtr;
+ ItclMemberFunc *imPtr;
+ ItclVariable *ivPtr;
+ FOREACH_HASH_DECLS;
+ char *methodName;
+ const char *val;
+ int result;
+ int noDelegate;
+ int delegateAll;
+
+ result = TCL_OK;
+ delegateAll = 0;
+ ioPtr->noComponentTrace = 1;
+ noDelegate = ITCL_CONSTRUCTOR|ITCL_DESTRUCTOR|ITCL_COMPONENT;
+ componentValuePtr = NULL;
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ methodName = Tcl_GetString(idmPtr->namePtr);
+ if (*methodName == '*') {
+ delegateAll = 1;
+ }
+ if (idmPtr->icPtr != NULL) {
+ Tcl_Obj *objPtr;
+ /* we cannot use Itcl_GetInstanceVar here as the object is not
+ * yet completely built. So use the varNsNamePtr
+ */
+ ivPtr = idmPtr->icPtr->ivPtr;
+ if (ivPtr->flags & ITCL_COMMON) {
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+
+ Tcl_AppendToObj(objPtr, (Tcl_GetObjectNamespace(
+ ivPtr->iclsPtr->oPtr))->fullName, -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr,
+ Tcl_GetString(idmPtr->icPtr->namePtr), -1);
+ val = Tcl_GetVar2(interp, Tcl_GetString(objPtr), NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+ } else {
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(ioPtr->varNsNamePtr), -1);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(ivPtr->fullNamePtr), -1);
+ val = Tcl_GetVar2(interp,
+ Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ }
+ componentValuePtr = Tcl_NewStringObj(val, -1);
+ Tcl_IncrRefCount(componentValuePtr);
+ } else {
+ componentValuePtr = NULL;
+ }
+ if (!delegateAll) {
+ result = DelegateFunction(interp, ioPtr, iclsPtr,
+ componentValuePtr, idmPtr);
+ if (result != TCL_OK) {
+ ioPtr->noComponentTrace = 0;
+ return result;
+ }
+ } else {
+ /* save to allow nested FOREACH */
+ search2 = search;
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ methodName = Tcl_GetString(imPtr->namePtr);
+ if (imPtr->flags & noDelegate) {
+ continue;
+ }
+ if (strcmp(methodName, "info") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "isa") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "createhull") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "keepcomponentoption") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "ignorecomponentoption") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "renamecomponentoption") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "setupcomponent") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "itcl_initoptions") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "mytypemethod") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "mymethod") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "myproc") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "mytypevar") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "myvar") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "itcl_hull") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "callinstance") == 0) {
+ continue;
+ }
+ if (strcmp(methodName, "getinstancevar") == 0) {
+ continue;
+ }
+ hPtr2 = Tcl_FindHashEntry(&idmPtr->exceptions,
+ (char *)imPtr->namePtr);
+ if (hPtr2 != NULL) {
+ continue;
+ }
+ result = DelegateFunction(interp, ioPtr, iclsPtr,
+ componentValuePtr, idmPtr);
+ if (result != TCL_OK) {
+ break;
+ }
+ }
+ search = search2;
+ }
+ if (componentValuePtr != NULL) {
+ Tcl_DecrRefCount(componentValuePtr);
+ }
+ }
+ ioPtr->noComponentTrace = 0;
+ result = DelegatedOptionsInstall(interp, iclsPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitExtendedClassOptions()
+ * ------------------------------------------------------------------------
+ */
+
+static int
+ItclInitExtendedClassOptions(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr)
+{
+ ItclClass *iclsPtr;
+ ItclOption *ioptPtr;
+ ItclHierIter hier;
+ FOREACH_HASH_DECLS;
+
+ iclsPtr = ioPtr->iclsPtr;
+ Itcl_InitHierIter(&hier, iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ FOREACH_HASH_VALUE(ioptPtr, &iclsPtr->options) {
+ if (ioptPtr->defaultValuePtr != NULL) {
+ if (ItclGetInstanceVar(interp, "itcl_options",
+ Tcl_GetString(ioptPtr->namePtr), ioPtr, iclsPtr)
+ == NULL) {
+ }
+ }
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ return TCL_OK;
+}
+
+ItclClass *
+ItclNamespace2Class(Tcl_Namespace *nsPtr)
+{
+ ItclObjectInfo * infoPtr;
+ Tcl_HashEntry *hPtr;
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(((Namespace *)nsPtr)->interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&(infoPtr->namespaceClasses), nsPtr);
+ if (hPtr == NULL) {
+ return NULL;
+ }
+ return Tcl_GetHashValue(hPtr);
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclParse.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclParse.c
new file mode 100644
index 0000000..9b34dc6
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclParse.c
@@ -0,0 +1,4309 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * Procedures in this file support the new syntax for [incr Tcl]
+ * class definitions:
+ *
+ * itcl_class <className> {
+ * inherit <base-class>...
+ *
+ * constructor {<arglist>} ?{<init>}? {<body>}
+ * destructor {<body>}
+ *
+ * method <name> {<arglist>} {<body>}
+ * proc <name> {<arglist>} {<body>}
+ * variable <name> ?<init>? ?<config>?
+ * common <name> ?<init>?
+ *
+ * public <thing> ?<args>...?
+ * protected <thing> ?<args>...?
+ * private <thing> ?<args>...?
+ * }
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+static const char initWidgetScript[] =
+"namespace eval ::itcl {\n"
+" proc _find_widget_init {} {\n"
+" global env tcl_library\n"
+" variable library\n"
+" variable patchLevel\n"
+" rename _find_widget_init {}\n"
+" if {[info exists library]} {\n"
+" lappend dirs $library\n"
+" } else {\n"
+" if {[catch {uplevel #0 source -rsrc itcl}] == 0} {\n"
+" return\n"
+" }\n"
+" set dirs {}\n"
+" if {[info exists env(ITCL_LIBRARY)]} {\n"
+" lappend dirs $env(ITCL_LIBRARY)\n"
+" }\n"
+" lappend dirs [file join [file dirname $tcl_library] itcl$patchLevel]\n"
+" set bindir [file dirname [info nameofexecutable]]\n"
+" lappend dirs [file join . library]\n"
+" lappend dirs [file join $bindir .. lib itcl$patchLevel]\n"
+" lappend dirs [file join $bindir .. library]\n"
+" lappend dirs [file join $bindir .. .. library]\n"
+" lappend dirs [file join $bindir .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. .. itcl library]\n"
+" lappend dirs [file join $bindir .. .. itcl-ng itcl library]\n"
+" # On MacOSX, check the directories in the tcl_pkgPath\n"
+" if {[string equal $::tcl_platform(platform) \"unix\"] &&"
+" [string equal $::tcl_platform(os) \"Darwin\"]} {\n"
+" foreach d $::tcl_pkgPath {\n"
+" lappend dirs [file join $d itcl$patchLevel]\n"
+" }\n"
+" }\n"
+" # On *nix, check the directories in the tcl_pkgPath\n"
+" if {[string equal $::tcl_platform(platform) \"unix\"]} {\n"
+" foreach d $::tcl_pkgPath {\n"
+" lappend dirs $d\n"
+" lappend dirs [file join $d itcl$patchLevel]\n"
+" }\n"
+" }\n"
+" }\n"
+" foreach i $dirs {\n"
+" set library $i\n"
+" set itclfile [file join $i itclWidget.tcl]\n"
+" if {![catch {uplevel #0 [list source $itclfile]} msg]} {\n"
+" return\n"
+" }\n"
+" }\n"
+" set msg \"Can't find a usable itclWidget.tcl in the following directories:\n\"\n"
+" append msg \" $dirs\n\"\n"
+" append msg \"This probably means that Itcl/Tcl weren't installed properly.\n\"\n"
+" append msg \"If you know where the Itcl library directory was installed,\n\"\n"
+" append msg \"you can set the environment variable ITCL_LIBRARY to point\n\"\n"
+" append msg \"to the library directory.\n\"\n"
+" error $msg\n"
+" }\n"
+" _find_widget_init\n"
+"}";
+
+/*
+ * Info needed for public/protected/private commands:
+ */
+typedef struct ProtectionCmdInfo {
+ int pLevel; /* protection level */
+ ItclObjectInfo *infoPtr; /* info regarding all known objects */
+} ProtectionCmdInfo;
+
+/*
+ * FORWARD DECLARATIONS
+ */
+static Tcl_CmdDeleteProc ItclFreeParserCommandData;
+static void ItclDelObjectInfo(char* cdata);
+static int ItclInitClassCommon(Tcl_Interp *interp, ItclClass *iclsPtr,
+ ItclVariable *ivPtr, const char *initStr);
+
+static Tcl_ObjCmdProc Itcl_ClassTypeVariableCmd;
+static Tcl_ObjCmdProc Itcl_ClassTypeMethodCmd;
+static Tcl_ObjCmdProc Itcl_ClassFilterCmd;
+static Tcl_ObjCmdProc Itcl_ClassMixinCmd;
+static Tcl_ObjCmdProc Itcl_WidgetCmd;
+static Tcl_ObjCmdProc Itcl_WidgetAdaptorCmd;
+static Tcl_ObjCmdProc Itcl_ClassComponentCmd;
+static Tcl_ObjCmdProc Itcl_ClassTypeComponentCmd;
+static Tcl_ObjCmdProc Itcl_ClassDelegateMethodCmd;
+static Tcl_ObjCmdProc Itcl_ClassDelegateOptionCmd;
+static Tcl_ObjCmdProc Itcl_ClassDelegateTypeMethodCmd;
+static Tcl_ObjCmdProc Itcl_ClassForwardCmd;
+static Tcl_ObjCmdProc Itcl_ClassMethodVariableCmd;
+static Tcl_ObjCmdProc Itcl_ClassTypeConstructorCmd;
+static Tcl_ObjCmdProc ItclGenericClassCmd;
+
+static const struct {
+ const char *name;
+ Tcl_ObjCmdProc *objProc;
+} parseCmds[] = {
+ {"common", Itcl_ClassCommonCmd},
+ {"component", Itcl_ClassComponentCmd},
+ {"constructor", Itcl_ClassConstructorCmd},
+ {"destructor", Itcl_ClassDestructorCmd},
+ {"filter", Itcl_ClassFilterCmd},
+ {"forward", Itcl_ClassForwardCmd},
+ {"handleClass", Itcl_HandleClass},
+ {"hulltype", Itcl_ClassHullTypeCmd},
+ {"inherit", Itcl_ClassInheritCmd},
+ {"method", Itcl_ClassMethodCmd},
+ {"methodvariable", Itcl_ClassMethodVariableCmd},
+ {"mixin", Itcl_ClassMixinCmd},
+ {"option", Itcl_ClassOptionCmd},
+ {"proc", Itcl_ClassProcCmd},
+ {"typecomponent", Itcl_ClassTypeComponentCmd },
+ {"typeconstructor", Itcl_ClassTypeConstructorCmd},
+ {"typemethod", Itcl_ClassTypeMethodCmd},
+ {"typevariable", Itcl_ClassTypeVariableCmd},
+ {"variable", Itcl_ClassVariableCmd},
+ {"widgetclass", Itcl_ClassWidgetClassCmd},
+ {NULL, NULL}
+};
+
+static const struct {
+ const char *name;
+ Tcl_ObjCmdProc *objProc;
+ int protection;
+} protectionCmds[] = {
+ {"private", Itcl_ClassProtectionCmd, ITCL_PRIVATE},
+ {"protected", Itcl_ClassProtectionCmd, ITCL_PROTECTED},
+ {"public", Itcl_ClassProtectionCmd, ITCL_PUBLIC},
+ {NULL, NULL, 0}
+};
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ParseInit()
+ *
+ * Invoked by Itcl_Init() whenever a new interpeter is created to add
+ * [incr Tcl] facilities. Adds the commands needed to parse class
+ * definitions.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ParseInit(
+ Tcl_Interp *interp, /* interpreter to be updated */
+ ItclObjectInfo *infoPtr) /* info regarding all known objects and classes */
+{
+ Tcl_Namespace *parserNs;
+ ProtectionCmdInfo *pInfoPtr;
+ Tcl_DString buffer;
+ int i;
+
+ /*
+ * Create the "itcl::parser" namespace used to parse class
+ * definitions.
+ */
+ parserNs = Tcl_CreateNamespace(interp, "::itcl::parser",
+ (ClientData)infoPtr, Itcl_ReleaseData);
+
+ if (!parserNs) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ " (cannot initialize itcl parser)",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Add commands for parsing class definitions.
+ */
+ Tcl_DStringInit(&buffer);
+ for (i=0 ; parseCmds[i].name ; i++) {
+ Tcl_DStringAppend(&buffer, "::itcl::parser::", 16);
+ Tcl_DStringAppend(&buffer, parseCmds[i].name, -1);
+ Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
+ parseCmds[i].objProc, (ClientData) infoPtr, NULL);
+ Tcl_DStringFree(&buffer);
+ }
+
+ for (i=0 ; protectionCmds[i].name ; i++) {
+ Tcl_DStringAppend(&buffer, "::itcl::parser::", 16);
+ Tcl_DStringAppend(&buffer, protectionCmds[i].name, -1);
+ pInfoPtr = (ProtectionCmdInfo*)ckalloc(sizeof(ProtectionCmdInfo));
+ pInfoPtr->pLevel = protectionCmds[i].protection;
+ pInfoPtr->infoPtr = infoPtr;
+ Tcl_CreateObjCommand(interp, Tcl_DStringValue(&buffer),
+ protectionCmds[i].objProc, (ClientData) pInfoPtr,
+ (Tcl_CmdDeleteProc*) ItclFreeParserCommandData);
+ Tcl_DStringFree(&buffer);
+ }
+
+ /*
+ * Set the runtime variable resolver for the parser namespace,
+ * to control access to "common" data members while parsing
+ * the class definition.
+ */
+ if (infoPtr->useOldResolvers) {
+ ItclSetParserResolver(parserNs);
+ }
+ /*
+ * Install the "class" command for defining new classes.
+ */
+ Tcl_CreateObjCommand(interp, "::itcl::class", Itcl_ClassCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::body", Itcl_BodyCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itcl::configbody", Itcl_ConfigBodyCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Itcl_EventuallyFree((ClientData)infoPtr, ItclDelObjectInfo);
+
+ /*
+ * Create the "itcl::find" command for high-level queries.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::find") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::find",
+ "classes", "?pattern?",
+ Itcl_FindClassesCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::find",
+ "objects", "?-class className? ?-isa className? ?pattern?",
+ Itcl_FindObjectsCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+
+ /*
+ * Create the "itcl::delete" command to delete objects
+ * and classes.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::delete") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::delete",
+ "class", "name ?name...?",
+ Itcl_DelClassCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::delete",
+ "object", "name ?name...?",
+ Itcl_DelObjectCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::delete",
+ "ensemble", "name ?name...?",
+ Itcl_EnsembleDeleteCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Create the "itcl::is" command to test object
+ * and classes existence.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::is") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::is",
+ "class", "name", Itcl_IsClassCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::is",
+ "object", "?-class classname? name", Itcl_IsObjectCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+
+ /*
+ * Add "code" and "scope" commands for handling scoped values.
+ */
+ Tcl_CreateObjCommand(interp, "::itcl::code", Itcl_CodeCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ Tcl_CreateObjCommand(interp, "::itcl::scope", Itcl_ScopeCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
+
+ /*
+ * Add the "filter" commands (add/delete)
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::filter") != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Itcl_AddEnsemblePart(interp, "::itcl::filter",
+ "add", "objectOrClass filter ? ... ?", Itcl_FilterAddCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::filter",
+ "delete", "objectOrClass filter ? ... ?", Itcl_FilterDeleteCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Add the "forward" commands (add/delete)
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::forward") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::forward",
+ "add", "objectOrClass srcCommand targetCommand ? options ... ?",
+ Itcl_ForwardAddCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::forward",
+ "delete", "objectOrClass targetCommand ? ... ?",
+ Itcl_ForwardDeleteCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Add the "mixin" (add/delete) commands.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::mixin") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::mixin",
+ "add", "objectOrClass class ? class ... ?",
+ Itcl_MixinAddCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::mixin",
+ "delete", "objectOrClass class ? class ... ?",
+ Itcl_MixinDeleteCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Add commands for handling import stubs at the Tcl level.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::import::stub") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::import::stub",
+ "create", "name", Itcl_StubCreateCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (Itcl_AddEnsemblePart(interp, "::itcl::import::stub",
+ "exists", "name", Itcl_StubExistsCmd,
+ (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ Tcl_CreateObjCommand(interp, "::itcl::type", Itcl_TypeClassCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::widget", Itcl_WidgetCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::widgetadaptor", Itcl_WidgetAdaptorCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::nwidget", Itcl_NWidgetCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::addoption", Itcl_AddOptionCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::addobjectoption",
+ Itcl_AddObjectOptionCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::adddelegatedoption",
+ Itcl_AddDelegatedOptionCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::adddelegatedmethod",
+ Itcl_AddDelegatedFunctionCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::addcomponent", Itcl_AddComponentCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::setcomponent", Itcl_SetComponentCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, "::itcl::extendedclass", Itcl_ExtendedClassCmd,
+ (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ Tcl_CreateObjCommand(interp, ITCL_COMMANDS_NAMESPACE "::genericclass",
+ ItclGenericClassCmd, (ClientData)infoPtr, Itcl_ReleaseData);
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ /*
+ * Add the "delegate" (method/option) commands.
+ */
+ if (Itcl_CreateEnsemble(interp, "::itcl::parser::delegate") != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::parser::delegate",
+ "method", "name to targetName as scipt using script",
+ Itcl_ClassDelegateMethodCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::parser::delegate",
+ "typemethod", "name to targetName as scipt using script",
+ Itcl_ClassDelegateTypeMethodCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ if (Itcl_AddEnsemblePart(interp, "::itcl::parser::delegate",
+ "option", "option to targetOption as script",
+ Itcl_ClassDelegateOptionCmd, (ClientData)infoPtr,
+ Itcl_ReleaseData) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Itcl_PreserveData((ClientData)infoPtr);
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::class" command to
+ * specify a class definition. Handles the following syntax:
+ *
+ * itcl::class <className> {
+ * inherit <base-class>...
+ *
+ * constructor {<arglist>} ?{<init>}? {<body>}
+ * destructor {<body>}
+ *
+ * method <name> {<arglist>} {<body>}
+ * proc <name> {<arglist>} {<body>}
+ * variable <varname> ?<init>? ?<config>?
+ * common <varname> ?<init>?
+ *
+ * public <args>...
+ * protected <args>...
+ * private <args>...
+ * }
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclGenericClassCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *namePtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclComponent *icPtr;
+ const char *typeStr;
+ int result;
+
+
+ ItclShowArgs(1, "ItclGenericClassCmd", objc-1, objv);
+ if (objc != 4) {
+ Tcl_AppendResult(interp, "usage: genericclass <classtype> <classname> ",
+ "<body>", NULL);
+ return TCL_ERROR;
+ }
+ infoPtr = (ItclObjectInfo *)clientData;
+ typeStr = Tcl_GetString(objv[1]);
+ hPtr = Tcl_FindHashEntry(&infoPtr->classTypes, (char *)objv[1]);
+ if (hPtr == NULL) {
+ Tcl_AppendResult(interp, "genericclass bad classtype \"", typeStr,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ result = ItclClassBaseCmd(clientData, interp, PTR2INT(Tcl_GetHashValue(hPtr)),
+ objc - 1, objv + 1, &iclsPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ if (PTR2INT(Tcl_GetHashValue(hPtr)) == ITCL_WIDGETADAPTOR) {
+ /* create the itcl_hull variable */
+ namePtr = Tcl_NewStringObj("itcl_hull", -1);
+ if (ItclCreateComponent(interp, iclsPtr, namePtr, ITCL_COMMON,
+ &icPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ iclsPtr->numVariables++;
+ Itcl_BuildVirtualTables(iclsPtr);
+ }
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, Tcl_GetString(iclsPtr->fullNamePtr), NULL);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCmd()
+ *
+ * Invoked by Tcl whenever the user issues an "itcl::class" command to
+ * specify a class definition. Handles the following syntax:
+ *
+ * itcl::class <className> {
+ * inherit <base-class>...
+ *
+ * constructor {<arglist>} ?{<init>}? {<body>}
+ * destructor {<body>}
+ *
+ * method <name> {<arglist>} {<body>}
+ * proc <name> {<arglist>} {<body>}
+ * variable <varname> ?<init>? ?<config>?
+ * common <varname> ?<init>?
+ *
+ * public <args>...
+ * protected <args>...
+ * private <args>...
+ * }
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclClass *iclsPtr;
+
+ return ItclClassBaseCmd(clientData, interp, ITCL_CLASS, objc, objv,
+ &iclsPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclClassBaseCmd()
+ *
+ * ------------------------------------------------------------------------
+ */
+
+static Tcl_MethodCallProc ObjCallProc;
+static Tcl_MethodCallProc ArgCallProc;
+static Tcl_CloneProc CloneProc;
+
+static const Tcl_MethodType itclObjMethodType = {
+ TCL_OO_METHOD_VERSION_CURRENT,
+ "itcl objv method",
+ ObjCallProc,
+ ItclReleaseIMF,
+ CloneProc
+};
+
+static const Tcl_MethodType itclArgMethodType = {
+ TCL_OO_METHOD_VERSION_CURRENT,
+ "itcl argv method",
+ ArgCallProc,
+ ItclReleaseIMF,
+ CloneProc
+};
+
+static int
+CloneProc(
+ Tcl_Interp *interp,
+ ClientData original,
+ ClientData *copyPtr)
+{
+ ItclPreserveIMF((ItclMemberFunc *)original);
+ *copyPtr = original;
+ return TCL_OK;
+}
+
+static int
+CallAfterCallMethod(
+ ClientData data[],
+ Tcl_Interp *interp,
+ int result)
+{
+ ClientData clientData = data[0];
+ Tcl_ObjectContext context = data[1];
+
+ return ItclAfterCallMethod(clientData, interp, context, NULL, result);
+}
+
+static int
+ObjCallProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext context,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ ItclMemberFunc *imPtr = (ItclMemberFunc *)clientData;
+
+ if (TCL_ERROR == ItclCheckCallMethod(clientData, interp, context,
+ NULL, NULL)) {
+ return TCL_ERROR;
+ }
+
+ Tcl_NRAddCallback(interp, CallAfterCallMethod, clientData, context,
+ NULL, NULL);
+
+ if ((imPtr->flags & ITCL_COMMON) == 0) {
+ return Itcl_ExecMethod(clientData, interp, objc-1, objv+1);
+ } else {
+ return Itcl_ExecProc(clientData, interp, objc-1, objv+1);
+ }
+}
+
+static int
+ArgCallProc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ Tcl_ObjectContext context,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return TCL_ERROR;
+}
+
+int
+ItclClassBaseCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int flags, /* flags: ITCL_CLASS, ITCL_TYPE,
+ * ITCL_WIDGET or ITCL_WIDGETADAPTOR */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[], /* argument objects */
+ ItclClass **iclsPtrPtr) /* for returning iclsPtr */
+{
+ Tcl_Obj *argumentPtr;
+ Tcl_Obj *bodyPtr;
+ FOREACH_HASH_DECLS;
+ Tcl_HashEntry *hPtr2;
+ Tcl_Namespace *parserNs, *ooNs;
+ Tcl_CallFrame frame;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ ItclObjectInfo* infoPtr;
+ char *className;
+ int isNewEntry;
+ int result;
+ int noCleanup;
+ ItclMemberFunc *imPtr;
+
+ infoPtr = (ItclObjectInfo*)clientData;
+ if (iclsPtrPtr != NULL) {
+ *iclsPtrPtr = NULL;
+ }
+ if (objc != 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name { definition }");
+ return TCL_ERROR;
+ }
+ ItclShowArgs(1, "ItclClassBaseCmd", objc, objv);
+ className = Tcl_GetString(objv[1]);
+
+ noCleanup = 0;
+ /*
+ * Find the namespace to use as a parser for the class definition.
+ * If for some reason it is destroyed, bail out here.
+ */
+ parserNs = Tcl_FindNamespace(interp, "::itcl::parser",
+ (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);
+
+ if (parserNs == NULL) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while parsing class definition for \"%s\")",
+ className));
+ return TCL_ERROR;
+ }
+
+ /*
+ * Try to create the specified class and its namespace.
+ */
+ /* need the workaround with infoPtr->currClassFlags to keep the stubs
+ * call interface compatible!
+ */
+ infoPtr->currClassFlags = flags;
+ if (Itcl_CreateClass(interp, className, infoPtr, &iclsPtr) != TCL_OK) {
+ infoPtr->currClassFlags = 0;
+ return TCL_ERROR;
+ }
+ infoPtr->currClassFlags = 0;
+ iclsPtr->flags = flags;
+
+ /*
+ * Import the built-in commands from the itcl::builtin namespace.
+ * Do this before parsing the class definition, so methods/procs
+ * can override the built-in commands.
+ */
+ result = Tcl_Import(interp, iclsPtr->nsPtr, "::itcl::builtin::*",
+ /* allowOverwrite */ 1);
+ ooNs = Tcl_GetObjectNamespace(iclsPtr->oPtr);
+ if ( result == TCL_OK && ooNs != iclsPtr->nsPtr) {
+ result = Tcl_Import(interp, ooNs, "::itcl::builtin::*", 1);
+ }
+
+ if (result != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while installing built-in commands for class \"%s\")",
+ className));
+ goto errorReturn;
+ }
+
+ /*
+ * Push this class onto the class definition stack so that it
+ * becomes the current context for all commands in the parser.
+ * Activate the parser and evaluate the class definition.
+ */
+ Itcl_PushStack((ClientData)iclsPtr, &infoPtr->clsStack);
+
+ result = Itcl_PushCallFrame(interp, &frame, parserNs,
+ /* isProcCallFrame */ 0);
+
+ Itcl_SetCallFrameResolver(interp, iclsPtr->resolvePtr);
+ if (result == TCL_OK) {
+ result = Tcl_EvalObjEx(interp, objv[2], 0);
+ Itcl_PopCallFrame(interp);
+ }
+ Itcl_PopStack(&infoPtr->clsStack);
+
+ noCleanup = 0;
+ if (result != TCL_OK) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, result);
+ Tcl_Obj *key = Tcl_NewStringObj("-errorline", -1);
+ Tcl_Obj *stackTrace = NULL;
+
+ Tcl_IncrRefCount(key);
+ Tcl_DictObjGet(NULL, options, key, &stackTrace);
+ Tcl_DecrRefCount(key);
+ if (stackTrace == NULL) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n error while parsing class \"%s\" body %s",
+ className, Tcl_GetString(objv[2])));
+ noCleanup = 1;
+ } else {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (class \"%s\" body line %s)",
+ className, Tcl_GetString(stackTrace)));
+ }
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+
+ if (Itcl_FirstListElem(&iclsPtr->bases) == NULL) {
+ /* No [inherit]. Use default inheritance root. */
+ Tcl_Obj *cmdPtr = Tcl_NewListObj(4, NULL);
+
+ Tcl_ListObjAppendElement(NULL, cmdPtr,
+ Tcl_NewStringObj("::oo::define", -1));
+ Tcl_ListObjAppendElement(NULL, cmdPtr, iclsPtr->fullNamePtr);
+ Tcl_ListObjAppendElement(NULL, cmdPtr,
+ Tcl_NewStringObj("superclass", -1));
+ Tcl_ListObjAppendElement(NULL, cmdPtr,
+ Tcl_NewStringObj("::itcl::Root", -1));
+
+ Tcl_IncrRefCount(cmdPtr);
+ result = Tcl_EvalObj(interp, cmdPtr);
+ Tcl_DecrRefCount(cmdPtr);
+ if (result == TCL_ERROR) {
+ goto errorReturn;
+ }
+ }
+
+ /*
+ * At this point, parsing of the class definition has succeeded.
+ * Add built-in methods such as "configure" and "cget"--as long
+ * as they don't conflict with those defined in the class.
+ */
+ if (Itcl_InstallBiMethods(interp, iclsPtr) != TCL_OK) {
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+
+ /*
+ * Build the name resolution tables for all data members.
+ */
+ Itcl_BuildVirtualTables(iclsPtr);
+
+ /* make the methods and procs known to TclOO */
+ FOREACH_HASH_VALUE(imPtr, &iclsPtr->functions) {
+ ClientData pmPtr;
+ argumentPtr = imPtr->codePtr->argumentPtr;
+ bodyPtr = imPtr->codePtr->bodyPtr;
+
+if (imPtr->codePtr->flags & ITCL_IMPLEMENT_OBJCMD) {
+ /* Implementation of this member is coded in C expecting Tcl_Obj */
+
+ imPtr->tmPtr = Tcl_NewMethod(interp, iclsPtr->clsPtr, imPtr->namePtr,
+ 1, &itclObjMethodType, (ClientData) imPtr);
+ ItclPreserveIMF(imPtr);
+
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ imPtr->tmPtr = Tcl_NewInstanceMethod(interp, iclsPtr->oPtr,
+ imPtr->namePtr, 1, &itclObjMethodType, (ClientData) imPtr);
+ ItclPreserveIMF(imPtr);
+ }
+
+} else if (imPtr->codePtr->flags & ITCL_IMPLEMENT_ARGCMD) {
+ /* Implementation of this member is coded in C expecting (char *) */
+
+ imPtr->tmPtr = Tcl_NewMethod(interp, iclsPtr->clsPtr, imPtr->namePtr,
+ 1, &itclArgMethodType, (ClientData) imPtr);
+
+ ItclPreserveIMF(imPtr);
+
+
+
+} else {
+ if (imPtr->codePtr->flags & ITCL_BUILTIN) {
+ int isDone;
+ isDone = 0;
+ if (imPtr->builtinArgumentPtr == NULL) {
+/* FIXME next lines are possibly a MEMORY leak not really sure!! */
+ argumentPtr = Tcl_NewStringObj("args", -1);
+ imPtr->builtinArgumentPtr = argumentPtr;
+ Tcl_IncrRefCount(imPtr->builtinArgumentPtr);
+ } else {
+ argumentPtr = imPtr->builtinArgumentPtr;
+ }
+ bodyPtr = Tcl_NewStringObj("return [", -1);
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-cget") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::cget", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-configure") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::configure", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-isa") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::isa", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-createhull") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::createhull", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-keepcomponentoption") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::keepcomponentoption", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-ignorecomponentoption") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::ignorercomponentoption", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-renamecomponentoption") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::renamecomponentoption", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-keepoptioncomponent") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::keepoptioncomponent", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-ignoreoptioncomponent") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::ignoreoptioncomponent", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-renameoptioncomponent") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::renameoptioncomponent", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-setupcomponent") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::setupcomponent", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-initoptions") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::initoptions", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-getinstancevar") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::getinstancevar",
+ -1);
+ isDone = 1;
+ }
+ if (iclsPtr->flags &
+ (ITCL_TYPE|ITCL_WIDGETADAPTOR|
+ ITCL_WIDGET|ITCL_ECLASS)) {
+ /* now the builtin stuff for snit functionality */
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-mytypemethod") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::mytypemethod",
+ -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-mymethod") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::mymethod", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-myvar") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::myvar", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-mytypevar") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::mytypevar", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-itcl_hull") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::itcl_hull", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-callinstance") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::callinstance",
+ -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-myproc") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::myproc", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-installhull") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::installhull",
+ -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-installcomponent") == 0) {
+ Tcl_AppendToObj(bodyPtr,
+ "::itcl::builtin::installcomponent", -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-classunknown") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::classunknown",
+ -1);
+ isDone = 1;
+ }
+ if (strcmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-destroy") == 0) {
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::destroy", -1);
+ isDone = 1;
+ }
+ }
+ if (strncmp(Tcl_GetString(imPtr->codePtr->bodyPtr),
+ "@itcl-builtin-setget", 20) == 0) {
+ char *cp = Tcl_GetString(imPtr->codePtr->bodyPtr)+20;
+ Tcl_AppendToObj(bodyPtr, "::itcl::builtin::setget ", -1);
+ Tcl_AppendToObj(bodyPtr, cp, -1);
+ Tcl_AppendToObj(bodyPtr, " ", 1);
+ isDone = 1;
+ }
+ if (!isDone) {
+ Tcl_AppendToObj(bodyPtr,
+ Tcl_GetString(imPtr->codePtr->bodyPtr), -1);
+ }
+ Tcl_AppendToObj(bodyPtr, " {*}$args]", -1);
+ }
+ imPtr->tmPtr = (ClientData)Itcl_NewProcClassMethod(interp,
+ iclsPtr->clsPtr, ItclCheckCallMethod, ItclAfterCallMethod,
+ ItclProcErrorProc, imPtr, imPtr->namePtr, argumentPtr,
+ bodyPtr, &pmPtr);
+ hPtr2 = Tcl_CreateHashEntry(&iclsPtr->infoPtr->procMethods,
+ (char *)imPtr->tmPtr, &isNewEntry);
+ if (isNewEntry) {
+ Tcl_SetHashValue(hPtr2, imPtr);
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ if (argumentPtr == NULL) {
+ argumentPtr = iclsPtr->infoPtr->typeDestructorArgumentPtr;
+ imPtr->codePtr->argumentPtr = argumentPtr;
+ Tcl_IncrRefCount(argumentPtr);
+ }
+ /*
+ * We're overwriting the tmPtr field, so yank out the
+ * entry in the procMethods map based on the old one.
+ */
+ if (isNewEntry) {
+ Tcl_DeleteHashEntry(hPtr2);
+ }
+ imPtr->tmPtr = (ClientData)Itcl_NewProcMethod(interp,
+ iclsPtr->oPtr, ItclCheckCallMethod, ItclAfterCallMethod,
+ ItclProcErrorProc, imPtr, imPtr->namePtr, argumentPtr,
+ bodyPtr, &pmPtr);
+ }
+}
+ if ((imPtr->flags & ITCL_COMMON) == 0) {
+ imPtr->accessCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(imPtr->fullNamePtr),
+ Itcl_ExecMethod, imPtr, ItclReleaseIMF);
+ ItclPreserveIMF(imPtr);
+ } else {
+ imPtr->accessCmd = Tcl_CreateObjCommand(interp,
+ Tcl_GetString(imPtr->fullNamePtr),
+ Itcl_ExecProc, imPtr, ItclReleaseIMF);
+ ItclPreserveIMF(imPtr);
+ }
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ /* initialize the typecomponents and typevariables */
+ if (Itcl_PushCallFrame(interp, &frame, iclsPtr->nsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ FOREACH_HASH_VALUE(ivPtr, &iclsPtr->variables) {
+ if ((ivPtr->flags & ITCL_COMMON) && (ivPtr->init != NULL)) {
+ if (Tcl_SetVar2(interp, Tcl_GetString(ivPtr->namePtr), NULL,
+ Tcl_GetString(ivPtr->init),
+ TCL_NAMESPACE_ONLY) == NULL) {
+ Itcl_PopCallFrame(interp);
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ }
+ }
+ Itcl_PopCallFrame(interp);
+ }
+ if (iclsPtr->typeConstructorPtr != NULL) {
+ /* call the typeconstructor body */
+ if (Itcl_PushCallFrame(interp, &frame, iclsPtr->nsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ result = Tcl_EvalObjEx(interp, iclsPtr->typeConstructorPtr,
+ TCL_EVAL_DIRECT);
+ Itcl_PopCallFrame(interp);
+ if (result != TCL_OK) {
+ goto errorReturn;
+ }
+ }
+ result = TCL_OK;
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ if (ItclCheckForInitializedComponents(interp, iclsPtr, NULL) !=
+ TCL_OK) {
+ result = TCL_ERROR;
+ goto errorReturn;
+ }
+ }
+
+ if (result == TCL_OK) {
+ Tcl_ResetResult(interp);
+ }
+ if (iclsPtrPtr != NULL) {
+ *iclsPtrPtr = iclsPtr;
+ }
+ ItclAddClassesDictInfo(interp, iclsPtr);
+ return result;
+errorReturn:
+ if (!noCleanup) {
+ Tcl_DeleteNamespace(iclsPtr->nsPtr);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCheckForInitializedComponents()
+ *
+ * check if all components for delegation exist and are initialized
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCheckForInitializedComponents(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclObject *ioPtr)
+{
+ FOREACH_HASH_DECLS;
+ Tcl_CallFrame frame;
+ Tcl_DString buffer;
+ ItclDelegatedFunction *idmPtr;
+ int result;
+ int doCheck;
+
+ result = TCL_OK;
+ /* check if the typecomponents are initialized */
+ if (Itcl_PushCallFrame(interp, &frame, iclsPtr->nsPtr,
+ /*isProcCallFrame*/0) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ idmPtr = NULL;
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ const char *val;
+ /* check here for delegated typemethods only
+ * rest is done in ItclCreateObject
+ */
+ doCheck = 1;
+ if (ioPtr == NULL) {
+ if (!(idmPtr->flags & ITCL_TYPE_METHOD)) {
+ doCheck = 0;
+ ioPtr = iclsPtr->infoPtr->currIoPtr;
+ }
+ }
+ if (doCheck) {
+ if (idmPtr->icPtr != NULL) {
+ if (idmPtr->icPtr->ivPtr->flags & ITCL_COMMON) {
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj(ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_AppendToObj(objPtr, (Tcl_GetObjectNamespace(
+ idmPtr->icPtr->ivPtr->iclsPtr->oPtr))->fullName,
+ -1);
+ Tcl_AppendToObj(objPtr, "::", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(
+ idmPtr->icPtr->ivPtr->namePtr), -1);
+ val = Tcl_GetVar2(interp, Tcl_GetString(objPtr), NULL, 0);
+ Tcl_DecrRefCount(objPtr);
+ } else {
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(ioPtr->varNsNamePtr), -1);
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetString(idmPtr->icPtr->ivPtr->fullNamePtr),
+ -1);
+ val = Tcl_GetVar2(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ Tcl_DStringFree(&buffer);
+ }
+ if ((ioPtr != NULL) && ((val != NULL) && (strlen(val) == 0))) {
+ val = ItclGetInstanceVar(
+ ioPtr->iclsPtr->interp,
+ "itcl_hull", NULL, ioPtr,
+ iclsPtr);
+ }
+ if ((val == NULL) || (strlen(val) == 0)) {
+ if (iclsPtr->flags & ITCL_WIDGETADAPTOR) {
+ if (strcmp (Tcl_GetString(idmPtr->icPtr->namePtr),
+ "itcl_hull") == 0) {
+ /* maybe that will be initialized in constructor
+ * later on */
+ continue;
+ }
+ }
+ result = TCL_ERROR;
+ break;
+ }
+ }
+ }
+ }
+ Itcl_PopCallFrame(interp);
+ if (result == TCL_ERROR) {
+ const char *startStr;
+ const char *sepStr;
+ const char *objectStr;
+ startStr = "";
+ sepStr = "";
+ objectStr = "";
+ if (ioPtr != NULL) {
+ sepStr = " ";
+ objectStr = Tcl_GetString(ioPtr->origNamePtr);
+ }
+ if (idmPtr->flags & ITCL_TYPE_METHOD) {
+ startStr = "type";
+ }
+ /* FIXME there somtimes is a message for widgetadaptor:
+ * can't read "itcl_hull": no such variable
+ * have to check why
+ */
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, Tcl_GetString(iclsPtr->fullNamePtr),
+ sepStr, objectStr, " delegates ", startStr, "method \"",
+ Tcl_GetString(idmPtr->namePtr),
+ "\" to undefined ", startStr, "component \"",
+ Tcl_GetString(idmPtr->icPtr->ivPtr->namePtr), "\"", NULL);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassInheritCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "inherit" command is invoked to define one or more base classes.
+ * Handles the following syntax:
+ *
+ * inherit <baseclass> ?<baseclass>...?
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassInheritCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ int result;
+ int i;
+ int newEntry;
+ int haveClasses;
+ const char *token;
+ Itcl_ListElem *elem;
+ Itcl_ListElem *elem2;
+ ItclClass *cdPtr;
+ ItclClass *baseClsPtr;
+ ItclClass *badCdPtr;
+ ItclHierIter hier;
+ Itcl_Stack stack;
+ Tcl_CallFrame frame;
+ Tcl_DString buffer;
+
+ ItclShowArgs(2, "Itcl_InheritCmd", objc, objv);
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "class ?class...?");
+ return TCL_ERROR;
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::inherit called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ /*
+ * An "inherit" statement can only be included once in a
+ * class definition.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ if (elem != NULL) {
+ Tcl_AppendToObj(Tcl_GetObjResult(interp), "inheritance \"", -1);
+
+ while (elem) {
+ cdPtr = (ItclClass*)Itcl_GetListValue(elem);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ Tcl_GetString(cdPtr->namePtr), " ", (char*)NULL);
+
+ elem = Itcl_NextListElem(elem);
+ }
+
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\" already defined for class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Validate each base class and add it to the "bases" list.
+ */
+ result = Itcl_PushCallFrame(interp, &frame, iclsPtr->nsPtr->parentPtr,
+ /* isProcCallFrame */ 0);
+
+ if (result != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ for (objc--,objv++; objc > 0; objc--,objv++) {
+
+ /*
+ * Make sure that the base class name is known in the
+ * parent namespace (currently active). If not, try
+ * to autoload its definition.
+ */
+ token = Tcl_GetString(*objv);
+ baseClsPtr = Itcl_FindClass(interp, token, /* autoload */ 1);
+ if (!baseClsPtr) {
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+ int errlen;
+ char *errmsg;
+
+ Tcl_IncrRefCount(resultPtr);
+ errmsg = Tcl_GetStringFromObj(resultPtr, &errlen);
+
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot inherit from \"", token, "\"",
+ (char*)NULL);
+
+ if (errlen > 0) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ " (", errmsg, ")", (char*)NULL);
+ }
+ Tcl_DecrRefCount(resultPtr);
+ goto inheritError;
+ }
+
+ /*
+ * Make sure that the base class is not the same as the
+ * class that is being built.
+ */
+ if (baseClsPtr == iclsPtr) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "class \"", Tcl_GetString(iclsPtr->namePtr),
+ "\" cannot inherit from itself",
+ (char*)NULL);
+ goto inheritError;
+ }
+
+ Itcl_AppendList(&iclsPtr->bases, (ClientData)baseClsPtr);
+ ItclPreserveClass(baseClsPtr);
+ }
+
+ /*
+ * Scan through the inheritance list to make sure that no
+ * class appears twice.
+ */
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (elem) {
+ elem2 = Itcl_NextListElem(elem);
+ while (elem2) {
+ if (Itcl_GetListValue(elem) == Itcl_GetListValue(elem2)) {
+ cdPtr = (ItclClass*)Itcl_GetListValue(elem);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "class \"", iclsPtr->fullNamePtr,
+ "\" cannot inherit base class \"",
+ cdPtr->fullNamePtr, "\" more than once",
+ (char*)NULL);
+ goto inheritError;
+ }
+ elem2 = Itcl_NextListElem(elem2);
+ }
+ elem = Itcl_NextListElem(elem);
+ }
+
+ /*
+ * Add each base class and all of its base classes into
+ * the heritage for the current class. Along the way, make
+ * sure that no class appears twice in the heritage.
+ */
+ Itcl_InitHierIter(&hier, iclsPtr);
+ cdPtr = Itcl_AdvanceHierIter(&hier); /* skip the class itself */
+ cdPtr = Itcl_AdvanceHierIter(&hier);
+ while (cdPtr != NULL) {
+ (void) Tcl_CreateHashEntry(&iclsPtr->heritage,
+ (char*)cdPtr, &newEntry);
+
+ if (!newEntry) {
+ break;
+ }
+ cdPtr = Itcl_AdvanceHierIter(&hier);
+ }
+ Itcl_DeleteHierIter(&hier);
+
+ /*
+ * Same base class found twice in the hierarchy?
+ * Then flag error. Show the list of multiple paths
+ * leading to the same base class.
+ */
+ if (!newEntry) {
+ Tcl_Obj *resultPtr = Tcl_GetObjResult(interp);
+
+ badCdPtr = cdPtr;
+ Tcl_AppendStringsToObj(resultPtr,
+ "class \"", Tcl_GetString(iclsPtr->fullNamePtr),
+ "\" inherits base class \"",
+ Tcl_GetString(badCdPtr->fullNamePtr), "\" more than once:",
+ (char*)NULL);
+
+ cdPtr = iclsPtr;
+ Itcl_InitStack(&stack);
+ Itcl_PushStack((ClientData)cdPtr, &stack);
+
+ /*
+ * Show paths leading to bad base class
+ */
+ while (Itcl_GetStackSize(&stack) > 0) {
+ cdPtr = (ItclClass*)Itcl_PopStack(&stack);
+
+ if (cdPtr == badCdPtr) {
+ Tcl_AppendToObj(resultPtr, "\n ", -1);
+ for (i=0; i < Itcl_GetStackSize(&stack); i++) {
+ if (Itcl_GetStackValue(&stack, i) == NULL) {
+ cdPtr = (ItclClass*)Itcl_GetStackValue(&stack, i-1);
+ Tcl_AppendStringsToObj(resultPtr,
+ Tcl_GetString(cdPtr->namePtr), "->",
+ (char*)NULL);
+ }
+ }
+ Tcl_AppendToObj(resultPtr,
+ Tcl_GetString(badCdPtr->namePtr), -1);
+ }
+ else if (!cdPtr) {
+ (void)Itcl_PopStack(&stack);
+ }
+ else {
+ elem = Itcl_LastListElem(&cdPtr->bases);
+ if (elem) {
+ Itcl_PushStack((ClientData)cdPtr, &stack);
+ Itcl_PushStack((ClientData)NULL, &stack);
+ while (elem) {
+ Itcl_PushStack(Itcl_GetListValue(elem), &stack);
+ elem = Itcl_PrevListElem(elem);
+ }
+ }
+ }
+ }
+ Itcl_DeleteStack(&stack);
+ goto inheritError;
+ }
+
+ /*
+ * At this point, everything looks good.
+ * Finish the installation of the base classes. Update
+ * each base class to recognize the current class as a
+ * derived class.
+ */
+ Tcl_DStringInit(&buffer);
+ haveClasses = 0;
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ Tcl_DStringAppend(&buffer, "::oo::define ", -1);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_DStringAppend(&buffer, " superclass", -1);
+ while (elem) {
+ baseClsPtr = (ItclClass*)Itcl_GetListValue(elem);
+ haveClasses++;
+ Tcl_DStringAppend(&buffer, " ", -1);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(baseClsPtr->fullNamePtr), -1);
+
+ Itcl_AppendList(&baseClsPtr->derived, (ClientData)iclsPtr);
+ ItclPreserveClass(iclsPtr);
+
+ elem = Itcl_NextListElem(elem);
+ }
+ Itcl_PopCallFrame(interp);
+ if (haveClasses) {
+ result = Tcl_EvalEx(interp, Tcl_DStringValue(&buffer), -1, 0);
+ }
+ Tcl_DStringFree(&buffer);
+
+ return result;
+
+
+ /*
+ * If the "inherit" list cannot be built properly, tear it
+ * down and return an error.
+ */
+inheritError:
+ Itcl_PopCallFrame(interp);
+
+ elem = Itcl_FirstListElem(&iclsPtr->bases);
+ while (elem) {
+ ItclReleaseClass( (ItclClass *)Itcl_GetListValue(elem) );
+ elem = Itcl_DeleteListElem(elem);
+ }
+ return TCL_ERROR;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassProtectionCmd()
+ *
+ * Invoked by Tcl whenever the user issues a protection setting
+ * command like "public" or "private". Creates commands and
+ * variables, and assigns a protection level to them. Protection
+ * levels are defined as follows:
+ *
+ * public => accessible from any namespace
+ * protected => accessible from selected namespaces
+ * private => accessible only in the namespace where it was defined
+ *
+ * Handles the following syntax:
+ *
+ * public <command> ?<arg> <arg>...?
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassProtectionCmd(
+ ClientData clientData, /* protection level (public/protected/private) */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ProtectionCmdInfo *pInfo = (ProtectionCmdInfo*)clientData;
+ int result;
+ int oldLevel;
+
+ ItclShowArgs(2, "Itcl_ClassProtectionCmd", objc, objv);
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "command ?arg arg...?");
+ return TCL_ERROR;
+ }
+
+ oldLevel = Itcl_Protection(interp, pInfo->pLevel);
+
+ if (objc == 2) {
+ /* something like: public { variable a; variable b } */
+ result = Tcl_EvalObjEx(interp, objv[1], 0);
+ } else {
+ /* something like: public variable a 123 456 */
+ result = Itcl_EvalArgs(interp, objc-1, objv+1);
+ if (result == TCL_ERROR) {
+ Tcl_ResetResult(interp);
+ Tcl_WrongNumArgs(interp, 1, objv, "command ?arg arg...? or wrong command name");
+ return TCL_ERROR;
+ }
+ }
+
+ if (result == TCL_BREAK) {
+ Tcl_SetResult(interp, "invoked \"break\" outside of a loop",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ } else {
+ if (result == TCL_CONTINUE) {
+ Tcl_SetResult(interp, "invoked \"continue\" outside of a loop",
+ TCL_STATIC);
+ result = TCL_ERROR;
+ } else {
+ if (result != TCL_OK) {
+ Tcl_Obj *options = Tcl_GetReturnOptions(interp, result);
+ Tcl_Obj *key = Tcl_NewStringObj("-errorline", -1);
+ Tcl_Obj *stackTrace = NULL;
+
+ Tcl_IncrRefCount(key);
+ Tcl_DictObjGet(NULL, options, key, &stackTrace);
+ Tcl_DecrRefCount(key);
+ if (stackTrace == NULL) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n error while parsing class \"%s\"",
+ Tcl_GetString(objv[0])));
+ } else {
+ char *token = Tcl_GetString(objv[0]);
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (%.100s body line %s)",
+ token, Tcl_GetString(stackTrace)));
+ }
+ }
+ }
+ }
+
+ Itcl_Protection(interp, oldLevel);
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassConstructorCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "constructor" command is invoked to define the constructor
+ * for an object. Handles the following syntax:
+ *
+ * constructor <arglist> ?<init>? <body>
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassConstructorCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ Tcl_Obj *namePtr;
+ char *arglist;
+ char *body;
+
+ ItclShowArgs(2, "Itcl_ClassConstructorCmd", objc, objv);
+
+ if (objc < 3 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "args ?init? body");
+ return TCL_ERROR;
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::constructor called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ namePtr = objv[0];
+ if (Tcl_FindHashEntry(&iclsPtr->functions, (char *)objv[0])) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", Tcl_GetString(namePtr), "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ /*
+ * If there is an object initialization statement, pick this
+ * out and take the last argument as the constructor body.
+ */
+ arglist = Tcl_GetString(objv[1]);
+ if (objc == 3) {
+ body = Tcl_GetString(objv[2]);
+ } else {
+ iclsPtr->initCode = objv[2];
+ Tcl_IncrRefCount(iclsPtr->initCode);
+ body = Tcl_GetString(objv[3]);
+ }
+
+ if (Itcl_CreateMethod(interp, iclsPtr, namePtr, arglist, body) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassDestructorCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "destructor" command is invoked to define the destructor
+ * for an object. Handles the following syntax:
+ *
+ * destructor <body>
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassDestructorCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ Tcl_Obj *namePtr;
+ char *body;
+
+ ItclShowArgs(2, "Itcl_ClassDestructorCmd", objc, objv);
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "body");
+ return TCL_ERROR;
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::destructor called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ namePtr = objv[0];
+ body = Tcl_GetString(objv[1]);
+
+ if (Tcl_FindHashEntry(&iclsPtr->functions, (char *)namePtr)) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", Tcl_GetString(namePtr), "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ if (Itcl_CreateMethod(interp, iclsPtr, namePtr, (char*)NULL, body)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassMethodCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "method" command is invoked to define an object method.
+ * Handles the following syntax:
+ *
+ * method <name> ?<arglist>? ?<body>?
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassMethodCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *namePtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ char *arglist;
+ char *body;
+
+ ItclShowArgs(2, "Itcl_ClassMethodCmd", objc, objv);
+
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name ?args? ?body?");
+ return TCL_ERROR;
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::method called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ namePtr = objv[1];
+
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions, (char *)objv[1]);
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "method \"", Tcl_GetString(namePtr),
+ "\" has been delegated", NULL);
+ return TCL_ERROR;
+ }
+ arglist = NULL;
+ body = NULL;
+ if (objc >= 3) {
+ arglist = Tcl_GetString(objv[2]);
+ }
+ if (objc >= 4) {
+ body = Tcl_GetString(objv[3]);
+ }
+
+ if (Itcl_CreateMethod(interp, iclsPtr, namePtr, arglist, body) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassProcCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "proc" command is invoked to define a common class proc.
+ * A "proc" is like a "method", but only has access to "common"
+ * class variables. Handles the following syntax:
+ *
+ * proc <name> ?<arglist>? ?<body>?
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassProcCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *namePtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ char *arglist;
+ char *body;
+
+ ItclShowArgs(1, "Itcl_ClassProcCmd", objc, objv);
+
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name ?args? ?body?");
+ return TCL_ERROR;
+ }
+
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ namePtr = objv[1];
+
+ arglist = NULL;
+ body = NULL;
+ if (objc >= 3) {
+ arglist = Tcl_GetString(objv[2]);
+ }
+ if (objc >= 4) {
+ body = Tcl_GetString(objv[3]);
+ }
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::proc called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ const char *name = Tcl_GetString(namePtr);
+ /* check if the typemethod is already delegated */
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), name) == 0) {
+ Tcl_AppendResult(interp, "Error in \"typemethod ", name,
+ "...\", \"", name, "\" has been delegated", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ if (Itcl_CreateProc(interp, iclsPtr, namePtr, arglist, body) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassTypeMethodCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "proc" command is invoked to define a common class proc.
+ * A "proc" is like a "method", but only has access to "common"
+ * class variables. Handles the following syntax:
+ *
+ * typemethod <name> ?<arglist>? ?<body>?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassTypeMethodCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ FOREACH_HASH_DECLS;
+ Tcl_Obj *namePtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ char *arglist;
+ char *body;
+ ItclMemberFunc *imPtr;
+
+ ItclShowArgs(1, "Itcl_ClassTypeMethodCmd", objc, objv);
+
+ if (objc < 2 || objc > 4) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name ?args? ?body?");
+ return TCL_ERROR;
+ }
+
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::typemethod called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ namePtr = objv[1];
+
+ arglist = NULL;
+ body = NULL;
+ if (objc >= 3) {
+ arglist = Tcl_GetString(objv[2]);
+ }
+ if (objc >= 4) {
+ body = Tcl_GetString(objv[3]);
+ }
+
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ const char *name = Tcl_GetString(namePtr);
+ /* check if the typemethod is already delegated */
+ FOREACH_HASH_VALUE(idmPtr, &iclsPtr->delegatedFunctions) {
+ if (strcmp(Tcl_GetString(idmPtr->namePtr), name) == 0) {
+ Tcl_AppendResult(interp, "Error in \"typemethod ", name,
+ "...\", \"", name, "\" has been delegated", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ iclsPtr->infoPtr->functionFlags = ITCL_TYPE_METHOD;
+ if (Itcl_CreateProc(interp, iclsPtr, namePtr, arglist, body) != TCL_OK) {
+ iclsPtr->infoPtr->functionFlags = 0;
+ return TCL_ERROR;
+ }
+ iclsPtr->infoPtr->functionFlags = 0;
+ hPtr = Tcl_FindHashEntry(&iclsPtr->functions, (char *)namePtr);
+ imPtr = Tcl_GetHashValue(hPtr);
+ imPtr->flags |= ITCL_TYPE_METHOD;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassVariableCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "variable" command is invoked to define an instance variable.
+ * Handles the following syntax:
+ *
+ * variable <varname> ?<init>? ?<config>?
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassVariableCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *namePtr;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ ItclVariable *ivPtr;
+ char *init;
+ char *config;
+ char *arrayInitStr;
+ const char *usageStr;
+ int pLevel;
+ int haveError;
+ int haveArrayInit;
+ int result;
+
+ result = TCL_OK;
+ haveError = 0;
+ haveArrayInit = 0;
+ usageStr = NULL;
+ arrayInitStr = NULL;
+ ItclShowArgs(1, "Itcl_ClassVariableCmd", objc, objv);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::variable called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ pLevel = Itcl_Protection(interp, 0);
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ if (objc > 2) {
+ if (strcmp(Tcl_GetString(objv[2]), "-array") == 0) {
+ if (objc == 4) {
+ arrayInitStr = Tcl_GetString(objv[3]);
+ haveArrayInit = 1;
+ } else {
+ haveError = 1;
+ usageStr = "varname ?init|-array init?";
+ }
+ }
+ }
+ }
+ if (!haveError && !haveArrayInit) {
+ if (pLevel == ITCL_PUBLIC) {
+ if (objc < 2 || objc > 4) {
+ usageStr = "name ?init? ?config?";
+ haveError = 1;
+ }
+ } else {
+ if ((objc < 2) || (objc > 3)) {
+ usageStr = "name ?init?";
+ haveError = 1;
+ }
+ }
+ }
+
+ if (haveError) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure that the variable name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ namePtr = objv[1];
+ if (strstr(Tcl_GetString(namePtr), "::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad variable name \"", Tcl_GetString(namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ init = NULL;
+ config = NULL;
+ if (!haveArrayInit) {
+ if (objc >= 3) {
+ init = Tcl_GetString(objv[2]);
+ }
+ if (objc >= 4) {
+ config = Tcl_GetString(objv[3]);
+ }
+ }
+
+ if (Itcl_CreateVariable(interp, iclsPtr, namePtr, init, config,
+ &ivPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ ivPtr->flags |= ITCL_VARIABLE;
+ }
+ if (haveArrayInit) {
+ ivPtr->arrayInitPtr = Tcl_NewStringObj(arrayInitStr, -1);
+ Tcl_IncrRefCount(ivPtr->arrayInitPtr);
+ } else {
+ ivPtr->arrayInitPtr = NULL;
+ }
+ iclsPtr->numVariables++;
+ ItclAddClassVariableDictInfo(interp, iclsPtr, ivPtr);
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclInitClassCommon()
+ *
+ * initialize a class commen variable
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclInitClassCommon(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ ItclVariable *ivPtr,
+ const char *initStr)
+{
+ Tcl_DString buffer;
+ Tcl_CallFrame frame;
+ Tcl_Namespace *commonNsPtr;
+ Tcl_HashEntry *hPtr;
+ Tcl_Var varPtr;
+ int result;
+ int isNew;
+
+ result = TCL_OK;
+ ivPtr->flags |= ITCL_COMMON;
+ iclsPtr->numCommons++;
+
+ /*
+ * Create the variable in the namespace associated with the
+ * class. Do this the hard way, to avoid the variable resolver
+ * procedures. These procedures won't work until we rebuild
+ * the virtual tables below.
+ */
+ Tcl_DStringInit(&buffer);
+ if (ivPtr->protection != ITCL_PUBLIC) {
+ /* public commons go to the class namespace directly the others
+ * go to the variables namespace of the class */
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ }
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(ivPtr->iclsPtr->oPtr))->fullName, -1);
+ commonNsPtr = Tcl_FindNamespace(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ if (commonNsPtr == NULL) {
+ Tcl_AppendResult(interp, "ITCL: cannot find common variables namespace",
+ " for class \"", Tcl_GetString(ivPtr->iclsPtr->fullNamePtr),
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ varPtr = Tcl_NewNamespaceVar(interp, commonNsPtr,
+ Tcl_GetString(ivPtr->namePtr));
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->classCommons, (char *)ivPtr,
+ &isNew);
+ if (isNew) {
+ Itcl_PreserveVar(varPtr);
+ Tcl_SetHashValue(hPtr, varPtr);
+ }
+ result = Itcl_PushCallFrame(interp, &frame, commonNsPtr,
+ /* isProcCallFrame */ 0);
+ Itcl_PopCallFrame(interp);
+
+ /*
+ * TRICKY NOTE: Make sure to rebuild the virtual tables for this
+ * class so that this variable is ready to access. The variable
+ * resolver for the parser namespace needs this info to find the
+ * variable if the developer tries to set it within the class
+ * definition.
+ *
+ * If an initialization value was specified, then initialize
+ * the variable now.
+ */
+ Itcl_BuildVirtualTables(iclsPtr);
+
+ if (initStr != NULL) {
+ const char *val;
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(ivPtr->namePtr), -1);
+ val = Tcl_SetVar(interp,
+ Tcl_DStringValue(&buffer), initStr,
+ TCL_NAMESPACE_ONLY);
+
+ if (!val) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot initialize common variable \"",
+ Tcl_GetString(ivPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (ivPtr->arrayInitPtr != NULL) {
+ int i;
+ int argc;
+ const char **argv;
+ const char *val;
+ Tcl_DStringAppend(&buffer, "::", -1);
+ Tcl_DStringAppend(&buffer, Tcl_GetString(ivPtr->namePtr), -1);
+ result = Tcl_SplitList(interp, Tcl_GetString(ivPtr->arrayInitPtr),
+ &argc, &argv);
+ for (i = 0; i < argc; i++) {
+ val = Tcl_SetVar2(interp, Tcl_DStringValue(&buffer), argv[i],
+ argv[i + 1], TCL_NAMESPACE_ONLY);
+ if (!val) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "cannot initialize common variable \"",
+ Tcl_GetString(ivPtr->namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ i++;
+ }
+ ckfree((char *)argv);
+ }
+ Tcl_DStringFree(&buffer);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCommonCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "common" command is invoked to define a variable that is
+ * common to all objects in the class. Handles the following syntax:
+ *
+ * common <varname> ?<init>?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclClassCommonCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[], /* argument objects */
+ int protection,
+ ItclVariable **ivPtrPtr)
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ ItclVariable *ivPtr;
+ Tcl_Obj *namePtr;
+ char *arrayInitStr;
+ const char *usageStr;
+ char *initStr;
+ int haveError;
+ int haveArrayInit;
+ int result;
+
+ result = TCL_OK;
+ haveError = 0;
+ haveArrayInit = 0;
+ usageStr = NULL;
+ arrayInitStr = NULL;
+ *ivPtrPtr = NULL;
+ ItclShowArgs(2, "Itcl_ClassCommonCmd", objc, objv);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::common called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGETADAPTOR)) {
+ if (objc > 2) {
+ if (strcmp(Tcl_GetString(objv[2]), "-array") == 0) {
+ if (objc == 4) {
+ arrayInitStr = Tcl_GetString(objv[3]);
+ haveArrayInit = 1;
+ } else {
+ haveError = 1;
+ usageStr = "varname ?init|-array init?";
+ }
+ }
+ }
+ }
+ if (!haveError && !haveArrayInit) {
+ if ((objc < 2) || (objc > 3)) {
+ usageStr = "varname ?init?";
+ haveError = 1;
+ }
+ }
+ if (haveError) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure that the variable name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ namePtr = objv[1];
+ if (strstr(Tcl_GetString(namePtr), "::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad variable name \"", Tcl_GetString(namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ initStr = NULL;
+ if (!haveArrayInit) {
+ if (objc >= 3) {
+ initStr = Tcl_GetString(objv[2]);
+ }
+ }
+
+ if (Itcl_CreateVariable(interp, iclsPtr, namePtr, initStr, (char*)NULL,
+ &ivPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (protection != 0) {
+ ivPtr->protection = protection;
+ }
+ if (haveArrayInit) {
+ ivPtr->arrayInitPtr = Tcl_NewStringObj(arrayInitStr, -1);
+ Tcl_IncrRefCount(ivPtr->arrayInitPtr);
+ } else {
+ ivPtr->arrayInitPtr = NULL;
+ }
+ *ivPtrPtr = ivPtr;
+ result = ItclInitClassCommon(interp, iclsPtr, ivPtr, initStr);
+ ItclAddClassVariableDictInfo(interp, iclsPtr, ivPtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassTypeVariableCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "typevariable" command is invoked to define a variable that is
+ * common to all objects in the class. Handles the following syntax:
+ *
+ * typevariable <varname> ?<init>?
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassTypeVariableCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclVariable *ivPtr;
+ int result;
+
+ ivPtr = NULL;
+ ItclShowArgs(1, "Itcl_ClassTypeVariableCmd", objc, objv);
+ result = ItclClassCommonCmd(clientData, interp, objc, objv, ITCL_PUBLIC,
+ &ivPtr);
+ if (ivPtr != NULL) {
+ ivPtr->flags |= ITCL_TYPE_VARIABLE;
+ ItclAddClassVariableDictInfo(interp, ivPtr->iclsPtr, ivPtr);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCommonCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "common" command is invoked to define a variable that is
+ * common to all objects in the class. Handles the following syntax:
+ *
+ * common <varname> ?<init>?
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCommonCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclVariable *ivPtr;
+
+ ItclShowArgs(2, "Itcl_ClassTypeVariableCmd", objc, objv);
+ return ItclClassCommonCmd(clientData, interp, objc, objv, 0, &ivPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclFreeParserCommandData()
+ *
+ * This callback will free() up memory dynamically allocated
+ * and passed as the ClientData argument to Tcl_CreateObjCommand.
+ * This callback is required because one can not simply pass
+ * a pointer to the free() or ckfree() to Tcl_CreateObjCommand.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclFreeParserCommandData(
+ ClientData cdata) /* client data to be destroyed */
+{
+ ckfree(cdata);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDelObjectInfo()
+ *
+ * Invoked when the management info for [incr Tcl] is no longer being
+ * used in an interpreter. This will only occur when all class
+ * manipulation commands are removed from the interpreter.
+ * ------------------------------------------------------------------------
+ */
+static void
+ItclDelObjectInfo(
+ char* cdata) /* client data for class command */
+{
+ Tcl_HashSearch place;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)cdata;
+ ItclObject *ioPtr;
+
+ /*
+ * Destroy all known objects by deleting their access
+ * commands.
+ */
+ hPtr = Tcl_FirstHashEntry(&infoPtr->objects, &place);
+ while (hPtr) {
+ ioPtr = (ItclObject*)Tcl_GetHashValue(hPtr);
+ Tcl_DeleteCommandFromToken(infoPtr->interp, ioPtr->accessCmd);
+ /*
+ * Fix 227804: Whenever an object to delete was found we
+ * have to reset the search to the beginning as the
+ * current entry in the search was deleted and accessing it
+ * is therefore not allowed anymore.
+ */
+
+ hPtr = Tcl_FirstHashEntry(&infoPtr->objects, &place);
+ /*hPtr = Tcl_NextHashEntry(&place);*/
+ }
+ Tcl_DeleteHashTable(&infoPtr->objects);
+
+ Itcl_DeleteStack(&infoPtr->clsStack);
+/* FIXME !!!
+ free class_meta_type and object_meta_type
+*/
+ ckfree((char*)infoPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassFilterCmd()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassFilterCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj **newObjv;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ClassFilterCmd", objc, objv);
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::filter called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/::itcl::type",
+ "/::itcl::extendedclass. Only these can have filters", NULL);
+ return TCL_ERROR;
+ }
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "<filterName> ?<filterName> ...?");
+ return TCL_ERROR;
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*(objc+2));
+ newObjv[0] = Tcl_NewStringObj("::oo::define", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj(Tcl_GetString(iclsPtr->fullNamePtr), -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = Tcl_NewStringObj("filter", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ memcpy(newObjv+3, objv+1, sizeof(Tcl_Obj *)*(objc-1));
+ItclShowArgs(1, "Itcl_ClassFilterCmd2", objc+2, newObjv);
+ result = Tcl_EvalObjv(interp, objc+2, newObjv, 0);
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ ckfree((char *)newObjv);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassMixinCmd()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassMixinCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclShowArgs(0, "Itcl_ClassMixinCmd", objc, objv);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_WidgetCmd()
+ *
+ * that is just a dummy command to load package ItclWidget
+ * and then to resend the command and execute it in that package
+ * package ItclWidget is renaming the Tcl command!!
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_WidgetCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_WidgetCmd", objc-1, objv);
+ infoPtr = (ItclObjectInfo *)clientData;
+ if (!infoPtr->itclWidgetInitted) {
+ result = Tcl_EvalEx(interp, initWidgetScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclWidgetInitted = 1;
+ }
+ return Tcl_EvalObjv(interp, objc, objv, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_WidgetAdaptorCmd()
+ *
+ * that is just a dummy command to load package ItclWidget
+ * and then to resend the command and execute it in that package
+ * package ItclWidget is renaming the Tcl command!!
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_WidgetAdaptorCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_WidgetAdaptorCmd", objc-1, objv);
+ infoPtr = (ItclObjectInfo *)clientData;
+ if (!infoPtr->itclWidgetInitted) {
+ result = Tcl_EvalEx(interp, initWidgetScript, -1, 0);
+ if (result != TCL_OK) {
+ return result;
+ }
+ infoPtr->itclWidgetInitted = 1;
+ }
+ return Tcl_EvalObjv(interp, objc, objv, 0);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclParseOption()
+ *
+ * Invoked by Tcl during the parsing whenever
+ * the "option" command is invoked to define an option
+ * Handles the following syntax:
+ *
+ * option
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclParseOption(
+ ItclObjectInfo *infoPtr, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[], /* argument objects */
+ ItclClass *iclsPtr,
+ ItclObject *ioPtr,
+ ItclOption **ioptPtrPtr) /* where the otpion info is found */
+{
+ Tcl_Obj *classNamePtr;
+ Tcl_Obj *nameSpecPtr;
+ Tcl_Obj **newObjv;
+ Tcl_HashEntry *hPtr;
+ ItclOption *ioptPtr;
+ char *init;
+ char *defaultValue;
+ char *cgetMethod;
+ char *cgetMethodVar;
+ char *configureMethod;
+ char *configureMethodVar;
+ char *validateMethod;
+ char *validateMethodVar;
+ const char *token;
+ const char *usage;
+ const char *optionName;
+ const char **argv;
+ const char *name;
+ const char *resourceName;
+ const char *className;
+ int argc;
+ int pLevel;
+ int readOnly;
+ int newObjc;
+ int foundOption;
+ int result;
+ int i;
+ const char *cp;
+
+ ItclShowArgs(1, "ItclParseOption", objc, objv);
+ pLevel = Itcl_Protection(interp, 0);
+
+ usage = "namespec \
+?init? \
+?-default value? \
+?-readonly? \
+?-cgetmethod methodName? \
+?-cgetmethodvar varName? \
+?-configuremethod methodName? \
+?-configuremethodvar varName? \
+?-validatemethod methodName? \
+?-validatemethodvar varName";
+
+ if (pLevel == ITCL_PUBLIC) {
+ if (objc < 2 || objc > 11) {
+ Tcl_WrongNumArgs(interp, 1, objv, usage);
+ return TCL_ERROR;
+ }
+ } else {
+ if ((objc < 2) || (objc > 12)) {
+ Tcl_WrongNumArgs(interp, 1, objv, usage);
+ return TCL_ERROR;
+ }
+ }
+
+ argv = NULL;
+ newObjv = NULL;
+ defaultValue = NULL;
+ cgetMethod = NULL;
+ configureMethod = NULL;
+ validateMethod = NULL;
+ cgetMethodVar = NULL;
+ configureMethodVar = NULL;
+ validateMethodVar = NULL;
+ readOnly = 0;
+ newObjc = 0;
+ optionName = Tcl_GetString(objv[1]);
+ if (iclsPtr != NULL) {
+ /* check for already delegated!! */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedOptions, (char *)objv[1]);
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "cannot define option \"", optionName,
+ "\" locally, it has already been delegated", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ }
+ if (ioPtr != NULL) {
+ /* check for already delegated!! */
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectDelegatedOptions,
+ (char *)objv[1]);
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "cannot define option \"", optionName,
+ "\" locally, it has already been delegated", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ }
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj *)*objc);
+ newObjv[newObjc] = objv[1];
+ newObjc++;
+ for (i=2; i<objc; i++) {
+ token = Tcl_GetString(objv[i]);
+ foundOption = 0;
+ if (*token == '-') {
+ if (objc < i+1) {
+ Tcl_WrongNumArgs(interp, 1, objv, usage);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if (strcmp(token, "-default") == 0) {
+ foundOption = 1;
+ i++;
+ defaultValue = Tcl_GetString(objv[i]);
+ } else {
+ if (strcmp(token, "-readonly") == 0) {
+ foundOption = 1;
+ readOnly = 1;
+ } else {
+ if (strncmp(token, "-cgetmethod", 11) == 0) {
+ if (strcmp(token, "-cgetmethod") == 0) {
+ foundOption = 1;
+ i++;
+ cgetMethod = Tcl_GetString(objv[i]);
+ }
+ if (strcmp(token, "-cgetmethodvar") == 0) {
+ foundOption = 1;
+ i++;
+ cgetMethodVar = Tcl_GetString(objv[i]);
+ }
+ } else {
+ if (strncmp(token, "-configuremethod", 16) == 0) {
+ if (strcmp(token, "-configuremethod") == 0) {
+ foundOption = 1;
+ i++;
+ configureMethod = Tcl_GetString(objv[i]);
+ }
+ if (strcmp(token, "-configuremethodvar") == 0) {
+ foundOption = 1;
+ i++;
+ configureMethodVar = Tcl_GetString(objv[i]);
+ }
+ } else {
+ if (strncmp(token, "-validatemethod", 15) == 0) {
+ if (strcmp(token, "-validatemethod") == 0) {
+ foundOption = 1;
+ i++;
+ validateMethod = Tcl_GetString(objv[i]);
+ }
+ if (strcmp(token, "-validatemethodvar") == 0) {
+ foundOption = 1;
+ i++;
+ validateMethodVar = Tcl_GetString(objv[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!foundOption) {
+ Tcl_AppendResult(interp, "funny option command option: \"",
+ token, "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ if (!foundOption) {
+ newObjv[newObjc] = objv[i];
+ newObjc++;
+ }
+ }
+
+ if ((cgetMethod != NULL) && (cgetMethodVar != NULL)) {
+ Tcl_AppendResult(interp,
+ "option -cgetmethod and -cgetmethodvar cannot be used both",
+ NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if ((configureMethod != NULL) && (configureMethodVar != NULL)) {
+ Tcl_AppendResult(interp,
+ "option -configuremethod and -configuremethodvar",
+ "cannot be used both",
+ NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if ((validateMethod != NULL) && (validateMethodVar != NULL)) {
+ Tcl_AppendResult(interp,
+ "option -validatemethod and -validatemethodvar",
+ "cannot be used both",
+ NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if (newObjc < 1) {
+ Tcl_AppendResult(interp, "usage: option ", usage, NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ resourceName = NULL;
+ className = NULL;
+
+ nameSpecPtr = newObjv[0];
+ token = Tcl_GetString(nameSpecPtr);
+ if (Tcl_SplitList(interp, (const char *)token, &argc, &argv) != TCL_OK) {
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ name = argv[0];
+ if (*name != '-') {
+ Tcl_AppendResult(interp, "bad option name \"", name,
+ "\", options must start with a \"-\"", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+
+ /*
+ * Make sure that the variable name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ if (strstr(name, "::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option name \"", name,
+ "\", option names must not contain \"::\"", (char*)NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ if (strstr(name, " ")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option name \"", name,
+ "\", option names must not contain \" \"", (char*)NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ cp = name;
+ while (*cp) {
+ if (isupper(UCHAR(*cp))) {
+ Tcl_AppendResult(interp, "bad option name \"", name, "\" ",
+ ", options must not contain uppercase characters", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ cp++;
+ }
+ if (argc > 1) {
+ resourceName = argv[1];
+ } else {
+ /* resource name defaults to option name minus hyphen */
+ resourceName = name+1;
+ }
+ if (argc > 2) {
+ className = argv[2];
+ } else {
+ /* class name defaults to option name minus hyphen and capitalized */
+ className = resourceName;
+ }
+ classNamePtr = ItclCapitalize(className);
+ init = defaultValue;
+ if ((newObjc > 1) && (init == NULL)) {
+ init = Tcl_GetString(newObjv[1]);
+ }
+
+ ioptPtr = (ItclOption*)ckalloc(sizeof(ItclOption));
+ memset(ioptPtr, 0, sizeof(ItclOption));
+ ioptPtr->protection = Itcl_Protection(interp, 0);
+ if (ioptPtr->protection == ITCL_DEFAULT_PROTECT) {
+ ioptPtr->protection = ITCL_PROTECTED;
+ }
+ ioptPtr->namePtr = Tcl_NewStringObj(name, -1);
+ Tcl_IncrRefCount(ioptPtr->namePtr);
+ ioptPtr->resourceNamePtr = Tcl_NewStringObj(resourceName, -1);
+ Tcl_IncrRefCount(ioptPtr->resourceNamePtr);
+ ioptPtr->classNamePtr = Tcl_NewStringObj(Tcl_GetString(classNamePtr), -1);
+ Tcl_IncrRefCount(ioptPtr->classNamePtr);
+ Tcl_DecrRefCount(classNamePtr);
+
+ if (init) {
+ ioptPtr->defaultValuePtr = Tcl_NewStringObj(init, -1);
+ Tcl_IncrRefCount(ioptPtr->defaultValuePtr);
+ }
+ if (cgetMethod != NULL) {
+ ioptPtr->cgetMethodPtr = Tcl_NewStringObj(cgetMethod, -1);
+ Tcl_IncrRefCount(ioptPtr->cgetMethodPtr);
+ }
+ if (configureMethod != NULL) {
+ ioptPtr->configureMethodPtr = Tcl_NewStringObj(configureMethod, -1);
+ Tcl_IncrRefCount(ioptPtr->configureMethodPtr);
+ }
+ if (validateMethod != NULL) {
+ ioptPtr->validateMethodPtr = Tcl_NewStringObj(validateMethod, -1);
+ Tcl_IncrRefCount(ioptPtr->validateMethodPtr);
+ }
+ if (cgetMethodVar != NULL) {
+ ioptPtr->cgetMethodVarPtr = Tcl_NewStringObj(cgetMethodVar, -1);
+ Tcl_IncrRefCount(ioptPtr->cgetMethodVarPtr);
+ }
+ if (configureMethodVar != NULL) {
+ ioptPtr->configureMethodVarPtr = Tcl_NewStringObj(configureMethodVar, -1);
+ Tcl_IncrRefCount(ioptPtr->configureMethodVarPtr);
+ }
+ if (validateMethodVar != NULL) {
+ ioptPtr->validateMethodVarPtr = Tcl_NewStringObj(validateMethodVar, -1);
+ Tcl_IncrRefCount(ioptPtr->validateMethodVarPtr);
+ }
+ if (readOnly != 0) {
+ ioptPtr->flags |= ITCL_OPTION_READONLY;
+ }
+
+ *ioptPtrPtr = ioptPtr;
+ ItclAddOptionDictInfo(interp, iclsPtr, ioptPtr);
+ result = TCL_OK;
+errorOut:
+ if (argv != NULL) {
+ ckfree((char *)argv);
+ }
+ if (newObjv != NULL) {
+ ckfree((char *)newObjv);
+ }
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassOptionCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "option" command is invoked to define an option
+ * Handles the following syntax:
+ *
+ * option
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassOptionCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclOption *ioptPtr;
+ const char *tkPackage;
+ const char *tkVersion;
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+
+ ItclShowArgs(1, "Itcl_ClassOptionCmd", objc, objv);
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::option called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "a \"class\" cannot have options", NULL);
+ return TCL_ERROR;
+ }
+
+ if ((objc > 1) && (strcmp(Tcl_GetString(objv[1]), "add") == 0)) {
+ tkVersion = "8.6";
+ tkPackage = Tcl_PkgPresent(interp, "Tk", tkVersion, 0);
+ if (tkPackage == NULL) {
+ tkPackage = Tcl_PkgRequire(interp, "Tk", tkVersion, 0);
+ }
+ if (tkPackage == NULL) {
+ Tcl_AppendResult(interp, "cannot load package Tk", tkVersion,
+ NULL);
+ return TCL_ERROR;
+ }
+ return Tcl_EvalObjv(interp, objc, objv, TCL_EVAL_GLOBAL);
+ }
+ if (ItclParseOption(infoPtr, interp, objc, objv, iclsPtr, NULL,
+ &ioptPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ if (Itcl_CreateOption(interp, iclsPtr, ioptPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateComponent()
+ *
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCreateComponent(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ Tcl_Obj *componentPtr,
+ int type,
+ ItclComponent **icPtrPtr)
+{
+ Tcl_HashEntry *hPtr;
+ ItclComponent *icPtr;
+ ItclVariable *ivPtr;
+ int result;
+ int isNew;
+
+ if (iclsPtr == NULL) {
+ return TCL_OK;
+ }
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->components, (char *)componentPtr,
+ &isNew);
+ if (isNew) {
+ if (Itcl_CreateVariable(interp, iclsPtr, componentPtr, NULL, NULL,
+ &ivPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (type & ITCL_COMMON) {
+ result = ItclInitClassCommon(interp, iclsPtr, ivPtr, "");
+ if (result != TCL_OK) {
+ return result;
+ }
+ }
+ if (iclsPtr->flags & (ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ if (strcmp(Tcl_GetString(componentPtr), "itcl_hull") == 0) {
+ /* special built in itcl_hull variable */
+ ivPtr->initted = 1;
+ ivPtr->flags |= ITCL_HULL_VAR;
+ }
+ }
+ ivPtr->flags |= ITCL_COMPONENT_VAR;
+ icPtr = (ItclComponent *)ckalloc(sizeof(ItclComponent));
+ memset(icPtr, 0, sizeof(ItclComponent));
+ Tcl_InitObjHashTable(&icPtr->keptOptions);
+ icPtr->namePtr = componentPtr;
+ Tcl_IncrRefCount(icPtr->namePtr);
+ icPtr->ivPtr = ivPtr;
+ Tcl_SetHashValue(hPtr, icPtr);
+ ItclAddClassVariableDictInfo(interp, iclsPtr, ivPtr);
+ } else {
+ icPtr =Tcl_GetHashValue(hPtr);
+ }
+ *icPtrPtr = icPtr;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclHandleClassComponent()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "component" command is invoked to define a component
+ * Handles the following syntax:
+ *
+ * component
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclHandleClassComponent(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[], /* argument objects */
+ ItclComponent **icPtrPtr)
+{
+ Tcl_Obj **newObjv;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclComponent *icPtr;
+ const char *usage;
+ const char *public;
+ int inherit;
+ int haveInherit;
+ int havePublic;
+ int newObjc;
+ int haveValue;
+ int storageClass;
+ int i;
+
+ ItclShowArgs(1, "Itcl_ClassComponentCmd", objc, objv);
+ if (icPtrPtr != NULL) {
+ *icPtrPtr = NULL;
+ }
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::component called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ usage = "component ?-public <typemethod>? ?-inherit ?<flag>??";
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::extendedclass/::itcl::widget",
+ "/::itcl::widgetadaptor/::itcl::type.",
+ " Only these can have components", NULL);
+ return TCL_ERROR;
+ }
+ if ((objc < 2) && (objc > 6)) {
+ Tcl_AppendResult(interp, "wrong # args should be: ", usage, NULL);
+ return TCL_ERROR;
+ }
+ inherit = 0;
+ haveInherit = 0;
+ public = NULL;
+ havePublic = 0;
+ for (i = 2; i < objc; i++) {
+ if (strcmp(Tcl_GetString(objv[i]), "-inherit") == 0) {
+ if (haveInherit) {
+ Tcl_AppendResult(interp, "wrong syntax should be: ",
+ usage, NULL);
+ return TCL_ERROR;
+ }
+ haveValue = 0;
+ inherit = 1;
+ if (i < objc - 1) {
+ if (strcmp(Tcl_GetString(objv[i + 1]), "yes") == 0) {
+ haveValue = 1;
+ }
+ if (strcmp(Tcl_GetString(objv[i + 1]), "YES") == 0) {
+ haveValue = 1;
+ }
+ if (strcmp(Tcl_GetString(objv[i + 1]), "no") == 0) {
+ haveValue = 1;
+ inherit = 0;
+ }
+ if (strcmp(Tcl_GetString(objv[i + 1]), "NO") == 0) {
+ haveValue = 1;
+ inherit = 0;
+ }
+ }
+ if (haveValue) {
+ i++;
+ }
+ haveInherit = 1;
+ } else {
+ if (strcmp(Tcl_GetString(objv[i]), "-public") == 0) {
+ if (havePublic) {
+ Tcl_AppendResult(interp, "wrong syntax should be: ",
+ usage, NULL);
+ return TCL_ERROR;
+ }
+ havePublic = 1;
+ if (i >= objc - 1) {
+ Tcl_AppendResult(interp, "wrong syntax should be: ",
+ usage, NULL);
+ return TCL_ERROR;
+ }
+ public = Tcl_GetString(objv[i + 1]);
+ } else {
+ Tcl_AppendResult(interp, "wrong syntax should be: ",
+ usage, NULL);
+ return TCL_ERROR;
+ }
+ }
+ i++;
+ }
+ storageClass = ITCL_COMMON;
+ if (iclsPtr->flags & ITCL_ECLASS) {
+ storageClass = 0;
+ }
+ if (ItclCreateComponent(interp, iclsPtr, objv[1], storageClass,
+ &icPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (inherit) {
+ icPtr->flags |= ITCL_COMPONENT_INHERIT;
+ newObjc = 4;
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*)*newObjc);
+ newObjv[0] = Tcl_NewStringObj("delegate::option", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = Tcl_NewStringObj("to", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ newObjv[3] = objv[1];
+ Tcl_IncrRefCount(newObjv[3]);
+ if (Itcl_ClassDelegateOptionCmd(infoPtr, interp, newObjc, newObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_SetStringObj(newObjv[0] , "delegate::method", -1);
+ if (Itcl_ClassDelegateMethodCmd(infoPtr, interp, newObjc, newObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[3]);
+ ckfree((char *)newObjv);
+ }
+ if (public != NULL) {
+ icPtr->flags |= ITCL_COMPONENT_PUBLIC;
+ newObjc = 4;
+ newObjv = (Tcl_Obj **)ckalloc(sizeof(Tcl_Obj*)*newObjc);
+ newObjv[0] = Tcl_NewStringObj("delegate::method", -1);
+ Tcl_IncrRefCount(newObjv[0]);
+ newObjv[1] = Tcl_NewStringObj(public, -1);
+ Tcl_IncrRefCount(newObjv[1]);
+ newObjv[2] = Tcl_NewStringObj("to", -1);
+ Tcl_IncrRefCount(newObjv[2]);
+ newObjv[3] = objv[1];
+ Tcl_IncrRefCount(newObjv[3]);
+ ItclShowArgs(1, "COMPPUB", newObjc, newObjv);
+ if (Itcl_ClassDelegateMethodCmd(infoPtr, interp, newObjc, newObjv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ Tcl_DecrRefCount(newObjv[0]);
+ Tcl_DecrRefCount(newObjv[1]);
+ Tcl_DecrRefCount(newObjv[2]);
+ Tcl_DecrRefCount(newObjv[3]);
+ ckfree((char *)newObjv);
+ }
+ if (icPtrPtr != NULL) {
+ *icPtrPtr = icPtr;
+ }
+ ItclAddClassComponentDictInfo(interp, iclsPtr, icPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassComponentCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "component" command is invoked to define a component
+ * Handles the following syntax:
+ *
+ * component
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassComponentCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclComponent *icPtr;
+
+ return ItclHandleClassComponent(clientData, interp, objc, objv, &icPtr);
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassTypeComponentCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "typecomponent" command is invoked to define a typecomponent
+ * Handles the following syntax:
+ *
+ * component
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassTypeComponentCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclComponent *icPtr;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ClassTypeComponentCmd", objc, objv);
+ result = ItclHandleClassComponent(clientData, interp, objc, objv, &icPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ icPtr->ivPtr->flags |= ITCL_COMMON;
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclCreateDelegatedFunction()
+ *
+ * Install a delegated function for a class
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+ItclCreateDelegatedFunction(
+ Tcl_Interp *interp,
+ ItclClass *iclsPtr,
+ Tcl_Obj *methodNamePtr,
+ ItclComponent *icPtr,
+ Tcl_Obj *targetPtr,
+ Tcl_Obj *usingPtr,
+ Tcl_Obj *exceptionsPtr,
+ ItclDelegatedFunction **idmPtrPtr)
+{
+ ItclDelegatedFunction *idmPtr;
+ const char **argv;
+ int argc;
+ int isNew;
+ int i;
+
+ idmPtr = (ItclDelegatedFunction *)ckalloc(sizeof(ItclDelegatedFunction));
+ memset(idmPtr, 0, sizeof(ItclDelegatedFunction));
+ Tcl_InitObjHashTable(&idmPtr->exceptions);
+ idmPtr->namePtr = Tcl_NewStringObj(Tcl_GetString(methodNamePtr), -1);
+ Tcl_IncrRefCount(idmPtr->namePtr);
+ idmPtr->icPtr = icPtr;
+ idmPtr->asPtr = targetPtr;
+ if (idmPtr->asPtr != NULL) {
+ Tcl_IncrRefCount(idmPtr->asPtr);
+ }
+ idmPtr->usingPtr = usingPtr;
+ if (idmPtr->usingPtr != NULL) {
+ Tcl_IncrRefCount(idmPtr->usingPtr);
+ }
+ if (exceptionsPtr != NULL) {
+ if (Tcl_SplitList(interp, Tcl_GetString(exceptionsPtr), &argc, &argv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for(i = 0; i < argc; i++) {
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj(argv[i], -1);
+ Tcl_CreateHashEntry(&idmPtr->exceptions, (char *)objPtr,
+ &isNew);
+ }
+ ckfree((char *) argv);
+ }
+ if (idmPtrPtr != NULL) {
+ *idmPtrPtr = idmPtr;
+ }
+ ItclAddClassDelegatedFunctionDictInfo(interp, iclsPtr, idmPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_HandleDelegateMethodCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "delegate method" command is invoked to define a
+ * Handles the following syntax:
+ *
+ * delegate method
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_HandleDelegateMethodCmd(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclObject *ioPtr, /* != NULL for ::itcl::adddelegatedmethod
+ otherwise NULL */
+ ItclClass *iclsPtr, /* != NULL for delegate method otherwise NULL */
+ ItclDelegatedFunction **idmPtrPtr,
+ /* where to return idoPtr */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *methodNamePtr;
+ Tcl_Obj *componentPtr;
+ Tcl_Obj *targetPtr;
+ Tcl_Obj *usingPtr;
+ Tcl_Obj *exceptionsPtr;
+ Tcl_HashEntry *hPtr;
+ ItclClass *iclsPtr2;
+ ItclComponent *icPtr;
+ ItclHierIter hier;
+ const char *usageStr;
+ const char *methodName;
+ const char *component;
+ const char *token;
+ int result;
+ int i;
+ int foundOpt;
+
+ ItclShowArgs(1, "Itcl_HandleDelegateMethodCmd", objc, objv);
+ usageStr = "delegate method <methodName> to <componentName> ?as <targetName>?\n\
+delegate method <methodName> ?to <componentName>? using <pattern>\n\
+delegate method * ?to <componentName>? ?using <pattern>? ?except <methods>?";
+ if (objc < 4) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ componentPtr = NULL;
+ icPtr = NULL;
+ methodName = Tcl_GetString(objv[1]);
+ component = NULL;
+ targetPtr = NULL;
+ usingPtr = NULL;
+ exceptionsPtr = NULL;
+ for(i=2;i<objc;i++) {
+ token = Tcl_GetString(objv[i]);
+ if (i+1 == objc) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ foundOpt = 0;
+ if (strcmp(token, "to") == 0) {
+ i++;
+ component = Tcl_GetString(objv[i]);
+ componentPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "as") == 0) {
+ i++;
+ targetPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "except") == 0) {
+ i++;
+ exceptionsPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "using") == 0) {
+ i++;
+ usingPtr = objv[i];
+ foundOpt++;
+ }
+ if (!foundOpt) {
+ Tcl_AppendResult(interp, "bad option \"", token, "\" should be ",
+ usageStr, NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((exceptionsPtr != NULL) && (*methodName != '*')) {
+ Tcl_AppendResult(interp,
+ "can only specify \"except\" with \"delegate method *\"", NULL);
+ return TCL_ERROR;
+ }
+ if ((component == NULL) && (usingPtr == NULL)) {
+ Tcl_AppendResult(interp, "missing to should be: ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ if ((*methodName == '*') && (targetPtr != NULL)) {
+ Tcl_AppendResult(interp,
+ "cannot specify \"as\" with \"delegate method *\"", NULL);
+ return TCL_ERROR;
+ }
+ /* check for already delegated */
+ methodNamePtr = Tcl_NewStringObj(methodName, -1);
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectDelegatedFunctions, (char *)
+ methodNamePtr);
+ } else {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions, (char *)
+ methodNamePtr);
+ }
+
+ hPtr = NULL;
+ if (ioPtr != NULL) {
+ if (componentPtr != NULL) {
+ Itcl_InitHierIter(&hier, ioPtr->iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components,
+ (char *)componentPtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ }
+ } else {
+ if (componentPtr != NULL) {
+ iclsPtr2 = iclsPtr;
+ Itcl_InitHierIter(&hier, iclsPtr2);
+ while ((iclsPtr2 = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->components,
+ (char *)componentPtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ }
+ }
+ if (hPtr == NULL) {
+ if (componentPtr != NULL) {
+ if (ItclCreateComponent(interp, iclsPtr, componentPtr,
+ ITCL_COMMON, &icPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components,
+ (char *)componentPtr);
+ }
+ }
+ if (hPtr != NULL) {
+ icPtr = Tcl_GetHashValue(hPtr);
+ }
+ if (*methodName != '*') {
+ /* FIXME !!! */
+ /* check for locally defined method */
+ hPtr = NULL;
+ if (ioPtr != NULL) {
+ } else {
+ /* FIXME !! have to check the hierarchy !! */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->functions,
+ (char *)methodNamePtr);
+
+ }
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "method \"", methodName,
+ "\" has been defined locally", NULL);
+ result = TCL_ERROR;
+ goto errorOut;
+ }
+ }
+ result = ItclCreateDelegatedFunction(interp, iclsPtr, methodNamePtr, icPtr,
+ targetPtr, usingPtr, exceptionsPtr, idmPtrPtr);
+ (*idmPtrPtr)->flags |= ITCL_METHOD;
+errorOut:
+ Tcl_DecrRefCount(methodNamePtr);
+ return result;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassDelegateMethodCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "delegate method" command is invoked to define a
+ * Handles the following syntax:
+ *
+ * delegate method
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassDelegateMethodCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedFunction *idmPtr;
+ int isNew;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ClassDelegateMethodCmd", objc, objv);
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::delegatemethod called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/::itcl::type",
+ "/::itcl::extendedclass.",
+ " Only these can delegate methods", NULL);
+ return TCL_ERROR;
+ }
+ result = Itcl_HandleDelegateMethodCmd(interp, NULL, iclsPtr, &idmPtr, objc,
+ objv);
+ if (result != TCL_OK) {
+ return result;
+ }
+ idmPtr->flags |= ITCL_METHOD;
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)idmPtr->namePtr, &isNew);
+ Tcl_SetHashValue(hPtr, idmPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_HandleDelegateOptionCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "delegate option" command is invoked to define a delegated option
+ * or if ::itcl::adddelegatedoption is called with an itcl object
+ * Handles the following syntax:
+ *
+ * delegate option ...
+ *
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_HandleDelegateOptionCmd(
+ Tcl_Interp *interp, /* current interpreter */
+ ItclObject *ioPtr, /* != NULL for ::itcl::adddelgatedoption
+ otherwise NULL */
+ ItclClass *iclsPtr, /* != NULL for delegate option otherwise NULL */
+ ItclDelegatedOption **idoPtrPtr,
+ /* where to return idoPtr */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+
+{
+ Tcl_Obj *allOptionNamePtr;
+ Tcl_Obj *optionNamePtr;
+ Tcl_Obj *componentPtr;
+ Tcl_Obj *targetPtr;
+ Tcl_Obj *exceptionsPtr;
+ Tcl_Obj *resourceNamePtr;
+ Tcl_Obj *classNamePtr;
+ Tcl_HashEntry *hPtr;
+ ItclComponent *icPtr;
+ ItclClass *iclsPtr2;
+ ItclDelegatedOption *idoPtr;
+ ItclHierIter hier;
+ const char *usageStr;
+ const char *option;
+ const char *component;
+ const char *token;
+ const char **argv;
+ int foundOpt;
+ int argc;
+ int isStarOption;
+ int isNew;
+ int i;
+ const char *cp;
+
+ ItclShowArgs(1, "Itcl_HandleDelegatedOptionCmd", objc, objv);
+ usageStr = "<optionDef> to <targetDef> ?as <script>? ?except <script>?";
+ if (objc < 4) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ componentPtr = NULL;
+ icPtr = NULL;
+ isStarOption = 0;
+ token = Tcl_GetString(objv[1]);
+ if (Tcl_SplitList(interp, (const char *)token, &argc, &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ option = argv[0];
+ if (strcmp(option, "*") == 0) {
+ isStarOption = 1;
+ }
+ if ((argc < 1) || (isStarOption && (argc > 1))) {
+ Tcl_AppendResult(interp, "<optionDef> must be either \"*\" or ",
+ "\"<optionName> <resourceName> <className>\"", NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ if (isStarOption && (argc > 3)) {
+ Tcl_AppendResult(interp, "<optionDef> syntax should be: ",
+ "\"<optionName> <resourceName> <className>\"", NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ if ((*option != '-') && !isStarOption) {
+ Tcl_AppendResult(interp, "bad delegated option name \"", option,
+ "\", options must start with a \"-\"", NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ /*
+ * Make sure that the variable name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ if (strstr(option, "::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option name \"", option,
+ "\", option names must not contain \"::\"", (char*)NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ if (strstr(option, " ")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad option name \"", option,
+ "\", option names must not contain \" \"", (char*)NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ cp = option;
+ while (*cp) {
+ if (isupper(UCHAR(*cp))) {
+ Tcl_AppendResult(interp, "bad option name \"", option, "\" ",
+ ", options must not contain uppercase characters", NULL);
+ ckfree((char *)argv);
+ return TCL_ERROR;
+ }
+ cp++;
+ }
+ optionNamePtr = Tcl_NewStringObj(option, -1);
+ Tcl_IncrRefCount(optionNamePtr);
+ resourceNamePtr = NULL;
+ classNamePtr = NULL;
+ if (argc > 1) {
+ resourceNamePtr = Tcl_NewStringObj(argv[1], -1);
+ Tcl_IncrRefCount(resourceNamePtr);
+ }
+ if (argc > 2) {
+ classNamePtr = Tcl_NewStringObj(argv[2], -1);
+ }
+ component = NULL;
+ targetPtr = NULL;
+ exceptionsPtr = NULL;
+ for(i=2;i<objc;i++) {
+ token = Tcl_GetString(objv[i]);
+ if (i+1 == objc) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ goto errorOut1;
+ }
+ foundOpt = 0;
+ if (strcmp(token, "to") == 0) {
+ i++;
+ component = Tcl_GetString(objv[i]);
+ componentPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "as") == 0) {
+ i++;
+ targetPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "except") == 0) {
+ i++;
+ exceptionsPtr = objv[i];
+ foundOpt++;
+ }
+ if (!foundOpt) {
+ Tcl_AppendResult(interp, "bad option \"", token, "\" should be ",
+ usageStr, NULL);
+ goto errorOut1;
+ }
+ }
+ if (component == NULL) {
+ Tcl_AppendResult(interp, "missing to should be: ", usageStr, NULL);
+ goto errorOut1;
+ }
+ if ((*option == '*') && (targetPtr != NULL)) {
+ Tcl_AppendResult(interp,
+ "cannot specify \"as\" with \"delegate option *\"", NULL);
+ goto errorOut1;
+ }
+ /* check for already delegated */
+ allOptionNamePtr = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(allOptionNamePtr);
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectDelegatedOptions, (char *)
+ allOptionNamePtr);
+ } else {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedOptions, (char *)
+ allOptionNamePtr);
+ }
+ Tcl_DecrRefCount(allOptionNamePtr);
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "option \"", option,
+ "\" is already delegated", NULL);
+ goto errorOut1;
+ }
+
+ if (ioPtr != NULL) {
+ Itcl_InitHierIter(&hier, ioPtr->iclsPtr);
+ while ((iclsPtr = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components,
+ (char *)componentPtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ } else {
+ Itcl_InitHierIter(&hier, iclsPtr);
+ while ((iclsPtr2 = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->components,
+ (char *)componentPtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ Itcl_DeleteHierIter(&hier);
+ }
+ if (hPtr == NULL) {
+ if (componentPtr != NULL) {
+ if (ItclCreateComponent(interp, iclsPtr, componentPtr,
+ ITCL_COMMON, &icPtr) != TCL_OK) {
+ goto errorOut1;
+ }
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components,
+ (char *)componentPtr);
+ }
+ }
+ if (hPtr != NULL) {
+ icPtr = Tcl_GetHashValue(hPtr);
+ }
+ if (*option != '*') {
+ /* FIXME !!! */
+ /* check for valid option name */
+ if (ioPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&ioPtr->objectOptions,
+ (char *)optionNamePtr);
+ } else {
+ Itcl_InitHierIter(&hier, iclsPtr);
+ while ((iclsPtr2 = Itcl_AdvanceHierIter(&hier)) != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr2->options,
+ (char *)optionNamePtr);
+ if (hPtr != NULL) {
+ break;
+ }
+ }
+ }
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "option \"", option,
+ "\" has been defined locally", NULL);
+ goto errorOut1;
+ return TCL_ERROR;
+ }
+ }
+ idoPtr = (ItclDelegatedOption *)ckalloc(sizeof(ItclDelegatedOption));
+ memset(idoPtr, 0, sizeof(ItclDelegatedOption));
+ Tcl_InitObjHashTable(&idoPtr->exceptions);
+ if (*option != '*') {
+ if (targetPtr == NULL) {
+ targetPtr = optionNamePtr;
+ }
+ if (resourceNamePtr == NULL) {
+ resourceNamePtr = Tcl_NewStringObj(option+1, -1);
+ Tcl_IncrRefCount(resourceNamePtr);
+ }
+ if (classNamePtr == NULL) {
+ classNamePtr = ItclCapitalize(Tcl_GetString(resourceNamePtr));
+ }
+ idoPtr->namePtr = optionNamePtr;
+ idoPtr->resourceNamePtr = resourceNamePtr;
+ idoPtr->classNamePtr = Tcl_NewStringObj(
+ Tcl_GetString(classNamePtr), -1);
+ Tcl_IncrRefCount(idoPtr->classNamePtr);
+ Tcl_DecrRefCount(classNamePtr);
+
+ } else {
+ idoPtr->namePtr = optionNamePtr;
+ }
+ Itcl_PreserveData(idoPtr);
+ Itcl_EventuallyFree((ClientData)idoPtr, ItclDeleteDelegatedOption);
+ idoPtr->icPtr = icPtr;
+ idoPtr->asPtr = targetPtr;
+ if (idoPtr->asPtr != NULL) {
+ Tcl_IncrRefCount(idoPtr->asPtr);
+ }
+ if (exceptionsPtr != NULL) {
+ ckfree((char *)argv);
+ argv = NULL;
+ if (Tcl_SplitList(interp, Tcl_GetString(exceptionsPtr), &argc, &argv)
+ != TCL_OK) {
+ goto errorOut2;
+ }
+ for(i=0;i<argc;i++) {
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj(argv[i], -1);
+ hPtr = Tcl_CreateHashEntry(&idoPtr->exceptions, (char *)objPtr,
+ &isNew);
+ }
+ }
+ if (idoPtrPtr != NULL) {
+ *idoPtrPtr = idoPtr;
+ }
+ ckfree((char *)argv);
+ ItclAddDelegatedOptionDictInfo(interp, iclsPtr, idoPtr);
+ return TCL_OK;
+errorOut2:
+ /* FIXME need to decr additional refCount's !! */
+errorOut1:
+ Tcl_DecrRefCount(optionNamePtr);
+ if (resourceNamePtr != NULL) {
+ Tcl_DecrRefCount(resourceNamePtr);
+ }
+ if (classNamePtr != NULL) {
+ Tcl_DecrRefCount(classNamePtr);
+ }
+ if (argv) {
+ ckfree((char *)argv);
+ }
+ return TCL_ERROR;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassDelegateOptionCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "delegate option" command is invoked to define a
+ * Handles the following syntax:
+ *
+ * delegate option
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassDelegateOptionCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclDelegatedOption *idoPtr;
+ const char *usageStr;
+ int isNew;
+ int result;
+
+ ItclShowArgs(1, "Itcl_ClassDelegateOptionCmd", objc, objv);
+ usageStr = "<optionDef> to <targetDef> ?as <script>? ?except <script>?";
+ if (objc < 4) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ infoPtr = (ItclObjectInfo *)clientData;
+ iclsPtr = (ItclClass *)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::delegateoption called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/::itcl::type",
+ "/::itcl::extendedclass.",
+ " Only these can delegate options", NULL);
+ return TCL_ERROR;
+ }
+ result = Itcl_HandleDelegateOptionCmd(interp, NULL, iclsPtr, &idoPtr,
+ objc, objv);
+ if (result != TCL_OK) {
+ return result;
+ }
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->delegatedOptions,
+ (char *)idoPtr->namePtr, &isNew);
+ Tcl_SetHashValue(hPtr, idoPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassDelegateTypeMethodCmd()
+ *
+ * Invoked by Tcl during the parsing of a class definition whenever
+ * the "delegate typemethod" command is invoked to define a
+ * Handles the following syntax:
+ *
+ * delegate typemethod
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassDelegateTypeMethodCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *typeMethodNamePtr;
+ Tcl_Obj *componentPtr;
+ Tcl_Obj *targetPtr;
+ Tcl_Obj *usingPtr;
+ Tcl_Obj *exceptionsPtr;
+ Tcl_HashEntry *hPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclComponent *icPtr;
+ ItclDelegatedFunction *idmPtr;
+ const char *usageStr;
+ const char *typeMethodName;
+ const char *component;
+ const char *token;
+ const char **argv;
+ int foundOpt;
+ int argc;
+ int isNew;
+ int i;
+
+ ItclShowArgs(1, "Itcl_ClassDelegateTypeMethodCmd", objc, objv);
+ usageStr = "delegate typemethod <typeMethodName> to <componentName> ?as <targetName>?\n\
+delegate typemethod <typeMethodName> ?to <componentName>? using <pattern>\n\
+delegate typemethod * ?to <componentName>? ?using <pattern>? ?except <typemethods>?";
+ componentPtr = NULL;
+ icPtr = NULL;
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::delegatetypemethod called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/::itcl::type.",
+ " Only these can delegate typemethods", NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc < 4) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ typeMethodName = Tcl_GetString(objv[1]);
+ /* check if typeMethodName has been delegated */
+ component = NULL;
+ targetPtr = NULL;
+ usingPtr = NULL;
+ exceptionsPtr = NULL;
+ for(i=2;i<objc;i++) {
+ token = Tcl_GetString(objv[i]);
+ if (i+1 == objc) {
+ Tcl_AppendResult(interp, "wrong # args should be ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ foundOpt = 0;
+ if (strcmp(token, "to") == 0) {
+ i++;
+ component = Tcl_GetString(objv[i]);
+ componentPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "as") == 0) {
+ i++;
+ targetPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "except") == 0) {
+ i++;
+ exceptionsPtr = objv[i];
+ foundOpt++;
+ }
+ if (strcmp(token, "using") == 0) {
+ i++;
+ usingPtr = objv[i];
+ foundOpt++;
+ }
+ if (!foundOpt) {
+ Tcl_AppendResult(interp, "bad option \"", token, "\" should be ",
+ usageStr, NULL);
+ return TCL_ERROR;
+ }
+ }
+ if ((component == NULL) && (usingPtr == NULL)) {
+ Tcl_AppendResult(interp, "missing to should be: ", usageStr, NULL);
+ return TCL_ERROR;
+ }
+ if ((*typeMethodName == '*') && (targetPtr != NULL)) {
+ Tcl_AppendResult(interp,
+ "cannot specify \"as\" with \"delegate typemethod *\"", NULL);
+ return TCL_ERROR;
+ }
+ if (componentPtr != NULL) {
+ hPtr = Tcl_FindHashEntry(&iclsPtr->components, (char *)componentPtr);
+ if (hPtr == NULL) {
+ if (ItclCreateComponent(interp, iclsPtr, componentPtr,
+ ITCL_COMMON, &icPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ } else {
+ icPtr = Tcl_GetHashValue(hPtr);
+ }
+ } else {
+ icPtr = NULL;
+ }
+ idmPtr = (ItclDelegatedFunction *)ckalloc(sizeof(ItclDelegatedFunction));
+ memset(idmPtr, 0, sizeof(ItclDelegatedFunction));
+ Tcl_InitObjHashTable(&idmPtr->exceptions);
+ typeMethodNamePtr = Tcl_NewStringObj(typeMethodName, -1);
+ if (*typeMethodName != '*') {
+ /* FIXME !!! */
+ /* check for locally defined typemethod */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->functions,
+ (char *)typeMethodNamePtr);
+ if (hPtr != NULL) {
+ Tcl_AppendResult(interp, "Error in \"delegate typemethod ",
+ typeMethodName, "...\", \"", typeMethodName,
+ "\" has been defined locally.", NULL);
+ Tcl_DeleteHashTable(&idmPtr->exceptions);
+ ckfree((char *)idmPtr);
+ Tcl_DecrRefCount(typeMethodNamePtr);
+ return TCL_ERROR;
+ }
+ idmPtr->namePtr = Tcl_NewStringObj(
+ Tcl_GetString(typeMethodNamePtr), -1);
+ Tcl_IncrRefCount(idmPtr->namePtr);
+ } else {
+ Tcl_DecrRefCount(typeMethodNamePtr);
+ typeMethodNamePtr = Tcl_NewStringObj("*", -1);
+ Tcl_IncrRefCount(typeMethodNamePtr);
+ idmPtr->namePtr = typeMethodNamePtr;
+ Tcl_IncrRefCount(typeMethodNamePtr);
+ if (exceptionsPtr != NULL) {
+ if (Tcl_SplitList(interp, Tcl_GetString(exceptionsPtr),
+ &argc, &argv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ for(i = 0; i < argc; i++) {
+ Tcl_Obj *objPtr;
+ objPtr = Tcl_NewStringObj(argv[i], -1);
+ hPtr = Tcl_CreateHashEntry(&idmPtr->exceptions, (char *)objPtr,
+ &isNew);
+ }
+ ckfree((char *) argv);
+ }
+ }
+ idmPtr->icPtr = icPtr;
+ idmPtr->asPtr = targetPtr;
+ if (idmPtr->asPtr != NULL) {
+ Tcl_IncrRefCount(idmPtr->asPtr);
+ }
+ idmPtr->usingPtr = usingPtr;
+ if (idmPtr->usingPtr != NULL) {
+ Tcl_IncrRefCount(idmPtr->usingPtr);
+ }
+ idmPtr->flags = ITCL_COMMON|ITCL_TYPE_METHOD;
+ hPtr = Tcl_CreateHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)idmPtr->namePtr, &isNew);
+ if (!isNew) {
+ ItclDeleteDelegatedFunction((ItclDelegatedFunction *)
+ Tcl_GetHashValue(hPtr));
+ }
+ Tcl_SetHashValue(hPtr, idmPtr);
+ Tcl_DecrRefCount(typeMethodNamePtr);
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassForwardCmd()
+ *
+ * Used similar to interp alias to forward the call of a method
+ * to another method within the class
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_ClassForwardCmd(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *prefixObj;
+ Tcl_Method mPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+
+ ItclShowArgs(1, "Itcl_ClassForwardCmd", objc, objv);
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::forward called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/",
+ "::itcl::type/::itcl::extendedclass.",
+ " Only these can forward", NULL);
+ return TCL_ERROR;
+ }
+ if (objc < 3) {
+ Tcl_WrongNumArgs(interp, 1, objv, "<forwardName> <targetName> ?<arg> ...?");
+ return TCL_ERROR;
+ }
+ prefixObj = Tcl_NewListObj(objc-2, objv+2);
+ mPtr = Itcl_NewForwardClassMethod(interp, iclsPtr->clsPtr, 1,
+ objv[1], prefixObj);
+ if (mPtr == NULL) {
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassMethodVariableCmd()
+ *
+ * Used to similar to iterp alias to forward the call of a method
+ * to another method within the class
+ *
+ * Returns TCL_OK/TCL_ERROR to indicate success/failure.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static int
+Itcl_ClassMethodVariableCmd(
+ ClientData clientData, /* unused */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Obj *namePtr;
+ Tcl_Obj *defaultPtr;
+ Tcl_Obj *callbackPtr;
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclVariable *ivPtr;
+ ItclMemberFunc *imPtr;
+ ItclMethodVariable *imvPtr;
+ const char *token;
+ const char *usageStr;
+ int i;
+ int foundOpt;
+ int result;
+ Tcl_Obj *objPtr;
+
+ ItclShowArgs(1, "Itcl_ClassMethodVariableCmd", objc, objv);
+ infoPtr = (ItclObjectInfo*)clientData;
+ iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::methodvariable called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "\"", Tcl_GetString(iclsPtr->namePtr),
+ " is no ::itcl::widget/::itcl::widgetadaptor/",
+ "::itcl::type/::itcl::extendedclass.",
+ " Only these can have methodvariables", NULL);
+ return TCL_ERROR;
+ }
+ usageStr = "<name> ?-default value? ?-callback script?";
+ if ((objc < 2) || (objc > 6)) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * Make sure that the variable name does not contain anything
+ * goofy like a "::" scope qualifier.
+ */
+ namePtr = objv[1];
+ if (strstr(Tcl_GetString(namePtr), "::")) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "bad variable name \"", Tcl_GetString(namePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ defaultPtr = NULL;
+ callbackPtr = NULL;
+ for (i=2;i<objc;i++) {
+ foundOpt = 0;
+ token = Tcl_GetString(objv[i]);
+ if (strcmp(token, "-default") == 0) {
+ if (i+1 > objc) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+ defaultPtr = objv[i+1];
+ i++;
+ foundOpt++;
+ }
+ if (strcmp(token, "-callback") == 0) {
+ if (i+1 > objc) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+ callbackPtr = objv[i+1];
+ i++;
+ foundOpt++;
+ }
+ if (!foundOpt) {
+ Tcl_WrongNumArgs(interp, 1, objv, usageStr);
+ return TCL_ERROR;
+ }
+ }
+
+ if (Itcl_CreateVariable(interp, iclsPtr, namePtr,
+ Tcl_GetString(defaultPtr), NULL, &ivPtr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ iclsPtr->numVariables++;
+ result = Itcl_CreateMethodVariable(interp, iclsPtr, namePtr, defaultPtr,
+ callbackPtr, &imvPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ objPtr = Tcl_NewStringObj("@itcl-builtin-setget ", -1);
+ Tcl_AppendToObj(objPtr, Tcl_GetString(namePtr), -1);
+ Tcl_AppendToObj(objPtr, " ", 1);
+ result = ItclCreateMethod(interp, iclsPtr, namePtr, "args",
+ Tcl_GetString(objPtr), &imPtr);
+ if (result != TCL_OK) {
+ return result;
+ }
+ /* install a write trace if callbackPtr != NULL */
+ /* FIXME to be done */
+ ItclAddClassVariableDictInfo(interp, iclsPtr, ivPtr);
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassTypeConstructorCmd()
+ *
+ * Invoked by Tcl during the parsing of a type class definition whenever
+ * the "typeconstructor" command is invoked to define the typeconstructor
+ * for an object. Handles the following syntax:
+ *
+ * typeconstructor <body>
+ *
+ * ------------------------------------------------------------------------
+ */
+static int
+Itcl_ClassTypeConstructorCmd(
+ ClientData clientData, /* info for all known objects */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+ Tcl_Obj *namePtr;
+
+ ItclShowArgs(1, "Itcl_ClassTypeConstructorCmd", objc, objv);
+
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "Error: ::itcl::parser::typeconstructor called from",
+ " not within a class", NULL);
+ return TCL_ERROR;
+ }
+ if (iclsPtr->flags & ITCL_CLASS) {
+ Tcl_AppendResult(interp, "a \"class\" cannot have a typeconstructor",
+ NULL);
+ return TCL_ERROR;
+ }
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "body");
+ return TCL_ERROR;
+ }
+
+ namePtr = objv[0];
+ if (iclsPtr->typeConstructorPtr != NULL) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "\"", Tcl_GetString(namePtr), "\" already defined in class \"",
+ Tcl_GetString(iclsPtr->fullNamePtr), "\"",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+
+ iclsPtr->typeConstructorPtr = Tcl_NewStringObj(Tcl_GetString(objv[1]), -1);
+ Tcl_IncrRefCount(iclsPtr->typeConstructorPtr);
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve.c
new file mode 100644
index 0000000..c22ced2
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve.c
@@ -0,0 +1,697 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * These procedures handle command and variable resolution
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+/*
+ * This structure is a subclass of Tcl_ResolvedVarInfo that contains the
+ * ItclVarLookup info needed at runtime.
+ */
+typedef struct ItclResolvedVarInfo {
+ Tcl_ResolvedVarInfo vinfo; /* This must be the first element. */
+ ItclVarLookup *vlookup; /* Pointer to lookup info. */
+} ItclResolvedVarInfo;
+
+static Tcl_Var ItclClassRuntimeVarResolver(
+ Tcl_Interp *interp, Tcl_ResolvedVarInfo *vinfoPtr);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCmdResolver()
+ *
+ * Used by the class namespaces to handle name resolution for all
+ * commands. This procedure looks for references to class methods
+ * and procs, and returns TCL_OK along with the appropriate Tcl
+ * command in the rPtr argument. If a particular command is private,
+ * this procedure returns TCL_ERROR and access to the command is
+ * denied. If a command is not recognized, this procedure returns
+ * TCL_CONTINUE, and lookup continues via the normal Tcl name
+ * resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCmdResolver(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the command being accessed */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ int flags, /* TCL_LEAVE_ERR_MSG => leave error messages
+ * in interp if anything goes wrong */
+ Tcl_Command *rPtr) /* returns: resolved command */
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_Obj *objPtr;
+ Tcl_Obj *namePtr;
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ ItclMemberFunc *imPtr;
+ int inOptionHandling;
+ int isCmdDeleted;
+
+ if ((name[0] == 't') && (strcmp(name, "this") == 0)) {
+ return TCL_CONTINUE;
+ }
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ /*
+ * If the command is a member function
+ */
+ imPtr = NULL;
+ objPtr = Tcl_NewStringObj(name, -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ if (hPtr == NULL) {
+ ItclCmdLookup *clookup;
+ if ((iclsPtr->flags & ITCL_ECLASS)) {
+ namePtr = Tcl_NewStringObj(name, -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->delegatedFunctions,
+ (char *)namePtr);
+ if (hPtr != NULL) {
+ objPtr = Tcl_NewStringObj("unknown", -1);
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveCmds, (char *)objPtr);
+ Tcl_DecrRefCount(objPtr);
+ }
+ Tcl_DecrRefCount(namePtr);
+ }
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ } else {
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(hPtr);
+ imPtr = clookup->imPtr;
+ }
+
+ if (iclsPtr->flags & (ITCL_TYPE|ITCL_WIDGET|ITCL_WIDGETADAPTOR)) {
+ /* FIXME check if called from an (instance) method (not from a typemethod) and only then error */
+ int isOk = 0;
+ if (strcmp(name, "info") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "mytypemethod") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "myproc") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "mymethod") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "mytypevar") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "myvar") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "itcl_hull") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "callinstance") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "getinstancevar") == 0) {
+ isOk = 1;
+ }
+ if (strcmp(name, "installcomponent") == 0) {
+ isOk = 1;
+ }
+ if (! isOk) {
+ if ((imPtr->flags & ITCL_TYPE_METHOD) != 0) {
+ Tcl_AppendResult(interp, "invalid command name \"", name,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ inOptionHandling = imPtr->iclsPtr->infoPtr->inOptionHandling;
+ if (((imPtr->flags & ITCL_COMMON) == 0) && !inOptionHandling) {
+ /* a method cannot be called directly in ITCL_TYPE
+ * so look, if there is a corresponding proc in the
+ * namespace one level up (i.e. for example ::). If yes
+ * use that.
+ */
+ Tcl_Namespace *nsPtr2;
+ Tcl_Command cmdPtr;
+ nsPtr2 = Itcl_GetUplevelNamespace(interp, 1);
+ cmdPtr = NULL;
+ if (nsPtr != nsPtr2) {
+ cmdPtr = Tcl_FindCommand(interp, name, nsPtr2, 0);
+ }
+ if (cmdPtr != NULL) {
+ *rPtr = cmdPtr;
+ return TCL_OK;
+ }
+ Tcl_AppendResult(interp, "invalid command name \"", name,
+ "\"", NULL);
+ return TCL_ERROR;
+ }
+ }
+ }
+ /*
+ * Looks like we found an accessible member function.
+ *
+ * TRICKY NOTE: Check to make sure that the command handle
+ * is still valid. If someone has deleted or renamed the
+ * command, it may not be. This is just the time to catch
+ * it--as it is being resolved again by the compiler.
+ */
+
+ /*
+ * The following #if is needed so itcl can be compiled with
+ * all versions of Tcl. The integer "deleted" was renamed to
+ * "flags" in tcl8.4a2. This #if is also found in itcl_ensemble.c .
+ * We're using a runtime check with itclCompatFlags to adjust for
+ * the behavior of this change, too.
+ *
+ */
+/* FIXME !!! */
+isCmdDeleted = 0;
+/* isCmdDeleted = (!imPtr->accessCmd || imPtr->accessCmd->flags); */
+
+ if (isCmdDeleted) {
+ imPtr->accessCmd = NULL;
+
+ if ((flags & TCL_LEAVE_ERR_MSG) != 0) {
+ Tcl_AppendResult(interp,
+ "can't access \"", name, "\": deleted or redefined\n",
+ "(use the \"body\" command to redefine methods/procs)",
+ (char*)NULL);
+ }
+ return TCL_ERROR; /* disallow access! */
+ }
+ *rPtr = imPtr->accessCmd;
+ return TCL_OK;
+}
+
+/* #define VAR_DEBUG */
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassVarResolver()
+ *
+ * Used by the class namespaces to handle name resolution for runtime
+ * variable accesses. This procedure looks for references to both
+ * common variables and instance variables at runtime. It is used as
+ * a second line of defense, to handle references that could not be
+ * resolved as compiled locals.
+ *
+ * If a variable is found, this procedure returns TCL_OK along with
+ * the appropriate Tcl variable in the rPtr argument. If a particular
+ * variable is private, this procedure returns TCL_ERROR and access
+ * to the variable is denied. If a variable is not recognized, this
+ * procedure returns TCL_CONTINUE, and lookup continues via the normal
+ * Tcl name resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassVarResolver(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ int flags, /* TCL_LEAVE_ERR_MSG => leave error messages
+ * in interp if anything goes wrong */
+ Tcl_Var *rPtr) /* returns: resolved variable */
+{
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclObject *contextIoPtr;
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+
+ contextIoPtr = NULL;
+ /*
+ * If this is a global variable, handle it in the usual
+ * Tcl manner.
+ */
+ if (flags & TCL_GLOBAL_ONLY) {
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * See if this is a formal parameter in the current proc scope.
+ * If so, that variable has precedence.
+ */
+ if ((strstr(name,"::") == NULL) &&
+ Itcl_IsCallFrameArgument(interp, name)) {
+ return TCL_CONTINUE;
+ }
+
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * See if the variable is a known data member and accessible.
+ */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, name);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ if (!vlookup->accessible) {
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * If this is a common data member, then its variable
+ * is easy to find. Return it directly.
+ */
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ *rPtr = Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ }
+
+ /*
+ * If this is an instance variable, then we have to
+ * find the object context,
+ */
+ if (TCL_ERROR == Itcl_GetContext(interp, &iclsPtr, &contextIoPtr)
+ || (contextIoPtr == NULL)) {
+ return TCL_CONTINUE;
+ }
+ /* Check that the object hasn't already been destroyed. */
+ hPtr = Tcl_FindHashEntry(&infoPtr->objects, (char *)contextIoPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ if (contextIoPtr->iclsPtr != vlookup->ivPtr->iclsPtr) {
+ if (strcmp(Tcl_GetString(vlookup->ivPtr->namePtr), "this") == 0) {
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->iclsPtr->resolveVars,
+ Tcl_GetString(vlookup->ivPtr->namePtr));
+
+ if (hPtr != NULL) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ }
+ }
+ }
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectVariables,
+ (char *)vlookup->ivPtr);
+
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ if (strcmp(name, "this") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ if (vlookup->ivPtr->iclsPtr->nsPtr == NULL) {
+ /* deletion of class is running */
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetCurrentNamespace(interp)->fullName, -1);
+ } else {
+ Tcl_DStringAppend(&buffer,
+ vlookup->ivPtr->iclsPtr->nsPtr->fullName, -1);
+ }
+ Tcl_DStringAppend(&buffer, "::this", 6);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ if (varPtr != NULL) {
+ *rPtr = varPtr;
+ return TCL_OK;
+ }
+ }
+ if (strcmp(name, "itcl_options") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ Tcl_DStringAppend(&buffer, "::itcl_options", -1);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ if (varPtr != NULL) {
+ *rPtr = varPtr;
+ return TCL_OK;
+ }
+ }
+ if (strcmp(name, "itcl_option_components") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ Tcl_DStringAppend(&buffer, "::itcl_option_components", -1);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer), NULL, 0);
+ Tcl_DStringFree(&buffer);
+ if (varPtr != NULL) {
+ *rPtr = varPtr;
+ return TCL_OK;
+ }
+ }
+ if (hPtr != NULL) {
+ *rPtr = Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ return TCL_CONTINUE;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCompiledVarResolver()
+ *
+ * Used by the class namespaces to handle name resolution for compile
+ * time variable accesses. This procedure looks for references to
+ * both common variables and instance variables at compile time. If
+ * the variables are found, they are characterized in a generic way
+ * by their ItclVarLookup record. At runtime, Tcl constructs the
+ * compiled local variables by calling ItclClassRuntimeVarResolver.
+ *
+ * If a variable is found, this procedure returns TCL_OK along with
+ * information about the variable in the rPtr argument. If a particular
+ * variable is private, this procedure returns TCL_ERROR and access
+ * to the variable is denied. If a variable is not recognized, this
+ * procedure returns TCL_CONTINUE, and lookup continues via the normal
+ * Tcl name resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCompiledVarResolver(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ int length, /* number of characters in name */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ Tcl_ResolvedVarInfo **rPtr) /* returns: info that makes it possible to
+ * resolve the variable at runtime */
+{
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+ char *buffer;
+ char storage[64];
+
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ /*
+ * Copy the name to local storage so we can NULL terminate it.
+ * If the name is long, allocate extra space for it.
+ */
+ if ((unsigned int)length < sizeof(storage)) {
+ buffer = storage;
+ } else {
+ buffer = (char*)ckalloc((unsigned)(length+1));
+ }
+ memcpy((void*)buffer, (void*)name, (size_t)length);
+ buffer[length] = '\0';
+
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, buffer);
+
+ if (buffer != storage) {
+ ckfree(buffer);
+ }
+
+ /*
+ * If the name is not found, or if it is inaccessible,
+ * continue on with the normal Tcl name resolution rules.
+ */
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ if (!vlookup->accessible) {
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * Return the ItclVarLookup record. At runtime, Tcl will
+ * call ItclClassRuntimeVarResolver with this record, to
+ * plug in the appropriate variable for the current object
+ * context.
+ */
+ (*rPtr) = (Tcl_ResolvedVarInfo *) ckalloc(sizeof(ItclResolvedVarInfo));
+ (*rPtr)->fetchProc = ItclClassRuntimeVarResolver;
+ (*rPtr)->deleteProc = NULL;
+ ((ItclResolvedVarInfo*)(*rPtr))->vlookup = vlookup;
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclClassRuntimeVarResolver()
+ *
+ * Invoked when Tcl sets up the call frame for an [incr Tcl] method/proc
+ * at runtime. Resolves data members identified earlier by
+ * Itcl_ClassCompiledVarResolver. Returns the Tcl_Var representation
+ * for the data member.
+ * ------------------------------------------------------------------------
+ */
+static Tcl_Var
+ItclClassRuntimeVarResolver(
+ Tcl_Interp *interp, /* current interpreter */
+ Tcl_ResolvedVarInfo *resVarInfo) /* contains ItclVarLookup rep
+ * for variable */
+{
+ ItclVarLookup *vlookup = ((ItclResolvedVarInfo*)resVarInfo)->vlookup;
+ ItclClass *iclsPtr;
+ ItclObject *contextIoPtr;
+ Tcl_HashEntry *hPtr;
+
+ /*
+ * If this is a common data member, then the associated
+ * variable is known directly.
+ */
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ }
+
+ /*
+ * Otherwise, get the current object context and find the
+ * variable in its data table.
+ *
+ * TRICKY NOTE: Get the index for this variable using the
+ * virtual table for the MOST-SPECIFIC class.
+ */
+ if (TCL_ERROR == Itcl_GetContext(interp, &iclsPtr, &contextIoPtr)
+ || (contextIoPtr == NULL)) {
+ return NULL;
+ }
+
+ if (contextIoPtr->iclsPtr != vlookup->ivPtr->iclsPtr) {
+ if (strcmp(Tcl_GetString(vlookup->ivPtr->namePtr), "this") == 0) {
+ /* only for the this variable we need the one of the
+ * contextIoPtr class */
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->iclsPtr->resolveVars,
+ Tcl_GetString(vlookup->ivPtr->namePtr));
+
+ if (hPtr != NULL) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ }
+ }
+ }
+ hPtr = Tcl_FindHashEntry(&contextIoPtr->objectVariables,
+ (char *)vlookup->ivPtr);
+ if (strcmp(Tcl_GetString(vlookup->ivPtr->namePtr), "this") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ if (vlookup->ivPtr->iclsPtr->nsPtr == NULL) {
+ Tcl_DStringAppend(&buffer,
+ Tcl_GetCurrentNamespace(interp)->fullName, -1);
+ } else {
+ Tcl_DStringAppend(&buffer,
+ vlookup->ivPtr->iclsPtr->nsPtr->fullName, -1);
+ }
+ Tcl_DStringAppend(&buffer, "::this", 6);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ if (varPtr != NULL) {
+ return varPtr;
+ }
+ }
+ if (strcmp(Tcl_GetString(vlookup->ivPtr->namePtr),
+ "itcl_options") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ Tcl_DStringAppend(&buffer, "::itcl_options", -1);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ Tcl_DStringFree(&buffer);
+ if (varPtr != NULL) {
+ return varPtr;
+ }
+ }
+ if (strcmp(Tcl_GetString(vlookup->ivPtr->namePtr),
+ "itcl_option_components") == 0) {
+ Tcl_Var varPtr;
+ Tcl_DString buffer;
+
+ Tcl_DStringInit(&buffer);
+ Tcl_DStringAppend(&buffer, ITCL_VARIABLES_NAMESPACE, -1);
+ Tcl_DStringAppend(&buffer,
+ (Tcl_GetObjectNamespace(contextIoPtr->oPtr)->fullName), -1);
+ Tcl_DStringAppend(&buffer, "::itcl_option_components", -1);
+ varPtr = Itcl_FindNamespaceVar(interp, Tcl_DStringValue(&buffer),
+ NULL, 0);
+ Tcl_DStringFree(&buffer);
+ if (varPtr != NULL) {
+ return varPtr;
+ }
+ }
+ if (hPtr != NULL) {
+ return (Tcl_Var)Tcl_GetHashValue(hPtr);
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ParseVarResolver()
+ *
+ * Used by the "parser" namespace to resolve variable accesses to
+ * common variables. The runtime resolver procedure is consulted
+ * whenever a variable is accessed within the namespace. It can
+ * deny access to certain variables, or perform special lookups itself.
+ *
+ * This procedure allows access only to "common" class variables that
+ * have been declared within the class or inherited from another class.
+ * A "set" command can be used to initialized common data members within
+ * the body of the class definition itself:
+ *
+ * itcl::class Foo {
+ * common colors
+ * set colors(red) #ff0000
+ * set colors(green) #00ff00
+ * set colors(blue) #0000ff
+ * ...
+ * }
+ *
+ * itcl::class Bar {
+ * inherit Foo
+ * set colors(gray) #a0a0a0
+ * set colors(white) #ffffff
+ *
+ * common numbers
+ * set numbers(0) zero
+ * set numbers(1) one
+ * }
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ParseVarResolver(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ Tcl_Namespace *contextNs, /* namespace context */
+ int flags, /* TCL_GLOBAL_ONLY => global variable
+ * TCL_NAMESPACE_ONLY => namespace variable */
+ Tcl_Var* rPtr) /* returns: Tcl_Var for desired variable */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)contextNs->clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+
+ /*
+ * See if the requested variable is a recognized "common" member.
+ * If it is, make sure that access is allowed.
+ */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, name);
+ if (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ if (!vlookup->accessible) {
+ Tcl_AppendResult(interp,
+ "can't access \"", name, "\": ",
+ Itcl_ProtectionStr(vlookup->ivPtr->protection),
+ " variable",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ *rPtr = Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ }
+ }
+
+ /*
+ * If the variable is not recognized, return TCL_CONTINUE and
+ * let lookup continue via the normal name resolution rules.
+ * This is important for variables like "errorInfo"
+ * that might get set while the parser namespace is active.
+ */
+ return TCL_CONTINUE;
+}
+
+
+
+int
+ItclSetParserResolver(
+ Tcl_Namespace *nsPtr)
+{
+ Itcl_SetNamespaceResolvers(nsPtr, (Tcl_ResolveCmdProc*)NULL,
+ Itcl_ParseVarResolver, (Tcl_ResolveCompiledVarProc*)NULL);
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve2.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve2.c
new file mode 100644
index 0000000..b75a5a3
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclResolve2.c
@@ -0,0 +1,564 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * These procedures handle command and variable resolution
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ *
+ * ========================================================================
+ * Copyright (c) Arnulf Wiedemann
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#include <tclInt.h>
+#include "itclInt.h"
+#include "itclVCInt.h"
+
+/*
+ * This structure is a subclass of Tcl_ResolvedVarInfo that contains the
+ * ItclVarLookup info needed at runtime.
+ */
+typedef struct ItclResolvedVarInfo {
+ Tcl_ResolvedVarInfo vinfo; /* This must be the first element. */
+ ItclVarLookup *vlookup; /* Pointer to lookup info. */
+} ItclResolvedVarInfo;
+
+static Tcl_Var ItclClassRuntimeVarResolver2 (
+ Tcl_Interp *interp, Tcl_ResolvedVarInfo *vinfoPtr);
+
+int
+Itcl_CheckClassVariableProtection(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *varName,
+ ClientData clientData)
+{
+ ItclClassVarInfo *icviPtr;
+
+ icviPtr = (ItclClassVarInfo *)clientData;
+ if (icviPtr->protection == ITCL_PRIVATE) {
+ if (icviPtr->declaringNsPtr != nsPtr) {
+ Tcl_AppendResult(interp, "can't read \"", varName,
+ "\": no such variable", NULL);
+ return TCL_ERROR;
+ }
+ }
+ return TCL_OK;
+}
+
+int
+Itcl_CheckClassCommandProtection(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *commandName,
+ ClientData clientData)
+{
+ /* FIXME need code here !!! */
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCmdResolver()
+ *
+ * Used by the class namespaces to handle name resolution for all
+ * commands. This procedure looks for references to class methods
+ * and procs, and returns TCL_OK along with the appropriate Tcl
+ * command in the rPtr argument. If a particular command is private,
+ * this procedure returns TCL_ERROR and access to the command is
+ * denied. If a command is not recognized, this procedure returns
+ * TCL_CONTINUE, and lookup continues via the normal Tcl name
+ * resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCmdResolver2(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the command being accessed */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ int flags, /* TCL_LEAVE_ERR_MSG => leave error messages
+ * in interp if anything goes wrong */
+ Tcl_Command *rPtr) /* returns: resolved command */
+{
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ ItclObject *contextIoPtr;
+
+ Tcl_Command cmdPtr;
+ ItclResolvingInfo *iriPtr;
+ ObjectCmdTableInfo *octiPtr;
+ ObjectCmdInfo *ociPtr;
+ Tcl_HashEntry *hPtr;
+
+ if ((name[0] == 't') && (strcmp(name, "this") == 0)) {
+ return TCL_CONTINUE;
+ }
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ ItclCallContext *callContextPtr;
+ callContextPtr = Itcl_PeekStack(&infoPtr->contextStack);
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&iriPtr->resolveCmds , nsPtr->fullName);
+ if (hPtr != NULL) {
+ Tcl_HashTable *tablePtr;
+ tablePtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr, name);
+ if (hPtr != NULL) {
+ ItclClassCmdInfo *icciPtr = Tcl_GetHashValue(hPtr);
+ if ((callContextPtr != NULL) && (callContextPtr->ioPtr != NULL)) {
+ contextIoPtr = callContextPtr->ioPtr;
+ hPtr = Tcl_FindHashEntry(&iriPtr->objectCmdsTables,
+ (char *)contextIoPtr);
+ if (hPtr != NULL) {
+ octiPtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(&octiPtr->cmdInfos,
+ (char *)icciPtr);
+ if (hPtr != NULL) {
+ int ret;
+ ociPtr = Tcl_GetHashValue(hPtr);
+ ret = (* iriPtr->cmdProtFcn)(interp,
+ Tcl_GetCurrentNamespace(interp), name,
+ (ClientData)icciPtr);
+ if (ret != TCL_OK) {
+ return ret;
+ }
+ cmdPtr = ociPtr->cmdPtr;
+ *rPtr = cmdPtr;
+ return TCL_OK;
+ }
+ }
+ }
+ }
+ }
+ return TCL_CONTINUE;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassVarResolver()
+ *
+ * Used by the class namespaces to handle name resolution for runtime
+ * variable accesses. This procedure looks for references to both
+ * common variables and instance variables at runtime. It is used as
+ * a second line of defense, to handle references that could not be
+ * resolved as compiled locals.
+ *
+ * If a variable is found, this procedure returns TCL_OK along with
+ * the appropriate Tcl variable in the rPtr argument. If a particular
+ * variable is private, this procedure returns TCL_ERROR and access
+ * to the variable is denied. If a variable is not recognized, this
+ * procedure returns TCL_CONTINUE, and lookup continues via the normal
+ * Tcl name resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassVarResolver2(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ int flags, /* TCL_LEAVE_ERR_MSG => leave error messages
+ * in interp if anything goes wrong */
+ Tcl_Var *rPtr) /* returns: resolved variable */
+{
+ ItclObjectInfo *infoPtr;
+ ItclClass *iclsPtr;
+ ItclObject *contextIoPtr;
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+
+ Tcl_Var varPtr;
+ ItclResolvingInfo *iriPtr;
+ ObjectVarTableInfo *ovtiPtr;
+ ObjectVarInfo *oviPtr;
+
+ Tcl_Namespace *upNsPtr;
+ upNsPtr = Itcl_GetUplevelNamespace(interp, 1);
+
+ /*
+ * If this is a global variable, handle it in the usual
+ * Tcl manner.
+ */
+ if (flags & TCL_GLOBAL_ONLY) {
+ return TCL_CONTINUE;
+ }
+
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+
+ /*
+ * See if this is a formal parameter in the current proc scope.
+ * If so, that variable has precedence. Look it up and return
+ * it here. This duplicates some of the functionality of
+ * TclLookupVar, but we return it here (instead of returning
+ * TCL_CONTINUE) to avoid looking it up again later.
+ */
+ ItclCallContext *callContextPtr;
+ callContextPtr = Itcl_PeekStack(&infoPtr->contextStack);
+ if ((strstr(name,"::") == NULL) &&
+ Itcl_IsCallFrameArgument(interp, name)) {
+ return TCL_CONTINUE;
+ }
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&iriPtr->resolveVars , nsPtr->fullName);
+ if (hPtr != NULL) {
+ Tcl_HashTable *tablePtr;
+ tablePtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr , name);
+ if (hPtr != NULL) {
+ int ret;
+ ItclClassVarInfo *icviPtr = Tcl_GetHashValue(hPtr);
+ ret = (* iriPtr->varProtFcn)(interp,
+ Tcl_GetCurrentNamespace(interp), name,
+ (ClientData)icviPtr);
+ if (ret != TCL_OK) {
+ return ret;
+ }
+ /*
+ * If this is an instance variable, then we have to
+ * find the object context,
+ */
+
+ if ((callContextPtr != NULL) && (callContextPtr->ioPtr != NULL)) {
+ contextIoPtr = callContextPtr->ioPtr;
+ hPtr = Tcl_FindHashEntry(&iriPtr->objectVarsTables,
+ (char *)contextIoPtr);
+ if (hPtr != NULL) {
+ ovtiPtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(&ovtiPtr->varInfos,
+ (char *)icviPtr);
+ if (hPtr != NULL) {
+ oviPtr = Tcl_GetHashValue(hPtr);
+ varPtr = oviPtr->varPtr;
+ *rPtr = varPtr;
+ return TCL_OK;
+ }
+ }
+ }
+ }
+ }
+ /*
+ * See if the variable is a known data member and accessible.
+ */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, name);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ if (!vlookup->accessible) {
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * If this is a common data member, then its variable
+ * is easy to find. Return it directly.
+ */
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ *rPtr = Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ }
+
+ return TCL_CONTINUE;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ClassCompiledVarResolver()
+ *
+ * Used by the class namespaces to handle name resolution for compile
+ * time variable accesses. This procedure looks for references to
+ * both common variables and instance variables at compile time. If
+ * the variables are found, they are characterized in a generic way
+ * by their ItclVarLookup record. At runtime, Tcl constructs the
+ * compiled local variables by calling ItclClassRuntimeVarResolver.
+ *
+ * If a variable is found, this procedure returns TCL_OK along with
+ * information about the variable in the rPtr argument. If a particular
+ * variable is private, this procedure returns TCL_ERROR and access
+ * to the variable is denied. If a variable is not recognized, this
+ * procedure returns TCL_CONTINUE, and lookup continues via the normal
+ * Tcl name resolution rules.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_ClassCompiledVarResolver2(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ int length, /* number of characters in name */
+ Tcl_Namespace *nsPtr, /* namespace performing the resolution */
+ Tcl_ResolvedVarInfo **rPtr) /* returns: info that makes it possible to
+ * resolve the variable at runtime */
+{
+ ItclClass *iclsPtr;
+ ItclObjectInfo *infoPtr;
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+ char *buffer;
+ char storage[64];
+
+ infoPtr = (ItclObjectInfo *)Tcl_GetAssocData(interp,
+ ITCL_INTERP_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&infoPtr->namespaceClasses, (char *)nsPtr);
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+ iclsPtr = Tcl_GetHashValue(hPtr);
+ /*
+ * Copy the name to local storage so we can NULL terminate it.
+ * If the name is long, allocate extra space for it.
+ */
+ if (length < sizeof(storage)) {
+ buffer = storage;
+ } else {
+ buffer = (char*)ckalloc((unsigned)(length+1));
+ }
+ memcpy((void*)buffer, (void*)name, (size_t)length);
+ buffer[length] = '\0';
+
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, buffer);
+
+ if (buffer != storage) {
+ ckfree(buffer);
+ }
+
+ /*
+ * If the name is not found, or if it is inaccessible,
+ * continue on with the normal Tcl name resolution rules.
+ */
+ if (hPtr == NULL) {
+ return TCL_CONTINUE;
+ }
+
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+ if (!vlookup->accessible) {
+ return TCL_CONTINUE;
+ }
+
+ /*
+ * Return the ItclVarLookup record. At runtime, Tcl will
+ * call ItclClassRuntimeVarResolver with this record, to
+ * plug in the appropriate variable for the current object
+ * context.
+ */
+ (*rPtr) = (Tcl_ResolvedVarInfo *) ckalloc(sizeof(ItclResolvedVarInfo));
+ (*rPtr)->fetchProc = ItclClassRuntimeVarResolver2;
+ (*rPtr)->deleteProc = NULL;
+ ((ItclResolvedVarInfo*)(*rPtr))->vlookup = vlookup;
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclClassRuntimeVarResolver()
+ *
+ * Invoked when Tcl sets up the call frame for an [incr Tcl] method/proc
+ * at runtime. Resolves data members identified earlier by
+ * Itcl_ClassCompiledVarResolver. Returns the Tcl_Var representation
+ * for the data member.
+ * ------------------------------------------------------------------------
+ */
+static Tcl_Var
+ItclClassRuntimeVarResolver2(
+ Tcl_Interp *interp, /* current interpreter */
+ Tcl_ResolvedVarInfo *resVarInfo) /* contains ItclVarLookup rep
+ * for variable */
+{
+ ItclVarLookup *vlookup = ((ItclResolvedVarInfo*)resVarInfo)->vlookup;
+
+ ItclClass *iclsPtr;
+ ItclObject *contextIoPtr;
+ Tcl_HashEntry *hPtr;
+
+ Tcl_Var varPtr;
+ ItclResolvingInfo *iriPtr;
+ ObjectVarTableInfo *ovtiPtr;
+ ObjectVarInfo *oviPtr;
+
+ /*
+ * If this is a common data member, then the associated
+ * variable is known directly.
+ */
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ return Tcl_GetHashValue(hPtr);
+ }
+ }
+ iclsPtr = vlookup->ivPtr->iclsPtr;
+
+ /*
+ * Otherwise, get the current object context and find the
+ * variable in its data table.
+ *
+ * TRICKY NOTE: Get the index for this variable using the
+ * virtual table for the MOST-SPECIFIC class.
+ */
+
+ ItclCallContext *callContextPtr;
+
+ callContextPtr = Itcl_PeekStack(&iclsPtr->infoPtr->contextStack);
+ if (callContextPtr == NULL) {
+ return NULL;
+ }
+ if (callContextPtr->ioPtr == NULL) {
+ return NULL;
+ }
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_FindHashEntry(&iriPtr->resolveVars,
+ Tcl_GetCurrentNamespace(interp)->fullName);
+ if (hPtr != NULL) {
+ Tcl_HashTable *tablePtr;
+ tablePtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr,
+ Tcl_GetString(vlookup->ivPtr->namePtr));
+ if (hPtr != NULL) {
+ ItclClassVarInfo *icviPtr = Tcl_GetHashValue(hPtr);
+ int ret;
+ ret = (* iriPtr->varProtFcn)(interp,
+ Tcl_GetCurrentNamespace(interp),
+ Tcl_GetString(vlookup->ivPtr->namePtr),
+ (ClientData)icviPtr);
+ if (ret != TCL_OK) {
+ return NULL;
+ }
+ /*
+ * If this is an instance variable, then we have to
+ * find the object context,
+ */
+
+ contextIoPtr = callContextPtr->ioPtr;
+ hPtr = Tcl_FindHashEntry(&iriPtr->objectVarsTables, (char *)contextIoPtr);
+ if (hPtr != NULL) {
+ ovtiPtr = Tcl_GetHashValue(hPtr);
+ hPtr = Tcl_FindHashEntry(&ovtiPtr->varInfos, (char *)icviPtr);
+ if (hPtr != NULL) {
+ oviPtr = Tcl_GetHashValue(hPtr);
+ varPtr = oviPtr->varPtr;
+ return varPtr;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ParseVarResolver()
+ *
+ * Used by the "parser" namespace to resolve variable accesses to
+ * common variables. The runtime resolver procedure is consulted
+ * whenever a variable is accessed within the namespace. It can
+ * deny access to certain variables, or perform special lookups itself.
+ *
+ * This procedure allows access only to "common" class variables that
+ * have been declared within the class or inherited from another class.
+ * A "set" command can be used to initialized common data members within
+ * the body of the class definition itself:
+ *
+ * itcl::class Foo {
+ * common colors
+ * set colors(red) #ff0000
+ * set colors(green) #00ff00
+ * set colors(blue) #0000ff
+ * ...
+ * }
+ *
+ * itcl::class Bar {
+ * inherit Foo
+ * set colors(gray) #a0a0a0
+ * set colors(white) #ffffff
+ *
+ * common numbers
+ * set numbers(0) zero
+ * set numbers(1) one
+ * }
+ *
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+int
+Itcl_ParseVarResolver2(
+ Tcl_Interp *interp, /* current interpreter */
+ const char* name, /* name of the variable being accessed */
+ Tcl_Namespace *contextNs, /* namespace context */
+ int flags, /* TCL_GLOBAL_ONLY => global variable
+ * TCL_NAMESPACE_ONLY => namespace variable */
+ Tcl_Var* rPtr) /* returns: Tcl_Var for desired variable */
+{
+ ItclObjectInfo *infoPtr = (ItclObjectInfo*)contextNs->clientData;
+ ItclClass *iclsPtr = (ItclClass*)Itcl_PeekStack(&infoPtr->clsStack);
+
+ Tcl_HashEntry *hPtr;
+ ItclVarLookup *vlookup;
+
+ /*
+ * See if the requested variable is a recognized "common" member.
+ * If it is, make sure that access is allowed.
+ */
+ hPtr = Tcl_FindHashEntry(&iclsPtr->resolveVars, name);
+ if (hPtr) {
+ vlookup = (ItclVarLookup*)Tcl_GetHashValue(hPtr);
+
+ if ((vlookup->ivPtr->flags & ITCL_COMMON) != 0) {
+ if (!vlookup->accessible) {
+ Tcl_AppendResult(interp,
+ "can't access \"", name, "\": ",
+ Itcl_ProtectionStr(vlookup->ivPtr->protection),
+ " variable",
+ (char*)NULL);
+ return TCL_ERROR;
+ }
+ hPtr = Tcl_FindHashEntry(&vlookup->ivPtr->iclsPtr->classCommons,
+ (char *)vlookup->ivPtr);
+ if (hPtr != NULL) {
+ *rPtr = Tcl_GetHashValue(hPtr);
+ return TCL_OK;
+ }
+ }
+ }
+
+ /*
+ * If the variable is not recognized, return TCL_CONTINUE and
+ * let lookup continue via the normal name resolution rules.
+ * This is important for variables like "errorInfo"
+ * that might get set while the parser namespace is active.
+ */
+ return TCL_CONTINUE;
+}
+
+
+
+int
+ItclSetParserResolver2(
+ Tcl_Namespace *nsPtr)
+{
+ Itcl_SetNamespaceResolvers(nsPtr, (Tcl_ResolveCmdProc*)NULL,
+ Itcl_ParseVarResolver2, (Tcl_ResolveCompiledVarProc*)NULL);
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclStubInit.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubInit.c
new file mode 100644
index 0000000..63d6437
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubInit.c
@@ -0,0 +1,240 @@
+/*
+ * This file is (mostly) automatically generated from itcl.decls.
+ * It is compiled and linked in with the itcl package proper.
+ */
+
+#include "itclInt.h"
+
+MODULE_SCOPE const ItclStubs itclStubs;
+/* !BEGIN!: Do not edit below this line. */
+
+static const ItclIntStubs itclIntStubs = {
+ TCL_STUB_MAGIC,
+ ITCLINT_STUBS_EPOCH,
+ ITCLINT_STUBS_REVISION,
+ 0,
+ Itcl_IsClassNamespace, /* 0 */
+ Itcl_IsClass, /* 1 */
+ Itcl_FindClass, /* 2 */
+ Itcl_FindObject, /* 3 */
+ Itcl_IsObject, /* 4 */
+ Itcl_ObjectIsa, /* 5 */
+ Itcl_Protection, /* 6 */
+ Itcl_ProtectionStr, /* 7 */
+ Itcl_CanAccess, /* 8 */
+ Itcl_CanAccessFunc, /* 9 */
+ 0, /* 10 */
+ Itcl_ParseNamespPath, /* 11 */
+ Itcl_DecodeScopedCommand, /* 12 */
+ Itcl_EvalArgs, /* 13 */
+ Itcl_CreateArgs, /* 14 */
+ 0, /* 15 */
+ 0, /* 16 */
+ Itcl_GetContext, /* 17 */
+ Itcl_InitHierIter, /* 18 */
+ Itcl_DeleteHierIter, /* 19 */
+ Itcl_AdvanceHierIter, /* 20 */
+ Itcl_FindClassesCmd, /* 21 */
+ Itcl_FindObjectsCmd, /* 22 */
+ 0, /* 23 */
+ Itcl_DelClassCmd, /* 24 */
+ Itcl_DelObjectCmd, /* 25 */
+ Itcl_ScopeCmd, /* 26 */
+ Itcl_CodeCmd, /* 27 */
+ Itcl_StubCreateCmd, /* 28 */
+ Itcl_StubExistsCmd, /* 29 */
+ Itcl_IsStub, /* 30 */
+ Itcl_CreateClass, /* 31 */
+ Itcl_DeleteClass, /* 32 */
+ Itcl_FindClassNamespace, /* 33 */
+ Itcl_HandleClass, /* 34 */
+ 0, /* 35 */
+ 0, /* 36 */
+ 0, /* 37 */
+ Itcl_BuildVirtualTables, /* 38 */
+ Itcl_CreateVariable, /* 39 */
+ Itcl_DeleteVariable, /* 40 */
+ Itcl_GetCommonVar, /* 41 */
+ 0, /* 42 */
+ 0, /* 43 */
+ Itcl_CreateObject, /* 44 */
+ Itcl_DeleteObject, /* 45 */
+ Itcl_DestructObject, /* 46 */
+ 0, /* 47 */
+ Itcl_GetInstanceVar, /* 48 */
+ 0, /* 49 */
+ Itcl_BodyCmd, /* 50 */
+ Itcl_ConfigBodyCmd, /* 51 */
+ Itcl_CreateMethod, /* 52 */
+ Itcl_CreateProc, /* 53 */
+ Itcl_CreateMemberFunc, /* 54 */
+ Itcl_ChangeMemberFunc, /* 55 */
+ Itcl_DeleteMemberFunc, /* 56 */
+ Itcl_CreateMemberCode, /* 57 */
+ Itcl_DeleteMemberCode, /* 58 */
+ Itcl_GetMemberCode, /* 59 */
+ 0, /* 60 */
+ Itcl_EvalMemberCode, /* 61 */
+ 0, /* 62 */
+ 0, /* 63 */
+ 0, /* 64 */
+ 0, /* 65 */
+ 0, /* 66 */
+ Itcl_GetMemberFuncUsage, /* 67 */
+ Itcl_ExecMethod, /* 68 */
+ Itcl_ExecProc, /* 69 */
+ 0, /* 70 */
+ Itcl_ConstructBase, /* 71 */
+ Itcl_InvokeMethodIfExists, /* 72 */
+ 0, /* 73 */
+ Itcl_ReportFuncErrors, /* 74 */
+ Itcl_ParseInit, /* 75 */
+ Itcl_ClassCmd, /* 76 */
+ Itcl_ClassInheritCmd, /* 77 */
+ Itcl_ClassProtectionCmd, /* 78 */
+ Itcl_ClassConstructorCmd, /* 79 */
+ Itcl_ClassDestructorCmd, /* 80 */
+ Itcl_ClassMethodCmd, /* 81 */
+ Itcl_ClassProcCmd, /* 82 */
+ Itcl_ClassVariableCmd, /* 83 */
+ Itcl_ClassCommonCmd, /* 84 */
+ Itcl_ParseVarResolver, /* 85 */
+ Itcl_BiInit, /* 86 */
+ Itcl_InstallBiMethods, /* 87 */
+ Itcl_BiIsaCmd, /* 88 */
+ Itcl_BiConfigureCmd, /* 89 */
+ Itcl_BiCgetCmd, /* 90 */
+ Itcl_BiChainCmd, /* 91 */
+ Itcl_BiInfoClassCmd, /* 92 */
+ Itcl_BiInfoInheritCmd, /* 93 */
+ Itcl_BiInfoHeritageCmd, /* 94 */
+ Itcl_BiInfoFunctionCmd, /* 95 */
+ Itcl_BiInfoVariableCmd, /* 96 */
+ Itcl_BiInfoBodyCmd, /* 97 */
+ Itcl_BiInfoArgsCmd, /* 98 */
+ 0, /* 99 */
+ Itcl_EnsembleInit, /* 100 */
+ Itcl_CreateEnsemble, /* 101 */
+ Itcl_AddEnsemblePart, /* 102 */
+ Itcl_GetEnsemblePart, /* 103 */
+ Itcl_IsEnsemble, /* 104 */
+ Itcl_GetEnsembleUsage, /* 105 */
+ Itcl_GetEnsembleUsageForObj, /* 106 */
+ Itcl_EnsembleCmd, /* 107 */
+ Itcl_EnsPartCmd, /* 108 */
+ Itcl_EnsembleErrorCmd, /* 109 */
+ 0, /* 110 */
+ 0, /* 111 */
+ 0, /* 112 */
+ 0, /* 113 */
+ 0, /* 114 */
+ Itcl_Assert, /* 115 */
+ Itcl_IsObjectCmd, /* 116 */
+ Itcl_IsClassCmd, /* 117 */
+ 0, /* 118 */
+ 0, /* 119 */
+ 0, /* 120 */
+ 0, /* 121 */
+ 0, /* 122 */
+ 0, /* 123 */
+ 0, /* 124 */
+ 0, /* 125 */
+ 0, /* 126 */
+ 0, /* 127 */
+ 0, /* 128 */
+ 0, /* 129 */
+ 0, /* 130 */
+ 0, /* 131 */
+ 0, /* 132 */
+ 0, /* 133 */
+ 0, /* 134 */
+ 0, /* 135 */
+ 0, /* 136 */
+ 0, /* 137 */
+ 0, /* 138 */
+ 0, /* 139 */
+ Itcl_FilterAddCmd, /* 140 */
+ Itcl_FilterDeleteCmd, /* 141 */
+ Itcl_ForwardAddCmd, /* 142 */
+ Itcl_ForwardDeleteCmd, /* 143 */
+ Itcl_MixinAddCmd, /* 144 */
+ Itcl_MixinDeleteCmd, /* 145 */
+ 0, /* 146 */
+ 0, /* 147 */
+ 0, /* 148 */
+ 0, /* 149 */
+ 0, /* 150 */
+ Itcl_BiInfoUnknownCmd, /* 151 */
+ Itcl_BiInfoVarsCmd, /* 152 */
+ Itcl_CanAccess2, /* 153 */
+ 0, /* 154 */
+ 0, /* 155 */
+ 0, /* 156 */
+ 0, /* 157 */
+ 0, /* 158 */
+ 0, /* 159 */
+ Itcl_SetCallFrameResolver, /* 160 */
+ ItclEnsembleSubCmd, /* 161 */
+ Itcl_GetUplevelNamespace, /* 162 */
+ Itcl_GetCallFrameClientData, /* 163 */
+ 0, /* 164 */
+ Itcl_SetCallFrameNamespace, /* 165 */
+ Itcl_GetCallFrameObjc, /* 166 */
+ Itcl_GetCallFrameObjv, /* 167 */
+ Itcl_NWidgetCmd, /* 168 */
+ Itcl_AddOptionCmd, /* 169 */
+ Itcl_AddComponentCmd, /* 170 */
+ Itcl_BiInfoOptionCmd, /* 171 */
+ Itcl_BiInfoComponentCmd, /* 172 */
+ Itcl_RenameCommand, /* 173 */
+ Itcl_PushCallFrame, /* 174 */
+ Itcl_PopCallFrame, /* 175 */
+ Itcl_GetUplevelCallFrame, /* 176 */
+ Itcl_ActivateCallFrame, /* 177 */
+ ItclSetInstanceVar, /* 178 */
+ ItclCapitalize, /* 179 */
+ ItclClassBaseCmd, /* 180 */
+ ItclCreateComponent, /* 181 */
+ Itcl_SetContext, /* 182 */
+ Itcl_UnsetContext, /* 183 */
+ ItclGetInstanceVar, /* 184 */
+};
+
+static const ItclStubHooks itclStubHooks = {
+ &itclIntStubs
+};
+
+const ItclStubs itclStubs = {
+ TCL_STUB_MAGIC,
+ ITCL_STUBS_EPOCH,
+ ITCL_STUBS_REVISION,
+ &itclStubHooks,
+ 0, /* 0 */
+ 0, /* 1 */
+ Itcl_RegisterC, /* 2 */
+ Itcl_RegisterObjC, /* 3 */
+ Itcl_FindC, /* 4 */
+ Itcl_InitStack, /* 5 */
+ Itcl_DeleteStack, /* 6 */
+ Itcl_PushStack, /* 7 */
+ Itcl_PopStack, /* 8 */
+ Itcl_PeekStack, /* 9 */
+ Itcl_GetStackValue, /* 10 */
+ Itcl_InitList, /* 11 */
+ Itcl_DeleteList, /* 12 */
+ Itcl_CreateListElem, /* 13 */
+ Itcl_DeleteListElem, /* 14 */
+ Itcl_InsertList, /* 15 */
+ Itcl_InsertListElem, /* 16 */
+ Itcl_AppendList, /* 17 */
+ Itcl_AppendListElem, /* 18 */
+ Itcl_SetListValue, /* 19 */
+ Itcl_EventuallyFree, /* 20 */
+ Itcl_PreserveData, /* 21 */
+ Itcl_ReleaseData, /* 22 */
+ Itcl_SaveInterpState, /* 23 */
+ Itcl_RestoreInterpState, /* 24 */
+ Itcl_DiscardInterpState, /* 25 */
+};
+
+/* !END!: Do not edit above this line. */
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclStubLib.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubLib.c
new file mode 100644
index 0000000..50683b7
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubLib.c
@@ -0,0 +1,69 @@
+/*
+ * SOURCE: tk/generic/tkStubLib.c, version 1.9 2004/03/17
+ */
+
+#define USE_TCL_STUBS 1
+#define USE_ITCL_STUBS 1
+#include "itclInt.h"
+
+#undef Itcl_InitStubs
+
+MODULE_SCOPE const ItclStubs *itclStubsPtr;
+MODULE_SCOPE const ItclIntStubs *itclIntStubsPtr;
+
+const ItclStubs *itclStubsPtr = NULL;
+const ItclIntStubs *itclIntStubsPtr = NULL;
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Itcl_InitStubs --
+ * Load the tclOO package, initialize stub table pointer. Do not call
+ * this function directly, use Itcl_InitStubs() macro instead.
+ *
+ * Results:
+ * The actual version of the package that satisfies the request, or
+ * NULL to indicate that an error occurred.
+ *
+ * Side effects:
+ * Sets the stub table pointer.
+ *
+ */
+
+const char *
+Itcl_InitStubs(
+ Tcl_Interp *interp,
+ const char *version,
+ int exact)
+{
+ const char *packageName = "itcl";
+ const char *errMsg = NULL;
+ ClientData clientData = NULL;
+ const ItclStubs *stubsPtr;
+ const ItclIntStubs *intStubsPtr;
+ const char *actualVersion;
+
+ actualVersion =
+ Tcl_PkgRequireEx(interp, packageName, version, exact, &clientData);
+ stubsPtr = clientData;
+ if ((actualVersion == NULL) || (clientData == NULL)) {
+ return NULL;
+ }
+ intStubsPtr = stubsPtr->hooks ?
+ stubsPtr->hooks->itclIntStubs : NULL;
+
+ if (!stubsPtr || !intStubsPtr) {
+ errMsg = "missing stub table pointer";
+ goto error;
+ }
+ itclStubsPtr = stubsPtr;
+ itclIntStubsPtr = intStubsPtr;
+ return actualVersion;
+
+ error:
+ Tcl_ResetResult(interp);
+ Tcl_AppendResult(interp, "Error loading ", packageName, " package",
+ " (requested version '", version, "', loaded version '",
+ actualVersion, "'): ", errMsg, NULL);
+ return NULL;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclStubs.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubs.c
new file mode 100644
index 0000000..bc7189c
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclStubs.c
@@ -0,0 +1,231 @@
+/*
+ * itclStubs.c --
+ *
+ * This file contains the C-implemeted part of Itcl object-system
+ * Itcl
+ *
+ * Copyright (c) 2006 by Arnulf P. Wiedemann
+ *
+ * See the file "license.terms" for information on usage and redistribution of
+ * this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include "itclInt.h"
+
+static void ItclDeleteStub(ClientData cdata);
+static int ItclHandleStubCmd(ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *const objv[]);
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_IsStub()
+ *
+ * Checks the given Tcl command to see if it represents an autoloading
+ * stub created by the "stub create" command. Returns non-zero if
+ * the command is indeed a stub.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_IsStub(
+ Tcl_Command cmdPtr) /* command being tested */
+{
+ Tcl_CmdInfo cmdInfo;
+
+ /*
+ * This may be an imported command, but don't try to get the
+ * original. Just check to see if this particular command
+ * is a stub. If we really want the original command, we'll
+ * find it at a higher level.
+ */
+ if (Tcl_GetCommandInfoFromToken(cmdPtr, &cmdInfo) == 1) {
+ if (cmdInfo.deleteProc == ItclDeleteStub) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_StubCreateCmd()
+ *
+ * Invoked by Tcl whenever the user issues a "stub create" command to
+ * create an autoloading stub for imported commands. Handles the
+ * following syntax:
+ *
+ * stub create <name>
+ *
+ * Creates a command called <name>. Executing this command will cause
+ * the real command <name> to be autoloaded.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_StubCreateCmd(
+ ClientData clientData, /* not used */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Command cmdPtr;
+ char *cmdName;
+ Tcl_CmdInfo cmdInfo;
+
+ ItclShowArgs(1, "Itcl_StubCreateCmd", objc, objv);
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name");
+ return TCL_ERROR;
+ }
+ cmdName = Tcl_GetString(objv[1]);
+
+ /*
+ * Create a stub command with the characteristic ItclDeleteStub
+ * procedure. That way, we can recognize this command later
+ * on as a stub. Save the cmd token as client data, so we can
+ * get the full name of this command later on.
+ */
+ cmdPtr = Tcl_CreateObjCommand(interp, cmdName,
+ ItclHandleStubCmd, (ClientData)NULL,
+ (Tcl_CmdDeleteProc*)ItclDeleteStub);
+
+ Tcl_GetCommandInfoFromToken(cmdPtr, &cmdInfo);
+ cmdInfo.objClientData = cmdPtr;
+ Tcl_SetCommandInfoFromToken(cmdPtr, &cmdInfo);
+
+ return TCL_OK;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_StubExistsCmd()
+ *
+ * Invoked by Tcl whenever the user issues a "stub exists" command to
+ * see if an existing command is an autoloading stub. Handles the
+ * following syntax:
+ *
+ * stub exists <name>
+ *
+ * Looks for a command called <name> and checks to see if it is an
+ * autoloading stub. Returns a boolean result.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_StubExistsCmd(
+ ClientData clientData, /* not used */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Command cmdPtr;
+ char *cmdName;
+
+ if (objc != 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "name");
+ return TCL_ERROR;
+ }
+ cmdName = Tcl_GetString(objv[1]);
+
+ cmdPtr = Tcl_FindCommand(interp, cmdName, (Tcl_Namespace*)NULL, 0);
+
+ if ((cmdPtr != NULL) && Itcl_IsStub(cmdPtr)) {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), 1);
+ } else {
+ Tcl_SetIntObj(Tcl_GetObjResult(interp), 0);
+ }
+ return TCL_OK;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclHandleStubCmd()
+ *
+ * Invoked by Tcl to handle commands created by "stub create".
+ * Calls "auto_load" with the full name of the current command to
+ * trigger autoloading of the real implementation. Then, calls the
+ * command to handle its function. If successful, this command
+ * returns TCL_OK along with the result from the real implementation
+ * of this command. Otherwise, it returns TCL_ERROR, along with an
+ * error message in the interpreter.
+ * ------------------------------------------------------------------------
+ */
+static int
+ItclHandleStubCmd(
+ ClientData clientData, /* command token for this stub */
+ Tcl_Interp *interp, /* current interpreter */
+ int objc, /* number of arguments */
+ Tcl_Obj *const objv[]) /* argument objects */
+{
+ Tcl_Command cmdPtr;
+ Tcl_Obj **cmdlinev;
+ Tcl_Obj *objAutoLoad[2];
+ Tcl_Obj *objPtr;
+ Tcl_Obj *cmdNamePtr;
+ Tcl_Obj *cmdlinePtr;
+ char *cmdName;
+ int result;
+ int loaded;
+ int cmdlinec;
+
+ ItclShowArgs(1, "ItclHandleStubCmd", objc, objv);
+ cmdPtr = (Tcl_Command) clientData;
+ cmdNamePtr = Tcl_NewStringObj((char*)NULL, 0);
+ Tcl_IncrRefCount(cmdNamePtr);
+ Tcl_GetCommandFullName(interp, cmdPtr, cmdNamePtr);
+ cmdName = Tcl_GetString(cmdNamePtr);
+
+ /*
+ * Try to autoload the real command for this stub.
+ */
+ objAutoLoad[0] = Tcl_NewStringObj("::auto_load", -1);
+ objAutoLoad[1] = cmdNamePtr;
+ result = Tcl_EvalObjv(interp, 2, objAutoLoad, 0);
+ if (result != TCL_OK) {
+ Tcl_DecrRefCount(cmdNamePtr);
+ return TCL_ERROR;
+ }
+
+ objPtr = Tcl_GetObjResult(interp);
+ result = Tcl_GetIntFromObj(interp, objPtr, &loaded);
+ if ((result != TCL_OK) || !loaded) {
+ Tcl_ResetResult(interp);
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "can't autoload \"", cmdName, "\"", (char*)NULL);
+ Tcl_DecrRefCount(cmdNamePtr);
+ return TCL_ERROR;
+ }
+
+ /*
+ * At this point, the real implementation has been loaded.
+ * Invoke the command again with the arguments passed in.
+ */
+ cmdlinePtr = Itcl_CreateArgs(interp, cmdName, objc - 1, objv + 1);
+ (void) Tcl_ListObjGetElements((Tcl_Interp*)NULL, cmdlinePtr,
+ &cmdlinec, &cmdlinev);
+
+ Tcl_DecrRefCount(cmdNamePtr);
+ Tcl_ResetResult(interp);
+ ItclShowArgs(1, "ItclHandleStubCmd", cmdlinec - 1, cmdlinev + 1);
+ result = Tcl_EvalObjv(interp, cmdlinec - 1, cmdlinev + 1, TCL_EVAL_DIRECT);
+ Tcl_DecrRefCount(cmdlinePtr);
+ Tcl_DecrRefCount(objAutoLoad[0]);
+ return result;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * ItclDeleteStub()
+ *
+ * Invoked by Tcl whenever a stub command is deleted. This procedure
+ * does nothing, but its presence identifies a command as a stub.
+ * ------------------------------------------------------------------------
+ */
+/* ARGSUSED */
+static void
+ItclDeleteStub(
+ ClientData cdata) /* not used */
+{
+ /* do nothing */
+}
+
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.c
new file mode 100644
index 0000000..7d3cdf4
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.c
@@ -0,0 +1,143 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * This file contains procedures that use the internal Tcl core stubs
+ * entries.
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ *
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#include <tclInt.h>
+#include "itclInt.h"
+
+Tcl_Command
+_Tcl_GetOriginalCommand(
+ Tcl_Command command)
+{
+ return TclGetOriginalCommand(command);
+}
+
+int
+_Tcl_CreateProc(
+ Tcl_Interp *interp, /* Interpreter containing proc. */
+ Tcl_Namespace *nsPtr, /* Namespace containing this proc. */
+ const char *procName, /* Unqualified name of this proc. */
+ Tcl_Obj *argsPtr, /* Description of arguments. */
+ Tcl_Obj *bodyPtr, /* Command body. */
+ Tcl_Proc *procPtrPtr) /* Returns: pointer to proc data. */
+{
+ int code = TclCreateProc(interp, (Namespace *)nsPtr, procName, argsPtr,
+ bodyPtr, (Proc **)procPtrPtr);
+ (*(Proc **)procPtrPtr)->cmdPtr = NULL;
+ return code;
+}
+
+void *
+_Tcl_GetObjInterpProc(
+ void)
+{
+ return (void *)TclGetObjInterpProc();
+}
+
+void
+_Tcl_ProcDeleteProc(
+ ClientData clientData)
+{
+ TclProcDeleteProc(clientData);
+}
+
+int
+Itcl_RenameCommand(
+ Tcl_Interp *interp,
+ const char *oldName,
+ const char *newName)
+{
+ return TclRenameCommand(interp, oldName, newName);
+}
+
+int
+Itcl_PushCallFrame(
+ Tcl_Interp * interp,
+ Tcl_CallFrame * framePtr,
+ Tcl_Namespace * nsPtr,
+ int isProcCallFrame)
+{
+ return Tcl_PushCallFrame(interp, framePtr, nsPtr, isProcCallFrame);
+}
+
+void
+Itcl_PopCallFrame(
+ Tcl_Interp * interp)
+{
+ Tcl_PopCallFrame(interp);
+}
+
+void
+Itcl_GetVariableFullName(
+ Tcl_Interp * interp,
+ Tcl_Var variable,
+ Tcl_Obj * objPtr)
+{
+ Tcl_GetVariableFullName(interp, variable, objPtr);
+}
+
+Tcl_Var
+Itcl_FindNamespaceVar(
+ Tcl_Interp * interp,
+ const char * name,
+ Tcl_Namespace * contextNsPtr,
+ int flags)
+{
+ return Tcl_FindNamespaceVar(interp, name, contextNsPtr, flags);
+}
+
+void
+Itcl_SetNamespaceResolvers (
+ Tcl_Namespace * namespacePtr,
+ Tcl_ResolveCmdProc * cmdProc,
+ Tcl_ResolveVarProc * varProc,
+ Tcl_ResolveCompiledVarProc * compiledVarProc)
+{
+ Tcl_SetNamespaceResolvers(namespacePtr, cmdProc, varProc, compiledVarProc);
+}
+
+Tcl_HashTable *
+Itcl_GetNamespaceCommandTable(
+ Tcl_Namespace *nsPtr)
+{
+ return TclGetNamespaceCommandTable(nsPtr);
+}
+
+Tcl_HashTable *
+Itcl_GetNamespaceChildTable(
+ Tcl_Namespace *nsPtr)
+{
+ return TclGetNamespaceChildTable(nsPtr);
+}
+
+int
+Itcl_InitRewriteEnsemble(
+ Tcl_Interp *interp,
+ int numRemoved,
+ int numInserted,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ return TclInitRewriteEnsemble(interp, numRemoved, numInserted, objv);
+}
+
+void
+Itcl_ResetRewriteEnsemble(
+ Tcl_Interp *interp,
+ int isRootEnsemble)
+{
+ TclResetRewriteEnsemble(interp, isRootEnsemble);
+}
+
+
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.h
new file mode 100644
index 0000000..b22ee06
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclTclIntStubsFcn.h
@@ -0,0 +1,38 @@
+/* these functions are Tcl internal stubs so make an Itcl_* wrapper */
+MODULE_SCOPE void Itcl_GetVariableFullName (Tcl_Interp * interp,
+ Tcl_Var variable, Tcl_Obj * objPtr);
+MODULE_SCOPE Tcl_Var Itcl_FindNamespaceVar (Tcl_Interp * interp,
+ const char * name, Tcl_Namespace * contextNsPtr, int flags);
+MODULE_SCOPE void Itcl_SetNamespaceResolvers (Tcl_Namespace * namespacePtr,
+ Tcl_ResolveCmdProc * cmdProc, Tcl_ResolveVarProc * varProc,
+ Tcl_ResolveCompiledVarProc * compiledVarProc);
+
+#ifndef _TCL_PROC_DEFINED
+typedef struct Tcl_Proc_ *Tcl_Proc;
+#define _TCL_PROC_DEFINED 1
+#endif
+#ifndef _TCL_RESOLVE_DEFINED
+struct Tcl_Resolve;
+#endif
+
+#define Tcl_GetOriginalCommand _Tcl_GetOriginalCommand
+#define Tcl_CreateProc _Tcl_CreateProc
+#define Tcl_ProcDeleteProc _Tcl_ProcDeleteProc
+#define Tcl_GetObjInterpProc _Tcl_GetObjInterpProc
+
+MODULE_SCOPE Tcl_Command _Tcl_GetOriginalCommand(Tcl_Command command);
+MODULE_SCOPE int _Tcl_CreateProc(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ const char *procName, Tcl_Obj *argsPtr, Tcl_Obj *bodyPtr,
+ Tcl_Proc *procPtrPtr);
+MODULE_SCOPE void _Tcl_ProcDeleteProc(ClientData clientData);
+MODULE_SCOPE void *_Tcl_GetObjInterpProc(void);
+MODULE_SCOPE int Tcl_RenameCommand(Tcl_Interp *interp, const char *oldName,
+ const char *newName);
+MODULE_SCOPE Tcl_HashTable *Itcl_GetNamespaceChildTable(Tcl_Namespace *nsPtr);
+MODULE_SCOPE Tcl_HashTable *Itcl_GetNamespaceCommandTable(Tcl_Namespace *nsPtr);
+MODULE_SCOPE int Itcl_InitRewriteEnsemble(Tcl_Interp *interp, int numRemoved,
+ int numInserted, int objc, Tcl_Obj *const *objv);
+MODULE_SCOPE void Itcl_ResetRewriteEnsemble(Tcl_Interp *interp,
+ int isRootEnsemble);
+
+
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclTestRegisterC.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclTestRegisterC.c
new file mode 100644
index 0000000..7489b89
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclTestRegisterC.c
@@ -0,0 +1,128 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This part adds a mechanism for integrating C procedures into
+ * [incr Tcl] classes as methods and procs. Each C procedure must
+ * either be declared via Itcl_RegisterC() or dynamically loaded.
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) Arnulf Wiedemann
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+#ifdef ITCL_DEBUG_C_INTERFACE
+
+#include <stdio.h>
+#include "itclInt.h"
+
+Tcl_CmdProc cArgFunc;
+Tcl_ObjCmdProc cObjFunc;
+
+int
+cArgFunc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int argc,
+ const char **argv)
+{
+ int result;
+ ItclObjectInfo * infoPtr = NULL;
+ ItclClass *iclsPtr = NULL;
+ ItclClass * classPtr;
+ ItclObject * rioPtr = (ItclObject *)1;
+ Tcl_Obj * objv[4];
+ FOREACH_HASH_DECLS;
+
+//fprintf(stderr, "argc: %d\n", argc);
+ if (argc != 4) {
+ Tcl_AppendResult(interp, "wrong #args: should be ::itcl::parser::handleClass className className objectName", NULL);
+ return TCL_ERROR;
+ }
+ objv[0] = Tcl_NewStringObj(argv[0], -1);
+ objv[1] = Tcl_NewStringObj(argv[1], -1); /* class name */
+ objv[2] = Tcl_NewStringObj(argv[2], -1); /* full class name */
+ objv[3] = Tcl_NewStringObj(argv[3], -1); /* object name */
+ Tcl_IncrRefCount(objv[0]);
+ Tcl_IncrRefCount(objv[1]);
+ Tcl_IncrRefCount(objv[2]);
+ Tcl_IncrRefCount(objv[3]);
+ infoPtr = (ClientData)Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ FOREACH_HASH_VALUE(classPtr,&infoPtr->nameClasses) {
+ if (strcmp(Tcl_GetString(objv[1]), Tcl_GetString(classPtr->fullNamePtr)) == 0 ||
+ strcmp(Tcl_GetString(objv[2]), Tcl_GetString(classPtr->fullNamePtr)) == 0) {
+ iclsPtr = classPtr;
+ break;
+ }
+ }
+ if (iclsPtr == NULL) {
+ Tcl_AppendResult(interp, "no such class: ", Tcl_GetString(objv[2]), NULL);
+ return TCL_ERROR;
+ }
+
+ /* try to create an object for a class as a test for calling a C function from
+ * an Itcl class. See file CreateItclObjectWithC_example.tcl in library directory
+ */
+ result = Itcl_CreateObject(interp, Tcl_GetString(objv[3]), iclsPtr, 4, objv, &rioPtr);
+ return result;
+}
+
+int
+cObjFunc(
+ ClientData clientData,
+ Tcl_Interp *interp,
+ int objc,
+ Tcl_Obj *const *objv)
+{
+ Tcl_Namespace *nsPtr;
+ ItclObjectInfo * infoPtr = NULL;
+ ItclClass *iclsPtr = NULL;
+ ItclClass * classPtr;
+ FOREACH_HASH_DECLS;
+ int i;
+
+ ItclShowArgs(0, "cObjFunc called", objc, objv);
+fprintf(stderr, "objv: %d %p\n", objc, objv);
+for(i = 0; i<objc;i++) {
+ fprintf(stderr, "arg:%d:%s:\n", i, Tcl_GetString(objv[i]));
+}
+ nsPtr = Tcl_GetCurrentNamespace(interp);
+fprintf(stderr, "IP:%p %p %p !%s!\n",interp, clientData, nsPtr, nsPtr->fullName);
+ infoPtr = (ClientData)Tcl_GetAssocData(interp, ITCL_INTERP_DATA, NULL);
+ FOREACH_HASH_VALUE(classPtr,&infoPtr->nameClasses) {
+ if (strcmp(Tcl_GetString(objv[1]), Tcl_GetString(classPtr->fullNamePtr)) == 0 ||
+ strcmp(Tcl_GetString(objv[2]), Tcl_GetString(classPtr->fullNamePtr)) == 0) {
+ iclsPtr = classPtr;
+ break;
+ }
+ }
+fprintf(stderr, "IP2:%p %p %p\n",interp, clientData, iclsPtr);
+ return TCL_OK;
+}
+
+
+void
+RegisterDebugCFunctions(Tcl_Interp *interp)
+{
+ int result;
+
+ /* args: interp, name, c-function, clientdata, deleteproc */
+ result = Itcl_RegisterC(interp, "cArgFunc", cArgFunc, NULL, NULL);
+ result = Itcl_RegisterObjC(interp, "cObjFunc", cObjFunc, NULL, NULL);
+ if (result != 0) {
+ }
+}
+#endif
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclUtil.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclUtil.c
new file mode 100644
index 0000000..057f01b
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclUtil.c
@@ -0,0 +1,1202 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * [incr Tcl] provides object-oriented extensions to Tcl, much as
+ * C++ provides object-oriented extensions to C. It provides a means
+ * of encapsulating related procedures together with their shared data
+ * in a local namespace that is hidden from the outside world. It
+ * promotes code re-use through inheritance. More than anything else,
+ * it encourages better organization of Tcl applications through the
+ * object-oriented paradigm, leading to code that is easier to
+ * understand and maintain.
+ *
+ * This segment provides common utility functions used throughout
+ * the other [incr Tcl] source files.
+ *
+ * ========================================================================
+ * AUTHOR: Michael J. McLennan
+ * Bell Labs Innovations for Lucent Technologies
+ * mmclennan@lucent.com
+ * http://www.tcltk.com/itcl
+ *
+ * overhauled version author: Arnulf Wiedemann
+ * ========================================================================
+ * Copyright (c) 1993-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.
+ */
+#include "itclInt.h"
+
+#ifdef ITCL_PRESERVE_DEBUG
+#include <malloc.h>
+#endif
+
+/*
+ * POOL OF LIST ELEMENTS FOR LINKED LIST
+ */
+static Itcl_ListElem *listPool = NULL;
+static int listPoolLen = 0;
+
+#define ITCL_VALID_LIST 0x01face10 /* magic bit pattern for validation */
+#define ITCL_LIST_POOL_SIZE 200 /* max number of elements in listPool */
+
+/*
+ * This structure is used to take a snapshot of the interpreter
+ * state in Itcl_SaveInterpState. You can snapshot the state,
+ * execute a command, and then back up to the result or the
+ * error that was previously in progress.
+ */
+typedef struct InterpState {
+ int validate; /* validation stamp */
+ int status; /* return code status */
+ Tcl_Obj *objResult; /* result object */
+ char *errorInfo; /* contents of errorInfo variable */
+ char *errorCode; /* contents of errorCode variable */
+} InterpState;
+
+#define TCL_STATE_VALID 0x01233210 /* magic bit pattern for validation */
+
+#ifdef ITCL_PRESERVE_DEBUG
+static Tcl_HashTable itclPreserveInfos;
+static int itclPreserveInfoInitted = 0;
+#endif
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_Assert()
+ *
+ * Called whenever an assert() test fails. Prints a diagnostic
+ * message and abruptly exits.
+ * ------------------------------------------------------------------------
+ */
+
+void
+Itcl_Assert(testExpr, fileName, lineNumber)
+ const char *testExpr; /* string representing test expression */
+ const char *fileName; /* file name containing this call */
+ int lineNumber; /* line number containing this call */
+{
+ Tcl_Panic("Itcl Assertion failed: \"%s\" (line %d of %s)",
+ testExpr, lineNumber, fileName);
+}
+
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InitStack()
+ *
+ * Initializes a stack structure, allocating a certain amount of memory
+ * for the stack and setting the stack length to zero.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_InitStack(stack)
+ Itcl_Stack *stack; /* stack to be initialized */
+{
+ stack->values = stack->space;
+ stack->max = sizeof(stack->space)/sizeof(ClientData);
+ stack->len = 0;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteStack()
+ *
+ * Destroys a stack structure, freeing any memory that may have been
+ * allocated to represent it.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DeleteStack(stack)
+ Itcl_Stack *stack; /* stack to be deleted */
+{
+ /*
+ * If memory was explicitly allocated (instead of using the
+ * built-in buffer) then free it.
+ */
+ if (stack->values != stack->space) {
+ ckfree((char*)stack->values);
+ }
+ stack->values = NULL;
+ stack->len = stack->max = 0;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_PushStack()
+ *
+ * Pushes a piece of client data onto the top of the given stack.
+ * If the stack is not large enough, it is automatically resized.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_PushStack(cdata,stack)
+ ClientData cdata; /* data to be pushed onto stack */
+ Itcl_Stack *stack; /* stack */
+{
+ ClientData *newStack;
+
+ if (stack->len+1 >= stack->max) {
+ stack->max = 2*stack->max;
+ newStack = (ClientData*)
+ ckalloc((unsigned)(stack->max*sizeof(ClientData)));
+
+ if (stack->values) {
+ memcpy((char*)newStack, (char*)stack->values,
+ (size_t)(stack->len*sizeof(ClientData)));
+
+ if (stack->values != stack->space)
+ ckfree((char*)stack->values);
+ }
+ stack->values = newStack;
+ }
+ stack->values[stack->len++] = cdata;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_PopStack()
+ *
+ * Pops a bit of client data from the top of the given stack.
+ * ------------------------------------------------------------------------
+ */
+ClientData
+Itcl_PopStack(stack)
+ Itcl_Stack *stack; /* stack to be manipulated */
+{
+ if (stack->values && (stack->len > 0)) {
+ stack->len--;
+ return stack->values[stack->len];
+ }
+ return (ClientData)NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_PeekStack()
+ *
+ * Gets the current value from the top of the given stack.
+ * ------------------------------------------------------------------------
+ */
+ClientData
+Itcl_PeekStack(stack)
+ Itcl_Stack *stack; /* stack to be examined */
+{
+ if (stack->values && (stack->len > 0)) {
+ return stack->values[stack->len-1];
+ }
+ return (ClientData)NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_GetStackValue()
+ *
+ * Gets a value at some index within the stack. Index "0" is the
+ * first value pushed onto the stack.
+ * ------------------------------------------------------------------------
+ */
+ClientData
+Itcl_GetStackValue(stack,pos)
+ Itcl_Stack *stack; /* stack to be examined */
+ int pos; /* get value at this index */
+{
+ if (stack->values && (stack->len > 0)) {
+ assert(pos < stack->len);
+ return stack->values[pos];
+ }
+ return (ClientData)NULL;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InitList()
+ *
+ * Initializes a linked list structure, setting the list to the empty
+ * state.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_InitList(listPtr)
+ Itcl_List *listPtr; /* list to be initialized */
+{
+ listPtr->validate = ITCL_VALID_LIST;
+ listPtr->num = 0;
+ listPtr->head = NULL;
+ listPtr->tail = NULL;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteList()
+ *
+ * Destroys a linked list structure, deleting all of its elements and
+ * setting it to an empty state. If the elements have memory associated
+ * with them, this memory must be freed before deleting the list or it
+ * will be lost.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DeleteList(listPtr)
+ Itcl_List *listPtr; /* list to be deleted */
+{
+ Itcl_ListElem *elemPtr;
+
+ assert(listPtr->validate == ITCL_VALID_LIST);
+
+ elemPtr = listPtr->head;
+ while (elemPtr) {
+ elemPtr = Itcl_DeleteListElem(elemPtr);
+ }
+ listPtr->validate = 0;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CreateListElem()
+ *
+ * Low-level routined used by procedures like Itcl_InsertList() and
+ * Itcl_AppendList() to create new list elements. If elements are
+ * available, one is taken from the list element pool. Otherwise,
+ * a new one is allocated.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_CreateListElem(
+ Itcl_List *listPtr) /* list that will contain this new element */
+{
+ Itcl_ListElem *elemPtr;
+
+ if (listPoolLen > 0) {
+ elemPtr = listPool;
+ listPool = elemPtr->next;
+ --listPoolLen;
+ } else {
+ elemPtr = (Itcl_ListElem*)ckalloc((unsigned)sizeof(Itcl_ListElem));
+ }
+ elemPtr->owner = listPtr;
+ elemPtr->value = NULL;
+ elemPtr->next = NULL;
+ elemPtr->prev = NULL;
+
+ return elemPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DeleteListElem()
+ *
+ * Destroys a single element in a linked list, returning it to a pool of
+ * elements that can be later reused. Returns a pointer to the next
+ * element in the list.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_DeleteListElem(elemPtr)
+ Itcl_ListElem *elemPtr; /* list element to be deleted */
+{
+ Itcl_List *listPtr;
+ Itcl_ListElem *nextPtr;
+
+ nextPtr = elemPtr->next;
+
+ if (elemPtr->prev) {
+ elemPtr->prev->next = elemPtr->next;
+ }
+ if (elemPtr->next) {
+ elemPtr->next->prev = elemPtr->prev;
+ }
+
+ listPtr = elemPtr->owner;
+ if (elemPtr == listPtr->head) {
+ listPtr->head = elemPtr->next;
+ }
+ if (elemPtr == listPtr->tail) {
+ listPtr->tail = elemPtr->prev;
+ }
+ --listPtr->num;
+
+ if (listPoolLen < ITCL_LIST_POOL_SIZE) {
+ elemPtr->next = listPool;
+ listPool = elemPtr;
+ ++listPoolLen;
+ } else {
+ ckfree((char*)elemPtr);
+ }
+ return nextPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InsertList()
+ *
+ * Creates a new list element containing the given value and returns
+ * a pointer to it. The element is inserted at the beginning of the
+ * specified list.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_InsertList(listPtr,val)
+ Itcl_List *listPtr; /* list being modified */
+ ClientData val; /* value associated with new element */
+{
+ Itcl_ListElem *elemPtr;
+ assert(listPtr->validate == ITCL_VALID_LIST);
+
+ elemPtr = Itcl_CreateListElem(listPtr);
+
+ elemPtr->value = val;
+ elemPtr->next = listPtr->head;
+ elemPtr->prev = NULL;
+ if (listPtr->head) {
+ listPtr->head->prev = elemPtr;
+ }
+ listPtr->head = elemPtr;
+ if (listPtr->tail == NULL) {
+ listPtr->tail = elemPtr;
+ }
+ ++listPtr->num;
+
+ return elemPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_InsertListElem()
+ *
+ * Creates a new list element containing the given value and returns
+ * a pointer to it. The element is inserted in the list just before
+ * the specified element.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_InsertListElem(pos,val)
+ Itcl_ListElem *pos; /* insert just before this element */
+ ClientData val; /* value associated with new element */
+{
+ Itcl_List *listPtr;
+ Itcl_ListElem *elemPtr;
+
+ listPtr = pos->owner;
+ assert(listPtr->validate == ITCL_VALID_LIST);
+ assert(pos != NULL);
+
+ elemPtr = Itcl_CreateListElem(listPtr);
+ elemPtr->value = val;
+
+ elemPtr->prev = pos->prev;
+ if (elemPtr->prev) {
+ elemPtr->prev->next = elemPtr;
+ }
+ elemPtr->next = pos;
+ pos->prev = elemPtr;
+
+ if (listPtr->head == pos) {
+ listPtr->head = elemPtr;
+ }
+ if (listPtr->tail == NULL) {
+ listPtr->tail = elemPtr;
+ }
+ ++listPtr->num;
+
+ return elemPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AppendList()
+ *
+ * Creates a new list element containing the given value and returns
+ * a pointer to it. The element is appended at the end of the
+ * specified list.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_AppendList(listPtr,val)
+ Itcl_List *listPtr; /* list being modified */
+ ClientData val; /* value associated with new element */
+{
+ Itcl_ListElem *elemPtr;
+ assert(listPtr->validate == ITCL_VALID_LIST);
+
+ elemPtr = Itcl_CreateListElem(listPtr);
+
+ elemPtr->value = val;
+ elemPtr->prev = listPtr->tail;
+ elemPtr->next = NULL;
+ if (listPtr->tail) {
+ listPtr->tail->next = elemPtr;
+ }
+ listPtr->tail = elemPtr;
+ if (listPtr->head == NULL) {
+ listPtr->head = elemPtr;
+ }
+ ++listPtr->num;
+
+ return elemPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_AppendListElem()
+ *
+ * Creates a new list element containing the given value and returns
+ * a pointer to it. The element is inserted in the list just after
+ * the specified element.
+ * ------------------------------------------------------------------------
+ */
+Itcl_ListElem*
+Itcl_AppendListElem(pos,val)
+ Itcl_ListElem *pos; /* insert just after this element */
+ ClientData val; /* value associated with new element */
+{
+ Itcl_List *listPtr;
+ Itcl_ListElem *elemPtr;
+
+ listPtr = pos->owner;
+ assert(listPtr->validate == ITCL_VALID_LIST);
+ assert(pos != NULL);
+
+ elemPtr = Itcl_CreateListElem(listPtr);
+ elemPtr->value = val;
+
+ elemPtr->next = pos->next;
+ if (elemPtr->next) {
+ elemPtr->next->prev = elemPtr;
+ }
+ elemPtr->prev = pos;
+ pos->next = elemPtr;
+
+ if (listPtr->tail == pos) {
+ listPtr->tail = elemPtr;
+ }
+ if (listPtr->head == NULL) {
+ listPtr->head = elemPtr;
+ }
+ ++listPtr->num;
+
+ return elemPtr;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_SetListValue()
+ *
+ * Modifies the value associated with a list element.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_SetListValue(elemPtr,val)
+ Itcl_ListElem *elemPtr; /* list element being modified */
+ ClientData val; /* new value associated with element */
+{
+ Itcl_List *listPtr = elemPtr->owner;
+ assert(listPtr->validate == ITCL_VALID_LIST);
+ assert(elemPtr != NULL);
+
+ elemPtr->value = val;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_FinishList()
+ *
+ * free all memory used in the list pool
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_FinishList()
+{
+ Itcl_ListElem *listPtr;
+ Itcl_ListElem *elemPtr;
+
+ listPtr = listPool;
+ while (listPtr != NULL) {
+ elemPtr = listPtr;
+ listPtr = elemPtr->next;
+ ckfree((char *)elemPtr);
+ elemPtr = NULL;
+ }
+ listPool = NULL;
+ listPoolLen = 0;
+}
+
+
+/*
+ * ========================================================================
+ * REFERENCE-COUNTED DATA
+ *
+ * The following procedures manage generic reference-counted data.
+ * They are similar in spirit to the Tcl_Preserve/Tcl_Release
+ * procedures defined in the Tcl/Tk core. But these procedures use
+ * a hash table instead of a linked list to maintain the references,
+ * so they scale better. Also, the Tcl procedures have a bad behavior
+ * during the "exit" command. Their exit handler shuts them down
+ * when other data is still being reference-counted and cleaned up.
+ *
+ * ------------------------------------------------------------------------
+ * Itcl_EventuallyFree()
+ *
+ * Registers a piece of data so that it will be freed when no longer
+ * in use. The data is registered with an initial usage count of "0".
+ * Future calls to Itcl_PreserveData() increase this usage count, and
+ * calls to Itcl_ReleaseData() decrease the count until it reaches
+ * zero and the data is freed.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_EventuallyFree(
+ ClientData cdata, /* data to be freed when not in use */
+ Tcl_FreeProc *fproc) /* procedure called to free data */
+{
+ /*
+ * If the clientData value is NULL, do nothing.
+ */
+ if (cdata == NULL) {
+ return;
+ }
+ Tcl_EventuallyFree(cdata, fproc);
+ return;
+
+}
+#ifdef ITCL_PRESERVE_DEBUG
+void
+Itcl_DbDumpPreserveInfo(
+ const char *fileName)
+{
+ FOREACH_HASH_DECLS;
+ FILE *fd;
+ ItclPreserveInfo *ipiPtr;
+ ItclPreserveInfoEntry *ipiePtr;
+ size_t j;
+
+ if (fileName == NULL) {
+ fd = stderr;
+ } else {
+ fd = fopen(fileName, "w");
+ }
+ fprintf(fd, "type\taddr\tfile\tline\n");
+ FOREACH_HASH_VALUE(ipiPtr, &itclPreserveInfos) {
+ if (ipiPtr->refCount == 0) {
+ continue;
+ }
+ fprintf(stderr, "DAT!%p!%" TCL_LL_MODIFIER "u!\n", ipiPtr->clientData, (Tcl_WideUInt) ipiPtr->refCount);
+ for (j = 0; j < ipiPtr->numEntries; j++) {
+ ipiePtr = &ipiPtr->entries[j];
+ if (ipiePtr->type != ITCL_PRESERVE_DELETED) {
+ fprintf(fd, "%s\t%p\t%s\t%d\n",
+ ipiePtr->type == ITCL_PRESERVE_INCR ? "INCR" : "DECR",
+ ipiPtr->clientData, ipiePtr->fileName, ipiePtr->line);
+ }
+ }
+ }
+ if (fd != stderr) {
+ fclose(fd);
+ }
+}
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_PreserveData()
+ *
+ * Increases the usage count for a piece of data that will be freed
+ * later when no longer needed. Each call to Itcl_PreserveData()
+ * puts one claim on a piece of data, and subsequent calls to
+ * Itcl_ReleaseData() remove those claims. When Itcl_EventuallyFree()
+ * is called, and when the usage count reaches zero, the data is
+ * freed.
+ * ------------------------------------------------------------------------
+ */
+#ifdef ITCL_PRESERVE_DEBUG
+void
+ItclDbgPreserveData(
+ ClientData cdata, /* data to be preserved */
+ int line,
+ const char *file)
+{
+
+ /*
+ * If the clientData value is NULL, do nothing.
+ */
+ if (cdata == NULL) {
+ return;
+ }
+ {
+ Tcl_HashEntry *hPtr;
+ ItclPreserveInfo *ipiPtr;
+ ItclPreserveInfoEntry *ipiePtr;
+ int isNew;
+
+ if (!itclPreserveInfoInitted) {
+ Tcl_InitHashTable(&itclPreserveInfos, TCL_ONE_WORD_KEYS);
+ itclPreserveInfoInitted = 1;
+ }
+ hPtr = Tcl_CreateHashEntry(&itclPreserveInfos, cdata, &isNew);
+ if (isNew) {
+ ipiPtr = (ItclPreserveInfo *)ckalloc(sizeof(ItclPreserveInfo));
+ ipiPtr->refCount = 0;
+ ipiPtr->size = ITCL_PRESERVE_BUCKET_SIZE;
+ ipiPtr->numEntries = 0;
+ ipiPtr->clientData = cdata;
+ ipiPtr->entries = (ItclPreserveInfoEntry *)malloc(
+ sizeof(ItclPreserveInfoEntry) * ipiPtr->size);
+ Tcl_SetHashValue(hPtr, ipiPtr);
+ }
+ ipiPtr = Tcl_GetHashValue(hPtr);
+ if (ipiPtr->numEntries >= ipiPtr->size) {
+ ipiPtr->size += ITCL_PRESERVE_BUCKET_SIZE;
+ ipiPtr->entries = (ItclPreserveInfoEntry *)
+ realloc((char *)ipiPtr->entries,
+ sizeof(ItclPreserveInfoEntry) *
+ ipiPtr->size);
+ }
+ ipiePtr = &ipiPtr->entries[ipiPtr->numEntries++];
+ ipiePtr->type = ITCL_PRESERVE_INCR;
+ ipiePtr->line = line;
+ ipiePtr->fileName = file;
+ ipiPtr->refCount++;
+ }
+
+ Tcl_Preserve(cdata);
+ return;
+}
+# else
+void
+Itcl_PreserveData(
+ ClientData cdata) /* data to be preserved */
+{
+
+ /*
+ * If the clientData value is NULL, do nothing.
+ */
+ if (cdata == NULL) {
+ return;
+ }
+ Tcl_Preserve(cdata);
+ return;
+}
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ReleaseData()
+ *
+ * Decreases the usage count for a piece of data that was registered
+ * previously via Itcl_PreserveData(). After Itcl_EventuallyFree()
+ * is called and the usage count reaches zero, the data is
+ * automatically freed.
+ * ------------------------------------------------------------------------
+ */
+#ifdef ITCL_PRESERVE_DEBUG
+void
+ItclDbgReleaseData(
+ ClientData cdata, /* data to be released */
+ int line,
+ const char *file)
+{
+
+ int noDelete = 0;
+
+ /*
+ * If the clientData value is NULL, do nothing.
+ */
+ if (cdata == NULL) {
+ return;
+ }
+ {
+ Tcl_HashEntry *hPtr;
+ ItclPreserveInfo *ipiPtr;
+ ItclPreserveInfoEntry *ipiePtr;
+
+ if (!itclPreserveInfoInitted) {
+ Tcl_InitHashTable(&itclPreserveInfos, TCL_ONE_WORD_KEYS);
+ itclPreserveInfoInitted = 1;
+ }
+ hPtr = Tcl_FindHashEntry(&itclPreserveInfos, cdata);
+ if (hPtr != NULL) {
+ ipiPtr = Tcl_GetHashValue(hPtr);
+ if (ipiPtr->numEntries >= ipiPtr->size) {
+ ipiPtr->size += ITCL_PRESERVE_BUCKET_SIZE;
+ ipiPtr->entries = (ItclPreserveInfoEntry *)
+ realloc((char *)ipiPtr->entries,
+ sizeof(ItclPreserveInfoEntry) *
+ ipiPtr->size);
+ }
+ ipiePtr = &ipiPtr->entries[ipiPtr->numEntries++];
+ ipiePtr->type = ITCL_PRESERVE_DECR;
+ ipiePtr->line = line;
+ ipiePtr->fileName = file;
+ if (ipiPtr->refCount-- == 0) {
+ fprintf(stderr, "REFCOUNT < 0 for: %p!\n", cdata);
+ noDelete = 1;
+ }
+ }
+ }
+ if (!noDelete) {
+ Tcl_Release(cdata);
+ }
+ return;
+}
+#else
+void
+Itcl_ReleaseData(
+ ClientData cdata) /* data to be released */
+{
+
+ /*
+ * If the clientData value is NULL, do nothing.
+ */
+ if (cdata == NULL) {
+ return;
+ }
+ Tcl_Release(cdata);
+ return;
+}
+#endif
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_SaveInterpState()
+ *
+ * Takes a snapshot of the current result state of the interpreter.
+ * The snapshot can be restored at any point by Itcl_RestoreInterpState.
+ * So if you are in the middle of building a return result, you can
+ * snapshot the interpreter, execute a command that might generate an
+ * error, restore the snapshot, and continue building the result string.
+ *
+ * Once a snapshot is saved, it must be restored by calling
+ * Itcl_RestoreInterpState, or discarded by calling
+ * Itcl_DiscardInterpState. Otherwise, memory will be leaked.
+ *
+ * Returns a token representing the state of the interpreter.
+ * ------------------------------------------------------------------------
+ */
+Itcl_InterpState
+Itcl_SaveInterpState(interp, status)
+ Tcl_Interp* interp; /* interpreter being modified */
+ int status; /* integer status code for current operation */
+{
+ return (Itcl_InterpState) Tcl_SaveInterpState(interp, status);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_RestoreInterpState()
+ *
+ * Restores the state of the interpreter to a snapshot taken by
+ * Itcl_SaveInterpState. This affects variables such as "errorInfo"
+ * and "errorCode". After this call, the token for the interpreter
+ * state is no longer valid.
+ *
+ * Returns the status code that was pending at the time the state was
+ * captured.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_RestoreInterpState(interp, state)
+ Tcl_Interp* interp; /* interpreter being modified */
+ Itcl_InterpState state; /* token representing interpreter state */
+{
+ return Tcl_RestoreInterpState(interp, (Tcl_InterpState)state);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DiscardInterpState()
+ *
+ * Frees the memory associated with an interpreter snapshot taken by
+ * Itcl_SaveInterpState. If the snapshot is not restored, this
+ * procedure must be called to discard it, or the memory will be lost.
+ * After this call, the token for the interpreter state is no longer
+ * valid.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_DiscardInterpState(state)
+ Itcl_InterpState state; /* token representing interpreter state */
+{
+ Tcl_DiscardInterpState((Tcl_InterpState)state);
+ return;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_Protection()
+ *
+ * Used to query/set the protection level used when commands/variables
+ * are defined within a class. The default protection level (when
+ * no public/protected/private command is active) is ITCL_DEFAULT_PROTECT.
+ * In the default case, new commands are treated as public, while new
+ * variables are treated as protected.
+ *
+ * If the specified level is 0, then this procedure returns the
+ * current value without changing it. Otherwise, it sets the current
+ * value to the specified protection level, and returns the previous
+ * value.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_Protection(interp, newLevel)
+ Tcl_Interp *interp; /* interpreter being queried */
+ int newLevel; /* new protection level or 0 */
+{
+ int oldVal;
+ ItclObjectInfo *infoPtr;
+
+ /*
+ * If a new level was specified, then set the protection level.
+ * In any case, return the protection level as it stands right now.
+ */
+ infoPtr = (ItclObjectInfo*) Tcl_GetAssocData(interp, ITCL_INTERP_DATA,
+ (Tcl_InterpDeleteProc**)NULL);
+
+ assert(infoPtr != NULL);
+ oldVal = infoPtr->protection;
+
+ if (newLevel != 0) {
+ assert(newLevel == ITCL_PUBLIC ||
+ newLevel == ITCL_PROTECTED ||
+ newLevel == ITCL_PRIVATE ||
+ newLevel == ITCL_DEFAULT_PROTECT);
+ infoPtr->protection = newLevel;
+ }
+ return oldVal;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_ParseNamespPath()
+ *
+ * Parses a reference to a namespace element of the form:
+ *
+ * namesp::namesp::namesp::element
+ *
+ * Returns pointers to the head part ("namesp::namesp::namesp")
+ * and the tail part ("element"). If the head part is missing,
+ * a NULL pointer is returned and the rest of the string is taken
+ * as the tail.
+ *
+ * Both head and tail point to locations within the given dynamic
+ * string buffer. This buffer must be uninitialized when passed
+ * into this procedure, and it must be freed later on, when the
+ * strings are no longer needed.
+ * ------------------------------------------------------------------------
+ */
+void
+Itcl_ParseNamespPath(
+ const char *name, /* path name to class member */
+ Tcl_DString *buffer, /* dynamic string buffer (uninitialized) */
+ const char **head, /* returns "namesp::namesp::namesp" part */
+ const char **tail) /* returns "element" part */
+{
+ register char *sep, *newname;
+
+ Tcl_DStringInit(buffer);
+
+ /*
+ * Copy the name into the buffer and parse it. Look
+ * backward from the end of the string to the first '::'
+ * scope qualifier.
+ */
+ Tcl_DStringAppend(buffer, name, -1);
+ newname = Tcl_DStringValue(buffer);
+
+ for (sep=newname; *sep != '\0'; sep++)
+ ;
+
+ while (--sep > newname) {
+ if (*sep == ':' && *(sep-1) == ':') {
+ break;
+ }
+ }
+
+ /*
+ * Found head/tail parts. If there are extra :'s, keep backing
+ * up until the head is found. This supports the Tcl namespace
+ * behavior, which allows names like "foo:::bar".
+ */
+ if (sep > newname) {
+ *tail = sep+1;
+ while (sep > newname && *(sep-1) == ':') {
+ sep--;
+ }
+ *sep = '\0';
+ *head = newname;
+ } else {
+
+ /*
+ * No :: separators--the whole name is treated as a tail.
+ */
+ *tail = newname;
+ *head = NULL;
+ }
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CanAccess2()
+ *
+ * Checks to see if a class member can be accessed from a particular
+ * namespace context. Public things can always be accessed. Protected
+ * things can be accessed if the "from" namespace appears in the
+ * inheritance hierarchy of the class namespace. Private things
+ * can be accessed only if the "from" namespace is the same as the
+ * class that contains them.
+ *
+ * Returns 1/0 indicating true/false.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CanAccess2(
+ ItclClass *iclsPtr, /* class being tested */
+ int protection, /* protection level being tested */
+ Tcl_Namespace* fromNsPtr) /* namespace requesting access */
+{
+ ItclClass* fromIclsPtr;
+ Tcl_HashEntry *entry;
+
+ /*
+ * If the protection level is "public" or "private", then the
+ * answer is known immediately.
+ */
+ if (protection == ITCL_PUBLIC) {
+ return 1;
+ } else {
+ if (protection == ITCL_PRIVATE) {
+ entry = Tcl_FindHashEntry(&iclsPtr->infoPtr->namespaceClasses,
+ fromNsPtr);
+ if (entry == NULL) {
+ return 0;
+ }
+ return (iclsPtr == Tcl_GetHashValue(entry));
+ }
+ }
+
+ /*
+ * If the protection level is "protected", then check the
+ * heritage of the namespace requesting access. If cdefnPtr
+ * is in the heritage, then access is allowed.
+ */
+ assert (protection == ITCL_PROTECTED);
+
+ if (Itcl_IsClassNamespace(fromNsPtr)) {
+ entry = Tcl_FindHashEntry(&iclsPtr->infoPtr->namespaceClasses,
+ fromNsPtr);
+ if (entry == NULL) {
+ return 0;
+ }
+ fromIclsPtr = Tcl_GetHashValue(entry);
+
+ entry = Tcl_FindHashEntry(&fromIclsPtr->heritage,
+ (char*)iclsPtr);
+
+ if (entry) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CanAccess()
+ *
+ * Checks to see if a class member can be accessed from a particular
+ * namespace context. Public things can always be accessed. Protected
+ * things can be accessed if the "from" namespace appears in the
+ * inheritance hierarchy of the class namespace. Private things
+ * can be accessed only if the "from" namespace is the same as the
+ * class that contains them.
+ *
+ * Returns 1/0 indicating true/false.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CanAccess(
+ ItclMemberFunc* imPtr, /* class member being tested */
+ Tcl_Namespace* fromNsPtr) /* namespace requesting access */
+{
+ return Itcl_CanAccess2(imPtr->iclsPtr, imPtr->protection, fromNsPtr);
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_CanAccessFunc()
+ *
+ * Checks to see if a member function with the specified protection
+ * level can be accessed from a particular namespace context. This
+ * follows the same rules enforced by Itcl_CanAccess, but adds one
+ * special case: If the function is a protected method, and if the
+ * current context is a base class that has the same method, then
+ * access is allowed.
+ *
+ * Returns 1/0 indicating true/false.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_CanAccessFunc(
+ ItclMemberFunc* imPtr, /* member function being tested */
+ Tcl_Namespace* fromNsPtr) /* namespace requesting access */
+{
+ ItclClass *iclsPtr;
+ ItclClass *fromIclsPtr;
+ ItclMemberFunc *ovlfunc;
+ Tcl_HashEntry *entry;
+
+ /*
+ * Apply the usual rules first.
+ */
+ if (Itcl_CanAccess(imPtr, fromNsPtr)) {
+ return 1;
+ }
+
+ /*
+ * As a last resort, see if the namespace is really a base
+ * class of the class containing the method. Look for a
+ * method with the same name in the base class. If there
+ * is one, then this method overrides it, and the base class
+ * has access.
+ */
+ if ((imPtr->flags & ITCL_COMMON) == 0 &&
+ Itcl_IsClassNamespace(fromNsPtr)) {
+ Tcl_HashEntry *hPtr;
+
+ iclsPtr = imPtr->iclsPtr;
+ hPtr = Tcl_FindHashEntry(&iclsPtr->infoPtr->namespaceClasses,
+ (char *)fromNsPtr);
+ if (hPtr == NULL) {
+ return 0;
+ }
+ fromIclsPtr = Tcl_GetHashValue(hPtr);
+
+ if (Tcl_FindHashEntry(&iclsPtr->heritage, (char*)fromIclsPtr)) {
+ entry = Tcl_FindHashEntry(&fromIclsPtr->resolveCmds,
+ (char *)imPtr->namePtr);
+
+ if (entry) {
+ ItclCmdLookup *clookup;
+ clookup = (ItclCmdLookup *)Tcl_GetHashValue(entry);
+ ovlfunc = clookup->imPtr;
+ if ((ovlfunc->flags & ITCL_COMMON) == 0 &&
+ ovlfunc->protection < ITCL_PRIVATE) {
+ return 1;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+
+/*
+ * ------------------------------------------------------------------------
+ * Itcl_DecodeScopedCommand()
+ *
+ * Decodes a scoped command of the form:
+ *
+ * namespace inscope <namesp> <command>
+ *
+ * If the given string is not a scoped value, this procedure does
+ * nothing and returns TCL_OK. If the string is a scoped value,
+ * then it is decoded, and the namespace, and the simple command
+ * string are returned as arguments; the simple command should
+ * be freed when no longer in use. If anything goes wrong, this
+ * procedure returns TCL_ERROR, along with an error message in
+ * the interpreter.
+ * ------------------------------------------------------------------------
+ */
+int
+Itcl_DecodeScopedCommand(
+ Tcl_Interp *interp, /* current interpreter */
+ const char *name, /* string to be decoded */
+ Tcl_Namespace **rNsPtr, /* returns: namespace for scoped value */
+ char **rCmdPtr) /* returns: simple command word */
+{
+ Tcl_Namespace *nsPtr;
+ char *cmdName;
+ const char *pos;
+ const char **listv;
+ int listc;
+ int result;
+ int len;
+
+ nsPtr = NULL;
+ len = strlen(name);
+ cmdName = ckalloc((unsigned)strlen(name)+1);
+ strcpy(cmdName, name);
+
+ if ((*name == 'n') && (len > 17) && (strncmp(name, "namespace", 9) == 0)) {
+ for (pos = (name + 9); (*pos == ' '); pos++) {
+ /* empty body: skip over spaces */
+ }
+ if ((*pos == 'i') && ((pos + 7) <= (name + len))
+ && (strncmp(pos, "inscope", 7) == 0)) {
+
+ result = Tcl_SplitList(interp, (const char *)name, &listc,
+ &listv);
+ if (result == TCL_OK) {
+ if (listc != 4) {
+ Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),
+ "malformed command \"", name, "\": should be \"",
+ "namespace inscope namesp command\"",
+ (char*)NULL);
+ result = TCL_ERROR;
+ } else {
+ nsPtr = Tcl_FindNamespace(interp, listv[2],
+ (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);
+
+ if (nsPtr == NULL) {
+ result = TCL_ERROR;
+ } else {
+ ckfree(cmdName);
+ cmdName = ckalloc((unsigned)(strlen(listv[3])+1));
+ strcpy(cmdName, listv[3]);
+ }
+ }
+ }
+ ckfree((char*)listv);
+
+ if (result != TCL_OK) {
+ Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
+ "\n (while decoding scoped command \"%s\")",
+ name));
+ ckfree(cmdName);
+ return TCL_ERROR;
+ }
+ }
+ }
+
+ *rNsPtr = nsPtr;
+ *rCmdPtr = cmdName;
+ return TCL_OK;
+}
+
+#ifdef ITCL_PRESERVE_DEBUG
+#undef Itcl_PreserveData
+#undef Itcl_ReleaseData
+
+void
+Itcl_PreserveData(
+ ClientData cdata)
+{
+ ItclDbgPreserveData(cdata, 0, "");
+}
+
+void
+Itcl_ReleaseData(
+ ClientData cdata)
+{
+ ItclDbgReleaseData(cdata, 0, "");
+}
+#endif
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclVCInt.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclVCInt.h
new file mode 100644
index 0000000..93ba54f
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclVCInt.h
@@ -0,0 +1,37 @@
+#define ITCL_RESOLVE_DATA "ITCL_Resolve_Info"
+
+typedef struct ItclResolvngInfo {
+ Tcl_Interp *interp;
+ Tcl_HashTable resolveVars; /* all possible names for variables in
+ * this class (e.g., x, foo::x, etc.) */
+ Tcl_HashTable resolveCmds; /* all possible names for functions in
+ * this class (e.g., x, foo::x, etc.) */
+ ItclCheckClassProtection *varProtFcn;
+ ItclCheckClassProtection *cmdProtFcn;
+ Tcl_HashTable objectVarsTables;
+ Tcl_HashTable objectCmdsTables;
+} ItclResolvingInfo;
+
+typedef struct ObjectVarInfo {
+ ClientData clientData;
+ ItclObject *ioPtr;
+ Tcl_Var varPtr;
+} ObjectVarInfo;
+
+typedef struct ObjectVarTableInfo {
+ Tcl_HashTable varInfos;
+ TclVarHashTable *tablePtr;
+} ObjectVarTableInfo;
+
+typedef struct ObjectCmdInfo {
+ ClientData clientData;
+ ItclObject *ioPtr;
+ Tcl_Command cmdPtr;
+} ObjectCmdInfo;
+
+typedef struct ObjectCmdTableInfo {
+ Tcl_HashTable cmdInfos;
+ Tcl_HashTable *tablePtr;
+} ObjectCmdTableInfo;
+
+
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.c b/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.c
new file mode 100644
index 0000000..0511d14
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.c
@@ -0,0 +1,234 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * These procedures handle command and variable resolution
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ *
+ * ========================================================================
+ * Copyright (c) Arnulf Wiedemann
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+#include <tclInt.h>
+#include "itclInt.h"
+#include "itclVCInt.h"
+
+#ifdef NEW_PROTO_RESOLVER
+static void
+ItclDeleteResolveInfo(
+ ClientData clientData,
+ Tcl_Interp *interp)
+{
+ ckfree((char *)clientData);
+}
+#endif
+
+int
+ItclVarsAndCommandResolveInit(
+ Tcl_Interp *interp)
+{
+#ifdef NEW_PROTO_RESOLVER
+ ItclResolvingInfo *iriPtr;
+
+ /*
+ * Create the top-level data structure for tracking objects.
+ * Store this as "associated data" for easy access, but link
+ * it to the itcl namespace for ownership.
+ */
+ iriPtr = (ItclResolvingInfo*)ckalloc(sizeof(ItclResolvingInfo));
+ memset(iriPtr, 0, sizeof(ItclResolvingInfo));
+ iriPtr->interp = interp;
+ Tcl_InitHashTable(&iriPtr->resolveVars, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iriPtr->resolveCmds, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iriPtr->objectVarsTables, TCL_ONE_WORD_KEYS);
+ Tcl_InitHashTable(&iriPtr->objectCmdsTables, TCL_ONE_WORD_KEYS);
+
+ Tcl_SetAssocData(interp, ITCL_RESOLVE_DATA,
+ (Tcl_InterpDeleteProc*)ItclDeleteResolveInfo, (ClientData)iriPtr);
+ Tcl_Preserve((ClientData)iriPtr);
+
+ Itcl_SetClassCommandProtectionCallback(interp, NULL,
+ Itcl_CheckClassCommandProtection);
+ Itcl_SetClassVariableProtectionCallback(interp, NULL,
+ Itcl_CheckClassVariableProtection);
+#endif
+ return TCL_OK;
+}
+
+ClientData
+Itcl_RegisterClassVariable(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *varName,
+ ClientData clientData)
+{
+ Tcl_HashTable *tablePtr;
+ Tcl_HashEntry *hPtr;
+ ItclResolvingInfo *iriPtr;
+ int isNew;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_CreateHashEntry(&iriPtr->resolveVars, nsPtr->fullName, &isNew);
+ if (isNew) {
+ tablePtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+ Tcl_SetHashValue(hPtr, tablePtr);
+
+ } else {
+ tablePtr = Tcl_GetHashValue(hPtr);
+ }
+ hPtr = Tcl_CreateHashEntry(tablePtr, varName, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, clientData);
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+ClientData
+Itcl_RegisterClassCommand(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ const char *cmdName,
+ ClientData clientData)
+{
+ Tcl_HashEntry *hPtr;
+ Tcl_HashTable *tablePtr;
+ ItclResolvingInfo *iriPtr;
+ int isNew;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_CreateHashEntry(&iriPtr->resolveCmds, nsPtr->fullName, &isNew);
+ if (isNew) {
+ tablePtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
+ Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS);
+ Tcl_SetHashValue(hPtr, tablePtr);
+
+ } else {
+ tablePtr = Tcl_GetHashValue(hPtr);
+ }
+ hPtr = Tcl_CreateHashEntry(tablePtr, cmdName, &isNew);
+ if (isNew) {
+ Tcl_SetHashValue(hPtr, clientData);
+ }
+ return Tcl_GetHashValue(hPtr);
+}
+
+Tcl_Var
+Itcl_RegisterObjectVariable(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ const char *varName,
+ ClientData clientData,
+ Tcl_Var varPtr,
+ Tcl_Namespace *nsPtr)
+{
+ Tcl_HashEntry *hPtr;
+ ItclResolvingInfo *iriPtr;
+ ObjectVarTableInfo *ovtiPtr;
+ ObjectVarInfo *oviPtr;
+ int isNew;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_CreateHashEntry(&iriPtr->objectVarsTables,
+ (char *)ioPtr, &isNew);
+ if (isNew) {
+ ovtiPtr = (ObjectVarTableInfo *)ckalloc(sizeof(ObjectVarTableInfo));
+ Tcl_InitHashTable(&ovtiPtr->varInfos, TCL_ONE_WORD_KEYS);
+ ovtiPtr->tablePtr = &((Namespace *)nsPtr)->varTable;
+ Tcl_SetHashValue(hPtr, ovtiPtr);
+ } else {
+ ovtiPtr = Tcl_GetHashValue(hPtr);
+ }
+ hPtr = Tcl_CreateHashEntry(&ovtiPtr->varInfos, (char *)clientData, &isNew);
+ if (isNew) {
+ oviPtr = (ObjectVarInfo *)ckalloc(sizeof(ObjectVarInfo));
+ memset(oviPtr, 0, sizeof(ObjectVarInfo));
+ Tcl_SetHashValue(hPtr, oviPtr);
+ } else {
+ oviPtr = Tcl_GetHashValue(hPtr);
+ }
+ oviPtr->clientData = clientData;
+ oviPtr->ioPtr = ioPtr;
+ if (varPtr == NULL) {
+ varPtr = Tcl_NewNamespaceVar(interp, nsPtr, varName);
+ }
+ oviPtr->varPtr = varPtr;
+ return varPtr;
+}
+
+Tcl_Command
+Itcl_RegisterObjectCommand(
+ Tcl_Interp *interp,
+ ItclObject *ioPtr,
+ const char *cmdName,
+ ClientData clientData,
+ Tcl_Command cmdPtr,
+ Tcl_Namespace *nsPtr)
+{
+ Tcl_HashEntry *hPtr;
+ ItclResolvingInfo *iriPtr;
+ ObjectCmdTableInfo *octiPtr;
+ ObjectCmdInfo *ociPtr;
+ int isNew;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ hPtr = Tcl_CreateHashEntry(&iriPtr->objectCmdsTables,
+ (char *)ioPtr, &isNew);
+ if (isNew) {
+ octiPtr = (ObjectCmdTableInfo *)ckalloc(sizeof(ObjectCmdTableInfo));
+ Tcl_InitHashTable(&octiPtr->cmdInfos, TCL_ONE_WORD_KEYS);
+ octiPtr->tablePtr = &((Namespace *)nsPtr)->cmdTable;
+ Tcl_SetHashValue(hPtr, octiPtr);
+ } else {
+ octiPtr = Tcl_GetHashValue(hPtr);
+ }
+ hPtr = Tcl_CreateHashEntry(&octiPtr->cmdInfos, (char *)clientData, &isNew);
+ if (isNew) {
+ ociPtr = (ObjectCmdInfo *)ckalloc(sizeof(ObjectCmdInfo));
+ memset(ociPtr, 0, sizeof(ObjectCmdInfo));
+ Tcl_SetHashValue(hPtr, ociPtr);
+ } else {
+ ociPtr = Tcl_GetHashValue(hPtr);
+ }
+ ociPtr->clientData = clientData;
+ ociPtr->ioPtr = ioPtr;
+ if (cmdPtr == NULL) {
+/*
+ cmdPtr = Tcl_NewNamespaceVar(interp, nsPtr, varName);
+*/
+ }
+ ociPtr->cmdPtr = cmdPtr;
+ return cmdPtr;
+}
+
+int
+Itcl_SetClassVariableProtectionCallback(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ ItclCheckClassProtection *fcnPtr)
+{
+ ItclResolvingInfo *iriPtr;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ iriPtr->varProtFcn = fcnPtr;
+ return TCL_OK;
+}
+
+int
+Itcl_SetClassCommandProtectionCallback(
+ Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr,
+ ItclCheckClassProtection *fcnPtr)
+{
+ ItclResolvingInfo *iriPtr;
+
+ iriPtr = Tcl_GetAssocData(interp, ITCL_RESOLVE_DATA, NULL);
+ iriPtr->cmdProtFcn = fcnPtr;
+ return TCL_OK;
+}
diff --git a/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.h b/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.h
new file mode 100644
index 0000000..966806b
--- /dev/null
+++ b/tcl8.6/pkgs/itcl4.1.1/generic/itclVarsAndCmds.h
@@ -0,0 +1,46 @@
+/*
+ * ------------------------------------------------------------------------
+ * PACKAGE: [incr Tcl]
+ * DESCRIPTION: Object-Oriented Extensions to Tcl
+ *
+ * These procedures handle command and variable resolution
+ *
+ * ========================================================================
+ * AUTHOR: Arnulf Wiedemann
+ *
+ * ========================================================================
+ * Copyright (c) Arnulf Wiedemann
+ * ------------------------------------------------------------------------
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ */
+
+typedef int (ItclCheckClassProtection)(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *varName, ClientData clientData);
+
+ClientData Itcl_RegisterClassVariable(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, const char *varName, ClientData clientData);
+
+Tcl_Var Itcl_RegisterObjectVariable( Tcl_Interp *interp, ItclObject *ioPtr,
+ const char *varName, ClientData clientData, Tcl_Var varPtr,
+ Tcl_Namespace *nsPtr);
+
+ClientData Itcl_RegisterClassCommand(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ const char *cmdName, ClientData clientData);
+
+Tcl_Command Itcl_RegisterObjectCommand( Tcl_Interp *interp, ItclObject *ioPtr,
+ const char *cmdName, ClientData clientData, Tcl_Command cmdPtr,
+ Tcl_Namespace *nsPtr);
+
+int Itcl_CheckClassVariableProtection(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ const char *varName, ClientData clientData);
+
+int Itcl_CheckClassCommandProtection(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
+ const char *cmdName, ClientData clientData);
+
+int Itcl_SetClassVariableProtectionCallback(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, ItclCheckClassProtection *fcnPtr);
+
+int Itcl_SetClassCommandProtectionCallback(Tcl_Interp *interp,
+ Tcl_Namespace *nsPtr, ItclCheckClassProtection *fcnPtr);
+