Check-in [32f829e03c]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge 8.7
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 32f829e03c95d78948cb29ffae1976d2465e8eba01befcfeffa4b2bc7cecb141
User & Date: jan.nijtmans 2019-12-02 11:50:26.677
Context
2019-12-02
13:35
Merge 8.7 check-in: 1f79812adb user: jan.nijtmans tags: trunk
11:50
Merge 8.7 check-in: 32f829e03c user: jan.nijtmans tags: trunk
10:58
Eliminate excess eol-spacing check-in: a8e4df4682 user: jan.nijtmans tags: core-8-branch
2019-12-01
21:26
Merge 8.7 check-in: 6deb3df3e1 user: jan.nijtmans tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to changes.
9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038

2018-02-06 [TIP 493] Cease Distribution of http 1.0 (porter)

2018-02-06 [TIP 484] internal rep for native ints are all 64-bit (nijtmans)

2018-02-14 [TIP 476] Scan/Printf consistency (nijtmans)

2018-03-05 [TIP 351] [lsearch] striding 

2018-03-05 [TIPs 330,336] tighten access to Interp fields (porter)

2018-03-12 [TIP 462] [::tcl::process] 

2018-03-12 [TIP 490] add oo support for msgcat => msgcat 1.7.0 (oehlmann)

2018-03-12 [TIP 499] custom locale preference list (oehlmann)
=> msgcat 1.7.0

2018-03-20 [TIP 503] End CONST84 support for Tcl 8.3 (porter)







|



|







9020
9021
9022
9023
9024
9025
9026
9027
9028
9029
9030
9031
9032
9033
9034
9035
9036
9037
9038

2018-02-06 [TIP 493] Cease Distribution of http 1.0 (porter)

2018-02-06 [TIP 484] internal rep for native ints are all 64-bit (nijtmans)

2018-02-14 [TIP 476] Scan/Printf consistency (nijtmans)

2018-03-05 [TIP 351] [lsearch] striding

2018-03-05 [TIPs 330,336] tighten access to Interp fields (porter)

2018-03-12 [TIP 462] [::tcl::process]

2018-03-12 [TIP 490] add oo support for msgcat => msgcat 1.7.0 (oehlmann)

2018-03-12 [TIP 499] custom locale preference list (oehlmann)
=> msgcat 1.7.0

2018-03-20 [TIP 503] End CONST84 support for Tcl 8.3 (porter)
Changes to generic/tcl.h.
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
    Tcl_FSFileAttrStringsProc *fileAttrStringsProc;
				/* List all valid attributes strings.  NULL if
				 * the filesystem does not support the 'file
				 * attributes' command.  Can be used to attach
				 * arbitrary additional data to files in a
				 * filesystem. */
    Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
				/* Called by 'Tcl_FSFileAttrsGet()' and by 
				 * 'file attributes'. */
    Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
				/* Called by 'Tcl_FSFileAttrsSet()' and by
				 * 'file attributes'.  */
    Tcl_FSCreateDirectoryProc *createDirectoryProc;
				/* Called by 'Tcl_FSCreateDirectory()'.  May be
				 * NULL if the filesystem is read-only. */







|







1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
    Tcl_FSFileAttrStringsProc *fileAttrStringsProc;
				/* List all valid attributes strings.  NULL if
				 * the filesystem does not support the 'file
				 * attributes' command.  Can be used to attach
				 * arbitrary additional data to files in a
				 * filesystem. */
    Tcl_FSFileAttrsGetProc *fileAttrsGetProc;
				/* Called by 'Tcl_FSFileAttrsGet()' and by
				 * 'file attributes'. */
    Tcl_FSFileAttrsSetProc *fileAttrsSetProc;
				/* Called by 'Tcl_FSFileAttrsSet()' and by
				 * 'file attributes'.  */
    Tcl_FSCreateDirectoryProc *createDirectoryProc;
				/* Called by 'Tcl_FSCreateDirectory()'.  May be
				 * NULL if the filesystem is read-only. */
Changes to generic/tclEncoding.c.
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
 *	little-endian systems.
 *
 * Results:
 *	Returns the new Tcl_Encoding,  or NULL if it could could
 *	not be created because the file contained invalid data.
 *
 * Side effects:
 *	See Tcl_CreateEncoding(). 
 *
 *-------------------------------------------------------------------------
 */

static Tcl_Encoding
LoadTableEncoding(
    const char *name,		/* Name of the new encoding. */







|







1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
 *	little-endian systems.
 *
 * Results:
 *	Returns the new Tcl_Encoding,  or NULL if it could could
 *	not be created because the file contained invalid data.
 *
 * Side effects:
 *	See Tcl_CreateEncoding().
 *
 *-------------------------------------------------------------------------
 */

static Tcl_Encoding
LoadTableEncoding(
    const char *name,		/* Name of the new encoding. */
Changes to generic/tclIOUtil.c.
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
	    && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) {
	FsRecacheFilesystemList();
    }
    return tsdPtr->filesystemList;
}

/*
 * The epoch can is changed when a filesystems is added or removed, when 
 * "system encoding" changes, and when env(HOME) changes.
 */

int
TclFSEpochOk(
    size_t filesystemEpoch)
{







|







616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
	    && (tsdPtr->filesystemEpoch != theFilesystemEpoch))) {
	FsRecacheFilesystemList();
    }
    return tsdPtr->filesystemList;
}

/*
 * The epoch can is changed when a filesystems is added or removed, when
 * "system encoding" changes, and when env(HOME) changes.
 */

