Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | [Bug #1536227]: Cygwin network pathname supoort |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | core-8-5-branch |
Files: | files | file ages | folders |
SHA1: |
b43269edb8904509542c187b2d912742 |
User & Date: | jan.nijtmans 2012-08-08 09:25:29 |
Context
2012-08-13
| ||
22:27 | [Bug 3555454] Rearrange a bit to quash 'declared but never defined' compiler warnings. check-in: 074c6d5d58 user: stwo tags: core-8-5-branch | |
2012-08-08
| ||
10:00 | [Bug #1536227]: Cygwin network pathname supoort check-in: dfd98db64f user: jan.nijtmans tags: trunk | |
09:25 | [Bug #1536227]: Cygwin network pathname supoort check-in: b43269edb8 user: jan.nijtmans tags: core-8-5-branch | |
2012-08-07
| ||
15:23 | 3554250 Overlooked one field of cleanup in the thread exit handler for the filesystem subsystem. check-in: ab38ae2fd5 user: dgp tags: core-8-5-branch | |
Changes
Changes to ChangeLog.
1 2 3 4 5 6 7 | 2012-08-07 Don Porter <[email protected]> * generic/tclIOUtil.c: [Bug 3554250] Overlooked one field of cleanup in the thread exit handler for the filesystem subsystem. 2012-07-31 Jan Nijtmans <[email protected]> | > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 | 2012-08-08 Jan Nijtmans <[email protected]> * generic/tclfileName.c: [Bug #1536227]: Cygwin network pathname * tests/fileName.test: support 2012-08-07 Don Porter <[email protected]> * generic/tclIOUtil.c: [Bug 3554250] Overlooked one field of cleanup in the thread exit handler for the filesystem subsystem. 2012-07-31 Jan Nijtmans <[email protected]> |
︙ | ︙ |
Changes to generic/tclFileName.c.
︙ | ︙ | |||
28 29 30 31 32 33 34 | static const char * DoTildeSubst(Tcl_Interp *interp, const char *user, Tcl_DString *resultPtr); static const char * ExtractWinRoot(const char *path, Tcl_DString *resultPtr, int offset, Tcl_PathType *typePtr); static int SkipToChar(char **stringPtr, int match); | | | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | static const char * DoTildeSubst(Tcl_Interp *interp, const char *user, Tcl_DString *resultPtr); static const char * ExtractWinRoot(const char *path, Tcl_DString *resultPtr, int offset, Tcl_PathType *typePtr); static int SkipToChar(char **stringPtr, int match); static Tcl_Obj * SplitWinPath(const char *path); static Tcl_Obj * SplitUnixPath(const char *path); static int DoGlob(Tcl_Interp *interp, Tcl_Obj *resultPtr, const char *separators, Tcl_Obj *pathPtr, int flags, char *pattern, Tcl_GlobTypeData *types); /* *---------------------------------------------------------------------- * |
︙ | ︙ | |||
195 196 197 198 199 200 201 | SetResultLength(resultPtr, offset, extended); if (path[2] != '/' && path[2] != '\\') { *typePtr = TCL_PATH_VOLUME_RELATIVE; Tcl_DStringAppend(resultPtr, path, 2); return &path[2]; } else { | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | SetResultLength(resultPtr, offset, extended); if (path[2] != '/' && path[2] != '\\') { *typePtr = TCL_PATH_VOLUME_RELATIVE; Tcl_DStringAppend(resultPtr, path, 2); return &path[2]; } else { const char *tail = &path[3]; /* * Skip separators. */ while (*tail && (tail[0] == '/' || tail[0] == '\\')) { tail++; |
︙ | ︙ | |||
373 374 375 376 377 378 379 | Tcl_Obj *pathPtr, /* Native path of interest */ int *driveNameLengthPtr, /* Returns length of drive, if non-NULL and * path was absolute */ Tcl_Obj **driveNameRef) { Tcl_PathType type = TCL_PATH_ABSOLUTE; int pathLen; | | | | > > | | | | < | | | | | > > > > > > | > > > < < < < < < < | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 | Tcl_Obj *pathPtr, /* Native path of interest */ int *driveNameLengthPtr, /* Returns length of drive, if non-NULL and * path was absolute */ Tcl_Obj **driveNameRef) { Tcl_PathType type = TCL_PATH_ABSOLUTE; int pathLen; const char *path = Tcl_GetStringFromObj(pathPtr, &pathLen); if (path[0] == '~') { /* * This case is common to all platforms. Paths that begin with ~ are * absolute. */ if (driveNameLengthPtr != NULL) { const char *end = path + 1; while ((*end != '\0') && (*end != '/')) { end++; } *driveNameLengthPtr = end - path; } } else { switch (tclPlatform) { case TCL_PLATFORM_UNIX: { const char *origPath = path; /* * Paths that begin with / are absolute. */ if (path[0] == '/') { ++path; #if defined(__CYGWIN__) || defined(__QNX__) /* * Check for "//" network path prefix */ if ((*path == '/') && path[1] && (path[1] != '/')) { path += 2; while (*path && *path != '/') { ++path; } #if defined(__CYGWIN__) /* UNC paths need to be followed by a share name */ if (*path++ && (*path && *path != '/')) { ++path; while (*path && *path != '/') { ++path; } } else { path = origPath + 1; } #endif } #endif if (driveNameLengthPtr != NULL) { /* * We need this addition in case the QNX or Cygwin code was used. */ *driveNameLengthPtr = (path - origPath); } } else { type = TCL_PATH_RELATIVE; } break; } case TCL_PLATFORM_WINDOWS: { |
︙ | ︙ | |||
542 543 544 545 546 547 548 | * number of elements in the path. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ Tcl_Obj *tmpPtr, *eltPtr; int i, size, len; | | > | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | * number of elements in the path. */ const char ***argvPtr) /* Pointer to place to store pointer to array * of pointers to path elements. */ { Tcl_Obj *resultPtr = NULL; /* Needed only to prevent gcc warnings. */ Tcl_Obj *tmpPtr, *eltPtr; int i, size, len; char *p; const char *str; /* * Perform the splitting, using objectified, vfs-aware code. */ tmpPtr = Tcl_NewStringObj(path, -1); Tcl_IncrRefCount(tmpPtr); |
︙ | ︙ | |||
627 628 629 630 631 632 633 | */ static Tcl_Obj * SplitUnixPath( const char *path) /* Pointer to string containing a path. */ { int length; | | > > > | | | | | < | | | | > > > > > > | > > > | < | | < < < < < > | < | < < | | | | | | | 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 | */ static Tcl_Obj * SplitUnixPath( const char *path) /* Pointer to string containing a path. */ { int length; const char *origPath = path, *elementStart; Tcl_Obj *result = Tcl_NewObj(); /* * Deal with the root directory as a special case. */ if (*path == '/') { Tcl_Obj *rootElt; ++path; #if defined(__CYGWIN__) || defined(__QNX__) /* * Check for "//" network path prefix */ if ((*path == '/') && path[1] && (path[1] != '/')) { path += 2; while (*path && *path != '/') { ++path; } #if defined(__CYGWIN__) /* UNC paths need to be followed by a share name */ if (*path++ && (*path && *path != '/')) { ++path; while (*path && *path != '/') { ++path; } } else { path = origPath + 1; } #endif } #endif rootElt = Tcl_NewStringObj(origPath, path - origPath); Tcl_ListObjAppendElement(NULL, result, rootElt); while (*path == '/') { ++path; } } /* * Split on slashes. Embedded elements that start with tilde will be * prefixed with "./" so they are not affected by tilde substitution. */ for (;;) { elementStart = path; while ((*path != '\0') && (*path != '/')) { path++; } length = path - elementStart; if (length > 0) { Tcl_Obj *nextElt; if ((elementStart[0] == '~') && (elementStart != origPath)) { TclNewLiteralStringObj(nextElt, "./"); Tcl_AppendToObj(nextElt, elementStart, length); } else { nextElt = Tcl_NewStringObj(elementStart, length); } Tcl_ListObjAppendElement(NULL, result, nextElt); } if (*path++ == '\0') { break; } } return result; } /* |
︙ | ︙ | |||
839 840 841 842 843 844 845 846 | void TclpNativeJoinPath( Tcl_Obj *prefix, const char *joining) { int length, needsSep; const char *p; | > | | 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | void TclpNativeJoinPath( Tcl_Obj *prefix, const char *joining) { int length, needsSep; char *dest; const char *p; const char *start; start = Tcl_GetStringFromObj(prefix, &length); /* * Remove the ./ from tilde prefixed elements, and drive-letter prefixed * elements on Windows, unless it is the first component. */ |
︙ | ︙ | |||
964 965 966 967 968 969 970 | int argc, const char *const *argv, Tcl_DString *resultPtr) /* Pointer to previously initialized DString */ { int i, len; Tcl_Obj *listObj = Tcl_NewObj(); Tcl_Obj *resultObj; | | | 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | int argc, const char *const *argv, Tcl_DString *resultPtr) /* Pointer to previously initialized DString */ { int i, len; Tcl_Obj *listObj = Tcl_NewObj(); Tcl_Obj *resultObj; const char *resultStr; /* * Build the list of paths. */ for (i = 0; i < argc; i++) { Tcl_ListObjAppendElement(NULL, listObj, |
︙ | ︙ | |||
1334 1335 1336 1337 1338 1339 1340 | case TCL_PLATFORM_WINDOWS: separators = "/\\:"; break; } if (dir == PATH_GENERAL) { int pathlength; | | | | 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 | case TCL_PLATFORM_WINDOWS: separators = "/\\:"; break; } if (dir == PATH_GENERAL) { int pathlength; const char *last; const char *first = Tcl_GetStringFromObj(pathOrDir,&pathlength); /* * Find the last path separator in the path */ last = first + pathlength; for (; last != first; last--) { |
︙ | ︙ | |||
1436 1437 1438 1439 1440 1441 1442 | globTypes->type = 0; globTypes->perm = 0; globTypes->macType = NULL; globTypes->macCreator = NULL; while (--length >= 0) { int len; | | | 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 | globTypes->type = 0; globTypes->perm = 0; globTypes->macType = NULL; globTypes->macCreator = NULL; while (--length >= 0) { int len; const char *str; Tcl_ListObjIndex(interp, typePtr, length, &look); str = Tcl_GetStringFromObj(look, &len); if (strcmp("readonly", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_RONLY; } else if (strcmp("hidden", str) == 0) { globTypes->perm |= TCL_GLOB_PERM_HIDDEN; |
︙ | ︙ | |||
1492 1493 1494 1495 1496 1497 1498 | if (globTypes->macType != NULL) { goto badMacTypesArg; } globTypes->macType = look; Tcl_IncrRefCount(look); } else { | | | | | 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 | if (globTypes->macType != NULL) { goto badMacTypesArg; } globTypes->macType = look; Tcl_IncrRefCount(look); } else { Tcl_Obj *item; if ((Tcl_ListObjLength(NULL, look, &len) == TCL_OK) && (len == 3)) { Tcl_ListObjIndex(interp, look, 0, &item); if (!strcmp("macintosh", Tcl_GetString(item))) { Tcl_ListObjIndex(interp, look, 1, &item); if (!strcmp("type", Tcl_GetString(item))) { Tcl_ListObjIndex(interp, look, 2, &item); if (globTypes->macType != NULL) { goto badMacTypesArg; |
︙ | ︙ | |||
1827 1828 1829 1830 1831 1832 1833 | return TCL_ERROR; } pathPrefix = Tcl_NewStringObj(Tcl_GetString(cwd), 3); Tcl_DecrRefCount(cwd); if (tail[0] == '/') { tail++; } else { | | | 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 | return TCL_ERROR; } pathPrefix = Tcl_NewStringObj(Tcl_GetString(cwd), 3); Tcl_DecrRefCount(cwd); if (tail[0] == '/') { tail++; } else { tail += 2; } Tcl_IncrRefCount(pathPrefix); break; } case TCL_PATH_ABSOLUTE: /* * Absolute, possibly network path //Machine/Share. Use that |
︙ | ︙ | |||
1898 1899 1900 1901 1902 1903 1904 | /* * Now we do the actual globbing, adding filenames as we go to buffer in * filenamesObj */ if (*tail == '\0' && pathPrefix != NULL) { /* | | | < > | | | | | > | > | 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 | /* * Now we do the actual globbing, adding filenames as we go to buffer in * filenamesObj */ if (*tail == '\0' && pathPrefix != NULL) { /* * An empty pattern. This means 'pathPrefix' is actually a full path * of a file/directory we want to simply check for existence and type. */ if (types == NULL) { /* * We just want to check for existence. In this case we make it * easy on Tcl_FSMatchInDirectory and its sub-implementations by * not bothering them (even though they should support this * situation) and we just use the simple existence check with * Tcl_FSAccess. */ if (Tcl_FSAccess(pathPrefix, F_OK) == 0) { Tcl_ListObjAppendElement(interp, filenamesObj, pathPrefix); } result = TCL_OK; } else { /* * We want to check for the correct type. Tcl_FSMatchInDirectory * is documented to do this for us, if we give it a NULL pattern. */ result = Tcl_FSMatchInDirectory(interp, filenamesObj, pathPrefix, NULL, types); } } else { result = DoGlob(interp, filenamesObj, separators, pathPrefix, globFlags & TCL_GLOBMODE_DIR, tail, types); } |
︙ | ︙ | |||
1983 1984 1985 1986 1987 1988 1989 | prefixLen++; } } Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv); for (i = 0; i< objc; i++) { int len; | | | | | | | | 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 | prefixLen++; } } Tcl_ListObjGetElements(NULL, filenamesObj, &objc, &objv); for (i = 0; i< objc; i++) { int len; const char *oldStr = Tcl_GetStringFromObj(objv[i], &len); Tcl_Obj *elem; if (len == prefixLen) { if ((pattern[0] == '\0') || (strchr(separators, pattern[0]) == NULL)) { TclNewLiteralStringObj(elem, "."); } else { TclNewLiteralStringObj(elem, "/"); } } else { elem = Tcl_NewStringObj(oldStr+prefixLen, len-prefixLen); } Tcl_ListObjReplace(interp, filenamesObj, i, 1, 1, &elem); } } /* * Now we have a list of discovered filenames in filenamesObj and a list * of previously discovered (saved earlier from the interpreter result) in * savedResultObj. Merge them and put them back in the interpreter result. |
︙ | ︙ | |||
2111 2112 2113 2114 2115 2116 2117 | DoGlob( Tcl_Interp *interp, /* Interpreter to use for error reporting * (e.g. unmatched brace). */ Tcl_Obj *matchesObj, /* Unshared list object in which to place all * resulting filenames. Caller allocates and * deallocates; DoGlob must not touch the * refCount of this object. */ | | | 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 | DoGlob( Tcl_Interp *interp, /* Interpreter to use for error reporting * (e.g. unmatched brace). */ Tcl_Obj *matchesObj, /* Unshared list object in which to place all * resulting filenames. Caller allocates and * deallocates; DoGlob must not touch the * refCount of this object. */ const char *separators, /* String containing separator characters that * should be used to identify globbing * boundaries. */ Tcl_Obj *pathPtr, /* Completely expanded prefix. */ int flags, /* If non-zero then pathPtr is a directory */ char *pattern, /* The pattern to match against. Must not be a * pointer to a static string. */ Tcl_GlobTypeData *types) /* List object containing list of acceptable |
︙ | ︙ | |||
2154 2155 2156 2157 2158 2159 2160 | } } else if (strchr(separators, *pattern) == NULL) { break; } count++; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 | } } else if (strchr(separators, *pattern) == NULL) { break; } count++; } /* * Look for the first matching pair of braces or the first directory * separator that is not inside a pair of braces. */ openBrace = closeBrace = NULL; quoted = 0; |
︙ | ︙ | |||
2269 2270 2271 2272 2273 2274 2275 | /* * Substitute the alternate patterns from the braces and recurse. */ if (openBrace != NULL) { char *element; | < > | 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 | /* * Substitute the alternate patterns from the braces and recurse. */ if (openBrace != NULL) { char *element; Tcl_DString newName; Tcl_DStringInit(&newName); /* * For each element within in the outermost pair of braces, append the * element and the remainder to the fixed portion before the first * brace and recursively call DoGlob. */ |
︙ | ︙ | |||
2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 | * Alternatively, if there are no globbing characters then again there are * two cases. If we're at the end of the string, we just need to check for * the given path's existence and type. If we're not at the end of the * string, we recurse. */ if (*p != '\0') { /* * Note that we are modifying the string in place. This won't work if * the string is a static. */ | > > < | | 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 | * Alternatively, if there are no globbing characters then again there are * two cases. If we're at the end of the string, we just need to check for * the given path's existence and type. If we're not at the end of the * string, we recurse. */ if (*p != '\0') { char savedChar = *p; /* * Note that we are modifying the string in place. This won't work if * the string is a static. */ *p = '\0'; firstSpecialChar = strpbrk(pattern, "*[]?\\"); *p = savedChar; } else { firstSpecialChar = strpbrk(pattern, "*[]?\\"); } if (firstSpecialChar != NULL) { /* * Look for matching files in the given directory. The implementation * of this function is filesystem specific. For each file that * matches, it will add the match onto the resultPtr given. */ static Tcl_GlobTypeData dirOnly = { TCL_GLOB_TYPE_DIR, 0, NULL, NULL }; char save = *p; Tcl_Obj *subdirsPtr; if (*p == '\0') { return Tcl_FSMatchInDirectory(interp, matchesObj, pathPtr, pattern, types); } /* |
︙ | ︙ | |||
2389 2390 2391 2392 2393 2394 2395 2396 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 | Tcl_DecrRefCount(subdirv[i]); subdirv[i] = copy; Tcl_ListObjLength(NULL, matchesObj, &end); while (repair < end) { const char *bytes; int numBytes; Tcl_Obj *fixme, *newObj; Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme); bytes = Tcl_GetStringFromObj(fixme, &numBytes); newObj = Tcl_NewStringObj(bytes+2, numBytes-2); Tcl_ListObjReplace(NULL, matchesObj, repair, 1, 1, &newObj); repair++; } repair = -1; } } } TclDecrRefCount(subdirsPtr); return result; } /* * We reach here with no pattern char in current section */ if (*p == '\0') { /* * This is the code path reached by a command like 'glob foo'. * * There are no more wildcards in the pattern and no more unprocessed * characters in the pattern, so now we can construct the path, and * pass it to Tcl_FSMatchInDirectory with an empty pattern to verify * the existence of the file and check it is of the correct type (if a * 'types' flag it given -- if no such flag was given, we could just * use 'Tcl_FSLStat', but for simplicity we keep to a common * approach). */ | > > > > < < < | 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 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 2382 2383 2384 2385 2386 2387 2388 | Tcl_DecrRefCount(subdirv[i]); subdirv[i] = copy; Tcl_ListObjLength(NULL, matchesObj, &end); while (repair < end) { const char *bytes; int numBytes; Tcl_Obj *fixme, *newObj; Tcl_ListObjIndex(NULL, matchesObj, repair, &fixme); bytes = Tcl_GetStringFromObj(fixme, &numBytes); newObj = Tcl_NewStringObj(bytes+2, numBytes-2); Tcl_ListObjReplace(NULL, matchesObj, repair, 1, 1, &newObj); repair++; } repair = -1; } } } TclDecrRefCount(subdirsPtr); return result; } /* * We reach here with no pattern char in current section */ if (*p == '\0') { int length; Tcl_DString append; /* * This is the code path reached by a command like 'glob foo'. * * There are no more wildcards in the pattern and no more unprocessed * characters in the pattern, so now we can construct the path, and * pass it to Tcl_FSMatchInDirectory with an empty pattern to verify * the existence of the file and check it is of the correct type (if a * 'types' flag it given -- if no such flag was given, we could just * use 'Tcl_FSLStat', but for simplicity we keep to a common * approach). */ Tcl_DStringInit(&append); Tcl_DStringAppend(&append, pattern, p-pattern); if (pathPtr != NULL) { (void) Tcl_GetStringFromObj(pathPtr, &length); } else { length = 0; |
︙ | ︙ |
Changes to tests/fileName.test.
︙ | ︙ | |||
185 186 187 188 189 190 191 | test filename-4.12 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split ../.. } {.. ..} test filename-4.13 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split //foo | | | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | test filename-4.12 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split ../.. } {.. ..} test filename-4.13 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split //foo } "/ foo" test filename-4.14 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split foo//bar } {foo bar} test filename-4.15 {Tcl_SplitPath: unix} {testsetplatform} { testsetplatform unix file split ~foo |
︙ | ︙ | |||
425 426 427 428 429 430 431 | test filename-7.16 {Tcl_JoinPath: unix} {testsetplatform} { testsetplatform unix file join a . ./~b } {a/./~b} test filename-7.17 {Tcl_JoinPath: unix} {testsetplatform} { testsetplatform unix file join //a b | | | | 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 | test filename-7.16 {Tcl_JoinPath: unix} {testsetplatform} { testsetplatform unix file join a . ./~b } {a/./~b} test filename-7.17 {Tcl_JoinPath: unix} {testsetplatform} { testsetplatform unix file join //a b } "/a/b" test filename-7.18 {Tcl_JoinPath: unix} {testsetplatform} { testsetplatform unix file join /// a b } "/a/b" test filename-9.1 {Tcl_JoinPath: win} {testsetplatform} { testsetplatform win file join a b } {a/b} test filename-9.2 {Tcl_JoinPath: win} {testsetplatform} { |
︙ | ︙ |