Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | generic: reduced diffs to trunk, win: clean code after bug [f00009f7ce] was fixed in trunk |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | mistake |
Files: | files | file ages | folders |
SHA1: |
a31e2a953a3f3f213d0fa2700cce8879 |
User & Date: | sebres 2015-07-31 10:27:01 |
Context
2015-07-31
| ||
10:27 | generic: reduced diffs to trunk, win: clean code after bug [f00009f7ce] was fixed in trunk Closed-Leaf check-in: a31e2a953a user: sebres tags: mistake | |
2015-07-29
| ||
14:54 | [3e7eca8c8c] Prevent overflow in size values passed to allocators. check-in: ee467fed92 user: dgp tags: core-8-5-branch | |
Changes
Changes to generic/tclInt.h.
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | #include "../compat/string.h" #else #include <string.h> #endif #ifdef STDC_HEADERS #include <stddef.h> #else typedef int ptrdiff_t; #endif /* * Ensure WORDS_BIGENDIAN is defined correctly: * Needs to happen here in addition to configure to work with fat compiles on * Darwin (where configure runs only once for multiple architectures). */ | > > | 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #include "../compat/string.h" #else #include <string.h> #endif #ifdef STDC_HEADERS #include <stddef.h> #else #ifndef __BORLANDC__ typedef int ptrdiff_t; #endif #endif /* * Ensure WORDS_BIGENDIAN is defined correctly: * Needs to happen here in addition to configure to work with fat compiles on * Darwin (where configure runs only once for multiple architectures). */ |
︙ | ︙ | |||
739 740 741 742 743 744 745 746 747 748 749 750 751 752 | (TclIsVarInHash(varPtr) \ ? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \ : NULL) #define VarHashRefCount(varPtr) \ ((VarInHash *) (varPtr))->refCount /* * Macros for direct variable access by TEBC. */ #define TclIsVarDirectReadable(varPtr) \ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) | > > > | 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 | (TclIsVarInHash(varPtr) \ ? ((TclVarHashTable *) ((((VarInHash *) (varPtr))->entry.tablePtr)))->nsPtr \ : NULL) #define VarHashRefCount(varPtr) \ ((VarInHash *) (varPtr))->refCount #define VarHashGetKey(varPtr) \ (((VarInHash *)(varPtr))->entry.key.objPtr) /* * Macros for direct variable access by TEBC. */ #define TclIsVarDirectReadable(varPtr) \ ( !((varPtr)->flags & (VAR_ARRAY|VAR_LINK|VAR_TRACED_READ)) \ && (varPtr)->value.objPtr) |
︙ | ︙ | |||
902 903 904 905 906 907 908 909 910 911 912 913 914 915 | Trace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ int reverseScan; /* Boolean set true when traces are scanning * in reverse order. */ } ActiveInterpTrace; /* * Flag values designating types of execution traces. See tclTrace.c for * related flag values. * * TCL_TRACE_ENTER_EXEC - triggers enter/enterstep traces. * - passed to Tcl_CreateObjTrace to set up | > > > > > > > > > > > > > > > > > | 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 | Trace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ int reverseScan; /* Boolean set true when traces are scanning * in reverse order. */ } ActiveInterpTrace; // [SB] - extension of org. ActiveInterpTrace structure // with current return code "code" and current "traceFlags", // used in TclCheckInterpTraces : typedef struct ActiveInterpTraceFull { struct ActiveInterpTrace *nextPtr; /* Next in list of all active command traces * for the interpreter, or NULL if no more. */ Trace *nextTracePtr; /* Next trace to check after current trace * procedure returns; if this trace gets * deleted, must update pointer to avoid using * free'd memory. */ int reverseScan; /* Boolean set true when traces are scanning * in reverse order. */ int code; /* The current result code. */ int traceFlags; /* Current tracing situation. */ } ActiveInterpTraceFull; /* * Flag values designating types of execution traces. See tclTrace.c for * related flag values. * * TCL_TRACE_ENTER_EXEC - triggers enter/enterstep traces. * - passed to Tcl_CreateObjTrace to set up |
︙ | ︙ | |||
2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 | MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsSpaceProc(char byte); MODULE_SCOPE int TclIsBareword(char byte); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *argPtr); MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, int indexCount, Tcl_Obj *const indexArray[]); /* TIP #280 */ | > | 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 | MODULE_SCOPE void TclInitNamespaceSubsystem(void); MODULE_SCOPE void TclInitNotifier(void); MODULE_SCOPE void TclInitObjSubsystem(void); MODULE_SCOPE void TclInitSubsystems(void); MODULE_SCOPE int TclInterpReady(Tcl_Interp *interp); MODULE_SCOPE int TclIsSpaceProc(char byte); MODULE_SCOPE int TclIsBareword(char byte); MODULE_SCOPE Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[]); MODULE_SCOPE int TclJoinThread(Tcl_ThreadId id, int *result); MODULE_SCOPE void TclLimitRemoveAllHandlers(Tcl_Interp *interp); MODULE_SCOPE Tcl_Obj * TclLindexList(Tcl_Interp *interp, Tcl_Obj *listPtr, Tcl_Obj *argPtr); MODULE_SCOPE Tcl_Obj * TclLindexFlat(Tcl_Interp *interp, Tcl_Obj *listPtr, int indexCount, Tcl_Obj *const indexArray[]); /* TIP #280 */ |
︙ | ︙ | |||
3954 3955 3956 3957 3958 3959 3960 | ((limit).granularityTicker % (limit).cmdGranularity == 0))) \ ? 1 : \ (((limit).active & TCL_LIMIT_TIME) && \ (((limit).timeGranularity == 1) || \ ((limit).granularityTicker % (limit).timeGranularity == 0)))\ ? 1 : 0))) | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 | ((limit).granularityTicker % (limit).cmdGranularity == 0))) \ ? 1 : \ (((limit).active & TCL_LIMIT_TIME) && \ (((limit).timeGranularity == 1) || \ ((limit).granularityTicker % (limit).timeGranularity == 0)))\ ? 1 : 0))) /* * [SB] extension * * Following describes the externally-visible facilities * of the Tcl extension. * * Copyright (c) 2010 by Serg G. Brester. All rights reserved. */ // global command resolver extension (used by tclextension) // TODO: check possibility of rewriting this handling to the standard // interpreter command resolver "Interp::resolverPtr" ... typedef Tcl_Command _Ttclex_GlobalCommandResolverGet _ANSI_ARGS_ ((Tcl_Interp *interp, Tcl_Obj *CONST obj)); typedef struct _Ttclex_GlobalCommandResolver { _Ttclex_GlobalCommandResolverGet * getCommand; // reserved, private : struct _Ttclex_GlobalCommandResolver * next; } _Ttclex_GlobalCommandResolver; // namespace published calls : #ifndef BUILD_tcl EXTERN Tcl_ObjCmdProc * tclex_InvokeImportedCmd; EXTERN Tcl_CmdDeleteProc * tclex_DeleteImportedCmd; EXTERN Tcl_ObjCmdProc * tclex_NamespaceInscopeCmd; #endif #include "tclIntDecls.h" #include "tclIntPlatDecls.h" #include "tclTomMathDecls.h" #endif /* _TCLINT */ /* * Local Variables: * mode: c * c-basic-offset: 4 * fill-column: 78 * End: */ |
Changes to generic/tclPathObj.c.
︙ | ︙ | |||
67 68 69 70 71 72 73 | * (ii) flags != 0, => Special path, see TclNewFSPathObj * * Now, this is a path like 'file join $dir $tail' where, cwdPtr is the $dir * and normPathPtr is the $tail. * */ | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | * (ii) flags != 0, => Special path, see TclNewFSPathObj * * Now, this is a path like 'file join $dir $tail' where, cwdPtr is the $dir * and normPathPtr is the $tail. * */ typedef struct { Tcl_Obj *translatedPathPtr; /* Name without any ~user sequences. If this * is NULL, then this is a pure normalized, * absolute path object, in which the parent * Tcl_Obj's string rep is already both * translated and normalized. */ Tcl_Obj *normPathPtr; /* Normalized absolute path, without ., .. or * ~user sequences. If the Tcl_Obj containing |
︙ | ︙ | |||
90 91 92 93 94 95 96 | * below. */ ClientData nativePathPtr; /* Native representation of this path, which * is filesystem dependent. */ int filesystemEpoch; /* Used to ensure the path representation was * generated during the correct filesystem * epoch. The epoch changes when * filesystem-mounts are changed. */ | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | * below. */ ClientData nativePathPtr; /* Native representation of this path, which * is filesystem dependent. */ int filesystemEpoch; /* Used to ensure the path representation was * generated during the correct filesystem * epoch. The epoch changes when * filesystem-mounts are changed. */ Tcl_Filesystem *fsPtr;/* The Tcl_Filesystem that claims this path */ } FsPath; /* * Flag values for FsPath->flags. */ #define TCLPATH_APPENDED 1 |
︙ | ︙ | |||
227 228 229 230 231 232 233 | int curLen; if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } | | | | | | | > | | | | | | | | 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | int curLen; if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } dirSep += 2; oldDirSep = dirSep; if (dirSep[0] != 0 && dirSep[1] == '.') { goto again; } continue; } if (dirSep[2] == '.' && IsSeparatorOrNull(dirSep[3])) { Tcl_Obj *linkObj; int curLen; char *linkStr; /* * Have '..' so need to skip previous directory. */ if (retVal == NULL) { const char *path = TclGetString(pathPtr); retVal = Tcl_NewStringObj(path, dirSep - path); Tcl_IncrRefCount(retVal); } Tcl_GetStringFromObj(retVal, &curLen); if (curLen == 0) { Tcl_AppendToObj(retVal, dirSep, 1); } if (!first || (tclPlatform == TCL_PLATFORM_UNIX)) { linkObj = Tcl_FSLink(retVal, NULL, 0); /* Safety check in case driver caused sharing */ if (Tcl_IsShared(retVal)) { TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(retVal); Tcl_IncrRefCount(retVal); } if (linkObj != NULL) { /* * Got a link. Need to check if the link is relative * or absolute, for those platforms where relative * links exist. */ if (tclPlatform != TCL_PLATFORM_WINDOWS && Tcl_FSGetPathType(linkObj) == TCL_PATH_RELATIVE) { /* * We need to follow this link which is relative * to retVal's directory. This means concatenating * the link onto the directory of the path so far. */ const char *path = Tcl_GetStringFromObj(retVal, &curLen); while (--curLen >= 0) { if (IsSeparatorOrNull(path[curLen])) { break; } } /* * We want the trailing slash. */ Tcl_SetObjLength(retVal, curLen+1); Tcl_AppendObjToObj(retVal, linkObj); TclDecrRefCount(linkObj); linkStr = Tcl_GetStringFromObj(retVal, &curLen); } else { /* * Absolute link. */ TclDecrRefCount(retVal); if (Tcl_IsShared(linkObj)) { retVal = Tcl_DuplicateObj(linkObj); TclDecrRefCount(linkObj); } else { retVal = linkObj; } linkStr = Tcl_GetStringFromObj(retVal, &curLen); /* * Convert to forward-slashes on windows. */ |
︙ | ︙ | |||
332 333 334 335 336 337 338 | } } } else { linkStr = Tcl_GetStringFromObj(retVal, &curLen); } /* | | | | 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | } } } else { linkStr = Tcl_GetStringFromObj(retVal, &curLen); } /* * Either way, we now remove the last path element (but * not the first character of the path). */ while (--curLen >= 0) { if (IsSeparatorOrNull(linkStr[curLen])) { if (curLen) { Tcl_SetObjLength(retVal, curLen); } else { |
︙ | ︙ | |||
394 395 396 397 398 399 400 | TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(pathPtr); Tcl_IncrRefCount(retVal); } } /* | | | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | TclDecrRefCount(retVal); retVal = Tcl_DuplicateObj(pathPtr); Tcl_IncrRefCount(retVal); } } /* * Ensure a windows drive like C:/ has a trailing separator. */ if (tclPlatform == TCL_PLATFORM_WINDOWS) { int len; const char *path = Tcl_GetStringFromObj(retVal, &len); if (len == 2 && path[0] != 0 && path[1] == ':') { |
︙ | ︙ | |||
507 508 509 510 511 512 513 | if (fsPathPtr->cwdPtr == NULL) { return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); } if (PATHFLAGS(pathPtr) == 0) { /* The path is not absolute... */ | | | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | if (fsPathPtr->cwdPtr == NULL) { return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); } if (PATHFLAGS(pathPtr) == 0) { /* The path is not absolute... */ #ifdef _WIN32 /* ... on Windows we must make another call to determine whether * it's relative or volumerelative [Bug 2571597]. */ return TclGetPathType(pathPtr, filesystemPtrPtr, driveNameLengthPtr, NULL); #else /* On other systems, quickly deduce !absolute -> relative */ return TCL_PATH_RELATIVE; |
︙ | ︙ | |||
823 824 825 826 827 828 829 | Tcl_Obj * Tcl_FSJoinPath( Tcl_Obj *listObj, /* Path elements to join, may have a zero * reference count. */ int elements) /* Number of elements to use (-1 = all) */ { | | | | < | | | < < < < < | > | > > | | < < > > | < > | | | > | < < < | | | > | | < | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 | Tcl_Obj * Tcl_FSJoinPath( Tcl_Obj *listObj, /* Path elements to join, may have a zero * reference count. */ int elements) /* Number of elements to use (-1 = all) */ { Tcl_Obj *copy, *res; int objc; Tcl_Obj **objv; if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) { return NULL; } elements = ((elements >= 0) && (elements <= objc)) ? elements : objc; copy = TclListObjCopy(NULL, listObj); Tcl_ListObjGetElements(NULL, listObj, &objc, &objv); res = TclJoinPath(elements, objv); Tcl_DecrRefCount(copy); return res; } Tcl_Obj * TclJoinPath( int elements, Tcl_Obj * const objv[]) { Tcl_Obj *res; int i; Tcl_Filesystem *fsPtr = NULL; res = NULL; for (i = 0; i < elements; i++) { int driveNameLength, strEltLen, length; Tcl_PathType type; char *strElt, *ptr; Tcl_Obj *driveName = NULL; Tcl_Obj *elt = objv[i]; /* * This is a special case where we can be much more efficient, where * we are joining a single relative path onto an object that is * already of path type. The 'TclNewFSPathObj' call below creates an * object which can be normalized more efficiently. Currently we only * use the special case when we have exactly two elements, but we * could expand that in the future. */ if ((i == (elements-2)) && (i == 0) && (elt->typePtr == &tclFsPathType) && !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))) { Tcl_Obj *tailObj = objv[i+1]; type = TclGetPathType(tailObj, NULL, NULL, NULL); if (type == TCL_PATH_RELATIVE) { const char *str; int len; str = Tcl_GetStringFromObj(tailObj, &len); if (len == 0) { /* * This happens if we try to handle the root volume '/'. * There's no need to return a special path object, when * the base itself is just fine! */ |
︙ | ︙ | |||
929 930 931 932 933 934 935 | * Otherwise we don't have an easy join, and we must let the * more general code below handle things. */ } else if (tclPlatform == TCL_PLATFORM_UNIX) { if (res != NULL) { TclDecrRefCount(res); } | | | | | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 | * Otherwise we don't have an easy join, and we must let the * more general code below handle things. */ } else if (tclPlatform == TCL_PLATFORM_UNIX) { if (res != NULL) { TclDecrRefCount(res); } return tailObj; } else { const char *str = TclGetString(tailObj); if (tclPlatform == TCL_PLATFORM_WINDOWS) { if (strchr(str, '\\') == NULL) { if (res != NULL) { TclDecrRefCount(res); } return tailObj; } } } } strElt = Tcl_GetStringFromObj(elt, &strEltLen); type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName); if (type != TCL_PATH_RELATIVE) { |
︙ | ︙ | |||
1015 1016 1017 1018 1019 1020 1021 | ptr++; } if (res != NULL) { TclDecrRefCount(res); } /* | | | | 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 | ptr++; } if (res != NULL) { TclDecrRefCount(res); } /* * This element is just what we want to return already; no further * manipulation is requred. */ return elt; } /* * The path element was not of a suitable form to be returned as is. |
︙ | ︙ | |||
1062 1063 1064 1065 1066 1067 1068 | if (fsPtr == &tclNativeFilesystem || fsPtr == NULL) { TclpNativeJoinPath(res, strElt); } else { char separator = '/'; int needsSep = 0; if (fsPtr->filesystemSeparatorProc != NULL) { | | | 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 | if (fsPtr == &tclNativeFilesystem || fsPtr == NULL) { TclpNativeJoinPath(res, strElt); } else { char separator = '/'; int needsSep = 0; if (fsPtr->filesystemSeparatorProc != NULL) { Tcl_Obj *sep = fsPtr->filesystemSeparatorProc(res); if (sep != NULL) { separator = TclGetString(sep)[0]; } /* Safety check in case the VFS driver caused sharing */ if (Tcl_IsShared(res)) { TclDecrRefCount(res); |
︙ | ︙ | |||
1156 1157 1158 1159 1160 1161 1162 | if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); } | | | 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 | if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); } return SetFsPathFromAny(interp, pathPtr); /* * We used to have more complex code here: * * FsPath *fsPathPtr = PATHOBJ(pathPtr); * if (fsPathPtr->cwdPtr == NULL || PATHFLAGS(pathPtr) != 0) { * return TCL_OK; |
︙ | ︙ | |||
1315 1316 1317 1318 1319 1320 1321 | PATHFLAGS(pathPtr) = TCLPATH_APPENDED; pathPtr->typePtr = &tclFsPathType; pathPtr->bytes = NULL; pathPtr->length = 0; /* * Look for path components made up of only "." | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 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 | PATHFLAGS(pathPtr) = TCLPATH_APPENDED; pathPtr->typePtr = &tclFsPathType; pathPtr->bytes = NULL; pathPtr->length = 0; /* * Look for path components made up of only "." * This is overly conservative analysis to keep simple. It may mark some * things as needing more aggressive normalization that don't actually * need it. No harm done. */ for (p = addStrRep; len > 0; p++, len--) { switch (state) { case 0: /* So far only "." since last dirsep or start */ switch (*p) { case '.': count++; break; case '/': case '\\': case ':': if (count) { PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM; len = 0; } break; default: count = 0; state = 1; } case 1: /* Scanning for next dirsep */ switch (*p) { case '/': case '\\': case ':': state = 0; break; } } } if (len == 0 && count) { PATHFLAGS(pathPtr) |= TCLPATH_NEEDNORM; } return pathPtr; } static Tcl_Obj * AppendPath( Tcl_Obj *head, Tcl_Obj *tail) { int numBytes; const char *bytes; Tcl_Obj *copy = Tcl_DuplicateObj(head); /* * This is likely buggy when dealing with virtual filesystem drivers * that use some character other than "/" as a path separator. I know * of no evidence that such a foolish thing exists. This solution was * chosen so that "JoinPath" operations that pass through either path * intrep produce the same results; that is, bugward compatibility. If * we need to fix that bug here, it needs fixing in TclJoinPath() too. */ bytes = Tcl_GetStringFromObj(tail, &numBytes); if (numBytes == 0) { Tcl_AppendToObj(copy, "/", 1); } else { TclpNativeJoinPath(copy, bytes); } |
︙ | ︙ | |||
1415 1416 1417 1418 1419 1420 1421 | { int cwdLen, len; const char *tempStr; if (pathPtr->typePtr == &tclFsPathType) { FsPath *fsPathPtr = PATHOBJ(pathPtr); | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 | { int cwdLen, len; const char *tempStr; if (pathPtr->typePtr == &tclFsPathType) { FsPath *fsPathPtr = PATHOBJ(pathPtr); if (PATHFLAGS(pathPtr) != 0 && fsPathPtr->cwdPtr == cwdPtr) { return fsPathPtr->normPathPtr; } } /* * We know the cwd is a normalised object which does not end in a * directory delimiter, unless the cwd is the name of a volume, in which * case it will end in a delimiter! We handle this situation here. A |
︙ | ︙ | |||
1556 1557 1558 1559 1560 1561 1562 | * Free old representation */ if (pathPtr->typePtr != NULL) { if (pathPtr->bytes == NULL) { if (pathPtr->typePtr->updateStringProc == NULL) { if (interp != NULL) { | | | > | | 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 | * Free old representation */ if (pathPtr->typePtr != NULL) { if (pathPtr->bytes == NULL) { if (pathPtr->typePtr->updateStringProc == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "can't find object string representation", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "WTF", NULL); } return TCL_ERROR; } pathPtr->typePtr->updateStringProc(pathPtr); } TclFreeIntRep(pathPtr); } |
︙ | ︙ | |||
1717 1718 1719 1720 1721 1722 1723 | Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp, srcFsPathPtr->cwdPtr); if (translatedCwdPtr == NULL) { return NULL; } retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1, | | | 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 | Tcl_Obj *translatedCwdPtr = Tcl_FSGetTranslatedPath(interp, srcFsPathPtr->cwdPtr); if (translatedCwdPtr == NULL) { return NULL; } retObj = Tcl_FSJoinToPath(translatedCwdPtr, 1, &srcFsPathPtr->normPathPtr); srcFsPathPtr->translatedPathPtr = retObj; if (translatedCwdPtr->typePtr == &tclFsPathType) { srcFsPathPtr->filesystemEpoch = PATHOBJ(translatedCwdPtr)->filesystemEpoch; } else { srcFsPathPtr->filesystemEpoch = 0; } |
︙ | ︙ | |||
1859 1860 1861 1862 1863 1864 1865 | (void) Tcl_GetStringFromObj(dir, &cwdLen); cwdLen += (Tcl_GetString(copy)[cwdLen] == '/'); /* Normalize the combined string. */ if (PATHFLAGS(pathPtr) & TCLPATH_NEEDNORM) { /* | | | | | > | | | | | | | < | | | | | 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 | (void) Tcl_GetStringFromObj(dir, &cwdLen); cwdLen += (Tcl_GetString(copy)[cwdLen] == '/'); /* Normalize the combined string. */ if (PATHFLAGS(pathPtr) & TCLPATH_NEEDNORM) { /* * If the "tail" part has components (like /../) that cause the * combined path to need more complete normalizing, call on the * more powerful routine to accomplish that so we avoid [Bug * 2385549] ... */ Tcl_Obj *newCopy = TclFSNormalizeAbsolutePath(interp, copy); Tcl_DecrRefCount(copy); copy = newCopy; } else { /* * ... but in most cases where we join a trouble free tail to a * normalized head, we can more efficiently normalize the combined * path by passing over only the unnormalized tail portion. When * this is sufficient, prior developers claim this should be much * faster. We use 'cwdLen-1' so that we are already pointing at * the dir-separator that we know about. The normalization code * will actually start off directly after that separator. */ TclFSNormalizeToUniquePath(interp, copy, cwdLen-1); } /* Now we need to construct the new path object. */ if (pathType == TCL_PATH_RELATIVE) { Tcl_Obj *origDir = fsPathPtr->cwdPtr; /* * NOTE: here we are (dangerously?) assuming that origDir points * to a Tcl_Obj with Tcl_ObjType == &tclFsPathType. The * pathType = Tcl_FSGetPathType(fsPathPtr->cwdPtr); * above that set the pathType value should have established that, * but it's far less clear on what basis we know there's been no * shimmering since then. */ FsPath *origDirFsPathPtr = PATHOBJ(origDir); fsPathPtr->cwdPtr = origDirFsPathPtr->cwdPtr; Tcl_IncrRefCount(fsPathPtr->cwdPtr); |
︙ | ︙ | |||
1936 1937 1938 1939 1940 1941 1942 | if (fsPathPtr->cwdPtr != NULL) { if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) { if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); | | | 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 | if (fsPathPtr->cwdPtr != NULL) { if (!TclFSCwdPointerEquals(&fsPathPtr->cwdPtr)) { if (pathPtr->bytes == NULL) { UpdateStringOfFsPath(pathPtr); } FreeFsPathInternalRep(pathPtr); if (SetFsPathFromAny(interp, pathPtr) != TCL_OK) { return NULL; } fsPathPtr = PATHOBJ(pathPtr); } else if (fsPathPtr->normPathPtr == NULL) { int cwdLen; Tcl_Obj *copy; |
︙ | ︙ | |||
1982 1983 1984 1985 1986 1987 1988 | * we're asking Tcl_FSGetPathType to return the path's type, but that * call can actually result in a lot of other filesystem action, which * might loop back through here. */ if (path[0] == '\0') { /* | | | | | | | 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 | * we're asking Tcl_FSGetPathType to return the path's type, but that * call can actually result in a lot of other filesystem action, which * might loop back through here. */ if (path[0] == '\0') { /* * Special handling for the empty string value. This one is very * weird with [file normalize {}] => {}. (The reasoning supporting * this is unknown to DGP, but he fears changing it.) Attempt here * to keep the expectations of other parts of Tcl_Filesystem code * about state of the FsPath fields satisfied. * * In particular, capture the cwd value and save so it can be * stored in the cwdPtr field below. */ useThisCwd = Tcl_FSGetCwd(interp); } else { |
︙ | ︙ | |||
2019 2020 2021 2022 2023 2024 2025 | Tcl_DecrRefCount(absolutePath); absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath); Tcl_IncrRefCount(absolutePath); /* * We have a refCount on the cwd. */ | | | > > | | > > | 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 | Tcl_DecrRefCount(absolutePath); absolutePath = Tcl_FSJoinToPath(useThisCwd, 1, &absolutePath); Tcl_IncrRefCount(absolutePath); /* * We have a refCount on the cwd. */ #ifdef _WIN32 } else if (type == TCL_PATH_VOLUME_RELATIVE) { /* * Only Windows has volume-relative paths. */ Tcl_DecrRefCount(absolutePath); absolutePath = TclWinVolumeRelativeNormalize(interp, path, &useThisCwd); if (absolutePath == NULL) { return NULL; } pureNormalized = 0; #endif /* _WIN32 */ } } /* * Already has refCount incremented. */ fsPathPtr->normPathPtr = TclFSNormalizeAbsolutePath(interp, absolutePath); /* * Check if path is pure normalized (this can only be the case if it * is an absolute path). */ if (pureNormalized) { int normPathLen, pathLen; const char *normPath; path = TclGetStringFromObj(pathPtr, &pathLen); normPath = TclGetStringFromObj(fsPathPtr->normPathPtr, &normPathLen); if ((pathLen == normPathLen) && !memcmp(path, normPath, pathLen)) { /* * The path was already normalized. Get rid of the duplicate. */ TclDecrRefCount(fsPathPtr->normPathPtr); /* |
︙ | ︙ | |||
2178 2179 2180 2181 2182 2183 2184 | char *nativePathPtr; proc = srcFsPathPtr->fsPtr->createInternalRepProc; if (proc == NULL) { return NULL; } | | | 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 | char *nativePathPtr; proc = srcFsPathPtr->fsPtr->createInternalRepProc; if (proc == NULL) { return NULL; } nativePathPtr = proc(pathPtr); srcFsPathPtr = PATHOBJ(pathPtr); srcFsPathPtr->nativePathPtr = nativePathPtr; } return srcFsPathPtr->nativePathPtr; } |
︙ | ︙ | |||
2319 2320 2321 2322 2323 2324 2325 | if (firstPtr == secondPtr) { return 1; } if (firstPtr == NULL || secondPtr == NULL) { return 0; } | | | | | | | | 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 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 | if (firstPtr == secondPtr) { return 1; } if (firstPtr == NULL || secondPtr == NULL) { return 0; } firstStr = TclGetStringFromObj(firstPtr, &firstLen); secondStr = TclGetStringFromObj(secondPtr, &secondLen); if ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)) { return 1; } /* * Try the most thorough, correct method of comparing fully normalized * paths. */ tempErrno = Tcl_GetErrno(); firstPtr = Tcl_FSGetNormalizedPath(NULL, firstPtr); secondPtr = Tcl_FSGetNormalizedPath(NULL, secondPtr); Tcl_SetErrno(tempErrno); if (firstPtr == NULL || secondPtr == NULL) { return 0; } firstStr = TclGetStringFromObj(firstPtr, &firstLen); secondStr = TclGetStringFromObj(secondPtr, &secondLen); return ((firstLen == secondLen) && !memcmp(firstStr, secondStr, firstLen)); } /* *--------------------------------------------------------------------------- * * SetFsPathFromAny -- * |
︙ | ︙ | |||
2432 2433 2434 2435 2436 2437 2438 | if (split != len) { name[split] = separator; } dir = TclGetEnv("HOME", &dirString); if (dir == NULL) { if (interp) { | | | | > > | < | > > | 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 | if (split != len) { name[split] = separator; } dir = TclGetEnv("HOME", &dirString); if (dir == NULL) { if (interp) { Tcl_SetObjResult(interp, Tcl_NewStringObj( "couldn't find HOME environment variable to" " expand path", -1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "HOMELESS", NULL); } return TCL_ERROR; } Tcl_DStringInit(&temp); Tcl_JoinPath(1, &dir, &temp); Tcl_DStringFree(&dirString); } else { /* * We have a user name '~user' */ Tcl_DStringInit(&temp); if (TclpGetUserHome(name+1, &temp) == NULL) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "user \"%s\" doesn't exist", name+1)); Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "NOUSER", NULL); } Tcl_DStringFree(&temp); if (split != len) { name[split] = separator; } return TCL_ERROR; } |
︙ | ︙ | |||
2495 2496 2497 2498 2499 2500 2501 | objc--; objv++; while (objc--) { TclpNativeJoinPath(transPtr, Tcl_GetString(*objv++)); } TclDecrRefCount(parts); } else { | | < < < < < > | | | < | < < < < | < | 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 | objc--; objv++; while (objc--) { TclpNativeJoinPath(transPtr, Tcl_GetString(*objv++)); } TclDecrRefCount(parts); } else { Tcl_Obj *pair[2]; pair[0] = transPtr; pair[1] = Tcl_NewStringObj(name+split+1, -1); transPtr = TclJoinPath(2, pair); Tcl_DecrRefCount(pair[0]); Tcl_DecrRefCount(pair[1]); } } } else { transPtr = TclJoinPath(1, &pathPtr); } /* * Now we have a translated filename in 'transPtr'. This will have forward * slashes on Windows, and will not contain any ~user sequences. */ |
︙ | ︙ | |||
2574 2575 2576 2577 2578 2579 2580 | TclDecrRefCount(fsPathPtr->cwdPtr); } if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsPtr != NULL) { Tcl_FSFreeInternalRepProc *freeProc = fsPathPtr->fsPtr->freeInternalRepProc; if (freeProc != NULL) { | | | 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 | TclDecrRefCount(fsPathPtr->cwdPtr); } if (fsPathPtr->nativePathPtr != NULL && fsPathPtr->fsPtr != NULL) { Tcl_FSFreeInternalRepProc *freeProc = fsPathPtr->fsPtr->freeInternalRepProc; if (freeProc != NULL) { freeProc(fsPathPtr->nativePathPtr); fsPathPtr->nativePathPtr = NULL; } } ckfree((char *) fsPathPtr); pathPtr->typePtr = NULL; } |
︙ | ︙ | |||
2627 2628 2629 2630 2631 2632 2633 | if (srcFsPathPtr->fsPtr != NULL && srcFsPathPtr->nativePathPtr != NULL) { Tcl_FSDupInternalRepProc *dupProc = srcFsPathPtr->fsPtr->dupInternalRepProc; if (dupProc != NULL) { copyFsPathPtr->nativePathPtr = | | | 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 | if (srcFsPathPtr->fsPtr != NULL && srcFsPathPtr->nativePathPtr != NULL) { Tcl_FSDupInternalRepProc *dupProc = srcFsPathPtr->fsPtr->dupInternalRepProc; if (dupProc != NULL) { copyFsPathPtr->nativePathPtr = dupProc(srcFsPathPtr->nativePathPtr); } else { copyFsPathPtr->nativePathPtr = NULL; } } else { copyFsPathPtr->nativePathPtr = NULL; } copyFsPathPtr->fsPtr = srcFsPathPtr->fsPtr; |
︙ | ︙ |
Changes to win/tclWinFile.c.
︙ | ︙ | |||
3167 3168 3169 3170 3171 3172 3173 | *--------------------------------------------------------------------------- */ ClientData TclNativeCreateNativeRep( Tcl_Obj *pathPtr) { | | > > | 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 | *--------------------------------------------------------------------------- */ ClientData TclNativeCreateNativeRep( Tcl_Obj *pathPtr) { char *nativePathPtr = NULL, *str; Tcl_DString ds; Tcl_Obj *validPathPtr; int len; if (TclFSCwdIsNative()) { /* * The cwd is native, which means we can use the translated path * without worrying about normalization (this will also usually be * shorter so the utf-to-external conversion will be somewhat faster). */ validPathPtr = Tcl_FSGetTranslatedPath(NULL, pathPtr); if (validPathPtr == NULL) { return NULL; } /* refCount of validPathPtr was already incremented in Tcl_FSGetTranslatedPath */ } else { /* * Make sure the normalized path is set. */ validPathPtr = Tcl_FSGetNormalizedPath(NULL, pathPtr); if (validPathPtr == NULL) { return NULL; } /* validPathPtr returned from Tcl_FSGetNormalizedPath is owned by Tcl, so incr refCount here */ Tcl_IncrRefCount(validPathPtr); } str = Tcl_GetStringFromObj(validPathPtr, &len); Tcl_WinUtfToTChar(str, len, &ds); if (tclWinProcs->useWide) { WCHAR *wp = (WCHAR *) Tcl_DStringValue(&ds); |
︙ | ︙ | |||
3224 3225 3226 3227 3228 3229 3230 | if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z')) && str[1]==':') { wp += 2; len -= 2; } while (len-->0) { if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) { | | < < | 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 | if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z')) && str[1]==':') { wp += 2; len -= 2; } while (len-->0) { if ((*wp < ' ') || wcschr(L"\"*:<>?|", *wp)) { goto done; } else if (*wp=='/') { *wp = '\\'; } ++wp; } len = Tcl_DStringLength(&ds) + sizeof(WCHAR); } else { |
︙ | ︙ | |||
3257 3258 3259 3260 3261 3262 3263 | if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z')) && str[1]==':') { p += 2; len -= 2; } while (len-->0) { if ((*p < ' ') || strchr("\"*:<>?|", *p)) { | | < < < > > > > > | 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 | if (((str[0]>='A'&&str[0]<='Z') || (str[0]>='a'&&str[0]<='z')) && str[1]==':') { p += 2; len -= 2; } while (len-->0) { if ((*p < ' ') || strchr("\"*:<>?|", *p)) { goto done; } else if (*p=='/') { *p = '\\'; } ++p; } len = Tcl_DStringLength(&ds) + sizeof(char); } nativePathPtr = ckalloc((unsigned) len); if (nativePathPtr == 0) goto done; memcpy(nativePathPtr, Tcl_DStringValue(&ds), (size_t) len); done: Tcl_DecrRefCount(validPathPtr); Tcl_DStringFree(&ds); return (ClientData) nativePathPtr; } /* *--------------------------------------------------------------------------- * |
︙ | ︙ |