zsh-workers
 help / color / mirror / code / Atom feed
* PATCH: prompt memory handling is screwy
@ 2008-10-24 10:24 Peter Stephenson
  2008-10-24 13:46 ` Peter Stephenson
  2008-10-24 14:40 ` Bart Schaefer
  0 siblings, 2 replies; 3+ messages in thread
From: Peter Stephenson @ 2008-10-24 10:24 UTC (permalink / raw)
  To: Zsh hackers list

Some idiot added a new feature recently that let the prompt code
be called recursively.  Currently the prompt code isn't written to
be called recursively, but luckily that's a fairly straightforward
change, if boring to rename all the variables.

There's also a "tricat" that should be a "zhtricat" because it wants
stuff from the stack.

Index: Src/prompt.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/prompt.c,v
retrieving revision 1.56
diff -u -r1.56 prompt.c
--- Src/prompt.c	29 Sep 2008 21:46:58 -0000	1.56
+++ Src/prompt.c	24 Oct 2008 10:21:07 -0000
@@ -55,46 +55,60 @@
     "heredocd", "brace",     "braceparam", "always",
 };
 
+
+struct buf_vars;
+
+struct buf_vars {
+/* Previous set of prompt variables on the stack. */
+
+    struct buf_vars *last;
+
 /* The buffer into which an expanded and metafied prompt is being written, *
  * and its size.                                                           */
 
-static char *buf;
-static int bufspc;
+    char *buf;
+    int bufspc;
 
 /* bp is the pointer to the current position in the buffer, where the next *
  * character will be added.                                                */
 
-static char *bp;
+    char *bp;
 
 /* Position of the start of the current line in the buffer */
 
-static char *bufline;
+    char *bufline;
 
 /* bp1 is an auxiliary pointer into the buffer, which when non-NULL is *
  * moved whenever the buffer is reallocated.  It is used when data is   *
  * being temporarily held in the buffer.                                */
 
-static char *bp1;
+    char *bp1;
 
 /* The format string, for %-expansion. */
 
-static char *fm;
+    char *fm;
 
 /* Non-zero if truncating the current segment of the buffer. */
 
-static int truncwidth;
+    int truncwidth;
 
 /* Current level of nesting of %{ / %} sequences. */
 
-static int dontcount;
+    int dontcount;
 
 /* Level of %{ / %} surrounding a truncation segment. */
 
-static int trunccount;
+    int trunccount;
 
 /* Strings to use for %r and %R (for the spelling prompt). */
 
-static char *rstring, *Rstring;
+    char *rstring, *Rstring;
+};
+
+typedef struct buf_vars *Buf_vars;
+
+/* The currently active prompt output variables */
+static Buf_vars bv;
 
 /*
  * Expand path p; maximum is npath segments where 0 means the whole path.
@@ -156,6 +170,8 @@
 mod_export char *
 promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
 {
+    struct buf_vars new_vars;
+
     if(!s)
 	return ztrdup("");
 
@@ -181,29 +197,39 @@
 	lastval = oldval;
     }
 
-    rstring = rs;
-    Rstring = Rs;
-    fm = s;
-    bp = bufline = buf = zshcalloc(bufspc = 256);
-    bp1 = NULL;
-    truncwidth = 0;
+    memset(&new_vars, 0, sizeof(new_vars));
+    new_vars.last = bv;
+    bv = &new_vars;
+
+    new_vars.rstring = rs;
+    new_vars.Rstring = Rs;
+    new_vars.fm = s;
+    new_vars.bufspc = 256;
+    new_vars.bp = new_vars.bufline = new_vars.buf = zshcalloc(new_vars.bufspc);
+    new_vars.bp1 = NULL;
+    new_vars.truncwidth = 0;
+
     putpromptchar(1, '\0', txtchangep);
     addbufspc(2);
-    if(dontcount)
-	*bp++ = Outpar;
-    *bp = '\0';
+    if (new_vars.dontcount)
+	*new_vars.bp++ = Outpar;
+    *new_vars.bp = '\0';
     if (!ns) {
 	/* If zero, Inpar, Outpar and Nularg should be removed. */
-	for (bp = buf; *bp; ) {
-	    if (*bp == Meta)
-		bp += 2;
-	    else if (*bp == Inpar || *bp == Outpar || *bp == Nularg)
-		chuck(bp);
+	for (new_vars.bp = new_vars.buf; *new_vars.bp; ) {
+	    if (*new_vars.bp == Meta)
+		new_vars.bp += 2;
+	    else if (*new_vars.bp == Inpar || *new_vars.bp == Outpar ||
+		     *new_vars.bp == Nularg)
+		chuck(new_vars.bp);
 	    else
-		bp++;
+		new_vars.bp++;
 	}
     }
