Index: TODO =================================================================== diff -u -N -r5a162b098b6a9550218646d470b274769bda8da1 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- TODO (.../TODO) (revision 5a162b098b6a9550218646d470b274769bda8da1) +++ TODO (.../TODO) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -5660,15 +5660,35 @@ "/obj/ info baseclass" - extended regression test + +- added nsf::method::property /obj/ /method/ debug ?0|1? + when debug is activated, a debug line written to the log file when + the function is called and exited + +- added nsf::method::property /obj/ /method/ deprecated ?0|1? + when deprecated is activated, a warning written to the log file when + the function is called + +- added flags to nsf::proc: -debug and -deprecated + (can als be set via nsf::method::property with an arbitrary object + and proc passed fully qualified) + +- bumped version number to 2.0.1 + ======================================================================== TODO: +- handling deprecated and debug in serializer (for methods and nsf::proc) +- add regression tests for debug and deprecated in methods +- add tests for nsf::proc flags -debug and -deprecated + - add to doc: info object method callprotection info method callprotection info baseclass + nsf::proc flags -debug and -deprecated - gcc6: - * ISOBJ(methodObj); will raise a warning, when methodObj is decared as nonnull + * ISOBJ(methodObj); will raise a warning, when methodObj is declared as nonnull * Same with ObjectName() and ClassName() * gcc6 seems to have a bug: when e.g. a variable "foo" is declared as nonnull, then the construct Index: configure =================================================================== diff -u -N -r1c9684a6be93da0beb9e73d6ff02ed2b6f014c19 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- configure (.../configure) (revision 1c9684a6be93da0beb9e73d6ff02ed2b6f014c19) +++ configure (.../configure) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for nsf 2.0.0. +# Generated by GNU Autoconf 2.69 for nsf 2.0.1. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='nsf' PACKAGE_TARNAME='nsf' -PACKAGE_VERSION='2.0.0' -PACKAGE_STRING='nsf 2.0.0' +PACKAGE_VERSION='2.0.1' +PACKAGE_STRING='nsf 2.0.1' PACKAGE_BUGREPORT='xotcl@alice.wu-wien.ac.at' PACKAGE_URL='' @@ -1333,7 +1333,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures nsf 2.0.0 to adapt to many kinds of systems. +\`configure' configures nsf 2.0.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1394,7 +1394,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of nsf 2.0.0:";; + short | recursive ) echo "Configuration of nsf 2.0.1:";; esac cat <<\_ACEOF @@ -1513,7 +1513,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -nsf configure 2.0.0 +nsf configure 2.0.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -1882,7 +1882,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by nsf $as_me 2.0.0, which was +It was created by nsf $as_me 2.0.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -8947,13 +8947,14 @@ # # Next Scripting specific configs # +#NSF_SRC_DIR=$srcdir +#NSF_SRC_DIR="`pwd`" NSF_BUILD_DIR=${PWD} cd ${srcdir} NSF_SRC_DIR=${PWD} cd ${NSF_BUILD_DIR} -#NSF_SRC_DIR="`pwd`" eval "NSF_PKG_LIBDIR=\"${libdir}/${PACKAGE_NAME}${PACKAGE_VERSION}\"" @@ -9587,7 +9588,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by nsf $as_me 2.0.0, which was +This file was extended by nsf $as_me 2.0.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -9640,7 +9641,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -nsf config.status 2.0.0 +nsf config.status 2.0.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" @@ -10215,7 +10216,7 @@ if test x"${srcdir}" = x. ; then confdir=. else - #mkdir -p $subdir + #mkdir -p $subdir confdir=${srcdir}/$subdir fi (cd $subdir; echo $SHELL ${confdir}/configure ${ac_configure_args} --prefix=${prefix} --with-nsf=${NSF_SRC_DIR}; eval $SHELL ${confdir}/configure ${ac_configure_args} --prefix=${prefix} --with-nsf=${NSF_SRC_DIR}) Index: configure.ac =================================================================== diff -u -N -r1c9684a6be93da0beb9e73d6ff02ed2b6f014c19 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- configure.ac (.../configure.ac) (revision 1c9684a6be93da0beb9e73d6ff02ed2b6f014c19) +++ configure.ac (.../configure.ac) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -13,7 +13,7 @@ #-------------------------------------------------------------------- AC_PREREQ([2.69]) -define(NsfVersion, 2.0.0) +define(NsfVersion, 2.0.1) AC_INIT([nsf],[NsfVersion], [xotcl@alice.wu-wien.ac.at]) AC_CONFIG_MACRO_DIR([m4]) Index: generic/nsf.c =================================================================== diff -u -N -r5a162b098b6a9550218646d470b274769bda8da1 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsf.c (.../nsf.c) (revision 5a162b098b6a9550218646d470b274769bda8da1) +++ generic/nsf.c (.../nsf.c) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -580,9 +580,11 @@ * * NsfDeprecatedCmd -- * - * Provide a warning about a deprecated command or method. The - * message is produced via calling the external Tcl function - * ::nsf::deprecated. + * Provide a warning about a deprecated command or method. The message is + * produced via calling the external Tcl function ::nsf::deprecated. In + * case, profiling is turned on, it is deactivated temporarily. Saving + * the interp result should not be an issue, since the command is called + * before the body of the command is executed. * * Results: * None. @@ -592,12 +594,11 @@ * *---------------------------------------------------------------------- */ -static void NsfDeprecatedCmd(Tcl_Interp *interp, const char *what, const char *oldCmd, const char *newCmd) - nonnull(1) nonnull(2) nonnull(3) nonnull(4); - -static void +void NsfDeprecatedCmd(Tcl_Interp *interp, const char *what, const char *oldCmd, const char *newCmd) { + NsfRuntimeState *rst = RUNTIME_STATE(interp); Tcl_DString ds, *dsPtr = &ds; + int prevProfileSetting; nonnull_assert(interp != NULL); nonnull_assert(newCmd != NULL); @@ -609,7 +610,12 @@ Tcl_DStringAppendElement(dsPtr, what); Tcl_DStringAppendElement(dsPtr, oldCmd); Tcl_DStringAppendElement(dsPtr, newCmd); + + prevProfileSetting = rst->doProfile; + rst->doProfile = 0; NsfDStringEval(interp, dsPtr, "log command"); + rst->doProfile = prevProfileSetting; + Tcl_DStringFree(dsPtr); } @@ -688,7 +694,8 @@ * *---------------------------------------------------------------------- */ -static void ParseContextExtendObjv(ParseContext *pcPtr, int from, int elts, Tcl_Obj *CONST source[]) nonnull(1) nonnull(4); +static void ParseContextExtendObjv(ParseContext *pcPtr, int from, int elts, Tcl_Obj *CONST source[]) + nonnull(1) nonnull(4); static void ParseContextExtendObjv(ParseContext *pcPtr, int from, int elts, Tcl_Obj *CONST source[]) { @@ -701,7 +708,9 @@ if (unlikely(requiredSize >= PARSE_CONTEXT_PREALLOC)) { if (pcPtr->objv == &pcPtr->objv_static[1]) { - /* realloc from preallocated memory */ + /* + * Realloc from preallocated memory + */ pcPtr->full_objv = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj *) * requiredSize); pcPtr->flags = (unsigned int *)ckalloc(sizeof(int) * requiredSize); MEM_COUNT_ALLOC("pcPtr.objv", pcPtr->full_objv); @@ -712,7 +721,9 @@ pcPtr->status |= NSF_PC_STATUS_FREE_OBJV; } else { - /* realloc from mallocated memory */ + /* + * Realloc from mallocated memory + */ pcPtr->full_objv = (Tcl_Obj **) ckrealloc((char *)pcPtr->full_objv, sizeof(Tcl_Obj *) * requiredSize); pcPtr->flags = (unsigned int *)ckrealloc((char *)pcPtr->flags, sizeof(int) * requiredSize); /*fprintf(stderr, "ParseContextExtendObjv: extend %p realloc %d new objv=%p pcPtr %p\n", @@ -3833,7 +3844,7 @@ for (mixinList = object->mixinOrder; mixinList; mixinList = mixinList->nextPtr) { NsfClass *mixin = NsfGetClassFromCmdPtr(mixinList->cmdPtr); if (mixin && (*pcl = (*lookupFunction)(interp, mixin, methodObj, &cmd))) { - if (Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD && !NsfObjectIsClass(object)) { + if ((Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD) != 0 && !NsfObjectIsClass(object)) { cmd = NULL; continue; } @@ -9020,8 +9031,8 @@ nonnull_assert(object != NULL); nonnull_assert(cmdList != NULL); - if ((cmdFlags & NSF_CMD_CALL_PRIVATE_METHOD) || - ((cmdFlags & NSF_CMD_CLASS_ONLY_METHOD) && !NsfObjectIsClass(object))) { + if ((cmdFlags & NSF_CMD_CALL_PRIVATE_METHOD) != 0 || + ((cmdFlags & NSF_CMD_CLASS_ONLY_METHOD) != 0 && !NsfObjectIsClass(object))) { /* * The command is not applicable for objects (i.e. might crash, * since it expects a class record); therefore skip it @@ -9078,7 +9089,7 @@ nonnull_assert(clPtr != NULL); nonnull_assert(currentCmdPtr != NULL); nonnull_assert(cmdPtr != NULL); - + assert(object->mixinStack != NULL); /* ensure that the mixin order is valid */ @@ -10445,7 +10456,7 @@ nonnull_assert(object != NULL); nonnull_assert(currentCmd != NULL); nonnull_assert(clPtr != NULL); - + assert(object->filterStack != NULL); /* * Ensure that the filter order is not invalid, otherwise compute order @@ -11979,9 +11990,9 @@ nonnull_assert(listObj != NULL); nonnull_assert(paramsPtr != NULL); nonnull_assert(formatFunction != NULL); - + assert(paramsPtr->name != NULL); - + if (paramsPtr->converter == ConvertToNothing && strcmp(paramsPtr->name, "args") == 0) { if ((contextObject != NULL) @@ -12293,7 +12304,7 @@ nonnull_assert(cmdPtr != NULL); nonnull_assert(cscPtr != NULL); nonnull_assert(object != NULL); - + assert(object->teardown != NULL); #if defined(NRE) @@ -12476,7 +12487,7 @@ nonnull_assert(objv != NULL); nonnull_assert(cmd != NULL); nonnull_assert(object != NULL); - + assert(object->teardown != NULL); #if defined(NRE) @@ -12971,6 +12982,12 @@ (char *)methodName, objc-1, (Tcl_Obj **)objv+1); } + if (unlikely((Tcl_Command_flags(cmd) & NSF_CMD_DEPRECATED_METHOD) != 0)) { + NsfProfileDeprecatedCall(interp, object, cscPtr->cl, methodName, ""); + } + if (unlikely((Tcl_Command_flags(cmd) & NSF_CMD_DEBUG_METHOD) != 0)) { + NsfProfileDebugCall(interp, object, cscPtr->cl, methodName, objc-1, (Tcl_Obj **)objv+1); + } /*fprintf(stderr, "MethodDispatch method '%s' cmd %p %s clientData %p cp=%p objc=%d cscPtr %p csc->flags %.6x \n", methodName, cmd, Tcl_GetCommandName(interp, cmd), clientData, @@ -13069,7 +13086,7 @@ #endif - } else if ((Tcl_Command_flags(cmd) & NSF_CMD_NONLEAF_METHOD) + } else if ((Tcl_Command_flags(cmd) & NSF_CMD_NONLEAF_METHOD) != 0 || ((cscPtr->flags & NSF_CSC_FORCE_FRAME) != 0u)) { /* * Technically, we would not need a frame to execute the cmd, but maybe, @@ -13138,7 +13155,7 @@ nonnull_assert(cmd != NULL); nonnull_assert(object != NULL); nonnull_assert(methodName != NULL); - + assert(object->teardown != NULL); CheckCStack(interp, "method", methodName); @@ -13212,7 +13229,7 @@ nonnull_assert(interp != NULL); nonnull_assert(cscPtr != NULL); - + object = cscPtr->self; assert(object != NULL); assert(object->id != NULL); @@ -13588,7 +13605,7 @@ * b) trying to call an object with no method interface */ if (((flags & (NSF_CM_LOCAL_METHOD|NSF_CM_IGNORE_PERMISSIONS)) == 0u - && (Tcl_Command_flags(cmd) & NSF_CMD_CALL_PRIVATE_METHOD)) + && (Tcl_Command_flags(cmd) & NSF_CMD_CALL_PRIVATE_METHOD) != 0) ) { cmd = NULL; } else { @@ -16356,29 +16373,22 @@ * *---------------------------------------------------------------------- */ -static int InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr) - nonnull(1) nonnull(2) nonnull(4) nonnull(3); +static int InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr, struct timeval *trtPtr) + nonnull(1) nonnull(2) nonnull(4) nonnull(3) nonnull(4); static int -InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr) { - Tcl_Obj *CONST *objv; - int objc, result; - const char *fullMethodName = ObjStr(procNameObj); +InvokeShadowedProc(Tcl_Interp *interp, Tcl_Obj *procNameObj, Tcl_Command cmd, ParseContext *pcPtr, struct timeval *trtPtr) { + Tcl_Obj *CONST *objv; + int objc, result; + const char *fullMethodName = ObjStr(procNameObj); Tcl_CallFrame *framePtr; - Proc *procPtr; -#if defined(NSF_PROFILE) - struct timeval trt; - NsfRuntimeState *rst = RUNTIME_STATE(interp); + Proc *procPtr; - if (rst->doProfile != 0) { - gettimeofday(&trt, NULL); - } -#endif - nonnull_assert(interp != NULL); nonnull_assert(procNameObj != NULL); nonnull_assert(cmd != NULL); nonnull_assert(pcPtr != NULL); + nonnull_assert(trtPtr != NULL); objv = pcPtr->full_objv; objc = pcPtr->objc+1; @@ -16390,8 +16400,6 @@ * slightly adapted to remove object dependencies. */ - /*fprintf(stderr, "fullMethodName %s epoch %d\n", fullMethodName, Tcl_Command_cmdEpoch(cmd));*/ - if (Tcl_Command_cmdEpoch(cmd)) { #if 1 /* @@ -16401,9 +16409,8 @@ return NsfPrintError(interp, "command '%s' is epoched", fullMethodName); #else /* - * We could refetch the command ... + * We must refetch the command ... */ - cmd = Tcl_GetCommandFromObj(interp, procNameObj); if (unlikely(cmd == NULL)) { return NsfPrintError(interp, "cannot lookup command '%s'", fullMethodName); @@ -16412,20 +16419,14 @@ return NsfPrintError(interp, "command '%s' is not a proc", fullMethodName); } /* - * ... and update the refCounts + * ... and update the refCounts and cmd in ClientData */ NsfCommandRelease(tcd->cmd); tcd->cmd = cmd; NsfCommandPreserve(tcd->cmd); #endif } -#if defined(NSF_PROFILE) - if (rst->doTrace) { - NsfProfileTraceCallAppend(interp, fullMethodName); - } -#endif - procPtr = (Proc *)Tcl_Command_objClientData(cmd); result = TclPushStackFrame(interp, &framePtr, (Tcl_Namespace *) procPtr->cmdPtr->nsPtr, @@ -16450,8 +16451,8 @@ Tcl_NRAddCallback(interp, ProcDispatchFinalize, (ClientData)fullMethodName, pcPtr, # if defined(NSF_PROFILE) - (ClientData)(unsigned long)trt.tv_usec, - (ClientData)(unsigned long)trt.tv_sec + (ClientData)(unsigned long)trtPtr->tv_usec, + (ClientData)(unsigned long)trtPtr->tv_sec # else NULL, NULL @@ -16464,8 +16465,8 @@ (ClientData)fullMethodName, pcPtr, # if defined(NSF_PROFILE) - (ClientData)(unsigned long)trt.tv_usec, - (ClientData)(unsigned long)trt.tv_sec + (ClientData)(unsigned long)trtPtr->tv_usec, + (ClientData)(unsigned long)trtPtr->tv_sec # else NULL, NULL @@ -16512,35 +16513,61 @@ if (likely(tcd->paramDefs && tcd->paramDefs->paramsPtr)) { ParseContext *pcPtr = (ParseContext *) NsfTclStackAlloc(interp, sizeof(ParseContext), "parse context"); -#if 0 - /* i see no difference from tcl */ - ALLOC_ON_STACK(Tcl_Obj*, objc, tov); - /* - * We have to substitute the first element of objv with the name - * of the function to be called. Since objv is immutable, we have - * to copy the full argument vector and replace the element on - * position [0] - */ - memcpy(tov+1, objv+1, sizeof(Tcl_Obj *)*(objc-1)); - tov[0] = tcd->procName; -#endif /* If the argument parsing is ok, the shadowed proc will be called */ result = ProcessMethodArguments(pcPtr, interp, NULL, - tcd->checkAlwaysFlag|NSF_ARGPARSE_FORCE_REQUIRED, + (((tcd->flags & NSF_PROC_FLAG_CHECK_ALWAYS) != 0) ? NSF_ARGPARSE_CHECK : 0) + |NSF_ARGPARSE_FORCE_REQUIRED, tcd->paramDefs, objv[0], objc, objv); if (likely(result == TCL_OK)) { - result = InvokeShadowedProc(interp, tcd->procName, tcd->cmd, pcPtr); + Tcl_Command cmd = tcd->wrapperCmd; + int cmdFlags; + struct timeval trt; + + assert(cmd != NULL); + + cmdFlags = Tcl_Command_flags(cmd); + +#if defined(NSF_PROFILE) + gettimeofday(&trt, NULL); + + if (RUNTIME_STATE(interp)->doTrace) { + NsfProfileTraceCallAppend(interp, ObjStr(objv[0])); + } + if ((cmdFlags & NSF_CMD_DEBUG_METHOD) != 0) { + NsfProfileDebugCall(interp, NULL, NULL, ObjStr(objv[0]), objc-1, (Tcl_Obj **)objv+1); + } +#else + if ((cmdFlags & NSF_CMD_DEBUG_METHOD) != 0) { + gettimeofday(&trt, NULL); + + NsfProfileDebugCall(interp, NULL, NULL, ObjStr(objv[0]), objc-1, (Tcl_Obj **)objv+1); + } else { + trt.tv_sec = 0; + trt.tv_usec = 0; + } +#endif + if ((cmdFlags & NSF_CMD_DEPRECATED_METHOD) != 0) { + NsfDeprecatedCmd(interp, "proc", ObjStr(objv[0]), ""); + } + + result = InvokeShadowedProc(interp, tcd->procName, tcd->cmd, pcPtr, &trt); + + if ((cmdFlags & NSF_CMD_DEBUG_METHOD) != 0) { + NsfProfileDebugExit(interp, NULL, NULL, ObjStr(objv[0]), trt.tv_sec, trt.tv_usec); + } + } else { - /*Tcl_Obj *resultObj = Tcl_GetObjResult(interp); - fprintf(stderr, "NsfProcStub: incorrect arguments (%s)\n", ObjStr(resultObj));*/ + /* + * Result is already set to TCL_ERROR, the error message should be already + * provided. + */ ParseContextRelease(pcPtr); NsfTclStackFree(interp, pcPtr, "release parse context"); } - /*FREE_ON_STACK(Tcl_Obj *, tov);*/ } else { fprintf(stderr, "no parameters\n"); assert(0); /* should never happen */ @@ -16575,21 +16602,22 @@ *---------------------------------------------------------------------- */ static int NsfProcAdd(Tcl_Interp *interp, NsfParsedParam *parsedParamPtr, - const char *procName, Tcl_Obj *body, - int with_ad, int with_checkAlways) nonnull(1) nonnull(2) nonnull(3) nonnull(4); + const char *procName, Tcl_Obj *body, + int with_ad, int with_checkAlways, int with_Debug, int with_Deprecated) + nonnull(1) nonnull(2) nonnull(3) nonnull(4); static int NsfProcAdd(Tcl_Interp *interp, NsfParsedParam *parsedParamPtr, const char *procName, Tcl_Obj *body, - int with_ad, int with_checkAlways) { - NsfParamDefs *paramDefs; - Nsf_Param *paramPtr; + int with_ad, int with_checkAlways, int with_Debug, int with_Deprecated) { + NsfParamDefs *paramDefs; + Nsf_Param *paramPtr; NsfProcClientData *tcd; - Tcl_Namespace *cmdNsPtr; - Tcl_Obj *argList, *procNameObj, *ov[4]; - Tcl_DString ds, *dsPtr = &ds; - int result, checkAlwaysFlag; - Tcl_Command cmd; + Tcl_Namespace *cmdNsPtr; + Tcl_Obj *argList, *procNameObj, *ov[4]; + Tcl_DString ds, *dsPtr = &ds; + int result, checkAlwaysFlag; + Tcl_Command cmd; nonnull_assert(interp != NULL); nonnull_assert(parsedParamPtr != NULL); @@ -16623,12 +16651,11 @@ } checkAlwaysFlag = (with_checkAlways != 0) ? NSF_ARGPARSE_CHECK : 0; - cmdNsPtr = Tcl_Command_nsPtr(cmd); /* - * Storing param defs is actually not needed to be stored, since the stub - * receives paramters + flag via client data... but it is needed for + * Storing param definitions is not needed for running the proc, since the + * stub receives parameters + flag via client data... but it is needed for * introspection. */ paramDefs = parsedParamPtr->paramDefs; @@ -16639,8 +16666,7 @@ /* * Let us create the shadowed Tcl proc, which is stored under - * ::nsf::procs::*. First build the fully qualified name - * procNameObj. + * ::nsf::procs::*. First build the fully qualified name procNameObj. */ Tcl_DStringSetLength(dsPtr, 0); Tcl_DStringAppend(dsPtr, "::nsf::procs", -1); @@ -16654,8 +16680,9 @@ * it does not exist. */ { - Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; + Namespace *nsPtr, *dummy1Ptr, *dummy2Ptr; const char *dummy; + /* create the target namespace, if it does not exist */ TclGetNamespaceForQualName(interp, ObjStr(procNameObj), NULL, TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1Ptr, @@ -16667,9 +16694,9 @@ */ tcd->procName = procNameObj; tcd->paramDefs = paramDefs; - tcd->with_ad = with_ad; - tcd->checkAlwaysFlag = checkAlwaysFlag; + tcd->flags = (checkAlwaysFlag != 0 ? NSF_PROC_FLAG_CHECK_ALWAYS : 0u) | (with_ad != 0 ? NSF_PROC_FLAG_AD : 0u); tcd->cmd = NULL; + tcd->wrapperCmd = cmd; // TODO should we preserve? /*fprintf(stderr, "NsfProcAdd %s tcd %p paramdefs %p\n", ObjStr(procNameObj), tcd, tcd->paramDefs);*/ @@ -16683,6 +16710,7 @@ for (paramPtr = paramDefs->paramsPtr; paramPtr->name; paramPtr++) { if (*paramPtr->name == '-') { Tcl_Obj *varNameObj = Tcl_NewStringObj(paramPtr->name+1, -1); + /* * If we have the -ad (for ars digita) flag set, we provide the * OpenACS semantics. This is (a) to use the name "boolean" for @@ -16719,16 +16747,24 @@ if (likely(result == TCL_OK)) { /* - * The shadowed proc was created successfully. Retrieve the - * defined proc and set its namespace to the namespace of the stub - * cmd + * The shadowed proc was created successfully. Retrieve the defined proc + * and set its namespace to the namespace of the stub cmd. */ Tcl_Command procCmd = Tcl_GetCommandFromObj(interp, procNameObj); + assert(procCmd != NULL); ((Command *)procCmd)->nsPtr = (Namespace *)cmdNsPtr; tcd->cmd = procCmd; NsfCommandPreserve(tcd->cmd); + if (with_Debug) { + Tcl_Command_flags(cmd) |= NSF_CMD_DEBUG_METHOD; + } + if (with_Deprecated) { + Tcl_Command_flags(cmd) |= NSF_CMD_DEPRECATED_METHOD; + } + + } else { /* * We could not define the shadowed proc. In this case, cleanup by @@ -17501,7 +17537,7 @@ /* fprintf(stderr, "NEXT found absolute cmd %s => %p\n", *methodNamePtr, *cmdPtr); */ } else if (object->nsPtr != NULL) { *cmdPtr = FindMethod(object->nsPtr, *methodNamePtr); - if ((*cmdPtr != NULL) && (Tcl_Command_flags(*cmdPtr) & NSF_CMD_CALL_PRIVATE_METHOD)) { + if ((*cmdPtr != NULL) && (Tcl_Command_flags(*cmdPtr) & NSF_CMD_CALL_PRIVATE_METHOD) != 0) { /*fprintf(stderr, "NEXT found private cmd %s => %p\n", *methodNamePtr, *cmdPtr);*/ *cmdPtr = NULL; } @@ -22423,7 +22459,7 @@ Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("-frame", 6)); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("object", 6)); } - if (Tcl_Command_flags(cmd) & NSF_CMD_NONLEAF_METHOD) { + if ((Tcl_Command_flags(cmd) & NSF_CMD_NONLEAF_METHOD) != 0) { Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("-frame", 6)); Tcl_ListObjAppendElement(interp, listObj, Tcl_NewStringObj("method", 6)); } @@ -22756,7 +22792,7 @@ */ NsfProcClientData *tcd = Tcl_Command_objClientData(cmd); - if (tcd && tcd->procName) { + if (tcd != NULL && tcd->procName) { Tcl_Command procCmd = Tcl_GetCommandFromObj(interp, tcd->procName); Tcl_DString ds, *dsPtr = &ds; Tcl_Obj *resultObj; @@ -22777,7 +22813,7 @@ DStringAppendQualName(dsPtr, Tcl_Command_nsPtr(cmd), methodName); /* don't hardcode names */ Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewStringObj("::nsf::proc", -1)); - if (tcd->with_ad != 0) { + if ((tcd->flags & NSF_PROC_FLAG_AD) != 0) { Tcl_ListObjAppendElement(interp, resultObj, Tcl_NewStringObj("-ad", 3)); } Tcl_ListObjAppendElement(interp, resultObj, @@ -23183,7 +23219,7 @@ methodTypeMatch = MethodTypeMatches(interp, methodType, cmd, object, key, withPer_object, &isObject); - if (Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD && !NsfObjectIsClass(object)) { + if ((Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD) != 0 && !NsfObjectIsClass(object)) { return TCL_OK; } /* @@ -23303,7 +23339,7 @@ } - if (Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD && !NsfObjectIsClass(object)) { + if ((Tcl_Command_flags(cmd) & NSF_CMD_CLASS_ONLY_METHOD) != 0 && !NsfObjectIsClass(object)) { continue; } if (!ProtectionMatches(withCallprotection, cmd) @@ -25389,7 +25425,6 @@ INCR_REF_COUNT(valueObj); tcd->cmdName = valueObj; } - // should we return old or new value? /class/set/... return new value, /configure/ often the old. Tcl_SetObjResult(interp, tcd->cmdName); break; @@ -25418,7 +25453,7 @@ {-argName "object" -required 1 -type object} {-argName "-per-object"} {-argName "methodName" -required 1 -type tclobj} - {-argName "methodproperty" -required 1 -type "class-only|call-private|call-protected|redefine-protected|returns|slotobj"} + {-argName "methodproperty" -required 1 -type "class-only|call-private|call-protected|deprecated|redefine-protected|returns|slotobj"} {-argName "value" -type tclobj} } */ @@ -25449,9 +25484,11 @@ } switch (methodproperty) { - case MethodpropertyClass_onlyIdx: /* fall through */ - case MethodpropertyCall_privateIdx: /* fall through */ - case MethodpropertyCall_protectedIdx: /* fall through */ + case MethodpropertyClass_onlyIdx: /* fall through */ + case MethodpropertyCall_privateIdx: /* fall through */ + case MethodpropertyCall_protectedIdx: /* fall through */ + case MethodpropertyDebugIdx: /* fall through */ + case MethodpropertyDeprecatedIdx: /* fall through */ case MethodpropertyRedefine_protectedIdx: /* fall through */ { int impliedSetFlag = 0, impliedClearFlag = 0; @@ -25468,10 +25505,17 @@ impliedClearFlag = NSF_CMD_CALL_PRIVATE_METHOD; flag = NSF_CMD_CALL_PROTECTED_METHOD; break; + case MethodpropertyDebugIdx: + flag = NSF_CMD_DEBUG_METHOD; + break; + case MethodpropertyDeprecatedIdx: + flag = NSF_CMD_DEPRECATED_METHOD; + break; case MethodpropertyRedefine_protectedIdx: flag = NSF_CMD_REDEFINE_PROTECTED_METHOD; break; default: flag = 0; + break; } if (valueObj != NULL) { @@ -25482,6 +25526,7 @@ return result; } if (bool != 0) { + /* * set flag */ @@ -26512,15 +26557,18 @@ /* cmd proc NsfProcCmd { - {-argName "-ad" -required 0 -nrargs 0 -type switch} - {-argName "-checkalways" -required 0 -nrargs 0 -type switch} - {-argName "procName" -required 1 -type tclobj} - {-argName "arguments" -required 1 -type tclobj} - {-argName "body" -required 1 -type tclobj} + {-argName "-ad" -required 0 -nrargs 0 -type switch} + {-argName "-checkalways" -required 0 -nrargs 0 -type switch} + {-argName "-debug" -required 0 -nrargs 0 -type switch} + {-argName "-deprecated" -required 0 -nrargs 0 -type switch} + {-argName "procName" -required 1 -type tclobj} + {-argName "arguments" -required 1 -type tclobj} + {-argName "body" -required 1 -type tclobj} } */ static int -NsfProcCmd(Tcl_Interp *interp, int with_ad, int with_checkAlways, Tcl_Obj *nameObj, Tcl_Obj *arguments, Tcl_Obj *body) { +NsfProcCmd(Tcl_Interp *interp, int with_ad, int with_checkAlways, int with_Debug, int with_Deprecated, + Tcl_Obj *nameObj, Tcl_Obj *arguments, Tcl_Obj *body) { NsfParsedParam parsedParam; int result; @@ -26540,13 +26588,14 @@ return result; } - if (parsedParam.paramDefs != NULL) { + if (parsedParam.paramDefs != NULL || with_Debug != 0) { /* * We need parameter handling. In such cases, a thin C-based layer * is added which handles the parameter passing and calls the proc * later. */ - result = NsfProcAdd(interp, &parsedParam, ObjStr(nameObj), body, with_ad, with_checkAlways); + result = NsfProcAdd(interp, &parsedParam, ObjStr(nameObj), body, + with_ad, with_checkAlways, with_Debug, with_Deprecated); } else { /* @@ -29404,11 +29453,11 @@ objectInfoMethod baseclass NsfObjInfoBaseclassMethod { } */ - + static int NsfObjInfoBaseclassMethod(Tcl_Interp *interp, NsfObject *object) { NsfObjectSystem *osPtr; - + nonnull_assert(interp != NULL); nonnull_assert(object != NULL); Index: generic/nsf.h =================================================================== diff -u -N -r16a02881bff0a0d626d0045dfd96660338d0c314 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsf.h (.../nsf.h) (revision 16a02881bff0a0d626d0045dfd96660338d0c314) +++ generic/nsf.h (.../nsf.h) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -219,10 +219,11 @@ # define NSF_MEM_COUNT 1 #endif + // if ((cmd) != NULL) {fprintf(stderr, "METHOD %s cmd %p flags %.8x (%.8x)\n", (method), (cmd), Tcl_Command_flags((cmd)), NSF_CMD_DEPRECATED_METHOD);} #if defined(NSF_PROFILE) || defined(NSF_DTRACE) # define CscInit(cscPtr, object, cl, cmd, frametype, flags, method) \ CscInit_((cscPtr), (object), (cl), (cmd), (frametype), (flags)); (cscPtr)->methodName = (method); \ - NsfProfileTraceCall((interp), (object), (cl), (cscPtr)->methodName); + NsfProfileTraceCall((interp), (object), (cl), (method)); #else # define CscInit(cscPtr, object, cl, cmd, frametype, flags, methodName) \ CscInit_((cscPtr), (object), (cl), (cmd), (frametype), (flags)) Index: generic/nsf.tcl =================================================================== diff -u -N -r729b49eb1dcb08183a0ed41588416a923271811a -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsf.tcl (.../nsf.tcl) (revision 729b49eb1dcb08183a0ed41588416a923271811a) +++ generic/nsf.tcl (.../nsf.tcl) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -160,9 +160,9 @@ # deprecated command # proc ::nsf::deprecated {what oldCmd newCmd} { - set msg "**\n** The $what $oldCmd is deprecated." + set msg "*** $what $oldCmd is deprecated." if {$newCmd ne ""} {append msg " use $newCmd instead."} - append msg "\n**\n" + #append msg "\n**\n" nsf::log Warning $msg } Index: generic/nsfAPI.decls =================================================================== diff -u -N -r5a162b098b6a9550218646d470b274769bda8da1 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision 5a162b098b6a9550218646d470b274769bda8da1) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -214,7 +214,7 @@ {-argName "object" -required 1 -type object} {-argName "-per-object" -required 0 -nrargs 0 -type switch} {-argName "methodName" -required 1 -type tclobj} - {-argName "methodProperty" -required 1 -type "class-only|call-private|call-protected|redefine-protected|returns"} + {-argName "methodProperty" -required 1 -type "class-only|call-private|call-protected|debug|deprecated|redefine-protected|returns"} {-argName "value" -type tclobj} } {-nxdoc 1} @@ -273,11 +273,13 @@ } cmd proc NsfProcCmd { - {-argName "-ad" -required 0 -nrargs 0 -type switch} - {-argName "-checkalways" -required 0 -nrargs 0 -type switch} - {-argName "procName" -required 1 -type tclobj} - {-argName "arguments" -required 1 -type tclobj} - {-argName "body" -required 1 -type tclobj} + {-argName "-ad" -required 0 -nrargs 0 -type switch} + {-argName "-checkalways" -required 0 -nrargs 0 -type switch} + {-argName "-debug" -required 0 -nrargs 0 -type switch} + {-argName "-deprecated" -required 0 -nrargs 0 -type switch} + {-argName "procName" -required 1 -type tclobj} + {-argName "arguments" -required 1 -type tclobj} + {-argName "body" -required 1 -type tclobj} } {-nxdoc 1} cmd relation::get NsfRelationGetCmd { Index: generic/nsfAPI.h =================================================================== diff -u -N -r5a162b098b6a9550218646d470b274769bda8da1 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsfAPI.h (.../nsfAPI.h) (revision 5a162b098b6a9550218646d470b274769bda8da1) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -207,12 +207,12 @@ return result; } -enum MethodpropertyIdx {MethodpropertyNULL, MethodpropertyClass_onlyIdx, MethodpropertyCall_privateIdx, MethodpropertyCall_protectedIdx, MethodpropertyRedefine_protectedIdx, MethodpropertyReturnsIdx}; +enum MethodpropertyIdx {MethodpropertyNULL, MethodpropertyClass_onlyIdx, MethodpropertyCall_privateIdx, MethodpropertyCall_protectedIdx, MethodpropertyDebugIdx, MethodpropertyDeprecatedIdx, MethodpropertyRedefine_protectedIdx, MethodpropertyReturnsIdx}; static int ConvertToMethodproperty(Tcl_Interp *interp, Tcl_Obj *objPtr, Nsf_Param const *pPtr, ClientData *clientData, Tcl_Obj **outObjPtr) { int index, result; - static const char *opts[] = {"class-only", "call-private", "call-protected", "redefine-protected", "returns", NULL}; + static const char *opts[] = {"class-only", "call-private", "call-protected", "debug", "deprecated", "redefine-protected", "returns", NULL}; (void)pPtr; result = Tcl_GetIndexFromObj(interp, objPtr, opts, "methodProperty", 0, &index); *clientData = (ClientData) INT2PTR(index + 1); @@ -281,7 +281,7 @@ {ConvertToMethodtype, "all|scripted|builtin|alias|forwarder|object|setter|nsfproc"}, {ConvertToFrame, "method|object|default"}, {ConvertToCurrentoption, "proc|method|methodpath|object|class|activelevel|args|activemixin|calledproc|calledmethod|calledclass|callingproc|callingmethod|callingclass|callinglevel|callingobject|filterreg|isnextcall|nextmethod"}, - {ConvertToMethodproperty, "class-only|call-private|call-protected|redefine-protected|returns"}, + {ConvertToMethodproperty, "class-only|call-private|call-protected|debug|deprecated|redefine-protected|returns"}, {ConvertToRelationtype, "object-mixin|class-mixin|object-filter|class-filter|class|superclass|rootclass"}, {ConvertToSource, "all|application|system"}, {ConvertToForwardproperty, "prefix|target|verbose"}, @@ -642,8 +642,8 @@ NSF_nonnull(1) NSF_nonnull(3); static int NsfParameterSpecsCmd(Tcl_Interp *interp, int withConfigure, int withNonposargs, Tcl_Obj *slotobjs) NSF_nonnull(1) NSF_nonnull(4); -static int NsfProcCmd(Tcl_Interp *interp, int withAd, int withCheckalways, Tcl_Obj *procName, Tcl_Obj *arguments, Tcl_Obj *body) - NSF_nonnull(1) NSF_nonnull(4) NSF_nonnull(5) NSF_nonnull(6); +static int NsfProcCmd(Tcl_Interp *interp, int withAd, int withCheckalways, int withDebug, int withDeprecated, Tcl_Obj *procName, Tcl_Obj *arguments, Tcl_Obj *body) + NSF_nonnull(1) NSF_nonnull(6) NSF_nonnull(7) NSF_nonnull(8); static int NsfProfileClearDataStub(Tcl_Interp *interp) NSF_nonnull(1); static int NsfProfileGetDataStub(Tcl_Interp *interp) @@ -2249,12 +2249,14 @@ &pc) == TCL_OK)) { int withAd = (int )PTR2INT(pc.clientData[0]); int withCheckalways = (int )PTR2INT(pc.clientData[1]); - Tcl_Obj *procName = (Tcl_Obj *)pc.clientData[2]; - Tcl_Obj *arguments = (Tcl_Obj *)pc.clientData[3]; - Tcl_Obj *body = (Tcl_Obj *)pc.clientData[4]; + int withDebug = (int )PTR2INT(pc.clientData[2]); + int withDeprecated = (int )PTR2INT(pc.clientData[3]); + Tcl_Obj *procName = (Tcl_Obj *)pc.clientData[4]; + Tcl_Obj *arguments = (Tcl_Obj *)pc.clientData[5]; + Tcl_Obj *body = (Tcl_Obj *)pc.clientData[6]; assert(pc.status == 0); - return NsfProcCmd(interp, withAd, withCheckalways, procName, arguments, body); + return NsfProcCmd(interp, withAd, withCheckalways, withDebug, withDeprecated, procName, arguments, body); } else { @@ -3749,9 +3751,11 @@ {"-nonposargs", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"slotobjs", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, -{"::nsf::proc", NsfProcCmdStub, 5, { +{"::nsf::proc", NsfProcCmdStub, 7, { {"-ad", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"-checkalways", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, + {"-debug", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, + {"-deprecated", 0, 0, Nsf_ConvertTo_Boolean, NULL,NULL,"switch",NULL,NULL,NULL,NULL,NULL}, {"procName", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"arguments", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, {"body", NSF_ARG_REQUIRED, 1, Nsf_ConvertTo_Tclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} Index: generic/nsfInt.h =================================================================== diff -u -N -r16a02881bff0a0d626d0045dfd96660338d0c314 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsfInt.h (.../nsfInt.h) (revision 16a02881bff0a0d626d0045dfd96660338d0c314) +++ generic/nsfInt.h (.../nsfInt.h) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -77,9 +77,7 @@ # include #endif -#if defined(NSF_PROFILE) -# include -#endif +#include #if __GNUC_PREREQ(2, 95) /* Use gcc branch prediction hint to minimize cost of e.g. DTrace @@ -446,6 +444,8 @@ /* NSF_CMD_NONLEAF_METHOD is used to flag, if a Method implemented via cmd calls "next" */ #define NSF_CMD_NONLEAF_METHOD 0x00080000 #define NSF_CMD_CLASS_ONLY_METHOD 0x00100000 +#define NSF_CMD_DEPRECATED_METHOD 0x00200000 +#define NSF_CMD_DEBUG_METHOD 0x00400000 /* * object flags ... */ @@ -606,12 +606,15 @@ /* * needed in nsf.c and in nsfShadow */ +#define NSF_PROC_FLAG_AD 0x01u +#define NSF_PROC_FLAG_CHECK_ALWAYS 0x02u + typedef struct NsfProcClientData { Tcl_Obj *procName; Tcl_Command cmd; + Tcl_Command wrapperCmd; NsfParamDefs *paramDefs; - int with_ad; - int checkAlwaysFlag; + unsigned int flags; } NsfProcClientData; typedef enum SystemMethodsIdx { @@ -919,6 +922,7 @@ * memory is very little. */ int debugLevel; + int debugCallingDepth; int doCheckArguments; int doCheckResults; int doFilters; @@ -1005,6 +1009,18 @@ * Profiling functions */ +EXTERN void NsfDeprecatedCmd(Tcl_Interp *interp, const char *what, const char *oldCmd, const char *newCmd) + nonnull(1) nonnull(2) nonnull(3) nonnull(4); +EXTERN void NsfProfileDeprecatedCall(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, + const char *methodName, const char *altMethod) + nonnull(1) nonnull(2) nonnull(4) nonnull(5); +EXTERN void NsfProfileDebugCall(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, + int objc, Tcl_Obj **objv) + nonnull(1) nonnull(4); +EXTERN void NsfProfileDebugExit(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, + long startSec, long startUsec) + nonnull(1) nonnull(4); + #if defined(NSF_PROFILE) EXTERN void NsfProfileRecordMethodData(Tcl_Interp* interp, NsfCallStackContent *cscPtr) nonnull(1) nonnull(2); @@ -1016,8 +1032,6 @@ EXTERN void NsfProfileGetData(Tcl_Interp *interp) nonnull(1); EXTERN int NsfProfileTrace(Tcl_Interp *interp, int withEnable, int withVerbose, int withInmemory, Tcl_Obj *builtins); -EXTERN void NsfProfileObjectLabel(Tcl_DString *dsPtr, NsfObject *obj, NsfClass *cl, const char *methodName) - nonnull(1) nonnull(2) nonnull(4); EXTERN void NsfProfileTraceCall(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName) nonnull(1) nonnull(2) nonnull(4); EXTERN void NsfProfileTraceExit(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, struct timeval *trt) @@ -1031,6 +1045,7 @@ nonnull(1); #endif + /* * MEM Counting */ @@ -1105,10 +1120,11 @@ EXTERN Tcl_Obj *NsfMethodNamePath(Tcl_Interp *interp, Tcl_CallFrame *framePtr, - CONST char *methodName) + const char *methodName) nonnull(1) nonnull(3) returns_nonnull; + /* * Definition of methodEpoch macros */ Index: generic/nsfProfile.c =================================================================== diff -u -N -r16a02881bff0a0d626d0045dfd96660338d0c314 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsfProfile.c (.../nsfProfile.c) (revision 16a02881bff0a0d626d0045dfd96660338d0c314) +++ generic/nsfProfile.c (.../nsfProfile.c) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -38,15 +38,218 @@ #include "nsfInt.h" #if defined(NSF_PROFILE) - typedef struct NsfProfileData { long microSec; long count; } NsfProfileData; +#endif +/* + *---------------------------------------------------------------------- + * NsfProfileObjectLabel, NsfProfileMethodLabel -- + * + * Produce a string label for an object or method using in profiling. + * NsfProfileMethodLabel() is available also when compiled without + * NSF_PROFILE. + * + * Results: + * None + * + * Side effects: + * Initializes and fills the passed DString, + * + *---------------------------------------------------------------------- + */ +#if defined(NSF_PROFILE) +static void NsfProfileObjectLabel(Tcl_DString *dsPtr, NsfObject *object, NsfClass *cl, const char *methodName) + nonnull(1) nonnull(2) nonnull(4); +static void +NsfProfileObjectLabel(Tcl_DString *dsPtr, NsfObject *object, NsfClass *cl, const char *methodName) { + + nonnull_assert(dsPtr != NULL); + nonnull_assert(object != NULL); + nonnull_assert(methodName != NULL); + + Tcl_DStringAppend(dsPtr, ObjectName(object), -1); + Tcl_DStringAppend(dsPtr, " ", 1); + Tcl_DStringAppend(dsPtr, ClassName(object->cl), -1); +} +#endif + + +static void NsfProfileMethodLabel(Tcl_DString *dsPtr, NsfObject *object, NsfClass *cl, const char *methodName) + nonnull(1) nonnull(4); + +static void +NsfProfileMethodLabel(Tcl_DString *dsPtr, NsfObject *object, NsfClass *cl, const char *methodName) { + + nonnull_assert(dsPtr != NULL); + nonnull_assert(methodName != NULL); + + if (cl != NULL && object != NULL) { + Tcl_DStringAppend(dsPtr, ObjStr(cl->object.cmdName), -1); + Tcl_DStringAppend(dsPtr, " ", 1); + } + Tcl_DStringAppendElement(dsPtr, methodName); +} + /* *---------------------------------------------------------------------- + * ReportLine -- + * + * Report a profile line via NsfLog(). Since NsfLog() uses a Tcl function, + * ReportLine has to turn off profiling to avoid recursive profile + * invocation. It is as well necessary to save the interp result. + * + * Results: + * None + * + * Side effects: + * logging + * + *---------------------------------------------------------------------- + */ +static void ReportLine(Tcl_Interp *interp, int level, NsfRuntimeState *rst, const char *line) + nonnull(1) nonnull(3) nonnull(4); + +static void +ReportLine(Tcl_Interp *interp, int level, NsfRuntimeState *rst, const char *line) { + Tcl_Obj *savedResultObj; + int prevProfileSetting; + + nonnull_assert(interp != NULL); + nonnull_assert(rst != NULL); + nonnull_assert(line != NULL); + + prevProfileSetting = rst->doProfile; + rst->doProfile = 0; + + savedResultObj = Tcl_GetObjResult(interp); + INCR_REF_COUNT(savedResultObj); + + NsfLog(interp, level, "%s", line); + + Tcl_SetObjResult(interp, savedResultObj); + DECR_REF_COUNT(savedResultObj); + + rst->doProfile = prevProfileSetting; +} + +/* + *---------------------------------------------------------------------- + * NsfProfileDeprecatedCall -- + * + * Output a line in case a deprecated function/method is called using + * the low-level NsfDeprecatedCmd() function. + * + * Results: + * None + * + * Side effects: + * logging + * + *---------------------------------------------------------------------- + */ +void +NsfProfileDeprecatedCall(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, + const char *methodName, const char *altMethod) { + Tcl_DString ds; + + nonnull_assert(interp != NULL); + nonnull_assert(object != NULL); + nonnull_assert(methodName != NULL); + nonnull_assert(altMethod != NULL); + + Tcl_DStringInit(&ds); + Tcl_DStringAppend(&ds, "{", 1); + NsfProfileMethodLabel(&ds, object, cl, methodName); + Tcl_DStringAppend(&ds, "}", 1); + + NsfDeprecatedCmd(interp,"method", ds.string, altMethod); + Tcl_DStringFree(&ds); +} + +/* + *---------------------------------------------------------------------- + * NsfProfileDebugCall, NsfProfileDebugExit -- + * + * Output a line in case a function/method is called/exited having the + * debug flag set. These two functions use ReportLine (which calls NsfLog) + * for reporting. + * + * Results: + * None + * + * Side effects: + * logging + * + *---------------------------------------------------------------------- + */ +void +NsfProfileDebugCall(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, + int objc, Tcl_Obj **objv) { + NsfRuntimeState *rst; + Tcl_Obj *listObj; + Tcl_DString ds; + + nonnull_assert(interp != NULL); + nonnull_assert(methodName != NULL); + + rst = RUNTIME_STATE(interp); + rst->debugCallingDepth++; + + Tcl_DStringInit(&ds); + Nsf_DStringPrintf(&ds, "call(%d) - {", rst->debugCallingDepth); + NsfProfileMethodLabel(&ds, object, cl, methodName); + Tcl_DStringAppend(&ds, "}", 1); + + listObj = Tcl_NewListObj(objc, objv); + INCR_REF_COUNT(listObj); + Nsf_DStringPrintf(&ds, " %s", ObjStr(listObj)); + DECR_REF_COUNT(listObj); + + ReportLine(interp, NSF_LOG_DEBUG, rst, ds.string); + + Tcl_DStringFree(&ds); + +} + +void +NsfProfileDebugExit(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, + long startSec, long startUsec) { + Tcl_DString ds, *dsPtr = &ds; + NsfRuntimeState *rst; + + nonnull_assert(interp != NULL); + nonnull_assert(methodName != NULL); + + rst = RUNTIME_STATE(interp); + Tcl_DStringInit(dsPtr); + Nsf_DStringPrintf(dsPtr, "exit(%d) - {", rst->debugCallingDepth); + + if (startSec != 0 || startUsec != 0) { + struct timeval trt; + + gettimeofday(&trt, NULL); + NsfProfileMethodLabel(dsPtr, object, cl, methodName); + Nsf_DStringPrintf(dsPtr, "} %ld usec", (trt.tv_sec - startSec) * 1000000 + (trt.tv_usec - startUsec)); + } else { + NsfProfileMethodLabel(dsPtr, object, cl, methodName); + Tcl_DStringAppend(dsPtr, "}", 1); + } + + ReportLine(interp, NSF_LOG_DEBUG, rst, ds.string); + Tcl_DStringFree(dsPtr); + + rst->debugCallingDepth--; +} + + +#if defined(NSF_PROFILE) + +/* + *---------------------------------------------------------------------- * NsfProfileFillTable -- * * Insert or Update a keyed entry with provided microseconds and @@ -300,42 +503,7 @@ } -/* - *---------------------------------------------------------------------- - * ReportLine -- - * - * Report a profile line via NsfLog(). Since NsfLog() uses a Tcl function, - * ReportLine has to turn off profiling to avoid recursive profile - * invocation. It is as well necessary to save the interp result. - * - * Results: - * None - * - * Side effects: - * logging - * - *---------------------------------------------------------------------- - */ -static void ReportLine(Tcl_Interp *interp, NsfRuntimeState *rst, const char *line) - nonnull(1) nonnull(2) nonnull(3); -static void -ReportLine(Tcl_Interp *interp, NsfRuntimeState *rst, const char *line) { - Tcl_Obj *savedResultObj; - - rst->doProfile = 0; - - savedResultObj = Tcl_GetObjResult(interp); - INCR_REF_COUNT(savedResultObj); - - NsfLog(interp, NSF_LOG_NOTICE, "%s", line); - - Tcl_SetObjResult(interp, savedResultObj); - DECR_REF_COUNT(savedResultObj); - - rst->doProfile = 1; -} - /* *---------------------------------------------------------------------- * NsfProfileTraceCallAppend, NsfProfileTraceExitAppend -- @@ -362,7 +530,7 @@ Tcl_DStringInit(&ds); Nsf_DStringPrintf(&ds, "call(%d): %s", profilePtr->depth, label); if (profilePtr->verbose) { - ReportLine(interp, rst, ds.string); + ReportLine(interp, NSF_LOG_NOTICE, rst, ds.string); } if (profilePtr->inmemory) { Tcl_DStringAppend(&ds, "\n", 1); @@ -380,7 +548,7 @@ Tcl_DStringInit(&ds); Nsf_DStringPrintf(&ds, "exit(%d): %s %.0f", profilePtr->depth, label, duration); if (profilePtr->verbose) { - ReportLine(interp, rst, ds.string); + ReportLine(interp, NSF_LOG_NOTICE, rst, ds.string); } if (profilePtr->inmemory) { Tcl_DStringAppend(&ds, "\n", 1); @@ -394,49 +562,6 @@ /* *---------------------------------------------------------------------- - * NsfProfileObjectLabel, NsfProfileMethodLabel -- - * - * Produce a string label for an object or method using in profiling. - * - * Results: - * None - * - * Side effects: - * Initializes and fills the passed DString, - * - *---------------------------------------------------------------------- - */ -static void NsfProfileMethodLabel(Tcl_DString *dsPtr, NsfObject *obj, NsfClass *cl, const char *methodName) - nonnull(1) nonnull(2) nonnull(4); - -void -NsfProfileObjectLabel(Tcl_DString *dsPtr, NsfObject *obj, NsfClass *cl, const char *methodName) { - - nonnull_assert(dsPtr != NULL); - nonnull_assert(obj != NULL); - nonnull_assert(methodName != NULL); - - Tcl_DStringAppend(dsPtr, ObjectName(obj), -1); - Tcl_DStringAppend(dsPtr, " ", 1); - Tcl_DStringAppend(dsPtr, ClassName(obj->cl), -1); -} - -static void -NsfProfileMethodLabel(Tcl_DString *dsPtr, NsfObject *obj, NsfClass *cl, const char *methodName) { - - nonnull_assert(dsPtr != NULL); - nonnull_assert(obj != NULL); - nonnull_assert(methodName != NULL); - - if (cl != NULL) { - Tcl_DStringAppend(dsPtr, ObjStr(cl->object.cmdName), -1); - Tcl_DStringAppend(dsPtr, " ", 1); - } - Tcl_DStringAppendElement(dsPtr, methodName); -} - -/* - *---------------------------------------------------------------------- * NsfProfileTraceCall, NsfProfileTraceExit -- * * Add entries to the trace dstring when methods/procs are called or @@ -477,6 +602,7 @@ } } + void NsfProfileTraceExit(Tcl_Interp *interp, NsfObject *object, NsfClass *cl, const char *methodName, struct timeval *callTime) { Index: generic/nsfStack.c =================================================================== diff -u -N -r16a02881bff0a0d626d0045dfd96660338d0c314 -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/nsfStack.c (.../nsfStack.c) (revision 16a02881bff0a0d626d0045dfd96660338d0c314) +++ generic/nsfStack.c (.../nsfStack.c) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -1229,6 +1229,15 @@ if (likely(cscPtr->cmdPtr != NULL)) { int allowDestroy = RUNTIME_STATE(interp)->exitHandlerDestroyRound == NSF_EXITHANDLER_OFF; + + if ((Tcl_Command_flags(cscPtr->cmdPtr) & NSF_CMD_DEBUG_METHOD) != 0) { +#if defined(NSF_PROFILE) || defined(NSF_DTRACE) + NsfProfileDebugExit(interp, cscPtr->self, cscPtr->cl, cscPtr->methodName, cscPtr->startSec, cscPtr->startUsec); +#else + NsfProfileDebugExit(interp, cscPtr->self, cscPtr->cl, Tcl_GetCommandName(interp, cscPtr->cmdPtr), 0, 0); +#endif + } + /* * Track object activations */ Index: generic/predefined.h =================================================================== diff -u -N -r729b49eb1dcb08183a0ed41588416a923271811a -r8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea --- generic/predefined.h (.../predefined.h) (revision 729b49eb1dcb08183a0ed41588416a923271811a) +++ generic/predefined.h (.../predefined.h) (revision 8854eeff1e1b2d5fde52ee4f71b1e2b7844b2dea) @@ -62,9 +62,8 @@ "proc ::nsf::log {level msg} {\n" "puts stderr \"$level: $msg\"}}\n" "proc ::nsf::deprecated {what oldCmd newCmd} {\n" -"set msg \"**\\n** The $what $oldCmd is deprecated.\"\n" +"set msg \"*** $what $oldCmd is deprecated.\"\n" "if {$newCmd ne \"\"} {append msg \" use $newCmd instead.\"}\n" -"append msg \"\\n**\\n\"\n" "nsf::log Warning $msg}\n" "proc tmpdir {} {\n" "foreach e [list TMPDIR TEMP TMP] {\n"