From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26229 invoked by alias); 10 Jun 2016 17:43:09 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 38649 Received: (qmail 20369 invoked from network); 10 Jun 2016 17:43:09 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.1 From: Daniel Shahaf To: zsh-workers@zsh.org Subject: [PATCH 3/3] Clean up chabspath() [':a' word modifier]. Date: Fri, 10 Jun 2016 17:36:24 +0000 Message-Id: <1465580184-3095-3-git-send-email-danielsh@tarsus.local2> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1465580184-3095-1-git-send-email-danielsh@tarsus.local2> References: <1465580184-3095-1-git-send-email-danielsh@tarsus.local2> Fail fast when the first character isn't "/", and use that to simplify the '..' handling. The incumbent code was subtly wrong in various ways (for example, the first 'else if' branch didn't check that dest[-4] was a slash). --- Src/hist.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Src/hist.c b/Src/hist.c index 07f56b0..2cce970 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -1767,6 +1767,10 @@ chabspath(char **junkptr) if (**junkptr != '/') { *junkptr = zhtricat(metafy(zgetcwd(), -1, META_HEAPDUP), "/", *junkptr); } + if (**junkptr != '/') { + /* Can happen after 'rmdir $PWD; zsh' */ + return 0; + } current = *junkptr; dest = *junkptr; @@ -1783,7 +1787,9 @@ chabspath(char **junkptr) for (;;) { if (*current == '/') { + /* Contract multiple slashes. */ #ifdef __CYGWIN__ + /* Exception: on Cygwin, two slashes at the very start are significant. */ if (current == *junkptr && current[1] == '/') *dest++ = *current++; #endif @@ -1791,28 +1797,17 @@ chabspath(char **junkptr) while (*current == '/') current++; } else if (!*current) { + /* Remove trailing slashes. */ while (dest > *junkptr + 1 && dest[-1] == '/') dest--; *dest = '\0'; break; } else if (current[0] == '.' && current[1] == '.' && (!current[2] || current[2] == '/')) { - if (current == *junkptr || dest == *junkptr) { - *dest++ = '.'; - *dest++ = '.'; - current += 2; - } else if (dest > *junkptr + 2 && - !strncmp(dest - 3, "../", 3)) { - *dest++ = '.'; - *dest++ = '.'; - current += 2; - } else if (dest > *junkptr + 1) { - *dest = '\0'; + if (dest > *junkptr + 1) { for (dest--; - dest > *junkptr + 1 && dest[-1] != '/'; + dest[-1] != '/'; dest--); - if (dest[-1] != '/') - dest--; current += 2; if (*current == '/') current++;