vi: install SIGINT handler _after_ restart setjmp is initialized

While at it, sanitized comment style, deleted wrong ones, renamed signal
handlers to <sig>_handler(), slightly optimized "cursor home+clear screen".

function                                             old     new   delta
cont_handler                                           -      66     +66
tstp_handler                                           -      64     +64
winch_handler                                          -      60     +60
int_handler                                            -      32     +32
edit_file                                            648     651      +3
redraw                                                52      43      -9
catch_sig                                             32       -     -32
winch_sig                                             60       -     -60
suspend_sig                                           64       -     -64
cont_sig                                              66       -     -66
------------------------------------------------------------------------------
(add/remove: 4/4 grow/shrink: 1/1 up/down: 225/-231)           Total: -6 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2019-04-01 11:58:11 +02:00
parent 35082fc2c1
commit 6ed94aa9b2

View File

@ -235,9 +235,10 @@ enum {
* Full sequence is "ESC [ <num> J", * Full sequence is "ESC [ <num> J",
* <num> is 0/1/2 = "erase below/above/all".) * <num> is 0/1/2 = "erase below/above/all".)
*/ */
#define ESC_CLEAR2EOS ESC"[J" #define ESC_CLEAR2EOS ESC"[J"
/* Cursor to given coordinate (1,1: top left) */ /* Cursor to given coordinate (1,1: top left) */
#define ESC_SET_CURSOR_POS ESC"[%u;%uH" #define ESC_SET_CURSOR_POS ESC"[%u;%uH"
#define ESC_SET_CURSOR_TOPLEFT ESC"[H"
//UNUSED //UNUSED
///* Cursor up and down */ ///* Cursor up and down */
//#define ESC_CURSOR_UP ESC"[A" //#define ESC_CURSOR_UP ESC"[A"
@ -352,7 +353,7 @@ struct globals {
char *context_start, *context_end; char *context_start, *context_end;
#endif #endif
#if ENABLE_FEATURE_VI_USE_SIGNALS #if ENABLE_FEATURE_VI_USE_SIGNALS
sigjmp_buf restart; // catch_sig() sigjmp_buf restart; // int_handler() jumps to location remembered here
#endif #endif
struct termios term_orig; // remember what the cooked mode was struct termios term_orig; // remember what the cooked mode was
#if ENABLE_FEATURE_VI_COLON #if ENABLE_FEATURE_VI_COLON
@ -535,15 +536,11 @@ static void rawmode(void); // set "raw" mode on tty
static void cookmode(void); // return to "cooked" mode on tty static void cookmode(void); // return to "cooked" mode on tty
// sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready) // sleep for 'h' 1/100 seconds, return 1/0 if stdin is (ready for read)/(not ready)
static int mysleep(int); static int mysleep(int);
static int readit(void); // read (maybe cursor) key from stdin
static int get_one_char(void); // read 1 char from stdin static int get_one_char(void); // read 1 char from stdin
// file_insert might reallocate text[]! // file_insert might reallocate text[]!
static int file_insert(const char *, char *, int); static int file_insert(const char *, char *, int);
static int file_write(char *, char *, char *); static int file_write(char *, char *, char *);
static void place_cursor(int, int);
static void screen_erase(void); static void screen_erase(void);
static void clear_to_eol(void);
static void clear_to_eos(void);
static void go_bottom_and_clear_to_eol(void); static void go_bottom_and_clear_to_eol(void);
static void standout_start(void); // send "start reverse video" sequence static void standout_start(void); // send "start reverse video" sequence
static void standout_end(void); // send "end reverse video" sequence static void standout_end(void); // send "end reverse video" sequence
@ -570,9 +567,9 @@ static char *get_address(char *, int *, int *); // get two colon addrs, if prese
#endif #endif
static void colon(char *); // execute the "colon" mode cmds static void colon(char *); // execute the "colon" mode cmds
#if ENABLE_FEATURE_VI_USE_SIGNALS #if ENABLE_FEATURE_VI_USE_SIGNALS
static void winch_sig(int); // catch window size changes static void winch_handler(int); // catch window size changes
static void suspend_sig(int); // catch ctrl-Z static void tstp_handler(int); // catch ctrl-Z
static void catch_sig(int); // catch ctrl-C and alarm time-outs static void int_handler(int); // catch ctrl-C
#endif #endif
#if ENABLE_FEATURE_VI_DOT_CMD #if ENABLE_FEATURE_VI_DOT_CMD
static void start_new_cmd_q(char); // new queue for command static void start_new_cmd_q(char); // new queue for command
@ -598,11 +595,11 @@ static void check_context(char); // remember context for '' command
#endif #endif
#if ENABLE_FEATURE_VI_UNDO #if ENABLE_FEATURE_VI_UNDO
static void flush_undo_data(void); static void flush_undo_data(void);
static void undo_push(char *, unsigned int, unsigned char); // Push an operation on the undo stack static void undo_push(char *, unsigned, unsigned char); // push an operation on the undo stack
static void undo_push_insert(char *, int, int); // convenience function static void undo_push_insert(char *, int, int); // convenience function
static void undo_pop(void); // Undo the last operation static void undo_pop(void); // undo the last operation
# if ENABLE_FEATURE_VI_UNDO_QUEUE # if ENABLE_FEATURE_VI_UNDO_QUEUE
static void undo_queue_commit(void); // Flush any queued objects to the undo stack static void undo_queue_commit(void); // flush any queued objects to the undo stack
# else # else
# define undo_queue_commit() ((void)0) # define undo_queue_commit() ((void)0)
# endif # endif
@ -644,7 +641,7 @@ int vi_main(int argc, char **argv)
srand((long) my_pid); srand((long) my_pid);
#endif #endif
#ifdef NO_SUCH_APPLET_YET #ifdef NO_SUCH_APPLET_YET
/* If we aren't "vi", we are "view" */ // if we aren't "vi", we are "view"
if (ENABLE_FEATURE_VI_READONLY && applet_name[2]) { if (ENABLE_FEATURE_VI_READONLY && applet_name[2]) {
SET_READONLY_MODE(readonly_mode); SET_READONLY_MODE(readonly_mode);
} }
@ -682,7 +679,7 @@ int vi_main(int argc, char **argv)
#endif #endif
case 'H': case 'H':
show_help(); show_help();
/* fall through */ // fall through
default: default:
bb_show_usage(); bb_show_usage();
return 1; return 1;
@ -699,7 +696,7 @@ int vi_main(int argc, char **argv)
// "Save cursor, use alternate screen buffer, clear screen" // "Save cursor, use alternate screen buffer, clear screen"
write1(ESC"[?1049h"); write1(ESC"[?1049h");
while (1) { while (1) {
edit_file(argv[optind]); /* param might be NULL */ edit_file(argv[optind]); // param might be NULL
if (++optind >= argc) if (++optind >= argc)
break; break;
} }
@ -804,13 +801,15 @@ static void edit_file(char *fn)
ccol = 0; ccol = 0;
#if ENABLE_FEATURE_VI_USE_SIGNALS #if ENABLE_FEATURE_VI_USE_SIGNALS
signal(SIGINT, catch_sig); signal(SIGWINCH, winch_handler);
signal(SIGWINCH, winch_sig); signal(SIGTSTP, tstp_handler);
signal(SIGTSTP, suspend_sig);
sig = sigsetjmp(restart, 1); sig = sigsetjmp(restart, 1);
if (sig != 0) { if (sig != 0) {
screenbegin = dot = text; screenbegin = dot = text;
} }
// int_handler() can jump to "restart",
// must install handler *after* initializing "restart"
signal(SIGINT, int_handler);
#endif #endif
cmd_mode = 0; // 0=command 1=insert 2='R'eplace cmd_mode = 0; // 0=command 1=insert 2='R'eplace
@ -994,7 +993,7 @@ static void setops(const char *args, const char *opname, int flg_no,
const char *short_opname, int opt) const char *short_opname, int opt)
{ {
const char *a = args + flg_no; const char *a = args + flg_no;
int l = strlen(opname) - 1; /* opname have + ' ' */ int l = strlen(opname) - 1; // opname have + ' '
// maybe strncmp? we had tons of erroneous strncasecmp's... // maybe strncmp? we had tons of erroneous strncasecmp's...
if (strncasecmp(a, opname, l) == 0 if (strncasecmp(a, opname, l) == 0
@ -1014,7 +1013,7 @@ static void setops(const char *args, const char *opname, int flg_no,
static void colon(char *buf) static void colon(char *buf)
{ {
#if !ENABLE_FEATURE_VI_COLON #if !ENABLE_FEATURE_VI_COLON
/* Simple ":cmd" handler with minimal set of commands */ // Simple ":cmd" handler with minimal set of commands
char *p = buf; char *p = buf;
int cnt; int cnt;
@ -1357,7 +1356,7 @@ static void colon(char *buf)
status_line_bold("No write since last change (:%s! overrides)", cmd); status_line_bold("No write since last change (:%s! overrides)", cmd);
} else { } else {
// reset the filenames to edit // reset the filenames to edit
optind = -1; /* start from 0th file */ optind = -1; // start from 0th file
editing = 0; editing = 0;
} }
# if ENABLE_FEATURE_VI_SET # if ENABLE_FEATURE_VI_SET
@ -2218,7 +2217,7 @@ static char *find_pair(char *p, const char c)
dir = strchr(braces, c) - braces; dir = strchr(braces, c) - braces;
dir ^= 1; dir ^= 1;
match = braces[dir]; match = braces[dir];
dir = ((dir & 1) << 1) - 1; /* 1 for ([{, -1 for )\} */ dir = ((dir & 1) << 1) - 1; // 1 for ([{, -1 for )\}
// look for match, count levels of pairs (( )) // look for match, count levels of pairs (( ))
level = 1; level = 1;
@ -2271,7 +2270,8 @@ static void flush_undo_data(void)
} }
// Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com) // Undo functions and hooks added by Jody Bruchon (jody@jodybruchon.com)
static void undo_push(char *src, unsigned int length, uint8_t u_type) // Add to the undo stack // Add to the undo stack
static void undo_push(char *src, unsigned length, uint8_t u_type)
{ {
struct undo_object *undo_entry; struct undo_object *undo_entry;
@ -2389,7 +2389,8 @@ static void undo_push_insert(char *p, int len, int undo)
} }
} }
static void undo_pop(void) // Undo the last operation // Undo the last operation
static void undo_pop(void)
{ {
int repeat; int repeat;
char *u_start, *u_end; char *u_start, *u_end;
@ -2453,7 +2454,8 @@ static void undo_pop(void) // Undo the last operation
} }
#if ENABLE_FEATURE_VI_UNDO_QUEUE #if ENABLE_FEATURE_VI_UNDO_QUEUE
static void undo_queue_commit(void) // Flush any queued objects to the undo stack // Flush any queued objects to the undo stack
static void undo_queue_commit(void)
{ {
// Pushes the queue object onto the undo stack // Pushes the queue object onto the undo stack
if (undo_q > 0) { if (undo_q > 0) {
@ -2758,49 +2760,44 @@ static void cookmode(void)
} }
#if ENABLE_FEATURE_VI_USE_SIGNALS #if ENABLE_FEATURE_VI_USE_SIGNALS
//----- Come here when we get a window resize signal --------- static void winch_handler(int sig UNUSED_PARAM)
static void winch_sig(int sig UNUSED_PARAM)
{ {
int save_errno = errno; int save_errno = errno;
// FIXME: do it in main loop!!! // FIXME: do it in main loop!!!
signal(SIGWINCH, winch_sig); signal(SIGWINCH, winch_handler);
query_screen_dimensions(); query_screen_dimensions();
new_screen(rows, columns); // get memory for virtual screen new_screen(rows, columns); // get memory for virtual screen
redraw(TRUE); // re-draw the screen redraw(TRUE); // re-draw the screen
errno = save_errno; errno = save_errno;
} }
static void cont_handler(int sig UNUSED_PARAM)
//----- Come here when we get a continue signal -------------------
static void cont_sig(int sig UNUSED_PARAM)
{ {
int save_errno = errno; int save_errno = errno;
rawmode(); // terminal to "raw" rawmode(); // terminal to "raw"
last_status_cksum = 0; // force status update last_status_cksum = 0; // force status update
redraw(TRUE); // re-draw the screen redraw(TRUE); // re-draw the screen
signal(SIGTSTP, suspend_sig); signal(SIGTSTP, tstp_handler);
signal(SIGCONT, SIG_DFL); signal(SIGCONT, SIG_DFL);
//kill(my_pid, SIGCONT); // huh? why? we are already "continued"... //kill(my_pid, SIGCONT); // huh? why? we are already "continued"...
errno = save_errno; errno = save_errno;
} }
static void tstp_handler(int sig UNUSED_PARAM)
//----- Come here when we get a Suspend signal -------------------
static void suspend_sig(int sig UNUSED_PARAM)
{ {
int save_errno = errno; int save_errno = errno;
go_bottom_and_clear_to_eol(); go_bottom_and_clear_to_eol();
cookmode(); // terminal to "cooked" cookmode(); // terminal to "cooked"
signal(SIGCONT, cont_sig); signal(SIGCONT, cont_handler);
signal(SIGTSTP, SIG_DFL); signal(SIGTSTP, SIG_DFL);
kill(my_pid, SIGTSTP); kill(my_pid, SIGTSTP);
errno = save_errno; errno = save_errno;
} }
//----- Come here when we get a signal --------------------------- //----- Come here when we get a signal ---------------------------
static void catch_sig(int sig) static void int_handler(int sig)
{ {
signal(SIGINT, catch_sig); signal(SIGINT, int_handler);
siglongjmp(restart, sig); siglongjmp(restart, sig);
} }
#endif /* FEATURE_VI_USE_SIGNALS */ #endif /* FEATURE_VI_USE_SIGNALS */
@ -2934,7 +2931,7 @@ static int file_insert(const char *fn, char *p, int initial)
return cnt; return cnt;
} }
/* Validate file */ // Validate file
if (fstat(fd, &statbuf) < 0) { if (fstat(fd, &statbuf) < 0) {
status_line_bold_errno(fn); status_line_bold_errno(fn);
goto fi; goto fi;
@ -2960,8 +2957,8 @@ static int file_insert(const char *fn, char *p, int initial)
#if ENABLE_FEATURE_VI_READONLY #if ENABLE_FEATURE_VI_READONLY
if (initial if (initial
&& ((access(fn, W_OK) < 0) || && ((access(fn, W_OK) < 0) ||
/* root will always have access() // root will always have access()
* so we check fileperms too */ // so we check fileperms too
!(statbuf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) !(statbuf.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH))
) )
) { ) {
@ -2979,10 +2976,9 @@ static int file_write(char *fn, char *first, char *last)
status_line_bold("No current filename"); status_line_bold("No current filename");
return -2; return -2;
} }
/* By popular request we do not open file with O_TRUNC, // By popular request we do not open file with O_TRUNC,
* but instead ftruncate() it _after_ successful write. // but instead ftruncate() it _after_ successful write.
* Might reduce amount of data lost on power fail etc. // Might reduce amount of data lost on power fail etc.
*/
fd = open(fn, (O_WRONLY | O_CREAT), 0666); fd = open(fn, (O_WRONLY | O_CREAT), 0666);
if (fd < 0) if (fd < 0)
return -1; return -1;
@ -3036,12 +3032,6 @@ static void go_bottom_and_clear_to_eol(void)
clear_to_eol(); clear_to_eol();
} }
//----- Erase from cursor to end of screen -----------------------
static void clear_to_eos(void)
{
write1(ESC_CLEAR2EOS);
}
//----- Start standout mode ------------------------------------ //----- Start standout mode ------------------------------------
static void standout_start(void) static void standout_start(void)
{ {
@ -3068,7 +3058,7 @@ static void indicate_error(void)
{ {
#if ENABLE_FEATURE_VI_CRASHME #if ENABLE_FEATURE_VI_CRASHME
if (crashme > 0) if (crashme > 0)
return; // generate a random command return;
#endif #endif
if (!err_method) { if (!err_method) {
write1(ESC_BELL); write1(ESC_BELL);
@ -3177,7 +3167,7 @@ static void print_literal(char *buf, const char *s)
} }
if (c < ' ' || c == 0x7f) { if (c < ' ' || c == 0x7f) {
*d++ = '^'; *d++ = '^';
c |= '@'; /* 0x40 */ c |= '@'; // 0x40
if (c == 0x7f) if (c == 0x7f)
c = '?'; c = '?';
} }
@ -3259,17 +3249,17 @@ static int format_edit_status(void)
cur, tot, percent); cur, tot, percent);
if (ret >= 0 && ret < trunc_at) if (ret >= 0 && ret < trunc_at)
return ret; /* it all fit */ return ret; // it all fit
return trunc_at; /* had to truncate */ return trunc_at; // had to truncate
#undef tot #undef tot
} }
//----- Force refresh of all Lines ----------------------------- //----- Force refresh of all Lines -----------------------------
static void redraw(int full_screen) static void redraw(int full_screen)
{ {
place_cursor(0, 0); // cursor to top,left; clear to the end of screen
clear_to_eos(); write1(ESC_SET_CURSOR_TOPLEFT ESC_CLEAR2EOS);
screen_erase(); // erase the internal screen buffer screen_erase(); // erase the internal screen buffer
last_status_cksum = 0; // force status update last_status_cksum = 0; // force status update
refresh(full_screen); // this will redraw the entire display refresh(full_screen); // this will redraw the entire display
@ -3354,7 +3344,7 @@ static void refresh(int full_screen)
#else #else
if (c != columns || r != rows) { if (c != columns || r != rows) {
full_screen = TRUE; full_screen = TRUE;
/* update screen memory since SIGWINCH won't have done it */ // update screen memory since SIGWINCH won't have done it
new_screen(rows, columns); new_screen(rows, columns);
} }
#endif #endif
@ -3431,7 +3421,6 @@ static void refresh(int full_screen)
//--------------------------------------------------------------------- //---------------------------------------------------------------------
//----- the Ascii Chart ----------------------------------------------- //----- the Ascii Chart -----------------------------------------------
//
// 00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel // 00 nul 01 soh 02 stx 03 etx 04 eot 05 enq 06 ack 07 bel
// 08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si // 08 bs 09 ht 0a nl 0b vt 0c np 0d cr 0e so 0f si
// 10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb // 10 dle 11 dc1 12 dc2 13 dc3 14 dc4 15 nak 16 syn 17 etb
@ -3466,7 +3455,7 @@ static void do_cmd(int c)
show_status_line(); show_status_line();
/* if this is a cursor key, skip these checks */ // if this is a cursor key, skip these checks
switch (c) { switch (c) {
case KEYCODE_UP: case KEYCODE_UP:
case KEYCODE_DOWN: case KEYCODE_DOWN:
@ -3499,7 +3488,7 @@ static void do_cmd(int c)
} }
} }
if (cmd_mode == 1) { if (cmd_mode == 1) {
// hitting "Insert" twice means "R" replace mode // hitting "Insert" twice means "R" replace mode
if (c == KEYCODE_INSERT) goto dc5; if (c == KEYCODE_INSERT) goto dc5;
// insert the char c at "dot" // insert the char c at "dot"
if (1 <= c || Isprint(c)) { if (1 <= c || Isprint(c)) {
@ -3958,7 +3947,7 @@ static void do_cmd(int c)
} }
if (cmdcnt == 0) if (cmdcnt == 0)
cmdcnt = 1; cmdcnt = 1;
/* fall through */ // fall through
case 'G': // G- goto to a line number (default= E-O-F) case 'G': // G- goto to a line number (default= E-O-F)
dot = end - 1; // assume E-O-F dot = end - 1; // assume E-O-F
if (cmdcnt > 0) { if (cmdcnt > 0) {