summaryrefslogtreecommitdiffstats
path: root/lib/libedit/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libedit/read.c')
-rw-r--r--lib/libedit/read.c120
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);
OpenPOWER on IntegriCloud