diff options
Diffstat (limited to 'cmd-line-utils/libedit/read.c')
-rw-r--r-- | cmd-line-utils/libedit/read.c | 265 |
1 files changed, 180 insertions, 85 deletions
diff --git a/cmd-line-utils/libedit/read.c b/cmd-line-utils/libedit/read.c index ac768142e79..a919b888965 100644 --- a/cmd-line-utils/libedit/read.c +++ b/cmd-line-utils/libedit/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.43 2009/02/05 19:15:44 christos Exp $ */ +/* $NetBSD: read.c,v 1.67 2011/08/16 16:25:15 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -48,14 +48,15 @@ static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #include <fcntl.h> #include <unistd.h> #include <stdlib.h> +#include <limits.h> #include "el.h" -#define OKCMD -1 +#define OKCMD -1 /* must be -1! */ private int read__fixio(int, int); private int read_preread(EditLine *); -private int read_char(EditLine *, char *); -private int read_getcmd(EditLine *, el_action_t *, char *); +private int read_char(EditLine *, Char *); +private int read_getcmd(EditLine *, el_action_t *, Char *); private void read_pop(c_macro_t *); /* read_init(): @@ -89,7 +90,7 @@ el_read_setfn(EditLine *el, el_rfunc_t rc) protected el_rfunc_t el_read_getfn(EditLine *el) { - return (el->el_read.read_char == read_char) ? + return el->el_read.read_char == read_char ? EL_BUILTIN_GETCFN : el->el_read.read_char; } @@ -131,7 +132,7 @@ read__fixio(int fd __attribute__((__unused__)), int e) #ifdef EWOULDBLOCK case EWOULDBLOCK: #ifndef TRY_AGAIN -#define TRY_AGAIN +#define TRY_AGAIN #endif #endif /* EWOULDBLOCK */ @@ -139,7 +140,7 @@ read__fixio(int fd __attribute__((__unused__)), int e) #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EAGAIN: #ifndef TRY_AGAIN -#define TRY_AGAIN +#define TRY_AGAIN #endif #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ #endif /* POSIX && EAGAIN */ @@ -148,10 +149,10 @@ read__fixio(int fd __attribute__((__unused__)), int e) #ifdef TRY_AGAIN #if defined(F_SETFL) && defined(O_NDELAY) if ((e = fcntl(fd, F_GETFL, 0)) == -1) - return (-1); + return -1; if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) - return (-1); + return -1; else e = 1; #endif /* F_SETFL && O_NDELAY */ @@ -160,21 +161,21 @@ read__fixio(int fd __attribute__((__unused__)), int e) { int zero = 0; - if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1) - return (-1); + if (ioctl(fd, FIONBIO, &zero) == -1) + return -1; else e = 1; } #endif /* FIONBIO */ #endif /* TRY_AGAIN */ - return (e ? 0 : -1); + return e ? 0 : -1; case EINTR: - return (0); + return 0; default: - return (-1); + return -1; } } @@ -188,10 +189,13 @@ read_preread(EditLine *el) int chrs = 0; if (el->el_tty.t_mode == ED_IO) - return (0); + return 0; +#ifndef WIDECHAR +/* FIONREAD attempts to buffer up multiple bytes, and to make that work + * properly with partial wide/UTF-8 characters would need some careful work. */ #ifdef FIONREAD - (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); + (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs > 0) { char buf[EL_BUFSIZ]; @@ -203,8 +207,8 @@ read_preread(EditLine *el) } } #endif /* FIONREAD */ - - return (chrs > 0); +#endif + return chrs > 0; } @@ -212,33 +216,37 @@ read_preread(EditLine *el) * Push a macro */ public void -el_push(EditLine *el, const char *str) +FUN(el,push)(EditLine *el, const Char *str) { c_macro_t *ma = &el->el_chared.c_macro; if (str != NULL && ma->level + 1 < EL_MAXMACRO) { ma->level++; - if ((ma->macro[ma->level] = el_strdup(str)) != NULL) + if ((ma->macro[ma->level] = Strdup(str)) != NULL) return; ma->level--; } - term_beep(el); - term__flush(el); + terminal_beep(el); + terminal__flush(el); } /* read_getcmd(): * Return next command from the input stream. + * Character values > 255 are not looked up in the map, but inserted. */ private int -read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) +read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch) { el_action_t cmd; int num; + el->el_errno = 0; do { - if ((num = el_getc(el, ch)) != 1) /* if EOF or error */ - return (num); + if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */ + el->el_errno = num == 0 ? 0 : errno; + return num; + } #ifdef KANJI if ((*ch & 0200)) { @@ -252,15 +260,20 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) el->el_state.metanext = 0; *ch |= 0200; } - cmd = el->el_map.current[(unsigned char) *ch]; +#ifdef WIDECHAR + if (*ch >= N_KEYS) + cmd = ED_INSERT; + else +#endif + cmd = el->el_map.current[(unsigned char) *ch]; if (cmd == ED_SEQUENCE_LEAD_IN) { - key_value_t val; - switch (key_get(el, ch, &val)) { + keymacro_value_t val; + switch (keymacro_get(el, ch, &val)) { case XK_CMD: cmd = val.cmd; break; case XK_STR: - el_push(el, val.str); + FUN(el,push)(el, val.str); break; #ifdef notyet case XK_EXE: @@ -277,28 +290,82 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) el->el_map.current = el->el_map.key; } while (cmd == ED_SEQUENCE_LEAD_IN); *cmdnum = cmd; - return (OKCMD); + return OKCMD; } - /* read_char(): * Read a character from the tty. */ private int -read_char(EditLine *el, char *cp) +read_char(EditLine *el, Char *cp) { - int num_read; + ssize_t num_read; int tried = 0; + char cbuf[MB_LEN_MAX]; + size_t cbp = 0; + int bytes = 0; - while ((num_read = read(el->el_infd, cp, 1)) == -1) +#ifdef WIDECHAR +static mbstate_t state, temp_state; +memset(&state, 0, sizeof(mbstate_t)); +#endif + + again: + el->el_signal->sig_no = 0; + while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) { + switch (el->el_signal->sig_no) { + case SIGCONT: + FUN(el,set)(el, EL_REFRESH); + /*FALLTHROUGH*/ + case SIGWINCH: + sig_set(el); + goto again; + default: + break; + } if (!tried && read__fixio(el->el_infd, errno) == 0) tried = 1; else { *cp = '\0'; - return (-1); + return -1; } + } + +#ifdef WIDECHAR + ++cbp; + if (cbp > (size_t) MB_CUR_MAX) { /* "shouldn't happen" */ + *cp = '\0'; + return (-1); + } + + temp_state= state; + + if ((bytes = mbrtowc(cp, cbuf, cbp, &state)) == -2) + { + /* Incomplete sequence, restore the state and scan more bytes. */ + state= temp_state; + goto again; + } + else if (bytes == -1) + { + /* Invalid sequence, reset the state and continue. */ + cbp= 0; + memset(&state, 0, sizeof(mbstate_t)); + goto again; + } + /* We successfully read one single or multi-byte character */ +#else + *cp = (unsigned char)cbuf[0]; +#endif - return (num_read); +#if 0 + if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) { + cbp = 0; /* skip this character */ + goto again; + } +#endif + + return (int)num_read; } /* read_pop(): @@ -310,8 +377,9 @@ read_pop(c_macro_t *ma) int i; el_free(ma->macro[0]); - for (i = ma->level--; i > 0; i--) - ma->macro[i - 1] = ma->macro[i]; + for (i = 0; i < ma->level; i++) + ma->macro[i] = ma->macro[i + 1]; + ma->level--; ma->offset = 0; } @@ -319,12 +387,12 @@ read_pop(c_macro_t *ma) * Read a character */ public int -el_getc(EditLine *el, char *cp) +FUN(el,getc)(EditLine *el, Char *cp) { int num_read; c_macro_t *ma = &el->el_chared.c_macro; - term__flush(el); + terminal__flush(el); for (;;) { if (ma->level < 0) { if (!read_preread(el)) @@ -339,30 +407,34 @@ el_getc(EditLine *el, char *cp) continue; } - *cp = ma->macro[0][ma->offset++] & 0377; + *cp = ma->macro[0][ma->offset++]; if (ma->macro[0][ma->offset] == '\0') { /* Needed for QuoteMode On */ read_pop(ma); } - return (1); + return 1; } #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Turning raw mode on\n"); #endif /* DEBUG_READ */ if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ - return (0); + return 0; #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Reading a character\n"); #endif /* DEBUG_READ */ num_read = (*el->el_read.read_char)(el, cp); +#ifdef WIDECHAR + if (el->el_flags & NARROW_READ) + *cp = *(char *)(void *)cp; +#endif #ifdef DEBUG_READ (void) fprintf(el->el_errfile, "Got it %c\n", *cp); #endif /* DEBUG_READ */ - return (num_read); + return num_read; } protected void @@ -383,7 +455,7 @@ read_prepare(EditLine *el) re_refresh(el); /* print the prompt */ if (el->el_flags & UNBUFFERED) - term__flush(el); + terminal__flush(el); } protected void @@ -395,27 +467,32 @@ read_finish(EditLine *el) sig_clr(el); } -public const char * -el_gets(EditLine *el, int *nread) +public const Char * +FUN(el,gets)(EditLine *el, int *nread) { int retval; el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ - char ch; + Char ch, *cp; int crlf = 0; + int nrb; #ifdef FIONREAD c_macro_t *ma = &el->el_chared.c_macro; #endif /* FIONREAD */ + if (nread == NULL) + nread = &nrb; + *nread = 0; + if (el->el_flags & NO_TTY) { - char *cp = el->el_line.buffer; size_t idx; - while ((*el->el_read.read_char)(el, cp) == 1) { + cp = el->el_line.buffer; + while ((num = (*el->el_read.read_char)(el, cp)) == 1) { /* make sure there is space for next character */ if (cp + 1 >= el->el_line.limit) { - idx = (cp - el->el_line.buffer); - if (!ch_enlargebufs(el, 2)) + idx = (size_t)(cp - el->el_line.buffer); + if (!ch_enlargebufs(el, (size_t)2)) break; cp = &el->el_line.buffer[idx]; } @@ -425,12 +502,13 @@ el_gets(EditLine *el, int *nread) if (cp[-1] == '\r' || cp[-1] == '\n') break; } + if (num == -1) { + if (errno == EINTR) + cp = el->el_line.buffer; + el->el_errno = errno; + } - el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; - if (nread) - *nread = el->el_line.cursor - el->el_line.buffer; - return (el->el_line.buffer); + goto noedit; } @@ -438,12 +516,12 @@ el_gets(EditLine *el, int *nread) if (el->el_tty.t_mode == EX_IO && ma->level < 0) { long chrs = 0; - (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); + (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs == 0) { if (tty_rawmode(el) < 0) { - if (nread) - *nread = 0; - return (NULL); + errno = 0; + *nread = 0; + return NULL; } } } @@ -453,25 +531,23 @@ el_gets(EditLine *el, int *nread) read_prepare(el); if (el->el_flags & EDIT_DISABLED) { - char *cp; size_t idx; + if ((el->el_flags & UNBUFFERED) == 0) cp = el->el_line.buffer; else cp = el->el_line.lastchar; - term__flush(el); + terminal__flush(el); - while ((*el->el_read.read_char)(el, cp) == 1) { + while ((num = (*el->el_read.read_char)(el, cp)) == 1) { /* make sure there is space next character */ if (cp + 1 >= el->el_line.limit) { - idx = (cp - el->el_line.buffer); - if (!ch_enlargebufs(el, 2)) + idx = (size_t)(cp - el->el_line.buffer); + if (!ch_enlargebufs(el, (size_t)2)) break; cp = &el->el_line.buffer[idx]; } - if (*cp == 4) /* ought to be stty eof */ - break; cp++; crlf = cp[-1] == '\r' || cp[-1] == '\n'; if (el->el_flags & UNBUFFERED) @@ -480,11 +556,13 @@ el_gets(EditLine *el, int *nread) break; } - el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; - if (nread) - *nread = el->el_line.cursor - el->el_line.buffer; - return (el->el_line.buffer); + if (num == -1) { + if (errno == EINTR) + cp = el->el_line.buffer; + el->el_errno = errno; + } + + goto noedit; } for (num = OKCMD; num == OKCMD;) { /* while still editing this @@ -500,6 +578,12 @@ el_gets(EditLine *el, int *nread) #endif /* DEBUG_READ */ break; } + if (el->el_errno == EINTR) { + el->el_line.buffer[0] = '\0'; + el->el_line.lastchar = + el->el_line.cursor = el->el_line.buffer; + break; + } if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) { /* BUG CHECK command */ #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, @@ -530,7 +614,7 @@ el_gets(EditLine *el, int *nread) el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { if (cmdnum == VI_DELETE_PREV_CHAR && el->el_chared.c_redo.pos != el->el_chared.c_redo.buf - && el_isprint((unsigned char)el->el_chared.c_redo.pos[-1])) + && Isprint(el->el_chared.c_redo.pos[-1])) el->el_chared.c_redo.pos--; else *el->el_chared.c_redo.pos++ = ch; @@ -561,7 +645,7 @@ el_gets(EditLine *el, int *nread) case CC_REFRESH_BEEP: re_refresh(el); - term_beep(el); + terminal_beep(el); break; case CC_NORM: /* normal char */ @@ -582,7 +666,7 @@ el_gets(EditLine *el, int *nread) break; case CC_NEWLINE: /* normal end of line */ - num = el->el_line.lastchar - el->el_line.buffer; + num = (int)(el->el_line.lastchar - el->el_line.buffer); break; case CC_FATAL: /* fatal error, reset to known state */ @@ -593,7 +677,7 @@ el_gets(EditLine *el, int *nread) /* put (real) cursor in a known place */ re_clear_display(el); /* reset the display stuff */ ch_reset(el, 1); /* reset the input pointers */ - re_refresh(el); /* print the prompt again */ + re_refresh(el); /* print the prompt again */ break; case CC_ERROR: @@ -602,8 +686,8 @@ el_gets(EditLine *el, int *nread) (void) fprintf(el->el_errfile, "*** editor ERROR ***\r\n\n"); #endif /* DEBUG_READ */ - term_beep(el); - term__flush(el); + terminal_beep(el); + terminal__flush(el); break; } el->el_state.argument = 1; @@ -613,15 +697,26 @@ el_gets(EditLine *el, int *nread) break; } - term__flush(el); /* flush any buffered output */ + terminal__flush(el); /* flush any buffered output */ /* make sure the tty is set up correctly */ if ((el->el_flags & UNBUFFERED) == 0) { read_finish(el); - if (nread) - *nread = num; + *nread = num != -1 ? num : 0; } else { - if (nread) - *nread = el->el_line.lastchar - el->el_line.buffer; + *nread = (int)(el->el_line.lastchar - el->el_line.buffer); } - return (num ? el->el_line.buffer : NULL); + goto done; +noedit: + el->el_line.cursor = el->el_line.lastchar = cp; + *cp = '\0'; + *nread = (int)(el->el_line.cursor - el->el_line.buffer); +done: + if (*nread == 0) { + if (num == -1) { + *nread = -1; + errno = el->el_errno; + } + return NULL; + } else + return el->el_line.buffer; } |