-    return buf;
+
+    bv = new_vars.last;
+
+    return new_vars.buf;
 }
 
 /* Perform %- and !-expansion as required on a section of the prompt.  The *
@@ -220,33 +246,33 @@
     time_t timet;
     Nameddir nd;
 
-    for (; *fm && *fm != endchar; fm++) {
+    for (; *bv->fm && *bv->fm != endchar; bv->fm++) {
 	arg = 0;
-	if (*fm == '%' && isset(PROMPTPERCENT)) {
+	if (*bv->fm == '%' && isset(PROMPTPERCENT)) {
 	    int minus = 0;
-	    fm++;
-	    if (*fm == '-') {
+	    bv->fm++;
+	    if (*bv->fm == '-') {
 		minus = 1;
-		fm++;
+		bv->fm++;
 	    }
-	    if (idigit(*fm)) {
-		arg = zstrtol(fm, &fm, 10);
+	    if (idigit(*bv->fm)) {
+		arg = zstrtol(bv->fm, &bv->fm, 10);
 		if (minus)
 		    arg *= -1;
 	    } else if (minus)
 		arg = -1;
-	    if (*fm == '(') {
+	    if (*bv->fm == '(') {
 		int tc, otruncwidth;
 
-		if (idigit(*++fm)) {
-		    arg = zstrtol(fm, &fm, 10);
+		if (idigit(*++bv->fm)) {
+		    arg = zstrtol(bv->fm, &bv->fm, 10);
 		} else if (arg < 0) {
 		    /* negative numbers don't make sense here */
 		    arg *= -1;
 		}
 		test = 0;
 		ss = pwd;
-		switch (tc = *fm) {
+		switch (tc = *bv->fm) {
 		case 'c':
 		case '.':
 		case '~':
@@ -310,8 +336,8 @@
 		    	test = 1;
 		    break;
 		case 'l':
-		    *bp = '\0';
-		    countprompt(bufline, &t0, 0, 0);
+		    *bv->bp = '\0';
+		    countprompt(bv->bufline, &t0, 0, 0);
 		    if (t0 >= arg)
 			test = 1;
 		    break;
@@ -343,42 +369,42 @@
 		    test = -1;
 		    break;
 		}
-		if (!*fm || !(sep = *++fm))
+		if (!*bv->fm || !(sep = *++bv->fm))
 		    return 0;
-		fm++;
+		bv->fm++;
 		/* Don't do the current truncation until we get back */
-		otruncwidth = truncwidth;
-		truncwidth = 0;
+		otruncwidth = bv->truncwidth;
+		bv->truncwidth = 0;
 		if (!putpromptchar(test == 1 && doprint, sep,
-				   txtchangep) || !*++fm ||
+				   txtchangep) || !*++bv->fm ||
 		    !putpromptchar(test == 0 && doprint, ')',
 				   txtchangep)) {
-		    truncwidth = otruncwidth;
+		    bv->truncwidth = otruncwidth;
 		    return 0;
 		}
-		truncwidth = otruncwidth;
+		bv->truncwidth = otruncwidth;
 		continue;
 	    }
 	    if (!doprint)
