Subject: lib/18103 - libedit fixes
To: None <netbsd-bugs@netbsd.org>
From: David Laight <david@l8s.co.uk>
List: netbsd-bugs
Date: 10/27/2002 19:27:05
(resend to nsd-bsdbugs following semd to gnats-bugs)
The following patch fixes a lot of problems with 'vi' style
editing in libedit. There are still a few unimplemented
features (in particular '.'). But it is a lot better.
Also fixed are the unresolved parts of lib/16444 lib/17246
and lib/17954. I did start fixing parts of lib/17163 but
the whole issue of malloc failing is too complicated.
Fixes include:
- undo works on more commands (eg r, R, C, S and ~)
- cursor left in correct place after undo
- deleting chars which in insert mode doesn't kill undo buffer
- paste buffer separated from undo buffer, so you can paste
deleted text after an insert
- word delimiters fixed to match vi spec
- counts of words (eg c2w) work
- selecting words backwards
- count works on ~ and r
- window size changes are picked up
- ERASE char not restricted to inserted chars
The undo code was getting complicated! Saving the entire line
and curser position made it trivial.
David
Index: Makefile
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/Makefile,v
retrieving revision 1.23
diff -u -r1.23 Makefile
--- Makefile 2002/08/19 14:55:15 1.23
+++ Makefile 2002/10/27 17:25:59
@@ -36,7 +36,7 @@
CPPFLAGS+=-I. -I${LIBEDITDIR}
CPPFLAGS+=-I. -I${.CURDIR}
CPPFLAGS+=#-DDEBUG_TTY -DDEBUG_KEY -DDEBUG_READ -DDEBUG -DDEBUG_REFRESH
-CPPFLAGS+=#-DDEBUG_PASTE
+CPPFLAGS+=#-DDEBUG_PASTE -DDEBUG_EDIT
AHDR=vi.h emacs.h common.h
ASRC=${LIBEDITDIR}/vi.c ${LIBEDITDIR}/emacs.c ${LIBEDITDIR}/common.c
Index: chared.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/chared.c,v
retrieving revision 1.15
diff -u -r1.15 chared.c
--- chared.c 2002/03/18 16:00:50 1.15
+++ chared.c 2002/10/27 17:26:01
@@ -58,17 +58,18 @@
* Handle state for the vi undo command
*/
protected void
-cv_undo(EditLine *el,int action, size_t size, char *ptr)
+cv_undo(EditLine *el, int size, char *ptr)
{
c_undo_t *vu = &el->el_chared.c_undo;
- vu->action = action;
- vu->ptr = ptr;
- vu->isize = size;
- (void) memcpy(vu->buf, vu->ptr, size);
-#ifdef DEBUG_UNDO
- (void) fprintf(el->el_errfile, "Undo buffer \"%s\" size = +%d -%d\n",
- vu->ptr, vu->isize, vu->dsize);
-#endif
+
+ vu->len = el->el_line.lastchar - el->el_line.buffer;
+ vu->cursor = el->el_line.cursor - el->el_line.buffer;
+ memcpy(vu->buf, el->el_line.buffer, vu->len + 1u);
+
+ if (ptr) {
+ memcpy(vu->paste, ptr, size +0u);
+ vu->paste_len = size;
+ }
}
@@ -102,12 +103,12 @@
if (el->el_line.cursor + num > el->el_line.lastchar)
num = el->el_line.lastchar - el->el_line.cursor;
+ if (el->el_map.current != el->el_map.emacs)
+ cv_undo(el, num, el->el_line.cursor);
+
if (num > 0) {
char *cp;
- if (el->el_map.current != el->el_map.emacs)
- cv_undo(el, INSERT, (size_t)num, el->el_line.cursor);
-
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
@@ -126,13 +127,12 @@
if (el->el_line.cursor - num < el->el_line.buffer)
num = el->el_line.cursor - el->el_line.buffer;
+ if (el->el_map.current != el->el_map.emacs)
+ cv_undo(el, num, el->el_line.cursor - num);
+
if (num > 0) {
char *cp;
- if (el->el_map.current != el->el_map.emacs)
- cv_undo(el, INSERT, (size_t)num,
- el->el_line.cursor - num);
-
for (cp = el->el_line.cursor - num;
cp <= el->el_line.lastchar;
cp++)
@@ -149,7 +149,7 @@
protected int
ce__isword(int p)
{
- return (isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL);
+ return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);
}
@@ -159,6 +159,16 @@
protected int
cv__isword(int p)
{
+ return (isalnum(p));
+}
+
+
+/* cv__isWord():
+ * Return if p is part of a big word according to vi
+ */
+protected int
+cv__isWord(int p)
+{
return (!isspace(p));
}
@@ -221,7 +231,7 @@
* vi historically deletes with cw only the word preserving the
* trailing whitespace! This is not what 'w' does..
*/
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
+ if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
while ((p < high) && isspace((unsigned char) *p))
p++;
}
@@ -238,26 +248,19 @@
* Find the previous word vi style
*/
protected char *
-cv_prev_word(EditLine *el, char *p, char *low, int n, int (*wtest)(int))
+cv_prev_word(char *p, char *low, int n, int (*wtest)(int))
{
int test;
+ p--;
while (n--) {
- p--;
- /*
- * vi historically deletes with cb only the word preserving the
- * leading whitespace! This is not what 'b' does..
- */
- if (el->el_chared.c_vcmd.action != (DELETE|INSERT))
- while ((p > low) && isspace((unsigned char) *p))
- p--;
+ while ((p > low) && isspace((unsigned char) *p))
+ p--;
test = (*wtest)((unsigned char) *p);
while ((p >= low) && (*wtest)((unsigned char) *p) == test)
p--;
- p++;
- while (isspace((unsigned char) *p))
- p++;
}
+ p++;
/* p now points where we want it */
if (p < low)
@@ -308,47 +311,27 @@
cv_delfini(EditLine *el)
{
int size;
- int oaction;
if (el->el_chared.c_vcmd.action & INSERT)
el->el_map.current = el->el_map.key;
- oaction = el->el_chared.c_vcmd.action;
el->el_chared.c_vcmd.action = NOP;
if (el->el_chared.c_vcmd.pos == 0)
return;
-
- if (el->el_line.cursor > el->el_chared.c_vcmd.pos) {
- size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
- c_delbefore(el, size);
- el->el_line.cursor = el->el_chared.c_vcmd.pos;
- re_refresh_cursor(el);
- } else if (el->el_line.cursor < el->el_chared.c_vcmd.pos) {
- size = (int)(el->el_chared.c_vcmd.pos - el->el_line.cursor);
+ size = (int) (el->el_line.cursor - el->el_chared.c_vcmd.pos);
+ el->el_line.cursor = el->el_chared.c_vcmd.pos;
+ if (size > 0) {
c_delafter(el, size);
+ re_refresh_cursor(el);
+ } else if (size < 0) {
+ c_delbefore(el, -size);
+ el->el_line.cursor += size;
} else {
- size = 1;
- c_delafter(el, size);
+ c_delafter(el, 1);
+ el->el_line.cursor--;
}
- switch (oaction) {
- case DELETE|INSERT:
- el->el_chared.c_undo.action = DELETE|INSERT;
- break;
- case DELETE:
- el->el_chared.c_undo.action = INSERT;
- break;
- case NOP:
- case INSERT:
- default:
- EL_ABORT((el->el_errfile, "Bad oaction %d\n", oaction));
- break;
- }
-
-
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.dsize = size;
}
@@ -378,21 +361,19 @@
* Go to the end of this word according to vi
*/
protected char *
-cv__endword(char *p, char *high, int n)
+cv__endword(char *p, char *high, int n, int (*wtest)(int))
{
+ int test;
+
p++;
while (n--) {
while ((p < high) && isspace((unsigned char) *p))
p++;
- if (isalnum((unsigned char) *p))
- while ((p < high) && isalnum((unsigned char) *p))
- p++;
- else
- while ((p < high) && !(isspace((unsigned char) *p) ||
- isalnum((unsigned char) *p)))
- p++;
+ test = (*wtest)((unsigned char) *p);
+ while ((p < high) && (*wtest)((unsigned char) *p) == test)
+ p++;
}
p--;
return (p);
@@ -411,20 +392,21 @@
(void) memset(el->el_line.buffer, 0, EL_BUFSIZ);
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
- el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - 2];
+ el->el_line.limit = &el->el_line.buffer[EL_BUFSIZ - EL_LEAVE];
el->el_chared.c_undo.buf = (char *) el_malloc(EL_BUFSIZ);
if (el->el_chared.c_undo.buf == NULL)
return (-1);
(void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ);
- el->el_chared.c_undo.action = NOP;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
+ el->el_chared.c_undo.len = -1;
+ el->el_chared.c_undo.cursor = 0;
+ el->el_chared.c_undo.paste = (char *) el_malloc(EL_BUFSIZ);
+ if (el->el_chared.c_undo.paste == NULL)
+ return (-1);
+ el->el_chared.c_undo.paste_len = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
el->el_chared.c_kill.buf = (char *) el_malloc(EL_BUFSIZ);
if (el->el_chared.c_kill.buf == NULL)
@@ -459,14 +441,11 @@
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
- el->el_chared.c_undo.action = NOP;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
+ el->el_chared.c_undo.len = -1;
+ el->el_chared.c_undo.cursor = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
el->el_chared.c_kill.mark = el->el_line.buffer;
@@ -521,7 +500,8 @@
el->el_line.buffer = newbuffer;
el->el_line.cursor = newbuffer + (el->el_line.cursor - oldbuf);
el->el_line.lastchar = newbuffer + (el->el_line.lastchar - oldbuf);
- el->el_line.limit = &newbuffer[newsz - EL_LEAVE];
+ /* don't set new size until all buffers are enlarged */
+ el->el_line.limit = &newbuffer[sz - EL_LEAVE];
/*
* Reallocate kill buffer.
@@ -550,14 +530,18 @@
/* zero the newly added memory, leave old data in */
(void) memset(&newbuffer[sz], 0, newsz - sz);
-
- el->el_chared.c_undo.ptr = el->el_line.buffer +
- (el->el_chared.c_undo.ptr - oldbuf);
el->el_chared.c_undo.buf = newbuffer;
+
+ newbuffer = el_realloc(el->el_chared.c_undo.paste, newsz);
+ if (!newbuffer)
+ return 0;
+ el->el_chared.c_undo.paste = newbuffer;
if (!hist_enlargebuf(el, sz, newsz))
return 0;
+ /* Safe to set enlarged buffer size */
+ el->el_line.limit = &newbuffer[newsz - EL_LEAVE];
return 1;
}
@@ -572,6 +556,9 @@
el->el_line.limit = NULL;
el_free((ptr_t) el->el_chared.c_undo.buf);
el->el_chared.c_undo.buf = NULL;
+ el_free((ptr_t) el->el_chared.c_undo.paste);
+ el->el_chared.c_undo.paste = NULL;
+ el->el_chared.c_undo.paste_len = 0;
el_free((ptr_t) el->el_chared.c_kill.buf);
el->el_chared.c_kill.buf = NULL;
el_free((ptr_t) el->el_chared.c_macro.macro);
Index: chared.h
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/chared.h,v
retrieving revision 1.8
diff -u -r1.8 chared.h
--- chared.h 2002/03/18 16:00:51 1.8
+++ chared.h 2002/10/27 17:26:02
@@ -71,14 +71,14 @@
} c_macro_t;
/*
- * Undo information for both vi and emacs
+ * Undo information for vi - no undo in emacs (yet)
*/
typedef struct c_undo_t {
- int action;
- size_t isize;
- size_t dsize;
- char *ptr;
- char *buf;
+ int len; /* length of saved line */
+ int cursor; /* position of saved cursor */
+ char *buf; /* full saved text */
+ size_t paste_len; /* bytes to paste */
+ char *paste; /* paste string */
} c_undo_t;
/*
@@ -87,7 +87,6 @@
typedef struct c_vcmd_t {
int action;
char *pos;
- char *ins;
} c_vcmd_t;
/*
@@ -120,7 +119,6 @@
#define NOP 0x00
#define DELETE 0x01
#define INSERT 0x02
-#define CHANGE 0x04
#define CHAR_FWD 0
#define CHAR_BACK 1
@@ -137,12 +135,13 @@
protected int cv__isword(int);
+protected int cv__isWord(int);
protected void cv_delfini(EditLine *);
-protected char *cv__endword(char *, char *, int);
+protected char *cv__endword(char *, char *, int, int (*)(int));
protected int ce__isword(int);
-protected void cv_undo(EditLine *, int, size_t, char *);
+protected void cv_undo(EditLine *, /* int,*/ int, char *);
protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int));
-protected char *cv_prev_word(EditLine*, char *, char *, int, int (*)(int));
+protected char *cv_prev_word(char *, char *, int, int (*)(int));
protected char *c__next_word(char *, char *, int, int (*)(int));
protected char *c__prev_word(char *, char *, int, int (*)(int));
protected void c_insert(EditLine *, int);
Index: common.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/common.c,v
retrieving revision 1.11
diff -u -r1.11 common.c
--- common.c 2002/03/18 16:00:51 1.11
+++ common.c 2002/10/27 17:26:06
@@ -72,7 +72,6 @@
protected el_action_t
ed_insert(EditLine *el, int c)
{
- int i;
if (c == '\0')
return (CC_ERROR);
@@ -85,29 +84,16 @@
}
if (el->el_state.argument == 1) {
- if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- *el->el_line.cursor;
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, 1);
- }
- c_insert(el, 1);
+ if (el->el_state.inputmode == MODE_INSERT
+ || el->el_line.cursor >= el->el_line.lastchar)
+ c_insert(el, 1);
*el->el_line.cursor++ = c;
el->el_state.doingarg = 0; /* just in case */
re_fastaddc(el); /* fast refresh for one char. */
} else {
- if (el->el_state.inputmode != MODE_INSERT) {
- for (i = 0; i < el->el_state.argument; i++)
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- el->el_line.cursor[i];
-
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, el->el_state.argument);
- }
- c_insert(el, el->el_state.argument);
+ if (el->el_state.inputmode != MODE_REPLACE_1)
+ c_insert(el, el->el_state.argument);
while (el->el_state.argument--)
*el->el_line.cursor++ = c;
@@ -115,7 +101,7 @@
}
if (el->el_state.inputmode == MODE_REPLACE_1)
- (void) vi_command_mode(el, 0);
+ return vi_command_mode(el, 0);
return (CC_NORM);
}
@@ -411,25 +397,9 @@
(el->el_state.argument * 10) + (c - '0');
}
return (CC_ARGHACK);
- } else {
- if (el->el_line.lastchar + 1 >= el->el_line.limit) {
- if (!ch_enlargebufs(el, 1))
- return (CC_ERROR);
- }
-
- if (el->el_state.inputmode != MODE_INSERT) {
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize++] =
- *el->el_line.cursor;
- el->el_chared.c_undo.buf[el->el_chared.c_undo.isize] =
- '\0';
- c_delafter(el, 1);
- }
- c_insert(el, 1);
- *el->el_line.cursor++ = c;
- el->el_state.doingarg = 0;
- re_fastaddc(el);
}
- return (CC_NORM);
+
+ return ed_insert(el, c);
}
@@ -579,8 +549,6 @@
re_goto_bottom(el);
*el->el_line.lastchar++ = '\n';
*el->el_line.lastchar = '\0';
- if (el->el_map.type == MAP_VI)
- el->el_chared.c_vcmd.ins = el->el_line.buffer;
return (CC_NEWLINE);
}
@@ -670,7 +638,7 @@
{
char beep = 0;
- el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.len = -1;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno == 0) { /* save the current buffer
@@ -704,7 +672,7 @@
ed_next_history(EditLine *el, int c)
{
- el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.len = -1;
*el->el_line.lastchar = '\0'; /* just in case */
el->el_history.eventno -= el->el_state.argument;
@@ -730,7 +698,7 @@
bool_t found = 0;
el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.len = -1;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno < 0) {
#ifdef DEBUG_EDIT
@@ -798,7 +766,7 @@
bool_t found = 0;
el->el_chared.c_vcmd.action = NOP;
- el->el_chared.c_undo.action = NOP;
+ el->el_chared.c_undo.len = -1;
*el->el_line.lastchar = '\0'; /* just in case */
if (el->el_history.eventno == 0)
Index: el.h
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/el.h,v
retrieving revision 1.11
diff -u -r1.11 el.h
--- el.h 2002/03/18 16:00:52 1.11
+++ el.h 2002/10/27 17:26:09
@@ -137,8 +137,12 @@
protected int el_editmode(EditLine *, int, const char **);
#ifdef DEBUG
-#define EL_ABORT(a) (void) (fprintf(el->el_errfile, "%s, %d: ", \
- __FILE__, __LINE__), fprintf a, abort())
+#define EL_ABORT(a) do { \
+ fprintf(el->el_errfile, "%s, %d: ", \
+ __FILE__, __LINE__); \
+ fprintf a; \
+ abort(); \
+ } while( /*CONSTCOND*/0);
#else
#define EL_ABORT(a) abort()
#endif
Index: emacs.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/emacs.c,v
retrieving revision 1.10
diff -u -r1.10 emacs.c
--- emacs.c 2002/03/18 16:00:52 1.10
+++ emacs.c 2002/10/27 17:26:09
@@ -215,7 +215,7 @@
{
char *kp, *cp;
- if (el->el_chared.c_kill.mark)
+ if (!el->el_chared.c_kill.mark)
return (CC_ERROR);
if (el->el_chared.c_kill.mark > el->el_line.cursor) {
Index: map.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/map.c,v
retrieving revision 1.15
diff -u -r1.15 map.c
--- map.c 2002/03/18 16:00:55 1.15
+++ map.c 2002/10/27 17:26:14
@@ -379,7 +379,7 @@
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_NEXT_CHAR, /* ^F */
/* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
+ /* 8 */ VI_DELETE_PREV_CHAR, /* ^H */ /* BackSpace key */
/* 9 */ ED_UNASSIGNED, /* ^I */ /* Tab Key */
/* 10 */ ED_NEWLINE, /* ^J */
/* 11 */ ED_KILL_LINE, /* ^K */
@@ -499,7 +499,7 @@
/* 124 */ ED_INSERT, /* | */
/* 125 */ ED_INSERT, /* } */
/* 126 */ ED_INSERT, /* ~ */
- /* 127 */ ED_DELETE_PREV_CHAR, /* ^? */
+ /* 127 */ VI_DELETE_PREV_CHAR, /* ^? */
/* 128 */ ED_UNASSIGNED, /* M-^@ */
/* 129 */ ED_UNASSIGNED, /* M-^A */
/* 130 */ ED_UNASSIGNED, /* M-^B */
@@ -639,7 +639,7 @@
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_UNASSIGNED, /* ^F */
/* 7 */ ED_UNASSIGNED, /* ^G */
- /* 8 */ ED_PREV_CHAR, /* ^H */
+ /* 8 */ ED_DELETE_PREV_CHAR, /* ^H */
/* 9 */ ED_UNASSIGNED, /* ^I */
/* 10 */ ED_NEWLINE, /* ^J */
/* 11 */ ED_KILL_LINE, /* ^K */
@@ -697,10 +697,10 @@
/* 63 */ VI_SEARCH_NEXT, /* ? */
/* 64 */ ED_UNASSIGNED, /* @ */
/* 65 */ VI_ADD_AT_EOL, /* A */
- /* 66 */ VI_PREV_SPACE_WORD, /* B */
+ /* 66 */ VI_PREV_BIG_WORD, /* B */
/* 67 */ VI_CHANGE_TO_EOL, /* C */
/* 68 */ ED_KILL_LINE, /* D */
- /* 69 */ VI_TO_END_WORD, /* E */
+ /* 69 */ VI_END_BIG_WORD, /* E */
/* 70 */ VI_PREV_CHAR, /* F */
/* 71 */ ED_UNASSIGNED, /* G */
/* 72 */ ED_UNASSIGNED, /* H */
@@ -718,7 +718,7 @@
/* 84 */ VI_TO_PREV_CHAR, /* T */
/* 85 */ ED_UNASSIGNED, /* U */
/* 86 */ ED_UNASSIGNED, /* V */
- /* 87 */ VI_NEXT_SPACE_WORD, /* W */
+ /* 87 */ VI_NEXT_BIG_WORD, /* W */
/* 88 */ ED_DELETE_PREV_CHAR, /* X */
/* 89 */ ED_UNASSIGNED, /* Y */
/* 90 */ ED_UNASSIGNED, /* Z */
Index: read.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/read.c,v
retrieving revision 1.21
diff -u -r1.21 read.c
--- read.c 2002/03/18 16:00:57 1.21
+++ read.c 2002/10/27 17:26:16
@@ -389,6 +389,11 @@
*nread = el->el_line.cursor - el->el_line.buffer;
return (el->el_line.buffer);
}
+
+ /* This is relatively cheap, and things go terribly wrong if
+ we have the wrong size. */
+ el_resize(el);
+
re_clear_display(el); /* reset the display stuff */
ch_reset(el);
@@ -434,6 +439,7 @@
*nread = el->el_line.cursor - el->el_line.buffer;
return (el->el_line.buffer);
}
+
for (num = OKCMD; num == OKCMD;) { /* while still editing this
* line */
#ifdef DEBUG_EDIT
@@ -470,6 +476,10 @@
}
#endif /* DEBUG_READ */
retval = (*el->el_map.func[cmdnum]) (el, ch);
+#ifdef DEBUG_READ
+ (void) fprintf(el->el_errfile,
+ "Returned state %d\n", retval );
+#endif /* DEBUG_READ */
/* save the last command here */
el->el_state.lastcmd = cmdnum;
@@ -544,9 +554,9 @@
}
}
- /* make sure the tty is set up correctly */
- (void) tty_cookedmode(el);
term__flush(); /* flush any buffered output */
+ /* make sure the tty is set up correctly */
+ (void) tty_cookedmode(el);
if (el->el_flags & HANDLE_SIGNALS)
sig_clr(el);
if (nread)
Index: readline.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/readline.c,v
retrieving revision 1.22
diff -u -r1.22 readline.c
--- readline.c 2002/04/09 01:57:34 1.22
+++ readline.c 2002/10/27 17:26:21
@@ -287,10 +287,9 @@
/* get one line from input stream */
ret = el_gets(e, &count);
- if (ret && count > 0) {
+ if (ret && count > 0 && (buf = strdup(ret))) {
int lastidx;
- buf = strdup(ret);
lastidx = count - 1;
if (buf[lastidx] == '\n')
buf[lastidx] = '\0';
@@ -328,7 +327,7 @@
_rl_compat_sub(const char *str, const char *what, const char *with,
int globally)
{
- char *result;
+ char *result, *r;
const char *temp, *new;
int len, with_len, what_len, add;
size_t size, i;
@@ -345,7 +344,12 @@
add = i + with_len;
if (i + add + 1 >= size) {
size += add + 1;
- result = realloc(result, size);
+ r = realloc(result, size);
+ if (!r) {
+ free(result);
+ return 0;
+ }
+ result = r;
}
(void) strncpy(&result[len], temp, i);
len += i;
@@ -356,7 +360,12 @@
add = strlen(temp);
if (len + add + 1 >= size) {
size += add + 1;
- result = realloc(result, size);
+ r = realloc(result, size);
+ if (!r) {
+ free(result);
+ return 0;
+ }
+ result = r;
}
(void) strcpy(&result[len], temp); /* safe */
len += add;
@@ -576,8 +585,10 @@
tempcmd = _rl_compat_sub(line, from, to,
(g_on) ? 1 : 0);
- free(line);
- line = tempcmd;
+ if (tempcmd) {
+ free(line);
+ line = tempcmd;
+ }
g_on = 0;
}
}
@@ -790,11 +801,17 @@
}
if (result_idx + 2 >= size) {
+ char **r;
size <<= 1;
- result = realloc(result, size * sizeof(char *));
+ r = realloc(result, size * sizeof(char *));
+ if (!r)
+ break;
+ result = r;
}
len = i - start;
temp = malloc(len + 1);
+ if (!temp)
+ break;
(void) strncpy(temp, &str[start], len);
temp[len] = '\0';
result[result_idx++] = temp;
@@ -1331,10 +1348,15 @@
matches = 0;
match_list_len = 1;
while ((retstr = (*genfunc) (text, matches)) != NULL) {
- if (matches + 1 >= match_list_len) {
+ /* allow for list terminater here */
+ if (matches + 2 >= match_list_len) {
+ char **nml;
match_list_len <<= 1;
- match_list = realloc(match_list,
+ nml = realloc(match_list,
match_list_len * sizeof(char *));
+ if (!nml)
+ break;
+ match_list = nml;
}
match_list[++matches] = retstr;
}
@@ -1354,14 +1376,15 @@
}
retstr = malloc(max_equal + 1);
- (void) strncpy(retstr, match_list[1], max_equal);
- retstr[max_equal] = '\0';
- match_list[0] = retstr;
+ if (retstr) {
+ (void) strncpy(retstr, match_list[1], max_equal);
+ retstr[max_equal] = '\0';
+ match_list[0] = retstr;
+ } else
+ /* avoid leaking memory */
+ match_list[0] = match_list[matches--];
/* add NULL as last pointer to the array */
- if (matches + 1 >= match_list_len)
- match_list = realloc(match_list,
- (match_list_len + 1) * sizeof(char *));
match_list[matches + 1] = (char *) NULL;
return (match_list);
Index: refresh.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/refresh.c,v
retrieving revision 1.18
diff -u -r1.18 refresh.c
--- refresh.c 2002/03/18 16:00:58 1.18
+++ refresh.c 2002/10/27 17:26:25
@@ -64,21 +64,21 @@
private void re__copy_and_pad(char *, const char *, size_t);
#ifdef DEBUG_REFRESH
-private void re_printstr(EditLine *, char *, char *, char *);
+private void re_printstr(EditLine *, const char *, char *, char *);
#define __F el->el_errfile
#define ELRE_ASSERT(a, b, c) do \
- if (a) { \
+ if (/*CONSTCOND*/ a) { \
(void) fprintf b; \
c; \
} \
- while (0)
+ while (/*CONSTCOND*/0)
#define ELRE_DEBUG(a, b) ELRE_ASSERT(a,b,;)
/* re_printstr():
* Print a string on the debugging pty
*/
private void
-re_printstr(EditLine *el, char *str, char *f, char *t)
+re_printstr(EditLine *el, const char *str, char *f, char *t)
{
ELRE_DEBUG(1, (__F, "%s:\"", str));
@@ -318,7 +318,6 @@
{
term_move_to_line(el, el->el_refresh.r_oldcv);
- term__putc('\r');
term__putc('\n');
re_clear_display(el);
term__flush();
Index: tokenizer.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/tokenizer.c,v
retrieving revision 1.10
diff -u -r1.10 tokenizer.c
--- tokenizer.c 2002/03/18 16:01:00 1.10
+++ tokenizer.c 2002/10/27 17:26:27
@@ -109,16 +109,19 @@
{
Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer));
+ if (!tok)
+ return 0;
+
tok->ifs = strdup(ifs ? ifs : IFS);
+ tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
+ tok->wspace = (char *) tok_malloc(WINCR);
+ if (!tok->ifs || !tok->argv || !tok->wspace) {
+ tok_end(tok);
+ return 0;
+ }
tok->argc = 0;
tok->amax = AINCR;
- tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax);
- if (tok->argv == NULL)
- return (NULL);
tok->argv[0] = NULL;
- tok->wspace = (char *) tok_malloc(WINCR);
- if (tok->wspace == NULL)
- return (NULL);
tok->wmax = tok->wspace + WINCR;
tok->wstart = tok->wspace;
tok->wptr = tok->wspace;
Index: vi.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libedit/vi.c,v
retrieving revision 1.9
diff -u -r1.9 vi.c
--- vi.c 2002/03/18 16:01:01 1.9
+++ vi.c 2002/10/27 17:26:29
@@ -59,22 +59,14 @@
private el_action_t
cv_action(EditLine *el, int c)
{
- char *cp, *kp;
if (el->el_chared.c_vcmd.action & DELETE) {
+ /* 'dd' and (possibly) friends */
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- kp = el->el_chared.c_undo.buf;
- for (cp = el->el_line.buffer; cp < el->el_line.lastchar; cp++) {
- *kp++ = *cp;
- el->el_chared.c_undo.dsize++;
- }
-
- el->el_chared.c_undo.action = INSERT;
- el->el_chared.c_undo.ptr = el->el_line.buffer;
+ cv_undo(el, el->el_line.lastchar - el->el_line.buffer,
+ el->el_line.buffer );
el->el_line.lastchar = el->el_line.buffer;
el->el_line.cursor = el->el_line.buffer;
if (c & INSERT)
@@ -103,7 +95,6 @@
#endif
}
-
/* cv_paste():
* Paste previous deletion before or after the cursor
*/
@@ -114,20 +105,22 @@
c_undo_t *un = &el->el_chared.c_undo;
#ifdef DEBUG_PASTE
- (void) fprintf(el->el_errfile, "Paste: %x \"%s\" +%d -%d\n",
- un->action, un->buf, un->isize, un->dsize);
+ (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n",
+ (int)un->paste_len, un->paste ? un->paste : "<null>" );
#endif
- if (un->isize == 0)
+ if (!un->paste || !un->paste_len)
return (CC_ERROR);
+ cv_undo(el, 0, 0);
+
if (!c && el->el_line.cursor < el->el_line.lastchar)
el->el_line.cursor++;
ptr = el->el_line.cursor;
- c_insert(el, (int) un->isize);
- if (el->el_line.cursor + un->isize > el->el_line.lastchar)
+ c_insert(el, (int) un->paste_len);
+ if (el->el_line.cursor + un->paste_len > el->el_line.lastchar)
return (CC_ERROR);
- (void) memcpy(ptr, un->buf, un->isize);
+ (void) memcpy(ptr, un->paste, un->paste_len);
return (CC_REFRESH);
}
@@ -158,22 +151,22 @@
}
-/* vi_prev_space_word():
+/* vi_prev_big_word():
* Vi move to the previous space delimited word
* [B]
*/
protected el_action_t
/*ARGSUSED*/
-vi_prev_space_word(EditLine *el, int c)
+vi_prev_big_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.cursor = cv_prev_word(el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
- cv__isword);
+ cv__isWord);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
@@ -185,7 +178,7 @@
/* vi_prev_word():
* Vi move to the previous word
- * [B]
+ * [b]
*/
protected el_action_t
/*ARGSUSED*/
@@ -195,10 +188,10 @@
if (el->el_line.cursor == el->el_line.buffer)
return (CC_ERROR);
- el->el_line.cursor = cv_prev_word(el, el->el_line.cursor,
+ el->el_line.cursor = cv_prev_word(el->el_line.cursor,
el->el_line.buffer,
el->el_state.argument,
- ce__isword);
+ cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
cv_delfini(el);
@@ -208,13 +201,13 @@
}
-/* vi_next_space_word():
+/* vi_next_big_word():
* Vi move to the next space delimited word
* [W]
*/
protected el_action_t
/*ARGSUSED*/
-vi_next_space_word(EditLine *el, int c)
+vi_next_big_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
@@ -223,7 +216,7 @@
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
- cv__isword);
+ cv__isWord);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
@@ -249,7 +242,7 @@
el->el_line.cursor = cv_next_word(el, el->el_line.cursor,
el->el_line.lastchar,
el->el_state.argument,
- ce__isword);
+ cv__isword);
if (el->el_map.type == MAP_VI)
if (el->el_chared.c_vcmd.action & DELETE) {
@@ -267,8 +260,15 @@
protected el_action_t
vi_change_case(EditLine *el, int c)
{
+ int i;
- if (el->el_line.cursor < el->el_line.lastchar) {
+ if (el->el_line.cursor >= el->el_line.lastchar)
+ return (CC_ERROR);
+ cv_undo(el, 0, 0);
+ for (i = 0; i < el->el_state.argument; i++) {
+ if (el->el_line.cursor >= el->el_line.lastchar)
+ break;
+
c = *el->el_line.cursor;
if (isupper(c))
*el->el_line.cursor++ = tolower(c);
@@ -277,9 +277,8 @@
else
el->el_line.cursor++;
re_fastaddc(el);
- return (CC_NORM);
}
- return (CC_ERROR);
+ return (CC_NORM);
}
@@ -310,11 +309,7 @@
{
el->el_line.cursor = el->el_line.buffer;
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
-
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
-
+ cv_undo(el, 0, 0);
el->el_map.current = el->el_map.key;
return (CC_CURSOR);
}
@@ -329,13 +324,13 @@
vi_replace_char(EditLine *el, int c)
{
+ if (el->el_state.argument > el->el_line.lastchar - el->el_line.cursor)
+ return CC_ERROR;
+
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE_1;
- el->el_chared.c_undo.action = CHANGE;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
- return (CC_NORM);
+ cv_undo(el, 0, 0);
+ return (CC_ARGHACK);
}
@@ -350,17 +345,14 @@
el->el_map.current = el->el_map.key;
el->el_state.inputmode = MODE_REPLACE;
- el->el_chared.c_undo.action = CHANGE;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.isize = 0;
- el->el_chared.c_undo.dsize = 0;
+ cv_undo(el, 0, 0);
return (CC_NORM);
}
/* vi_substitute_char():
* Vi replace character under the cursor and enter insert mode
- * [r]
+ * [s]
*/
protected el_action_t
/*ARGSUSED*/
@@ -382,6 +374,8 @@
vi_substitute_line(EditLine *el, int c)
{
+ cv_undo(el, el->el_line.lastchar - el->el_line.buffer,
+ el->el_line.buffer);
(void) em_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
@@ -397,6 +391,8 @@
vi_change_to_eol(EditLine *el, int c)
{
+ cv_undo(el, el->el_line.lastchar - el->el_line.cursor,
+ el->el_line.cursor);
(void) ed_kill_line(el, 0);
el->el_map.current = el->el_map.key;
return (CC_REFRESH);
@@ -413,11 +409,7 @@
{
el->el_map.current = el->el_map.key;
-
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
-
+ cv_undo(el, 0, 0);
return (CC_NORM);
}
@@ -441,9 +433,7 @@
} else
ret = CC_NORM;
- el->el_chared.c_vcmd.ins = el->el_line.cursor;
- el->el_chared.c_undo.ptr = el->el_line.cursor;
- el->el_chared.c_undo.action = DELETE;
+ cv_undo(el, 0, 0);
return (ret);
}
@@ -460,11 +450,7 @@
el->el_map.current = el->el_map.key;
el->el_line.cursor = el->el_line.lastchar;
-
- /* Mark where insertion begins */
- el->el_chared.c_vcmd.ins = el->el_line.lastchar;
- el->el_chared.c_undo.ptr = el->el_line.lastchar;
- el->el_chared.c_undo.action = DELETE;
+ cv_undo(el, 0, 0);
return (CC_CURSOR);
}
@@ -482,20 +468,20 @@
}
-/* vi_end_word():
+/* vi_end_big_word():
* Vi move to the end of the current space delimited word
* [E]
*/
protected el_action_t
/*ARGSUSED*/
-vi_end_word(EditLine *el, int c)
+vi_end_big_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv__endword(el->el_line.cursor,
- el->el_line.lastchar, el->el_state.argument);
+ el->el_line.lastchar, el->el_state.argument, cv__isWord);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
@@ -506,20 +492,20 @@
}
-/* vi_to_end_word():
+/* vi_end_word():
* Vi move to the end of the current word
* [e]
*/
protected el_action_t
/*ARGSUSED*/
-vi_to_end_word(EditLine *el, int c)
+vi_end_word(EditLine *el, int c)
{
if (el->el_line.cursor == el->el_line.lastchar)
return (CC_ERROR);
el->el_line.cursor = cv__endword(el->el_line.cursor,
- el->el_line.lastchar, el->el_state.argument);
+ el->el_line.lastchar, el->el_state.argument, cv__isword);
if (el->el_chared.c_vcmd.action & DELETE) {
el->el_line.cursor++;
@@ -538,100 +524,19 @@
/*ARGSUSED*/
vi_undo(EditLine *el, int c)
{
- char *cp, *kp;
- char temp;
- int i, size;
- c_undo_t *un = &el->el_chared.c_undo;
+ c_undo_t un = el->el_chared.c_undo;
-#ifdef DEBUG_UNDO
- (void) fprintf(el->el_errfile, "Undo: %x \"%s\" +%d -%d\n",
- un->action, un->buf, un->isize, un->dsize);
-#endif
- switch (un->action) {
- case DELETE:
- if (un->dsize == 0)
- return (CC_NORM);
-
- (void) memcpy(un->buf, un->ptr, un->dsize);
- for (cp = un->ptr; cp <= el->el_line.lastchar; cp++)
- *cp = cp[un->dsize];
-
- el->el_line.lastchar -= un->dsize;
- el->el_line.cursor = un->ptr;
-
- un->action = INSERT;
- un->isize = un->dsize;
- un->dsize = 0;
- break;
-
- case DELETE | INSERT:
- size = un->isize - un->dsize;
- if (size > 0)
- i = un->dsize;
- else
- i = un->isize;
- cp = un->ptr;
- kp = un->buf;
- while (i-- > 0) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- if (size > 0) {
- el->el_line.cursor = cp;
- c_insert(el, size);
- while (size-- > 0 && cp < el->el_line.lastchar) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- } else if (size < 0) {
- size = -size;
- for (; cp <= el->el_line.lastchar; cp++) {
- *kp++ = *cp;
- *cp = cp[size];
- }
- el->el_line.lastchar -= size;
- }
- el->el_line.cursor = un->ptr;
- i = un->dsize;
- un->dsize = un->isize;
- un->isize = i;
- break;
-
- case INSERT:
- if (un->isize == 0)
- return (CC_NORM);
-
- el->el_line.cursor = un->ptr;
- c_insert(el, (int) un->isize);
- (void) memcpy(un->ptr, un->buf, un->isize);
- un->action = DELETE;
- un->dsize = un->isize;
- un->isize = 0;
- break;
-
- case CHANGE:
- if (un->isize == 0)
- return (CC_NORM);
-
- el->el_line.cursor = un->ptr;
- size = (int) (el->el_line.cursor - el->el_line.lastchar);
- if (size < un->isize)
- size = un->isize;
- cp = un->ptr;
- kp = un->buf;
- for (i = 0; i < size; i++) {
- temp = *kp;
- *kp++ = *cp;
- *cp++ = temp;
- }
- un->dsize = 0;
- break;
+ if (un.len == -1)
+ return CC_ERROR;
- default:
- return (CC_ERROR);
- }
+ /* switch line buffer and undo buffer */
+ el->el_chared.c_undo.buf = el->el_line.buffer;
+ el->el_chared.c_undo.len = el->el_line.lastchar - el->el_line.buffer;
+ el->el_chared.c_undo.cursor = el->el_line.cursor - el->el_line.buffer;
+ el->el_line.limit = un.buf + (el->el_line.limit - el->el_line.buffer);
+ el->el_line.buffer = un.buf;
+ el->el_line.cursor = un.buf + un.cursor;
+ el->el_line.lastchar = un.buf + un.len;
return (CC_REFRESH);
}
@@ -645,22 +550,12 @@
/*ARGSUSED*/
vi_command_mode(EditLine *el, int c)
{
- int size;
/* [Esc] cancels pending action */
- el->el_chared.c_vcmd.ins = 0;
el->el_chared.c_vcmd.action = NOP;
el->el_chared.c_vcmd.pos = 0;
el->el_state.doingarg = 0;
- size = el->el_chared.c_undo.ptr - el->el_line.cursor;
- if (size < 0)
- size = -size;
- if (el->el_chared.c_undo.action == (INSERT | DELETE) ||
- el->el_chared.c_undo.action == DELETE)
- el->el_chared.c_undo.dsize = size;
- else
- el->el_chared.c_undo.isize = size;
el->el_state.inputmode = MODE_INSERT;
el->el_map.current = el->el_map.alt;
@@ -699,22 +594,23 @@
/* vi_delete_prev_char():
* Vi move to previous character (backspace)
- * [^H]
+ * [^H] in insert mode only
*/
protected el_action_t
/*ARGSUSED*/
vi_delete_prev_char(EditLine *el, int c)
{
-
- if (el->el_chared.c_vcmd.ins == 0)
- return (CC_ERROR);
+ char *cp;
- if (el->el_chared.c_vcmd.ins >
- el->el_line.cursor - el->el_state.argument)
+ cp = el->el_line.cursor;
+ if (cp <= el->el_line.buffer)
return (CC_ERROR);
- c_delbefore(el, el->el_state.argument);
- el->el_line.cursor -= el->el_state.argument;
+ /* do the delete here so we dont mess up the undo and paste buffers */
+ el->el_line.cursor = --cp;
+ for (; cp < el->el_line.lastchar; cp++)
+ cp[0] = cp[1];
+ el->el_line.lastchar = cp - 1;
return (CC_REFRESH);
}
--
David Laight: david@l8s.co.uk