diff --git a/ChangeLog b/ChangeLog index 7e34501ae..530e0310d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2001-02-19 Peter Stephenson + + * 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 * 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; + char *str = strend(*junkptr); - if ((remcut = strrchr(str, '/'))) { - if (str != remcut) - *remcut = '\0'; - else - str[1] = '\0'; - return 1; + /* 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