int
TclFSEpochOk(
    size_t filesystemEpoch)
{
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
 *----------------------------------------------------------------------
 *
 * Tcl_FSMatchInDirectory --
 *
 *	Search in the given pathname for files matching the given pattern.
 *	Used by [glob].  Processes just one pattern for one directory.  Callers
 *	such as TclGlob and DoGlob implement manage the searching of multiple
 *	directories in cases such as  
 *		glob -dir $dir -join * pkgIndex.tcl
 *
 * Results:
 *
 *	TCL_OK, or TCL_ERROR
 *
 * Side effects:







|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
 *----------------------------------------------------------------------
 *
 * Tcl_FSMatchInDirectory --
 *
 *	Search in the given pathname for files matching the given pattern.
 *	Used by [glob].  Processes just one pattern for one directory.  Callers
 *	such as TclGlob and DoGlob implement manage the searching of multiple
 *	directories in cases such as
 *		glob -dir $dir -join * pkgIndex.tcl
 *
 * Results:
 *
 *	TCL_OK, or TCL_ERROR
 *
 * Side effects:
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
 *	a different filesystem.
 *
 *	Tcl has no control over (2) and (3), so each registered filesystem must
 *	call Tcl_FSMountsChnaged in each of those circumstances.
 *
 *	The reason for the exception in 2,3 for the native filesystem is that
 *	the native filesystem claims every file without determining whether
 *	whether the file exists, or even whether the pathname makes sense. 
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FSMountsChanged(
    const Tcl_Filesystem *fsPtr)
{
    /*
     * fsPtr is currently unused.  In the future it might invalidate files for
     * a particular filesystem, or take some other more advanced action.
     */

    (void)fsPtr;

    /*
     * Increment the filesystem epoch to invalidate every existing cached
     * internal representation. 
     */

    Tcl_MutexLock(&filesystemMutex);
    if (++theFilesystemEpoch == 0) {
	++theFilesystemEpoch;
    }
    Tcl_MutexUnlock(&filesystemMutex);







|

















|







1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
 *	a different filesystem.
 *
 *	Tcl has no control over (2) and (3), so each registered filesystem must
 *	call Tcl_FSMountsChnaged in each of those circumstances.
 *
 *	The reason for the exception in 2,3 for the native filesystem is that
 *	the native filesystem claims every file without determining whether
 *	whether the file exists, or even whether the pathname makes sense.
 *
 *----------------------------------------------------------------------
 */

void
Tcl_FSMountsChanged(
    const Tcl_Filesystem *fsPtr)
{
    /*
     * fsPtr is currently unused.  In the future it might invalidate files for
     * a particular filesystem, or take some other more advanced action.
     */

    (void)fsPtr;

    /*
     * Increment the filesystem epoch to invalidate every existing cached
     * internal representation.
     */

    Tcl_MutexLock(&filesystemMutex);
    if (++theFilesystemEpoch == 0) {
	++theFilesystemEpoch;
    }
    Tcl_MutexUnlock(&filesystemMutex);
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
int
TclGetOpenModeEx(
    Tcl_Interp *interp,		/* Interpreter, possibly NULL, to use for
				 * error reporting. */
    const char *modeString,	/* Mode string, e.g. "r+" or "RDONLY CREAT" */
    int *seekFlagPtr,		/* Sets this to 1 to tell the the caller to seek to
				 * EOF after opening the file, and 0 otherwise. */
    int *binaryPtr)		/* Sets this to 1 to tell the caller to 
				 * configure the channel for binary
				 * operations after opening the file. */
{
    int mode, modeArgc, c, i, gotRW;
    const char **modeArgv, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)








|







1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
int
TclGetOpenModeEx(
    Tcl_Interp *interp,		/* Interpreter, possibly NULL, to use for
				 * error reporting. */
    const char *modeString,	/* Mode string, e.g. "r+" or "RDONLY CREAT" */
    int *seekFlagPtr,		/* Sets this to 1 to tell the the caller to seek to
				 * EOF after opening the file, and 0 otherwise. */
    int *binaryPtr)		/* Sets this to 1 to tell the caller to
				 * configure the channel for binary
				 * operations after opening the file. */
{
    int mode, modeArgc, c, i, gotRW;
    const char **modeArgv, *flag;
#define RW_MODES (O_RDONLY|O_WRONLY|O_RDWR)

1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return result;
    }

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl 
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * If the encoding is specified, set the channel to that encoding.







|







1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return result;
    }

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * If the encoding is specified, set the channel to that encoding.
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    TclPkgFileSeen(interp, TclGetString(pathPtr));

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl 
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * If the encoding is specified, set the channel to that encoding.







|







1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
		"couldn't read file \"%s\": %s",
		TclGetString(pathPtr), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
    TclPkgFileSeen(interp, TclGetString(pathPtr));

    /*
     * The eof character is \32 (^Z). This is standard on Windows, and Tcl
     * uses it on every platform to allow for scripted documents. [Bug: 2040]
     */

    Tcl_SetChannelOption(interp, chan, "-eofchar", "\32 {}");

    /*
     * If the encoding is specified, set the channel to that encoding.
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
    return msg;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSStat --
 *	Calls 'statProc' of the filesystem corresponding to pathPtr. 
 *
 *	Replaces the standard library routines stat.
 *
 *
 * Results:
 *	See stat documentation.
 *







|







2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
    return msg;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSStat --
 *	Calls 'statProc' of the filesystem corresponding to pathPtr.
 *
 *	Replaces the standard library routines stat.
 *
 *
 * Results:
 *	See stat documentation.
 *
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSLstat --
 *	Calls the 'lstatProc' of the filesystem corresponding to pathPtr. 
 *
 *	Replaces the library version of lstat.  If the filesystem doesn't
 *	provide lstatProc but does provide statProc, Tcl falls back to
 *	statProc.
 *
 * Results:
 *	See lstat documentation.







|







2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
    return -1;
}

/*
 *----------------------------------------------------------------------
 *
 * Tcl_FSLstat --
 *	Calls the 'lstatProc' of the filesystem corresponding to pathPtr.
 *
 *	Replaces the library version of lstat.  If the filesystem doesn't
 *	provide lstatProc but does provide statProc, Tcl falls back to
 *	statProc.
 *
 * Results:
 *	See lstat documentation.
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
{
    const Tcl_Filesystem *fsPtr;
    Tcl_Channel retVal = NULL;


    if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) {
	/*
	 * Return the correct error message. 
	 */
	return NULL;
    }

    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) {
	int mode, seekFlag, binary;







|







2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
{
    const Tcl_Filesystem *fsPtr;
    Tcl_Channel retVal = NULL;


    if (Tcl_FSGetNormalizedPath(interp, pathPtr) == NULL) {
	/*
	 * Return the correct error message.
	 */
	return NULL;
    }

    fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);
    if (fsPtr != NULL && fsPtr->openFileChannelProc != NULL) {
	int mode, seekFlag, binary;
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
		 */

		retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd);
		Tcl_IncrRefCount(retVal);
		norm = TclFSNormalizeAbsolutePath(interp,retVal);
		if (norm != NULL) {
		    /*
		     * Assign to global storage the pathname of the current directory 
		     * and copy it into thread-local storage as well.
		     *
		     * At system startup multiple threads could in principle
		     * call this function simultaneously, which is a little
		     * peculiar, but should be fine given the mutex locks in
		     * FSUPdateCWD.  Once some value is assigned to the global
		     * variable the 'else' branch below is always taken, which







|







2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
		 */

		retVal = fsRecPtr->fsPtr->internalToNormalizedProc(retCd);
		Tcl_IncrRefCount(retVal);
		norm = TclFSNormalizeAbsolutePath(interp,retVal);
		if (norm != NULL) {
		    /*
		     * Assign to global storage the pathname of the current directory
		     * and copy it into thread-local storage as well.
		     *
		     * At system startup multiple threads could in principle
		     * call this function simultaneously, which is a little
		     * peculiar, but should be fine given the mutex locks in
		     * FSUPdateCWD.  Once some value is assigned to the global
		     * variable the 'else' branch below is always taken, which
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
		 *	cd = Tcl_FSGetNativePath(pathPtr);
		 * but this can't be guaranteed in the general case.  In fact,
		 * the internal handle could be any value the filesystem
		 * decides to use to identify a node.
		 */

		FsUpdateCwd(normDirName, cd);
	    } 
	} else {
	    /*
	     * Tcl_FSGetCwd() synchronizes the file-global cwdPathPtr if
	     * needed.  However, if there is no 'getCwdProc', cwdPathPtr must be
	     * updated right now because there won't be another chance.  This
	     * block of code is currently executed whether or not the
	     * filesystem provides a getCwdProc, but it should in principle







|







2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
		 *	cd = Tcl_FSGetNativePath(pathPtr);
		 * but this can't be guaranteed in the general case.  In fact,
		 * the internal handle could be any value the filesystem
		 * decides to use to identify a node.
		 */

		FsUpdateCwd(normDirName, cd);
	    }
	} else {
	    /*
	     * Tcl_FSGetCwd() synchronizes the file-global cwdPathPtr if
	     * needed.  However, if there is no 'getCwdProc', cwdPathPtr must be
	     * updated right now because there won't be another chance.  This
	     * block of code is currently executed whether or not the
	     * filesystem provides a getCwdProc, but it should in principle
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
    const char *sym1, const char *sym2,
				/* Names of two functions to find in the
				 * dynamic shared object. */
    Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr,
				/* Places to store pointers to the functions
				 * named by sym1 and sym2. */
    Tcl_LoadHandle *handlePtr,	/* A place to store the token for the loaded
				 * object.  Can be passed to 
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* A place to store a pointer to the function
				 * that unloads the object. */
{
    const char *symbols[3];
    void *procPtrs[2];







|







3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
    const char *sym1, const char *sym2,
				/* Names of two functions to find in the
				 * dynamic shared object. */
    Tcl_PackageInitProc **proc1Ptr, Tcl_PackageInitProc **proc2Ptr,
				/* Places to store pointers to the functions
				 * named by sym1 and sym2. */
    Tcl_LoadHandle *handlePtr,	/* A place to store the token for the loaded
				 * object.  Can be passed to
				 * (*unloadProcPtr)() to unload the file. */
    Tcl_FSUnloadFileProc **unloadProcPtr)
				/* A place to store a pointer to the function
				 * that unloads the object. */
{
    const char *symbols[3];
    void *procPtrs[2];
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LoadFile --
 *
 *	Load a dynamic shared object by calling 'loadFileProc' of the
 *	filesystem corresponding to the given pathname, and then finds within
 *	the loaded object the functions named in symbols[].  
 *
 *	The given pathname is passed unmodified to `loadFileProc`, which
 *	decides how to resolve it.  On POSIX systems the native filesystem
 *	passes the given pathname to dlopen(), which resolves the filename
 *	according to its own set of rules.  This behaviour is not very
 *	compatible with virtual filesystems, and has other problems as
 *	documented for [load], so it is recommended to use an absolute







|







3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
/*
 *----------------------------------------------------------------------
 *
 * Tcl_LoadFile --
 *
 *	Load a dynamic shared object by calling 'loadFileProc' of the
 *	filesystem corresponding to the given pathname, and then finds within
 *	the loaded object the functions named in symbols[].
 *
 *	The given pathname is passed unmodified to `loadFileProc`, which
 *	decides how to resolve it.  On POSIX systems the native filesystem
 *	passes the given pathname to dlopen(), which resolves the filename
 *	according to its own set of rules.  This behaviour is not very
 *	compatible with virtual filesystems, and has other problems as
 *	documented for [load], so it is recommended to use an absolute
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
	}
	if (Tcl_GetErrno() != EXDEV) {
	    return retVal;
	}
    }

    /*
     * The filesystem doesn't support 'load'. Fall to the following: 
     */

    /*
     * Make sure the file is accessible.
     */

    if (Tcl_FSAccess(pathPtr, R_OK) != 0) {







|







3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
	}
	if (Tcl_GetErrno() != EXDEV) {
	    return retVal;
	}
    }

    /*
     * The filesystem doesn't support 'load'. Fall to the following:
     */

    /*
     * Make sure the file is accessible.
     */

    if (Tcl_FSAccess(pathPtr, R_OK) != 0) {
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
    if (copyFsPtr != &tclNativeFilesystem) {
	/* refCount of copyToPtr is already incremented.  */
	tvdlPtr->divertedFile = copyToPtr;

	/*
	 * This is the filesystem for the temporary file the object was loaded
	 * from.  A reference to copyToPtr is already stored in
	 * tvdlPtr->divertedFile, so need need to increment the refCount again. 
	 */

	tvdlPtr->divertedFilesystem = copyFsPtr;
	tvdlPtr->divertedFileNativeRep = NULL;
    } else {
	/*
	 * Grab the native representation.







|







3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
    if (copyFsPtr != &tclNativeFilesystem) {
	/* refCount of copyToPtr is already incremented.  */
	tvdlPtr->divertedFile = copyToPtr;

	/*
	 * This is the filesystem for the temporary file the object was loaded
	 * from.  A reference to copyToPtr is already stored in
	 * tvdlPtr->divertedFile, so need need to increment the refCount again.
	 */

	tvdlPtr->divertedFilesystem = copyFsPtr;
	tvdlPtr->divertedFileNativeRep = NULL;
    } else {
	/*
	 * Grab the native representation.
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSLink(
    Tcl_Obj *pathPtr,		/* Pathaname of file. */
    Tcl_Obj *toPtr,		/* 
				 * NULL or the pathname of a file to link to.
				 */
    int linkAction)		/* Action to perform. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL && fsPtr->linkProc != NULL) {







|







3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
Tcl_FSLink(
    Tcl_Obj *pathPtr,		/* Pathaname of file. */
    Tcl_Obj *toPtr,		/*
				 * NULL or the pathname of a file to link to.
				 */
    int linkAction)		/* Action to perform. */
{
    const Tcl_Filesystem *fsPtr = Tcl_FSGetFileSystemForPath(pathPtr);

    if (fsPtr != NULL && fsPtr->linkProc != NULL) {
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
}

/*
 *---------------------------------------------------------------------------
 *
 * FsListMounts --
 *
 *	Lists the mounts mathing the given pattern in the given directory. 
 *
 * Results:
 *	A list, having a refCount of 0, of the matching mounts, or NULL if no
 *	search was performed because no filesystem provided a search routine.
 *
 * Side effects:
 *	None.







|







3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
}

/*
 *---------------------------------------------------------------------------
 *
 * FsListMounts --
 *
 *	Lists the mounts mathing the given pattern in the given directory.
 *
 * Results:
 *	A list, having a refCount of 0, of the matching mounts, or NULL if no
 *	search was performed because no filesystem provided a search routine.
 *
 * Side effects:
 *	None.
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219

/*
 *---------------------------------------------------------------------------
 *
 * TclCrossFilesystemCopy --
 *
 *	Helper for Tcl_FSCopyFile and Tcl_FSLoadFile.  Copies a file from one
 *	filesystem to another, overwiting any file that already exists. 
 *
 * Results:
 *	A standard Tcl return code.
 *
 * Side effects:
 *	A file may be copied.
 *







|







4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219

/*
 *---------------------------------------------------------------------------
 *
 * TclCrossFilesystemCopy --
 *
 *	Helper for Tcl_FSCopyFile and Tcl_FSLoadFile.  Copies a file from one
 *	filesystem to another, overwiting any file that already exists.
 *
 * Results:
 *	A standard Tcl return code.
 *
 * Side effects:
 *	A file may be copied.
 *
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
	Disclaim();
	return retVal;
    }

    /*
     * Call each of the "pathInFilesystem" functions in succession until the
     * corresponding filesystem is found.
     */ 
    for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
	ClientData clientData = NULL;

	if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) {
	    continue;
	}








|







4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
	Disclaim();
	return retVal;
    }

    /*
     * Call each of the "pathInFilesystem" functions in succession until the
     * corresponding filesystem is found.
     */
    for (; fsRecPtr!=NULL ; fsRecPtr=fsRecPtr->nextPtr) {
	ClientData clientData = NULL;

	if (fsRecPtr->fsPtr->pathInFilesystemProc == NULL) {
	    continue;
	}

Changes to generic/tclPathObj.c.
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    UpdateStringOfFsPath,		/* updateStringProc */
    SetFsPathFromAny			/* setFromAnyProc */
};

