Index: generic/nsf.c =================================================================== diff -u -ra02e56f649d5466d4f240350ac4551b7385d1f53 -ra1104c7d659bdf1eb764a98eb5e5a39f7dfe493d --- generic/nsf.c (.../nsf.c) (revision a02e56f649d5466d4f240350ac4551b7385d1f53) +++ generic/nsf.c (.../nsf.c) (revision a1104c7d659bdf1eb764a98eb5e5a39f7dfe493d) @@ -5,10 +5,10 @@ * for supporting language oriented programming. For Details, see * http://next-scripting.org/ * - * Copyright (C) 1999-2012 Gustaf Neumann (a) (b) + * Copyright (C) 1999-2013 Gustaf Neumann (a) (b) * Copyright (C) 1999-2007 Uwe Zdun (a) (b) * Copyright (C) 2007-2008 Martin Matuska (b) - * Copyright (C) 2010-2012 Stefan Sobernig (b) + * Copyright (C) 2010-2013 Stefan Sobernig (b) * * * (a) University of Essen @@ -299,7 +299,9 @@ NsfObject *object, int processFlags, NsfParamDefs *paramDefs, Tcl_Obj *methodNameObj, int objc, Tcl_Obj *CONST objv[]); static int ParameterCheck(Tcl_Interp *interp, Tcl_Obj *paramObjPtr, Tcl_Obj *valueObj, - const char *argNamePrefix, int doCheckArguments, Nsf_Param **paramPtrPtr); + const char *argNamePrefix, int doCheckArguments, + int isNamed, int doConfigureParameter, + Nsf_Param **paramPtrPtr); static void ParamDefsRefCountIncr(NsfParamDefs *paramDefs); static void ParamDefsRefCountDecr(NsfParamDefs *paramDefs); static int ParamSetFromAny(Tcl_Interp *interp, register Tcl_Obj *objPtr); @@ -1303,7 +1305,7 @@ static int NsfCallObjectUnknownHandler(Tcl_Interp *interp, Tcl_Obj *nameObj) { - int result = 0; + int result; Tcl_Obj *ov[3]; /*fprintf(stderr, "try ::nsf::object::unknown for '%s'\n", ObjStr(nameObj));*/ @@ -2706,6 +2708,7 @@ if (NsfObjectIsClass(object)) { return ((NsfClass *)object)->osPtr; } + assert(object->cl); return object->cl->osPtr; } @@ -5065,7 +5068,6 @@ static Tcl_Obj * AutonameIncr(Tcl_Interp *interp, Tcl_Obj *nameObj, NsfObject *object, int instanceOpt, int resetOpt) { - int valueLength; Tcl_Obj *valueObj, *resultObj = NULL; int flogs = TCL_LEAVE_ERR_MSG; CallFrame frame, *framePtr = &frame; @@ -5142,7 +5144,7 @@ } } if (format) { - Tcl_Obj *savedResultObj = NULL; + Tcl_Obj *savedResultObj; ALLOC_ON_STACK(Tcl_Obj*, 3, ov); savedResultObj = Tcl_GetObjResult(interp); @@ -5163,9 +5165,9 @@ FREE_ON_STACK(Tcl_Obj*, ov); } else { - char *valueString = Tcl_GetStringFromObj(valueObj, &valueLength); + char *valueString = Tcl_GetString(valueObj); - Tcl_AppendLimitedToObj(resultObj, valueString, valueLength, INT_MAX, NULL); + Tcl_AppendLimitedToObj(resultObj, valueString, valueObj->length, INT_MAX, NULL); /*fprintf(stderr, "+++ append to obj done\n");*/ } } @@ -5538,9 +5540,8 @@ */ static void CmdListFree(NsfCmdList **cmdList, NsfFreeCmdListClientData *freeFct) { - NsfCmdList *del; while (*cmdList) { - del = *cmdList; + NsfCmdList *del = *cmdList; *cmdList = (*cmdList)->nextPtr; CmdListDeleteCmdListEntry(del, freeFct); } @@ -5626,12 +5627,11 @@ */ static void TclObjListFreeList(NsfTclObjList *list) { - NsfTclObjList *del; while (list) { - del = list; + NsfTclObjList *del = list; list = list->nextPtr; DECR_REF_COUNT2("listContent", del->content); - if (del->payload) {DECR_REF_COUNT2("listContent", del->payload);} + if (del->payload) {DECR_REF_COUNT2("listPayload", del->payload);} FREE(NsfTclObjList, del); } } @@ -5744,21 +5744,6 @@ return listObj; } -/* append a string of pre and post assertions to a method body */ -static void -AssertionAppendPrePost(Tcl_Interp *interp, Tcl_DString *dsPtr, NsfProcAssertion *procs) { - if (procs) { - Tcl_Obj *preCondition = AssertionList(interp, procs->pre); - Tcl_Obj *postCondition = AssertionList(interp, procs->post); - INCR_REF_COUNT(preCondition); INCR_REF_COUNT(postCondition); - Tcl_DStringAppendElement(dsPtr, "-precondition"); - Tcl_DStringAppendElement(dsPtr, ObjStr(preCondition)); - Tcl_DStringAppendElement(dsPtr, "-postcondition"); - Tcl_DStringAppendElement(dsPtr, ObjStr(postCondition)); - DECR_REF_COUNT(preCondition); DECR_REF_COUNT(postCondition); - } -} - static int AssertionListCheckOption(Tcl_Interp *interp, NsfObject *object) { NsfObjectOpt *opt = object->opt; @@ -5791,9 +5776,8 @@ static void AssertionRemoveProc(NsfAssertionStore *aStore, CONST char *name) { - Tcl_HashEntry *hPtr; if (aStore) { - hPtr = Tcl_CreateHashEntry(&aStore->procs, name, NULL); + Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(&aStore->procs, name, NULL); if (hPtr) { NsfProcAssertion *procAss = (NsfProcAssertion *) Tcl_GetHashValue(hPtr); @@ -5815,6 +5799,7 @@ AssertionRemoveProc(aStore, name); procs->pre = AssertionNewList(interp, pre); procs->post = AssertionNewList(interp, post); + assert(aStore); hPtr = Tcl_CreateHashEntry(&aStore->procs, name, &new); if (new) { Tcl_SetHashValue(hPtr, procs); @@ -5832,10 +5817,10 @@ static void AssertionRemoveStore(NsfAssertionStore *aStore) { - Tcl_HashSearch hSrch; - Tcl_HashEntry *hPtr; - if (aStore) { + Tcl_HashSearch hSrch; + Tcl_HashEntry *hPtr; + for (hPtr = Tcl_FirstHashEntry(&aStore->procs, &hSrch); hPtr; hPtr = Tcl_FirstHashEntry(&aStore->procs, &hSrch)) { /* @@ -5970,7 +5955,6 @@ static int AssertionCheck(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, CONST char *method, int checkOption) { - NsfProcAssertion *procs; int result = TCL_OK; NsfAssertionStore *aStore; @@ -5982,7 +5966,7 @@ assert(object->opt); if (checkOption & object->opt->checkoptions) { - procs = AssertionFindProcs(aStore, method); + NsfProcAssertion *procs = AssertionFindProcs(aStore, method); if (procs) { switch (checkOption) { case CHECK_PRE: @@ -6632,9 +6616,9 @@ if (startCl->opt) { NsfCmdList *m; - NsfClass *cl; for (m = startCl->opt->isClassMixinOf; m; m = m->nextPtr) { + NsfClass *cl; /* we should have no deleted commands in the list */ assert((Tcl_Command_flags(m->cmdPtr) & CMD_IS_DELETED) == 0); @@ -6656,9 +6640,9 @@ */ if (startCl->opt) { NsfCmdList *m; - NsfObject *object; for (m = startCl->opt->isObjectMixinOf; m; m = m->nextPtr) { + NsfObject *object; /* we should have no deleted commands in the list */ assert((Tcl_Command_flags(m->cmdPtr) & CMD_IS_DELETED) == 0); @@ -7081,14 +7065,15 @@ NsfClasses *clPtr; Tcl_HashSearch hSrch; Tcl_HashEntry *hPtr; - Tcl_HashTable objTable, *commandTable = &objTable, *instanceTablePtr; + Tcl_HashTable objTable, *commandTable = &objTable; /* * Iterate over the subclass hierarchy. */ for (clPtr = subClasses; clPtr; clPtr = clPtr->nextPtr) { Tcl_HashSearch hSrch; Tcl_HashEntry *hPtr; + Tcl_HashTable *instanceTablePtr; /* * Reset mixin order for all objects having this class as per object mixin @@ -7197,15 +7182,15 @@ MixinComputeDefined(interp, object); } if (object->flags & NSF_MIXIN_ORDER_DEFINED_AND_VALID) { - NsfCmdList *ml = object->mixinOrder; + NsfCmdList *ml; - while (ml) { + for (ml = object->mixinOrder; ml; ml = ml->nextPtr) { NsfClass *mixin = NsfGetClassFromCmdPtr(ml->cmdPtr); - if (pattern) { - if (!Tcl_StringMatch(ClassName(mixin), pattern)) continue; + + if (pattern && !Tcl_StringMatch(ClassName(mixin), pattern)) { + continue; } npl = NsfClassListAdd(npl, mixin, NULL); - ml = ml->nextPtr; } } } @@ -7444,15 +7429,16 @@ MixinInfo(Tcl_Interp *interp, NsfCmdList *m, CONST char *pattern, int withGuards, NsfObject *matchObject) { Tcl_Obj *list = Tcl_NewListObj(0, NULL); - NsfClass *mixinClass; /*fprintf(stderr, " mixin info m=%p, pattern %s, matchObject %p\n", m, pattern, matchObject);*/ while (m) { + NsfClass *mixinClass = NsfGetClassFromCmdPtr(m->cmdPtr); + /* fprintf(stderr, " mixin info m=%p, next=%p, pattern %s, matchObject %p\n", m, m->next, pattern, matchObject);*/ - mixinClass = NsfGetClassFromCmdPtr(m->cmdPtr); + if (mixinClass && (!pattern || (matchObject && &(mixinClass->object) == matchObject) @@ -7717,9 +7703,8 @@ } if (object->flags & NSF_MIXIN_ORDER_DEFINED_AND_VALID) { NsfCmdList *ml; - NsfClass *mixin; for (ml = object->mixinOrder; ml && !guardAdded; ml = ml->nextPtr) { - mixin = NsfGetClassFromCmdPtr(ml->cmdPtr); + NsfClass *mixin = NsfGetClassFromCmdPtr(ml->cmdPtr); if (mixin && mixin->opt) { guardAdded = GuardAddFromDefinitionList(dest, filterCmd, mixin->opt->classFilters); @@ -7934,15 +7919,14 @@ static void FilterSearchAgain(Tcl_Interp *interp, NsfCmdList **filters, NsfObject *startingObject, NsfClass *startingClass) { - char *simpleName; - Tcl_Command cmd; NsfCmdList *cmdList, *del; NsfClass *cl = NULL; CmdListRemoveDeleted(filters, GuardDel); for (cmdList = *filters; cmdList; ) { - simpleName = (char *) Tcl_GetCommandName(interp, cmdList->cmdPtr); - cmd = FilterSearch(simpleName, startingObject, startingClass, &cl); + char *simpleName = (char *) Tcl_GetCommandName(interp, cmdList->cmdPtr); + Tcl_Command cmd = FilterSearch(simpleName, startingObject, startingClass, &cl); + if (cmd == NULL) { del = CmdListRemoveFromList(filters, cmdList); cmdList = cmdList->nextPtr; @@ -8067,7 +8051,6 @@ static int FilterInfo(Tcl_Interp *interp, NsfCmdList *f, CONST char *pattern, int withGuards, int withMethodHandles) { - CONST char *simpleName; Tcl_Obj *list = Tcl_NewListObj(0, NULL); /*fprintf(stderr, "FilterInfo %p %s %d %d\n", pattern, pattern, @@ -8081,11 +8064,13 @@ } while (f) { - simpleName = Tcl_GetCommandName(interp, f->cmdPtr); + CONST char *simpleName = Tcl_GetCommandName(interp, f->cmdPtr); + if (!pattern || Tcl_StringMatch(simpleName, pattern)) { if (withGuards && f->clientData) { Tcl_Obj *innerList = Tcl_NewListObj(0, NULL); Tcl_Obj *g = (Tcl_Obj *) f->clientData; + Tcl_ListObjAppendElement(interp, innerList, Tcl_NewStringObj(simpleName, -1)); Tcl_ListObjAppendElement(interp, innerList, NsfGlobalObjs[NSF_GUARD_OPTION]); @@ -8094,6 +8079,7 @@ } else { if (withMethodHandles) { NsfClass *filterClass = f->clorobj; + Tcl_ListObjAppendElement(interp, list, MethodHandleObj((NsfObject *)filterClass, !NsfObjectIsClass(&filterClass->object), simpleName)); @@ -8116,7 +8102,6 @@ FilterComputeOrderFullList(Tcl_Interp *interp, NsfCmdList **filters, NsfCmdList **filterList) { NsfCmdList *f ; - char *simpleName; NsfClass *fcl; NsfClasses *pl; @@ -8126,7 +8111,7 @@ CmdListRemoveDeleted(filters, GuardDel); for (f = *filters; f; f = f->nextPtr) { - simpleName = (char *) Tcl_GetCommandName(interp, f->cmdPtr); + char *simpleName = (char *) Tcl_GetCommandName(interp, f->cmdPtr); fcl = f->clorobj; CmdListAdd(filterList, f->cmdPtr, fcl, /*noDuplicates*/ 0, 1); @@ -8597,7 +8582,8 @@ /*fprintf(stderr, "MakeProcError %p type %p refCount %d\n", procNameObj, procNameObj->typePtr, procNameObj->refCount);*/ - procName = Tcl_GetStringFromObj(procNameObj, &nameLen); + procName = Tcl_GetString(procNameObj); + nameLen = procNameObj->length; overflow = (nameLen > limit); Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf( "\n (procedure \"%.*s%s\" line %d)", @@ -8821,7 +8807,9 @@ NsfProcDeleteProc(ClientData clientData) { NsfProcContext *ctxPtr = (NsfProcContext *)clientData; - (*ctxPtr->oldDeleteProc)(ctxPtr->oldDeleteData); + if (ctxPtr->oldDeleteProc) { + (*ctxPtr->oldDeleteProc)(ctxPtr->oldDeleteData); + } if (ctxPtr->paramDefs) { /*fprintf(stderr, "free ParamDefs %p\n", ctxPtr->paramDefs);*/ ParamDefsRefCountDecr(ctxPtr->paramDefs); @@ -8964,6 +8952,7 @@ static void ParamDefsRefCountIncr(NsfParamDefs *paramDefs) { + assert(paramDefs); paramDefs->refCount ++; } static void @@ -9074,6 +9063,8 @@ } if ((paramPtr->flags & NSF_ARG_INITCMD)) { ParamDefsFormatOption(nameStringObj, "initcmd", &colonWritten, &first); + } else if ((paramPtr->flags & NSF_ARG_CMD)) { + ParamDefsFormatOption(nameStringObj, "cmd", &colonWritten, &first); } else if ((paramPtr->flags & NSF_ARG_ALIAS)) { ParamDefsFormatOption(nameStringObj, "alias", &colonWritten, &first); } else if ((paramPtr->flags & NSF_ARG_FORWARD)) { @@ -9250,13 +9241,28 @@ static void NsfParamDefsSyntaxOne(Tcl_Obj *argStringObj, Nsf_Param CONST *pPtr) { - Tcl_AppendLimitedToObj(argStringObj, pPtr->name, -1, INT_MAX, NULL); if (pPtr->nrArgs > 0 && *pPtr->name == '-') { + Tcl_AppendLimitedToObj(argStringObj, pPtr->name, -1, INT_MAX, NULL); Tcl_AppendLimitedToObj(argStringObj, " ", 1, INT_MAX, NULL); - Tcl_AppendLimitedToObj(argStringObj, ParamGetDomain(pPtr), -1, INT_MAX, NULL); - if (pPtr->flags & NSF_ARG_MULTIVALUED) { - Tcl_AppendLimitedToObj(argStringObj, " ...", 4, INT_MAX, NULL); + if ((pPtr->flags & NSF_ARG_IS_ENUMERATION)) { + Tcl_AppendLimitedToObj(argStringObj, ParamGetDomain(pPtr), -1, INT_MAX, NULL); + if (pPtr->flags & NSF_ARG_MULTIVALUED) { + Tcl_AppendLimitedToObj(argStringObj, " ...", 4, INT_MAX, NULL); + } + } else { + Tcl_AppendLimitedToObj(argStringObj, "/", 1, INT_MAX, NULL); + Tcl_AppendLimitedToObj(argStringObj, ParamGetDomain(pPtr), -1, INT_MAX, NULL); + if (pPtr->flags & NSF_ARG_MULTIVALUED) { + Tcl_AppendLimitedToObj(argStringObj, " ...", 4, INT_MAX, NULL); + } + Tcl_AppendLimitedToObj(argStringObj, "/", 1, INT_MAX, NULL); } + } else if (*pPtr->name != '-') { + Tcl_AppendLimitedToObj(argStringObj, "/", 1, INT_MAX, NULL); + Tcl_AppendLimitedToObj(argStringObj, pPtr->name, -1, INT_MAX, NULL); + Tcl_AppendLimitedToObj(argStringObj, "/", 1, INT_MAX, NULL); + } else { + Tcl_AppendLimitedToObj(argStringObj, pPtr->name, -1, INT_MAX, NULL); } } @@ -9301,8 +9307,9 @@ } Tcl_AppendLimitedToObj(argStringObj, " ", 1, INT_MAX, NULL); } + if (pPtr->converter == ConvertToNothing && strcmp(pPtr->name, "args") == 0) { - Tcl_AppendLimitedToObj(argStringObj, "?arg ...?", 9, INT_MAX, NULL); + Tcl_AppendLimitedToObj(argStringObj, "?/arg .../?", 11, INT_MAX, NULL); } else if (pPtr->flags & NSF_ARG_REQUIRED) { if ((pPtr->flags & NSF_ARG_IS_ENUMERATION)) { Tcl_AppendLimitedToObj(argStringObj, ParamGetDomain(pPtr), -1, INT_MAX, NULL); @@ -10303,7 +10310,7 @@ if (paramDefs && paramDefs->returns) { Tcl_Obj *valueObj = Tcl_GetObjResult(interp); result = ParameterCheck(interp, paramDefs->returns, valueObj, "return-value:", - rst->doCheckResults, NULL); + rst->doCheckResults, 0, 0, NULL); } } else { /*fprintf(stderr, "We have no cmdPtr in cscPtr %p %s", cscPtr, ObjectName(object)); @@ -11913,23 +11920,38 @@ paramPtr->flags |= NSF_ARG_IS_CONVERTER; } else if (strncmp(option, "initcmd", 7) == 0) { + if (unlikely(paramPtr->flags & (NSF_ARG_CMD|NSF_ARG_ALIAS|NSF_ARG_FORWARD))) { + return NsfPrintError(interp, "parameter option 'initcmd' not valid in this option combination"); + } paramPtr->flags |= NSF_ARG_INITCMD; + } else if (strncmp(option, "cmd", 3) == 0) { + if (unlikely(paramPtr->flags & (NSF_ARG_INITCMD|NSF_ARG_ALIAS|NSF_ARG_FORWARD))) { + return NsfPrintError(interp, "parameter option 'cmd' not valid in this option combination"); + } + paramPtr->flags |= NSF_ARG_CMD; + } else if (strncmp(option, "alias", 5) == 0) { + if (unlikely(paramPtr->flags & (NSF_ARG_INITCMD|NSF_ARG_CMD|NSF_ARG_FORWARD))) { + return NsfPrintError(interp, "parameter option 'alias' not valid in this option combination"); + } paramPtr->flags |= NSF_ARG_ALIAS; } else if (strncmp(option, "forward", 7) == 0) { + if (unlikely(paramPtr->flags & (NSF_ARG_INITCMD|NSF_ARG_CMD|NSF_ARG_ALIAS))) { + return NsfPrintError(interp, "parameter option 'forward' not valid in this option combination"); + } paramPtr->flags |= NSF_ARG_FORWARD; } else if (strncmp(option, "slotassign", 10) == 0) { if (unlikely(paramPtr->slotObj == NULL)) { - return NsfPrintError(interp, "option 'slotassign' must follow 'slot='"); + return NsfPrintError(interp, "parameter option 'slotassign' must follow 'slot='"); } paramPtr->flags |= NSF_ARG_SLOTASSIGN; } else if (strncmp(option, "slotinitialize", 14) == 0) { if (unlikely(paramPtr->slotObj == NULL)) { - return NsfPrintError(interp, "option 'slotinit' must follow 'slot='"); + return NsfPrintError(interp, "parameter option 'slotinit' must follow 'slot='"); } paramPtr->flags |= NSF_ARG_SLOTINITIALIZE; @@ -11954,7 +11976,7 @@ } else if (strncmp(option, "noarg", 5) == 0) { if ((paramPtr->flags & NSF_ARG_ALIAS) == 0) { - return NsfPrintError(interp, "option \"noarg\" only allowed for parameter type \"alias\""); + return NsfPrintError(interp, "parameter option \"noarg\" only allowed for parameter type \"alias\""); } paramPtr->flags |= NSF_ARG_NOARG; paramPtr->nrArgs = 0; @@ -12141,13 +12163,7 @@ } if (unlikely((paramPtr->flags & NSF_ARG_METHOD_INVOCATION) && (paramPtr->flags & NSF_ARG_NOCONFIG))) { - return NsfPrintError(interp, "option 'noconfig' cannot used together with this type of object parameter"); - } else if (unlikely((paramPtr->flags & (NSF_ARG_ALIAS|NSF_ARG_FORWARD)) == (NSF_ARG_ALIAS|NSF_ARG_FORWARD))) { - return NsfPrintError(interp, "parameter types 'alias' and 'forward' cannot be used together"); - } else if (unlikely((paramPtr->flags & (NSF_ARG_ALIAS|NSF_ARG_INITCMD)) == (NSF_ARG_ALIAS|NSF_ARG_INITCMD))) { - return NsfPrintError(interp, "parameter types 'alias' and 'initcmd' cannot be used together"); - } else if (unlikely((paramPtr->flags & (NSF_ARG_FORWARD|NSF_ARG_INITCMD)) == (NSF_ARG_FORWARD|NSF_ARG_INITCMD))) { - return NsfPrintError(interp, "parameter types 'forward' and 'initcmd' cannot be used together"); + return NsfPrintError(interp, "parameter option 'noconfig' cannot used together with this type of object parameter"); } return result; @@ -12565,7 +12581,7 @@ */ forwardSpec = paramPtr->method ? paramPtr->method : NULL; /* different default? */ if (forwardSpec == NULL) { - return NsfPrintError(interp, "no forward spec available\n"); + return NsfPrintError(interp, "forward: no spec available\n"); } result = Tcl_ListObjGetElements(interp, forwardSpec, &nobjc, &nobjv); @@ -12659,7 +12675,7 @@ NSF_CSC_TYPE_PLAIN, 0, NsfGlobalStrings[NSF_CONFIGURE]); Nsf_PushFrameCsc(interp, cscPtr, framePtr2); - if (paramPtr->flags & NSF_ARG_INITCMD) { + if (paramPtr->flags & (NSF_ARG_INITCMD|NSF_ARG_CMD)) { /* cscPtr->cmdPtr = NSFindCommand(interp, "::eval"); */ result = Tcl_EvalObjEx(interp, newValue, TCL_EVAL_DIRECT); @@ -12773,8 +12789,10 @@ ObjStr(paramPtr->nameObj), ObjStr(newValue), result);*/ if (likely(result == TCL_OK)) { - if (paramPtr->flags & NSF_ARG_INITCMD && RUNTIME_STATE(interp)->doKeepinitcmd) { - Tcl_ObjSetVar2(interp, paramPtr->nameObj, NULL, newValue, TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); + if (paramPtr->flags & NSF_ARG_CMD && RUNTIME_STATE(interp)->doKeepcmds) { + fprintf(stderr, "setting %s(%s) /%s/\n", ObjStr(NsfGlobalObjs[NSF_ARRAY_CMD]), ObjStr(paramPtr->nameObj), ObjStr(newValue)); + Tcl_ObjSetVar2(interp, NsfGlobalObjs[NSF_ARRAY_CMD], + paramPtr->nameObj, newValue, 0); } } @@ -13073,7 +13091,7 @@ (FRAME_IS_PROC)); if (likely(result == TCL_OK)) { - unsigned int dummy; + unsigned int dummy = 0; result = ByteCompiled(interp, &dummy, procPtr, fullMethodName); } if (unlikely(result != TCL_OK)) { @@ -13759,7 +13777,7 @@ Tcl_Obj *listObj) { NsfObject *slotContainerObject; Tcl_DString ds, *dsPtr = &ds; - int fullQualPattern = (pattern && *pattern == ':'); + int fullQualPattern = (pattern && *pattern == ':' && *(pattern+1) == ':'); /*fprintf(stderr, "AddSlotObjects parent %s prefix %s type %p %s\n", ObjectName(parent), prefix, type, type ? ClassName(type) : "");*/ @@ -13775,14 +13793,14 @@ Tcl_HashEntry *hPtr; Tcl_HashTable *cmdTablePtr = Tcl_Namespace_cmdTablePtr(slotContainerObject->nsPtr); Tcl_Command cmd; - int new; hPtr = Tcl_FirstHashEntry(cmdTablePtr, &hSrch); for (; hPtr; hPtr = Tcl_NextHashEntry(&hSrch)) { char *key = Tcl_GetHashKey(cmdTablePtr, hPtr); NsfObject *childObject; if (slotTablePtr) { + int new; /* * Check, if we have and entry with this key already processed. We * never want to report shadowed entries. @@ -13814,10 +13832,25 @@ * If the pattern looks like fully qualified, we match against the * fully qualified name. */ - match = fullQualPattern ? - Tcl_StringMatch(ObjectName(childObject), pattern) : - Tcl_StringMatch(key, pattern); - + + if (fullQualPattern) { + match = Tcl_StringMatch(ObjectName(childObject), pattern); + } else { + /* + * do we have a mangled name of a private property/variable? + */ + if (*key == '_' && *(key+1) == '_' && *(key+2) == '_' && *(key+3) == '_') { + Tcl_Obj *value = Nsf_ObjGetVar2((Nsf_Object *)childObject, interp, + NsfGlobalObjs[NSF_SETTERNAME], NULL, 0); + match = value ? Tcl_StringMatch(ObjStr(value), pattern) : 0; + + /*fprintf(stderr, "pattern <%s> fullQualPattern %d child %s key %s %p <%s> match %d\n", + pattern, fullQualPattern, ObjectName(childObject), key, + value, value ? ObjStr(value) : "", match);*/ + } else { + match = Tcl_StringMatch(key, pattern); + } + } if (!match) { continue; } @@ -14299,7 +14332,7 @@ object, cl, methodName, frameType, 0); #endif } else if (result == TCL_OK) { - NsfCallStackContent *topCscPtr = NULL; + NsfCallStackContent *topCscPtr; int isLeafNext; /* @@ -14505,12 +14538,13 @@ Tcl_HashSearch search; Tcl_HashEntry *entryPtr = Tcl_FirstHashEntry(Tcl_Namespace_childTablePtr(nsPtr), &search); Tcl_Var *varPtr; - int result; varPtr = (Tcl_Var *) Tcl_FindNamespaceVar(interp, name, nsPtr, 0); /*fprintf(stderr, "found %s in %s -> %p\n", name, nsPtr->fullName, varPtr);*/ if (varPtr) { Tcl_DString dFullname, *dsPtr = &dFullname; + int result; + Tcl_DStringInit(dsPtr); Tcl_DStringAppend(dsPtr, "unset ", -1); DStringAppendQualName(dsPtr, nsPtr, name); @@ -15517,7 +15551,7 @@ */ object->flags &= ~NSF_INIT_CALLED; /* - * Make sure, the object survives initialization; the initcmd might + * Make sure, the object survives initialization; the cmd/initcmd might * destroy it. */ NsfObjectRefCountIncr(object); @@ -15547,6 +15581,26 @@ if (likely(result == TCL_OK)) { Tcl_SetObjResult(interp, savedObjResult); } + } else { + /* + * Configure failed and might have left the object in a bogus state. To + * avoid strange errors, we delete the half-baked object. + */ + + Tcl_Obj *errObj; + + /* + * Preserve the outer error message, calls triggered by + * DispatchDestroyMethod() can cause the interp result to be reset + */ + + errObj = Tcl_GetObjResult(interp); + INCR_REF_COUNT(errObj); + + DispatchDestroyMethod(interp, (NsfObject *)object, 0); + + Tcl_SetObjResult(interp, errObj); + DECR_REF_COUNT(errObj); } NsfCleanupObject(object, "obj init"); @@ -15641,7 +15695,7 @@ GetInstVarIntoCurrentScope(Tcl_Interp *interp, const char *cmdName, NsfObject *object, Tcl_Obj *varName, Tcl_Obj *newName) { Var *otherPtr = NULL, *arrayPtr; - int new = 0, flogs = TCL_LEAVE_ERR_MSG; + int flogs = TCL_LEAVE_ERR_MSG; Tcl_CallFrame *varFramePtr; CallFrame frame, *framePtr = &frame; char *varNameString; @@ -15691,6 +15745,7 @@ */ if (varFramePtr && (Tcl_CallFrame_isProcCallFrame(varFramePtr) & FRAME_IS_PROC)) { Var *varPtr = (Var *)CompiledLocalsLookup((CallFrame *)varFramePtr, varNameString); + int new = 0; if (varPtr == NULL) { /* @@ -16227,7 +16282,7 @@ if (unlikely(tcd->verbose)) { Tcl_Obj *cmd = Tcl_NewListObj(objc, objv); - /*fprintf(stderr, "forwarder calls '%s'\n", ObjStr(cmd));*/ + fprintf(stderr, "forwarder calls '%s'\n", ObjStr(cmd)); DECR_REF_COUNT(cmd); } if (tcd->objframe) { @@ -16308,7 +16363,8 @@ * with the given cmd name. */ ALLOC_ON_STACK(Tcl_Obj*, objc, ov); - /*fprintf(stderr, "+++ forwardMethod must subst \n");*/ + /*fprintf(stderr, "+++ forwardMethod must subst oc=%d <%s>\n", + objc, ObjStr(tcd->cmdName));*/ memcpy(ov, objv, sizeof(Tcl_Obj *)*objc); ov[0] = tcd->cmdName; result = CallForwarder(tcd, interp, objc, ov); @@ -16615,8 +16671,8 @@ int result; Tcl_Obj *methodObj = Tcl_NewStringObj(methodName, -1); - /* fprintf(stderr, "CallConfigureMethod method %s->'%s' level %d, argc %d\n", - ObjectName(object), methodName, level, argc);*/ + /*fprintf(stderr, "CallConfigureMethod method %s->'%s' argc %d\n", + ObjectName(object), methodName, argc);*/ /* * When configure gets "-init" passed, we call "init" and notice the fact it @@ -16634,7 +16690,7 @@ DECR_REF_COUNT(methodObj); /*fprintf(stderr, "method '%s' called args: %d o=%p, result=%d %d\n", - methodName, argc+1, obj, result, TCL_ERROR);*/ + methodName, argc+1, object, result, TCL_ERROR);*/ if (result != TCL_OK) { Tcl_Obj *res = Tcl_DuplicateObj(Tcl_GetObjResult(interp)); /* save the result */ @@ -16811,7 +16867,7 @@ */ if ((unlikely((doCheckArguments & NSF_ARGPARSE_CHECK) == 0) && (pPtr->flags & (NSF_ARG_IS_CONVERTER)) == 0 - ) || (pPtr->flags & (NSF_ARG_INITCMD))) { + ) || (pPtr->flags & (NSF_ARG_CMD))) { /* fprintf(stderr, "*** omit argument check for arg %s flags %.6x\n", pPtr->name, pPtr->flags); */ *clientData = ObjStr(objPtr); return TCL_OK; @@ -16976,7 +17032,8 @@ */ if (pPtr->type || unlikely(pPtr->flags & NSF_ARG_MULTIVALUED)) { int mustDecrList = 0; - if (unlikely(ArgumentCheck(interp, newValue, pPtr, + if (unlikely((pPtr->flags & NSF_ARG_INITCMD) == 0 && + ArgumentCheck(interp, newValue, pPtr, RUNTIME_STATE(interp)->doCheckArguments, &mustDecrList, &checkedData, &pcPtr->objv[i]) != TCL_OK)) { if (mustDecrNewValue) { @@ -17581,7 +17638,7 @@ ListCmdParams(Tcl_Interp *interp, Tcl_Command cmd, CONST char *methodName, NsfParamsPrintStyle printStyle) { NsfParamDefs *paramDefs; - Tcl_Obj *list; + Tcl_Obj *listObj; Proc *procPtr; assert(methodName); @@ -17593,9 +17650,9 @@ /* * Obtain parameter info from paramDefs. */ - list = ListParamDefs(interp, paramDefs->paramsPtr, printStyle); - Tcl_SetObjResult(interp, list); - DECR_REF_COUNT2("paramDefsObj", list); + listObj = ListParamDefs(interp, paramDefs->paramsPtr, printStyle); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); return TCL_OK; } @@ -17606,7 +17663,7 @@ */ CompiledLocal *args = procPtr->firstLocalPtr; - list = Tcl_NewListObj(0, NULL); + listObj = Tcl_NewListObj(0, NULL); for ( ; args; args = args->nextPtr) { if (!TclIsCompiledLocalArgument(args)) { @@ -17615,20 +17672,39 @@ if (printStyle == NSF_PARAMS_SYNTAX && strcmp(args->name, "args") == 0) { if (args != procPtr->firstLocalPtr) { - Tcl_AppendToObj(list, " ", 1); + Tcl_AppendToObj(listObj, " ", 1); } - Tcl_AppendToObj(list, "?arg ...?", 9); + Tcl_AppendToObj(listObj, "?/arg .../?", 11); } else { - Tcl_Obj *innerlist = Tcl_NewListObj(0, NULL); - Tcl_ListObjAppendElement(interp, innerlist, Tcl_NewStringObj(args->name, -1)); - if (printStyle == NSF_PARAMS_PARAMETER && args->defValuePtr) { - Tcl_ListObjAppendElement(interp, innerlist, args->defValuePtr); + if (printStyle == NSF_PARAMS_SYNTAX) { + /* + * A default means that the argument is optional. + */ + if (args->defValuePtr) { + Tcl_AppendToObj(listObj, "?", 1); + Tcl_AppendToObj(listObj, args->name, -1); + Tcl_AppendToObj(listObj, "?", 1); + } else { + Tcl_AppendToObj(listObj, "/", 1); + Tcl_AppendToObj(listObj, args->name, -1); + Tcl_AppendToObj(listObj, "/", 1); + } + } else { + Tcl_Obj *innerListObj = Tcl_NewListObj(0, NULL); + + Tcl_ListObjAppendElement(interp, innerListObj, Tcl_NewStringObj(args->name, -1)); + /* + * Return default just for NSF_PARAMS_PARAMETER. + */ + if (args->defValuePtr && printStyle == NSF_PARAMS_PARAMETER) { + Tcl_ListObjAppendElement(interp, innerListObj, args->defValuePtr); + } + Tcl_ListObjAppendElement(interp, listObj, innerListObj); } - Tcl_ListObjAppendElement(interp, list, innerlist); } } - Tcl_SetObjResult(interp, list); + Tcl_SetObjResult(interp, listObj); return TCL_OK; } @@ -17657,7 +17733,8 @@ if (((Command *)cmd)->objProc == NsfSetterMethod) { SetterCmdClientData *cd = (SetterCmdClientData *)Tcl_Command_objClientData(cmd); - if (cd->paramsPtr) { + + if (cd && cd->paramsPtr) { Tcl_Obj *list; NsfParamDefs paramDefs; paramDefs.paramsPtr = cd->paramsPtr; @@ -17686,7 +17763,7 @@ Tcl_DStringInit(dsPtr); DStringAppendQualName(dsPtr, Tcl_Command_nsPtr(cmd), methodName); /*fprintf(stderr,"Looking up ::nsf::parametersyntax(%s) ...\n", Tcl_DStringValue(dsPtr));*/ - parameterSyntaxObj = Tcl_GetVar2Ex(interp, "::nsf::parametersyntax", + parameterSyntaxObj = Tcl_GetVar2Ex(interp, NsfGlobalStrings[NSF_ARRAY_PARAMETERSYNTAX], Tcl_DStringValue(dsPtr), TCL_GLOBAL_ONLY); /*fprintf(stderr, "No parametersyntax so far methodName %s cmd name %s ns %s\n", @@ -17760,8 +17837,12 @@ ? Tcl_NewStringObj("protected", 9) : Tcl_NewStringObj("public", 6)); } - if (withPer_object) { - Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("class", 5)); + + //if (withPer_object) { + // Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("class", 5)); + //} + if (!NsfObjectIsClass(object) || withPer_object) { + Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("object", 6)); } Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(registerCmdName, -1)); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj(methodName, -1)); @@ -17852,8 +17933,8 @@ paramDefs = ParamDefsGet(importedCmd); if (paramDefs && paramDefs->returns) { Tcl_SetObjResult(interp, paramDefs->returns); - return TCL_OK; } + return TCL_OK; } case InfomethodsubcmdSyntaxIdx: { @@ -17999,7 +18080,7 @@ /* todo: don't hard-code registering command name "setter" / NSF_SETTER */ AppendMethodRegistration(interp, resultObj, NsfGlobalStrings[NSF_SETTER], regObject, - cd->paramsPtr ? ObjStr(cd->paramsPtr->paramObj) : methodName, + (cd && cd->paramsPtr) ? ObjStr(cd->paramsPtr->paramObj) : methodName, cmd, 0, outputPerObject, 1); Tcl_SetObjResult(interp, resultObj); break; @@ -18145,7 +18226,7 @@ * MethodSourceMatches -- * * Check, whether the provided class or object (mutually exclusive) matches - * with the required method source (typically all|application|baseclasses). + * with the required method source (typically all|application|system). * * Results: * Returns true or false @@ -18172,7 +18253,7 @@ } isBaseClass = IsBaseClass(&cl->object); - if (withSource == SourceBaseclassesIdx && isBaseClass) { + if (withSource == SourceSystemIdx && isBaseClass) { return 1; } else if (withSource == SourceApplicationIdx && !isBaseClass) { return 1; @@ -18311,7 +18392,7 @@ Tcl_HashEntry *hPtr; Tcl_Command cmd; char *key; - int new, isObject, methodTypeMatch; + int isObject, methodTypeMatch; int prefixLength = prefix ? Tcl_DStringLength(prefix) : 0; Tcl_Obj *resultObj = Tcl_GetObjResult(interp); @@ -18366,6 +18447,7 @@ key = Tcl_DStringValue(prefix); } if (dups) { + int new; Tcl_CreateHashEntry(dups, key, &new); if (new) { Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewStringObj(key, -1)); @@ -18413,7 +18495,13 @@ /* Don't report slot container */ continue; } + if ((childObject->flags & NSF_KEEP_CALLER_SELF) == 0) { + /* Do only report sub-objects with keep caller self */ + continue; + } + /*fprintf(stderr, "ListMethodKeys key %s append key space flags %.6x\n", + key, childObject->flags);*/ if (prefix == NULL) { DSTRING_INIT(dsPtr); Tcl_DStringAppend(dsPtr, key, -1); @@ -18455,6 +18543,7 @@ if (pattern && !Tcl_StringMatch(key, pattern)) continue; if (dups) { + int new; Tcl_CreateHashEntry(dups, key, &new); if (!new) continue; } @@ -18498,12 +18587,12 @@ Tcl_HashSearch hSrch; Tcl_HashTable *cmdTablePtr = Tcl_Namespace_cmdTablePtr(object->nsPtr); Tcl_HashEntry *hPtr; - char *key; for (hPtr = Tcl_FirstHashEntry(cmdTablePtr, &hSrch); hPtr; hPtr = Tcl_NextHashEntry(&hSrch)) { - key = Tcl_GetHashKey(cmdTablePtr, hPtr); + char *key = Tcl_GetHashKey(cmdTablePtr, hPtr); + if (!pattern || Tcl_StringMatch(key, pattern)) { Tcl_Command cmd = (Tcl_Command)Tcl_GetHashValue(hPtr); @@ -18692,7 +18781,7 @@ AliasAdd(Tcl_Interp *interp, Tcl_Obj *cmdName, CONST char *methodName, int withPer_object, CONST char *cmd) { Tcl_DString ds, *dsPtr = &ds; - Tcl_SetVar2Ex(interp, NsfGlobalStrings[NSF_ALIAS_ARRAY], + Tcl_SetVar2Ex(interp, NsfGlobalStrings[NSF_ARRAY_ALIAS], AliasIndex(dsPtr, cmdName, methodName, withPer_object), Tcl_NewStringObj(cmd, -1), TCL_GLOBAL_ONLY); @@ -18705,7 +18794,7 @@ static int AliasDelete(Tcl_Interp *interp, Tcl_Obj *cmdName, CONST char *methodName, int withPer_object) { Tcl_DString ds, *dsPtr = &ds; - int result = Tcl_UnsetVar2(interp, NsfGlobalStrings[NSF_ALIAS_ARRAY], + int result = Tcl_UnsetVar2(interp, NsfGlobalStrings[NSF_ARRAY_ALIAS], AliasIndex(dsPtr, cmdName, methodName, withPer_object), TCL_GLOBAL_ONLY); /*fprintf(stderr, "aliasDelete ::nsf::alias(%s) returned %d (%d)\n", @@ -18717,7 +18806,7 @@ static Tcl_Obj * AliasGet(Tcl_Interp *interp, Tcl_Obj *cmdName, CONST char *methodName, int withPer_object, int leaveError) { Tcl_DString ds, *dsPtr = &ds; - Tcl_Obj *obj = Tcl_GetVar2Ex(interp, NsfGlobalStrings[NSF_ALIAS_ARRAY], + Tcl_Obj *obj = Tcl_GetVar2Ex(interp, NsfGlobalStrings[NSF_ARRAY_ALIAS], AliasIndex(dsPtr, cmdName, methodName, withPer_object), TCL_GLOBAL_ONLY); /*fprintf(stderr, "aliasGet methodName '%s' returns %p\n", methodName, obj);*/ @@ -19171,7 +19260,7 @@ /* cmd configure NsfConfigureCmd { - {-argName "configureoption" -required 1 -type "debug|dtrace|filter|profile|softrecreate|objectsystems|keepinitcmd|checkresults|checkarguments"} + {-argName "configureoption" -required 1 -type "debug|dtrace|filter|profile|softrecreate|objectsystems|keepcmds|checkresults|checkarguments"} {-argName "value" -required 0 -type tclobj} } */ @@ -19184,7 +19273,7 @@ /* TODO: opts copied from tclAPI.h; maybe make global value? */ static CONST char *opts[] = { "debug", "dtrace", "filter", "profile", "softrecreate", - "objectsystems", "keepinitcmd", "checkresults", "checkarguments", NULL}; + "objectsystems", "keepcmds", "checkresults", "checkarguments", NULL}; NSF_DTRACE_CONFIGURE_PROBE((char *)opts[configureoption-1], valueObj ? ObjStr(valueObj) : NULL); } #endif @@ -19272,11 +19361,11 @@ } break; - case ConfigureoptionKeepinitcmdIdx: + case ConfigureoptionKeepcmdsIdx: Tcl_SetBooleanObj(Tcl_GetObjResult(interp), - (RUNTIME_STATE(interp)->doKeepinitcmd)); + (RUNTIME_STATE(interp)->doKeepcmds)); if (valueObj) { - RUNTIME_STATE(interp)->doKeepinitcmd = bool; + RUNTIME_STATE(interp)->doKeepcmds = bool; } break; @@ -19609,17 +19698,27 @@ /* cmd is NsfIsCmd { - {-argName "-complain"} + {-argName "-complain" -nrargs 0} + {-argName "-configure" -nrargs 0} + {-argName "-name" -required 0} {-argName "constraint" -required 1 -type tclobj} {-argName "value" -required 1 -type tclobj} -} +} {-nxdoc 1} */ static int -NsfIsCmd(Tcl_Interp *interp, int withComplain, Tcl_Obj *constraintObj, Tcl_Obj *valueObj) { +NsfIsCmd(Tcl_Interp *interp, + int withComplain, + int doConfigureParameter, + CONST char *name, + Tcl_Obj *constraintObj, + Tcl_Obj *valueObj) { Nsf_Param *paramPtr = NULL; int result; - result = ParameterCheck(interp, constraintObj, valueObj, "value:", 1, ¶mPtr); + result = ParameterCheck(interp, constraintObj, valueObj, + name ? name : "value:", 1, (name != NULL), + doConfigureParameter, + ¶mPtr); if (paramPtr == NULL) { /* @@ -19748,9 +19847,9 @@ * We have an alias to a tcl proc; */ Proc *procPtr = (Proc *)Tcl_Command_objClientData(cmd); - Tcl_Obj *bodyObj = procPtr->bodyPtr; + Tcl_Obj *bodyObj = procPtr ? procPtr->bodyPtr : NULL; - if (bodyObj->typePtr == Nsf_OT_byteCodeType) { + if (bodyObj && bodyObj->typePtr == Nsf_OT_byteCodeType) { /* * Flush old byte code */ @@ -19768,7 +19867,7 @@ if (newObjProc) { /* add a wrapper */ - /*fprintf(stderr, "NsfMethodAliasCmd cmd %p\n", cmd);*/ + /*fprintf(stderr, "NsfMethodAliasCmd add wrapper cmd %p\n", cmd);*/ NsfCommandPreserve(cmd); tcd = NEW(AliasCmdClientData); tcd->cmdName = object->cmdName; @@ -19788,6 +19887,7 @@ * depending on a volatile client data) */ tcd = Tcl_Command_objClientData(cmd); + /*fprintf(stderr, "NsfMethodAliasCmd no wrapper cmd %p\n", cmd);*/ } flags = 0; @@ -20008,6 +20108,7 @@ withDefault, withEarlybinding, withMethodprefix, withObjframe, withOnerror, withVerbose, target, nobjc, nobjv, &tcd); + if (result == TCL_OK) { CONST char *methodName = NSTail(ObjStr(methodObj)); NsfClass *cl = @@ -20513,7 +20614,7 @@ int flags, result; if (unlikely(self == NULL)) { - return NsfNoCurrentObjectError(interp, ObjStr(nobjv[0])); + return NsfNoCurrentObjectError(interp, method_definitions[NsfMyCmdIdx].methodName); } if ((withIntrinsic && withLocal) @@ -20596,229 +20697,6 @@ } /* -cmd nscopycmds NsfNSCopyCmdsCmd { - {-argName "fromNs" -required 1 -type tclobj} - {-argName "toNs" -required 1 -type tclobj} -} -*/ -static int -NsfNSCopyCmdsCmd(Tcl_Interp *interp, Tcl_Obj *fromNs, Tcl_Obj *toNs) { - Tcl_Command cmd; - Tcl_Obj *newFullCmdName, *oldFullCmdName; - CONST char *newName, *oldName, *name; - Tcl_Namespace *fromNsPtr, *toNsPtr; - Tcl_HashTable *cmdTablePtr; - Tcl_HashSearch hSrch; - Tcl_HashEntry *hPtr; - NsfObject *object; - NsfClass *cl; - int fromClassNS; - - if (TclGetNamespaceFromObj(interp, fromNs, &fromNsPtr) != TCL_OK) { - return TCL_OK; - } - - name = ObjStr(fromNs); - - /* check, if we work on an object or class namespace */ - object = GetObjectFromNsName(interp, name, &fromClassNS); - - if (unlikely(object == NULL)) { - return NsfPrintError(interp, "argument 1 '%s' is not an object", ObjStr(fromNs)); - } - - cl = fromClassNS ? (NsfClass *)object : NULL; - - if (TclGetNamespaceFromObj(interp, toNs, &toNsPtr) != TCL_OK) { - return NsfPrintError(interp, "CopyCmds: Destination namespace %s does not exist", - ObjStr(toNs)); - } - /* - * Copy all procs & commands in the namespace. - */ - cmdTablePtr = Tcl_Namespace_cmdTablePtr(fromNsPtr); - hPtr = Tcl_FirstHashEntry(cmdTablePtr, &hSrch); - while (hPtr) { - /*fprintf(stderr, "copy cmdTablePtr = %p, first=%p\n", cmdTablePtr, hPtr);*/ - name = Tcl_GetHashKey(cmdTablePtr, hPtr); - - /* - * Construct full cmd names. - */ - newFullCmdName = Tcl_NewStringObj(toNsPtr->fullName, -1); - oldFullCmdName = Tcl_NewStringObj(fromNsPtr->fullName, -1); - - INCR_REF_COUNT(newFullCmdName); INCR_REF_COUNT(oldFullCmdName); - Tcl_AppendStringsToObj(newFullCmdName, "::", name, (char *) NULL); - Tcl_AppendStringsToObj(oldFullCmdName, "::", name, (char *) NULL); - newName = ObjStr(newFullCmdName); - oldName = ObjStr(oldFullCmdName); - - /*fprintf(stderr, "try to copy command from '%s' to '%s'\n", oldName, newName);*/ - /* - * Make sure that the destination command does not already exist. - * Otherwise: do not copy. - */ - cmd = Tcl_FindCommand(interp, newName, NULL, TCL_GLOBAL_ONLY); - if (cmd) { - /*fprintf(stderr, "%s already exists\n", newName);*/ - if (!GetObjectFromString(interp, newName)) { - /* command or scripted method will be deleted & then copied */ - Tcl_DeleteCommandFromToken(interp, cmd); - } else { - /* don't overwrite objects -> will be recreated */ - hPtr = Tcl_NextHashEntry(&hSrch); - DECR_REF_COUNT(newFullCmdName); - DECR_REF_COUNT(oldFullCmdName); - continue; - } - } - - /* - * Find the existing command. An error is returned if simpleName can't - * be found. - */ - cmd = Tcl_FindCommand(interp, oldName, NULL, TCL_GLOBAL_ONLY); - if (cmd == NULL) { - NsfPrintError(interp, "can't copy \"%s\": command doesn't exist", oldName); - DECR_REF_COUNT(newFullCmdName); - DECR_REF_COUNT(oldFullCmdName); - return TCL_ERROR; - } - /* - * Do not copy Objects or Classes. - */ - if (!GetObjectFromString(interp, oldName)) { - - if (CmdIsProc(cmd)) { - Proc *procPtr = (Proc *)Tcl_Command_objClientData(cmd); - Tcl_Obj *arglistObj; - int result; - - /* - * Build a list containing the arguments of the proc. - */ - result = ListCmdParams(interp, cmd, oldName, NSF_PARAMS_PARAMETER); - if (result != TCL_OK) { - return result; - } - - arglistObj = Tcl_GetObjResult(interp); - INCR_REF_COUNT(arglistObj); - - if (Tcl_Command_objProc(cmd) == RUNTIME_STATE(interp)->objInterpProc) { - Tcl_DString ds, *dsPtr = &ds; - - if (cl) { - /* Next Scripting class-methods */ -#if defined(NSF_WITH_ASSERTIONS) - NsfProcAssertion *procs; - procs = cl->opt ? AssertionFindProcs(cl->opt->assertions, name) : NULL; -#endif - - DSTRING_INIT(dsPtr); - Tcl_DStringAppendElement(dsPtr, "::nsf::method::create"); - Tcl_DStringAppendElement(dsPtr, NSCutNsfClasses(toNsPtr->fullName)); - Tcl_DStringAppendElement(dsPtr, name); - Tcl_DStringAppendElement(dsPtr, ObjStr(arglistObj)); - Tcl_DStringAppendElement(dsPtr, StripBodyPrefix(ObjStr(procPtr->bodyPtr))); -#if defined(NSF_WITH_ASSERTIONS) - if (procs) { - NsfRequireClassOpt(cl); - AssertionAppendPrePost(interp, dsPtr, procs); - } -#endif - result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), 0); - DSTRING_FREE(dsPtr); - - } else { - /* Next Scripting object-methods */ - NsfObject *object = GetObjectFromString(interp, fromNsPtr->fullName); -#if defined(NSF_WITH_ASSERTIONS) - NsfProcAssertion *procs; -#endif - - if (object) { -#if defined(NSF_WITH_ASSERTIONS) - procs = object->opt ? AssertionFindProcs(object->opt->assertions, name) : NULL; -#endif - } else { - DECR_REF_COUNT(newFullCmdName); - DECR_REF_COUNT(oldFullCmdName); - DECR_REF_COUNT(arglistObj); - return NsfPrintError(interp, "no object for assertions"); - } - - DSTRING_INIT(dsPtr); - Tcl_DStringAppendElement(dsPtr, "::nsf::method::create"); - Tcl_DStringAppendElement(dsPtr, toNsPtr->fullName); - Tcl_DStringAppendElement(dsPtr, "-per-object"); - Tcl_DStringAppendElement(dsPtr, name); - Tcl_DStringAppendElement(dsPtr, ObjStr(arglistObj)); - Tcl_DStringAppendElement(dsPtr, StripBodyPrefix(ObjStr(procPtr->bodyPtr))); -#if defined(NSF_WITH_ASSERTIONS) - if (procs) { - NsfRequireObjectOpt(object); - AssertionAppendPrePost(interp, dsPtr, procs); - } -#endif - result = Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr), Tcl_DStringLength(dsPtr), 0); - DSTRING_FREE(dsPtr); - } - if (result == TCL_OK) { - NsfParamDefs *paramDefs; - paramDefs = ParamDefsGet(cmd); - - if (paramDefs && paramDefs->returns) { - Tcl_DString ds2, *dsPtr2 = &ds2; - DSTRING_INIT(dsPtr2); - Tcl_DStringAppendElement(dsPtr2, "::nsf::method::property"); - Tcl_DStringAppendElement(dsPtr2, cl ? NSCutNsfClasses(toNsPtr->fullName) : toNsPtr->fullName); - Tcl_DStringAppendElement(dsPtr2, ObjStr(Tcl_GetObjResult(interp))); - Tcl_DStringAppendElement(dsPtr2, "returns"); - Tcl_DStringAppendElement(dsPtr2, ObjStr(paramDefs->returns)); - Tcl_EvalEx(interp, Tcl_DStringValue(dsPtr2), Tcl_DStringLength(dsPtr2), 0); - DSTRING_FREE(dsPtr2); - } - } - DECR_REF_COUNT(arglistObj); - } else { - /* Tcl Proc */ - Tcl_VarEval(interp, "proc ", newName, " {", ObjStr(arglistObj), "} {\n", - ObjStr(procPtr->bodyPtr), "}", (char *) NULL); - } - } else { - /* - * Otherwise copy command. - */ - Tcl_ObjCmdProc *objProc = Tcl_Command_objProc(cmd); - Tcl_CmdDeleteProc *deleteProc = Tcl_Command_deleteProc(cmd); - ClientData clientData; - if (objProc) { - clientData = Tcl_Command_objClientData(cmd); - if (clientData == NULL || clientData == (ClientData)NSF_CMD_NONLEAF_METHOD) { - /* if client data is not null, we would have to copy - the client data; we don't know its size...., so rely - on introspection for copying */ - Tcl_CreateObjCommand(interp, newName, objProc, - Tcl_Command_objClientData(cmd), deleteProc); - } - } else { - clientData = Tcl_Command_clientData(cmd); - if (clientData == NULL || clientData == (ClientData)NSF_CMD_NONLEAF_METHOD) { - Tcl_CreateCommand(interp, newName, Tcl_Command_proc(cmd), - Tcl_Command_clientData(cmd), deleteProc); - } - } - } - } - hPtr = Tcl_NextHashEntry(&hSrch); - DECR_REF_COUNT(newFullCmdName); DECR_REF_COUNT(oldFullCmdName); - } - return TCL_OK; -} - -/* cmd nscopyvars NsfNSCopyVars { {-argName "fromNs" -required 1 -type tclobj} {-argName "toNs" -required 1 -type tclobj} @@ -20933,46 +20811,88 @@ /* cmd parameter::get NsfParameterGetCmd { - {-argName "parametersubcmd" -type "list|name|syntax" -required 1} - {-argName "parameterspec" -required 1 -type tclobj} + {-argName "parametersubcmd" -type "default|list|name|syntax|type" -required 1} + {-argName "parameterspec" -required 1 -type tclobj} + {-argName "varname" -required 0 -type tclobj} } */ static int -NsfParameterGetCmd(Tcl_Interp *interp, int parametersubcmd, Tcl_Obj *parameterspec) { +NsfParameterGetCmd(Tcl_Interp *interp, int parametersubcmd, Tcl_Obj *parameterspec, Tcl_Obj *varname) { NsfParsedParam parsedParam; - Tcl_Obj *paramsObj = Tcl_NewListObj(1, ¶meterspec), *listObj = NULL; + Tcl_Obj *paramsObj, *listObj = NULL; Nsf_Param *paramsPtr; int result; + if (parametersubcmd != ParametersubcmdDefaultIdx && varname != NULL) { + return NsfPrintError(interp, "parameter::get: provided third arguement is only valid for querying defaults"); + } + + paramsObj = Tcl_NewListObj(1, ¶meterspec); + INCR_REF_COUNT(paramsObj); result = ParamDefsParse(interp, NULL, paramsObj, - NSF_DISALLOWED_ARG_OBJECT_PARAMETER, 0, + NSF_DISALLOWED_ARG_OBJECT_PARAMETER, 1, &parsedParam); + DECR_REF_COUNT(paramsObj); + if (result != TCL_OK) { return result; } + assert(parsedParam.paramDefs); paramsPtr = parsedParam.paramDefs->paramsPtr; + assert(paramsPtr); switch (parametersubcmd) { + case ParametersubcmdDefaultIdx: + if (paramsPtr->defaultValue) { + if (varname) { + Tcl_Obj *resultObj = Tcl_ObjSetVar2(interp, varname, NULL, + paramsPtr->defaultValue, + TCL_LEAVE_ERR_MSG|TCL_PARSE_PART1); + if (resultObj == NULL) { + ParamDefsRefCountDecr(parsedParam.paramDefs); + return TCL_ERROR; + } + } + Tcl_SetObjResult(interp, NsfGlobalObjs[NSF_ONE]); + } else { + Tcl_SetObjResult(interp, NsfGlobalObjs[NSF_ZERO]); + } + break; + case ParametersubcmdListIdx: listObj = ParamDefsList(interp, paramsPtr); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); break; + case ParametersubcmdNameIdx: listObj = ParamDefsNames(interp, paramsPtr); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); break; - /* case InfoobjectparametersubcmdParameterIdx: - listObj = ParamDefsFormat(interp, paramsPtr); - break;*/ + case ParametersubcmdSyntaxIdx: listObj = NsfParamDefsSyntax(paramsPtr); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); break; + + case ParametersubcmdTypeIdx: + if (paramsPtr->type) { + if (paramsPtr->converter == Nsf_ConvertToTclobj && paramsPtr->converterArg) { + Tcl_SetObjResult(interp, paramsPtr->converterArg); + } else { + Tcl_SetObjResult(interp, Tcl_NewStringObj(paramsPtr->type, -1)); + } + } else { + Tcl_SetObjResult(interp, NsfGlobalObjs[NSF_EMPTY]); + } + break; } - assert(listObj); - Tcl_SetObjResult(interp, listObj); - - DECR_REF_COUNT2("paramDefsObj", listObj); ParamDefsRefCountDecr(parsedParam.paramDefs); + return TCL_OK; } @@ -21046,7 +20966,7 @@ if (withConfigure) { int configure = 0; Tcl_Obj *configureObj = Nsf_ObjGetVar2((Nsf_Object *)slotObject, interp, - NsfGlobalObjs[NSF_CONFIG], NULL, 0); + NsfGlobalObjs[NSF_CONFIGURABLE], NULL, 0); if (!configureObj) continue; Tcl_GetBooleanFromObj(interp, configureObj, &configure); if (!configure) continue; @@ -21250,7 +21170,7 @@ case RelationtypeRootclassIdx: { - NsfClass *metaClass; + NsfClass *metaClass = NULL; if (!NsfObjectIsClass(object)) { return NsfObjErrType(interp, "rootclass", object->cmdName, "class", NULL); @@ -21809,6 +21729,7 @@ ParamSetFromAny2( Tcl_Interp *interp, /* Used for error reporting if not NULL. */ const char *varNamePrefix, /* shows up as varName in error message */ + int configureParameter, /* allow object parameters */ register Tcl_Obj *objPtr) /* The object to convert. */ { Tcl_Obj *fullParamObj = Tcl_NewStringObj(varNamePrefix, -1); @@ -21818,12 +21739,11 @@ paramWrapperPtr->paramPtr = ParamsNew(1); paramWrapperPtr->refCount = 1; paramWrapperPtr->canFree = 0; - /*fprintf(stderr, "allocating %p\n", paramWrapperPtr->paramPtr);*/ Tcl_AppendLimitedToObj(fullParamObj, ObjStr(objPtr), -1, INT_MAX, NULL); INCR_REF_COUNT(fullParamObj); result = ParamParse(interp, NsfGlobalObjs[NSF_VALUECHECK], fullParamObj, - NSF_DISALLOWED_ARG_VALUECHECK /* disallowed options */, + configureParameter ? NSF_DISALLOWED_ARG_OBJECT_PARAMETER : NSF_DISALLOWED_ARG_VALUECHECK, paramWrapperPtr->paramPtr, &possibleUnknowns, &plainParams, &nrNonposArgs); /* @@ -21863,7 +21783,7 @@ Tcl_Interp *interp, /* Used for error reporting if not NULL. */ register Tcl_Obj *objPtr) /* The object to convert. */ { - return ParamSetFromAny2(interp, "value:", objPtr); + return ParamSetFromAny2(interp, "value:", 0, objPtr); } /* @@ -22019,7 +21939,9 @@ static int ParameterCheck(Tcl_Interp *interp, Tcl_Obj *paramObjPtr, Tcl_Obj *valueObj, - const char *argNamePrefix, int doCheckArguments, Nsf_Param **paramPtrPtr) { + const char *argNamePrefix, int doCheckArguments, + int isNamed, int doConfigureParameter, + Nsf_Param **paramPtrPtr) { Nsf_Param *paramPtr; NsfParamWrapper *paramWrapperPtr; Tcl_Obj *outObjPtr = NULL; @@ -22034,10 +21956,10 @@ } else { /* * We could use in principle Tcl_ConvertToType(..., ¶mObjType) instead - * of checking the type manually, be we want to pass the argNamePrefix + * of checking the type manually, but we want to pass the argNamePrefix * explicitly. */ - result = ParamSetFromAny2(interp, argNamePrefix, paramObjPtr); + result = ParamSetFromAny2(interp, argNamePrefix, doConfigureParameter, paramObjPtr); if (result == TCL_OK) { paramWrapperPtr = (NsfParamWrapper *) paramObjPtr->internalRep.twoPtrValue.ptr1; } else { @@ -22047,6 +21969,10 @@ paramPtr = paramWrapperPtr->paramPtr; if (paramPtrPtr) *paramPtrPtr = paramPtr; + if (isNamed) { + paramPtr->flags &= ~NSF_ARG_UNNAMED; + } + result = ArgumentCheck(interp, valueObj, paramPtr, doCheckArguments, &flags, &checkedData, &outObjPtr); /*fprintf(stderr, "ParameterCheck paramPtr %p final refCount of wrapper %d can free %d flags %.6x\n", paramPtr, paramWrapperPtr->refCount, paramWrapperPtr->canFree, flags);*/ @@ -22263,20 +22189,24 @@ } } } else if (unlikely(paramPtr->flags & NSF_ARG_REQUIRED - && pc.full_objv[i] == NsfGlobalObjs[NSF___UNKNOWN__] - && (object->flags & NSF_INIT_CALLED) == 0) - ) { - /* - * The checking for required arguments happens only, when the actual - * value is not the default, but the magic __UNKNOWN Tcl_Obj, and the - * object is not jet initialized. Logic behind this: if the object is - * initialized, configure must have been called before, and the required - * action must have been already taken). We might change this to the - * overwriting logic like above, but we have as well to deal with - * aliases. + && pc.full_objv[i] == NsfGlobalObjs[NSF___UNKNOWN__])) { + + /* Previous versions contained a test for + * (object->flags & NSF_INIT_CALLED) + * + * to perform required testing just for in the non-initialized state. We + * switched in 2.0b5 to checking for the existance of the associated + * instance variable, which works under the assumption that the instance + * variable has the same name and that e.g. an required alias parameter + * sets this variable either. Similar assumption is in the default + * handling. Future versions might use a more generneral handling of the + * parameter states. */ + + Tcl_Obj *varObj = Tcl_ObjGetVar2(interp, paramPtr->nameObj, NULL, TCL_PARSE_PART1); + if (varObj == NULL) { Tcl_Obj *paramDefsObj = NsfParamDefsSyntax(paramDefs->paramsPtr); - + NsfPrintError(interp, "required argument '%s' is missing, should be:\n\t%s%s%s %s", paramPtr->nameObj ? ObjStr(paramPtr->nameObj) : paramPtr->name, pc.object ? ObjectName(pc.object) : "", @@ -22288,6 +22218,7 @@ Nsf_PopFrameObj(interp, framePtr); result = TCL_ERROR; goto configure_exit; + } } newValue = pc.full_objv[i]; @@ -22321,9 +22252,11 @@ /* * Special setter methods for invoking methods calls; handles types - * "initcmd", "alias" and "forward". + * "cmd", "initcmd", "alias" and "forward". */ - if (paramPtr->flags & NSF_ARG_METHOD_INVOCATION) { + if ((paramPtr->flags & NSF_ARG_METHOD_INVOCATION) + //&& (paramPtr->flags & NSF_ARG_METHOD_CALL || object->flags & NSF_INIT_CALLED) + ) { int consuming = (*paramPtr->name == '-' || paramPtr->nrArgs > 0); if (consuming && newValue == NsfGlobalObjs[NSF___UNKNOWN__]) { @@ -22335,7 +22268,54 @@ /*fprintf(stderr, "%s consuming nrargs %d no value\n", paramPtr->name, paramPtr->nrArgs);*/ continue; } - // oooo; + + if ((paramPtr->flags & NSF_ARG_INITCMD)) { + // oooo; + + if (paramPtr->defaultValue) { + /* + * The "defaultValue" holds the initcmd to be executed + */ + Tcl_Obj *varObj = Tcl_ObjGetVar2(interp, NsfGlobalObjs[NSF_ARRAY_INITCMD], + paramPtr->nameObj, 0); + // TODO cleanup + /*fprintf(stderr, "INITCMD isdefault %d default %s value %p var %p\n", + (pc.flags[i-1] & NSF_PC_IS_DEFAULT), + paramPtr->defaultValue ? ObjStr(paramPtr->defaultValue) : "NONE", + ObjStr(newValue), + varObj + );*/ + if (varObj == NULL) { + /* + * The variable is not set. Therefore, we assume, we have to + * execute the initcmd. On success, we note the execution in the NSF_ARRAY_INITCMD + * variable (usually __initcmd(name)) + */ + result = ParameterMethodDispatch(interp, object, paramPtr, paramPtr->defaultValue, + uplevelVarFramePtr, initString, + objv[pc.lastObjc], (Tcl_Obj **)&objv[pc.lastObjc + 1], + objc - pc.lastObjc); + if (result != TCL_OK) { + Nsf_PopFrameObj(interp, framePtr); + goto configure_exit; + } + Tcl_ObjSetVar2(interp, NsfGlobalObjs[NSF_ARRAY_INITCMD], + paramPtr->nameObj, Tcl_NewIntObj(1), 0); + } + + } else { + //TODO should we require a default? + + } + /* + * if we have a new actual value, proceed to setvars + */ + if ((pc.flags[i-1] & NSF_PC_IS_DEFAULT) == 0) { + goto setvars; + } + continue; + } + result = ParameterMethodDispatch(interp, object, paramPtr, newValue, uplevelVarFramePtr, initString, objv[pc.lastObjc], (Tcl_Obj **)&objv[pc.lastObjc + 1], @@ -22347,6 +22327,7 @@ continue; } + setvars: if (newValue == NsfGlobalObjs[NSF___UNKNOWN__]) { /* * Nothing to do, we have a value setter, but no value is specified and @@ -22401,6 +22382,10 @@ ParamDefsRefCountDecr(paramDefs); ParseContextRelease(&pc); + + if (result == TCL_OK) { + Tcl_ResetResult(interp); + } return result; } @@ -22467,7 +22452,7 @@ } if (!found) { - result = NsfPrintError(interp, "cannot lookup parameter value for %s", nameString); + result = NsfPrintError(interp, "cget: unknown configure parameter %s", nameString); goto cget_exit; } @@ -22496,7 +22481,7 @@ /* * We do NOT have a slot */ - if (found && paramPtr->flags & NSF_ARG_METHOD_INVOCATION) { + if (found && paramPtr->flags & NSF_ARG_METHOD_CALL) { if (paramPtr->flags & NSF_ARG_ALIAS) { /* * It is a parameter associated with an aliased method. Invoke the @@ -23288,6 +23273,23 @@ } /* +classMethod getCachedParameters NsfCGetCachendParameters { +} +*/ +static int +NsfCGetCachendParameters(Tcl_Interp *interp, NsfClass *class) { + + if (likely(class && class->parsedParamPtr)) { + Tcl_Obj *listObj; + + listObj = ListParamDefs(interp, class->parsedParamPtr->paramDefs->paramsPtr, NSF_PARAMS_PARAMETER); + Tcl_SetObjResult(interp, listObj); + DECR_REF_COUNT2("paramDefsObj", listObj); + } + return TCL_OK; +} + +/* classMethod mixinguard NsfCMixinGuardMethod { {-argName "mixin" -required 1 -type tclobj} {-argName "guard" -required 1 -type tclobj} @@ -23726,10 +23728,10 @@ objectInfoMethod lookupmethods NsfObjInfoLookupMethodsMethod { {-argName "-callprotection" -nrargs 1 -type "all|public|protected|private" -default all} {-argName "-incontext"} - {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} + {-argName "-type" -nrargs 1 -typeName "methodtype" -type "all|scripted|builtin|alias|forwarder|object|setter"} {-argName "-nomixins"} {-argName "-path" -nrargs 0} - {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} + {-argName "-source" -nrargs 1 -type "all|application|system"} {-argName "pattern" -required 0} } */ @@ -23798,10 +23800,11 @@ } if (object->flags & NSF_MIXIN_ORDER_DEFINED_AND_VALID) { NsfCmdList *ml; - NsfClass *mixin; + for (ml = object->mixinOrder; ml; ml = ml->nextPtr) { int guardOk = TCL_OK; - mixin = NsfGetClassFromCmdPtr(ml->cmdPtr); + NsfClass *mixin = NsfGetClassFromCmdPtr(ml->cmdPtr); + assert(mixin); if (withIncontext) { if (!RUNTIME_STATE(interp)->guardCount) { @@ -23830,7 +23833,7 @@ /* objectInfoMethod lookupslots NsfObjInfoLookupSlotsMethod { - {-argName "-source" -nrargs 1 -type "all|application|baseclasses" -default all} + {-argName "-source" -nrargs 1 -type "all|application|system" -default all} {-argName "-type" -required 0 -nrargs 1 -type class} {-argName "pattern" -required 0} } @@ -23878,7 +23881,7 @@ /* objectInfoMethod method NsfObjInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|exists|registrationhandle|definitionhandle|handle|origin|parameter|syntax|type|precondition|postcondition|submethods"} + {-argName "infomethodsubcmd" -type "args|body|definition|exists|registrationhandle|definitionhandle|origin|parameter|syntax|type|precondition|postcondition|submethods"} {-argName "name" -required 1 -type tclobj} } */ @@ -23894,9 +23897,6 @@ Tcl_DStringInit(dsPtr); cmd = ResolveMethodName(interp, object->nsPtr, methodNameObj, dsPtr, ®Object, &defObject, &methodName1, &fromClassNS); - if (subcmd == InfomethodsubcmdHandleIdx) { - subcmd = InfomethodsubcmdDefinitionhandleIdx; - } /*fprintf(stderr, "NsfObjInfoMethodMethod method %s / %s object %p regObject %p defObject %p fromClass %d\n", ObjStr(methodNameObj), methodName1, object, regObject, defObject, fromClassNS);*/ @@ -23912,7 +23912,7 @@ /* objectInfoMethod methods NsfObjInfoMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} - {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} + {-argName "-type" -nrargs 1 -typeName "methodtype" -type "all|scripted|builtin|alias|forwarder|object|setter"} {-argName "-path" -nrargs 0} {-argName "pattern"} } @@ -24080,7 +24080,7 @@ static int NsfObjInfoPrecedenceMethod(Tcl_Interp *interp, NsfObject *object, int withIntrinsicOnly, CONST char *pattern) { - NsfClasses *precedenceList = NULL, *pl; + NsfClasses *precedenceList, *pl; Tcl_Obj *resultObj = Tcl_NewObj(); precedenceList = ComputePrecedenceList(interp, object, pattern, !withIntrinsicOnly, 1); @@ -24291,7 +24291,7 @@ /* classInfoMethod method NsfClassInfoMethodMethod { - {-argName "infomethodsubcmd" -type "args|body|definition|exists|registrationhandle|definitionhandle|origin|handle|parameter|syntax|type|precondition|postcondition|submethods|returns"} + {-argName "infomethodsubcmd" -type "args|body|definition|exists|registrationhandle|definitionhandle|origin|parameter|syntax|type|precondition|postcondition|submethods|returns"} {-argName "name" -required 1 -type tclobj} } */ @@ -24307,10 +24307,6 @@ Tcl_DStringInit(dsPtr); cmd = ResolveMethodName(interp, class->nsPtr, methodNameObj, dsPtr, ®Object, &defObject, &methodName1, &fromClassNS); - if (subcmd == InfomethodsubcmdHandleIdx) { - subcmd = InfomethodsubcmdDefinitionhandleIdx; - } - /*fprintf(stderr, "NsfClassInfoMethodMethod object %p regObject %p defObject %p %s fromClass %d cmd %p method %s\n", &class->object, regObject, defObject, ObjectName(defObject), fromClassNS, cmd, methodName1);*/ @@ -24329,9 +24325,9 @@ classInfoMethod methods NsfClassInfoMethodsMethod { {-argName "-callprotection" -type "all|public|protected|private" -default all} {-argName "-closure" -nrargs 0} - {-argName "-methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} + {-argName "-type" -typeName "methodtype" -nrargs 1 -type "all|scripted|builtin|alias|forwarder|object|setter"} {-argName "-path" -nrargs 0} - {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} + {-argName "-source" -nrargs 1 -type "all|application|system"} {-argName "pattern"} } */ @@ -24518,7 +24514,7 @@ /* classInfoMethod slots NsfClassInfoSlotobjectsMethod { {-argName "-closure" -nrargs 0} - {-argName "-source" -nrargs 1 -type "all|application|baseclasses"} + {-argName "-source" -nrargs 1 -type "all|application|system"} {-argName "-type" -required 0 -nrargs 1 -type class} {-argName "pattern" -required 0} } @@ -24764,7 +24760,6 @@ Tcl_HashTable *cmdTablePtr, *childTablePtr; register Tcl_HashEntry *entryPtr; Tcl_HashSearch search; - Tcl_Command cmd; if (nsPtr == NULL) { nsPtr = Tcl_GetGlobalNamespace(interp); @@ -24779,7 +24774,8 @@ for (entryPtr = Tcl_FirstHashEntry(cmdTablePtr, &search); entryPtr; entryPtr = Tcl_NextHashEntry(&search)) { - cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr); + Tcl_Command cmd = (Tcl_Command)Tcl_GetHashValue(entryPtr); + if (Tcl_Command_objProc(cmd) == NsfProcStub) { /*fprintf(stderr, "cmdname = %s cmd %p\n", Tcl_GetHashKey(cmdTablePtr, entryPtr), cmd);*/ @@ -25045,9 +25041,9 @@ * the remaining objects to their base classes, and set the superclasses * to the most general superclass. */ - for (entry = *instances, lastEntry = NULL; + for (entry = *instances; entry; - lastEntry = entry, entry = entry->nextPtr) { + entry = entry->nextPtr) { NsfObject *object = (NsfObject *)entry->clorobj; NsfClass *baseClass; NsfObjectSystem *osPtr; @@ -25255,24 +25251,44 @@ int Nsf_Init(Tcl_Interp *interp) { + static NsfMutex initMutex = 0; ClientData runtimeState; - int result, i; NsfRuntimeState *rst; - + int result, i; #ifdef NSF_BYTECODE /*NsfCompEnv *interpstructions = NsfGetCompEnv();*/ #endif - static NsfMutex initMutex = 0; +#ifdef USE_TCL_STUBS + static int stubsInitialized = 0; +#endif + #if 0 ProfilerStart("profiler"); #endif + #ifdef USE_TCL_STUBS - if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { - return TCL_ERROR; + /* + * Since the stub-tables are initialized globally (not per interp), we want + * to initialize these only once. The read operation on "stubsInitialized" + * is a potentially dirty read. However, we can't use a mutex lock around + * this, since Tcl_MutexLock() requires (at least on some platforms) + * initialized stub-tables. The dirty read of stubsInitialized is not so + * invasive as the dirty reads caused by overwriting the stub tables. + * + * NsfMutexLock(&stubFlagMutex); + * ... + * NsfMutexUnlock(&stubFlagMutex); + */ + + if (stubsInitialized == 0) { + if (Tcl_InitStubs(interp, "8.5", 0) == NULL) { + return TCL_ERROR; + } + if (Tcl_TomMath_InitStubs(interp, "8.5") == NULL) { + return TCL_ERROR; + } + stubsInitialized = 1; } - if (Tcl_TomMath_InitStubs(interp, "8.5") == NULL) { - return TCL_ERROR; - } #endif #if defined(TCL_MEM_DEBUG)