diff options
author | pfg <pfg@FreeBSD.org> | 2017-02-20 03:33:59 +0000 |
---|---|---|
committer | pfg <pfg@FreeBSD.org> | 2017-02-20 03:33:59 +0000 |
commit | 90692e8243d9334f92182299ee401dc0a90965e2 (patch) | |
tree | d5cbabb64df66f2169ffabac4e42167e5a6ce02b /lib/libedit/read.c | |
parent | 3c4b6c4becf1f0078e5df17d458c36274d426a68 (diff) | |
download | FreeBSD-src-90692e8243d9334f92182299ee401dc0a90965e2.zip FreeBSD-src-90692e8243d9334f92182299ee401dc0a90965e2.tar.gz |
MFC r312997, r313002:
Re-import libedit 2016-02-27 and update libedit with changes from NetBSD's
2016-03-21.
Obtained from: NetBSD
Diffstat (limited to 'lib/libedit/read.c')
-rw-r--r-- | lib/libedit/read.c | 120 |
1 files changed, 61 insertions, 59 deletions
diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 9740599..66e266b 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.71 2014/07/06 18:15:34 christos Exp $ */ +/* $NetBSD: read.c,v 1.86 2016/03/02 19:24:20 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: read.c,v 1.71 2014/07/06 18:15:34 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.86 2016/03/02 19:24:20 christos Exp $"); #endif #endif /* not lint && not SCCSID */ #include <sys/cdefs.h> @@ -47,18 +47,21 @@ __FBSDID("$FreeBSD$"); * read.c: Clean this junk up! This is horrible code. * Terminal read functions */ +#include <ctype.h> #include <errno.h> #include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> #include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + #include "el.h" #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_char(EditLine *, wchar_t *); private int read_getcmd(EditLine *, el_action_t *, Char *); private void read_pop(c_macro_t *); @@ -241,18 +244,21 @@ FUN(el,push)(EditLine *el, const Char *str) private int read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch) { + static const Char meta = (Char)0x80; el_action_t cmd; + wchar_t wc; int num; el->el_errno = 0; do { - if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */ + if ((num = el_wgetc(el, &wc)) != 1) {/* if EOF or error */ el->el_errno = num == 0 ? 0 : errno; return 0; /* not OKCMD */ } + *ch = (Char)wc; #ifdef KANJI - if ((*ch & 0200)) { + if ((*ch & meta)) { el->el_state.metanext = 0; cmd = CcViMap[' ']; break; @@ -261,7 +267,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch) if (el->el_state.metanext) { el->el_state.metanext = 0; - *ch |= 0200; + *ch |= meta; } #ifdef WIDECHAR if (*ch >= N_KEYS) @@ -296,29 +302,17 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch) return OKCMD; } -#ifdef WIDECHAR -/* utf8_islead(): - * Test whether a byte is a leading byte of a UTF-8 sequence. - */ -private int -utf8_islead(int c) -{ - return c < 0x80 || /* single byte char */ - (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */ -} -#endif - /* read_char(): * Read a character from the tty. */ private int -read_char(EditLine *el, Char *cp) +read_char(EditLine *el, wchar_t *cp) { ssize_t num_read; int tried = 0; char cbuf[MB_LEN_MAX]; size_t cbp = 0; - int bytes = 0; + int save_errno = errno; again: el->el_signal->sig_no = 0; @@ -334,50 +328,59 @@ read_char(EditLine *el, Char *cp) default: break; } - if (!tried && read__fixio(el->el_infd, e) == 0) + if (!tried && read__fixio(el->el_infd, e) == 0) { + errno = save_errno; tried = 1; - else { + } else { errno = e; - *cp = '\0'; + *cp = L'\0'; return -1; } } /* Test for EOF */ if (num_read == 0) { - errno = 0; - *cp = '\0'; + *cp = L'\0'; return 0; } -#ifdef WIDECHAR - if (el->el_flags & CHARSET_IS_UTF8) { - if (!utf8_islead((unsigned char)cbuf[0])) - goto again; /* discard the byte we read and try again */ + for (;;) { + ++cbp; - if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) { - ct_mbtowc_reset; - if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */ + switch (ct_mbrtowc(cp, cbuf, cbp)) { + case (size_t)-1: + if (cbp > 1) { + /* + * Invalid sequence, discard all bytes + * except the last one. + */ + cbuf[0] = cbuf[cbp - 1]; + cbp = 0; + break; + } else { + /* Invalid byte, discard it. */ + cbp = 0; + goto again; + } + case (size_t)-2: + /* + * We don't support other multibyte charsets. + * The second condition shouldn't happen + * and is here merely for additional safety. + */ + if ((el->el_flags & CHARSET_IS_UTF8) == 0 || + cbp >= MB_LEN_MAX) { errno = EILSEQ; - *cp = '\0'; + *cp = L'\0'; return -1; } + /* Incomplete sequence, read another byte. */ goto again; + default: + /* Valid character, process it. */ + return 1; } - } else if (isascii((unsigned char)cbuf[0]) || - /* we don't support other multibyte charsets */ - ++cbp != 1 || - /* Try non-ASCII characters in a 8-bit character set */ - (bytes = ct_mbtowc(cp, cbuf, cbp)) != 1) -#endif - *cp = (unsigned char)cbuf[0]; - - if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) { - cbp = 0; /* skip this character */ - goto again; } - - return (int)num_read; } /* read_pop(): @@ -395,11 +398,11 @@ read_pop(c_macro_t *ma) ma->offset = 0; } -/* el_getc(): - * Read a character +/* el_wgetc(): + * Read a wide character */ public int -FUN(el,getc)(EditLine *el, Char *cp) +el_wgetc(EditLine *el, wchar_t *cp) { int num_read; c_macro_t *ma = &el->el_chared.c_macro; @@ -441,12 +444,8 @@ FUN(el,getc)(EditLine *el, Char *cp) num_read = (*el->el_read.read_char)(el, cp); if (num_read < 0) el->el_errno = errno; -#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); + (void) fprintf(el->el_errfile, "Got it %lc\n", *cp); #endif /* DEBUG_READ */ return num_read; } @@ -487,6 +486,7 @@ FUN(el,gets)(EditLine *el, int *nread) int retval; el_action_t cmdnum = 0; int num; /* how many chars we have read at NL */ + wchar_t wc; Char ch, *cp; int crlf = 0; int nrb; @@ -502,7 +502,8 @@ FUN(el,gets)(EditLine *el, int *nread) size_t idx; cp = el->el_line.buffer; - while ((num = (*el->el_read.read_char)(el, cp)) == 1) { + while ((num = (*el->el_read.read_char)(el, &wc)) == 1) { + *cp = (Char)wc; /* make sure there is space for next character */ if (cp + 1 >= el->el_line.limit) { idx = (size_t)(cp - el->el_line.buffer); @@ -554,7 +555,8 @@ FUN(el,gets)(EditLine *el, int *nread) terminal__flush(el); - while ((num = (*el->el_read.read_char)(el, cp)) == 1) { + while ((num = (*el->el_read.read_char)(el, &wc)) == 1) { + *cp = (Char)wc; /* make sure there is space next character */ if (cp + 1 >= el->el_line.limit) { idx = (size_t)(cp - el->el_line.buffer); @@ -615,7 +617,7 @@ FUN(el,gets)(EditLine *el, int *nread) break; if (b->name) (void) fprintf(el->el_errfile, - "Executing %s\n", b->name); + "Executing " FSTR "\n", b->name); else (void) fprintf(el->el_errfile, "Error command = %d\n", cmdnum); |