-		switch(*fm) {
+		switch(*bv->fm) {
 		  case '[':
-		    while(idigit(*++fm));
-		    while(*++fm != ']');
+		    while(idigit(*++bv->fm));
+		    while(*++bv->fm != ']');
 		    continue;
 		  case '<':
-		    while(*++fm != '<');
+		    while(*++bv->fm != '<');
 		    continue;
 		  case '>':
-		    while(*++fm != '>');
+		    while(*++bv->fm != '>');
 		    continue;
 		  case 'D':
-		    if(fm[1]=='{')
-			while(*++fm != '}');
+		    if(bv->fm[1]=='{')
+			while(*++bv->fm != '}');
 		    continue;
 		  default:
 		    continue;
 		}
-	    switch (*fm) {
+	    switch (*bv->fm) {
 	    case '~':
 		promptpath(pwd, arg, 1);
 		break;
@@ -399,16 +425,16 @@
 	    case 'h':
 	    case '!':
 		addbufspc(DIGBUFSIZE);
-		convbase(bp, curhist, 10);
-		bp += strlen(bp);
+		convbase(bv->bp, curhist, 10);
+		bv->bp += strlen(bv->bp);
 		break;
 	    case 'j':
 		for (numjobs = 0, j = 1; j <= maxjob; j++)
 		    if (jobtab[j].stat && jobtab[j].procs &&
 		    	!(jobtab[j].stat & STAT_NOPRINT)) numjobs++;
 		addbufspc(DIGBUFSIZE);
-		sprintf(bp, "%d", numjobs);
-		bp += strlen(bp);
+		sprintf(bv->bp, "%d", numjobs);
+		bv->bp += strlen(bv->bp);
 		break;
 	    case 'M':
 		queue_signals();
@@ -468,11 +494,11 @@
 		tsetcap(TCUNDERLINEEND, TSC_PROMPT|TSC_DIRTY);
 		break;
 	    case 'F':
-		if (fm[1] == '{') {
-		    fm += 2;
-		    arg = match_colour((const char **)&fm, 1, 0);
-		    if (*fm != '}')
-			fm--;
+		if (bv->fm[1] == '{') {
+		    bv->fm += 2;
+		    arg = match_colour((const char **)&bv->fm, 1, 0);
+		    if (*bv->fm != '}')
+			bv->fm--;
 		} else
 		    arg = match_colour(NULL, 1, arg);
 		if (arg >= 0 && !(arg & TXTNOFGCOLOUR)) {
@@ -489,11 +515,11 @@
 		set_colour_attribute(TXTNOFGCOLOUR, COL_SEQ_FG, TSC_PROMPT);
 		break;
 	    case 'K':
-		if (fm[1] == '{') {
-		    fm += 2;
-		    arg = match_colour((const char **)&fm, 0, 0);
-		    if (*fm != '}')
-			fm--;
+		if (bv->fm[1] == '{') {
+		    bv->fm += 2;
+		    arg = match_colour((const char **)&bv->fm, 0, 0);
+		    if (*bv->fm != '}')
+			bv->fm--;
 		} else
 		    arg = match_colour(NULL, 0, arg);
 		if (arg >= 0 && !(arg & TXTNOBGCOLOUR)) {
@@ -510,20 +536,20 @@
 		set_colour_attribute(TXTNOBGCOLOUR, COL_SEQ_BG, TSC_PROMPT);
 		break;
 	    case '[':
-		if (idigit(*++fm))
-		    arg = zstrtol(fm, &fm, 10);
+		if (idigit(*++bv->fm))
+		    arg = zstrtol(bv->fm, &bv->fm, 10);
 		if (!prompttrunc(arg, ']', doprint, endchar, txtchangep))
-		    return *fm;
+		    return *bv->fm;
 		break;
 	    case '<':
 	    case '>':
-		if (!prompttrunc(arg, *fm, doprint, endchar, txtchangep))
-		    return *fm;
+		if (!prompttrunc(arg, *bv->fm, doprint, endchar, txtchangep))
+		    return *bv->fm;
 		break;
 	    case '{': /*}*/
-		if (!dontcount++) {
+		if (!bv->dontcount++) {
 		    addbufspc(1);
-		    *bp++ = Inpar;
+		    *bv->bp++ = Inpar;
 		}
 		if (arg <= 0)
 		    break;
@@ -533,18 +559,18 @@
 		if (arg > 0) {
 		    addbufspc(arg);
 		    while (arg--)
-			*bp++ = Nularg;
+			*bv->bp++ = Nularg;
 		} else {
 		    addbufspc(1);
-		    *bp++ = Nularg;
+		    *bv->bp++ = Nularg;
 		}
 		break;
 	    case /*{*/ '}':
-		if (trunccount && trunccount >= dontcount)
-		    return *fm;
-		if (dontcount && !--dontcount) {
+		if (bv->trunccount && bv->trunccount >= bv->dontcount)
+		    return *bv->fm;
+		if (bv->dontcount && !--bv->dontcount) {
 		    addbufspc(1);
-		    *bp++ = Outpar;
+		    *bv->bp++ = Outpar;
 		}
 		break;
 	    case 't':
@@ -557,7 +583,7 @@
 		{
 		    char *tmfmt, *dd, *tmbuf = NULL;
 
-		    switch (*fm) {
+		    switch (*bv->fm) {
 		    case 'T':
 			tmfmt = "%K:%M";
 			break;
@@ -571,19 +597,19 @@
 			tmfmt = "%m/%d/%y";
 			break;
 		    case 'D':
-			if (fm[1] == '{' /*}*/) {
-			    for (ss = fm + 2; *ss && *ss != /*{*/ '}'; ss++)
+			if (bv->fm[1] == '{' /*}*/) {
+			    for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}'; ss++)
 				if(*ss == '\\' && ss[1])
 				    ss++;
-			    dd = tmfmt = tmbuf = zalloc(ss - fm);
-			    for (ss = fm + 2; *ss && *ss != /*{*/ '}';
+			    dd = tmfmt = tmbuf = zalloc(ss - bv->fm);
+			    for (ss = bv->fm + 2; *ss && *ss != /*{*/ '}';
 				 ss++) {
 				if(*ss == '\\' && ss[1])
 				    ss++;
 				*dd++ = *ss;
 			    }
 			    *dd = 0;
-			    fm = ss - !*ss;
+			    bv->fm = ss - !*ss;
 			    if (!*tmfmt) {
 				free(tmbuf);
 				continue;
@@ -606,13 +632,13 @@
 		     */
 		    for(j = 0, t0 = strlen(tmfmt)*8; j < 3; j++, t0*=2) {
 			addbufspc(t0);
-			if (ztrftime(bp, t0, tmfmt, tm) >= 0)
+			if (ztrftime(bv->bp, t0, tmfmt, tm) >= 0)
 			    break;
 		    }
 		    /* There is enough room for this because addbufspc(t0)
 		     * allocates room for t0 * 2 bytes. */
-		    metafy(bp, -1, META_NOALLOC);
-		    bp += strlen(bp);
+		    metafy(bv->bp, -1, META_NOALLOC);
+		    bv->bp += strlen(bv->bp);
 		    zsfree(tmbuf);
 		    break;
 		}
@@ -637,22 +663,22 @@
 		break;
 	    case 'L':
 		addbufspc(DIGBUFSIZE);
-		sprintf(bp, "%ld", (long)shlvl);
-		bp += strlen(bp);
+		sprintf(bv->bp, "%ld", (long)shlvl);
+		bv->bp += strlen(bv->bp);
 		break;
 	    case '?':
 		addbufspc(DIGBUFSIZE);
-		sprintf(bp, "%ld", (long)lastval);
-		bp += strlen(bp);
+		sprintf(bv->bp, "%ld", (long)lastval);
+		bv->bp += strlen(bv->bp);
 		break;
 	    case '%':
 	    case ')':
 		addbufspc(1);
-		*bp++ = *fm;
+		*bv->bp++ = *bv->fm;
 		break;
 	    case '#':
 		addbufspc(1);
-		*bp++ = privasserted() ? '#' : '%';
+		*bv->bp++ = privasserted() ? '#' : '%';
 		break;
 	    case 'v':
 		if (!arg)
@@ -674,7 +700,7 @@
 			    stradd(cmdnames[cmdstack[t0]]);
 			    if (arg) {
 				addbufspc(1);
-				*bp++=' ';
+				*bv->bp++=' ';
 			    }
 			}
 		    } else {
@@ -685,7 +711,7 @@
 			    stradd(cmdnames[cmdstack[t0]]);
 			    if (arg) {
 				addbufspc(1);
-				*bp++=' ';
+				*bv->bp++=' ';
 			    }
 			}
 		    }
@@ -700,7 +726,7 @@
 			    stradd(cmdnames[cmdstack[t0]]);
 			    if (arg) {
 				addbufspc(1);
-				*bp++=' ';
+				*bv->bp++=' ';
 			    }
 			}
 		    } else {
@@ -711,19 +737,19 @@
 			    stradd(cmdnames[cmdstack[t0]]);
 			    if (arg) {
 				addbufspc(1);
-				*bp++=' ';
+				*bv->bp++=' ';
 			    }
 			}
 		    }
 		}
 		break;
 	    case 'r':
-		if(rstring)
-		    stradd(rstring);
+		if(bv->rstring)
+		    stradd(bv->rstring);
 		break;
 	    case 'R':
-		if(Rstring)
-		    stradd(Rstring);
+		if(bv->Rstring)
+		    stradd(bv->Rstring);
 		break;
 	    case 'I':
 		if (funcstack && funcstack->tp != FS_SOURCE &&
@@ -738,16 +764,16 @@
 		    if (funcstack->tp == FS_EVAL)
 			lineno--;
 		    addbufspc(DIGBUFSIZE);
-		    sprintf(bp, "%ld", (long)flineno);
-		    bp += strlen(bp);
+		    sprintf(bv->bp, "%ld", (long)flineno);
+		    bv->bp += strlen(bv->bp);
 		    break;
 		}
 		/* else we're in a file and lineno is already correct */
 		/* FALLTHROUGH */
 	    case 'i':
 		addbufspc(DIGBUFSIZE);
-		sprintf(bp, "%ld", (long)lineno);
-		bp += strlen(bp);
+		sprintf(bv->bp, "%ld", (long)lineno);
+		bv->bp += strlen(bv->bp);
 		break;
 	    case 'x':
 		if (funcstack && funcstack->tp != FS_SOURCE &&
@@ -761,23 +787,23 @@
 	    case '\0':
 		return 0;
 	    case Meta:
-		fm++;
+		bv->fm++;
 		break;
 	    }
-	} else if(*fm == '!' && isset(PROMPTBANG)) {
+	} else if(*bv->fm == '!' && isset(PROMPTBANG)) {
 	    if(doprint) {
-		if(fm[1] == '!') {
-		    fm++;
+		if(bv->fm[1] == '!') {
+		    bv->fm++;
 		    addbufspc(1);
 		    pputc('!');
 		} else {
 		    addbufspc(DIGBUFSIZE);
-		    convbase(bp, curhist, 10);
-		    bp += strlen(bp);
+		    convbase(bv->bp, curhist, 10);
+		    bv->bp += strlen(bv->bp);
 		}
 	    }
 	} else {
-	    char c = *fm == Meta ? *++fm ^ 32 : *fm;
+	    char c = *bv->fm == Meta ? *++bv->fm ^ 32 : *bv->fm;
 
 	    if (doprint) {
 		addbufspc(1);
@@ -786,7 +812,7 @@
 	}
     }
 
-    return *fm;
+    return *bv->fm;
 }
 
 /* pputc adds a character to the buffer, metafying.  There must *
@@ -797,12 +823,12 @@
 pputc(char c)
 {
     if (imeta(c)) {
-	*bp++ = Meta;
+	*bv->bp++ = Meta;
 	c ^= 32;
     }
-    *bp++ = c;
-    if (c == '\n' && !dontcount)
-	bufline = bp;
+    *bv->bp++ = c;
+    if (c == '\n' && !bv->dontcount)
+	bv->bufline = bv->bp;
 }
 
 /* Make sure there is room for `need' more characters in the buffer. */
@@ -812,16 +838,16 @@
 addbufspc(int need)
 {
     need *= 2;   /* for metafication */
-    if((bp - buf) + need > bufspc) {
-	int bo = bp - buf;
-	int bo1 = bp1 ? bp1 - buf : -1;
+    if((bv->bp - bv->buf) + need > bv->bufspc) {
+	int bo = bv->bp - bv->buf;
+	int bo1 = bv->bp1 ? bv->bp1 - bv->buf : -1;
 
 	if(need & 255)
 	    need = (need | 255) + 1;
-	buf = realloc(buf, bufspc += need);
-	bp = buf + bo;
+	bv->buf = realloc(bv->buf, bv->bufspc += need);
+	bv->bp = bv->buf + bo;
 	if(bo1 != -1)
-	    bp1 = buf + bo1;
+	    bv->bp1 = bv->buf + bo1;
     }
 }
 
@@ -877,7 +903,7 @@
 
 	/* Put printed representation into the buffer */
 	while (*pc)
-	    *bp++ = *pc++;
+	    *bv->bp++ = *pc++;
     }
 
     free(ums);
@@ -888,7 +914,7 @@
      * prompt buffer. */
     for (ps = d; *ps; ps++) {
 	for (pc = nicechar(*ps == Meta ? *++ps^32 : *ps); *pc; pc++)
-	    *bp++ = *pc;
+	    *bv->bp++ = *pc;
     }
 #endif
 }
@@ -910,12 +936,12 @@
 	    tputs(tcstr[cap], 1, putshout);
 	    break;
 	case TSC_PROMPT:
-	    if (!dontcount) {
+	    if (!bv->dontcount) {
 		addbufspc(1);
-		*bp++ = Inpar;
+		*bv->bp++ = Inpar;
 	    }
 	    tputs(tcstr[cap], 1, putstr);
-	    if (!dontcount) {
+	    if (!bv->dontcount) {
 		int glitch = 0;
 
 		if (cap == TCSTANDOUTBEG || cap == TCSTANDOUTEND)
@@ -926,8 +952,8 @@
 		    glitch = 0;
 		addbufspc(glitch + 1);
 		while(glitch--)
-		    *bp++ = Nularg;
-		*bp++ = Outpar;
+		    *bv->bp++ = Nularg;
+		*bv->bp++ = Outpar;
 	    }
 	    break;
 	}
@@ -1081,59 +1107,59 @@
 	    unsigned int *txtchangep)
 {
     if (arg > 0) {
-	char ch = *fm, *ptr, *truncstr;
+	char ch = *bv->fm, *ptr, *truncstr;
 	int truncatleft = ch == '<';
-	int w = bp - buf;
+	int w = bv->bp - bv->buf;
 
 	/*
 	 * If there is already a truncation active, return so that
 	 * can be finished, backing up so that the new truncation
 	 * can be started afterwards.
 	 */
-	if (truncwidth) {
-	    while (*--fm != '%')
+	if (bv->truncwidth) {
+	    while (*--bv->fm != '%')
 		;
-	    fm--;
+	    bv->fm--;
 	    return 0;
 	}
 
-	truncwidth = arg;
-	if (*fm != ']')
-	    fm++;
-	while (*fm && *fm != truncchar) {
-	    if (*fm == '\\' && fm[1])
-		++fm;
+	bv->truncwidth = arg;
+	if (*bv->fm != ']')
+	    bv->fm++;
+	while (*bv->fm && *bv->fm != truncchar) {
+	    if (*bv->fm == '\\' && bv->fm[1])
+		++bv->fm;
 	    addbufspc(1);
-	    *bp++ = *fm++;
+	    *bv->bp++ = *bv->fm++;
 	}
-	if (!*fm)
+	if (!*bv->fm)
 	    return 0;
-	if (bp - buf == w && truncchar == ']') {
+	if (bv->bp - bv->buf == w && truncchar == ']') {
 	    addbufspc(1);
-	    *bp++ = '<';
+	    *bv->bp++ = '<';
 	}
-	ptr = buf + w;		/* addbufspc() may have realloc()'d buf */
+	ptr = bv->buf + w;		/* addbv->bufspc() may have realloc()'d bv->buf */
 	/*
 	 * Now:
-	 *   buf is the start of the output prompt buffer
+	 *   bv->buf is the start of the output prompt buffer
 	 *   ptr is the start of the truncation string
-	 *   bp is the end of the truncation string
+	 *   bv->bp is the end of the truncation string
 	 */
-	truncstr = ztrduppfx(ptr, bp - ptr);
+	truncstr = ztrduppfx(ptr, bv->bp - ptr);
 
-	bp = ptr;
-	w = bp - buf;
-	fm++;
-	trunccount = dontcount;
+	bv->bp = ptr;
+	w = bv->bp - bv->buf;
+	bv->fm++;
+	bv->trunccount = bv->dontcount;
 	putpromptchar(doprint, endchar, txtchangep);
-	trunccount = 0;
-	ptr = buf + w;		/* putpromptchar() may have realloc()'d */
-	*bp = '\0';
+	bv->trunccount = 0;
+	ptr = bv->buf + w;		/* putpromptchar() may have realloc()'d */
+	*bv->bp = '\0';
 	/*
 	 * Now:
 	 *   ptr is the start of the truncation string and also
 	 *     where we need to start putting any truncated output
-	 *   bp is the end of the string we have just added, which
+	 *   bv->bp is the end of the string we have just added, which
 	 *     may need truncating.
 	 */
 
@@ -1142,28 +1168,28 @@
 	 * (note that above it was a raw string pointer difference).
 	 * It's the full width of the string we may need to truncate.
 	 *
-	 * truncwidth has come from the user, so we interpret this
+	 * bv->truncwidth has come from the user, so we interpret this
 	 * as a screen width, too.
 	 */
 	countprompt(ptr, &w, 0, -1);
-	if (w > truncwidth) {
+	if (w > bv->truncwidth) {
 	    /*
 	     * We need to truncate.  t points to the truncation string
 	     * -- which is inserted literally, without nice
 	     * representation.  twidth is its printing width, and maxwidth
 	     * is the amount of the main string that we want to keep.
 	     * Note that if the truncation string is longer than the
-	     * truncation length (twidth > truncwidth), the truncation
+	     * truncation length (twidth > bv->truncwidth), the truncation
 	     * string is used in full.
 	     */
 	    char *t = truncstr;
-	    int fullen = bp - ptr;
+	    int fullen = bv->bp - ptr;
 	    int twidth, maxwidth;
 	    int ntrunc = strlen(t);
 
 	    twidth = MB_METASTRWIDTH(t);
-	    if (twidth < truncwidth) {
-		maxwidth = truncwidth - twidth;
+	    if (twidth < bv->truncwidth) {
+		maxwidth = bv->truncwidth - twidth;
 		/*
 		 * It's not safe to assume there are no invisible substrings
 		 * just because the width is less than the full string
@@ -1171,7 +1197,7 @@
 		 */
 		addbufspc(ntrunc+1);
 		/* may have realloc'd */
-		ptr = bp - fullen;
+		ptr = bv->bp - fullen;
 
 		if (truncatleft) {
 		    /*
@@ -1284,7 +1310,7 @@
 		    while (*fulltextptr)
 			*ptr++ = *fulltextptr++;
 		    /* Mark the end of copying */
-		    bp = ptr;
+		    bv->bp = ptr;
 		} else {
 		    /*
 		     * Truncating at the right is easier: just leave
@@ -1360,19 +1386,19 @@
 		    ptr = skiptext;
 		    while (*t)
 			*ptr++ = *t++;
-		    bp = ptr;
+		    bv->bp = ptr;
 		    if (*skiptext) {
 			/* Move remaining text so we don't overwrite it */
-			memmove(bp, skiptext, strlen(skiptext)+1);
-			skiptext = bp;
+			memmove(bv->bp, skiptext, strlen(skiptext)+1);
+			skiptext = bv->bp;
 
 			/*
-			 * Copy anything we want, updating bp
+			 * Copy anything we want, updating bv->bp
 			 */
 			while (*skiptext) {
 			    if (*skiptext == Inpar) {
 				for (;;) {
-				    *bp++ = *skiptext;
+				    *bv->bp++ = *skiptext;
 				    if (*skiptext == Outpar ||
 					*skiptext == '\0')
 					break;
@@ -1388,39 +1414,39 @@
 		/* Just copy truncstr; no other text appears. */
 		while (*t)
 		    *ptr++ = *t++;
-		bp = ptr;
+		bv->bp = ptr;
 	    }
-	    *bp = '\0';
+	    *bv->bp = '\0';
 	}
 	zsfree(truncstr);
-	truncwidth = 0;
+	bv->truncwidth = 0;
 	/*
 	 * We may have returned early from the previous putpromptchar *
 	 * because we found another truncation following this one.    *
 	 * In that case we need to do the rest now.                   *
 	 */
-	if (!*fm)
+	if (!*bv->fm)
 	    return 0;
-	if (*fm != endchar) {
-	    fm++;
+	if (*bv->fm != endchar) {
+	    bv->fm++;
 	    /*
-	     * With truncwidth set to zero, we always reach endchar *
+	     * With bv->truncwidth set to zero, we always reach endchar *
 	     * (or the terminating NULL) this time round.         *
 	     */
 	    if (!putpromptchar(doprint, endchar, txtchangep))
 		return 0;
 	}
 	/* Now we have to trick it into matching endchar again */
-	fm--;
+	bv->fm--;
     } else {
-	if (*fm != ']')
-	    fm++;
-	while(*fm && *fm != truncchar) {
-	    if (*fm == '\\' && fm[1])
-		fm++;
-	    fm++;
+	if (*bv->fm != ']')
+	    bv->fm++;
+	while(*bv->fm && *bv->fm != truncchar) {
+	    if (*bv->fm == '\\' && bv->fm[1])
+		bv->fm++;
+	    bv->fm++;
 	}
-	if (truncwidth || !*fm)
+	if (bv->truncwidth || !*bv->fm)
 	    return 0;
     }
     return 1;
@@ -1872,14 +1898,14 @@
 	{
 	    if (is_prompt)
 	    {
-		if (!dontcount) {
+		if (!bv->dontcount) {
 		    addbufspc(1);
-		    *bp++ = Inpar;
+		    *bv->bp++ = Inpar;
 		}
 		tputs(tgoto(tcstr[tc], colour, colour), 1, putstr);
-		if (!dontcount) {
+		if (!bv->dontcount) {
 		    addbufspc(1);
-		    *bp++ = Outpar;
+		    *bv->bp++ = Outpar;
 		}
 	    } else {
 		tputs(tgoto(tcstr[tc], colour, colour), 1, putshout);
@@ -1907,14 +1933,14 @@
     strcpy(ptr, fg_bg_sequences[fg_bg].end);
 
     if (is_prompt) {
-	if (!dontcount) {
+	if (!bv->dontcount) {
 	    addbufspc(1);
-	    *bp++ = Inpar;
+	    *bv->bp++ = Inpar;
 	}
 	tputs(colseq_buf, 1, putstr);
-	if (!dontcount) {
+	if (!bv->dontcount) {
 	    addbufspc(1);
-	    *bp++ = Outpar;
+	    *bv->bp++ = Outpar;
 	}
     } else
 	tputs(colseq_buf, 1, putshout);
Index: Src/utils.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/utils.c,v
retrieving revision 1.203
diff -u -r1.203 utils.c
--- Src/utils.c	29 Sep 2008 15:18:55 -0000	1.203
+++ Src/utils.c	24 Oct 2008 10:21:08 -0000
@@ -863,7 +863,7 @@
 	    (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
 	    /* better duplicate this string since it's come from REPLY */
 	    finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir));
-	    finddir_last->node.nam = tricat("[", dupstring(ares[0]), "]");
+	    finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]");
 	    finddir_last->dir = dupstrpfx(finddir_full, len);
 	    finddir_last->diff = len - strlen(finddir_last->node.nam);
 	    finddir_best = len;


-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: prompt memory handling is screwy
  2008-10-24 10:24 PATCH: prompt memory handling is screwy Peter Stephenson
@ 2008-10-24 13:46 ` Peter Stephenson
  2008-10-24 14:40 ` Bart Schaefer
  1 sibling, 0 replies; 3+ messages in thread
From: Peter Stephenson @ 2008-10-24 13:46 UTC (permalink / raw)
  To: Zsh hackers list

On Fri, 24 Oct 2008 11:24:48 +0100
Peter Stephenson <pws@csr.com> wrote:
> Some idiot added a new feature recently that let the prompt code
> be called recursively.  Currently the prompt code isn't written to
> be called recursively, but luckily that's a fairly straightforward
> change, if boring to rename all the variables.

Here's a test.  This is actually more hairy even than the fix:  since I'm
testing directory handling I need to output directories and remove the
bits of the path that vary.  Hence if it fails it may well be the test, not
the shell.  This was giving segmentation violations before the patch.

Index: Test/D01prompt.ztst
===================================================================
RCS file: /cvsroot/zsh/zsh/Test/D01prompt.ztst,v
retrieving revision 1.4
diff -u -r1.4 D01prompt.ztst
--- Test/D01prompt.ztst	26 Sep 2008 09:11:30 -0000	1.4
+++ Test/D01prompt.ztst	24 Oct 2008 13:33:06 -0000
@@ -147,3 +147,57 @@
 >~[scuzzy]/rubbish
 >~mydir/foo
 ?(eval):33: no directory expansion: ~[scuzzy]
+
+  (
+  zsh_directory_name() {
+  emulate -L zsh
+  setopt extendedglob
+  local -a match mbegin mend
+  if [[ $1 = n ]]; then
+      if [[ $2 = *:l ]]; then
+	  reply=(${2%%:l}/very_long_directory_name)
+	  return 0
+      else
+	  return 1
+      fi
+  else
+      if [[ $2 = (#b)(*)/very_long_directory_name ]]; then
+	reply=(${match[1]}:l ${#2})
+	return 0
+      else
+	return 1
+      fi
+  fi
+  }
+  parent=$PWD
+  dir=$parent/very_long_directory_name
+  mkdir $dir
+  cd $dir
+  fn() {
+     PS4='+%N:%i> '
+     setopt localoptions xtrace
+     # The following is the key to the test.
+     # It invokes zsh_directory_name which does PS4 output stuff
+     # while we're doing prompt handling for the parameter
+     # substitution.  This checks recursion works OK.
+     local d=${(%):-%~}
+     print ${d//$parent/\<parent\>}
+  }
+  fn 2>stderr
+  # post process error to remove variable contents
+  while read line; do
+    # tricky: reply is set to include directory length which is variable
+    [[ $line = *reply* ]] && continue
+    print ${line//$parent/\<parent\>}
+  done <stderr >&2
+  )
+0:Recursive use of prompts
+>~[<parent>:l]
+?+zsh_directory_name:1> emulate -L zsh
+?+zsh_directory_name:2> setopt extendedglob
+?+zsh_directory_name:3> local -a match mbegin mend
+?+zsh_directory_name:4> [[ d == n ]]
+?+zsh_directory_name:12> [[ <parent>/very_long_directory_name == (#b)(*)/very_long_directory_name ]]
+?+zsh_directory_name:14> return 0
+?+fn:7> local 'd=~[<parent>:l]'
+?+fn:8> print '~[<parent>:l]'

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: PATCH: prompt memory handling is screwy
  2008-10-24 10:24 PATCH: prompt memory handling is screwy Peter Stephenson
  2008-10-24 13:46 ` Peter Stephenson
@ 2008-10-24 14:40 ` Bart Schaefer
  1 sibling, 0 replies; 3+ messages in thread
From: Bart Schaefer @ 2008-10-24 14:40 UTC (permalink / raw)
  To: Zsh hackers list

On Oct 24, 11:24am, Peter Stephenson wrote:
}
} Some idiot added a new feature recently that let the prompt code
} be called recursively.

I've forgotten what feature this was and why it ends up calling the
prompt code recursively.

However, now that you've fixed that, maybe there's an obvious way to
simplify the handling of the %( ... %) construct, particularly with
respect to prompt truncation.

No, I'm *not* suggesting tackling *that* before the 4.3.7 release.


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2008-10-24 14:41 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-24 10:24 PATCH: prompt memory handling is screwy Peter Stephenson
2008-10-24 13:46 ` Peter Stephenson
2008-10-24 14:40 ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).