diff options
author | Joe Rayhawk <jrayhawk@fairlystable.org> | 2025-04-30 02:07:56 -0700 |
---|---|---|
committer | Joe Rayhawk <jrayhawk@fairlystable.org> | 2025-04-30 02:07:56 -0700 |
commit | 26e09889646be3ea65b4a3dfeda26213e4bb6a27 (patch) | |
tree | 4f3c73a9416bf47ad7e125383d23cf42879e38d7 /Src/hist.c | |
parent | 841bce705a58b04220b1f257abcc00ae71cbdbdc (diff) | |
parent | 001cba48ce3b964cf01fb3e2af54b20eacbc9bf5 (diff) | |
download | zsh-26e09889646be3ea65b4a3dfeda26213e4bb6a27.tar.gz zsh-26e09889646be3ea65b4a3dfeda26213e4bb6a27.zip |
Merge branch 'upstream' into debian
Diffstat (limited to 'Src/hist.c')
-rw-r--r-- | Src/hist.c | 93 |
1 files changed, 59 insertions, 34 deletions
diff --git a/Src/hist.c b/Src/hist.c index bff0abe61..00bdbb2b8 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -34,25 +34,25 @@ * word control. */ /**/ -mod_export int (*hgetc) _((void)); +mod_export int (*hgetc) (void); /**/ -void (*hungetc) _((int)); +void (*hungetc) (int); /**/ -void (*hwaddc) _((int)); +void (*hwaddc) (int); /**/ -void (*hwbegin) _((int)); +void (*hwbegin) (int); /**/ -void (*hwabort) _((void)); +void (*hwabort) (void); /**/ -void (*hwend) _((void)); +void (*hwend) (void); /**/ -void (*addtoline) _((int)); +void (*addtoline) (int); /* != 0 means history substitution is turned off */ @@ -163,6 +163,11 @@ char *hsubl; /**/ char *hsubr; +/* state of histsubstpattern at last substitution */ + +/**/ +int hsubpatopt; + /* pointer into the history line */ /**/ @@ -624,7 +629,7 @@ histsubchar(int c) return substfailed(); if (!hsubl) return -1; - if (subst(&sline, hsubl, hsubr, gbal)) + if (subst(&sline, hsubl, hsubr, gbal, 0)) return substfailed(); } else { /* Line doesn't begin ^foo^bar */ @@ -831,7 +836,7 @@ histsubchar(int c) if ((c = ingetc()) == 'g') { gbal = 1; c = ingetc(); - if (c != 's' && c != '&') { + if (c != 's' && c != 'S' && c != '&') { zerr("'s' or '&' modifier expected after 'g'"); return -1; } @@ -891,11 +896,13 @@ histsubchar(int c) } break; case 's': + case 'S': + hsubpatopt = (c == 'S'); if (getsubsargs(sline, &gbal, &cflag)) return -1; /* fall through */ case '&': if (hsubl && hsubr) { - if (subst(&sline, hsubl, hsubr, gbal)) + if (subst(&sline, hsubl, hsubr, gbal, hsubpatopt)) return substfailed(); } else { herrflush(); @@ -1352,7 +1359,8 @@ putoldhistentryontop(short keep_going) do { if (max_unique_ct-- <= 0 || he == hist_ring) { max_unique_ct = 0; - he = hist_ring->down; + if (hist_ring) + he = hist_ring->down; next = hist_ring; break; } @@ -1360,12 +1368,16 @@ putoldhistentryontop(short keep_going) next = he->down; } while (!(he->node.flags & HIST_DUP)); } - if (he != hist_ring->down) { + /* Is it really possible for hist_ring to be NULL here? */ + if (he && (!hist_ring || he != hist_ring->down)) { he->up->down = he->down; he->down->up = he->up; he->up = hist_ring; - he->down = hist_ring->down; - hist_ring->down = he->down->up = he; + if (hist_ring) { + he->down = hist_ring->down; + hist_ring->down = he; + } + he->down->up = he; } hist_ring = he; } @@ -1461,7 +1473,7 @@ should_ignore_line(Eprog prog) mod_export int hend(Eprog prog) { - int flag, hookret, stack_pos = histsave_stack_pos; + int flag, hookret = 0, stack_pos = histsave_stack_pos; /* * save: * 0: don't save @@ -1643,12 +1655,17 @@ hend(Eprog prog) void ihwbegin(int offset) { + int pos = hptr - chline + offset; if (stophist == 2 || (histactive & HA_INWORD) || (inbufflags & (INP_ALIAS|INP_HIST)) == INP_ALIAS) return; if (chwordpos%2) chwordpos--; /* make sure we're on a word start, not end */ - chwords[chwordpos++] = hptr - chline + offset; + DPUTS1(pos < 0, "History word position < 0 in %s", + dupstrpfx(chline, hptr-chline)); + if (pos < 0) + pos = 0; + chwords[chwordpos++] = pos; } /* Abort current history word, not needed */ @@ -2235,7 +2252,7 @@ casemodify(char *str, int how) char *mbptr; for (mbptr = mbstr; mbptr < mbstr + len2; mbptr++) { - if (imeta(STOUC(*mbptr))) { + if (imeta((unsigned char) *mbptr)) { *ptr2++ = Meta; *ptr2++ = *mbptr ^ 32; } else @@ -2254,10 +2271,10 @@ casemodify(char *str, int how) int c; int mod = 0; if (*str == Meta) { - c = STOUC(str[1] ^ 32); + c = (unsigned char) (str[1] ^ 32); str += 2; } else - c = STOUC(*str++); + c = (unsigned char) *str++; switch (how) { case CASMOD_LOWER: if (isupper(c)) { @@ -2310,7 +2327,7 @@ casemodify(char *str, int how) /**/ int -subst(char **strptr, char *in, char *out, int gbal) +subst(char **strptr, char *in, char *out, int gbal, int forcepat) { char *str = *strptr, *substcut, *sptr; int off, inlen, outlen; @@ -2318,7 +2335,7 @@ subst(char **strptr, char *in, char *out, int gbal) if (!*in) in = str, gbal = 0; - if (isset(HISTSUBSTPATTERN)) { + if (isset(HISTSUBSTPATTERN) || forcepat) { int fl = SUB_LONG|SUB_REST|SUB_RETFAIL; char *oldin = in; if (gbal) @@ -2821,11 +2838,12 @@ readhistfile(char *fn, int err, int readflags) */ if (uselex || remeta) freeheap(); - if (errflag & ERRFLAG_INT) { - /* Can't assume fast read next time if interrupted. */ - lasthist.interrupted = 1; + if (errflag & ERRFLAG_INT) break; - } + } + if (errflag & ERRFLAG_INT) { + /* Can't assume fast read next time if interrupted. */ + lasthist.interrupted = 1; } if (start && readflags & HFILE_USE_OPTIONS) { zsfree(lasthist.text); @@ -2874,9 +2892,9 @@ flockhistfile(char *fn, int keep_trying) /* * Timeout is ten seconds. */ - end_time = time(NULL) + (time_t)10; + end_time = zmonotime(NULL) + (time_t)10; while (fcntl(flock_fd, F_SETLKW, &lck) == -1) { - if (!keep_trying || time(NULL) >= end_time || + if (!keep_trying || zmonotime(NULL) >= end_time || /* * Randomise wait to minimise clashes with shells exiting at * the same time. @@ -3091,7 +3109,9 @@ savehistfile(char *fn, int err, int writeflags) hist_ignore_all_dups |= isset(HISTSAVENODUPS); readhistfile(fn, err, 0); hist_ignore_all_dups = isset(HISTIGNOREALLDUPS); - if (histlinect) + if (errflag & ERRFLAG_INT) + ret = -1; + else if (histlinect) savehistfile(fn, err, 0); pophiststack(); @@ -3120,7 +3140,7 @@ static int lockhistct; static int checklocktime(char *lockfile, long *sleep_usp, time_t then) { - time_t now = time(NULL); + time_t now = zmonotime(NULL); if (now + 10 < then) { /* File is more than 10 seconds in the future? */ @@ -3536,9 +3556,8 @@ bufferwords(LinkList list, char *buf, int *index, int flags) } else if (buf) { if (IS_REDIROP(tok) && tokfd >= 0) { char b[20]; - - sprintf(b, "%d%s", tokfd, tokstrings[tok]); - addlinknode(list, dupstring(b)); + int l = sprintf(b, "%d%s", tokfd, tokstrings[tok]); + addlinknode(list, dupstring_wlen(b, l)); num++; } else if (tok != NEWLIN) { addlinknode(list, dupstring(tokstrings[tok])); @@ -3791,8 +3810,14 @@ histsplitwords(char *lineptr, short **wordsp, int *nwordsp, int *nwordposp, zrealloc(words, nwords*sizeof(*words)); } words[nwordpos++] = lineptr - start; - while (*lineptr && !inblank(*lineptr)) - lineptr++; + while (*lineptr) { + if (*lineptr == Meta && lineptr[1]) + lineptr += 2; + else if (!inblank(*lineptr)) + lineptr++; + else + break; + } words[nwordpos++] = lineptr - start; } } while (*lineptr); |