From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8741 invoked from network); 24 Mar 2003 13:08:52 -0000 Received: from sunsite.dk (130.225.247.90) by ns1.primenet.com.au with SMTP; 24 Mar 2003 13:08:52 -0000 Received: (qmail 3542 invoked by alias); 24 Mar 2003 13:08:47 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 18378 Received: (qmail 3534 invoked from network); 24 Mar 2003 13:08:47 -0000 Received: from localhost (HELO sunsite.dk) (127.0.0.1) by localhost with SMTP; 24 Mar 2003 13:08:47 -0000 X-MessageWall-Score: 0 (sunsite.dk) Received: from [62.189.183.235] by sunsite.dk (MessageWall 1.0.8) with SMTP; 24 Mar 2003 13:8:46 -0000 Received: from exchange01.csr.com (unverified) by (Content Technologies SMTPRS 4.2.1) with ESMTP id for ; Mon, 24 Mar 2003 13:16:48 +0000 Received: from csr.com (tinky-winky.csr.com [192.168.144.127]) by exchange01.csr.com with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2650.21) id G0TVKAQ5; Mon, 24 Mar 2003 13:08:09 -0000 To: zsh-workers@sunsite.dk (Zsh hackers list) Subject: PATCH: $killring now works, perhaps... Date: Mon, 24 Mar 2003 13:08:44 +0000 Message-ID: <26695.1048511324@csr.com> From: Peter Stephenson I took a closer look at using $killring in anger and there were a whole heap of problems... - memory management was wrong in several places leading to core dumps (I hadn't properly worked out what was a NULL-terminated string and what had an explicit length and what that length actually was) - looping over elements when setting $killring was wrong, it went in the wrong direction - getting the killring when there was nothing in it should have returned the default length but didn't. I've been validating this with the following chunk of code which emulates bash-backward-kill-word. I think this gives a reasonably intuitive method for cycling the kill ring, but let me know if you think it should work differently. (The flag that makes consecutive kills join together in the cut buffer is unimplemented. I think it can be done in shell code by looking at LASTWIDGET and seeing if it contained the string `kill', although that's a bit ugly.) emulate -L zsh setopt extendedglob local -a match mbegin mend LBUFFER=${LBUFFER%%(#b)([[:alnum:]]##[^[:alnum:]]#)} [[ -z $match[1] ]] && return 1 killring=($CUTBUFFER "${(@)killring[1,-2]}") CUTBUFFER=$match[1] Index: Src/Zle/zle_params.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Zle/zle_params.c,v retrieving revision 1.9 diff -u -r1.9 zle_params.c --- Src/Zle/zle_params.c 5 Mar 2003 17:24:55 -0000 1.9 +++ Src/Zle/zle_params.c 24 Mar 2003 13:00:10 -0000 @@ -365,8 +365,8 @@ if (x) { unmetafy(x, &cutbuf.len); cutbuf.buf = zalloc(cutbuf.len); - strcpy((char *)cutbuf.buf, x); - zsfree(x); + memcpy((char *)cutbuf.buf, x, cutbuf.len); + free(x); } else { cutbuf.buf = NULL; cutbuf.len = 0; @@ -398,7 +398,7 @@ if (kring) { for (kptr = kring, kcnt = 0; kcnt < kringsize; kcnt++, kptr++) if (kptr->buf) - free(kptr->buf); + zfree(kptr->buf, kptr->len); zfree(kring, kringsize * sizeof(struct cutbuffer)); kring = NULL; kringsize = kringnum = 0; @@ -408,23 +408,23 @@ * Insert the elements into the kill ring. * Regardless of the old order, we number it with the current * entry first. + * + * Be careful to add elements by looping backwards; this + * fits in with how we cycle the ring. */ + int kpos = 0; kringsize = arrlen(x); kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer)); - for (p = x, kptr = kring; *p; p++, kptr++) { + for (p = x; *p; p++) { int len = strlen(*p); - kptr->buf = (char *)zalloc(len); - strcpy(kptr->buf, *p); - unmetafy(kptr->buf, &kptr->len); - if (len != kptr->len) { - /* Might as well have the lengths consistent. */ - char *p2 = zalloc(kptr->len); - memcpy(p2, kptr->buf, kptr->len); - zfree(kptr->buf, len); - kptr->buf = p2; - } + kptr = kring + kpos; + unmetafy(*p, &kptr->len); + kptr->buf = (char *)zalloc(kptr->len); + memcpy(kptr->buf, *p, kptr->len); + zfree(*p, len+1); + kpos = (kpos + kringsize -1 ) % kringsize; } - freearray(x); + free(x); } } @@ -441,10 +441,9 @@ char **ret, **p; /* Supposed to work even if kring is NULL */ - for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) { - if (!kring[kpos].buf) - break; - kpos = (kpos + kringsize - 1) % kringsize; + if (!kring) { + kringsize = KRINGCTDEF; + kring = (Cutbuffer)zcalloc(kringsize * sizeof(struct cutbuffer)); } p = ret = (char **)zhalloc((kringsize+1) * sizeof(char *)); @@ -452,7 +451,13 @@ for (kpos = kringnum, kcnt = 0; kcnt < kringsize; kcnt++) { Cutbuffer kptr = kring + kpos; if (kptr->buf) + { + /* + * Need to use HEAPDUP to make sure there's room for the + * terminating NULL. + */ *p++ = metafy((char *)kptr->buf, kptr->len, META_HEAPDUP); + } else *p++ = dupstring(""); kpos = (kpos + kringsize - 1) % kringsize; -- Peter Stephenson Software Engineer CSR Ltd., Science Park, Milton Road, Cambridge, CB4 0WH, UK Tel: +44 (0)1223 692070 ********************************************************************** The information transmitted is intended only for the person or entity to which it is addressed and may contain confidential and/or privileged material. Any review, retransmission, dissemination or other use of, or taking of any action in reliance upon, this information by persons or entities other than the intended recipient is prohibited. If you received this in error, please contact the sender and delete the material from any computer. **********************************************************************