/*
 * struct FsPath --
 *
 * Internal representation of a Tcl_Obj of fsPathType 
 */

typedef struct {
    Tcl_Obj *translatedPathPtr; /*  If the path has been normalized (flags ==
				 *  0), this is NULL.  Otherwise it is a path
				 *  in which any ~user sequences have been
				 *  translated away. */







|







43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
    UpdateStringOfFsPath,		/* updateStringProc */
    SetFsPathFromAny			/* setFromAnyProc */
};

/*
 * struct FsPath --
 *
 * Internal representation of a Tcl_Obj of fsPathType
 */

typedef struct {
    Tcl_Obj *translatedPathPtr; /*  If the path has been normalized (flags ==
				 *  0), this is NULL.  Otherwise it is a path
				 *  in which any ~user sequences have been
				 *  translated away. */
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
 *	arrange for Tcl_DecRefCount to be called when the object is no-longer
 *	needed.
 *
 * Side effects:
 *	None (beyond the memory allocation for the result).
 *
 * Special note:
 *	Originally based on code from Matt Newman and Jean-Claude Wippler. 
 *	Totally rewritten later by Vince Darley to handle symbolic links.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclFSNormalizeAbsolutePath(







|







120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
 *	arrange for Tcl_DecRefCount to be called when the object is no-longer
 *	needed.
 *
 * Side effects:
 *	None (beyond the memory allocation for the result).
 *
 * Special note:
 *	Originally based on code from Matt Newman and Jean-Claude Wippler.
 *	Totally rewritten later by Vince Darley to handle symbolic links.
 *
 *---------------------------------------------------------------------------
 */

Tcl_Obj *
TclFSNormalizeAbsolutePath(
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
}

/*
 *---------------------------------------------------------------------------
 *
 * TclFSEnsureEpochOk --
 *
 *	Ensure that the path is a valid path, and that it has a 
 *	fsPathType internal representation that is not stale.
 *
 * Results:
 *	A standard Tcl return code.
 *
 * Side effects:
 *	The internal representation of fsPtrPtr is converted to fsPathType if







|







2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
}

/*
 *---------------------------------------------------------------------------
 *
 * TclFSEnsureEpochOk --
 *
 *	Ensure that the path is a valid path, and that it has a
 *	fsPathType internal representation that is not stale.
 *
 * Results:
 *	A standard Tcl return code.
 *
 * Side effects:
 *	The internal representation of fsPtrPtr is converted to fsPathType if
Changes to generic/tclScan.c.
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
		    mp_int big;
		    if (mp_init(&big) != MP_OKAY) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"insufficient memory to create bignum", -1));
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
			return TCL_ERROR;
		    } else {
			mp_set_ull(&big, (Tcl_WideUInt)wideValue);    
			Tcl_SetBignumObj(objPtr, &big);
		    }
		} else {
		    TclSetIntObj(objPtr, wideValue);
		}
	    } else if (flags & SCAN_BIG) {
		if (flags & SCAN_UNSIGNED) {







|







931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
		    mp_int big;
		    if (mp_init(&big) != MP_OKAY) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj(
				"insufficient memory to create bignum", -1));
			Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
			return TCL_ERROR;
		    } else {
			mp_set_ull(&big, (Tcl_WideUInt)wideValue);
			Tcl_SetBignumObj(objPtr, &big);
		    }
		} else {
		    TclSetIntObj(objPtr, wideValue);
		}
	    } else if (flags & SCAN_BIG) {
		if (flags & SCAN_UNSIGNED) {
Changes to library/tcltest/pkgIndex.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.1 [list source [file join $dir tcltest.tcl]]











|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.2 [list source [file join $dir tcltest.tcl]]
Changes to library/tcltest/tcltest.tcl.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

package require Tcl 8.5-		;# -verbose line uses [info frame]
namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.5.1

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package provide Tcl] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package provide Tcl]
    variable patchLevel [info patchlevel]








|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

package require Tcl 8.5-		;# -verbose line uses [info frame]
namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.5.2

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package provide Tcl] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package provide Tcl]
    variable patchLevel [info patchlevel]

2354
2355
2356
2357
2358
2359
2360
2361

2362
2363
2364
2365








2366
2367
2368
2369
2370
2371
2372
    # If there is no "memory" command (because memory debugging isn't
    # enabled), then don't attempt to use the command.

    if {[llength [info commands memory]] == 1} {
	memory tag $name
    }

    set code [catch {uplevel 1 $script} actualAnswer]


    return [list $actualAnswer $code]
}











# SetupTest --
#
# Evaluates the -setup script for a test

proc tcltest::SetupTest setup {







|
>




>
>
>
>
>
>
>
>







2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
    # If there is no "memory" command (because memory debugging isn't
    # enabled), then don't attempt to use the command.

    if {[llength [info commands memory]] == 1} {
	memory tag $name
    }

    set code [catch {uplevel 1 [list [
	namespace origin EvalTest] $script]} actualAnswer copts]

    return [list $actualAnswer $code]
}


proc tcltest::EvalTest script {
    set code [catch {uplevel 1 $script} cres copts]
    dict set copts -code $code
    dict incr copts -level
    return -options $copts $cres
}



# SetupTest --
#
# Evaluates the -setup script for a test

proc tcltest::SetupTest setup {
Changes to tests/info.test.
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
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
	incr level -1
    }
    return $res
}

test info-22.0 {info frame, levels} {!singleTestInterp} {
    info frame
} 7
test info-22.1 {info frame, bad level relative} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame -8} msg
    set msg
} {bad level "-8"}
test info-22.2 {info frame, bad level absolute} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame 9} msg
    set msg
} {bad level "9"}
test info-22.3 {info frame, current, relative} -match glob -body {
    info frame 0
} -result {type source line 750 file */info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-22.4 {info frame, current, relative, nested} -match glob -body {
    set res [info frame 0]
} -result {type source line 753 file */info.test cmd {info frame 0} proc ::tcltest::RunTest} -cleanup {unset res}
test info-22.5 {info frame, current, absolute} -constraints {!singleTestInterp} -match glob -body {
    reduce [info frame 7]
} -result {type source line 756 file info.test cmd {info frame 7} proc ::tcltest::RunTest}
test info-22.6 {info frame, global, relative} {!singleTestInterp} {
    reduce [info frame -6]
} {type source line 758 file info.test cmd test\ info-22.6\ \{info\ frame,\ global,\ relative\}\ \{!singleTestInter level 0}
test info-22.7 {info frame, global, absolute} {!singleTestInterp} {
    reduce [info frame 1]
} {type source line 761 file info.test cmd test\ info-22.7\ \{info\ frame,\ global,\ absolute\}\ \{!singleTestInter level 0}
test info-22.8 {info frame, basic trace} -match glob -body {
    join [lrange [etrace] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 765 file info.test cmd etrace proc ::tcltest::RunTest}
* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::RunTest}}
unset -nocomplain msg













|


|

|


|

|


|


|

|
|

|







|
|







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
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
	incr level -1
    }
    return $res
}

test info-22.0 {info frame, levels} {!singleTestInterp} {
    info frame
} 9
test info-22.1 {info frame, bad level relative} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame -10} msg
    set msg
} {bad level "-10"}
test info-22.2 {info frame, bad level absolute} {!singleTestInterp} {
    # catch is another level!, i.e. we have 8, not 7
    catch {info frame 11} msg
    set msg
} {bad level "11"}
test info-22.3 {info frame, current, relative} -match glob -body {
    info frame 0
} -result {type source line 750 file */info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-22.4 {info frame, current, relative, nested} -match glob -body {
    set res [info frame 0]
} -result {type source line 753 file */info.test cmd {info frame 0} proc ::tcltest::EvalTest} -cleanup {unset res}
test info-22.5 {info frame, current, absolute} -constraints {!singleTestInterp} -match glob -body {
    reduce [info frame 9]
} -result {type source line 756 file info.test cmd {info frame 9} proc ::tcltest::EvalTest}
test info-22.6 {info frame, global, relative} {!singleTestInterp} {
    reduce [info frame -8]
} {type source line 758 file info.test cmd test\ info-22.6\ \{info\ frame,\ global,\ relative\}\ \{!singleTestInter level 0}
test info-22.7 {info frame, global, absolute} {!singleTestInterp} {
    reduce [info frame 1]
} {type source line 761 file info.test cmd test\ info-22.7\ \{info\ frame,\ global,\ absolute\}\ \{!singleTestInter level 0}
test info-22.8 {info frame, basic trace} -match glob -body {
    join [lrange [etrace] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type source line 765 file info.test cmd etrace proc ::tcltest::EvalTest}
* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::EvalTest}}
unset -nocomplain msg






788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
    i eval {	set script {info frame}
		eval $script}
} -setup {interp create i} -cleanup {interp delete i} -result 2
test info-23.3 {eval'd info frame, literal} -match glob -body {
    eval {
	info frame 0
    }
} -result {type source line 793 file * cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.4 {eval'd info frame, semi-dynamic} {
    eval info frame 0
} {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.5 {eval'd info frame, dynamic} -cleanup {unset script} -body {
    set script {info frame 0}
    eval $script
} -result {type eval line 1 cmd {info frame 0} proc ::tcltest::RunTest}
test info-23.6 {eval'd info frame, trace} -match glob -cleanup {unset script} -body {
    set script {etrace}
    join [lrange [eval $script] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::RunTest}
* {type source line 805 file info.test cmd {eval $script} proc ::tcltest::RunTest}}

# -------------------------------------------------------------------------

# Procedures defined in scripts which are arguments to control
# structures (like 'namespace eval', 'interp eval', 'if', 'while',
# 'switch', 'catch', 'for', 'foreach', etc.) have no absolute
# location. The command implementations execute such scripts through







|


|



|




|
|







788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
    i eval {	set script {info frame}
		eval $script}
} -setup {interp create i} -cleanup {interp delete i} -result 2
test info-23.3 {eval'd info frame, literal} -match glob -body {
    eval {
	info frame 0
    }
} -result {type source line 793 file * cmd {info frame 0} proc ::tcltest::EvalTest}
test info-23.4 {eval'd info frame, semi-dynamic} {
    eval info frame 0
} {type eval line 1 cmd {info frame 0} proc ::tcltest::EvalTest}
test info-23.5 {eval'd info frame, dynamic} -cleanup {unset script} -body {
    set script {info frame 0}
    eval $script
} -result {type eval line 1 cmd {info frame 0} proc ::tcltest::EvalTest}
test info-23.6 {eval'd info frame, trace} -match glob -cleanup {unset script} -body {
    set script {etrace}
    join [lrange [eval $script] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::EvalTest}
* {type source line 805 file info.test cmd {eval $script} proc ::tcltest::EvalTest}}

# -------------------------------------------------------------------------

# Procedures defined in scripts which are arguments to control
# structures (like 'namespace eval', 'interp eval', 'if', 'while',
# 'switch', 'catch', 'for', 'foreach', etc.) have no absolute
# location. The command implementations execute such scripts through
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
    return $res
    # This was reporting line 3 instead of the correct 4 because the
    # bs+nl combination is subst by the parser before the 'if'
    # command, and the bcc, see the word. Fixed by recording the
    # offsets of all bs+nl sequences in literal words, then using the
    # information in the bcc and other places to bump line numbers when
    # parsing over the location. Also affected: testcases 22.8 and 23.6.
} -result {type source line 1018 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

# -------------------------------------------------------------------------
# See 24.0 - 24.5 for similar situations, using literal scripts.

set body {set flag 0
    set a c
    set res [info frame 0]} ;# line 3!

test info-31.0 {ns eval, script in variable} -body {namespace eval foo {variable res {}}
    namespace eval foo $body
    return $foo::res
} -result {type eval line 3 cmd {info frame 0} level 0} -cleanup {
    catch {namespace delete foo}
}
test info-31.1 {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.1a {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 then $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.2 {while, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    while {$flag} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

# .3 - proc - scoping prevent return of result ...

test info-31.4 {foreach, script in variable} -cleanup {unset var res a flag} -body {
    foreach var val $body
    set res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.5 {for, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    for {} {$flag} {} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

test info-31.6 {eval, script in variable} -cleanup {unset res a flag} -body {
    eval $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::RunTest}

# -------------------------------------------------------------------------

set body {
    foo {
	proc ::foo::bar {} {info frame 0}
    }







|

















|




|





|






|





|




|







1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
    return $res
    # This was reporting line 3 instead of the correct 4 because the
    # bs+nl combination is subst by the parser before the 'if'
    # command, and the bcc, see the word. Fixed by recording the
    # offsets of all bs+nl sequences in literal words, then using the
    # information in the bcc and other places to bump line numbers when
    # parsing over the location. Also affected: testcases 22.8 and 23.6.
} -result {type source line 1018 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

# -------------------------------------------------------------------------
# See 24.0 - 24.5 for similar situations, using literal scripts.

set body {set flag 0
    set a c
    set res [info frame 0]} ;# line 3!

test info-31.0 {ns eval, script in variable} -body {namespace eval foo {variable res {}}
    namespace eval foo $body
    return $foo::res
} -result {type eval line 3 cmd {info frame 0} level 0} -cleanup {
    catch {namespace delete foo}
}
test info-31.1 {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

test info-31.1a {if, script in variable} -cleanup {unset res a flag} -body {
    if 1 then $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

test info-31.2 {while, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    while {$flag} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

# .3 - proc - scoping prevent return of result ...

test info-31.4 {foreach, script in variable} -cleanup {unset var res a flag} -body {
    foreach var val $body
    set res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

test info-31.5 {for, script in variable} -cleanup {unset flag res a} -body {
    set flag 1
    for {} {$flag} {} $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

test info-31.6 {eval, script in variable} -cleanup {unset res a flag} -body {
    eval $body
    return $res
} -result {type eval line 3 cmd {info frame 0} proc ::tcltest::EvalTest}

# -------------------------------------------------------------------------

set body {
    foo {
	proc ::foo::bar {} {info frame 0}
    }
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
    set cmd [list foreach $foo {x y} {
	set res [join [lrange [etrace] 0 2] \n]
	break
    }]
    eval $cmd
    return $res
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 2 cmd etrace proc ::tcltest::RunTest}
* {type eval line 1 cmd foreac proc ::tcltest::RunTest}} -cleanup {unset foo cmd res b c}

# -------------------------------------------------------------------------

# 6 cases.
## DV. direct-var          - unchanged
## DPV direct-proc-var     - ditto
## PPV proc-proc-var       - ditto







|
|







1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
    set cmd [list foreach $foo {x y} {
	set res [join [lrange [etrace] 0 2] \n]
	break
    }]
    eval $cmd
    return $res
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 2 cmd etrace proc ::tcltest::EvalTest}
* {type eval line 1 cmd foreac proc ::tcltest::EvalTest}} -cleanup {unset foo cmd res b c}

# -------------------------------------------------------------------------

# 6 cases.
## DV. direct-var          - unchanged
## DPV direct-proc-var     - ditto
## PPV proc-proc-var       - ditto
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
test info-38.1 {location information for uplevel, dv, direct-var} -match glob -body {
    set script {
	set y DV.
	etrace
    }
    join [lrange [uplevel \#0 $script] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::tcltest::RunTest}
* {type source line 1361 file info.test cmd {uplevel \\#0 $script} proc ::tcltest::RunTest}} -cleanup {unset script y}

# 38.2 moved to bottom to not disturb other tests with the necessary changes to this one.








test info-38.3 {location information for uplevel, dpv, direct-proc-var} -match glob -body {
    set script {
	set y DPV
	etrace
    }
    join [lrange [control y $script] 0 3] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1380 file info.test cmd {control y $script} proc ::tcltest::RunTest}} -cleanup {unset script y}

# 38.4 moved to bottom to not disturb other tests with the necessary changes to this one.









test info-38.5 {location information for uplevel, ppv, proc-proc-var} -match glob -body {
    join [lrange [datav] 0 4] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1353 file info.test cmd {control y $script} proc ::datav level 1}
* {type source line 1397 file info.test cmd datav proc ::tcltest::RunTest}}

# 38.6 moved to bottom to not disturb other tests with the necessary changes to this one.







testConstraint testevalex [llength [info commands testevalex]]
test info-38.7 {location information for arg substitution} -constraints testevalex -match glob -body {
    join [lrange [testevalex {return -level 0 [etrace]}] 0 3] \n
} -result {* {type source line 730 file info.test cmd {info frame \$level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::RunTest}
* {type source line 1414 file info.test cmd {testevalex {return -level 0 \[etrace]}} proc ::tcltest::RunTest}
* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::RunTest}}

# -------------------------------------------------------------------------
# literal sharing

test info-39.0 {location information not confused by literal sharing} -body {
    namespace eval ::foo {}
    proc ::foo::bar {} {







|
|



















|

















|













|
|
|







1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
test info-38.1 {location information for uplevel, dv, direct-var} -match glob -body {
    set script {
	set y DV.
	etrace
    }
    join [lrange [uplevel \#0 $script] 0 2] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::tcltest::EvalTest}
* {type source line 1361 file info.test cmd {uplevel \\#0 $script} proc ::tcltest::EvalTest}} -cleanup {unset script y}

# 38.2 moved to bottom to not disturb other tests with the necessary changes to this one.








test info-38.3 {location information for uplevel, dpv, direct-proc-var} -match glob -body {
    set script {
	set y DPV
	etrace
    }
    join [lrange [control y $script] 0 3] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1380 file info.test cmd {control y $script} proc ::tcltest::EvalTest}} -cleanup {unset script y}

# 38.4 moved to bottom to not disturb other tests with the necessary changes to this one.









test info-38.5 {location information for uplevel, ppv, proc-proc-var} -match glob -body {
    join [lrange [datav] 0 4] \n
} -result {* {type source line 730 file info.test cmd {info frame $level} proc ::etrace level 0}
* {type eval line 3 cmd etrace proc ::control}
* {type source line 1338 file info.test cmd {uplevel 1 $script} proc ::control}
* {type source line 1353 file info.test cmd {control y $script} proc ::datav level 1}
* {type source line 1397 file info.test cmd datav proc ::tcltest::EvalTest}}

# 38.6 moved to bottom to not disturb other tests with the necessary changes to this one.







testConstraint testevalex [llength [info commands testevalex]]
test info-38.7 {location information for arg substitution} -constraints testevalex -match glob -body {
    join [lrange [testevalex {return -level 0 [etrace]}] 0 3] \n
} -result {* {type source line 730 file info.test cmd {info frame \$level} proc ::etrace level 0}
* {type eval line 1 cmd etrace proc ::tcltest::EvalTest}
* {type source line 1414 file info.test cmd {testevalex {return -level 0 \[etrace]}} proc ::tcltest::EvalTest}
* {type source line * file tcltest* cmd {uplevel 1 $script} proc ::tcltest::EvalTest}}

# -------------------------------------------------------------------------
# literal sharing

test info-39.0 {location information not confused by literal sharing} -body {
    namespace eval ::foo {}
    proc ::foo::bar {} {
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
    return [reduce $xxx::res]
} {type source line 1457 file info.test cmd {info frame 0} level 0}

test info-30.3 {bs+nl in literal words, namespace multi-word script} {
    namespace eval xxx variable res \
	[list [reduce [info frame 0]]];# line 1464
    return $xxx::res
} {type source line 1464 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.4 {bs+nl in literal words, eval script} -cleanup {unset res} -body {
    eval {
	set ::res \
	    [reduce [info frame 0]];# line 1471
    }
    return $res
} -result {type source line 1471 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.5 {bs+nl in literal words, eval script, with nested words} -body {
    eval {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1481
	    }
    }
    return $res
} -cleanup {unset res} -result {type source line 1481 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.6 {bs+nl in computed word} -cleanup {unset res} -body {
    set res "\
[reduce [info frame 0]]";# line 1489
} -result { type source line 1489 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.7 {bs+nl in computed word, in proc} -body {
    proc abra {} {
	return "\
[reduce [info frame 0]]";# line 1495
    }
    abra
} -cleanup {
    rename abra {}
} -result { type source line 1495 file info.test cmd {info frame 0} proc ::abra level 0}

test info-30.8 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce [info frame 0]]";# line 1506
}
} -cleanup {unset res} -result { type source line 1506 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.9 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce \
     [info frame 0]]";# line 1515
}
} -cleanup {unset res} -result { type source line 1515 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.10 {bs+nl in computed word, key to array} -body {
    set tmp([set \
	    res "\
[reduce \
     [info frame 0]]"]) x ; #1523
    unset tmp
    set res
} -cleanup {unset res} -result { type source line 1523 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.11 {bs+nl in subst arguments} -body {
    subst {[set \
	    res "\
[reduce \
     [info frame 0]]"]} ; #1532
} -cleanup {unset res} -result { type source line 1532 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.12 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[set x {}] \
[reduce \
     [info frame 0]]";# line 1541
}
} -cleanup {unset res x} -result {   type source line 1541 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.13 {bs+nl in literal words, uplevel script, with nested words} -body {
    subinterp ; set res [interp eval sub { uplevel #0 {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1550







|







|










|




|

















|








|








|






|









|







1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
    return [reduce $xxx::res]
} {type source line 1457 file info.test cmd {info frame 0} level 0}

test info-30.3 {bs+nl in literal words, namespace multi-word script} {
    namespace eval xxx variable res \
	[list [reduce [info frame 0]]];# line 1464
    return $xxx::res
} {type source line 1464 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.4 {bs+nl in literal words, eval script} -cleanup {unset res} -body {
    eval {
	set ::res \
	    [reduce [info frame 0]];# line 1471
    }
    return $res
} -result {type source line 1471 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.5 {bs+nl in literal words, eval script, with nested words} -body {
    eval {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1481
	    }
    }
    return $res
} -cleanup {unset res} -result {type source line 1481 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.6 {bs+nl in computed word} -cleanup {unset res} -body {
    set res "\
[reduce [info frame 0]]";# line 1489
} -result { type source line 1489 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.7 {bs+nl in computed word, in proc} -body {
    proc abra {} {
	return "\
[reduce [info frame 0]]";# line 1495
    }
    abra
} -cleanup {
    rename abra {}
} -result { type source line 1495 file info.test cmd {info frame 0} proc ::abra level 0}

test info-30.8 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce [info frame 0]]";# line 1506
}
} -cleanup {unset res} -result { type source line 1506 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.9 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[reduce \
     [info frame 0]]";# line 1515
}
} -cleanup {unset res} -result { type source line 1515 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.10 {bs+nl in computed word, key to array} -body {
    set tmp([set \
	    res "\
[reduce \
     [info frame 0]]"]) x ; #1523
    unset tmp
    set res
} -cleanup {unset res} -result { type source line 1523 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.11 {bs+nl in subst arguments} -body {
    subst {[set \
	    res "\
[reduce \
     [info frame 0]]"]} ; #1532
} -cleanup {unset res} -result { type source line 1532 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.12 {bs+nl in computed word, nested eval} -body {
    eval {
	set \
	    res "\
[set x {}] \
[reduce \
     [info frame 0]]";# line 1541
}
} -cleanup {unset res x} -result {   type source line 1541 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.13 {bs+nl in literal words, uplevel script, with nested words} -body {
    subinterp ; set res [interp eval sub { uplevel #0 {
	if {1} \
	    {
		set ::res \
		    [reduce [info frame 0]];# line 1550
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
type source line 1589 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.17 {bs+nl in multi-body switch, direct} {
    switch -regexp -- {key    } \
	^key     { reduce [info frame 0] ;# 1601 } \
        \t###    { } \
        {[0-9]*} { }
} {type source line 1601 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {
    proc abra {script} {
	append script "\n# end of script"
	uplevel 1 $script
    }
    set res [abra {







|







1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
type source line 1589 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.17 {bs+nl in multi-body switch, direct} {
    switch -regexp -- {key    } \
	^key     { reduce [info frame 0] ;# 1601 } \
        \t###    { } \
        {[0-9]*} { }
} {type source line 1601 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.18 {bs+nl, literal word, uplevel through proc, appended, loss of primary tracking data} {
    proc abra {script} {
	append script "\n# end of script"
	uplevel 1 $script
    }
    set res [abra {
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
    switch -regexp -- {key    } { \

	^key     { reduce \
		       [info frame 0] }
	\t###    { }
        {[0-9]*} { }
    }
} {type source line 1643 file info.test cmd {info frame 0} proc ::tcltest::RunTest}

test info-30.21 {bs+nl in if, full compiled} {
    proc a {value} {
	if {$value} \
	    {info frame 0} \
	    {info frame 0} ; # 1653
    }







|







1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
    switch -regexp -- {key    } { \

	^key     { reduce \
		       [info frame 0] }
	\t###    { }
        {[0-9]*} { }
    }
} {type source line 1643 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}

test info-30.21 {bs+nl in if, full compiled} {
    proc a {value} {
	if {$value} \
	    {info frame 0} \
	    {info frame 0} ; # 1653
    }
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
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
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
    set res "\n[join $res \n]"
} {
type source line 1696 file info.test cmd {info frame 0} proc ::a level 0
type source line 1700 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.25 {TIP 280 for compiled [subst]} {
    subst {[reduce [info frame 0]]} ; # 1712
} {type source line 1712 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.26 {TIP 280 for compiled [subst]} {
    subst \
	    {[reduce [info frame 0]]} ; # 1716
} {type source line 1716 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.27 {TIP 280 for compiled [subst]} {
    subst {
[reduce [info frame 0]]} ; # 1720
} {
type source line 1720 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.28 {TIP 280 for compiled [subst]} {
    subst {\
[reduce [info frame 0]]} ; # 1725
} { type source line 1725 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.29 {TIP 280 for compiled [subst]} {
    subst {foo\
[reduce [info frame 0]]} ; # 1729
} {foo type source line 1729 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.30 {TIP 280 for compiled [subst]} {
    subst {foo
[reduce [info frame 0]]} ; # 1733
} {foo
type source line 1733 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.31 {TIP 280 for compiled [subst]} {
    subst {[][reduce [info frame 0]]} ; # 1737
} {type source line 1737 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.32 {TIP 280 for compiled [subst]} {
    subst {[\
][reduce [info frame 0]]} ; # 1741
} {type source line 1741 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.33 {TIP 280 for compiled [subst]} {
    subst {[
][reduce [info frame 0]]} ; # 1745
} {type source line 1745 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.34 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
][reduce [info frame 0]]} ; # 1749
} {type source line 1749 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.35 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
]
[reduce [info frame 0]]} ; # 1754
} {
type source line 1754 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.36 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}][reduce [info frame 0]]} ; # 1759
} {
type source line 1759 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.37 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}]
[reduce [info frame 0]]} ; # 1765
} {

type source line 1765 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.38 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}][reduce [info frame 0]]} ; # 1771
} { type source line 1771 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.39 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}]\
[reduce [info frame 0]]} ; # 1776
} {  type source line 1776 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.40 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty[reduce [info frame 0]]} ; # 1782
} -cleanup {
    unset empty
} -result {type source line 1782 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.41 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty
[reduce [info frame 0]]} ; # 1791
} -cleanup {
    unset empty
} -result {
type source line 1791 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.42 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}; subst {$empty\
[reduce [info frame 0]]} ; # 1800
} -cleanup {
    unset empty
} -result { type source line 1800 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.43 {TIP 280 for compiled [subst]} -body {
    unset -nocomplain a\nb
    set a\nb {}
    subst {${a
b}[reduce [info frame 0]]} ; # 1808
} -cleanup {unset a\nb} -result {type source line 1808 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.44 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n) {}
    subst {$a(
)[reduce [info frame 0]]} ; # 1814
} {type source line 1814 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.45 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a() {}
    subst {$a([
return -level 0])[reduce [info frame 0]]} ; # 1820
} {type source line 1820 file info.test cmd {info frame 0} proc ::tcltest::RunTest}
test info-30.46 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(1825) YES;  set a(1824) 1824; set a(1826) 1826
    subst {$a([dict get [info frame 0] line])} ; # 1825
} YES
test info-30.47 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n1831) YES;  set a(\n1830) 1830; set a(\n1832) 1832
    subst {$a(
[dict get [info frame 0] line])} ; # 1831
} YES
unset -nocomplain a

test info-30.48 {Bug 2850901} testevalex {
    testevalex {return -level 0 [format %s {}
][reduce [info frame 0]]} ; # line 2 of the eval
} {type eval line 2 cmd {info frame 0} proc ::tcltest::RunTest}


# -------------------------------------------------------------------------
# literal sharing 2, bug 2933089

test info-39.1 {location information not confused by literal sharing, bug 2933089} -setup {
    set result {}







|



|




|



|



|




|


|



|



|



|





|




|






|



|




|







|









|







|





|





|





|
















|







1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
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
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
    set res "\n[join $res \n]"
} {
type source line 1696 file info.test cmd {info frame 0} proc ::a level 0
type source line 1700 file info.test cmd {info frame 0} proc ::a level 0}

test info-30.25 {TIP 280 for compiled [subst]} {
    subst {[reduce [info frame 0]]} ; # 1712
} {type source line 1712 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.26 {TIP 280 for compiled [subst]} {
    subst \
	    {[reduce [info frame 0]]} ; # 1716
} {type source line 1716 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.27 {TIP 280 for compiled [subst]} {
    subst {
[reduce [info frame 0]]} ; # 1720
} {
type source line 1720 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.28 {TIP 280 for compiled [subst]} {
    subst {\
[reduce [info frame 0]]} ; # 1725
} { type source line 1725 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.29 {TIP 280 for compiled [subst]} {
    subst {foo\
[reduce [info frame 0]]} ; # 1729
} {foo type source line 1729 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.30 {TIP 280 for compiled [subst]} {
    subst {foo
[reduce [info frame 0]]} ; # 1733
} {foo
type source line 1733 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.31 {TIP 280 for compiled [subst]} {
    subst {[][reduce [info frame 0]]} ; # 1737
} {type source line 1737 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.32 {TIP 280 for compiled [subst]} {
    subst {[\
][reduce [info frame 0]]} ; # 1741
} {type source line 1741 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.33 {TIP 280 for compiled [subst]} {
    subst {[
][reduce [info frame 0]]} ; # 1745
} {type source line 1745 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.34 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
][reduce [info frame 0]]} ; # 1749
} {type source line 1749 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.35 {TIP 280 for compiled [subst]} {
    subst {[format %s {}
]
[reduce [info frame 0]]} ; # 1754
} {
type source line 1754 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.36 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}][reduce [info frame 0]]} ; # 1759
} {
type source line 1759 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.37 {TIP 280 for compiled [subst]} {
    subst {
[format %s {}]
[reduce [info frame 0]]} ; # 1765
} {

type source line 1765 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.38 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}][reduce [info frame 0]]} ; # 1771
} { type source line 1771 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.39 {TIP 280 for compiled [subst]} {
    subst {\
[format %s {}]\
[reduce [info frame 0]]} ; # 1776
} {  type source line 1776 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.40 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty[reduce [info frame 0]]} ; # 1782
} -cleanup {
    unset empty
} -result {type source line 1782 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.41 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}
    subst {$empty
[reduce [info frame 0]]} ; # 1791
} -cleanup {
    unset empty
} -result {
type source line 1791 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.42 {TIP 280 for compiled [subst]} -setup {
    unset -nocomplain empty
} -body {
    set empty {}; subst {$empty\
[reduce [info frame 0]]} ; # 1800
} -cleanup {
    unset empty
} -result { type source line 1800 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.43 {TIP 280 for compiled [subst]} -body {
    unset -nocomplain a\nb
    set a\nb {}
    subst {${a
b}[reduce [info frame 0]]} ; # 1808
} -cleanup {unset a\nb} -result {type source line 1808 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.44 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n) {}
    subst {$a(
)[reduce [info frame 0]]} ; # 1814
} {type source line 1814 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.45 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a() {}
    subst {$a([
return -level 0])[reduce [info frame 0]]} ; # 1820
} {type source line 1820 file info.test cmd {info frame 0} proc ::tcltest::EvalTest}
test info-30.46 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(1825) YES;  set a(1824) 1824; set a(1826) 1826
    subst {$a([dict get [info frame 0] line])} ; # 1825
} YES
test info-30.47 {TIP 280 for compiled [subst]} {
    unset -nocomplain a
    set a(\n1831) YES;  set a(\n1830) 1830; set a(\n1832) 1832
    subst {$a(
[dict get [info frame 0] line])} ; # 1831
} YES
unset -nocomplain a

test info-30.48 {Bug 2850901} testevalex {
    testevalex {return -level 0 [format %s {}
][reduce [info frame 0]]} ; # line 2 of the eval
} {type eval line 2 cmd {info frame 0} proc ::tcltest::EvalTest}


# -------------------------------------------------------------------------
# literal sharing 2, bug 2933089

test info-39.1 {location information not confused by literal sharing, bug 2933089} -setup {
    set result {}
Changes to unix/Makefile.in.
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
	@echo "Installing package opt 0.4.7"
	@for i in $(TOP_DIR)/library/opt/*.tcl; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
	done
	@echo "Installing package msgcat 1.7.0 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/msgcat-1.7.0.tm
	@echo "Installing package tcltest 2.5.1 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/tcltest-2.5.1.tm
	@echo "Installing package platform 1.0.14 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/platform-1.0.14.tm
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/platform/shell-1.1.4.tm
	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"







|

|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
	@echo "Installing package opt 0.4.7"
	@for i in $(TOP_DIR)/library/opt/*.tcl; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)"/opt0.4; \
	done
	@echo "Installing package msgcat 1.7.0 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/msgcat-1.7.0.tm
	@echo "Installing package tcltest 2.5.2 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/tcltest-2.5.2.tm
	@echo "Installing package platform 1.0.14 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/platform-1.0.14.tm
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \
		"$(MODULE_INSTALL_DIR)"/tcl9/9.0/platform/shell-1.1.4.tm
	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"
Changes to unix/tclUnixFCmd.c.
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060

	    break;
	}
	currentPathEndPosition++;
    }

    /*
     * Call 'realpath' to obtain a canonical path. 
     */

#ifndef NO_REALPATH
    if (haveRealpath) {
	if (nextCheckpoint == 0) {
	    /*
	     * The path contains at most one component, e.g. '/foo' or '/', so
	     * so there is nothing to resolve. Also, on some platforms
	     * 'Realpath' transforms an empty string into the normalized pwd,
	     * which is the wrong answer. 
	     */

	    return 0;
	}

	nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);
	if (Realpath(nativePath, normPath) != NULL) {







|









|







2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060

	    break;
	}
	currentPathEndPosition++;
    }

    /*
     * Call 'realpath' to obtain a canonical path.
     */

#ifndef NO_REALPATH
    if (haveRealpath) {
	if (nextCheckpoint == 0) {
	    /*
	     * The path contains at most one component, e.g. '/foo' or '/', so
	     * so there is nothing to resolve. Also, on some platforms
	     * 'Realpath' transforms an empty string into the normalized pwd,
	     * which is the wrong answer.
	     */

	    return 0;
	}

	nativePath = Tcl_UtfToExternalDString(NULL, path,nextCheckpoint, &ds);
	if (Realpath(nativePath, normPath) != NULL) {
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
	     */

	    Tcl_DStringFree(&ds);
	    Tcl_ExternalToUtfDString(NULL, normPath, newNormLen, &ds);

	    if (path[nextCheckpoint] != '\0') {
		/*
		 * Append the remaining path components. 
		 */

		int normLen = Tcl_DStringLength(&ds);

		Tcl_DStringAppend(&ds, path + nextCheckpoint,
			pathLen - nextCheckpoint);








|







2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
	     */

	    Tcl_DStringFree(&ds);
	    Tcl_ExternalToUtfDString(NULL, normPath, newNormLen, &ds);

	    if (path[nextCheckpoint] != '\0') {
		/*
		 * Append the remaining path components.
		 */

		int normLen = Tcl_DStringLength(&ds);

		Tcl_DStringAppend(&ds, path + nextCheckpoint,
			pathLen - nextCheckpoint);

Changes to win/Makefile.in.
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
	@echo "Installing package opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.0 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/msgcat-1.7.0.tm;
	@echo "Installing package tcltest 2.5.1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/tcltest-2.5.1.tm;
	@echo "Installing package platform 1.0.14 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/platform-1.0.14.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/platform/shell-1.1.4.tm;
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \







|
|







873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
	@echo "Installing package opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; \
	    do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.0 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/msgcat-1.7.0.tm;
	@echo "Installing package tcltest 2.5.2 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/tcltest-2.5.2.tm;
	@echo "Installing package platform 1.0.14 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/platform-1.0.14.tm;
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl $(SCRIPT_INSTALL_DIR)/../tcl9/9.0/platform/shell-1.1.4.tm;
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \