diff options
author | sebres <sebres@users.sourceforge.net> | 2018-11-20 20:11:02 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2018-11-20 20:11:02 (GMT) |
commit | 23102369d18f15a160e508c36990054b67c5a446 (patch) | |
tree | 57d3189c4d78ea119ea3b3e466e04d8bb9f5ad66 /generic/tclPathObj.c | |
parent | 1aa5869ecef3ba22e6cf9dbd3a08725d5c1f4541 (diff) | |
download | tcl-23102369d18f15a160e508c36990054b67c5a446.zip tcl-23102369d18f15a160e508c36990054b67c5a446.tar.gz tcl-23102369d18f15a160e508c36990054b67c5a446.tar.bz2 |
refactoring normalize in case of second path starting with tilde (~/~foo) - force second path as relative by join (provide normalize flag for TclJoinPath);
test cases extended
Diffstat (limited to 'generic/tclPathObj.c')
-rw-r--r-- | generic/tclPathObj.c | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/generic/tclPathObj.c b/generic/tclPathObj.c index 5c30bcf..c0e8081 100644 --- a/generic/tclPathObj.c +++ b/generic/tclPathObj.c @@ -821,7 +821,7 @@ GetExtension( *--------------------------------------------------------------------------- */ -Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[]); +Tcl_Obj * TclJoinPath(int elements, Tcl_Obj * const objv[], int normalize); Tcl_Obj * Tcl_FSJoinPath( @@ -829,7 +829,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; @@ -838,17 +838,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 normalize) /* 1 if special normalization case (force second + * path relative) */ { Tcl_Obj *res = NULL; /* Resulting path object (container of join) */ Tcl_Obj *elt; /* Path part (result if returns part of path) */ @@ -875,13 +875,14 @@ TclJoinPath( * to be an absolute path. Added a check for that elt is absolute. */ - if ((i == (elements-2)) && (i == 0) + if ((i == 0) && (elements == 2) && (elt->typePtr == &tclFsPathType) && !((elt->bytes != NULL) && (elt->bytes[0] == '\0')) && TclGetPathType(elt, NULL, NULL, NULL) == TCL_PATH_ABSOLUTE) { Tcl_Obj *tailObj = objv[i+1]; - type = TclGetPathType(tailObj, NULL, NULL, NULL); + type = normalize ? TCL_PATH_RELATIVE : + TclGetPathType(tailObj, NULL, NULL, NULL); if (type == TCL_PATH_RELATIVE) { const char *str; int len; @@ -953,7 +954,8 @@ TclJoinPath( } strElt = Tcl_GetStringFromObj(elt, &strEltLen); driveNameLength = 0; - type = TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName); + type = (normalize && (i > 0)) ? TCL_PATH_RELATIVE : + TclGetPathType(elt, &fsPtr, &driveNameLength, &driveName); if (type != TCL_PATH_RELATIVE) { /* * Zero out the current result. @@ -2413,37 +2415,30 @@ SetFsPathFromAny( * Handle tilde substitutions, if needed. */ - if (name[0] == '~') { + if (len && name[0] == '~') { char *expandedUser; 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) { @@ -2461,22 +2456,24 @@ SetFsPathFromAny( * We have a user name '~user' */ + 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_ResetResult(interp); - Tcl_AppendResult(interp, "user \"", name+1, + Tcl_AppendResult(interp, "user \"", expandedUser, "\" doesn't exist", 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); } expandedUser = Tcl_DStringValue(&temp); @@ -2514,7 +2511,7 @@ SetFsPathFromAny( pair[0] = transPtr; pair[1] = Tcl_NewStringObj(name+split+1, -1); - transPtr = TclJoinPath(2, pair); + transPtr = TclJoinPath(2, pair, 1); if (transPtr != pair[0]) { TclDecrRefCount(pair[0]); } @@ -2525,7 +2522,7 @@ SetFsPathFromAny( } Tcl_DStringFree(&temp); } else { - transPtr = TclJoinPath(1, &pathPtr); + transPtr = TclJoinPath(1, &pathPtr, 1); } /* |