From a39c3adecee0998e61b340c84581dd7744de2cc4 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 23 Oct 2014 17:00:31 +0200 Subject: 33512: add support for "0 vi buffer and yank to it --- Src/Zle/zle_utils.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 1089e274f..1479365df 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -43,10 +43,10 @@ struct cutbuffer *kring; int kringsize, kringnum; /* Vi named cut buffers. 0-25 are the named buffers "a to "z, and * - * 26-34 are the numbered buffer stack "1 to "9. */ + * 26-35 are the numbered buffer stack "0 to "9. */ /**/ -struct cutbuffer vibuf[35]; +struct cutbuffer vibuf[36]; /* the line before last mod (for undo purposes) */ @@ -942,16 +942,23 @@ cuttext(ZLE_STRING_T line, int ct, int flags) b->len = len + ct; } return; + } else if (flags & CUT_YANK) { + /* Save in "0 */ + free(vibuf[26].buf); + vibuf[26].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); + ZS_memcpy(vibuf[26].buf, line, ct); + vibuf[26].len = ct; + vibuf[26].flags = vilinerange ? CUTBUFFER_LINE : 0; } else { /* Save in "1, shifting "1-"8 along to "2-"9 */ int n; free(vibuf[34].buf); - for(n=34; n>26; n--) + for(n=35; n>27; n--) vibuf[n] = vibuf[n-1]; - vibuf[26].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); - ZS_memcpy(vibuf[26].buf, line, ct); - vibuf[26].len = ct; - vibuf[26].flags = vilinerange ? CUTBUFFER_LINE : 0; + vibuf[27].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); + ZS_memcpy(vibuf[27].buf, line, ct); + vibuf[27].len = ct; + vibuf[27].flags = vilinerange ? CUTBUFFER_LINE : 0; } if (!cutbuf.buf) { cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE); -- cgit v1.2.3 From 72c666fb4fd2ad4551a83f4cc40f99fa491afa92 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 23 Oct 2014 17:14:19 +0200 Subject: 33514: even with a named vi buffer, we should update the default buffer --- ChangeLog | 3 +++ Src/Zle/zle_utils.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index f209352a5..f96b4e3e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2014-10-23 Oliver Kiddle + * 33514: Src/Zle/zle_utils.c: even with a named vi buffer, we + should update the default buffer + * 33513: Src/Zle/iwidgets.list: vi mode deletions should replace cut buffer not append to it diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 1479365df..f69bc77c9 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -941,7 +941,6 @@ cuttext(ZLE_STRING_T line, int ct, int flags) ZS_memcpy(b->buf + len, line, ct); b->len = len + ct; } - return; } else if (flags & CUT_YANK) { /* Save in "0 */ free(vibuf[26].buf); -- cgit v1.2.3 From bdedf7b40b85f54979c1e9d19445f8dfbf64967d Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 23 Oct 2014 21:47:23 +0200 Subject: 33518: add support for "_ vi buffer and arguments to vi-set-buffer from a zle widget --- ChangeLog | 4 ++++ Doc/Zsh/zle.yo | 36 ++++++++++++++++++++------------ Src/Zle/zle.h | 1 + Src/Zle/zle_utils.c | 2 +- Src/Zle/zle_vi.c | 24 +++++++++++++++------ Test/X02zlevi.ztst | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 107 insertions(+), 20 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index f96b4e3e2..79e1701c8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2014-10-23 Oliver Kiddle + * 33518: Doc/Zsh/zle.yo, Src/Zle/zle.h, Src/Zle/zle_utils.c, + Src/Zle/zle_vi.c, Test/X02zlevi.ztst: add support for "_ vi + buffer and arguments to vi-set-buffer from a zle widget + * 33514: Src/Zle/zle_utils.c: even with a named vi buffer, we should update the default buffer diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 98f38025a..881e56b19 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -2180,19 +2180,29 @@ command. tt(run-help) is normally aliased to tt(man). tindex(vi-set-buffer) item(tt(vi-set-buffer) (unbound) (") (unbound))( Specify a buffer to be used in the following command. -There are 35 buffers that can be specified: -the 26 `named' buffers tt("a) to tt("z) -and the nine `queued' buffers tt("1) to tt("9). The named buffers can also -be specified as tt("A) to tt("Z). - -When a buffer is specified for a cut command, the text being cut replaces -the previous contents of the specified buffer. If a named buffer -is specified using a capital, the newly cut text is appended to the buffer -instead of overwriting it. - -If no buffer is specified for a cut command, tt("1) is used, and the -contents of tt("1) to tt("8) are each shifted along one buffer; the contents of -tt("9) is lost. +There are 37 buffers that can be specified: +the 26 `named' buffers tt("a) to tt("z), the `yank' buffer tt("0), +the nine `queued' buffers tt("1) to tt("9) and the `black hole' buffer +tt("_). The named buffers can also be specified as tt("A) to tt("Z). + +When a buffer is specified for a cut, change or yank command, the text +concerned replaces the previous contents of the specified buffer. If +a named buffer is specified using a capital, the newly cut text is +appended to the buffer instead of overwriting it. When using the tt("_) +buffer, nothing happens. This can be useful for deleting text without +affecting the normal registers. + +If no buffer is specified for a cut or change command, tt("1) is used, and +the contents of tt("1) to tt("8) are each shifted along one buffer; +the contents of tt("9) is lost. If no buffer is specified for a yank +command, tt("0") is used. Finally, a paste command without a specified +buffer will paste the text from the most recent command regardless of any +buffer that might have been used with that command. + +When called from a widget function by the tt(zle) command, the buffer +can optionally be specified with an argument. For example, + +example(zle vi-set-buffer A) ) tindex(vi-set-mark) item(tt(vi-set-mark) (unbound) (m) (unbound))( diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h index 860c8217c..dd6cdcca0 100644 --- a/Src/Zle/zle.h +++ b/Src/Zle/zle.h @@ -240,6 +240,7 @@ struct modifier { #define MOD_VIBUF (1<<2) /* a vi cut buffer has been selected */ #define MOD_VIAPP (1<<3) /* appending to the vi cut buffer */ #define MOD_NEG (1<<4) /* last command was negate argument */ +#define MOD_NULL (1<<5) /* throw away text for the vi cut buffer */ /* current modifier status */ diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index f69bc77c9..46d5373fb 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -914,7 +914,7 @@ cut(int i, int ct, int flags) void cuttext(ZLE_STRING_T line, int ct, int flags) { - if (!ct) + if (!ct || zmod.flags & MOD_NULL) return; UNMETACHECK(); diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 2555c6a00..20cece0a8 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -782,7 +782,7 @@ viputbefore(UNUSED(char **args)) int n = zmult; startvichange(-1); - if (n < 0) + if (n < 0 || zmod.flags & MOD_NULL) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; @@ -814,7 +814,7 @@ viputafter(UNUSED(char **args)) int n = zmult; startvichange(-1); - if (n < 0) + if (n < 0 || zmod.flags & MOD_NULL) return 1; if (zmod.flags & MOD_VIBUF) buf = &vibuf[zmod.vibuf]; @@ -905,14 +905,26 @@ vicapslockpanic(UNUSED(char **args)) /**/ int -visetbuffer(UNUSED(char **args)) +visetbuffer(char **args) { ZLE_INT_T ch; - if ((zmod.flags & MOD_VIBUF) || - (((ch = getfullchar(0)) < ZWC('0') || ch > ZWC('9')) && + if (*args) { + ch = **args; + if (args[1] || (ch && (*args)[1])) + return 1; + } else { + ch = getfullchar(0); + } + if (ch == ZWC('_')) { + zmod.flags |= MOD_NULL; + prefixflag = 1; + return 0; + } else + zmod.flags &= ~MOD_NULL; + if ((ch < ZWC('0') || ch > ZWC('9')) && (ch < ZWC('a') || ch > ZWC('z')) && - (ch < ZWC('A') || ch > ZWC('Z')))) + (ch < ZWC('A') || ch > ZWC('Z'))) return 1; if (ch >= ZWC('A') && ch <= ZWC('Z')) /* needed in cut() */ zmod.flags |= MOD_VIAPP; diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst index 19188dfb7..4a39442e1 100644 --- a/Test/X02zlevi.ztst +++ b/Test/X02zlevi.ztst @@ -10,6 +10,66 @@ %test + zletest $'yankee doodle\ebhDyy0"1P' +0:paste register 1 to get last deletion +>BUFFER: doodleyankee +>CURSOR: 6 + + zletest $'yankee\eyyodoodle\edd"0p' +0:paste register 0 to get last yank +>BUFFER: yankee +>yankee +>CURSOR: 7 + + zletest $'err\eddahello\e"hddP' +0:setting named register also sets unnamed register +>BUFFER: hello +>CURSOR: 0 + + zletest $'first\e"ay0ddasecond\e"Add"aP' +0:appending to named register +>BUFFER: firs +>second +>CURSOR: 0 + + zletest $'word\e"a"byy"bp' +0:set one and then a different register +>BUFFER: word +>word +>CURSOR: 5 + + zletest $'i\exaar\e0"a"_cewn\eP' +0:set register then set black hole register +>BUFFER: win +>CURSOR: 1 + + zletest $'double\eyy"_"0P' +0:reset register after selecting black hole +>BUFFER: double +>double +>CURSOR: 0 + +# zsh works like vi here; in vim you get the concatenated string + zletest $'first\e"addasecond\eddP' +0:retrieve unnamed register after appending +>BUFFER: second +>CURSOR: 0 + + zletest $'Z\exayankee doodle\e"_db0"_yeP' +0:yank and delete to black hole register +>BUFFER: Zyankee e +>CURSOR: 0 + + zletest $'foo\eddabar\e"_p..' +0:paste from black hole register and repeat +>BUFFER: bar +>CURSOR: 2 + + zletest $'start\eFa"ac2lnew\eX"ap..' +0:repeat paste from named register +>BUFFER: stnwararart +>CURSOR: 9 + zletest $'word\euaend' 0:undo initial change >BUFFER: end -- cgit v1.2.3 From 4d89ec25f17712e8e1710727a7ca211c5591d9e9 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Mon, 3 Nov 2014 00:31:57 +0100 Subject: 33575: reset vi change start position if text is inserted before it or on history movement --- ChangeLog | 5 +++++ Src/Zle/zle_params.c | 2 +- Src/Zle/zle_utils.c | 3 +++ 3 files changed, 9 insertions(+), 1 deletion(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 678b561ac..2616ac480 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-11-02 Oliver Kiddle + + * 33575: Src/Zle/zle_params.c, Src/Zle/zle_utils.c: reset vi change + start position if text is inserted before it or on history movement + 2014-11-02 Peter Stephenson * 33591: Src/exec.c, Test/D04parameter.ztst: don't treat an exec diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c index 5845207fa..dc5fed4ce 100644 --- a/Src/Zle/zle_params.c +++ b/Src/Zle/zle_params.c @@ -198,7 +198,7 @@ set_buffer(UNUSED(Param pm), char *x) setline(x, 0); zsfree(x); } else - zlecs = zlell = 0; + viinsbegin = zlecs = zlell = 0; fixsuffix(); menucmp = 0; } diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 46d5373fb..741f119d2 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -785,6 +785,8 @@ spaceinline(int ct) if (mark > zlecs) mark += ct; + if (viinsbegin > zlecs) + viinsbegin = 0; if (region_highlights) { for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; @@ -1104,6 +1106,7 @@ setline(char *s, int flags) */ free(zleline); + viinsbegin = 0; zleline = stringaszleline(scp, 0, &zlell, &linesz, NULL); if ((flags & ZSL_TOEND) && (zlecs = zlell) && invicmdmode()) -- cgit v1.2.3 From c7ff843ecf60ab74ce98929e45029b1aef5014e1 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Wed, 5 Nov 2014 22:50:48 +0100 Subject: 33604: fix change merging for vi mode where a change has just been undone --- ChangeLog | 5 +++++ Src/Zle/zle_utils.c | 6 +++--- Src/Zle/zle_vi.c | 4 ++-- Test/X02zlevi.ztst | 6 ++++++ 4 files changed, 16 insertions(+), 5 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 1b17490cf..cb739d5a1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-11-05 Oliver Kiddle + + * 33604: Src/Zle/zle_utils.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst: + fix change merging for vi mode where a change has just been undone + 2014-11-04 Oliver Kiddle * 33596: Src/Zle/zle_keymap.c: make local keymap keybinding hide diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 741f119d2..e95a34b95 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1395,7 +1395,8 @@ static struct change *nextchanges, *endnextchanges; /* incremented to provide a unique change number */ -static zlong undo_changeno; +/**/ +zlong undo_changeno; /* If non-zero, the last increment to undo_changeno was for the variable */ @@ -1668,8 +1669,7 @@ splitundo(char **args) { if (vistartchange >= 0) { mergeundo(); - vistartchange = (curchange && curchange->prev) ? - curchange->prev->changeno : 0; + vistartchange = undo_changeno; } handleundo(); return 0; diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c index 18c76f917..d74b40d62 100644 --- a/Src/Zle/zle_vi.c +++ b/Src/Zle/zle_vi.c @@ -109,7 +109,7 @@ startvitext(int im) { startvichange(im); selectkeymap("main", 1); - vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0; + vistartchange = undo_changeno; viinsbegin = zlecs; } @@ -403,7 +403,7 @@ vichange(UNUSED(char **args)) forekill(c2 - zlecs, CUT_RAW); selectkeymap("main", 1); viinsbegin = zlecs; - vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0; + vistartchange = undo_changeno; } return ret; } diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst index f8a94ce3d..561a5fd73 100644 --- a/Test/X02zlevi.ztst +++ b/Test/X02zlevi.ztst @@ -205,6 +205,12 @@ zletest $'pre\eA123\C-_\C-y\eu' 0:undo and redo in insert mode, undo in command >BUFFER: pre +>CURSOR: 2 + + zletest $'two\eOone\eo\euo\eu' +0:undo starting with a next change in the change list +>BUFFER: one +>two >CURSOR: 2 zpty_run 'bindkey "^Gu" split-undo' -- cgit v1.2.3 From 36b8f8331939a1b5ccc40b39787a1b8901acc6f9 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 7 Nov 2014 11:29:13 +0100 Subject: 33624: keep region active when widget fails --- ChangeLog | 4 ++++ Src/Zle/zle_utils.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 24c1396bb..4c1c88a6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-11-06 Oliver Kiddle + + * 33624: Src/Zle/zle_utils.c: keep region active when widget fails + 2014-11-07 Mikael Magnusson * 33607: Src/Modules/attr.c: Fix some minor problems in zattr module diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index e95a34b95..03a2bdca7 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1365,7 +1365,6 @@ int handlefeep(UNUSED(char **args)) { zbeep(); - region_active = 0; return 0; } -- cgit v1.2.3 From 99382e689dc41731ee225221964d58732ff7a4e6 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 13 Nov 2014 09:58:34 +0100 Subject: 33669: allow an empty line to be yanked with yy This by allocating 1 byte instead of 0 for the empty buffer. --- ChangeLog | 5 +++++ Src/Zle/zle_utils.c | 5 +++-- Test/X02zlevi.ztst | 7 +++++++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 64d0820be..5609754f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-11-13 Oliver Kiddle + + * 33669: Src/Zle/zle_utils.c, Test/X02zlevi.ztst: allow an empty + line to be yanked with yy by allocating 1 byte instead of 0 + 2014-11-11 Peter Stephenson * 33658: Doc/Zsh/options.yo: AUTO_CD depends on SHIN_STDIN. diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 03a2bdca7..f56063e82 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -916,7 +916,7 @@ cut(int i, int ct, int flags) void cuttext(ZLE_STRING_T line, int ct, int flags) { - if (!ct || zmod.flags & MOD_NULL) + if (!(ct || vilinerange) || zmod.flags & MOD_NULL) return; UNMETACHECK(); @@ -989,8 +989,9 @@ cuttext(ZLE_STRING_T line, int ct, int flags) cutbuf.buf = s; cutbuf.len += ct; } else { + /* don't alloc 0 bytes; length 0 occurs for blank lines in vi mode */ cutbuf.buf = realloc((char *)cutbuf.buf, - (cutbuf.len + ct) * ZLE_CHAR_SIZE); + (cutbuf.len + (ct ? ct : 1)) * ZLE_CHAR_SIZE); ZS_memcpy(cutbuf.buf + cutbuf.len, line, ct); cutbuf.len += ct; } diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst index 7e5385bfe..4b9c4d91f 100644 --- a/Test/X02zlevi.ztst +++ b/Test/X02zlevi.ztst @@ -30,6 +30,13 @@ >BUFFER: one >CURSOR: 0 + zletest $'1\eo\eyya2\epa3' +0:yank and paste blank line +>BUFFER: 1 +>2 +>3 +>CURSOR: 5 + zletest $' four\eO\C-v\tthree\eO two\eOone\e3J' 0:join lines with line count >BUFFER: one two three -- cgit v1.2.3 From 0ea8f28e7b230315fe3fcca162a15258b618b0b2 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Mon, 17 Nov 2014 16:32:04 +0100 Subject: 33700: new widget for put in vim style visual selection mode --- ChangeLog | 4 ++++ Doc/Zsh/zle.yo | 7 ++++++ Src/Zle/iwidgets.list | 1 + Src/Zle/zle_misc.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++---- Src/Zle/zle_utils.c | 2 +- 5 files changed, 70 insertions(+), 5 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 1491234a3..fc9f8e5fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2014-11-17 Oliver Kiddle + * 33700: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, + Src/Zle/zle_misc.c, Src/Zle/zle_utils.c: new widget + for put in vim style visual selection mode + * 33699: Test/X02zlevi.ztst, Test/comptest: support short delays in zle tests where we need KEYTIMEOUT to elapse diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo index 6fe7c9bf2..998bf4a10 100644 --- a/Doc/Zsh/zle.yo +++ b/Doc/Zsh/zle.yo @@ -1721,6 +1721,13 @@ Insert the contents of the kill buffer after the cursor. If the kill buffer contains a sequence of lines (as opposed to characters), paste it below the current line. ) +tindex(put-replace-selection) +item(tt(put-replace-selection) (unbound) (unbound) (unbound))( +Replace the contents of the current region or selection with the +contents of the kill buffer. If the kill buffer contains a sequence of +lines (as opposed to characters), the current line will be split by the +pasted lines. +) tindex(quoted-insert) item(tt(quoted-insert) (^V) (unbound) (unbound))( Insert the next character typed into the buffer literally. diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list index a2bad5aa9..070116f5f 100644 --- a/Src/Zle/iwidgets.list +++ b/Src/Zle/iwidgets.list @@ -89,6 +89,7 @@ "push-input", pushinput, 0 "push-line", pushline, 0 "push-line-or-edit", pushlineoredit, 0 +"put-replace-selection", putreplaceselection, ZLE_KEEPSUFFIX "quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX "quote-line", quoteline, 0 "quote-region", quoteregion, 0 diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index 3d4a9bb4e..3e6d1aaac 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -507,11 +507,26 @@ yank(UNUSED(char **args)) return 0; } -static void pastebuf(Cutbuffer buf, int mult, int after) +/* position: 0 is before, 1 after, 2 split the line */ +static void pastebuf(Cutbuffer buf, int mult, int position) { int cc; if (buf->flags & CUTBUFFER_LINE) { - if (after) { + if (position == 2) { + if (!zlecs) + position = 0; + else if (zlecs == zlell) + position = 1; + } + if (position == 2) { + yankb = zlecs; + spaceinline(buf->len + 2); + zleline[zlecs++] = ZWC('\n'); + ZS_memcpy(zleline + zlecs, buf->buf, buf->len); + zlecs += buf->len; + zleline[zlecs] = ZWC('\n'); + yanke = zlecs + 1; + } else if (position != 0) { yankb = zlecs = findeol(); spaceinline(buf->len + 1); zleline[zlecs++] = ZWC('\n'); @@ -526,7 +541,7 @@ static void pastebuf(Cutbuffer buf, int mult, int after) } vifirstnonblank(zlenoargs); } else { - if (after && zlecs != findeol()) + if (position == 1 && zlecs != findeol()) INCCS(); yankb = zlecs; cc = buf->len; @@ -583,6 +598,44 @@ viputafter(UNUSED(char **args)) return 0; } +/**/ +int +putreplaceselection(UNUSED(char **args)) +{ + int n = zmult; + struct cutbuffer prevbuf; + Cutbuffer putbuf; + int clear = 0; + int pos = 2; + + startvichange(-1); + if (n < 0 || zmod.flags & MOD_NULL) + return 1; + putbuf = (zmod.flags & MOD_VIBUF) ? &vibuf[zmod.vibuf] : &cutbuf; + if (!putbuf->buf) + return 1; + memcpy(&prevbuf, putbuf, sizeof(prevbuf)); + + /* if "9 was specified, prevent killregion from freeing it */ + if (zmod.vibuf == 35) { + putbuf->buf = 0; + clear = 1; + } + + zmod.flags = 0; /* flags apply to paste not kill */ + if (region_active == 2 && prevbuf.flags & CUTBUFFER_LINE) { + int a, b; + regionlines(&a, &b); + pos = (b == zlell); + } + killregion(zlenoargs); + + pastebuf(&prevbuf, n, pos); + if (clear) + free(prevbuf.buf); + return 0; +} + /**/ int yankpop(UNUSED(char **args)) @@ -635,7 +688,7 @@ yankpop(UNUSED(char **args)) zlecs = yankb; foredel(yanke - yankb, CUT_RAW); zlecs = yankcs; - pastebuf(buf, 1, lastcmd & ZLE_YANKAFTER); + pastebuf(buf, 1, !!(lastcmd & ZLE_YANKAFTER)); return 0; } diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index f56063e82..08a32c30e 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -953,7 +953,7 @@ cuttext(ZLE_STRING_T line, int ct, int flags) } else { /* Save in "1, shifting "1-"8 along to "2-"9 */ int n; - free(vibuf[34].buf); + free(vibuf[35].buf); for(n=35; n>27; n--) vibuf[n] = vibuf[n-1]; vibuf[27].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE); -- cgit v1.2.3 From d067ebcacd55472f720b2765ec686a69b25c9a90 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 7 Dec 2014 16:24:19 +0000 Subject: 33876: etc.: Separate errors and keyboards interrupts Combination of 12 commits from interrupt_abort branch. Basic strategy is to introduce bits to errflag and to set and reset them separately. Remove interrupt status on return to main keymap. Turn off ERRFLAG_INT for always block. Restore bit thereafter: we probably need a new variable in order to allow user interrupts to be reset in the always block. Add TRY_BLOCK_INTERRUPT This works the same as TRY_BLOCK_ERROR, but for a SIGINT, too. Ensure propagation of SIGINT from exited job. If received by foreground job, shell uses ERRFLAG_INT, not ERRFLAG_ERROR, to set the new state. Reset errflag before precmd() Add always block in _main_completion to fix ZLS_COLORS Ensures we get the right state of $ZLS_COLORS at the end of _main_complete even if there's an interrupt. However, the "right state" is a bit messy as it depends on styles. --- ChangeLog | 20 +++++++++++-- Completion/Base/Core/_main_complete | 21 ++++++++------ Doc/Zsh/params.yo | 11 ++++++++ Src/Modules/zpty.c | 2 +- Src/Modules/zutil.c | 8 ++++-- Src/Zle/compcore.c | 2 +- Src/Zle/compctl.c | 10 +++---- Src/Zle/compresult.c | 2 +- Src/Zle/textobjects.c | 2 +- Src/Zle/zle_hist.c | 6 ++-- Src/Zle/zle_keymap.c | 10 +++++++ Src/Zle/zle_main.c | 14 ++++++---- Src/Zle/zle_misc.c | 2 +- Src/Zle/zle_tricky.c | 20 +++++++++++-- Src/Zle/zle_utils.c | 3 +- Src/builtin.c | 22 +++++++-------- Src/exec.c | 56 +++++++++++++++++++++++-------------- Src/glob.c | 12 ++++---- Src/hist.c | 10 ++++--- Src/init.c | 29 ++++++++++++++++--- Src/input.c | 3 +- Src/jobs.c | 23 +++++++++------ Src/lex.c | 5 ++-- Src/loop.c | 28 ++++++++++++++++--- Src/params.c | 13 +++++---- Src/parse.c | 31 ++++++++++---------- Src/prompt.c | 7 +++-- Src/signals.c | 28 ++++++++++++++++--- Src/subst.c | 27 ++++++++++++------ Src/utils.c | 8 +++--- Src/zsh.h | 14 ++++++++++ 31 files changed, 315 insertions(+), 134 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index 94e28ccb2..e30324894 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2014-12-11 Peter Stephenson + + * 33876: etc.: Completion/Base/Core/_main_complete, + Doc/Zsh/params.yo, Src/Modules/zpty.c, Src/Modules/zutil.c, + Src/Zle/compcore.c, Src/Zle/compctl.c, Src/Zle/compresult.c, + Src/Zle/textobjects.c, Src/Zle/zle_hist.c, Src/Zle/zle_keymap.c, + Src/Zle/zle_main.c, Src/Zle/zle_misc.c, Src/Zle/zle_tricky.c, + Src/Zle/zle_utils.c, Src/builtin.c, Src/exec.c, Src/glob.c, + Src/hist.c, Src/init.c, Src/input.c, Src/jobs.c, Src/lex.c, + Src/loop.c, Src/params.c, Src/parse.c, Src/prompt.c, + Src/signals.c, Src/subst.c, Src/utils.c, Src/zsh.h: Separate + shell errors and user interrupt flags into different bits of + errflag: ERRFLAG_ERROR and ERRFLAG_INT. Various + rationalisations to make keyboard interrupts work smoothly. + Work done on interrupt_abort branch. + 2014-12-10 Mikael Magnusson * 33948: Completion/Unix/Command/_getent, @@ -612,7 +628,7 @@ * 33354: Src/jobs.c, Test/A05execution.ztst: when backgrounding a pipeline, close all pipe descriptors in the parent; add test for both this and 33345+33346 - + 2014-10-03 Bart Schaefer * 33346: Src/parse.c: another bit of the 33345 repair @@ -2083,7 +2099,7 @@ 2013-12-20 Barton E. Schaefer * 32172; Test/A05execution.ztst: regression test for 32171 - + * 32171: Src/exec.c: fix leaked pipe descriptor that could deadlock a pipeline from a complex shell construct or function into an external command diff --git a/Completion/Base/Core/_main_complete b/Completion/Base/Core/_main_complete index bc63e83fb..d6a100777 100644 --- a/Completion/Base/Core/_main_complete +++ b/Completion/Base/Core/_main_complete @@ -43,6 +43,8 @@ local -a precommands typeset -U _lastdescr _comp_ignore _comp_colors +{ + [[ -z "$curcontext" ]] && curcontext=::: zstyle -s ":completion:${curcontext}:" insert-tab tmp || tmp=yes @@ -349,17 +351,20 @@ fi ( "$_comp_force_list" = ?* && nm -ge _comp_force_list ) ]] && compstate[list]="${compstate[list]//messages} force" -if [[ "$compstate[old_list]" = keep ]]; then - if [[ $_saved_colors_set = 1 ]]; then - ZLS_COLORS="$_saved_colors" +} always { + # Stuff we always do to clean up. + if [[ "$compstate[old_list]" = keep ]]; then + if [[ $_saved_colors_set = 1 ]]; then + ZLS_COLORS="$_saved_colors" + else + unset ZLS_COLORS + fi + elif (( $#_comp_colors )); then + ZLS_COLORS="${(j.:.)_comp_colors}" else unset ZLS_COLORS fi -elif (( $#_comp_colors )); then - ZLS_COLORS="${(j.:.)_comp_colors}" -else - unset ZLS_COLORS -fi +} # Now call the post-functions. diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index 5833d6be9..391a5fb0a 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -754,6 +754,17 @@ It may be reset, clearing the error condition. See ifzman(em(Complex Commands) in zmanref(zshmisc))\ ifnzman(noderef(Complex Commands)) ) +vindex(TRY_BLOCK_INTERRUPT) +item(tt(TRY_BLOCK_INTERRUPT) )( +This variable works in a similar way to tt(TRY_BLOCK_ERROR), but +represents the status of an interrupt from the signal SIGINT, which +typically comes from the keyboard when the user types tt(^C). If set to +0, any such interrupt will be reset; otherwise, the interrupt is +propagated after the tt(always) block. + +Note that it is possible that an interrupt arrives during the execution +of the tt(always) block; this interrupt is also propagated. +) vindex(TTY) item(tt(TTY))( The name of the tty associated with the shell, if any. diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c index 63c79a731..7b6130c6f 100644 --- a/Src/Modules/zpty.c +++ b/Src/Modules/zpty.c @@ -308,7 +308,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock) prog = parse_string(zjoin(args, ' ', 1), 0); if (!prog) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; scriptname = oscriptname; ineval = oineval; return 1; diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c index 1cca0c4b8..c89495070 100644 --- a/Src/Modules/zutil.c +++ b/Src/Modules/zutil.c @@ -301,7 +301,8 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval) int ef = errflag; eprog = parse_string(zjoin(vals, ' ', 1), 0); - errflag = ef; + /* Keep any user interrupt error status */ + errflag = ef | (errflag & ERRFLAG_INT); if (!eprog) { @@ -394,10 +395,11 @@ evalstyle(Stypat p) unsetparam("reply"); execode(p->eval, 1, 0, "style"); if (errflag) { - errflag = ef; + /* Keep any user interrupt error status */ + errflag = ef | (errflag & ERRFLAG_INT); return NULL; } - errflag = ef; + errflag = ef | (errflag & ERRFLAG_INT); queue_signals(); if ((ret = getaparam("reply"))) diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c index 35d410cc6..b0c6e06f8 100644 --- a/Src/Zle/compcore.c +++ b/Src/Zle/compcore.c @@ -1671,7 +1671,7 @@ set_comp_sep(void) noaliases = ona; strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; noerrs = ne; lexrestore(); wb = owb; diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c index 0b7a32445..d15c2d1b0 100644 --- a/Src/Zle/compctl.c +++ b/Src/Zle/compctl.c @@ -1879,7 +1879,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat) if (!m || !(m = m->next)) break; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; } redup(osi, 0); dat->lst = 1; @@ -2121,7 +2121,7 @@ getreal(char *str) if (!errflag && nonempty(l) && ((char *) peekfirst(l)) && ((char *) peekfirst(l))[0]) return dupstring(peekfirst(l)); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; return dupstring(str); } @@ -2599,7 +2599,7 @@ makecomplistlist(Compctl cc, char *s, int incmd, int compadd) makecomplistflags(cc, s, incmd, compadd); /* Reset some information variables for the next try. */ - errflag = 0; + errflag &= ~ERRFLAG_ERROR; offs = oloffs; wb = owb; we = owe; @@ -2847,7 +2847,7 @@ sep_comp_string(char *ss, char *s, int noffs) noaliases = ona; strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; noerrs = ne; lexrestore(); wb = owb; @@ -3725,7 +3725,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd) noaliases = ona; strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; lexrestore(); /* Fine, now do full expansion. */ prefork(foo, 0); diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c index fcceb670c..93438a053 100644 --- a/Src/Zle/compresult.c +++ b/Src/Zle/compresult.c @@ -1092,7 +1092,7 @@ do_single(Cmatch m) noerrs = 1; parsestr(p); singsub(&p); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; noerrs = ne; } } else { diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c index 85d014b27..37d2c0ad9 100644 --- a/Src/Zle/textobjects.c +++ b/Src/Zle/textobjects.c @@ -275,7 +275,7 @@ selectargument(UNUSED(char **args)) noaliases = ona; strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; noerrs = ne; lexrestore(); zlemetacs = ocs; diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c index 9f65994dc..88623bb3c 100644 --- a/Src/Zle/zle_hist.c +++ b/Src/Zle/zle_hist.c @@ -853,8 +853,10 @@ pushlineoredit(char **args) free(zhline); } ret = pushline(args); - if (!isfirstln) - errflag = done = 1; + if (!isfirstln) { + errflag |= ERRFLAG_ERROR; + done = 1; + } clearlist = 1; return ret; } diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c index 30d25ebaa..48f210c7e 100644 --- a/Src/Zle/zle_keymap.c +++ b/Src/Zle/zle_keymap.c @@ -504,6 +504,16 @@ mod_export void selectlocalmap(Keymap m) { localkeymap = m; + if (!m) + { + /* + * No local keymap; so we are returning to the global map. If + * the user ^Ced in the local map, they probably just want to go + * back to normal editing. So remove the interrupt error + * status. + */ + errflag &= ~ERRFLAG_INT; + } } /* Reopen the currently selected keymap, in case it got deleted. This * diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c index caa052b13..a2f48e13a 100644 --- a/Src/Zle/zle_main.c +++ b/Src/Zle/zle_main.c @@ -744,7 +744,7 @@ raw_getbyte(long do_keytmout, char *cptr) } if (errflag) { /* No sensible way of handling errors here */ - errflag = 0; + errflag &= ~ERRFLAG_ERROR; /* * Paranoia: don't run the hooks again this * time. @@ -882,7 +882,7 @@ getbyte(long do_keytmout, int *timeout) die = 0; if (!errflag && !retflag && !breaks && !exit_pending) continue; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; breaks = obreaks; errno = old_errno; return lastchar = EOF; @@ -1075,7 +1075,7 @@ zlecore(void) DECCS(); handleundo(); } else { - errflag = 1; + errflag |= ERRFLAG_ERROR; break; } #ifdef HAVE_POLL @@ -1233,6 +1233,10 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish) zleactive = 1; resetneeded = 1; + /* + * Start of the main zle read. + * Fully reset error conditions, including user interrupt. + */ errflag = retflag = 0; lastcol = -1; initmodifier(&zmod); @@ -1658,7 +1662,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func)) } if (!t || errflag) { /* error in editing */ - errflag = 0; + errflag &= ~ERRFLAG_ERROR; breaks = obreaks; if (t) zsfree(t); @@ -1778,7 +1782,7 @@ recursiveedit(UNUSED(char **args)) zrefresh(); zlecore(); - locerror = errflag; + locerror = errflag ? 1 : 0; errflag = done = eofsent = 0; return locerror; diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c index d432acf7b..23286fc20 100644 --- a/Src/Zle/zle_misc.c +++ b/Src/Zle/zle_misc.c @@ -1041,7 +1041,7 @@ copyprevshellword(UNUSED(char **args)) int sendbreak(UNUSED(char **args)) { - errflag = 1; + errflag |= ERRFLAG_ERROR; return 1; } diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c index b15d91c8e..864f804b7 100644 --- a/Src/Zle/zle_tricky.c +++ b/Src/Zle/zle_tricky.c @@ -829,7 +829,7 @@ docomplete(int lst) if (olst == COMP_EXPAND_COMPLETE && !strcmp(ol, zlemetaline)) { zlemetacs = ocs; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; if (!compfunc) { char *p; @@ -877,6 +877,19 @@ docomplete(int lst) active = 0; makecommaspecial(0); + + /* + * As a special case, we reset user interrupts here. + * That's because completion is an intensive piece of + * computation that the user might want to interrupt separately + * from anything else going on. If they do, they probably + * want to keep the line edit buffer intact. + * + * There's a race here that the user might hit ^C just + * after completion exited anyway, but that's inevitable. + */ + errflag &= ~ERRFLAG_INT; + return dat[1]; } @@ -1394,7 +1407,8 @@ get_comp_string(void) } strinend(); inpop(); - errflag = lexflags = 0; + lexflags = 0; + errflag &= ~ERRFLAG_ERROR; if (parbegin != -1) { /* We are in command or process substitution if we are not in * a $((...)). */ @@ -2917,7 +2931,7 @@ getcurcmd(void) popheap(); strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; unmetafy_line(); lexrestore(); diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index 08a32c30e..de91182b5 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -1715,7 +1715,8 @@ zlecallhook(char *name, char *arg) execzlefunc(thingy, args, 1); unrefthingy(thingy); - errflag = saverrflag; + /* Retain any user interrupt error status */ + errflag = saverrflag | (errflag & ERRFLAG_INT); retflag = savretflag; } diff --git a/Src/builtin.c b/Src/builtin.c index c2af51f2e..ad3a1925f 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -422,7 +422,7 @@ execbuiltin(LinkList args, Builtin bn) argc -= argv - argarr; if (errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; return 1; } @@ -3136,7 +3136,7 @@ bin_unset(char *name, char **argv, Options ops, int func) } } returnval = errflag; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; } else { zerrnam(name, "%s: invalid element for unset", s); returnval = 1; @@ -4242,7 +4242,7 @@ bin_print(char *name, char **args, Options ops, int func) if (*argp) { width = (int)mathevali(*argp++); if (errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; ret = 1; } } @@ -4272,7 +4272,7 @@ bin_print(char *name, char **args, Options ops, int func) if (*argp) { prec = (int)mathevali(*argp++); if (errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; ret = 1; } } @@ -4452,7 +4452,7 @@ bin_print(char *name, char **args, Options ops, int func) zlongval = (curarg) ? mathevali(curarg) : 0; if (errflag) { zlongval = 0; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; ret = 1; } print_val(zlongval) @@ -4481,7 +4481,7 @@ bin_print(char *name, char **args, Options ops, int func) } else doubleval = 0; if (errflag) { doubleval = 0; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; ret = 1; } print_val(doubleval) @@ -4494,7 +4494,7 @@ bin_print(char *name, char **args, Options ops, int func) zulongval = (curarg) ? mathevali(curarg) : 0; if (errflag) { zulongval = 0; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; ret = 1; } print_val(zulongval) @@ -4871,7 +4871,7 @@ zexit(int val, int from_where) in_exit = -1; /* * We want to do all remaining processing regardless of preceding - * errors. + * errors, even user interrupts. */ errflag = 0; @@ -5074,7 +5074,7 @@ eval(char **argv) if (fpushed) funcstack = funcstack->prev; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; scriptname = oscriptname; ineval = oineval; @@ -6101,7 +6101,7 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func) condlex = zshlex; if (errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; lexrestore(); return 1; } @@ -6278,7 +6278,7 @@ bin_let(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int func)) while (*argv) val = matheval(*argv++); /* Errors in math evaluation in let are non-fatal. */ - errflag = 0; + errflag &= ~ERRFLAG_ERROR; /* should test for fabs(val.u.d) < epsilon? */ return (val.type == MN_INTEGER) ? val.u.l == 0 : val.u.d == 0.0; } diff --git a/Src/exec.c b/Src/exec.c index a5f877191..6a7dbb1e1 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -59,7 +59,7 @@ mod_export int noerrs; /**/ int nohistsave; -/* error/break flag */ +/* error flag: bits from enum errflag_bits */ /**/ mod_export int errflag; @@ -1601,7 +1601,8 @@ execpline(Estate state, wordcode slcode, int how, int last1) (killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1); list_pipe_pid = pid; list_pipe_start = bgtime; - nowait = errflag = 1; + nowait = 1; + errflag |= ERRFLAG_ERROR; breaks = loops; close(synch[1]); read_loop(synch[0], &dummy, 1); @@ -1634,7 +1635,10 @@ execpline(Estate state, wordcode slcode, int how, int last1) list_pipe_child = 1; opts[INTERACTIVE] = 0; if (errbrk_saved) { - errflag = prev_errflag; + /* + * Keep any user interrupt bit in errflag. + */ + errflag = prev_errflag | (errflag & ERRFLAG_INT); breaks = prev_breaks; } break; @@ -1719,12 +1723,14 @@ execpline2(Estate state, wordcode pcode, if (pipe(synch) < 0) { zerr("pipe failed: %e", errno); - lastval = errflag = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; return; } else if ((pid = zfork(&bgtime)) == -1) { close(synch[0]); close(synch[1]); - lastval = errflag = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; return; } else if (pid) { char dummy, *text; @@ -2560,7 +2566,8 @@ execcmd(Estate state, int input, int output, int how, int last1) while (next && *next == '-' && strlen(next) >= 2) { if (!firstnode(args)) { zerr("exec requires a command to execute"); - errflag = lastval = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; goto done; } uremnode(args, firstnode(args)); @@ -2577,12 +2584,14 @@ execcmd(Estate state, int input, int output, int how, int last1) } else { if (!firstnode(args)) { zerr("exec requires a command to execute"); - errflag = lastval = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; goto done; } if (!nextnode(firstnode(args))) { zerr("exec flag -a requires a parameter"); - errflag = lastval = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; goto done; } exec_argv0 = (char *) @@ -2598,7 +2607,8 @@ execcmd(Estate state, int input, int output, int how, int last1) break; default: zerr("unknown exec flag -%c", *cmdopt); - errflag = lastval = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; return; } } @@ -2661,7 +2671,8 @@ execcmd(Estate state, int input, int output, int how, int last1) } else if (!nullcmd || !*nullcmd || opts[CSHNULLCMD] || (cflags & BINF_PREFIX)) { zerr("redirection with no command"); - errflag = lastval = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; return; } else if (!nullcmd || !*nullcmd || opts[SHNULLCMD]) { if (!args) @@ -2691,7 +2702,7 @@ execcmd(Estate state, int input, int output, int how, int last1) if (varspc) addvars(state, varspc, 0); if (errflag) - lastval = errflag; + lastval = 1; else lastval = cmdoutval; if (isset(XTRACE)) { @@ -2795,7 +2806,7 @@ execcmd(Estate state, int input, int output, int how, int last1) } } if (!nextnode(firstnode(args))) - errflag = 1; + errflag |= ERRFLAG_ERROR; } if (type == WC_FUNCDEF) { @@ -2940,7 +2951,8 @@ execcmd(Estate state, int input, int output, int how, int last1) } else if ((pid = zfork(&bgtime)) == -1) { close(synch[0]); close(synch[1]); - lastval = errflag = 1; + lastval = 1; + errflag |= ERRFLAG_ERROR; goto fatal; } if (pid) { @@ -3529,7 +3541,7 @@ execcmd(Estate state, int input, int output, int how, int last1) else exit(1); } - errflag = 1; + errflag |= ERRFLAG_ERROR; } } if (newxtrerr) { @@ -3759,8 +3771,10 @@ gethere(char **strp, int typ) parsestr(buf); - if (!errflag) - errflag = ef; + if (!errflag) { + /* Retain any user interrupt error */ + errflag = ef | (errflag & ERRFLAG_INT); + } } s = dupstring(buf); zfree(buf, bsiz); @@ -3854,7 +3868,7 @@ getoutput(char *cmd, int qt) return readoutput(stream, qt); } if (mpipe(pipes) < 0) { - errflag = 1; + errflag |= ERRFLAG_ERROR; cmdoutpid = 0; return NULL; } @@ -3864,7 +3878,7 @@ getoutput(char *cmd, int qt) /* fork error */ zclose(pipes[0]); zclose(pipes[1]); - errflag = 1; + errflag |= ERRFLAG_ERROR; cmdoutpid = 0; child_unblock(); return NULL; @@ -4274,7 +4288,7 @@ execcond(Estate state, UNUSED(int do_exec)) * into a shell error. */ if (stat == 2) - errflag = 1; + errflag |= ERRFLAG_ERROR; cmdpop(); if (isset(XTRACE)) { fprintf(xtrerr, " ]]\n"); @@ -4314,7 +4328,7 @@ execarith(Estate state, UNUSED(int do_exec)) fflush(xtrerr); } if (errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; return 2; } /* should test for fabs(val.u.d) < epsilon? */ @@ -4932,7 +4946,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) (name = fname)))) { zwarn("%s: function not defined by file", name); if (noreturnval) - errflag = 1; + errflag |= ERRFLAG_ERROR; else lastval = 1; goto doneshfunc; diff --git a/Src/glob.c b/Src/glob.c index b3903f2ff..82f8d626c 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -682,7 +682,7 @@ parsecomplist(char *instr) /* Now get the next path component if there is one. */ l1 = (Complist) zhalloc(sizeof *l1); if ((l1->next = parsecomplist(instr)) == NULL) { - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL); @@ -728,7 +728,7 @@ parsecomplist(char *instr) return (ef && !l1->next) ? NULL : l1; } } - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } @@ -1790,7 +1790,7 @@ zglob(LinkList list, LinkNode np, int nountok) insertlinknode(list, node, ostr); return; } - errflag = 0; + errflag &= ~ERRFLAG_ERROR; zerr("bad pattern: %s", ostr); return; } @@ -1873,7 +1873,8 @@ zglob(LinkList list, LinkNode np, int nountok) tmpptr->sortstrs[iexec] = tmpptr->name; } - errflag = ef; + /* Retain any user interrupt error status */ + errflag = ef | (errflag & ERRFLAG_INT); lastval = lv; } else { /* Failed, let's be safe */ @@ -3733,7 +3734,8 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str) execode(prog, 1, 0, "globqual"); ret = lastval; - errflag = ef; + /* Retain any user interrupt error status */ + errflag = ef | (errflag & ERRFLAG_INT); lastval = lv; if (!(inserts = getaparam("reply")) && diff --git a/Src/hist.c b/Src/hist.c index 7fe843a4a..a0061707c 100644 --- a/Src/hist.c +++ b/Src/hist.c @@ -287,7 +287,8 @@ ihgetc(void) c = histsubchar(c); if (c < 0) { /* bad expansion */ - errflag = lexstop = 1; + lexstop = 1; + errflag |= ERRFLAG_ERROR; return ' '; } } @@ -721,7 +722,7 @@ histsubchar(int c) noerrs = 1; parse_subst_string(sline); noerrs = one; - errflag = oef; + errflag = oef | (errflag & ERRFLAG_INT); remnulargs(sline); untokenize(sline); } @@ -880,7 +881,8 @@ hbegin(int dohist) char *hf; isfirstln = isfirstch = 1; - errflag = histdone = 0; + errflag &= ~ERRFLAG_ERROR; + histdone = 0; if (!dohist) stophist = 2; else if (dohist != 2) @@ -3182,7 +3184,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags) noaliases = ona; strinend(); inpop(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; nocomments = onc; noerrs = ne; lexrestore(); diff --git a/Src/init.c b/Src/init.c index 655166135..305908724 100644 --- a/Src/init.c +++ b/Src/init.c @@ -118,11 +118,24 @@ loop(int toplevel, int justonce) if (interact && toplevel) { int hstop = stophist; stophist = 3; + /* + * Reset all errors including the interrupt error status + * immediately, so preprompt runs regardless of what + * just happened. We'll reset again below as a + * precaution to ensure we get back to the command line + * no matter what. + */ + errflag = 0; preprompt(); if (stophist != 3) hbegin(1); else stophist = hstop; + /* + * Reset all errors, including user interupts. + * This is what allows ^C in an interactive shell + * to return us to the command line. + */ errflag = 0; } } @@ -178,7 +191,15 @@ loop(int toplevel, int justonce) /* The only permanent storage is from getpermtext() */ zsfree(cmdstr); - errflag = 0; + /* + * Note this does *not* remove a user interrupt error + * condition, even though we're at the top level loop: + * that would be inconsistent with the case where + * we didn't execute a preexec function. This is + * an implementation detail that an interrupting user + * does't care about. + */ + errflag &= ~ERRFLAG_ERROR; } if (stopmsg) /* unset 'you have stopped jobs' flag */ stopmsg--; @@ -689,7 +710,7 @@ init_term(void) { if (isset(INTERACTIVE)) zerr("can't find terminal definition for %s", term); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; termflags |= TERM_BAD; return 0; } else { @@ -1336,7 +1357,7 @@ source(char *s) if (prog) { pushheap(); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; execode(prog, 1, 0, "filecode"); popheap(); if (errflag) @@ -1379,7 +1400,7 @@ source(char *s) lineno = oldlineno; /* our current lineno */ loops = oloops; /* the # of nested loops we are in */ dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */ - errflag = 0; + errflag &= ~ERRFLAG_ERROR; if (!exit_pending) retflag = 0; scriptname = old_scriptname; diff --git a/Src/input.c b/Src/input.c index 4ac7e6ec8..9552331a9 100644 --- a/Src/input.c +++ b/Src/input.c @@ -291,7 +291,8 @@ inputline(void) } if (errflag) { free(ingetcline); - return lexstop = errflag = 1; + errflag |= ERRFLAG_ERROR; + return lexstop = 1; } if (isset(VERBOSE)) { /* Output the whole line read so far. */ diff --git a/Src/jobs.c b/Src/jobs.c index 6663a40a6..a668b07e6 100644 --- a/Src/jobs.c +++ b/Src/jobs.c @@ -509,7 +509,7 @@ update_job(Job jn) prev_errflag = errflag; } breaks = loops; - errflag = 1; + errflag |= ERRFLAG_INT; inerrflush(); } } else { @@ -526,7 +526,7 @@ update_job(Job jn) prev_errflag = errflag; } breaks = loops; - errflag = 1; + errflag |= ERRFLAG_INT; inerrflush(); } if (somestopped && jn->stat & STAT_SUPERJOB) @@ -581,7 +581,7 @@ update_job(Job jn) breaks = loops; } else { breaks = loops; - errflag = 1; + errflag |= ERRFLAG_INT; } check_cursh_sig(sig); } @@ -1444,12 +1444,19 @@ zwaitjob(int job, int wait_cmd) restore_queue_signals(q); return 128 + last_signal; } - /* Commenting this out makes ^C-ing a job started by a function - stop the whole function again. But I guess it will stop - something else from working properly, we have to find out - what this might be. --oberon + /* Commenting this out makes ^C-ing a job started by a function + stop the whole function again. But I guess it will stop + something else from working properly, we have to find out + what this might be. --oberon + + When attempting to separate errors and interrupts, we + assumed because of the previous comment it would be OK + to remove ERRFLAG_ERROR and leave ERRFLAG_INT set, since + that's the one related to ^C. But that doesn't work. + There's something more here we don't understand. --pws + + errflag = 0; */ - errflag = 0; */ if (subsh) { killjb(jn, SIGCONT); jn->stat &= ~STAT_STOPPED; diff --git a/Src/lex.c b/Src/lex.c index b2a05448c..4addf8033 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -385,7 +385,7 @@ lexrestore(void) ecnfunc = ln->ecnfunc; hlinesz = ln->hlinesz; toklineno = ln->toklineno; - errflag = 0; + errflag &= ~ERRFLAG_ERROR; free(ln); unqueue_signals(); @@ -1737,7 +1737,8 @@ parse_subst_string(char *s) inpop(); DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty."); lexrestore(); - errflag = err; + /* Keep any interrupt error status */ + errflag = err | (errflag & ERRFLAG_INT); if (ctok == LEXERR) { untokenize(s); return 1; diff --git a/Src/loop.c b/Src/loop.c index 82d2fe31a..8bb1ec9dd 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -259,7 +259,8 @@ execselect(Estate state, UNUSED(int do_exec)) 0, ZLCON_SELECT); if (errflag) str = NULL; - errflag = oef; + /* Keep any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); } else { str = promptexpand(prompt3, 0, NULL, NULL, NULL); zputs(str, stderr); @@ -632,6 +633,14 @@ execcase(Estate state, int do_exec) zlong try_errflag = -1; +/** + * Corresponding interrupt error status form `try' block. + */ + +/**/ +zlong +try_interrupt = -1; + /**/ zlong try_tryflag = 0; @@ -643,7 +652,7 @@ exectry(Estate state, int do_exec) Wordcode end, always; int endval; int save_retflag, save_breaks, save_contflag; - zlong save_try_errflag, save_try_tryflag; + zlong save_try_errflag, save_try_tryflag, save_try_interrupt; end = state->pc + WC_TRY_SKIP(state->pc[-1]); always = state->pc + 1 + WC_TRY_SKIP(*state->pc); @@ -670,7 +679,10 @@ exectry(Estate state, int do_exec) /* The always clause. */ save_try_errflag = try_errflag; - try_errflag = (zlong)errflag; + save_try_interrupt = try_interrupt; + try_errflag = (zlong)(errflag & ERRFLAG_ERROR); + try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0); + /* We need to reset all errors to allow the block to execute */ errflag = 0; save_retflag = retflag; retflag = 0; @@ -682,8 +694,16 @@ exectry(Estate state, int do_exec) state->pc = always; execlist(state, 1, do_exec); - errflag = try_errflag ? 1 : 0; + if (try_errflag) + errflag |= ERRFLAG_ERROR; + else + errflag &= ~ERRFLAG_ERROR; + if (try_interrupt) + errflag |= ERRFLAG_INT; + else + errflag &= ~ERRFLAG_INT; try_errflag = save_try_errflag; + try_interrupt = save_try_interrupt; if (!retflag) retflag = save_retflag; if (!breaks) diff --git a/Src/params.c b/Src/params.c index 61edc5d08..79088d162 100644 --- a/Src/params.c +++ b/Src/params.c @@ -331,6 +331,7 @@ IPDEF5("SHLVL", &shlvl, varinteger_gsu), #define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0} IPDEF6("OPTIND", &zoptind, varinteger_gsu), IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu), +IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu), #define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} #define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0} @@ -2654,7 +2655,7 @@ assignsparam(char *s, char *val, int flags) if (!isident(s)) { zerr("not an identifier: %s", s); zsfree(val); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } queue_signals(); @@ -2783,7 +2784,7 @@ assignaparam(char *s, char **val, int flags) if (!isident(s)) { zerr("not an identifier: %s", s); freearray(val); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } queue_signals(); @@ -2799,7 +2800,7 @@ assignaparam(char *s, char **val, int flags) zerr("%s: attempt to set slice of associative array", v->pm->node.nam); freearray(val); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } v = NULL; @@ -2870,13 +2871,13 @@ sethparam(char *s, char **val) if (!isident(s)) { zerr("not an identifier: %s", s); freearray(val); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } if (strchr(s, '[')) { freearray(val); zerr("nested associative arrays not yet supported"); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } if (unset(EXECOPT)) @@ -2916,7 +2917,7 @@ setnparam(char *s, mnumber val) if (!isident(s)) { zerr("not an identifier: %s", s); - errflag = 1; + errflag |= ERRFLAG_ERROR; return NULL; } if (unset(EXECOPT)) diff --git a/Src/parse.c b/Src/parse.c index 4ceeb4eaf..c1709e03a 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -71,13 +71,14 @@ struct heredocs *hdocs; #define YYERROR(O) { tok = LEXERR; ecused = (O); return 0; } #define YYERRORV(O) { tok = LEXERR; ecused = (O); return; } -#define COND_ERROR(X,Y) do { \ - zwarn(X,Y); \ - herrflush(); \ - if (noerrs != 2) \ - errflag = 1; \ - YYERROR(ecused) \ -} while(0) +#define COND_ERROR(X,Y) \ + do { \ + zwarn(X,Y); \ + herrflush(); \ + if (noerrs != 2) \ + errflag |= ERRFLAG_ERROR; \ + YYERROR(ecused) \ + } while(0) /* @@ -506,7 +507,7 @@ par_event(void) yyerror(1); herrflush(); if (noerrs != 2) - errflag = 1; + errflag |= ERRFLAG_ERROR; ecused--; return 0; } else { @@ -2339,7 +2340,7 @@ yyerror(int noerr) zwarn("parse error"); } if (!noerr && noerrs != 2) - errflag = 1; + errflag |= ERRFLAG_ERROR; } /* @@ -3031,7 +3032,7 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags) file = metafy(file, flen, META_REALLOC); if (!(prog = parse_string(file, 1)) || errflag) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); zfree(file, flen); zwarnnam(nam, "can't read file: %s", *files); @@ -3141,7 +3142,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map, for (hn = shfunctab->nodes[i]; hn; hn = hn->next) if (cur_add_func(nam, (Shfunc) hn, lnames, progs, &hlen, &tlen, what)) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); unlink(dump); return 1; @@ -3166,7 +3167,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map, pattry(pprog, hn->nam) && cur_add_func(nam, (Shfunc) hn, lnames, progs, &hlen, &tlen, what)) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); unlink(dump); return 1; @@ -3177,13 +3178,13 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map, if (errflag || !(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) { zwarnnam(nam, "unknown function: %s", *names); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); unlink(dump); return 1; } if (cur_add_func(nam, shf, lnames, progs, &hlen, &tlen, what)) { - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); unlink(dump); return 1; @@ -3192,7 +3193,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map, } if (empty(progs)) { zwarnnam(nam, "no functions"); - errflag = 0; + errflag &= ~ERRFLAG_ERROR; close(dfd); unlink(dump); return 1; diff --git a/Src/prompt.c b/Src/prompt.c index 0cc9ef917..3552575f3 100644 --- a/Src/prompt.c +++ b/Src/prompt.c @@ -192,8 +192,11 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep) if (*s == Nularg && s[1] == '\0') *s = '\0'; - /* Ignore errors and status change in prompt substitution */ - errflag = olderr; + /* + * Ignore errors and status change in prompt substitution. + * However, keep any user interrupt error that occurred. + */ + errflag = olderr | (errflag & ERRFLAG_INT); lastval = oldval; } diff --git a/Src/signals.c b/Src/signals.c index e72850516..899f1217b 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -619,7 +619,7 @@ zhandler(int sig) zexit(SIGINT, 1); if (list_pipe || chline || simple_pline) { breaks = loops; - errflag = 1; + errflag |= ERRFLAG_INT; inerrflush(); check_cursh_sig(SIGINT); } @@ -640,6 +640,11 @@ zhandler(int sig) if (idle >= 0 && idle < tmout) alarm(tmout - idle); else { + /* + * We want to exit now. + * Cancel all errors, including a user interrupt + * which is now redundant. + */ errflag = noerrs = 0; zwarn("timeout"); stopmsg = 1; @@ -1267,7 +1272,18 @@ dotrapargs(int sig, int *sigtr, void *sigfn) !(isfunc && new_trap_return == 0)) { if (isfunc) { breaks = loops; - errflag = 1; + /* + * For SIGINT we behave the same as the default behaviour + * i.e. we set the error bit indicating an interrupt. + * We do this with SIGQUIT, too, even though we don't + * handle SIGQUIT by default. That's to try to make + * it behave a bit more like its normal behaviour when + * the trap handler has told us that's what it wants. + */ + if (sig == SIGINT || sig == SIGQUIT) + errflag |= ERRFLAG_INT; + else + errflag |= ERRFLAG_ERROR; } lastval = new_trap_return; /* return triggered */ @@ -1282,8 +1298,12 @@ dotrapargs(int sig, int *sigtr, void *sigfn) */ lastval = olastval; } - if (try_tryflag) - errflag = traperr; + if (try_tryflag) { + if (traperr) + errflag |= ERRFLAG_ERROR; + else + errflag &= ~ERRFLAG_ERROR; + } breaks += obreaks; /* return not triggered: restore old flag */ retflag = oretflag; diff --git a/Src/subst.c b/Src/subst.c index 61aa1c136..43932c256 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2822,7 +2822,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) haserr = parse_subst_string(s); noerrs = one; if (!quoteerr) { - errflag = oef; + /* Retain user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); if (haserr) shtokenize(s); } else if (haserr || errflag) { @@ -3249,8 +3250,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) haserr = 1; } noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } if (haserr || errflag) return NULL; } @@ -3483,8 +3486,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) untokenize(*ap); } noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } else if (haserr || errflag) { zerr("parse error in parameter value"); return NULL; @@ -3516,8 +3521,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags) noerrs = 1; haserr = parse_subst_string(val); noerrs = one; - if (!quoteerr) - errflag = oef; + if (!quoteerr) { + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); + } else if (haserr || errflag) { zerr("parse error in parameter value"); return NULL; @@ -4086,7 +4093,8 @@ modify(char **str, char **ptr) noerrs = 1; parse_subst_string(copy); noerrs = one; - errflag = oef; + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); remnulargs(copy); untokenize(copy); } @@ -4161,7 +4169,8 @@ modify(char **str, char **ptr) noerrs = 1; parse_subst_string(*str); noerrs = one; - errflag = oef; + /* Retain any user interrupt error status */ + errflag = oef | (errflag & ERRFLAG_INT); remnulargs(*str); untokenize(*str); } diff --git a/Src/utils.c b/Src/utils.c index ab3d3da93..893a8ca02 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -153,7 +153,7 @@ VA_DCL if (errflag || noerrs) { if (noerrs < 2) - errflag = 1; + errflag |= ERRFLAG_ERROR; return; } @@ -161,7 +161,7 @@ VA_DCL VA_GET_ARG(ap, fmt, const char *); zwarning(NULL, fmt, ap); va_end(ap); - errflag = 1; + errflag |= ERRFLAG_ERROR; } /**/ @@ -181,7 +181,7 @@ VA_DCL VA_GET_ARG(ap, fmt, const char *); zwarning(cmd, fmt, ap); va_end(ap); - errflag = 1; + errflag |= ERRFLAG_ERROR; } /**/ @@ -330,7 +330,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap) num = va_arg(ap, int); if (num == EINTR) { fputs("interrupt\n", file); - errflag = 1; + errflag |= ERRFLAG_ERROR; return; } errmsg = strerror(num); diff --git a/Src/zsh.h b/Src/zsh.h index 031deaf3f..b366e0ff4 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2623,6 +2623,20 @@ enum trap_state { #define IN_EVAL_TRAP() \ (intrap && !trapisfunc && traplocallevel == locallevel) +/* + * Bits in the errflag variable. + */ +enum errflag_bits { + /* + * Standard internal error bit. + */ + ERRFLAG_ERROR = 1, + /* + * User interrupt. + */ + ERRFLAG_INT = 2 +}; + /***********/ /* Sorting */ /***********/ -- cgit v1.2.3 From 04e555a92e49eb41f4321c67511bec94a86b867a Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 16 Dec 2014 21:14:16 +0000 Subject: 33981: more care with region_highlights management --- Src/Zle/zle_refresh.c | 7 ++++-- Src/Zle/zle_utils.c | 61 ++++++++++++++++++++++++++++----------------------- 2 files changed, 39 insertions(+), 29 deletions(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c index 467629d25..9f8075386 100644 --- a/Src/Zle/zle_refresh.c +++ b/Src/Zle/zle_refresh.c @@ -396,8 +396,9 @@ get_region_highlight(UNUSED(Param pm)) struct region_highlight *rhp; /* region_highlights may not have been set yet */ - if (arrsize) - arrsize -= N_SPECIAL_HIGHLIGHTS; + if (!arrsize) + return hmkarray(NULL); + arrsize -= N_SPECIAL_HIGHLIGHTS; arrp = retarr = (char **)zhalloc((arrsize+1)*sizeof(char *)); /* ignore special highlighting */ @@ -1028,6 +1029,8 @@ zrefresh(void) /* this will create region_highlights if it's still NULL */ zle_set_highlight(); + DPUTS(!region_highlights, "region_highlights not created"); + /* check for region between point ($CURSOR) and mark ($MARK) */ if (region_active) { if (zlecs <= mark) { diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index de91182b5..e361e5e2a 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -675,35 +675,42 @@ zle_restore_positions(void) zlell = oldpos->ll; } - /* Count number of regions and see if the array needs resizing */ - for (nreg = 0, oldrhp = oldpos->regions; - oldrhp; - nreg++, oldrhp = oldrhp->next) - ; - if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) { - n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS; - region_highlights = (struct region_highlight *) - zrealloc(region_highlights, - sizeof(struct region_highlight) * n_region_highlights); - } - oldrhp = oldpos->regions; - rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; - while (oldrhp) { - struct zle_region *nextrhp = oldrhp->next; - - rhp->atr = oldrhp->atr; - rhp->flags = oldrhp->flags; - if (zlemetaline) { - rhp->start_meta = oldrhp->start; - rhp->end_meta = oldrhp->end; - } else { - rhp->start = oldrhp->start; - rhp->end = oldrhp->end; + if (oldpos->regions) { + /* Count number of regions and see if the array needs resizing */ + for (nreg = 0, oldrhp = oldpos->regions; + oldrhp; + nreg++, oldrhp = oldrhp->next) + ; + if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) { + n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS; + region_highlights = (struct region_highlight *) + zrealloc(region_highlights, + sizeof(struct region_highlight) * n_region_highlights); } + oldrhp = oldpos->regions; + rhp = region_highlights + N_SPECIAL_HIGHLIGHTS; + while (oldrhp) { + struct zle_region *nextrhp = oldrhp->next; - zfree(oldrhp, sizeof(*oldrhp)); - oldrhp = nextrhp; - rhp++; + rhp->atr = oldrhp->atr; + rhp->flags = oldrhp->flags; + if (zlemetaline) { + rhp->start_meta = oldrhp->start; + rhp->end_meta = oldrhp->end; + } else { + rhp->start = oldrhp->start; + rhp->end = oldrhp->end; + } + + zfree(oldrhp, sizeof(*oldrhp)); + oldrhp = nextrhp; + rhp++; + } + } else if (region_highlights) { + zfree(region_highlights, sizeof(struct region_highlight) * + n_region_highlights); + region_highlights = NULL; + n_region_highlights = 0; } zfree(oldpos, sizeof(*oldpos)); -- cgit v1.2.3 From 18b60d85126ff29aa2bced1d213452a103a313e6 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Mon, 5 Jan 2015 15:17:14 +0100 Subject: 34117: zle: size_t is unsigned, use int instead The function wctomb returns an int according to my manpage, and we furthermore check if it is negative, and then return it, and the function signature is int, so declaring it as an int seems to make more sense. --- ChangeLog | 2 ++ Src/Zle/zle_utils.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Src/Zle/zle_utils.c') diff --git a/ChangeLog b/ChangeLog index b163935b6..384a85208 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-01-06 Mikael Magnusson + * 34117: Src/Zle/zle_utils.c: size_t is unsigned, use int instead + * 34116: Src/Zle/computil.c: Check for NULL before passing to strlen diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c index e361e5e2a..e4ab97a54 100644 --- a/Src/Zle/zle_utils.c +++ b/Src/Zle/zle_utils.c @@ -117,7 +117,7 @@ int zlecharasstring(ZLE_CHAR_T inchar, char *buf) { #ifdef MULTIBYTE_SUPPORT - size_t ret; + int ret; char *ptr; #ifdef __STDC_ISO_10646__ -- cgit v1.2.3