Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch bug-3422267ed6b7992 Excluding Merge-Ins
This is equivalent to a diff from fc0e2a4f3f to 526420ad4a
|
2020-09-07
| ||
| 11:58 | Merge-mark check-in: dfba372d88 user: jan.nijtmans tags: core-8-branch | |
|
2020-09-06
| ||
| 15:09 | Merge 8.7 Leaf check-in: e82a85a057 user: jan.nijtmans tags: http-bug-cb0373bb33-again | |
| 14:41 | Merge 8.7 Closed-Leaf check-in: 526420ad4a user: jan.nijtmans tags: bug-3422267ed6b7992 | |
| 14:36 | Re-apply fix for [c1a376375e0e6488], as the build-problems originated elsewhere check-in: fc0e2a4f3f user: jan.nijtmans tags: core-8-branch | |
|
2020-09-05
| ||
| 21:54 | Merge core-8-branch check-in: 0d5bf116cf user: jan.nijtmans tags: bug-3422267ed6b7992 | |
| 21:37 | New bug-c1a376375e0e6488 branch with (up to now) failing solutions. Please make sure Travis builds O... Closed-Leaf check-in: 30f7888909 user: jan.nijtmans tags: bug-c1a376375e0e6488 | |
| 21:33 | Backout [c1a376375e0e6488]: imported namespace ensemble command name distorted during deletion trace... check-in: e4a2a2c7d1 user: jan.nijtmans tags: core-8-branch | |
Changes to .travis.yml.
| ︙ | ︙ | |||
456 457 458 459 460 461 462 |
- ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
before_script:
- export ERROR_ON_FAILURES=1
script:
- make all tcltest
- make test
- make install
| > | 456 457 458 459 460 461 462 463 |
- ./configure ${CFGOPT} "--prefix=$HOME/install dir" || (cat config.log && exit 1)
before_script:
- export ERROR_ON_FAILURES=1
script:
- make all tcltest
- make test
- make install
|
Changes to generic/tclBasic.c.
| ︙ | ︙ | |||
961 962 963 964 965 966 967 968 969 |
Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
}
hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
cmdInfoPtr->name, &isNew);
if (isNew) {
cmdPtr = (Command *)ckalloc(sizeof(Command));
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = iPtr->globalNsPtr;
| > > < | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 |
Tcl_Panic("builtin command with NULL object command proc and a NULL compile proc");
}
hPtr = Tcl_CreateHashEntry(&iPtr->globalNsPtr->cmdTable,
cmdInfoPtr->name, &isNew);
if (isNew) {
cmdPtr = (Command *)ckalloc(sizeof(Command));
cmdPtr->refCount = 1;
cmdPtr->hPtr = hPtr;
cmdPtr->refCount++;
cmdPtr->nsPtr = iPtr->globalNsPtr;
cmdPtr->cmdEpoch = 0;
cmdPtr->compileProc = cmdInfoPtr->compileProc;
cmdPtr->proc = TclInvokeObjectCommand;
cmdPtr->clientData = cmdPtr;
cmdPtr->objProc = cmdInfoPtr->objProc;
cmdPtr->objClientData = NULL;
cmdPtr->deleteProc = NULL;
|
| ︙ | ︙ | |||
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 |
* need the info will be soon enough.
*/
TclInvalidateNsCmdLookup(nsPtr);
TclInvalidateNsPath(nsPtr);
}
cmdPtr = (Command *)ckalloc(sizeof(Command));
Tcl_SetHashValue(hPtr, cmdPtr);
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = nsPtr;
| > > < | 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 |
* need the info will be soon enough.
*/
TclInvalidateNsCmdLookup(nsPtr);
TclInvalidateNsPath(nsPtr);
}
cmdPtr = (Command *)ckalloc(sizeof(Command));
cmdPtr->refCount = 1;
Tcl_SetHashValue(hPtr, cmdPtr);
cmdPtr->hPtr = hPtr;
cmdPtr->refCount++;
cmdPtr->nsPtr = nsPtr;
cmdPtr->cmdEpoch = 0;
cmdPtr->compileProc = NULL;
cmdPtr->objProc = TclInvokeStringCommand;
cmdPtr->objClientData = cmdPtr;
cmdPtr->proc = proc;
cmdPtr->clientData = clientData;
cmdPtr->deleteProc = deleteProc;
|
| ︙ | ︙ | |||
2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 |
* need the info will be soon enough.
*/
TclInvalidateNsCmdLookup(nsPtr);
TclInvalidateNsPath(nsPtr);
}
cmdPtr = (Command *)ckalloc(sizeof(Command));
Tcl_SetHashValue(hPtr, cmdPtr);
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = nsPtr;
| > > > > < | 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 |
* need the info will be soon enough.
*/
TclInvalidateNsCmdLookup(nsPtr);
TclInvalidateNsPath(nsPtr);
}
cmdPtr = (Command *)ckalloc(sizeof(Command));
cmdPtr->refCount = 1;
Tcl_SetHashValue(hPtr, cmdPtr);
cmdPtr->refCount++;
cmdPtr->hPtr = hPtr;
cmdPtr->nsPtr = nsPtr;
cmdPtr->cmdEpoch = 0;
cmdPtr->compileProc = NULL;
cmdPtr->objProc = proc;
cmdPtr->objClientData = clientData;
cmdPtr->proc = TclInvokeObjectCommand;
cmdPtr->clientData = cmdPtr;
cmdPtr->deleteProc = deleteProc;
|
| ︙ | ︙ | |||
3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 |
* structure. Take care to only remove the hash entry if it has not
* already been removed; otherwise if we manage to hit this function
* three times, everything goes up in smoke. [Bug 1220058]
*/
if (cmdPtr->hPtr != NULL) {
Tcl_DeleteHashEntry(cmdPtr->hPtr);
cmdPtr->hPtr = NULL;
}
/*
* Bump the command epoch counter. This will invalidate all cached
* references that point to this command.
*/
| > | 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 |
* structure. Take care to only remove the hash entry if it has not
* already been removed; otherwise if we manage to hit this function
* three times, everything goes up in smoke. [Bug 1220058]
*/
if (cmdPtr->hPtr != NULL) {
Tcl_DeleteHashEntry(cmdPtr->hPtr);
TclCleanupCommandMacro(cmdPtr);
cmdPtr->hPtr = NULL;
}
/*
* Bump the command epoch counter. This will invalidate all cached
* references that point to this command.
*/
|
| ︙ | ︙ | |||
3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 |
* that the deletion callback renamed the command. Instead, use
* cmdPtr->hptr, and make sure that no-one else has already deleted the
* hash entry.
*/
if (cmdPtr->hPtr != NULL) {
Tcl_DeleteHashEntry(cmdPtr->hPtr);
cmdPtr->hPtr = NULL;
/*
* Bump the command epoch counter. This will invalidate all cached
* references that point to this command.
*/
| > | 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 |
* that the deletion callback renamed the command. Instead, use
* cmdPtr->hptr, and make sure that no-one else has already deleted the
* hash entry.
*/
if (cmdPtr->hPtr != NULL) {
Tcl_DeleteHashEntry(cmdPtr->hPtr);
TclCleanupCommandMacro(cmdPtr);
cmdPtr->hPtr = NULL;
/*
* Bump the command epoch counter. This will invalidate all cached
* references that point to this command.
*/
|
| ︙ | ︙ |
Changes to generic/tclInt.h.
| ︙ | ︙ | |||
4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 |
} \
(location) = (cmdPtr); \
} while (0)
#define TclRoutineHasName(cmdPtr) \
((cmdPtr)->hPtr != NULL)
/*
*----------------------------------------------------------------
* Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number
* of calls out of the critical path. Note that this code isn't particularly
* readable; the non-inline version (in tclInterp.c) is much easier to
* understand. Note also that these macros takes different args (iPtr->limit)
| > > > > > > > > > > > | 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 |
} \
(location) = (cmdPtr); \
} while (0)
#define TclRoutineHasName(cmdPtr) \
((cmdPtr)->hPtr != NULL)
#define TclProcDecrRefCount(procPtr) \
if ((procPtr)->refCount-- <= 1) { \
TclProcCleanupProc(procPtr); \
}
#define TclProcIncrRefCount(procPtr) \
(procPtr)->refCount++;
/*
*----------------------------------------------------------------
* Inline versions of Tcl_LimitReady() and Tcl_LimitExceeded to limit number
* of calls out of the critical path. Note that this code isn't particularly
* readable; the non-inline version (in tclInterp.c) is much easier to
* understand. Note also that these macros takes different args (iPtr->limit)
|
| ︙ | ︙ |
Changes to generic/tclNamesp.c.
| ︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 | * special-purpose commands and variables for packages. * * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2002-2005 Donal K. Fellows. * Copyright (c) 2006 Neil Madden. * Contributions from Don Porter, NIST, 2007. (not subject to US copyright) * * Originally implemented by * Michael J. McLennan * Bell Labs Innovations for Lucent Technologies * mmclennan@lucent.com * | > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * special-purpose commands and variables for packages. * * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2002-2005 Donal K. Fellows. * Copyright (c) 2006 Neil Madden. * Copyright (c) 2018-2020 Nathan Coulter * Contributions from Don Porter, NIST, 2007. (not subject to US copyright) * * Originally implemented by * Michael J. McLennan * Bell Labs Innovations for Lucent Technologies * mmclennan@lucent.com * |
| ︙ | ︙ | |||
955 956 957 958 959 960 961 |
entryPtr = Tcl_NextHashEntry(&search);
}
}
/*
* If the namespace has associated ensemble commands, delete them first.
* This leaves the actual contents of the namespace alone (unless they are
| | | 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 |
entryPtr = Tcl_NextHashEntry(&search);
}
}
/*
* If the namespace has associated ensemble commands, delete them first.
* This leaves the actual contents of the namespace alone (unless they are
* linked ensemble commands, of course). This code is
* reentrant so command delete traces won't purturb things badly.
*/
while (nsPtr->ensembles != NULL) {
EnsembleConfig *ensemblePtr = (EnsembleConfig *) nsPtr->ensembles;
/*
|
| ︙ | ︙ | |||
1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 |
importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),
TclInvokeImportedCmd, InvokeImportedNRCmd, dataPtr,
DeleteImportedCmd);
dataPtr->realCmdPtr = cmdPtr;
/* corresponding decrement is in DeleteImportedCmd */
cmdPtr->refCount++;
dataPtr->selfPtr = (Command *) importedCmd;
dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
Tcl_DStringFree(&ds);
/*
* Create an ImportRef structure describing this new import command
* and add it to the import ref list in the "real" command.
*/
refPtr = (ImportRef *)ckalloc(sizeof(ImportRef));
refPtr->importedCmdPtr = (Command *) importedCmd;
refPtr->nextPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = refPtr;
} else {
Command *overwrite = (Command *)Tcl_GetHashValue(found);
if (overwrite->deleteProc == DeleteImportedCmd) {
ImportedCmdData *dataPtr = (ImportedCmdData *)overwrite->objClientData;
| > > | 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 |
importedCmd = Tcl_NRCreateCommand(interp, Tcl_DStringValue(&ds),
TclInvokeImportedCmd, InvokeImportedNRCmd, dataPtr,
DeleteImportedCmd);
dataPtr->realCmdPtr = cmdPtr;
/* corresponding decrement is in DeleteImportedCmd */
cmdPtr->refCount++;
dataPtr->selfPtr = (Command *) importedCmd;
dataPtr->selfPtr->refCount++;
dataPtr->selfPtr->compileProc = cmdPtr->compileProc;
Tcl_DStringFree(&ds);
/*
* Create an ImportRef structure describing this new import command
* and add it to the import ref list in the "real" command.
*/
refPtr = (ImportRef *)ckalloc(sizeof(ImportRef));
refPtr->importedCmdPtr = (Command *) importedCmd;
refPtr->importedCmdPtr->refCount++;
refPtr->nextPtr = cmdPtr->importRefPtr;
cmdPtr->importRefPtr = refPtr;
} else {
Command *overwrite = (Command *)Tcl_GetHashValue(found);
if (overwrite->deleteProc == DeleteImportedCmd) {
ImportedCmdData *dataPtr = (ImportedCmdData *)overwrite->objClientData;
|
| ︙ | ︙ | |||
1946 1947 1948 1949 1950 1951 1952 | } /* *---------------------------------------------------------------------- * * TclGetOriginalCommand -- * | | | | < < < < < < | < | 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 |
}
/*
*----------------------------------------------------------------------
*
* TclGetOriginalCommand --
*
* Returns the routine that an imported routine references, traversing any
* intermediate imported routines to find the origin routine. Returns NULL
* if the given routine is not imported.
*
* Results:
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
Tcl_Command
TclGetOriginalCommand(
Tcl_Command command) /* A routine to find the original routine for */
{
Command *cmdPtr = (Command *) command;
ImportedCmdData *dataPtr;
if (cmdPtr->deleteProc != DeleteImportedCmd) {
return NULL;
}
|
| ︙ | ︙ | |||
2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 |
*/
if (prevPtr == NULL) { /* refPtr is first in list. */
realCmdPtr->importRefPtr = refPtr->nextPtr;
} else {
prevPtr->nextPtr = refPtr->nextPtr;
}
ckfree(refPtr);
TclCleanupCommandMacro(realCmdPtr);
ckfree(dataPtr);
return;
}
prevPtr = refPtr;
}
| > | 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 |
*/
if (prevPtr == NULL) { /* refPtr is first in list. */
realCmdPtr->importRefPtr = refPtr->nextPtr;
} else {
prevPtr->nextPtr = refPtr->nextPtr;
}
TclCleanupCommandMacro(refPtr->importedCmdPtr);
ckfree(refPtr);
TclCleanupCommandMacro(realCmdPtr);
ckfree(dataPtr);
return;
}
prevPtr = refPtr;
}
|
| ︙ | ︙ |
Changes to generic/tclOO.c.
| ︙ | ︙ | |||
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 |
nsPtr = (Namespace *)oPtr->namespacePtr;
if (nsPtr->parentPtr != NULL) {
nsPtr = nsPtr->parentPtr;
}
}
oPtr->command = TclCreateObjCommandInNs(interp, nameStr,
(Tcl_Namespace *)nsPtr, TclOOPublicObjectCmd, oPtr, NULL);
/*
* Add the NRE command and trace directly. While this breaks a number of
* abstractions, it is faster and we're inside Tcl here so we're allowed.
*/
cmdPtr = (Command *) oPtr->command;
cmdPtr->nreProc = PublicNRObjectCmd;
cmdPtr->tracePtr = tracePtr = (CommandTrace *)ckalloc(sizeof(CommandTrace));
tracePtr->traceProc = ObjectRenamedTrace;
tracePtr->clientData = oPtr;
tracePtr->flags = TCL_TRACE_RENAME|TCL_TRACE_DELETE;
tracePtr->nextPtr = NULL;
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* SquelchCachedName --
| > > > | 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 |
nsPtr = (Namespace *)oPtr->namespacePtr;
if (nsPtr->parentPtr != NULL) {
nsPtr = nsPtr->parentPtr;
}
}
oPtr->command = TclCreateObjCommandInNs(interp, nameStr,
(Tcl_Namespace *)nsPtr, TclOOPublicObjectCmd, oPtr, NULL);
((Command *)oPtr->command)->refCount++;
/*
* Add the NRE command and trace directly. While this breaks a number of
* abstractions, it is faster and we're inside Tcl here so we're allowed.
*/
cmdPtr = (Command *) oPtr->command;
cmdPtr->nreProc = PublicNRObjectCmd;
cmdPtr->tracePtr = tracePtr = (CommandTrace *)ckalloc(sizeof(CommandTrace));
tracePtr->traceProc = ObjectRenamedTrace;
tracePtr->clientData = oPtr;
tracePtr->flags = TCL_TRACE_RENAME|TCL_TRACE_DELETE;
tracePtr->nextPtr = NULL;
tracePtr->refCount = 1;
oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
((Command *)oPtr->myCommand)->refCount++;
oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
MyClassDeleted);
((Command *)oPtr->myclassCommand)->refCount++;
return oPtr;
}
/*
* ----------------------------------------------------------------------
*
* SquelchCachedName --
|
| ︙ | ︙ | |||
782 783 784 785 786 787 788 |
static void
MyDeleted(
ClientData clientData) /* Reference to the object whose [my] has been
* squelched. */
{
Object *oPtr = (Object *)clientData;
| | > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 |
static void
MyDeleted(
ClientData clientData) /* Reference to the object whose [my] has been
* squelched. */
{
Object *oPtr = (Object *)clientData;
TclCleanupCommandMacro((Command *)oPtr->myCommand);
oPtr->myCommand = NULL;
}
static void
MyClassDeleted(
ClientData clientData)
{
Object *oPtr = (Object *)clientData;
TclCleanupCommandMacro((Command *)oPtr->myclassCommand);
oPtr->myclassCommand = NULL;
}
/*
* ----------------------------------------------------------------------
*
* ObjectRenamedTrace --
|
| ︙ | ︙ | |||
835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
* The namespace is only deleted if it hasn't already been deleted. [Bug
* 2950259].
*/
if (!Destructing(oPtr)) {
Tcl_DeleteNamespace(oPtr->namespacePtr);
}
oPtr->command = NULL;
TclOODecrRefCount(oPtr);
return;
}
/*
* ----------------------------------------------------------------------
| > | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 |
* The namespace is only deleted if it hasn't already been deleted. [Bug
* 2950259].
*/
if (!Destructing(oPtr)) {
Tcl_DeleteNamespace(oPtr->namespacePtr);
}
TclCleanupCommandMacro((Command *)oPtr->command);
oPtr->command = NULL;
TclOODecrRefCount(oPtr);
return;
}
/*
* ----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclProc.c.
| ︙ | ︙ | |||
66 67 68 69 70 71 72 |
NULL /* SetFromAny function; Tcl_ConvertToType
* should panic instead. */
};
#define ProcSetIntRep(objPtr, procPtr) \
do { \
Tcl_ObjIntRep ir; \
| | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
NULL /* SetFromAny function; Tcl_ConvertToType
* should panic instead. */
};
#define ProcSetIntRep(objPtr, procPtr) \
do { \
Tcl_ObjIntRep ir; \
TclProcIncrRefCount((procPtr)); \
ir.twoPtrValue.ptr1 = (procPtr); \
ir.twoPtrValue.ptr2 = NULL; \
Tcl_StoreIntRep((objPtr), &tclProcBodyType, &ir); \
} while (0)
#define ProcGetIntRep(objPtr, procPtr) \
do { \
|
| ︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
static const Tcl_ObjType lambdaType = {
"lambdaExpr", /* name */
FreeLambdaInternalRep, /* freeIntRepProc */
DupLambdaInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
SetLambdaFromAny /* setFromAnyProc */
};
#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr) \
do { \
Tcl_ObjIntRep ir; \
ir.twoPtrValue.ptr1 = (procPtr); \
ir.twoPtrValue.ptr2 = (nsObjPtr); \
Tcl_IncrRefCount((nsObjPtr)); \
Tcl_StoreIntRep((objPtr), &lambdaType, &ir); \
} while (0)
#define LambdaGetIntRep(objPtr, procPtr, nsObjPtr) \
do { \
const Tcl_ObjIntRep *irPtr; \
irPtr = TclFetchIntRep((objPtr), &lambdaType); \
(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL; \
(nsObjPtr) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL; \
| > > | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
static const Tcl_ObjType lambdaType = {
"lambdaExpr", /* name */
FreeLambdaInternalRep, /* freeIntRepProc */
DupLambdaInternalRep, /* dupIntRepProc */
NULL, /* updateStringProc */
SetLambdaFromAny /* setFromAnyProc */
};
#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr) \
do { \
Tcl_ObjIntRep ir; \
ir.twoPtrValue.ptr1 = (procPtr); \
ir.twoPtrValue.ptr2 = (nsObjPtr); \
Tcl_IncrRefCount((nsObjPtr)); \
Tcl_StoreIntRep((objPtr), &lambdaType, &ir); \
} while (0)
#define LambdaGetIntRep(objPtr, procPtr, nsObjPtr) \
do { \
const Tcl_ObjIntRep *irPtr; \
irPtr = TclFetchIntRep((objPtr), &lambdaType); \
(procPtr) = irPtr ? (Proc *)irPtr->twoPtrValue.ptr1 : NULL; \
(nsObjPtr) = irPtr ? (Tcl_Obj *)irPtr->twoPtrValue.ptr2 : NULL; \
|
| ︙ | ︙ | |||
187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
if (simpleName == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": bad procedure name",
procName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
return TCL_ERROR;
}
/*
* Create the data structure to represent the procedure.
*/
if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, simpleName, objv[2],
objv[3], &procPtr) != TCL_OK) {
| > > > > | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
if (simpleName == NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't create procedure \"%s\": bad procedure name",
procName));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "COMMAND", NULL);
return TCL_ERROR;
}
/*
* Create the data structure to represent the procedure.
*/
if (TclCreateProc(interp, /*ignored nsPtr*/ NULL, simpleName, objv[2],
objv[3], &procPtr) != TCL_OK) {
|
| ︙ | ︙ | |||
210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
/*
* Now initialize the new procedure's cmdPtr field. This will be used
* later when the procedure is called to determine what namespace the
* procedure will run in. This will be different than the current
* namespace if the proc was renamed into a different namespace.
*/
procPtr->cmdPtr = (Command *) cmd;
/*
* TIP #280: Remember the line the procedure body is starting on. In a
* bytecode context we ask the engine to provide us with the necessary
* information. This is for the initialization of the byte code compiler
* when the body is used for the first time.
| > > > > | 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
/*
* Now initialize the new procedure's cmdPtr field. This will be used
* later when the procedure is called to determine what namespace the
* procedure will run in. This will be different than the current
* namespace if the proc was renamed into a different namespace.
*/
((Command *)cmd)->refCount++;
if (procPtr->cmdPtr != NULL) {
TclCleanupCommandMacro(procPtr->cmdPtr);
}
procPtr->cmdPtr = (Command *) cmd;
/*
* TIP #280: Remember the line the procedure body is starting on. In a
* bytecode context we ask the engine to provide us with the necessary
* information. This is for the initialization of the byte code compiler
* when the body is used for the first time.
|
| ︙ | ︙ | |||
308 309 310 311 312 313 314 |
Tcl_DecrRefCount(contextPtr->data.eval.path);
contextPtr->data.eval.path = NULL;
}
TclStackFree(interp, contextPtr);
}
/*
| | | | 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
Tcl_DecrRefCount(contextPtr->data.eval.path);
contextPtr->data.eval.path = NULL;
}
TclStackFree(interp, contextPtr);
}
/*
* Optimize for no-op procs: If the body is not precompiled, e.g like a TclPro
* procbody, the argument list is just "args", and the body is empty,
* define a compileProc to compile a no-op.
*
* Notes:
* - cannot be done for any argument list without having different
* compiled/not-compiled behaviour in the "wrong argument #" case, or
* making this code much more complicated. In any case, it doesn't
* seem to make a lot of sense to verify the number of arguments we
|
| ︙ | ︙ | |||
409 410 411 412 413 414 415 |
Tcl_Obj **argArray;
int precompiled = 0;
ProcGetIntRep(bodyPtr, procPtr);
if (procPtr != NULL) {
/*
* Because the body is a TclProProcBody, the actual body is already
| | > > > > > > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 |
Tcl_Obj **argArray;
int precompiled = 0;
ProcGetIntRep(bodyPtr, procPtr);
if (procPtr != NULL) {
/*
* Because the body is a TclProProcBody, the actual body is already
* compiled not shared with anyone else, it's OK not to
* unshare it (as a matter of fact, it is bad to unshare it, because
* there may be no source code).
*
* We don't create and initialize a Proc structure for the procedure;
* rather, we use what is in the body object. We increment the ref
* count of the Proc struct since the command (soon to be created)
* will be holding a reference to it.
*/
procPtr->iPtr = iPtr;
/*
* procPtr->cmdPtr is not incremented here because the caller provides
* their own cmdPtr.
*/
procPtr->refCount++;
precompiled = 1;
} else {
/*
* If the procedure's body object is shared because its string value
* is identical to, e.g., the body of another procedure, we must
* create a private copy for this procedure to use. Such sharing of
* procedure bodies is rare but can cause problems. A procedure body
|
| ︙ | ︙ | |||
466 467 468 469 470 471 472 473 474 475 476 477 478 479 |
*/
Tcl_IncrRefCount(bodyPtr);
procPtr = (Proc *)ckalloc(sizeof(Proc));
procPtr->iPtr = iPtr;
procPtr->refCount = 1;
procPtr->bodyPtr = bodyPtr;
procPtr->numArgs = 0; /* Actual argument count is set below. */
procPtr->numCompiledLocals = 0;
procPtr->firstLocalPtr = NULL;
procPtr->lastLocalPtr = NULL;
}
| > > > > > | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 |
*/
Tcl_IncrRefCount(bodyPtr);
procPtr = (Proc *)ckalloc(sizeof(Proc));
procPtr->iPtr = iPtr;
procPtr->refCount = 1;
/* if cmdPtr isn't initialized to NULL here
* tclOOMethod.c:PushMethodCallFrame stores and attempts to use an
* invalid value in fdPtr->oldCmdPtr
*/
procPtr->cmdPtr = NULL;
procPtr->bodyPtr = bodyPtr;
procPtr->numArgs = 0; /* Actual argument count is set below. */
procPtr->numCompiledLocals = 0;
procPtr->firstLocalPtr = NULL;
procPtr->lastLocalPtr = NULL;
}
|
| ︙ | ︙ | |||
571 572 573 574 575 576 577 |
if (precompiled) {
/*
* Compare the parsed argument with the stored one. Note that the
* only flag value that makes sense at this point is VAR_ARGUMENT
* (its value was kept the same as pre VarReform to simplify
* tbcload's processing of older byetcodes).
*
| | | 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
if (precompiled) {
/*
* Compare the parsed argument with the stored one. Note that the
* only flag value that makes sense at this point is VAR_ARGUMENT
* (its value was kept the same as pre VarReform to simplify
* tbcload's processing of older byetcodes).
*
* The only other flag value that is important to retrieve from
* precompiled procs is VAR_TEMPORARY (also unchanged). It is
* needed later when retrieving the variable names.
*/
if ((localPtr->nameLength != nameLength)
|| (memcmp(localPtr->name, argname, nameLength) != 0)
|| (localPtr->frameIndex != i)
|
| ︙ | ︙ | |||
662 663 664 665 666 667 668 |
}
*procPtrPtr = procPtr;
return TCL_OK;
procError:
if (precompiled) {
| | | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 |
}
*procPtrPtr = procPtr;
return TCL_OK;
procError:
if (precompiled) {
TclProcDecrRefCount(procPtr);
} else {
Tcl_DecrRefCount(bodyPtr);
while (procPtr->firstLocalPtr != NULL) {
localPtr = procPtr->firstLocalPtr;
procPtr->firstLocalPtr = localPtr->nextPtr;
if (localPtr->defValuePtr != NULL) {
|
| ︙ | ︙ | |||
1759 1760 1761 1762 1763 1764 1765 |
}
#endif /* USE_DTRACE */
/*
* Invoke the commands in the procedure's body.
*/
| | | 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 |
}
#endif /* USE_DTRACE */
/*
* Invoke the commands in the procedure's body.
*/
TclProcIncrRefCount(procPtr);
ByteCodeGetIntRep(procPtr->bodyPtr, &tclByteCodeType, codePtr);
TclNRAddCallback(interp, InterpProcNR2, procNameObj, errorProc,
NULL, NULL);
return TclNRExecuteByteCode(interp, codePtr);
}
|
| ︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 |
if (TCL_DTRACE_PROC_RETURN_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
TCL_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result);
}
| < | < | 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 |
if (TCL_DTRACE_PROC_RETURN_ENABLED()) {
int l = iPtr->varFramePtr->isProcCallFrame & FRAME_IS_LAMBDA ? 1 : 0;
TCL_DTRACE_PROC_RETURN(l < iPtr->varFramePtr->objc ?
TclGetString(iPtr->varFramePtr->objv[l]) : NULL, result);
}
TclProcDecrRefCount(procPtr);
/*
* Free the stack-allocated compiled locals and CallFrame. It is important
* to pop the call frame without freeing it first: the compiledLocals
* cannot be freed before the frame is popped, as the local variables must
* be deleted. But the compiledLocals must be freed first, as they were
* allocated later on the stack.
|
| ︙ | ︙ | |||
2093 2094 2095 2096 2097 2098 2099 |
*/
void
TclProcDeleteProc(
ClientData clientData) /* Procedure to be deleted. */
{
Proc *procPtr = (Proc *)clientData;
| | | < < | 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 |
*/
void
TclProcDeleteProc(
ClientData clientData) /* Procedure to be deleted. */
{
Proc *procPtr = (Proc *)clientData;
TclProcDecrRefCount(procPtr);
return;
}
/*
*----------------------------------------------------------------------
*
* TclProcCleanupProc --
*
|
| ︙ | ︙ | |||
2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 |
if (localPtr->defValuePtr != NULL) {
defPtr = localPtr->defValuePtr;
Tcl_DecrRefCount(defPtr);
}
ckfree(localPtr);
localPtr = nextPtr;
}
ckfree(procPtr);
/*
* TIP #280: Release the location data associated with this Proc
* structure, if any. The interpreter may not exist (For example for
* procbody structures created by tbcload.
*/
| > > > > > > | 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 |
if (localPtr->defValuePtr != NULL) {
defPtr = localPtr->defValuePtr;
Tcl_DecrRefCount(defPtr);
}
ckfree(localPtr);
localPtr = nextPtr;
}
/*
* TclOOMethod.c:clOOMakeProcMethod sets cmdPtr to NULL
*/
if (procPtr->cmdPtr) {
TclCleanupCommandMacro(procPtr->cmdPtr);
}
ckfree(procPtr);
/*
* TIP #280: Release the location data associated with this Proc
* structure, if any. The interpreter may not exist (For example for
* procbody structures created by tbcload.
*/
|
| ︙ | ︙ | |||
2267 2268 2269 2270 2271 2272 2273 | * representation is the given Proc struct. The newly created object's * reference count is 0. * * Results: * Returns a pointer to a newly allocated Tcl_Obj, NULL on error. * * Side effects: | | | | 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 |
* representation is the given Proc struct. The newly created object's
* reference count is 0.
*
* Results:
* Returns a pointer to a newly allocated Tcl_Obj, NULL on error.
*
* Side effects:
* The reference count in the procPtr is bumped up
* by one since the internal rep stores a pointer to it.
*
*----------------------------------------------------------------------
*/
Tcl_Obj *
TclNewProcBodyObj(
Proc *procPtr) /* the Proc struct to store as the internal
|
| ︙ | ︙ | |||
2346 2347 2348 2349 2350 2351 2352 |
static void
ProcBodyFree(
Tcl_Obj *objPtr) /* The object to clean up. */
{
Proc *procPtr;
ProcGetIntRep(objPtr, procPtr);
| < < | < | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 |
static void
ProcBodyFree(
Tcl_Obj *objPtr) /* The object to clean up. */
{
Proc *procPtr;
ProcGetIntRep(objPtr, procPtr);
TclProcDecrRefCount(procPtr);
}
/*
*----------------------------------------------------------------------
*
* DupLambdaInternalRep, FreeLambdaInternalRep, SetLambdaFromAny --
*
|
| ︙ | ︙ | |||
2377 2378 2379 2380 2381 2382 2383 |
{
Proc *procPtr;
Tcl_Obj *nsObjPtr;
LambdaGetIntRep(srcPtr, procPtr, nsObjPtr);
assert(procPtr != NULL);
| < | > > > > > > | 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 |
{
Proc *procPtr;
Tcl_Obj *nsObjPtr;
LambdaGetIntRep(srcPtr, procPtr, nsObjPtr);
assert(procPtr != NULL);
TclProcIncrRefCount(procPtr);
LambdaSetIntRep(copyPtr, procPtr, nsObjPtr);
}
static void
FreeLambdaInternalRep(
Tcl_Obj *objPtr) /* CmdName object with internal representation
* to free. */
{
Proc *procPtr;
Tcl_Obj *nsObjPtr;
LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
assert(procPtr != NULL);
if (procPtr->refCount-- <= 1) {
/*
* procPtr->cmdPtr was not allocated but instead synthesized by
* TclNRApplyObjCmd. Tell TclProcCleanupProc() not to send it through
* the standard cleanup routine.
*/
procPtr->cmdPtr = NULL;
TclProcCleanupProc(procPtr);
}
TclDecrRefCount(nsObjPtr);
}
static int
SetLambdaFromAny(
|
| ︙ | ︙ | |||
2683 2684 2685 2686 2687 2688 2689 2690 2691 |
extraPtr->efi.length = 1;
extraPtr->efi.fields[0].name = "lambda";
extraPtr->efi.fields[0].proc = NULL;
extraPtr->efi.fields[0].clientData = lambdaPtr;
extraPtr->cmd.clientData = &extraPtr->efi;
result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
if (result == TCL_OK) {
| > | > > > | 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 |
extraPtr->efi.length = 1;
extraPtr->efi.fields[0].name = "lambda";
extraPtr->efi.fields[0].proc = NULL;
extraPtr->efi.fields[0].clientData = lambdaPtr;
extraPtr->cmd.clientData = &extraPtr->efi;
TclProcIncrRefCount(procPtr);
result = TclPushProcCallFrame(procPtr, interp, objc, objv, 1);
if (result == TCL_OK) {
TclNRAddCallback(interp, ApplyNR2, extraPtr, procPtr, NULL, NULL);
result = TclNRInterpProcCore(interp, objv[1], 2, &MakeLambdaError);
}
return result;
}
static int
ApplyNR2(
ClientData data[],
Tcl_Interp *interp,
int result)
{
ApplyExtraData *extraPtr = (ApplyExtraData *)data[0];
Proc *procPtr = (Proc *)data[1];
procPtr->cmdPtr = NULL;
TclProcDecrRefCount(procPtr);
TclStackFree(interp, extraPtr);
return result;
}
/*
*----------------------------------------------------------------------
|
| ︙ | ︙ |
Changes to generic/tclTestProcBodyObj.c.
| ︙ | ︙ | |||
209 210 211 212 213 214 215 |
* bodyName the name of an existing procedure from which the
* body is to be copied.
* This command can be used to trigger the branches in Tcl_ProcObjCmd that
* construct a proc from a "procbody", for example:
* proc a {x} {return $x}
* a 123
* procbodytest::proc b {x} a
| | | 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
* bodyName the name of an existing procedure from which the
* body is to be copied.
* This command can be used to trigger the branches in Tcl_ProcObjCmd that
* construct a proc from a "procbody", for example:
* proc a {x} {return $x}
* a 123
* procbodytest::proc b {x} a
* The call to "a 123" is necessary so that the Proc pointer
* for "a" is filled in by the internal compiler; this is a hack.
*
* Results:
* Returns a standard Tcl code.
*
* Side effects:
* A new procedure is created.
|
| ︙ | ︙ |
Changes to tests/interp.test.
| ︙ | ︙ | |||
3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 |
interp debug {} -frames
} -returnCodes error -result {bad debug option "-frames": must be -frame}
test interp-38.8 {interp debug basic setup} -body {
interp debug {} -frame 0 bogus
} -returnCodes {
error
} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}
# cleanup
unset -nocomplain hidden_cmds
foreach i [interp children] {
interp delete $i
}
::tcltest::cleanupTests
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 |
interp debug {} -frames
} -returnCodes error -result {bad debug option "-frames": must be -frame}
test interp-38.8 {interp debug basic setup} -body {
interp debug {} -frame 0 bogus
} -returnCodes {
error
} -result {wrong # args: should be "interp debug path ?-frame ?bool??"}
test interp-39.0 {
no segmentation fault when a command is deleted
} -body {
variable res {}
proc p1 args {
return success
}
namespace eval ns1 {
namespace export *
}
interp alias {} [namespace current]::ns1::p2 {} [namespace current]::p1
namespace eval ns2 {
namespace import [namespace parent]::ns1::p2
}
proc ondelete {oldname newname op} {
variable res
namespace delete ns1
catch {
ns1::p2
} res
}
trace add command ns2::p2 delete [namespace which ondelete]
rename ns2::p2 {}
rename p1 {}
if {
[string match {*invalid command name*ns1::p2*} $res]
} {
return 1
} else {
return $res
}
} -cleanup {
} -result 1
# cleanup
unset -nocomplain hidden_cmds
foreach i [interp children] {
interp delete $i
}
::tcltest::cleanupTests
|
| ︙ | ︙ |
Changes to tests/namespace.test.
| ︙ | ︙ | |||
532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
} -body {
namespace eval my \
[list namespace forget [namespace current]::link2::cmd]
my::cmd
} -cleanup {
namespace delete origin link link2 my
} -returnCodes error -match glob -result *
test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} -setup {
catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 |
} -body {
namespace eval my \
[list namespace forget [namespace current]::link2::cmd]
my::cmd
} -cleanup {
namespace delete origin link link2 my
} -returnCodes error -match glob -result *
test namespace-10.10 {
reference counting of target of imported command
should not produce a memory error in Tcl built with -DPURIFY
--enable-symbols
} -body {
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 args {}
}
namespace eval test_ns_import {
namespace import [namespace parent]::test_ns_export::cmd1
}
proc test_ns_export::cmd1 args {}
namespace delete test_ns_export
return success
} -result success
test namespace-10.11 {
when a routine is replaced, the new routine becomes the target for any
imports of the old routine
} -body {
namespace eval ns1 {
namespace export *
proc p1 {} {
return failure
}
}
namespace eval ns2 {
namespace import [namespace parent]::ns1::p1
}
proc ns1::p1 {} {
return success
}
set res [ns2::p1]
rename ns1::p1 {}
return $res
} -result success
test namespace-11.1 {TclGetOriginalCommand, check if not imported cmd} -setup {
catch {namespace delete {*}[namespace children :: test_ns_*]}
} -body {
namespace eval test_ns_export {
namespace export cmd1
proc cmd1 {args} {return "cmd1: $args"}
|
| ︙ | ︙ |
Changes to tests/proc.test.
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
set rv [p P Q R]
procbodytest::proc t {x y {z ZZ}} p
lappend rv [t S T U]
} -constraints procbodytest -returnCodes error -cleanup {
catch {rename p ""}
catch {rename t ""}
} -result {procedure "t": formal parameter "z" has default value inconsistent with precompiled body}
| | < < < | > > | | | | | > > > > > > > > > > > > | | | | | | | | | | > > | > > > > > > > > > > > | > > | 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
set rv [p P Q R]
procbodytest::proc t {x y {z ZZ}} p
lappend rv [t S T U]
} -constraints procbodytest -returnCodes error -cleanup {
catch {rename p ""}
catch {rename t ""}
} -result {procedure "t": formal parameter "z" has default value inconsistent with precompiled body}
try [string map {
@procpx@ {
proc px x {
set y [string tolower $x]
return $x:$y
}
px x
}
@cleanup@ {
unset -nocomplain end i tmp leakedBytes
}
} {
test proc-4.8 {TclCreateProc, procbody obj, no leak on multiple iterations} -setup {
proc getbytes {} {
set lines [split [memory info] \n]
lindex $lines 3 3
}
@procpx@
} -constraints {procbodytest memory} -body {
set end [getbytes]
for {set i 0} {$i < 5} {incr i} {
procbodytest::proc tx x px
set tmp $end
set end [getbytes]
}
set leakedBytes [expr {$end - $tmp}]
} -cleanup {
rename getbytes {}
@cleanup@
} -result 0
test proc-4.8.1 {
same as 4.8 but without the memory constraint so that valgrind can look
for leaks in tclTestProcBodyObj.c itself
} -setup {
@procpx@
} -constraints procbodytest -body {
procbodytest::proc tx x px
return 0
} -cleanup {
@cleanup@
} -result 0
}]
test proc-4.9 {[39fed4dae5] Valid Tcl_PkgPresent return} procbodytest {
procbodytest::check
} 1
test proc-5.1 {Bytecompiling noop; test for correct argument substitution} -body {
proc p args {} ; # this will be bytecompiled into t
proc t {} {
|
| ︙ | ︙ |