summaryrefslogtreecommitdiffstats
path: root/generic/tclPathObj.c
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2018-11-22 14:16:51 (GMT)
committersebres <sebres@users.sourceforge.net>2018-11-22 14:16:51 (GMT)
commit1cf15d2b4dfa14df45471804f579f5e4e1cbfae2 (patch)
tree6db90761464a8bb5655c9caff61fcc3579057886 /generic/tclPathObj.c
parenta27b61390990c4773c93bf87f132987b980a1582 (diff)
parentfb0f0b6c373000a8893904c0eea7580fdc902d20 (diff)
downloadtcl-1cf15d2b4dfa14df45471804f579f5e4e1cbfae2.zip
tcl-1cf15d2b4dfa14df45471804f579f5e4e1cbfae2.tar.gz
tcl-1cf15d2b4dfa14df45471804f579f5e4e1cbfae2.tar.bz2
merge 8.6
Diffstat (limited to 'generic/tclPathObj.c')
-rw-r--r--generic/tclPathObj.c77
1 files changed, 41 insertions, 36 deletions
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c
index 31a0cbf..ea8a7ec 100644
--- a/generic/tclPathObj.c
+++ b/generic/tclPathObj.c
@@ -827,7 +827,7 @@ Tcl_FSJoinPath(
* reference count. */
int elements) /* Number of elements to use (-1 = all) */
{
- Tcl_Obj *copy, *res;
+ Tcl_Obj *res;
int objc;
Tcl_Obj **objv;
@@ -836,17 +836,17 @@ Tcl_FSJoinPath(
}
elements = ((elements >= 0) && (elements <= objc)) ? elements : objc;
- copy = TclListObjCopy(NULL, listObj);
Tcl_ListObjGetElements(NULL, listObj, &objc, &objv);
- res = TclJoinPath(elements, objv);
- Tcl_DecrRefCount(copy);
+ res = TclJoinPath(elements, objv, 0);
return res;
}
Tcl_Obj *
TclJoinPath(
- int elements,
- Tcl_Obj * const objv[])
+ int elements, /* Number of elements to use (-1 = all) */
+ Tcl_Obj * const objv[], /* Path elements to join */
+ int forceRelative) /* If non-zero, assume all more paths are
+ * relative (e. g. simple normalization) */
{
Tcl_Obj *res = NULL;
int i;
@@ -878,10 +878,13 @@ TclJoinPath(
if ((eltIr)
&& !((elt->bytes != NULL) && (elt->bytes[0] == '\0'))
- && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
- Tcl_Obj *tailObj = objv[1];
- Tcl_PathType type = TclGetPathType(tailObj, NULL, NULL, NULL);
+ && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) {
+ Tcl_Obj *tailObj = objv[1];
+ Tcl_PathType type;
+ /* if forceRelative - second path is relative */
+ type = forceRelative ? TCL_PATH_RELATIVE :
+ TclGetPathType(tailObj, NULL, NULL, NULL);
if (type == TCL_PATH_RELATIVE) {
const char *str;
int len;
@@ -959,7 +962,9 @@ TclJoinPath(
strElt = TclGetStringFromObj(elt, &strEltLen);
driveNameLength = 0;
- type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
+ /* if forceRelative - all paths excepting first one are relative */
+ type = (forceRelative && (i > 0)) ? TCL_PATH_RELATIVE :
+ TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName);
if (type != TCL_PATH_RELATIVE) {
/*
* Zero out the current result.
@@ -2271,36 +2276,29 @@ SetFsPathFromAny(
* Handle tilde substitutions, if needed.
*/
- if (name[0] == '~') {
+ if (len && name[0] == '~') {
Tcl_DString temp;
int split;
char separator = '/';
+ /*
+ * We have multiple cases '~/foo/bar...', '~user/foo/bar...', etc.
+ * split becomes value 1 for '~/...' as well as for '~'.
+ */
split = FindSplitPos(name, separator);
- if (split != len) {
- /*
- * We have multiple pieces '~user/foo/bar...'
- */
-
- name[split] = '\0';
- }
/*
* Do some tilde substitution.
*/
- if (name[1] == '\0') {
+ if (split == 1) {
/*
- * We have just '~'
+ * We have just '~' (or '~/...')
*/
const char *dir;
Tcl_DString dirString;
- if (split != len) {
- name[split] = separator;
- }
-
dir = TclGetEnv("HOME", &dirString);
if (dir == NULL) {
if (interp) {
@@ -2320,23 +2318,26 @@ SetFsPathFromAny(
* We have a user name '~user'
*/
+ const char *expandedUser;
+ Tcl_DString userName;
+
+ Tcl_DStringInit(&userName);
+ Tcl_DStringAppend(&userName, name+1, split-1);
+ expandedUser = Tcl_DStringValue(&userName);
+
Tcl_DStringInit(&temp);
- if (TclpGetUserHome(name+1, &temp) == NULL) {
+ if (TclpGetUserHome(expandedUser, &temp) == NULL) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "user \"%s\" doesn't exist", name+1));
+ "user \"%s\" doesn't exist", expandedUser));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "PATH", "NOUSER",
NULL);
}
+ Tcl_DStringFree(&userName);
Tcl_DStringFree(&temp);
- if (split != len) {
- name[split] = separator;
- }
return TCL_ERROR;
}
- if (split != len) {
- name[split] = separator;
- }
+ Tcl_DStringFree(&userName);
}
transPtr = TclDStringToObj(&temp);
@@ -2373,13 +2374,17 @@ SetFsPathFromAny(
pair[0] = transPtr;
pair[1] = Tcl_NewStringObj(name+split+1, -1);
- transPtr = TclJoinPath(2, pair);
- Tcl_DecrRefCount(pair[0]);
- Tcl_DecrRefCount(pair[1]);
+ transPtr = TclJoinPath(2, pair, 1);
+ if (transPtr != pair[0]) {
+ Tcl_DecrRefCount(pair[0]);
+ }
+ if (transPtr != pair[1]) {
+ Tcl_DecrRefCount(pair[1]);
+ }
}
}
} else {
- transPtr = TclJoinPath(1, &pathPtr);
+ transPtr = TclJoinPath(1, &pathPtr, 1);
}
/*