aboutsummaryrefslogtreecommitdiff
path: root/jim-file.c
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2019-10-17 22:04:49 +1000
committerSteve Bennett <steveb@workware.net.au>2019-10-18 07:59:35 +1000
commit058d07b597ce088b86e7e8a070bcfa07509f26e1 (patch)
treee7e6af728d0eecbf8b9c39fbe8c9f9bfa8cdf8e5 /jim-file.c
parentca4fa3865a730857b385e6e34af67db3471e0089 (diff)
downloadjimtcl-058d07b597ce088b86e7e8a070bcfa07509f26e1.zip
jimtcl-058d07b597ce088b86e7e8a070bcfa07509f26e1.tar.gz
jimtcl-058d07b597ce088b86e7e8a070bcfa07509f26e1.tar.bz2
file: Better support for trailing slashes in pathnames
e.g. file tail /abc/def/ => def Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'jim-file.c')
-rw-r--r--jim-file.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/jim-file.c b/jim-file.c
index dca906d..f47e236 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -215,9 +215,43 @@ static int StoreStatData(Jim_Interp *interp, Jim_Obj *varName, const struct stat
return JIM_OK;
}
+/**
+ * Give a path of length 'len', returns the length of the path
+ * with any trailing slashes removed.
+ */
+static int JimPathLenNoTrailingSlashes(const char *path, int len)
+{
+ int i;
+ for (i = len; i > 1 && path[i - 1] == '/'; i--) {
+ /* Trailing slash, so remove it */
+ if (ISWINDOWS && path[i - 2] == ':') {
+ /* But on windows, we won't remove the trailing slash from c:/ */
+ break;
+ }
+ }
+ return i;
+}
+
+/**
+ * Give a path in objPtr, returns a new path with any trailing slash removed.
+ * Use Jim_DecrRefCount() on the returned object (which may be identical to objPtr).
+ */
+static Jim_Obj *JimStripTrailingSlashes(Jim_Interp *interp, Jim_Obj *objPtr)
+{
+ int len = Jim_Length(objPtr);
+ const char *path = Jim_String(objPtr);
+ int i = JimPathLenNoTrailingSlashes(path, len);
+ if (i != len) {
+ objPtr = Jim_NewStringObj(interp, path, i);
+ }
+ Jim_IncrRefCount(objPtr);
+ return objPtr;
+}
+
static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *p = strrchr(path, '/');
if (!p && path[0] == '.' && path[1] == '.' && path[2] == '\0') {
@@ -233,29 +267,35 @@ static int file_cmd_dirname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
Jim_SetResultString(interp, path, p - path + 1);
}
else {
- Jim_SetResultString(interp, path, p - path);
+ /* Strip any trailing slashes from the result */
+ int len = JimPathLenNoTrailingSlashes(path, p - path);
+ Jim_SetResultString(interp, path, len);
}
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}
static int file_cmd_rootname(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *lastSlash = strrchr(path, '/');
const char *p = strrchr(path, '.');
if (p == NULL || (lastSlash != NULL && lastSlash > p)) {
- Jim_SetResult(interp, argv[0]);
+ Jim_SetResult(interp, objPtr);
}
else {
Jim_SetResultString(interp, path, p - path);
}
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}
static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *lastSlash = strrchr(path, '/');
const char *p = strrchr(path, '.');
@@ -263,20 +303,23 @@ static int file_cmd_extension(Jim_Interp *interp, int argc, Jim_Obj *const *argv
p = "";
}
Jim_SetResultString(interp, p, -1);
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}
static int file_cmd_tail(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path = Jim_String(argv[0]);
+ Jim_Obj *objPtr = JimStripTrailingSlashes(interp, argv[0]);
+ const char *path = Jim_String(objPtr);
const char *lastSlash = strrchr(path, '/');
if (lastSlash) {
Jim_SetResultString(interp, lastSlash + 1, -1);
}
else {
- Jim_SetResult(interp, argv[0]);
+ Jim_SetResult(interp, objPtr);
}
+ Jim_DecrRefCount(interp, objPtr);
return JIM_OK;
}