1
0
Fork 0
mirror of git://git.code.sf.net/p/zsh/code synced 2025-09-11 13:01:28 +02:00

25930: dynamic directory expansion memory handling was screwy

This commit is contained in:
Peter Stephenson 2008-10-24 10:27:25 +00:00
parent b0e0d901b2
commit 337530b4d6
3 changed files with 229 additions and 197 deletions

View file

@ -1,3 +1,9 @@
2008-10-24 Peter Stephenson <pws@csr.com>
* 25930: Src/prompt.c, Src/utils.c: dynamic directory names
may need recursive prompt expansion; memory leak with reverse
expansion of dynamic directory names.
2008-10-23 Peter Stephenson <pws@csr.com> 2008-10-23 Peter Stephenson <pws@csr.com>
* users/13375: Src/Zle/zle_refresh.c: rewrite ternary expression * users/13375: Src/Zle/zle_refresh.c: rewrite ternary expression

View file

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

View file

@ -863,7 +863,7 @@ finddir(char *s)
(len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) { (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
/* better duplicate this string since it's come from REPLY */ /* better duplicate this string since it's come from REPLY */
finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir)); 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->dir = dupstrpfx(finddir_full, len);
finddir_last->diff = len - strlen(finddir_last->node.nam); finddir_last->diff = len - strlen(finddir_last->node.nam);
finddir_best = len; finddir_best = len;