summaryrefslogtreecommitdiffstats
path: root/generic/tclPathObj.c
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2012-01-27 21:56:52 (GMT)
committerdgp <dgp@users.sourceforge.net>2012-01-27 21:56:52 (GMT)
commit6740ac50e9a65342cacd77245cacb8ad443dda00 (patch)
treef4482a0b82fb53236a1951b0d815fc6f2b21a95e /generic/tclPathObj.c
parent8783392efa27d4df503dc1b7029e8fde6ba03b4a (diff)
downloadtcl-6740ac50e9a65342cacd77245cacb8ad443dda00.zip
tcl-6740ac50e9a65342cacd77245cacb8ad443dda00.tar.gz
tcl-6740ac50e9a65342cacd77245cacb8ad443dda00.tar.bz2
3479689 New internal routine TclJoinPath().
Refactor all the *Join*Path* routines to give them more useful interfaces that are easier to manage getting the refcounts right.
Diffstat (limited to 'generic/tclPathObj.c')
-rw-r--r--generic/tclPathObj.c61
1 files changed, 26 insertions, 35 deletions
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 30f2081..7ab8a4e 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -838,44 +838,39 @@ Tcl_FSJoinPath(
* reference count. */
int elements) /* Number of elements to use (-1 = all) */
{
- Tcl_Obj *res;
- int i;
- const Tcl_Filesystem *fsPtr = NULL;
+ Tcl_Obj *copy, *res;
+ int objc;
+ Tcl_Obj **objv;
- if (elements < 0) {
- if (Tcl_ListObjLength(NULL, listObj, &elements) != TCL_OK) {
- return NULL;
- }
- } else {
- /*
- * Just make sure it is a valid list.
- */
-
- int listTest;
-
- if (Tcl_ListObjLength(NULL, listObj, &listTest) != TCL_OK) {
- return NULL;
- }
+ if (Tcl_ListObjLength(NULL, listObj, &objc) != TCL_OK) {
+ return NULL;
+ }
- /*
- * Correct this if it is too large, otherwise we will waste our time
- * joining null elements to the path.
- */
+ 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;
+}
- if (elements > listTest) {
- elements = listTest;
- }
- }
+Tcl_Obj *
+TclJoinPath(
+ int elements,
+ Tcl_Obj * const objv[])
+{
+ Tcl_Obj *res;
+ int i;
+ const Tcl_Filesystem *fsPtr = NULL;
res = NULL;
for (i = 0; i < elements; i++) {
- Tcl_Obj *elt, *driveName = NULL;
int driveNameLength, strEltLen, length;
Tcl_PathType type;
char *strElt, *ptr;
-
- Tcl_ListObjIndex(NULL, listObj, i, &elt);
+ Tcl_Obj *driveName = NULL;
+ Tcl_Obj *elt = objv[i];
/*
* This is a special case where we can be much more efficient, where
@@ -889,9 +884,8 @@ Tcl_FSJoinPath(
if ((i == (elements-2)) && (i == 0)
&& (elt->typePtr == &tclFsPathType)
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))) {
- Tcl_Obj *tailObj;
+ Tcl_Obj *tailObj = objv[i+1];
- Tcl_ListObjIndex(NULL, listObj, i+1, &tailObj);
type = TclGetPathType(tailObj, NULL, NULL, NULL);
if (type == TCL_PATH_RELATIVE) {
const char *str;
@@ -1389,7 +1383,7 @@ AppendPath(
* 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 Tcl_FSJoinPath() too.
+ * we need to fix that bug here, it needs fixing in TclJoinPath() too.
*/
bytes = Tcl_GetStringFromObj(tail, &numBytes);
if (numBytes == 0) {
@@ -2499,10 +2493,7 @@ SetFsPathFromAny(
}
Tcl_DStringFree(&temp);
} else {
- /* Bug 3479689: protect 0-refcount pathPth from getting freed */
- pathPtr->refCount++;
- transPtr = Tcl_FSJoinToPath(pathPtr, 0, NULL);
- pathPtr->refCount--;
+ transPtr = TclJoinPath(1, &pathPtr);
}
#if defined(__CYGWIN__) && defined(__WIN32__)