mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
WL#5945 : Improve libedit library
Updated libedit library.
This commit is contained in:
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
return (num_read);
|
||||
#ifdef WIDECHAR
|
||||
++cbp;
|
||||
if (cbp > 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
|
||||
|
||||
#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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user