summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--Doc/Zsh/expn.yo11
-rw-r--r--Src/hist.c75
-rw-r--r--Src/string.c14
-rw-r--r--Src/system.h6
5 files changed, 83 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 7e34501ae..530e0310d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2001-02-19 Peter Stephenson <pws@csr.com>
+
+ * Alexandre: 13280: Doc/Zsh/expn.yo, Src/hist.c, Src/string.c,
+ Src/system.h: More sh-like and path-like handling of colon
+ modifiers.
+
2001-02-17 Peter Stephenson <pws@pwstephenson.fsnet.co.uk>
* unposted: Doc/Zsh/metafaq.yo: site name change from Geoff.
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 723d023af..60b73af33 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -202,16 +202,19 @@ noted.
startitem()
item(tt(h))(
-Remove a trailing pathname component, leaving the head.
+Remove a trailing pathname component, leaving the head. This works
+like `tt(dirname)'.
)
item(tt(r))(
-Remove a trailing suffix of the form `tt(.)var(xxx)', leaving the basename.
+Remove a filename extension of the form `tt(.)var(xxx)', leaving
+the root name.
)
item(tt(e))(
-Remove all but the suffix.
+Remove all but the extension.
)
item(tt(t))(
-Remove all leading pathname components, leaving the tail.
+Remove all leading pathname components, leaving the tail. This works
+like `tt(basename)'.
)
item(tt(p))(
Print the new command but do not execute it. Only works with history
diff --git a/Src/hist.c b/Src/hist.c
index b9480d786..138cb1bf5 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -1350,28 +1350,45 @@ hcomsearch(char *str)
int
remtpath(char **junkptr)
{
- char *str = *junkptr, *remcut;
-
- if ((remcut = strrchr(str, '/'))) {
- if (str != remcut)
- *remcut = '\0';
- else
- str[1] = '\0';
- return 1;
+ char *str = strend(*junkptr);
+
+ /* ignore trailing slashes */
+ while (str >= *junkptr && IS_DIRSEP(*str))
+ --str;
+ /* skip filename */
+ while (str >= *junkptr && !IS_DIRSEP(*str))
+ --str;
+ if (str < *junkptr) {
+ *junkptr = dupstring (".");
+ return 0;
}
- return 0;
+ /* repeated slashes are considered like a single slash */
+ while (str > *junkptr && IS_DIRSEP(str[-1]))
+ --str;
+ /* never erase the root slash */
+ if (str == *junkptr) {
+ ++str;
+ /* Leading doubled slashes (`//') have a special meaning on cygwin
+ and some old flavor of UNIX, so we do not assimilate them to
+ a single slash. However a greater number is ok to squeeze. */
+ if (IS_DIRSEP(*str) && !IS_DIRSEP(str[1]))
+ ++str;
+ }
+ *str = '\0';
+ return 1;
}
/**/
int
remtext(char **junkptr)
{
- char *str = *junkptr, *remcut;
+ char *str;
- if ((remcut = strrchr(str, '.')) && remcut != str) {
- *remcut = '\0';
- return 1;
- }
+ for (str = strend(*junkptr); str >= *junkptr && !IS_DIRSEP(*str); --str)
+ if (*str == '.') {
+ *str = '\0';
+ return 1;
+ }
return 0;
}
@@ -1379,12 +1396,15 @@ remtext(char **junkptr)
int
rembutext(char **junkptr)
{
- char *str = *junkptr, *remcut;
+ char *str;
- if ((remcut = strrchr(str, '.')) && remcut != str) {
- *junkptr = dupstring(remcut + 1); /* .xx or xx? */
- return 1;
- }
+ for (str = strend(*junkptr); str >= *junkptr && !IS_DIRSEP(*str); --str)
+ if (*str == '.') {
+ *junkptr = dupstring(str + 1); /* .xx or xx? */
+ return 1;
+ }
+ /* no extension */
+ *junkptr = dupstring ("");
return 0;
}
@@ -1392,13 +1412,20 @@ rembutext(char **junkptr)
mod_export int
remlpaths(char **junkptr)
{
- char *str = *junkptr, *remcut;
+ char *str = strend(*junkptr);
- if ((remcut = strrchr(str, '/'))) {
- *remcut = '\0';
- *junkptr = dupstring(remcut + 1);
- return 1;
+ if (IS_DIRSEP(*str)) {
+ /* remove trailing slashes */
+ while (str >= *junkptr && IS_DIRSEP(*str))
+ --str;
+ str[1] = '\0';
}
+ for (; str >= *junkptr; --str)
+ if (IS_DIRSEP(*str)) {
+ *str = '\0';
+ *junkptr = dupstring(str + 1);
+ return 1;
+ }
return 0;
}
diff --git a/Src/string.c b/Src/string.c
index 3dad89911..a0fc2ee8c 100644
--- a/Src/string.c
+++ b/Src/string.c
@@ -79,7 +79,7 @@ zhtricat(char const *s1, char const *s2, char const *s3)
char *ptr;
size_t l1 = strlen(s1);
size_t l2 = strlen(s2);
-
+
ptr = (char *)zhalloc(l1 + l2 + strlen(s3) + 1);
strcpy(ptr, s1);
strcpy(ptr + l1, s2);
@@ -133,3 +133,15 @@ appstr(char *base, char const *append)
{
return strcat(realloc(base, strlen(base) + strlen(append) + 1), append);
}
+
+/* Return a pointer to the last character of a string,
+ unless the string is empty. */
+
+/**/
+mod_export char *
+strend(char *str)
+{
+ if (*str == '\0')
+ return str;
+ return str + strlen (str) - 1;
+}
diff --git a/Src/system.h b/Src/system.h
index 4ba9bf8ab..50661e0fd 100644
--- a/Src/system.h
+++ b/Src/system.h
@@ -657,3 +657,9 @@ extern short ospeed;
#ifndef MAILDIR_SUPPORT
#define mailstat(X,Y) stat(X,Y)
#endif
+
+#ifdef __CYGWIN__
+# define IS_DIRSEP(c) ((c) == '/' || (c) == '\\')
+#else
+# define IS_DIRSEP(c) ((c) == '/')
+#endif