diff options
| -rw-r--r-- | Makefile | 75 | ||||
| -rw-r--r-- | TEST/Makefile | 13 | ||||
| -rw-r--r-- | TEST/test.c | 87 | ||||
| -rw-r--r-- | chared.c | 342 | ||||
| -rw-r--r-- | chared.h | 55 | ||||
| -rw-r--r-- | common.c | 218 | ||||
| -rw-r--r-- | config.h | 18 | ||||
| -rw-r--r-- | editline.3 | 191 | ||||
| -rw-r--r-- | editrc.5 | 44 | ||||
| -rw-r--r-- | el.c | 108 | ||||
| -rw-r--r-- | el.h | 31 | ||||
| -rw-r--r-- | emacs.c | 109 | ||||
| -rw-r--r-- | filecomplete.c | 539 | ||||
| -rw-r--r-- | filecomplete.h | 51 | ||||
| -rw-r--r-- | hist.c | 64 | ||||
| -rw-r--r-- | hist.h | 12 | ||||
| -rw-r--r-- | histedit.h | 57 | ||||
| -rw-r--r-- | history.c | 268 | ||||
| -rw-r--r-- | key.c | 53 | ||||
| -rw-r--r-- | key.h | 23 | ||||
| -rw-r--r-- | makelist | 10 | ||||
| -rw-r--r-- | map.c | 317 | ||||
| -rw-r--r-- | map.h | 10 | ||||
| -rw-r--r-- | parse.c | 41 | ||||
| -rw-r--r-- | parse.h | 10 | ||||
| -rw-r--r-- | prompt.c | 19 | ||||
| -rw-r--r-- | prompt.h | 8 | ||||
| -rw-r--r-- | read.c | 177 | ||||
| -rw-r--r-- | read.h | 4 | ||||
| -rw-r--r-- | readline.c | 1621 | ||||
| -rw-r--r-- | readline/Makefile | 14 | ||||
| -rw-r--r-- | readline/readline.h | 91 | ||||
| -rw-r--r-- | refresh.c | 54 | ||||
| -rw-r--r-- | refresh.h | 8 | ||||
| -rw-r--r-- | search.c | 199 | ||||
| -rw-r--r-- | search.h | 14 | ||||
| -rw-r--r-- | shlib_version | 4 | ||||
| -rw-r--r-- | sig.c | 19 | ||||
| -rw-r--r-- | sig.h | 11 | ||||
| -rw-r--r-- | sys.h | 54 | ||||
| -rw-r--r-- | term.c | 81 | ||||
| -rw-r--r-- | term.h | 29 | ||||
| -rw-r--r-- | tokenizer.c | 133 | ||||
| -rw-r--r-- | tokenizer.h | 54 | ||||
| -rw-r--r-- | tty.c | 160 | ||||
| -rw-r--r-- | tty.h | 16 | ||||
| -rw-r--r-- | vi.c | 822 | 
47 files changed, 4015 insertions, 2323 deletions
| @@ -1,9 +1,15 @@ -#	$NetBSD: Makefile,v 1.20 2001/01/05 21:15:49 jdolecek Exp $ +#	$NetBSD: Makefile,v 1.34 2005/05/28 12:02:53 lukem Exp $  #	@(#)Makefile	8.1 (Berkeley) 6/4/93 +USE_SHLIBDIR=	yes + +WARNS=	3  LIB=	edit -OSRCS=	chared.c common.c el.c emacs.c fcns.c help.c hist.c key.c map.c \ +LIBDPLIBS=     termcap ${.CURDIR}/../libterm + +OSRCS=	chared.c common.c el.c emacs.c fcns.c filecomplete.c help.c hist.c \ +	key.c map.c \  	parse.c prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c  MAN=	editline.3 editrc.5 @@ -13,75 +19,86 @@ MLINKS=	editline.3 el_init.3 editline.3 el_end.3 editline.3 el_reset.3 \  	editline.3 el_parse.3 editline.3 el_set.3 editline.3 el_get.3 \  	editline.3 el_source.3 editline.3 el_resize.3 editline.3 el_line.3 \  	editline.3 el_insertstr.3 editline.3 el_deletestr.3 \ -	editline.3 history_init.3 editline.3 history_end.3 editline.3 history.3 +	editline.3 history_init.3 editline.3 history_end.3 \ +	editline.3 history.3 \ +	editline.3 tok_init.3 editline.3 tok_end.3 editline.3 tok_reset.3 \ +	editline.3 tok_line.3 editline.3 tok_str.3  # For speed and debugging  #SRCS=   ${OSRCS} tokenizer.c history.c readline.c  # For protection  SRCS=	editline.c tokenizer.c history.c readline.c -SRCS+=	common.h emacs.h fcns.h help.h vi.h -  LIBEDITDIR?=${.CURDIR}  INCS= histedit.h  INCSDIR=/usr/include -CLEANFILES+=common.h editline.c emacs.h fcns.c fcns.h help.c help.h vi.h +CLEANFILES+=editline.c  CLEANFILES+=common.h.tmp editline.c.tmp emacs.h.tmp fcns.c.tmp fcns.h.tmp  CLEANFILES+=help.c.tmp help.h.tmp vi.h.tmp +CLEANFILES+=test.o test  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 +DPSRCS+=	${AHDR} fcns.h help.h fcns.c help.c +CLEANFILES+=	${AHDR} fcns.h help.h fcns.c help.c +  SUBDIR=	readline -vi.h: vi.c makelist -	sh ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/vi.c > ${.TARGET}.tmp && \ +vi.h: vi.c makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/vi.c \ +	    > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -emacs.h: emacs.c makelist -	sh ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/emacs.c > ${.TARGET}.tmp && \ +emacs.h: emacs.c makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/emacs.c \ +	    > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -common.h: common.c makelist -	sh ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/common.c > ${.TARGET}.tmp && \ +common.h: common.c makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/common.c \ +	    > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -fcns.h: ${AHDR} makelist -	sh ${LIBEDITDIR}/makelist -fh ${AHDR} > ${.TARGET}.tmp && \ +fcns.h: ${AHDR} makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -fh ${AHDR} > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -fcns.c: ${AHDR} fcns.h makelist -	sh ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \ +fcns.c: ${AHDR} fcns.h help.h makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -help.c: ${ASRC} makelist  -	sh ${LIBEDITDIR}/makelist -bc ${ASRC} > ${.TARGET}.tmp && \ +help.c: ${ASRC} makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -bc ${ASRC} > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -help.h: ${ASRC} makelist -	sh ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \ +help.h: ${ASRC} makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET} -editline.c: ${OSRCS} -	sh ${LIBEDITDIR}/makelist -e ${.ALLSRC:T} > ${.TARGET}.tmp && \ +editline.c: ${OSRCS} makelist Makefile +	${_MKTARGET_CREATE} +	${HOST_SH} ${LIBEDITDIR}/makelist -e ${OSRCS:T} > ${.TARGET}.tmp && \  	    mv ${.TARGET}.tmp ${.TARGET}  test.o:	${LIBEDITDIR}/TEST/test.c  test:	libedit.a test.o  +	${_MKTARGET_LINK}  	${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermcap -# minimal dependency to make "make depend" optional -editline.o editline.po editline.so editline.ln:	\ -	common.h emacs.h fcns.c fcns.h help.c help.h vi.h -readline.o readline.po readline.so readline.ln:	\ -	common.h emacs.h fcns.h help.h vi.h -  .include <bsd.lib.mk>  .include <bsd.subdir.mk> diff --git a/TEST/Makefile b/TEST/Makefile new file mode 100644 index 000000000000..0118710e7f7a --- /dev/null +++ b/TEST/Makefile @@ -0,0 +1,13 @@ +# $NetBSD: Makefile,v 1.2 2003/12/05 13:37:48 lukem Exp $ + +NOMAN=1 +PROG=test +CPPFLAGS=-I${.CURDIR}/.. +LDADD+=-ledit -ltermcap +DPADD+=${LIBEDIT} ${LIBTERMCAP} + +.ifdef DEBUG +CPPFLAGS+=-DDEBUG +.endif + +.include <bsd.prog.mk> diff --git a/TEST/test.c b/TEST/test.c index 267cccf21dae..f17897ff5c0e 100644 --- a/TEST/test.c +++ b/TEST/test.c @@ -1,4 +1,4 @@ -/*	$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $	*/ +/*	$NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,7 +32,7 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #ifndef lint  __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\  	The Regents of the University of California.  All rights reserved.\n"); @@ -46,14 +42,13 @@ __COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\  #if 0  static char sccsid[] = "@(#)test.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $"); +__RCSID("$NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * test.c: A little test program   */ -#include "sys.h"  #include <stdio.h>  #include <string.h>  #include <signal.h> @@ -64,12 +59,11 @@ __RCSID("$NetBSD: test.c,v 1.9 2000/09/04 23:36:41 lukem Exp $");  #include <dirent.h>  #include "histedit.h" -#include "tokenizer.h"  static int continuation = 0; -static EditLine *el = NULL; +volatile sig_atomic_t gotsig = 0; -static	u_char	complete(EditLine *, int); +static	unsigned char	complete(EditLine *, int);  	int	main(int, char **);  static	char   *prompt(EditLine *);  static	void	sig(int); @@ -77,8 +71,8 @@ static	void	sig(int);  static char *  prompt(EditLine *el)  { -	static char a[] = "Edit$"; -	static char b[] = "Edit>"; +	static char a[] = "Edit$ "; +	static char b[] = "Edit> ";  	return (continuation ? b : a);  } @@ -86,9 +80,7 @@ prompt(EditLine *el)  static void  sig(int i)  { - -	(void) fprintf(stderr, "Got signal %d.\n", i); -	el_reset(el); +	gotsig = i;  }  static unsigned char @@ -103,7 +95,8 @@ complete(EditLine *el, int ch)  	/*  	 * Find the last word  	 */ -	for (ptr = lf->cursor - 1; !isspace(*ptr) && ptr > lf->buffer; ptr--) +	for (ptr = lf->cursor - 1; +	    !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--)  		continue;  	len = lf->cursor - ++ptr; @@ -126,10 +119,14 @@ complete(EditLine *el, int ch)  int  main(int argc, char *argv[])  { +	EditLine *el = NULL;  	int num;  	const char *buf;  	Tokenizer *tok; -	int lastevent = 0, ncontinuation; +#if 0 +	int lastevent = 0; +#endif +	int ncontinuation;  	History *hist;  	HistEvent ev; @@ -173,17 +170,41 @@ main(int argc, char *argv[])  	el_source(el, NULL);  	while ((buf = el_gets(el, &num)) != NULL && num != 0)  { -		int ac; -		char **av; +		int ac, cc, co;  #ifdef DEBUG -		(void) fprintf(stderr, "got %d %s", num, buf); +		int i;  #endif +		const char **av; +		const LineInfo *li; +		li = el_line(el); +#ifdef DEBUG +		(void) fprintf(stderr, "==> got %d %s", num, buf); +		(void) fprintf(stderr, "  > li `%.*s_%.*s'\n", +		    (li->cursor - li->buffer), li->buffer, +		    (li->lastchar - 1 - li->cursor), +		    (li->cursor >= li->lastchar) ? "" : li->cursor); + +#endif +		if (gotsig) { +			(void) fprintf(stderr, "Got signal %d.\n", gotsig); +			gotsig = 0; +			el_reset(el); +		} +  		if (!continuation && num == 1)  			continue; -		if (tok_line(tok, buf, &ac, &av) > 0) -			ncontinuation = 1; - +		ac = cc = co = 0; +		ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); +		if (ncontinuation < 0) { +			(void) fprintf(stderr, "Internal error\n"); +			continuation = 0; +			continue; +		} +#ifdef DEBUG +		(void) fprintf(stderr, "  > nc %d ac %d cc %d co %d\n", +		    ncontinuation, ac, cc, co); +#endif  #if 0  		if (continuation) {  			/* @@ -191,7 +212,7 @@ main(int argc, char *argv[])  			 * moved around in history.  			 */  			if (history(hist, &ev, H_SET, lastevent) == -1) -				err(1, "%d: %s\n", lastevent, ev.str); +				err(1, "%d: %s", lastevent, ev.str);  			history(hist, &ev, H_ADD , buf);  		} else {  			history(hist, &ev, H_ENTER, buf); @@ -204,6 +225,18 @@ main(int argc, char *argv[])  		continuation = ncontinuation;  		ncontinuation = 0; +		if (continuation) +			continue; +#ifdef DEBUG +		for (i = 0; i < ac; i++) { +			(void) fprintf(stderr, "  > arg# %2d ", i); +			if (i != cc) +				(void) fprintf(stderr, "`%s'\n", av[i]); +			else +				(void) fprintf(stderr, "`%.*s_%s'\n", +				    co, av[i], av[i] + co); +		} +#endif  		if (strcmp(av[0], "history") == 0) {  			int rv; @@ -239,7 +272,7 @@ main(int argc, char *argv[])  		} else if (el_parse(el, ac, av) == -1) {  			switch (fork()) {  			case 0: -				execvp(av[0], av); +				execvp(av[0], (char *const *)__UNCONST(av));  				perror(av[0]);  				_exit(1);  				/*NOTREACHED*/ @@ -1,4 +1,4 @@ -/*	$NetBSD: chared.c,v 1.14 2001/05/17 01:02:17 christos Exp $	*/ +/*	$NetBSD: chared.c,v 1.24 2005/08/01 23:00:15 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,23 +32,23 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)chared.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: chared.c,v 1.14 2001/05/17 01:02:17 christos Exp $"); +__RCSID("$NetBSD: chared.c,v 1.24 2005/08/01 23:00:15 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * chared.c: Character editor utilities   */ -#include "sys.h" -  #include <stdlib.h>  #include "el.h" +private void ch__clearmacro __P((EditLine *)); +  /* value to leave unused in line buffer */  #define	EL_LEAVE	2 @@ -60,17 +56,36 @@ __RCSID("$NetBSD: chared.c,v 1.14 2001/05/17 01:02:17 christos Exp $");   *	Handle state for the vi undo command   */  protected void -cv_undo(EditLine *el,int action, size_t size, char *ptr) +cv_undo(EditLine *el)  {  	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 +	c_redo_t *r = &el->el_chared.c_redo; +	unsigned int size; + +	/* Save entire line for undo */ +	size = el->el_line.lastchar - el->el_line.buffer; +	vu->len = size; +	vu->cursor = el->el_line.cursor - el->el_line.buffer; +	memcpy(vu->buf, el->el_line.buffer, size); + +	/* save command info for redo */ +	r->count = el->el_state.doingarg ? el->el_state.argument : 0; +	r->action = el->el_chared.c_vcmd.action; +	r->pos = r->buf; +	r->cmd = el->el_state.thiscmd; +	r->ch = el->el_state.thisch; +} + +/* cv_yank(): + *	Save yank/delete data for paste + */ +protected void +cv_yank(EditLine *el, const char *ptr, int size) +{ +	c_kill_t *k = &el->el_chared.c_kill; + +	memcpy(k->buf, ptr, size +0u); +	k->last = k->buf + size;  } @@ -82,8 +97,10 @@ c_insert(EditLine *el, int num)  {  	char *cp; -	if (el->el_line.lastchar + num >= el->el_line.limit) -		return;			/* can't go past end of buffer */ +	if (el->el_line.lastchar + num >= el->el_line.limit) { +		if (!ch_enlargebufs(el, num +0u)) +			return;		/* can't go past end of buffer */ +	}  	if (el->el_line.cursor < el->el_line.lastchar) {  		/* if I must move chars */ @@ -104,12 +121,14 @@ c_delafter(EditLine *el, int num)  	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); +		cv_yank(el, 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); -  		for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)  			*cp = cp[num]; @@ -118,6 +137,21 @@ c_delafter(EditLine *el, int num)  } +/* c_delafter1(): + *	Delete the character after the cursor, do not yank + */ +protected void +c_delafter1(EditLine *el) +{ +	char *cp; + +	for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) +		*cp = cp[1]; + +	el->el_line.lastchar--; +} + +  /* c_delbefore():   *	Delete num characters before the cursor   */ @@ -128,13 +162,14 @@ c_delbefore(EditLine *el, int num)  	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); +		cv_yank(el, el->el_line.cursor - num, 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++) @@ -145,13 +180,28 @@ c_delbefore(EditLine *el, int num)  } +/* c_delbefore1(): + *	Delete the character before the cursor, do not yank + */ +protected void +c_delbefore1(EditLine *el) +{ +	char *cp; + +	for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) +		*cp = cp[1]; + +	el->el_line.lastchar--; +} + +  /* ce__isword():   *	Return if p is part of a word according to emacs   */  protected int  ce__isword(int p)  { -	return (isalpha(p) || isdigit(p) || strchr("*?_-.[]~=", p) != NULL); +	return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL);  } @@ -161,6 +211,20 @@ ce__isword(int p)  protected int  cv__isword(int p)  { +	if (isalnum(p) || p == '_') +		return 1; +	if (isgraph(p)) +		return 2; +	return 0; +} + + +/* cv__isWord(): + *	Return if p is part of a big word according to vi + */ +protected int +cv__isWord(int p) +{  	return (!isspace(p));  } @@ -223,7 +287,7 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))  		 * 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++;  	} @@ -240,26 +304,19 @@ cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int))   *	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) @@ -310,47 +367,34 @@ protected void  cv_delfini(EditLine *el)  {  	int size; -	int oaction; +	int action = el->el_chared.c_vcmd.action; -	if (el->el_chared.c_vcmd.action & INSERT) +	if (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) +		/* sanity */  		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); -		c_delafter(el, size); -	} else { +	size = el->el_line.cursor - el->el_chared.c_vcmd.pos; +	if (size == 0)  		size = 1; -		c_delafter(el, size); -	} -	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_line.cursor = el->el_chared.c_vcmd.pos; +	if (action & YANK) { +		if (size > 0) +			cv_yank(el, el->el_line.cursor, size); +		else +			cv_yank(el, el->el_line.cursor + size, -size); +	} else { +		if (size > 0) { +			c_delafter(el, size); +			re_refresh_cursor(el); +		} else  { +			c_delbefore(el, -size); +			el->el_line.cursor += size; +		}  	} - - -	el->el_chared.c_undo.ptr = el->el_line.cursor; -	el->el_chared.c_undo.dsize = size; +	el->el_chared.c_vcmd.action = NOP;  } @@ -380,21 +424,19 @@ ce__endword(char *p, char *high, int n)   *	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); @@ -406,6 +448,8 @@ cv__endword(char *p, char *high, int n)  protected int  ch_init(EditLine *el)  { +	c_macro_t *ma = &el->el_chared.c_macro; +  	el->el_line.buffer		= (char *) el_malloc(EL_BUFSIZ);  	if (el->el_line.buffer == NULL)  		return (-1); @@ -413,20 +457,23 @@ ch_init(EditLine *el)  	(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_redo.buf	= (char *) el_malloc(EL_BUFSIZ); +	if (el->el_chared.c_redo.buf == NULL) +		return (-1); +	el->el_chared.c_redo.pos	= el->el_chared.c_redo.buf; +	el->el_chared.c_redo.lim	= el->el_chared.c_redo.buf + EL_BUFSIZ; +	el->el_chared.c_redo.cmd	= ED_UNASSIGNED;  	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) @@ -443,11 +490,10 @@ ch_init(EditLine *el)  	el->el_state.argument		= 1;  	el->el_state.lastcmd		= ED_UNASSIGNED; -	el->el_chared.c_macro.nline	= NULL; -	el->el_chared.c_macro.level	= -1; -	el->el_chared.c_macro.macro	= (char **) el_malloc(EL_MAXMACRO * -	    sizeof(char *)); -	if (el->el_chared.c_macro.macro == NULL) +	ma->level	= -1; +	ma->offset	= 0; +	ma->macro	= (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); +	if (ma->macro == NULL)  		return (-1);  	return (0);  } @@ -456,19 +502,16 @@ ch_init(EditLine *el)   *	Reset the character editor   */  protected void -ch_reset(EditLine *el) +ch_reset(EditLine *el, int mclear)  {  	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; @@ -480,9 +523,17 @@ ch_reset(EditLine *el)  	el->el_state.argument		= 1;  	el->el_state.lastcmd		= ED_UNASSIGNED; -	el->el_chared.c_macro.level	= -1; +	if (mclear) +		ch__clearmacro(el); +} -	el->el_history.eventno		= 0; +private void +ch__clearmacro(el) +	EditLine *el; +{ +	c_macro_t *ma = &el->el_chared.c_macro; +	while (ma->level >= 0) +		el_free((ptr_t)ma->macro[ma->level--]);  }  /* ch_enlargebufs(): @@ -523,7 +574,8 @@ ch_enlargebufs(el, addlen)  	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. @@ -552,14 +604,22 @@ ch_enlargebufs(el, addlen)  	/* 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_redo.buf, newsz); +	if (!newbuffer) +		return 0; +	el->el_chared.c_redo.pos = newbuffer + +			(el->el_chared.c_redo.pos - el->el_chared.c_redo.buf); +	el->el_chared.c_redo.lim = newbuffer + +			(el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); +	el->el_chared.c_redo.buf = newbuffer;  	if (!hist_enlargebuf(el, sz, newsz))  		return 0; +	/* Safe to set enlarged buffer size */ +	el->el_line.limit  = &el->el_line.buffer[newsz - EL_LEAVE];  	return 1;  } @@ -574,11 +634,16 @@ ch_end(EditLine *el)  	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_redo.buf); +	el->el_chared.c_redo.buf = NULL; +	el->el_chared.c_redo.pos = NULL; +	el->el_chared.c_redo.lim = NULL; +	el->el_chared.c_redo.cmd = ED_UNASSIGNED;  	el_free((ptr_t) el->el_chared.c_kill.buf);  	el->el_chared.c_kill.buf = NULL; +	ch_reset(el, 1);  	el_free((ptr_t) el->el_chared.c_macro.macro);  	el->el_chared.c_macro.macro = NULL; -	ch_reset(el);  } @@ -626,51 +691,64 @@ el_deletestr(EditLine *el, int n)   *	Get a string   */  protected int -c_gets(EditLine *el, char *buf) +c_gets(EditLine *el, char *buf, const char *prompt)  {  	char ch; -	int len = 0; +	int len; +	char *cp = el->el_line.buffer; + +	if (prompt) { +		len = strlen(prompt); +		memcpy(cp, prompt, len + 0u); +		cp += len; +	} +	len = 0; + +	for (;;) { +		el->el_line.cursor = cp; +		*cp = ' '; +		el->el_line.lastchar = cp + 1; +		re_refresh(el); + +		if (el_getc(el, &ch) != 1) { +			ed_end_of_file(el, 0); +			len = -1; +			break; +		} -	for (ch = 0; ch == 0;) { -		if (el_getc(el, &ch) != 1) -			return (ed_end_of_file(el, 0));  		switch (ch) { +  		case 0010:	/* Delete and backspace */  		case 0177: -			if (len > 1) { -				*el->el_line.cursor-- = '\0'; -				el->el_line.lastchar = el->el_line.cursor; -				buf[len--] = '\0'; -			} else { -				el->el_line.buffer[0] = '\0'; -				el->el_line.lastchar = el->el_line.buffer; -				el->el_line.cursor = el->el_line.buffer; -				return (CC_REFRESH); +			if (len <= 0) { +				len = -1; +				break;  			} -			re_refresh(el); -			ch = 0; -			break; +			cp--; +			continue;  		case 0033:	/* ESC */  		case '\r':	/* Newline */  		case '\n': +			buf[len] = ch;  			break;  		default: -			if (len >= EL_BUFSIZ) +			if (len >= EL_BUFSIZ - 16)  				term_beep(el);  			else {  				buf[len++] = ch; -				*el->el_line.cursor++ = ch; -				el->el_line.lastchar = el->el_line.cursor; +				*cp++ = ch;  			} -			re_refresh(el); -			ch = 0; -			break; +			continue;  		} +		break;  	} -	buf[len] = ch; -	return (len); + +	el->el_line.buffer[0] = '\0'; +	el->el_line.lastchar = el->el_line.buffer; +	el->el_line.cursor = el->el_line.buffer; +	return len;  } @@ -1,4 +1,4 @@ -/*	$NetBSD: chared.h,v 1.6 2001/01/10 07:45:41 jdolecek Exp $	*/ +/*	$NetBSD: chared.h,v 1.15 2005/08/01 23:00:15 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -66,28 +62,36 @@  typedef struct c_macro_t {  	int	  level; +	int	  offset;  	char	**macro; -	char	 *nline;  } 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 */  } c_undo_t; +/* redo for vi */ +typedef struct c_redo_t { +	char	*buf;			/* redo insert key sequence */ +	char	*pos; +	char	*lim; +	el_action_t	cmd;		/* command to redo */ +	char	ch;			/* char that invoked it */ +	int	count; +	int	action;			/* from cv_action() */ +} c_redo_t; +  /*   * Current action information for vi   */  typedef struct c_vcmd_t {  	int	 action;  	char	*pos; -	char	*ins;  } c_vcmd_t;  /* @@ -106,6 +110,7 @@ typedef struct c_kill_t {  typedef struct el_chared_t {  	c_undo_t	c_undo;  	c_kill_t	c_kill; +	c_redo_t	c_redo;  	c_vcmd_t	c_vcmd;  	c_macro_t	c_macro;  } el_chared_t; @@ -120,10 +125,10 @@ typedef struct el_chared_t {  #define	NOP		0x00  #define	DELETE		0x01  #define	INSERT		0x02 -#define	CHANGE		0x04 +#define	YANK		0x04 -#define	CHAR_FWD	0 -#define	CHAR_BACK	1 +#define	CHAR_FWD	(+1) +#define	CHAR_BACK	(-1)  #define	MODE_INSERT	0  #define	MODE_REPLACE	1 @@ -137,23 +142,27 @@ typedef struct el_chared_t {  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 *); +protected void	 cv_yank(EditLine *, const char *, int);  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);  protected void	 c_delbefore(EditLine *, int); +protected void	 c_delbefore1(EditLine *);  protected void	 c_delafter(EditLine *, int); -protected int	 c_gets(EditLine *, char *); +protected void	 c_delafter1(EditLine *); +protected int	 c_gets(EditLine *, char *, const char *);  protected int	 c_hpos(EditLine *);  protected int	 ch_init(EditLine *); -protected void	 ch_reset(EditLine *); -protected int	 ch_enlargebufs	__P((EditLine *, size_t)); +protected void	 ch_reset(EditLine *, int); +protected int	 ch_enlargebufs(EditLine *, size_t);  protected void	 ch_end(EditLine *);  #endif /* _h_el_chared */ @@ -1,4 +1,4 @@ -/*	$NetBSD: common.c,v 1.10 2001/01/10 07:45:41 jdolecek Exp $	*/ +/*	$NetBSD: common.c,v 1.17 2005/08/01 23:00:15 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)common.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: common.c,v 1.10 2001/01/10 07:45:41 jdolecek Exp $"); +__RCSID("$NetBSD: common.c,v 1.17 2005/08/01 23:00:15 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * common.c: Common Editor functions   */ -#include "sys.h"  #include "el.h"  /* ed_end_of_file(): @@ -57,7 +52,7 @@ __RCSID("$NetBSD: common.c,v 1.10 2001/01/10 07:45:41 jdolecek Exp $");   */  protected el_action_t  /*ARGSUSED*/ -ed_end_of_file(EditLine *el, int c) +ed_end_of_file(EditLine *el, int c __attribute__((__unused__)))  {  	re_goto_bottom(el); @@ -73,7 +68,7 @@ ed_end_of_file(EditLine *el, int c)  protected el_action_t  ed_insert(EditLine *el, int c)  { -	int i; +	int count = el->el_state.argument;  	if (c == '\0')  		return (CC_ERROR); @@ -81,42 +76,28 @@ ed_insert(EditLine *el, int c)  	if (el->el_line.lastchar + el->el_state.argument >=  	    el->el_line.limit) {  		/* end of buffer space, try to allocate more */ -		if (!ch_enlargebufs(el, (size_t) el->el_state.argument)) +		if (!ch_enlargebufs(el, (size_t) count))  			return CC_ERROR;	/* error allocating more */  	} -	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 (count == 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--) +		while (count-- && el->el_line.cursor < el->el_line.lastchar)  			*el->el_line.cursor++ = c;  		re_refresh(el);  	}  	if (el->el_state.inputmode == MODE_REPLACE_1) -		(void) vi_command_mode(el, 0); +		return vi_command_mode(el, 0);  	return (CC_NORM);  } @@ -128,7 +109,7 @@ ed_insert(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_delete_prev_word(EditLine *el, int c) +ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *p, *kp; @@ -156,7 +137,7 @@ ed_delete_prev_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_delete_next_char(EditLine *el, int c) +ed_delete_next_char(EditLine *el, int c __attribute__((__unused__)))  {  #ifdef notdef			/* XXX */  #define	EL	el->el_line @@ -207,7 +188,7 @@ ed_delete_next_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_kill_line(EditLine *el, int c) +ed_kill_line(EditLine *el, int c __attribute__((__unused__)))  {  	char *kp, *cp; @@ -228,7 +209,7 @@ ed_kill_line(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_move_to_end(EditLine *el, int c) +ed_move_to_end(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_line.cursor = el->el_line.lastchar; @@ -236,7 +217,7 @@ ed_move_to_end(EditLine *el, int c)  #ifdef VI_MOVE  		el->el_line.cursor--;  #endif -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -251,7 +232,7 @@ ed_move_to_end(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_move_to_beg(EditLine *el, int c) +ed_move_to_beg(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_line.cursor = el->el_line.buffer; @@ -260,7 +241,7 @@ ed_move_to_beg(EditLine *el, int c)  			/* We want FIRST non space character */  		while (isspace((unsigned char) *el->el_line.cursor))  			el->el_line.cursor++; -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -300,18 +281,22 @@ ed_transpose_chars(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_next_char(EditLine *el, int c) +ed_next_char(EditLine *el, int c __attribute__((__unused__)))  { +	char *lim = el->el_line.lastchar; -	if (el->el_line.cursor >= el->el_line.lastchar) +	if (el->el_line.cursor >= lim || +	    (el->el_line.cursor == lim - 1 && +	    el->el_map.type == MAP_VI && +	    el->el_chared.c_vcmd.action == NOP))  		return (CC_ERROR);  	el->el_line.cursor += el->el_state.argument; -	if (el->el_line.cursor > el->el_line.lastchar) -		el->el_line.cursor = el->el_line.lastchar; +	if (el->el_line.cursor > lim) +		el->el_line.cursor = lim;  	if (el->el_map.type == MAP_VI) -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -325,7 +310,7 @@ ed_next_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_prev_word(EditLine *el, int c) +ed_prev_word(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_line.cursor == el->el_line.buffer) @@ -337,7 +322,7 @@ ed_prev_word(EditLine *el, int c)  	    ce__isword);  	if (el->el_map.type == MAP_VI) -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -351,7 +336,7 @@ ed_prev_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_prev_char(EditLine *el, int c) +ed_prev_char(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_line.cursor > el->el_line.buffer) { @@ -360,7 +345,7 @@ ed_prev_char(EditLine *el, int c)  			el->el_line.cursor = el->el_line.buffer;  		if (el->el_map.type == MAP_VI) -			if (el->el_chared.c_vcmd.action & DELETE) { +			if (el->el_chared.c_vcmd.action != NOP) {  				cv_delfini(el);  				return (CC_REFRESH);  			} @@ -412,25 +397,9 @@ ed_digit(EditLine *el, int c)  			    (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);  } @@ -464,12 +433,10 @@ ed_argument_digit(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_unassigned(EditLine *el, int c) +ed_unassigned(EditLine *el, int c __attribute__((__unused__)))  { -	term_beep(el); -	term__flush(); -	return (CC_NORM); +	return (CC_ERROR);  } @@ -483,7 +450,8 @@ ed_unassigned(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_sigint(EditLine *el, int c) +ed_tty_sigint(EditLine *el __attribute__((__unused__)),  +	      int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -496,7 +464,8 @@ ed_tty_sigint(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_dsusp(EditLine *el, int c) +ed_tty_dsusp(EditLine *el __attribute__((__unused__)),  +	     int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -509,7 +478,8 @@ ed_tty_dsusp(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_flush_output(EditLine *el, int c) +ed_tty_flush_output(EditLine *el __attribute__((__unused__)),  +		    int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -522,7 +492,8 @@ ed_tty_flush_output(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_sigquit(EditLine *el, int c) +ed_tty_sigquit(EditLine *el __attribute__((__unused__)),  +	       int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -535,7 +506,8 @@ ed_tty_sigquit(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_sigtstp(EditLine *el, int c) +ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),  +	       int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -548,7 +520,8 @@ ed_tty_sigtstp(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_stop_output(EditLine *el, int c) +ed_tty_stop_output(EditLine *el __attribute__((__unused__)),  +		   int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -561,7 +534,8 @@ ed_tty_stop_output(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_tty_start_output(EditLine *el, int c) +ed_tty_start_output(EditLine *el __attribute__((__unused__)),  +		    int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -574,14 +548,12 @@ ed_tty_start_output(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_newline(EditLine *el, int c) +ed_newline(EditLine *el, int c __attribute__((__unused__)))  {  	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);  } @@ -592,7 +564,7 @@ ed_newline(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_delete_prev_char(EditLine *el, int c) +ed_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_line.cursor <= el->el_line.buffer) @@ -612,7 +584,7 @@ ed_delete_prev_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_clear_screen(EditLine *el, int c) +ed_clear_screen(EditLine *el, int c __attribute__((__unused__)))  {  	term_clear_screen(el);	/* clear the whole real screen */ @@ -627,7 +599,8 @@ ed_clear_screen(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_redisplay(EditLine *el, int c) +ed_redisplay(EditLine *el __attribute__((__unused__)),  +	     int c __attribute__((__unused__)))  {  	return (CC_REDISPLAY); @@ -640,10 +613,10 @@ ed_redisplay(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_start_over(EditLine *el, int c) +ed_start_over(EditLine *el, int c __attribute__((__unused__)))  { -	ch_reset(el); +	ch_reset(el, 0);  	return (CC_REFRESH);  } @@ -654,7 +627,8 @@ ed_start_over(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_sequence_lead_in(EditLine *el, int c) +ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),  +		    int c __attribute__((__unused__)))  {  	return (CC_NORM); @@ -667,11 +641,12 @@ ed_sequence_lead_in(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_prev_history(EditLine *el, int c) +ed_prev_history(EditLine *el, int c __attribute__((__unused__)))  {  	char beep = 0; +	int sv_event = el->el_history.eventno; -	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 @@ -684,15 +659,17 @@ ed_prev_history(EditLine *el, int c)  	el->el_history.eventno += el->el_state.argument;  	if (hist_get(el) == CC_ERROR) { +		if (el->el_map.type == MAP_VI) { +			el->el_history.eventno = sv_event; +			return CC_ERROR; +		}  		beep = 1;  		/* el->el_history.eventno was fixed by first call */  		(void) hist_get(el);  	} -	re_refresh(el);  	if (beep) -		return (CC_ERROR); -	else -		return (CC_NORM);	/* was CC_UP_HIST */ +		return CC_REFRESH_BEEP; +	return CC_REFRESH;  } @@ -702,19 +679,24 @@ ed_prev_history(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_next_history(EditLine *el, int c) +ed_next_history(EditLine *el, int c __attribute__((__unused__)))  { +	el_action_t beep = CC_REFRESH, rval; -	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;  	if (el->el_history.eventno < 0) {  		el->el_history.eventno = 0; -		return (CC_ERROR);/* make it beep */ +		beep = CC_REFRESH_BEEP;  	} -	return (hist_get(el)); +	rval = hist_get(el); +	if (rval == CC_REFRESH) +		return beep; +	return rval; +  } @@ -724,14 +706,14 @@ ed_next_history(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_search_prev_history(EditLine *el, int c) +ed_search_prev_history(EditLine *el, int c __attribute__((__unused__)))  {  	const char *hp;  	int h;  	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 @@ -792,14 +774,14 @@ ed_search_prev_history(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_search_next_history(EditLine *el, int c) +ed_search_next_history(EditLine *el, int c __attribute__((__unused__)))  {  	const char *hp;  	int h;  	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) @@ -846,7 +828,7 @@ ed_search_next_history(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_prev_line(EditLine *el, int c) +ed_prev_line(EditLine *el, int c __attribute__((__unused__)))  {  	char *ptr;  	int nchars = c_hpos(el); @@ -889,7 +871,7 @@ ed_prev_line(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_next_line(EditLine *el, int c) +ed_next_line(EditLine *el, int c __attribute__((__unused__)))  {  	char *ptr;  	int nchars = c_hpos(el); @@ -923,30 +905,18 @@ ed_next_line(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -ed_command(EditLine *el, int c) +ed_command(EditLine *el, int c __attribute__((__unused__)))  {  	char tmpbuf[EL_BUFSIZ];  	int tmplen; -	el->el_line.buffer[0] = '\0'; -	el->el_line.lastchar = el->el_line.buffer; -	el->el_line.cursor = el->el_line.buffer; - -	c_insert(el, 3);	/* prompt + ": " */ -	*el->el_line.cursor++ = '\n'; -	*el->el_line.cursor++ = ':'; -	*el->el_line.cursor++ = ' '; -	re_refresh(el); - -	tmplen = c_gets(el, tmpbuf); -	tmpbuf[tmplen] = '\0'; +	tmplen = c_gets(el, tmpbuf, "\n: "); +	term__putc('\n'); -	el->el_line.buffer[0] = '\0'; -	el->el_line.lastchar = el->el_line.buffer; -	el->el_line.cursor = el->el_line.buffer; +	if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) +		term_beep(el); -	if (parse_line(el, tmpbuf) == -1) -		return (CC_ERROR); -	else -		return (CC_REFRESH); +	el->el_map.current = el->el_map.key; +	re_clear_display(el); +	return CC_REFRESH;  } diff --git a/config.h b/config.h new file mode 100644 index 000000000000..e2fc0cad9b7f --- /dev/null +++ b/config.h @@ -0,0 +1,18 @@ +/* config.h.  Generated automatically by configure.  */ +/* #undef SUNOS */ + +#define HAVE_SYS_CDEFS_H 1 +#define HAVE_TERMCAP_H 1 +/* #undef HAVE_CURSES_H */ +/* #undef HAVE_NCURSES_H */ +/* #undef HAVE_TERM_H */ +#define HAVE_VIS_H 1 +#define HAVE_ISSETUGID 1 + +#define HAVE_STRLCAT 1 +#define HAVE_STRLCPY 1 +#define HAVE_FGETLN 1 +#define HAVE_STRVIS 1 +#define HAVE_STRUNVIS 1 + +#include "sys.h" diff --git a/editline.3 b/editline.3 index f74849114f58..3d4ccb1068ab 100644 --- a/editline.3 +++ b/editline.3 @@ -1,6 +1,6 @@ -.\"	$NetBSD: editline.3,v 1.22 2001/09/27 19:29:50 christos Exp $ +.\"	$NetBSD: editline.3,v 1.48 2005/07/14 15:02:37 wiz Exp $  .\" -.\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc. +.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.  .\" All rights reserved.  .\"  .\" This file was contributed to The NetBSD Foundation by Luke Mewburn. @@ -33,7 +33,7 @@  .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  .\" POSSIBILITY OF SUCH DAMAGE.  .\" -.Dd November 12, 1999 +.Dd July 14, 2005  .Os  .Dt EDITLINE 3  .Sh NAME @@ -53,12 +53,17 @@  .Nm el_deletestr ,  .Nm history_init ,  .Nm history_end , -.Nm history -.Nd line editor and history functions +.Nm history , +.Nm tok_init , +.Nm tok_end , +.Nm tok_reset , +.Nm tok_line , +.Nm tok_str +.Nd line editor, history and tokenization functions  .Sh LIBRARY  .Lb libedit  .Sh SYNOPSIS -.Fd #include <histedit.h> +.In histedit.h  .Ft EditLine *  .Fn el_init "const char *prog" "FILE *fin" "FILE *fout" "FILE *ferr"  .Ft void @@ -72,7 +77,7 @@  .Ft void  .Fn el_push "EditLine *e" "const char *str"  .Ft int -.Fn el_parse "EditLine *e" "int argc" "char *argv[]" +.Fn el_parse "EditLine *e" "int argc" "const char *argv[]"  .Ft int  .Fn el_set "EditLine *e" "int op" "..."  .Ft int @@ -93,10 +98,20 @@  .Fn history_end "History *h"  .Ft int  .Fn history "History *h" "HistEvent *ev" "int op" "..." +.Ft Tokenizer * +.Fn tok_init "const char *IFS" +.Ft void +.Fn tok_end "Tokenizer *t" +.Ft void +.Fn tok_reset "Tokenizer *t" +.Ft int +.Fn tok_line "Tokenizer *t" "const LineInfo *li" "int *argc" "const char **argv[]" "int *cursorc" "int *cursoro" +.Ft int +.Fn tok_str "Tokenizer *t" "const char *str" "int *argc" "const char **argv[]"  .Sh DESCRIPTION  The  .Nm -library provides generic line editing and history functions, +library provides generic line editing, history and tokenization functions,  similar to those found in  .Xr sh 1 .  .Pp @@ -152,7 +167,7 @@ if no characters were read or if an error occurred.  Read a character from the tty.  .Fa ch  is modified to contain the character read. -Returns the number of characters read if successful, -1 otherwise. +Returns the number of characters read if successful, \-1 otherwise.  .It Fn el_push  Pushes  .Fa str @@ -174,7 +189,7 @@ to execute builtin  .Nm  commands.  If the command is prefixed with -.Dq prog: +.Dq prog :  then  .Fn el_parse  will only execute the command if @@ -184,7 +199,7 @@ matches the  argument supplied to  .Fn el_init .  The return value is --1 if the command is unknown, +\-1 if the command is unknown,  0 if there was no error or  .Dq prog  didn't match, or @@ -303,7 +318,7 @@ for more information.  .It Dv EL_ADDFN , Xo  .Fa "const char *name" ,  .Fa "const char *help" , -.Fa "unsigned char (*func)(EditLine *e, int ch) +.Fa "unsigned char (*func)(EditLine *e, int ch)"  .Xc  Add a user defined function,  .Fn func , @@ -336,7 +351,7 @@ Refresh display.  Refresh display, and beep.  .It Dv CC_CURSOR  Cursor moved, so update and perform -.Dv CC_REFRESH. +.Dv CC_REFRESH .  .It Dv CC_REDISPLAY  Redisplay entire input line.  This is useful if a key binding outputs extra information. @@ -362,7 +377,7 @@ is non-zero,  editing is enabled (the default).  Note that this is only an indication, and does not  affect the operation of -.Nm "" . +.Nm .  At this time, it is the caller's responsibility to  check this  (using @@ -379,6 +394,13 @@ and  .Fn el_getc .  The builtin function can be set or restored with the special function  name ``EL_BUILTIN_GETCFN''. +.It Dv EL_CLIENTDATA , Fa "void *data" +Register +.Fa data +to be associated with this EditLine structure. +It can be retrieved with the corresponding +.Fn el_get +call.  .El  .It Fn el_get  Get @@ -387,6 +409,7 @@ parameters.  .Fa op  determines which parameter to retrieve into  .Fa result . +Returns 0 if successful, \-1 otherwise.  .Pp  The following values for  .Fa op @@ -413,6 +436,19 @@ Return non-zero if editing is enabled.  .It Dv EL_GETCFN, Fa "int (**f)(EditLine *, char *)"  Return a pointer to the function that read characters, which is equal to  ``EL_BUILTIN_GETCFN'' in the case of the default builtin function. +.It Dv EL_CLIENTDATA , Fa "void **data" +Retrieve +.Fa data +previously registered with the corresponding +.Fn el_set +call. +.It Dv EL_UNBUFFERED, Fa "int" +Sets or clears unbuffered mode. +In this mode, +.Fn el_gets +will return immediately after processing a single character. +.It Dv EL_PREP_TERM, Fa "int" +Sets or clears terminal editing mode.  .El  .It Fn el_source  Initialise @@ -455,11 +491,21 @@ typedef struct lineinfo {      const char *lastchar;  /* address of last character */  } LineInfo;  .Ed +.Pp +.Fa buffer +is not NUL terminated. +This function may be called after +.Fn el_gets +to obtain the +.Fa LineInfo +structure pertaining to line returned by that function, +and from within user defined functions added with +.Dv EL_ADDFN .  .It Fn el_insertstr  Insert  .Fa str  into the line at the cursor. -Returns -1 if +Returns \-1 if  .Fa str  is empty or won't fit, and 0 otherwise.  .It Fn el_deletestr @@ -539,7 +585,11 @@ Set the cursor to point to the requested element.  .It Dv H_ADD , Fa "const char *str"  Append  .Fa str -to the current element of the history, or create an element with +to the current element of the history, or perform the +.Dv H_ENTER +operation with argument +.Fa str +if there is no current element.  .It Dv H_APPEND , Fa "const char *str"  Append  .Fa str @@ -549,6 +599,17 @@ Add  .Fa str  as a new element to the history, and, if necessary,  removing the oldest entry to keep the list to the created size. +If +.Dv H_SETUNIQUE +was has been called with a non-zero arguments, the element +will not be entered into the history if its contents match +the ones of the current history element. +If the element is entered +.Fn history +returns 1, if it is ignored as a duplicate returns 0. +Finally +.Fn history +returns \-1 if an error occurred.  .It Dv H_PREV_STR , Fa "const char *str"  Return the closest previous event that starts with  .Fa str . @@ -567,22 +628,109 @@ Load the history list stored in  .It Dv H_SAVE , Fa "const char *file"  Save the history list to  .Fa file . +.It Dv H_SETUNIQUE , Fa "int unique" +Set if the adjacent identical event strings should not be entered into +the history. +.It Dv H_GETUNIQUE +Retrieve the current setting if if adjacent elements should be entered into +the history. +.It Dv H_DEL , Fa "int num" +Delete the event numbered +.Fa e . +This function is only provided for +.Xr readline 3 +compatibility. +The caller is responsible for free'ing the string in the returned +.Fa HistEvent .  .El  .Pp  .Fn history -returns 0 if the operation +returns \*[Gt]= 0 if the operation  .Fa op -succeeds. Otherwise, -1 is returned and +succeeds. +Otherwise, \-1 is returned and  .Fa ev  is updated to contain more details about the error.  .El +.Sh TOKENIZATION FUNCTIONS +The tokenization functions use a common data structure, +.Fa Tokenizer , +which is created by +.Fn tok_init +and freed by +.Fn tok_end . +.Pp +The following functions are available: +.Bl -tag -width 4n +.It Fn tok_init +Initialise the tokenizer, and return a data structure +to be used by all other tokenizer functions. +.Fa IFS +contains the Input Field Separators, which defaults to +.Aq space , +.Aq tab , +and +.Aq newline +if +.Dv NULL . +.It Fn tok_end +Clean up and finish with +.Fa t , +assumed to have been created with +.Fn tok_init . +.It Fn tok_reset +Reset the tokenizer state. +Use after a line has been successfully tokenized +by +.Fn tok_line +or +.Fn tok_str +and before a new line is to be tokenized. +.It Fn tok_line +Tokenize +.Fa li , +If successful, modify: +.Fa argv +to contain the words, +.Fa argc +to contain the number of words, +.Fa cursorc +(if not +.Dv NULL ) +to contain the index of the word containing the cursor, +and +.Fa cursoro +(if not +.Dv NULL ) +to contain the offset within +.Fa argv[cursorc] +of the cursor. +.Pp +Returns +0 if successful, +\-1 for an internal error, +1 for an unmatched single quote, +2 for an unmatched double quote, +and +3 for a backslash quoted +.Aq newline . +A positive exit code indicates that another line should be read +and tokenization attempted again. +. +.It Fn tok_str +A simpler form of +.Fn tok_line ; +.Fa str +is a NUL terminated string to tokenize. +.El +.  .\"XXX.Sh EXAMPLES  .\"XXX: provide some examples  .Sh SEE ALSO -.Xr editrc 5 ,  .Xr sh 1 ,  .Xr signal 3 , -.Xr termcap 3 +.Xr termcap 3 , +.Xr editrc 5  .Sh HISTORY  The  .Nm @@ -610,9 +758,6 @@ and  .Dv EL_RPROMPT .  Jaromir Dolecek implemented the readline emulation.  .Sh BUGS -The tokenization functions are not publically defined in -.Fd <histedit.h>. -.Pp  At this time, it is the responsibility of the caller to  check the result of the  .Dv EL_EDITMODE @@ -1,4 +1,4 @@ -.\"	$NetBSD: editrc.5,v 1.11 2001/06/19 13:42:09 wiz Exp $ +.\"	$NetBSD: editrc.5,v 1.19 2003/11/01 23:35:33 christos Exp $  .\"  .\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.  .\" All rights reserved. @@ -33,7 +33,7 @@  .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  .\" POSSIBILITY OF SUCH DAMAGE.  .\" -.Dd November 8, 2000 +.Dd October 18, 2003  .Os  .Dt EDITRC 5  .Sh NAME @@ -62,7 +62,7 @@ for more information.  .Ar prog  is the program name string that a program defines when it calls  .Xr el_init 3 -to setup +to set up  .Xr editline 3 ,  which is usually  .Va argv[0] . @@ -122,7 +122,7 @@ Options include:  Bind all keys to the standard GNU Emacs-like bindings.  .It Fl v  Bind all keys to the standard -.Xr vi 1 -like +.Xr vi 1 Ns -like  bindings.  .It Fl a  List or change key bindings in the @@ -222,7 +222,7 @@ or  indicating that the terminal does or does not have that capability.  .Pp  .Fl s -returns an emptry string for non-existent capabilities, rather than +returns an empty string for non-existent capabilities, rather than  causing an error.  .Fl v  causes messages to be verbose. @@ -230,11 +230,27 @@ causes messages to be verbose.  Enable or disable the  .Nm editline  functionality in a program. -.It Ic history -List the history. +.It Ic history Ar list | Ar size Dv n | Ar unique Dv n +The  +.Ar list +command lists all entries in the history. +The +.Ar size +command sets the history size to +.Dv n +entries. +The +.Ar unique +command controls if history should keep duplicate entries. +If +.Dv n +is non zero, only keep unique history entries. +If +.Dv n +is zero, then keep all entries (the default).  .It Ic telltc  List the values of all the terminal capabilities (see -.Xr termcap 5 ). +.Xr termcap 5 ) .  .It Ic settc Ar cap Ar val  Set the terminal capability  .Ar cap @@ -251,6 +267,7 @@ No sanity checking is done.  .Op Ar +mode  .Op Ar -mode  .Op Ar mode +.Op Ar char=c  .Xc  Control which tty modes that  .Nm @@ -291,6 +308,15 @@ fixes  on or off or removes control of  .Ar mode  in the chosen set. +.Pp +.Ic Setty +can also be used to set tty characters to particular values using +.Ar char=value . +If +.Ar value +is empty +then the character is set to +.Dv _POSIX_VDISABLE .  .El  .Sh EDITOR COMMANDS  The following editor commands are available for use in key bindings: @@ -380,7 +406,7 @@ Cut the entire line and save in cut buffer.  Cut area between mark and cursor and save in cut buffer.  .It Ic em-copy-region  Copy area between mark and cursor to cut buffer. -.It Ic em-gosmacs-traspose +.It Ic em-gosmacs-transpose  Exchange the two characters before the cursor.  .It Ic em-next-word  Move next to end of current word. @@ -1,4 +1,4 @@ -/*	$NetBSD: el.c,v 1.23 2001/09/27 19:29:50 christos Exp $	*/ +/*	$NetBSD: el.c,v 1.40 2005/08/01 23:00:15 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,20 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)el.c	8.2 (Berkeley) 1/3/94";  #else -__RCSID("$NetBSD: el.c,v 1.23 2001/09/27 19:29:50 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.40 2005/08/01 23:00:15 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * el.c: EditLine interface functions   */ -#include "sys.h" -  #include <sys/types.h>  #include <sys/param.h>  #include <string.h> @@ -65,9 +59,6 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)  {  	EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); -#ifdef DEBUG -	char *tty; -#endif  	if (el == NULL)  		return (NULL); @@ -77,14 +68,21 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)  	el->el_infd = fileno(fin);  	el->el_outfile = fout;  	el->el_errfile = ferr; -	el->el_prog = strdup(prog); +	if ((el->el_prog = el_strdup(prog)) == NULL) { +		el_free(el); +		return NULL; +	}  	/*           * Initialize all the modules. Order is important!!!           */  	el->el_flags = 0; -	(void) term_init(el); +	if (term_init(el) == -1) { +		el_free(el->el_prog); +		el_free(el); +		return NULL; +	}  	(void) key_init(el);  	(void) map_init(el);  	if (tty_init(el) == -1) @@ -135,7 +133,7 @@ el_reset(EditLine *el)  {  	tty_cookedmode(el); -	ch_reset(el);		/* XXX: Do we want that? */ +	ch_reset(el, 0);		/* XXX: Do we want that? */  } @@ -146,7 +144,7 @@ public int  el_set(EditLine *el, int op, ...)  {  	va_list va; -	int rv; +	int rv = 0;  	if (el == NULL)  		return (-1); @@ -171,7 +169,6 @@ el_set(EditLine *el, int op, ...)  			el->el_flags |= HANDLE_SIGNALS;  		else  			el->el_flags &= ~HANDLE_SIGNALS; -		rv = 0;  		break;  	case EL_BIND: @@ -180,7 +177,7 @@ el_set(EditLine *el, int op, ...)  	case EL_ECHOTC:  	case EL_SETTY:  	{ -		char *argv[20]; +		const char *argv[20];  		int i;  		for (i = 1; i < 20; i++) @@ -255,8 +252,34 @@ el_set(EditLine *el, int op, ...)  		break;  	} +	case EL_CLIENTDATA: +		el->el_data = va_arg(va, void *); +		break; + +	case EL_UNBUFFERED: +		rv = va_arg(va, int); +		if (rv && !(el->el_flags & UNBUFFERED)) { +			el->el_flags |= UNBUFFERED; +			read_prepare(el); +		} else if (!rv && (el->el_flags & UNBUFFERED)) { +			el->el_flags &= ~UNBUFFERED; +			read_finish(el); +		} +		rv = 0; +		break; + +	case EL_PREP_TERM: +		rv = va_arg(va, int); +		if (rv) +			(void) tty_rawmode(el); +		else +			(void) tty_cookedmode(el); +		rv = 0; +		break; +  	default:  		rv = -1; +		break;  	}  	va_end(va); @@ -277,11 +300,11 @@ el_get(EditLine *el, int op, void *ret)  	switch (op) {  	case EL_PROMPT:  	case EL_RPROMPT: -		rv = prompt_get(el, (el_pfunc_t *) & ret, op); +		rv = prompt_get(el, (void *) &ret, op);  		break;  	case EL_EDITOR: -		rv = map_get_editor(el, (const char **) &ret); +		rv = map_get_editor(el, (void *) &ret);  		break;  	case EL_SIGNAL: @@ -294,21 +317,22 @@ el_get(EditLine *el, int op, void *ret)  		rv = 0;  		break; -#if 0				/* XXX */  	case EL_TERMINAL: -		rv = term_get(el, (const char *) &ret); +		term_get(el, (const char **)ret); +		rv = 0;  		break; +#if 0				/* XXX */  	case EL_BIND:  	case EL_TELLTC:  	case EL_SETTC:  	case EL_ECHOTC:  	case EL_SETTY:  	{ -		char *argv[20]; +		const char *argv[20];  		int i; -		for (i = 1; i < 20; i++) + 		for (i = 1; i < sizeof(argv) / sizeof(argv[0]); i++)  			if ((argv[i] = va_arg(va, char *)) == NULL)  				break; @@ -370,6 +394,16 @@ el_get(EditLine *el, int op, void *ret)  		rv = 0;  		break; +	case EL_CLIENTDATA: +		*((void **)ret) = el->el_data; +		rv = 0; +		break; + +	case EL_UNBUFFERED: +		*((int *) ret) = (!(el->el_flags & UNBUFFERED)); +		rv = 0; +		break; +  	default:  		rv = -1;  	} @@ -388,7 +422,6 @@ el_line(EditLine *el)  	return (const LineInfo *) (void *) &el->el_line;  } -static const char elpath[] = "/.editrc";  /* el_source():   *	Source a file @@ -398,10 +431,14 @@ el_source(EditLine *el, const char *fname)  {  	FILE *fp;  	size_t len; -	char *ptr, path[MAXPATHLEN]; +	char *ptr;  	fp = NULL;  	if (fname == NULL) { +#ifdef HAVE_ISSETUGID +		static const char elpath[] = "/.editrc"; +		char path[MAXPATHLEN]; +  		if (issetugid())  			return (-1);  		if ((ptr = getenv("HOME")) == NULL) @@ -411,6 +448,14 @@ el_source(EditLine *el, const char *fname)  		if (strlcat(path, elpath, sizeof(path)) >= sizeof(path))  			return (-1);  		fname = path; +#else +		/* +		 * If issetugid() is missing, always return an error, in order +		 * to keep from inadvertently opening up the user to a security +		 * hole. +		 */ +		return (-1); +#endif  	}  	if (fp == NULL)  		fp = fopen(fname, "r"); @@ -469,7 +514,7 @@ el_beep(EditLine *el)   */  protected int  /*ARGSUSED*/ -el_editmode(EditLine *el, int argc, char **argv) +el_editmode(EditLine *el, int argc, const char **argv)  {  	const char *how; @@ -477,10 +522,13 @@ el_editmode(EditLine *el, int argc, char **argv)  		return (-1);  	how = argv[1]; -	if (strcmp(how, "on") == 0) +	if (strcmp(how, "on") == 0) {  		el->el_flags &= ~EDIT_DISABLED; -	else if (strcmp(how, "off") == 0) +		tty_rawmode(el); +	} else if (strcmp(how, "off") == 0) { +		tty_cookedmode(el);  		el->el_flags |= EDIT_DISABLED; +	}  	else {  		(void) fprintf(el->el_errfile, "edit: Bad value `%s'.\n", how);  		return (-1); @@ -1,4 +1,4 @@ -/*	$NetBSD: el.h,v 1.9 2001/09/27 19:29:50 christos Exp $	*/ +/*	$NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -55,9 +51,10 @@  #define	EL_BUFSIZ	1024		/* Maximum line size		*/ -#define	HANDLE_SIGNALS	1<<0 -#define	NO_TTY		1<<1 -#define	EDIT_DISABLED	1<<2 +#define	HANDLE_SIGNALS	0x01 +#define	NO_TTY		0x02 +#define	EDIT_DISABLED	0x04 +#define	UNBUFFERED	0x08  typedef int bool_t;			/* True or not			*/ @@ -72,7 +69,7 @@ typedef struct el_line_t {  	char	*buffer;		/* Input line			*/  	char	*cursor;		/* Cursor position		*/  	char	*lastchar;		/* Last character		*/ -	const char	*limit;			/* Max position			*/ +	const char	*limit;		/* Max position			*/  } el_line_t;  /* @@ -84,11 +81,14 @@ typedef struct el_state_t {  	int		argument;	/* Numeric argument		*/  	int		metanext;	/* Is the next char a meta char */  	el_action_t	lastcmd;	/* Previous command		*/ +	el_action_t	thiscmd;	/* this command 		*/ +	char		thisch;		/* char that generated it	*/  } el_state_t;  /*   * Until we come up with something better...   */ +#define	el_strdup(a)	strdup(a)  #define	el_malloc(a)	malloc(a)  #define	el_realloc(a,b)	realloc(a, b)  #define	el_free(a)	free(a) @@ -117,6 +117,7 @@ struct editline {  	coord_t		  el_cursor;	/* Cursor location		*/  	char		**el_display;	/* Real screen image = what is there */  	char		**el_vdisplay;	/* Virtual screen image = what we see */ +	void		 *el_data;	/* Client data			*/  	el_line_t	  el_line;	/* The current line information	*/  	el_state_t	  el_state;	/* Current editor state		*/  	el_term_t	  el_term;	/* Terminal dependent stuff	*/ @@ -133,11 +134,15 @@ struct editline {  	el_read_t	  el_read;	/* Character reading stuff	*/  }; -protected int	el_editmode(EditLine *, int, char **); +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 @@ -1,4 +1,4 @@ -/*	$NetBSD: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek Exp $	*/ +/*	$NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)emacs.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek Exp $"); +__RCSID("$NetBSD: emacs.c,v 1.19 2004/10/28 21:14:52 dsl Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * emacs.c: Emacs functions   */ -#include "sys.h"  #include "el.h"  /* em_delete_or_list(): @@ -57,7 +52,7 @@ __RCSID("$NetBSD: emacs.c,v 1.9 2001/01/10 07:45:41 jdolecek Exp $");   */  protected el_action_t  /*ARGSUSED*/ -em_delete_or_list(EditLine *el, int c) +em_delete_or_list(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_line.cursor == el->el_line.lastchar) { @@ -76,7 +71,10 @@ em_delete_or_list(EditLine *el, int c)  			return (CC_ERROR);  		}  	} else { -		c_delafter(el, el->el_state.argument);	/* delete after dot */ +		if (el->el_state.doingarg) +			c_delafter(el, el->el_state.argument); +		else +			c_delafter1(el);  		if (el->el_line.cursor > el->el_line.lastchar)  			el->el_line.cursor = el->el_line.lastchar;  				/* bounds check */ @@ -91,7 +89,7 @@ em_delete_or_list(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_delete_next_word(EditLine *el, int c) +em_delete_next_word(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *p, *kp; @@ -120,14 +118,12 @@ em_delete_next_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_yank(EditLine *el, int c) +em_yank(EditLine *el, int c __attribute__((__unused__)))  {  	char *kp, *cp; -	if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) { -		if (!ch_enlargebufs(el, 1)) -			return (CC_ERROR); -	} +	if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf) +		return (CC_NORM);  	if (el->el_line.lastchar +  	    (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= @@ -157,7 +153,7 @@ em_yank(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_kill_line(EditLine *el, int c) +em_kill_line(EditLine *el, int c __attribute__((__unused__)))  {  	char *kp, *cp; @@ -179,7 +175,7 @@ em_kill_line(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_kill_region(EditLine *el, int c) +em_kill_region(EditLine *el, int c __attribute__((__unused__)))  {  	char *kp, *cp; @@ -212,11 +208,11 @@ em_kill_region(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_copy_region(EditLine *el, int c) +em_copy_region(EditLine *el, int c __attribute__((__unused__)))  {  	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) { @@ -236,12 +232,12 @@ em_copy_region(EditLine *el, int c)  } -/* em_gosmacs_traspose(): +/* em_gosmacs_transpose():   *	Exchange the two characters before the cursor   *	Gosling emacs transpose chars [^T]   */  protected el_action_t -em_gosmacs_traspose(EditLine *el, int c) +em_gosmacs_transpose(EditLine *el, int c)  {  	if (el->el_line.cursor > &el->el_line.buffer[1]) { @@ -261,7 +257,7 @@ em_gosmacs_traspose(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_next_word(EditLine *el, int c) +em_next_word(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_line.cursor == el->el_line.lastchar)  		return (CC_ERROR); @@ -272,7 +268,7 @@ em_next_word(EditLine *el, int c)  	    ce__isword);  	if (el->el_map.type == MAP_VI) -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -286,7 +282,7 @@ em_next_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_upper_case(EditLine *el, int c) +em_upper_case(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *ep; @@ -294,8 +290,8 @@ em_upper_case(EditLine *el, int c)  	    el->el_state.argument, ce__isword);  	for (cp = el->el_line.cursor; cp < ep; cp++) -		if (islower((unsigned char) *cp)) -			*cp = toupper(*cp); +		if (islower((unsigned char)*cp)) +			*cp = toupper((unsigned char)*cp);  	el->el_line.cursor = ep;  	if (el->el_line.cursor > el->el_line.lastchar) @@ -310,7 +306,7 @@ em_upper_case(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_capitol_case(EditLine *el, int c) +em_capitol_case(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *ep; @@ -318,16 +314,16 @@ em_capitol_case(EditLine *el, int c)  	    el->el_state.argument, ce__isword);  	for (cp = el->el_line.cursor; cp < ep; cp++) { -		if (isalpha((unsigned char) *cp)) { -			if (islower((unsigned char) *cp)) -				*cp = toupper(*cp); +		if (isalpha((unsigned char)*cp)) { +			if (islower((unsigned char)*cp)) +				*cp = toupper((unsigned char)*cp);  			cp++;  			break;  		}  	}  	for (; cp < ep; cp++) -		if (isupper((unsigned char) *cp)) -			*cp = tolower(*cp); +		if (isupper((unsigned char)*cp)) +			*cp = tolower((unsigned char)*cp);  	el->el_line.cursor = ep;  	if (el->el_line.cursor > el->el_line.lastchar) @@ -342,7 +338,7 @@ em_capitol_case(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_lower_case(EditLine *el, int c) +em_lower_case(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *ep; @@ -350,8 +346,8 @@ em_lower_case(EditLine *el, int c)  	    el->el_state.argument, ce__isword);  	for (cp = el->el_line.cursor; cp < ep; cp++) -		if (isupper((unsigned char) *cp)) -			*cp = tolower(*cp); +		if (isupper((unsigned char)*cp)) +			*cp = tolower((unsigned char)*cp);  	el->el_line.cursor = ep;  	if (el->el_line.cursor > el->el_line.lastchar) @@ -366,7 +362,7 @@ em_lower_case(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_set_mark(EditLine *el, int c) +em_set_mark(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_chared.c_kill.mark = el->el_line.cursor; @@ -380,7 +376,7 @@ em_set_mark(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_exchange_mark(EditLine *el, int c) +em_exchange_mark(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp; @@ -397,7 +393,7 @@ em_exchange_mark(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_universal_argument(EditLine *el, int c) +em_universal_argument(EditLine *el, int c __attribute__((__unused__)))  {				/* multiply current argument by 4 */  	if (el->el_state.argument > 1000000) @@ -414,7 +410,7 @@ em_universal_argument(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_meta_next(EditLine *el, int c) +em_meta_next(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_state.metanext = 1; @@ -427,7 +423,7 @@ em_meta_next(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_toggle_overwrite(EditLine *el, int c) +em_toggle_overwrite(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? @@ -441,7 +437,7 @@ em_toggle_overwrite(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_copy_prev_word(EditLine *el, int c) +em_copy_prev_word(EditLine *el, int c __attribute__((__unused__)))  {  	char *cp, *oldc, *dp; @@ -468,7 +464,7 @@ em_copy_prev_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_inc_search_next(EditLine *el, int c) +em_inc_search_next(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_search.patlen = 0; @@ -481,9 +477,32 @@ em_inc_search_next(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -em_inc_search_prev(EditLine *el, int c) +em_inc_search_prev(EditLine *el, int c __attribute__((__unused__)))  {  	el->el_search.patlen = 0;  	return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY));  } + + +/* em_delete_prev_char(): + *	Delete the character to the left of the cursor + *	[^?] + */ +protected el_action_t +/*ARGSUSED*/ +em_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) +{ + +	if (el->el_line.cursor <= el->el_line.buffer) +		return (CC_ERROR); + +	if (el->el_state.doingarg) +		c_delbefore(el, el->el_state.argument); +	else +		c_delbefore1(el); +	el->el_line.cursor -= el->el_state.argument; +	if (el->el_line.cursor < el->el_line.buffer) +		el->el_line.cursor = el->el_line.buffer; +	return (CC_REFRESH); +} diff --git a/filecomplete.c b/filecomplete.c new file mode 100644 index 000000000000..e0738a7e52b2 --- /dev/null +++ b/filecomplete.c @@ -0,0 +1,539 @@ +/*	$NetBSD: filecomplete.c,v 1.7 2005/06/11 18:18:59 christos Exp $	*/ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the NetBSD + *	Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: filecomplete.c,v 1.7 2005/06/11 18:18:59 christos Exp $"); +#endif /* not lint && not SCCSID */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <dirent.h> +#include <string.h> +#include <pwd.h> +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <limits.h> +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_VIS_H +#include <vis.h> +#else +#include "np/vis.h" +#endif +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif +#include "el.h" +#include "fcns.h"		/* for EL_NUM_FCNS */ +#include "histedit.h" +#include "filecomplete.h" + +static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', +    '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; + + +/********************************/ +/* completion functions */ + +/* + * does tilde expansion of strings of type ``~user/foo'' + * if ``user'' isn't valid user name or ``txt'' doesn't start + * w/ '~', returns pointer to strdup()ed copy of ``txt'' + * + * it's callers's responsibility to free() returned string + */ +char * +fn_tilde_expand(const char *txt) +{ +	struct passwd pwres, *pass; +	char *temp; +	size_t len = 0; +	char pwbuf[1024]; + +	if (txt[0] != '~') +		return (strdup(txt)); + +	temp = strchr(txt + 1, '/'); +	if (temp == NULL) { +		temp = strdup(txt + 1); +		if (temp == NULL) +			return NULL; +	} else { +		len = temp - txt + 1;	/* text until string after slash */ +		temp = malloc(len); +		if (temp == NULL) +			return NULL; +		(void)strncpy(temp, txt + 1, len - 2); +		temp[len - 2] = '\0'; +	} +	if (temp[0] == 0) { +		if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) +			pass = NULL; +	} else { +		if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) +			pass = NULL; +	} +	free(temp);		/* value no more needed */ +	if (pass == NULL) +		return (strdup(txt)); + +	/* update pointer txt to point at string immedially following */ +	/* first slash */ +	txt += len; + +	temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); +	if (temp == NULL) +		return NULL; +	(void)sprintf(temp, "%s/%s", pass->pw_dir, txt); + +	return (temp); +} + + +/* + * return first found file name starting by the ``text'' or NULL if no + * such file can be found + * value of ``state'' is ignored + * + * it's caller's responsibility to free returned string + */ +char * +fn_filename_completion_function(const char *text, int state) +{ +	static DIR *dir = NULL; +	static char *filename = NULL, *dirname = NULL, *dirpath = NULL; +	static size_t filename_len = 0; +	struct dirent *entry; +	char *temp; +	size_t len; + +	if (state == 0 || dir == NULL) { +		temp = strrchr(text, '/'); +		if (temp) { +			char *nptr; +			temp++; +			nptr = realloc(filename, strlen(temp) + 1); +			if (nptr == NULL) { +				free(filename); +				return NULL; +			} +			filename = nptr; +			(void)strcpy(filename, temp); +			len = temp - text;	/* including last slash */ +			nptr = realloc(dirname, len + 1); +			if (nptr == NULL) { +				free(filename); +				return NULL; +			} +			dirname = nptr; +			(void)strncpy(dirname, text, len); +			dirname[len] = '\0'; +		} else { +			if (*text == 0) +				filename = NULL; +			else { +				filename = strdup(text); +				if (filename == NULL) +					return NULL; +			} +			dirname = NULL; +		} + +		if (dir != NULL) { +			(void)closedir(dir); +			dir = NULL; +		} + +		/* support for ``~user'' syntax */ +		free(dirpath); + +		if (dirname == NULL && (dirname = strdup("./")) == NULL) +			return NULL; + +		if (*dirname == '~') +			dirpath = fn_tilde_expand(dirname); +		else +			dirpath = strdup(dirname); + +		if (dirpath == NULL) +			return NULL; + +		dir = opendir(dirpath); +		if (!dir) +			return (NULL);	/* cannot open the directory */ + +		/* will be used in cycle */ +		filename_len = filename ? strlen(filename) : 0; +	} + +	/* find the match */ +	while ((entry = readdir(dir)) != NULL) { +		/* skip . and .. */ +		if (entry->d_name[0] == '.' && (!entry->d_name[1] +		    || (entry->d_name[1] == '.' && !entry->d_name[2]))) +			continue; +		if (filename_len == 0) +			break; +		/* otherwise, get first entry where first */ +		/* filename_len characters are equal	  */ +		if (entry->d_name[0] == filename[0] +#if defined(__SVR4) || defined(__linux__) +		    && strlen(entry->d_name) >= filename_len +#else +		    && entry->d_namlen >= filename_len +#endif +		    && strncmp(entry->d_name, filename, +			filename_len) == 0) +			break; +	} + +	if (entry) {		/* match found */ + +#if defined(__SVR4) || defined(__linux__) +		len = strlen(entry->d_name); +#else +		len = entry->d_namlen; +#endif + +		temp = malloc(strlen(dirname) + len + 1); +		if (temp == NULL) +			return NULL; +		(void)sprintf(temp, "%s%s", dirname, entry->d_name); +	} else { +		(void)closedir(dir); +		dir = NULL; +		temp = NULL; +	} + +	return (temp); +} + + +static const char * +append_char_function(const char *name) +{ +	struct stat stbuf; +	char *expname = *name == '~' ? fn_tilde_expand(name) : NULL; +	const char *rs = ""; + +	if (stat(expname ? expname : name, &stbuf) == -1) +		goto out; +	if (S_ISDIR(stbuf.st_mode)) +		rs = "/"; +out: +	if (expname) +		free(expname); +	return rs; +} +/* + * returns list of completions for text given + * non-static for readline. + */ +char ** completion_matches(const char *, char *(*)(const char *, int)); +char ** +completion_matches(const char *text, char *(*genfunc)(const char *, int)) +{ +	char **match_list = NULL, *retstr, *prevstr; +	size_t match_list_len, max_equal, which, i; +	size_t matches; + +	matches = 0; +	match_list_len = 1; +	while ((retstr = (*genfunc) (text, (int)matches)) != NULL) { +		/* allow for list terminator here */ +		if (matches + 3 >= match_list_len) { +			char **nmatch_list; +			while (matches + 3 >= match_list_len) +				match_list_len <<= 1; +			nmatch_list = realloc(match_list, +			    match_list_len * sizeof(char *)); +			if (nmatch_list == NULL) { +				free(match_list); +				return NULL; +			} +			match_list = nmatch_list; + +		} +		match_list[++matches] = retstr; +	} + +	if (!match_list) +		return NULL;	/* nothing found */ + +	/* find least denominator and insert it to match_list[0] */ +	which = 2; +	prevstr = match_list[1]; +	max_equal = strlen(prevstr); +	for (; which <= matches; which++) { +		for (i = 0; i < max_equal && +		    prevstr[i] == match_list[which][i]; i++) +			continue; +		max_equal = i; +	} + +	retstr = malloc(max_equal + 1); +	if (retstr == NULL) { +		free(match_list); +		return NULL; +	} +	(void)strncpy(retstr, match_list[1], max_equal); +	retstr[max_equal] = '\0'; +	match_list[0] = retstr; + +	/* add NULL as last pointer to the array */ +	match_list[matches + 1] = (char *) NULL; + +	return (match_list); +} + +/* + * Sort function for qsort(). Just wrapper around strcasecmp(). + */ +static int +_fn_qsort_string_compare(const void *i1, const void *i2) +{ +	const char *s1 = ((const char * const *)i1)[0]; +	const char *s2 = ((const char * const *)i2)[0]; + +	return strcasecmp(s1, s2); +} + +/* + * Display list of strings in columnar format on readline's output stream. + * 'matches' is list of strings, 'len' is number of strings in 'matches', + * 'max' is maximum length of string in 'matches'. + */ +void +fn_display_match_list (EditLine *el, char **matches, int len, int max) +{ +	int i, idx, limit, count; +	int screenwidth = el->el_term.t_size.h; + +	/* +	 * Find out how many entries can be put on one line, count +	 * with two spaces between strings. +	 */ +	limit = screenwidth / (max + 2); +	if (limit == 0) +		limit = 1; + +	/* how many lines of output */ +	count = len / limit; +	if (count * limit < len) +		count++; + +	/* Sort the items if they are not already sorted. */ +	qsort(&matches[1], (size_t)(len - 1), sizeof(char *), +	    _fn_qsort_string_compare); + +	idx = 1; +	for(; count > 0; count--) { +		for(i = 0; i < limit && matches[idx]; i++, idx++) +			(void)fprintf(el->el_outfile, "%-*s  ", max, +			    matches[idx]); +		(void)fprintf(el->el_outfile, "\n"); +	} +} + +/* + * Complete the word at or before point, + * 'what_to_do' says what to do with the completion. + * \t   means do standard completion. + * `?' means list the possible completions. + * `*' means insert all of the possible completions. + * `!' means to do standard completion, and list all possible completions if + * there is more than one. + * + * Note: '*' support is not implemented + *       '!' could never be invoked + */ +int +fn_complete(EditLine *el, +	char *(*complet_func)(const char *, int), +	char **(*attempted_completion_function)(const char *, int, int), +	const char *word_break, const char *special_prefixes, +	const char *(*app_func)(const char *), int query_items, +	int *completion_type, int *over, int *point, int *end) +{ +	const LineInfo *li; +	char *temp, **matches; +	const char *ctemp; +	size_t len; +	int what_to_do = '\t'; + +	if (el->el_state.lastcmd == el->el_state.thiscmd) +		what_to_do = '?'; + +	/* readline's rl_complete() has to be told what we did... */ +	if (completion_type != NULL) +		*completion_type = what_to_do; + +	if (!complet_func) +		complet_func = fn_filename_completion_function; +	if (!app_func) +		app_func = append_char_function; + +	/* We now look backwards for the start of a filename/variable word */ +	li = el_line(el); +	ctemp = (const char *) li->cursor; +	while (ctemp > li->buffer +	    && !strchr(word_break, ctemp[-1]) +	    && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) ) +		ctemp--; + +	len = li->cursor - ctemp; +	temp = alloca(len + 1); +	(void)strncpy(temp, ctemp, len); +	temp[len] = '\0'; + +	/* these can be used by function called in completion_matches() */ +	/* or (*attempted_completion_function)() */ +	if (point != 0) +		*point = li->cursor - li->buffer; +	if (end != NULL) +		*end = li->lastchar - li->buffer; + +	if (attempted_completion_function) { +		int cur_off = li->cursor - li->buffer; +		matches = (*attempted_completion_function) (temp, +		    (int)(cur_off - len), cur_off); +	} else +		matches = 0; +	if (!attempted_completion_function ||  +	    (over != NULL && *over && !matches)) +		matches = completion_matches(temp, complet_func); + +	if (over != NULL) +		*over = 0; + +	if (matches) { +		int i, retval = CC_REFRESH; +		int matches_num, maxlen, match_len, match_display=1; + +		/* +		 * Only replace the completed string with common part of +		 * possible matches if there is possible completion. +		 */ +		if (matches[0][0] != '\0') { +			el_deletestr(el, (int) len); +			el_insertstr(el, matches[0]); +		} + +		if (what_to_do == '?') +			goto display_matches; + +		if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { +			/* +			 * We found exact match. Add a space after +			 * it, unless we do filename completion and the +			 * object is a directory. +			 */ +			el_insertstr(el, (*append_char_function)(matches[0]));  +		} else if (what_to_do == '!') { +    display_matches: +			/* +			 * More than one match and requested to list possible +			 * matches. +			 */ + +			for(i=1, maxlen=0; matches[i]; i++) { +				match_len = strlen(matches[i]); +				if (match_len > maxlen) +					maxlen = match_len; +			} +			matches_num = i - 1; +				 +			/* newline to get on next line from command line */ +			(void)fprintf(el->el_outfile, "\n"); + +			/* +			 * If there are too many items, ask user for display +			 * confirmation. +			 */ +			if (matches_num > query_items) { +				(void)fprintf(el->el_outfile, +				    "Display all %d possibilities? (y or n) ", +				    matches_num); +				(void)fflush(el->el_outfile); +				if (getc(stdin) != 'y') +					match_display = 0; +				(void)fprintf(el->el_outfile, "\n"); +			} + +			if (match_display) +				fn_display_match_list(el, matches, matches_num, +					maxlen); +			retval = CC_REDISPLAY; +		} else if (matches[0][0]) { +			/* +			 * There was some common match, but the name was +			 * not complete enough. Next tab will print possible +			 * completions. +			 */ +			el_beep(el); +		} else { +			/* lcd is not a valid object - further specification */ +			/* is needed */ +			el_beep(el); +			retval = CC_NORM; +		} + +		/* free elements of array and the array itself */ +		for (i = 0; matches[i]; i++) +			free(matches[i]); +		free(matches), matches = NULL; + +		return (retval); +	} +	return (CC_NORM); +} + +/* + * el-compatible wrapper around rl_complete; needed for key binding + */ +/* ARGSUSED */ +unsigned char +_el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) +{ +	return (unsigned char)fn_complete(el, NULL, NULL, +	    break_chars, NULL, NULL, 100, +	    NULL, NULL, NULL, NULL); +} diff --git a/filecomplete.h b/filecomplete.h new file mode 100644 index 000000000000..335ec7296e69 --- /dev/null +++ b/filecomplete.h @@ -0,0 +1,51 @@ +/*	$NetBSD: filecomplete.h,v 1.4 2005/06/11 18:18:59 christos Exp $	*/ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jaromir Dolecek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by the NetBSD + *	Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + *    contributors may be used to endorse or promote products derived + *    from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _FILECOMPLETE_H_ +#define _FILECOMPLETE_H_ + +int fn_complete(EditLine *, +    char *(*)(const char *, int), +    char **(*)(const char *, int, int), +    const char *, const char *, const char *(*)(const char *), int, +    int *, int *, int *, int *); + +void fn_display_match_list(EditLine *, char **, int, int); +char *fn_tilde_expand(const char *); +char *fn_filename_completion_function(const char *, int); + +#endif @@ -1,4 +1,4 @@ -/*	$NetBSD: hist.c,v 1.9 2001/05/17 01:02:17 christos Exp $	*/ +/*	$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)hist.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: hist.c,v 1.9 2001/05/17 01:02:17 christos Exp $"); +__RCSID("$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * hist.c: History access functions   */ -#include "sys.h"  #include <stdlib.h>  #include "el.h" @@ -133,18 +128,16 @@ hist_get(EditLine *el)  			el->el_history.eventno = h;  			return (CC_ERROR);  		} -	(void) strncpy(el->el_line.buffer, hp, +	(void) strlcpy(el->el_line.buffer, hp,  			(size_t)(el->el_line.limit - el->el_line.buffer));  	el->el_line.lastchar = el->el_line.buffer + strlen(el->el_line.buffer); -	if (el->el_line.lastchar > el->el_line.buffer) { -		if (el->el_line.lastchar[-1] == '\n') -			el->el_line.lastchar--; -		if (el->el_line.lastchar[-1] == ' ') -			el->el_line.lastchar--; -		if (el->el_line.lastchar < el->el_line.buffer) -			el->el_line.lastchar = el->el_line.buffer; -	} +	if (el->el_line.lastchar > el->el_line.buffer +	    && el->el_line.lastchar[-1] == '\n') +		el->el_line.lastchar--; +	if (el->el_line.lastchar > el->el_line.buffer +	    && el->el_line.lastchar[-1] == ' ') +		el->el_line.lastchar--;  #ifdef KSHVI  	if (el->el_map.type == MAP_VI)  		el->el_line.cursor = el->el_line.buffer; @@ -156,21 +149,40 @@ hist_get(EditLine *el)  } -/* hist_list() - *	List history entries +/* hist_command() + *	process a history command   */  protected int -/*ARGSUSED*/ -hist_list(EditLine *el, int argc, char **argv) +hist_command(EditLine *el, int argc, const char **argv)  {  	const char *str; +	int num; +	HistEvent ev;  	if (el->el_history.ref == NULL)  		return (-1); -	for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) -		(void) fprintf(el->el_outfile, "%d %s", -		    el->el_history.ev.num, str); -	return (0); + +	if (argc == 1 || strcmp(argv[1], "list") == 0) { +		 /* List history entries */ + +		for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) +			(void) fprintf(el->el_outfile, "%d %s", +			    el->el_history.ev.num, str); +		return (0); +	} + +	if (argc != 3) +		return (-1); + +	num = (int)strtol(argv[2], NULL, 0); + +	if (strcmp(argv[1], "size") == 0) +		return history(el->el_history.ref, &ev, H_SETSIZE, num); + +	if (strcmp(argv[1], "unique") == 0) +		return history(el->el_history.ref, &ev, H_SETUNIQUE, num); + +	return -1;  }  /* hist_enlargebuf() @@ -1,4 +1,4 @@ -/*	$NetBSD: hist.h,v 1.6 2001/01/10 07:45:41 jdolecek Exp $	*/ +/*	$NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -66,7 +62,7 @@ typedef struct el_history_t {  #define	HIST_FIRST(el)		HIST_FUN(el, H_FIRST, NULL)  #define	HIST_LAST(el)		HIST_FUN(el, H_LAST, NULL)  #define	HIST_PREV(el)		HIST_FUN(el, H_PREV, NULL) -#define	HIST_EVENT(el, num)	HIST_FUN(el, H_EVENT, num) +#define	HIST_SET(el, num)	HIST_FUN(el, H_SET, num)  #define	HIST_LOAD(el, fname)	HIST_FUN(el, H_LOAD fname)  #define	HIST_SAVE(el, fname)	HIST_FUN(el, H_SAVE fname) @@ -74,7 +70,7 @@ protected int		hist_init(EditLine *);  protected void		hist_end(EditLine *);  protected el_action_t	hist_get(EditLine *);  protected int		hist_set(EditLine *, hist_fun_t, ptr_t); -protected int		hist_list(EditLine *, int, char **); +protected int		hist_command(EditLine *, int, const char **);  protected int		hist_enlargebuf(EditLine *, size_t, size_t);  #endif /* _h_el_hist */ diff --git a/histedit.h b/histedit.h index 9c3a2dc24014..40f0dd10e88e 100644 --- a/histedit.h +++ b/histedit.h @@ -1,4 +1,4 @@ -/*	$NetBSD: histedit.h,v 1.17 2001/09/27 19:29:50 christos Exp $	*/ +/*	$NetBSD: histedit.h,v 1.28 2005/07/14 15:00:58 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -44,12 +40,20 @@  #ifndef _HISTEDIT_H_  #define	_HISTEDIT_H_ +#define	LIBEDIT_MAJOR 2 +#define	LIBEDIT_MINOR 9 +  #include <sys/types.h>  #include <stdio.h> +#ifdef __cplusplus +extern "C" { +#endif +  /*   * ==== Editing ====   */ +  typedef struct editline EditLine;  /* @@ -61,7 +65,6 @@ typedef struct lineinfo {  	const char	*lastchar;  } LineInfo; -  /*   * EditLine editor function return codes.   * For user-defined function interface @@ -81,16 +84,15 @@ typedef struct lineinfo {   * Initialization, cleanup, and resetting   */  EditLine	*el_init(const char *, FILE *, FILE *, FILE *); -void		 el_reset(EditLine *);  void		 el_end(EditLine *); - +void		 el_reset(EditLine *);  /*   * Get a line, a character or push a string back in the input queue   */  const char	*el_gets(EditLine *, int *);  int		 el_getc(EditLine *, char *); -void		 el_push(EditLine *, const char *); +void		 el_push(EditLine *, char *);  /*   * Beep! @@ -101,13 +103,14 @@ void		 el_beep(EditLine *);   * High level function internals control   * Parses argc, argv array and executes builtin editline commands   */ -int		 el_parse(EditLine *, int, char **); +int		 el_parse(EditLine *, int, const char **);  /*   * Low level editline access functions   */  int		 el_set(EditLine *, int, ...);  int		 el_get(EditLine *, int, void *); +unsigned char	_el_fn_complete(EditLine *, int);  /*   * el_set/el_get parameters @@ -127,6 +130,9 @@ int		 el_get(EditLine *, int, void *);  #define	EL_EDITMODE	11	/* , int);			*/  #define	EL_RPROMPT	12	/* , el_pfunc_t);		*/  #define	EL_GETCFN	13	/* , el_rfunc_t);		*/ +#define	EL_CLIENTDATA	14	/* , void *);			*/ +#define	EL_UNBUFFERED	15	/* , int);			*/ +#define	EL_PREP_TERM    16      /* , int);                      */  #define EL_BUILTIN_GETCFN	(NULL) @@ -142,7 +148,6 @@ int		el_source(EditLine *, const char *);   */  void		 el_resize(EditLine *); -  /*   * User-defined function interface.   */ @@ -150,6 +155,7 @@ const LineInfo	*el_line(EditLine *);  int		 el_insertstr(EditLine *, const char *);  void		 el_deletestr(EditLine *, int); +  /*   * ==== History ====   */ @@ -177,7 +183,7 @@ int		history(History *, HistEvent *, int, ...);  #define	H_PREV		 5	/* , void);		*/  #define	H_NEXT		 6	/* , void);		*/  #define	H_CURR		 8	/* , const int);	*/ -#define	H_SET		 7	/* , void);		*/ +#define	H_SET		 7	/* , int);		*/  #define	H_ADD		 9	/* , const char *);	*/  #define	H_ENTER		10	/* , const char *);	*/  #define	H_APPEND	11	/* , const char *);	*/ @@ -189,5 +195,30 @@ int		history(History *, HistEvent *, int, ...);  #define	H_LOAD		17	/* , const char *);	*/  #define	H_SAVE		18	/* , const char *);	*/  #define	H_CLEAR		19	/* , void);		*/ +#define	H_SETUNIQUE	20	/* , int);		*/ +#define	H_GETUNIQUE	21	/* , void);		*/ +#define	H_DEL		22	/* , int);		*/ + + +/* + * ==== Tokenization ==== + */ + +typedef struct tokenizer Tokenizer; + +/* + * String tokenization functions, using simplified sh(1) quoting rules + */ +Tokenizer	*tok_init(const char *); +void		 tok_end(Tokenizer *); +void		 tok_reset(Tokenizer *); +int		 tok_line(Tokenizer *, const LineInfo *, +		    int *, const char ***, int *, int *); +int		 tok_str(Tokenizer *, const char *, +		    int *, const char ***); + +#ifdef __cplusplus +} +#endif  #endif /* _HISTEDIT_H_ */ diff --git a/history.c b/history.c index d048898023e9..6d880cfa2e43 100644 --- a/history.c +++ b/history.c @@ -1,4 +1,4 @@ -/*	$NetBSD: history.c,v 1.18 2001/09/29 17:52:10 jdolecek Exp $	*/ +/*	$NetBSD: history.c,v 1.31 2005/08/01 14:34:06 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,24 +32,26 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)history.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: history.c,v 1.18 2001/09/29 17:52:10 jdolecek Exp $"); +__RCSID("$NetBSD: history.c,v 1.31 2005/08/01 14:34:06 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * hist.c: History access functions   */ -#include "sys.h" -  #include <string.h>  #include <stdlib.h>  #include <stdarg.h> +#ifdef HAVE_VIS_H  #include <vis.h> +#else +#include "np/vis.h" +#endif  #include <sys/stat.h>  static const char hist_cookie[] = "_HiStOrY_V2_\n"; @@ -74,10 +72,12 @@ struct history {  	history_gfun_t h_prev;	/* Get the previous element	 */  	history_gfun_t h_curr;	/* Get the current element	 */  	history_sfun_t h_set;	/* Set the current element	 */ +	history_sfun_t h_del;	/* Set the given element	 */  	history_vfun_t h_clear;	/* Clear the history list	 */  	history_efun_t h_enter;	/* Add an element		 */  	history_efun_t h_add;	/* Append to an element		 */  }; +  #define	HNEXT(h, ev)		(*(h)->h_next)((h)->h_ref, ev)  #define	HFIRST(h, ev)		(*(h)->h_first)((h)->h_ref, ev)  #define	HPREV(h, ev)		(*(h)->h_prev)((h)->h_ref, ev) @@ -87,14 +87,24 @@ struct history {  #define	HCLEAR(h, ev)		(*(h)->h_clear)((h)->h_ref, ev)  #define	HENTER(h, ev, str)	(*(h)->h_enter)((h)->h_ref, ev, str)  #define	HADD(h, ev, str)	(*(h)->h_add)((h)->h_ref, ev, str) +#define	HDEL(h, ev, n)		(*(h)->h_del)((h)->h_ref, ev, n) +#define	h_strdup(a)	strdup(a)  #define	h_malloc(a)	malloc(a)  #define	h_realloc(a, b)	realloc((a), (b))  #define	h_free(a)	free(a) +typedef struct { +    int		num; +    char	*str; +} HistEventPrivate; + +  private int history_setsize(History *, HistEvent *, int);  private int history_getsize(History *, HistEvent *); +private int history_setunique(History *, HistEvent *, int); +private int history_getunique(History *, HistEvent *);  private int history_set_fun(History *, History *);  private int history_load(History *, const char *);  private int history_save(History *, const char *); @@ -113,31 +123,41 @@ typedef struct hentry_t {  	HistEvent ev;		/* What we return		 */  	struct hentry_t *next;	/* Next entry			 */  	struct hentry_t *prev;	/* Previous entry		 */ -}        hentry_t; +} hentry_t;  typedef struct history_t { -	hentry_t list;		/* Fake list header element	 */ -	hentry_t *cursor;	/* Current element in the list	 */ -	int max;		/* Maximum number of events	 */ -	int cur;		/* Current number of events	 */ +	hentry_t list;		/* Fake list header element	*/ +	hentry_t *cursor;	/* Current element in the list	*/ +	int max;		/* Maximum number of events	*/ +	int cur;		/* Current number of events	*/  	int eventid;		/* For generation of unique event id	 */ -}         history_t; +	int flags;		/* History flags		*/ +#define H_UNIQUE	1	/* Store only unique elements	*/ +} history_t; -private int history_def_first(ptr_t, HistEvent *); -private int history_def_last(ptr_t, HistEvent *);  private int history_def_next(ptr_t, HistEvent *); +private int history_def_first(ptr_t, HistEvent *);  private int history_def_prev(ptr_t, HistEvent *); +private int history_def_last(ptr_t, HistEvent *);  private int history_def_curr(ptr_t, HistEvent *); -private int history_def_set(ptr_t, HistEvent *, const int n); +private int history_def_set(ptr_t, HistEvent *, const int); +private void history_def_clear(ptr_t, HistEvent *);  private int history_def_enter(ptr_t, HistEvent *, const char *);  private int history_def_add(ptr_t, HistEvent *, const char *); -private void history_def_init(ptr_t *, HistEvent *, int); -private void history_def_clear(ptr_t, HistEvent *); +private int history_def_del(ptr_t, HistEvent *, const int); + +private int history_def_init(ptr_t *, HistEvent *, int);  private int history_def_insert(history_t *, HistEvent *, const char *);  private void history_def_delete(history_t *, HistEvent *, hentry_t *); -#define	history_def_setsize(p, num)(void) (((history_t *) p)->max = (num)) -#define	history_def_getsize(p)  (((history_t *) p)->cur) +#define	history_def_setsize(p, num)(void) (((history_t *)p)->max = (num)) +#define	history_def_getsize(p)  (((history_t *)p)->cur) +#define	history_def_getunique(p) (((((history_t *)p)->flags) & H_UNIQUE) != 0) +#define	history_def_setunique(p, uni) \ +    if (uni) \ +	(((history_t *)p)->flags) |= H_UNIQUE; \ +    else \ +	(((history_t *)p)->flags) &= ~H_UNIQUE  #define	he_strerror(code)	he_errlist[code]  #define	he_seterrev(evp, code)	{\ @@ -230,20 +250,19 @@ history_def_next(ptr_t p, HistEvent *ev)  {  	history_t *h = (history_t *) p; -	if (h->cursor != &h->list) -		h->cursor = h->cursor->next; -	else { +	if (h->cursor == &h->list) {  		he_seterrev(ev, _HE_EMPTY_LIST);  		return (-1);  	} -	if (h->cursor != &h->list) -		*ev = h->cursor->ev; -	else { +	if (h->cursor->next == &h->list) {  		he_seterrev(ev, _HE_END_REACHED);  		return (-1);  	} +        h->cursor = h->cursor->next; +        *ev = h->cursor->ev; +  	return (0);  } @@ -256,21 +275,20 @@ history_def_prev(ptr_t p, HistEvent *ev)  {  	history_t *h = (history_t *) p; -	if (h->cursor != &h->list) -		h->cursor = h->cursor->prev; -	else { +	if (h->cursor == &h->list) {  		he_seterrev(ev,  		    (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);  		return (-1);  	} -	if (h->cursor != &h->list) -		*ev = h->cursor->ev; -	else { +	if (h->cursor->prev == &h->list) {  		he_seterrev(ev, _HE_START_REACHED);  		return (-1);  	} +        h->cursor = h->cursor->prev; +        *ev = h->cursor->ev; +  	return (0);  } @@ -331,39 +349,59 @@ history_def_add(ptr_t p, HistEvent *ev, const char *str)  	history_t *h = (history_t *) p;  	size_t len;  	char *s; +	HistEventPrivate *evp = (void *)&h->cursor->ev;  	if (h->cursor == &h->list)  		return (history_def_enter(p, ev, str)); -	len = strlen(h->cursor->ev.str) + strlen(str) + 1; +	len = strlen(evp->str) + strlen(str) + 1;  	s = (char *) h_malloc(len); -	if (!s) { +	if (s == NULL) {  		he_seterrev(ev, _HE_MALLOC_FAILED);  		return (-1);  	}  	(void) strlcpy(s, h->cursor->ev.str, len);  	(void) strlcat(s, str, len); -	/* LINTED const cast */ -	h_free((ptr_t) h->cursor->ev.str); -	h->cursor->ev.str = s; +	h_free((ptr_t)evp->str); +	evp->str = s;  	*ev = h->cursor->ev;  	return (0);  } +/* history_def_del(): + *	Delete element hp of the h list + */ +/* ARGSUSED */ +private int +history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)), +    const int num) +{ +	history_t *h = (history_t *) p; +	if (history_def_set(h, ev, num) != 0) +		return (-1); +	ev->str = strdup(h->cursor->ev.str); +	ev->num = h->cursor->ev.num; +	history_def_delete(h, ev, h->cursor); +	return (0); +} + +  /* history_def_delete():   *	Delete element hp of the h list   */  /* ARGSUSED */  private void -history_def_delete(history_t *h, HistEvent *ev, hentry_t *hp) +history_def_delete(history_t *h,  +		   HistEvent *ev __attribute__((__unused__)), hentry_t *hp)  { - +	HistEventPrivate *evp = (void *)&hp->ev;  	if (hp == &h->list)  		abort(); +	if (h->cursor == hp) +		h->cursor = hp->prev;  	hp->prev->next = hp->next;  	hp->next->prev = hp->prev; -	/* LINTED const cast */ -	h_free((ptr_t) hp->ev.str); +	h_free((ptr_t) evp->str);  	h_free(hp);  	h->cur--;  } @@ -377,11 +415,11 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str)  {  	h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); -	if (h->cursor) -		h->cursor->ev.str = strdup(str); -	if (!h->cursor || !h->cursor->ev.str) { -		he_seterrev(ev, _HE_MALLOC_FAILED); -		return (-1); +	if (h->cursor == NULL) +		goto oomem; +	if ((h->cursor->ev.str = h_strdup(str)) == NULL) { +		h_free((ptr_t)h->cursor); +		goto oomem;  	}  	h->cursor->ev.num = ++h->eventid;  	h->cursor->next = h->list.next; @@ -392,6 +430,9 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str)  	*ev = h->cursor->ev;  	return (0); +oomem: +	he_seterrev(ev, _HE_MALLOC_FAILED); +	return (-1);  } @@ -403,6 +444,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)  {  	history_t *h = (history_t *) p; +	if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && +	    strcmp(h->list.next->ev.str, str) == 0) +	    return (0);  +  	if (history_def_insert(h, ev, str) == -1)  		return (-1);	/* error, keep error message */ @@ -413,7 +458,7 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)  	while (h->cur > h->max && h->cur > 0)  		history_def_delete(h, ev, h->list.prev); -	return (0); +	return (1);  } @@ -421,10 +466,12 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str)   *	Default history initialization function   */  /* ARGSUSED */ -private void -history_def_init(ptr_t *p, HistEvent *ev, int n) +private int +history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n)  {  	history_t *h = (history_t *) h_malloc(sizeof(history_t)); +	if (h == NULL) +		return -1;  	if (n <= 0)  		n = 0; @@ -435,7 +482,9 @@ history_def_init(ptr_t *p, HistEvent *ev, int n)  	h->list.ev.str = NULL;  	h->list.ev.num = 0;  	h->cursor = &h->list; +	h->flags = 0;  	*p = (ptr_t) h; +	return 0;  } @@ -464,10 +513,15 @@ history_def_clear(ptr_t p, HistEvent *ev)  public History *  history_init(void)  { -	History *h = (History *) h_malloc(sizeof(History));  	HistEvent ev; +	History *h = (History *) h_malloc(sizeof(History)); +	if (h == NULL) +		return NULL; -	history_def_init(&h->h_ref, &ev, 0); +	if (history_def_init(&h->h_ref, &ev, 0) == -1) { +		h_free((ptr_t)h); +		return NULL; +	}  	h->h_ent = -1;  	h->h_next = history_def_next;  	h->h_first = history_def_first; @@ -478,6 +532,7 @@ history_init(void)  	h->h_clear = history_def_clear;  	h->h_enter = history_def_enter;  	h->h_add = history_def_add; +	h->h_del = history_def_del;  	return (h);  } @@ -493,6 +548,7 @@ history_end(History *h)  	if (h->h_next == history_def_next)  		history_def_clear(h->h_ref, &ev); +	h_free(h);  } @@ -523,18 +579,46 @@ history_setsize(History *h, HistEvent *ev, int num)  private int  history_getsize(History *h, HistEvent *ev)  { -	int retval = 0; -  	if (h->h_next != history_def_next) {  		he_seterrev(ev, _HE_NOT_ALLOWED);  		return (-1);  	} -	retval = history_def_getsize(h->h_ref); -	if (retval < -1) { +	ev->num = history_def_getsize(h->h_ref); +	if (ev->num < -1) {  		he_seterrev(ev, _HE_SIZE_NEGATIVE);  		return (-1);  	} -	ev->num = retval; +	return (0); +} + + +/* history_setunique(): + *	Set if adjacent equal events should not be entered in history. + */ +private int +history_setunique(History *h, HistEvent *ev, int uni) +{ + +	if (h->h_next != history_def_next) { +		he_seterrev(ev, _HE_NOT_ALLOWED); +		return (-1); +	} +	history_def_setunique(h->h_ref, uni); +	return (0); +} + + +/* history_getunique(): + *	Get if adjacent equal events should not be entered in history. + */ +private int +history_getunique(History *h, HistEvent *ev) +{ +	if (h->h_next != history_def_next) { +		he_seterrev(ev, _HE_NOT_ALLOWED); +		return (-1); +	} +	ev->num = history_def_getunique(h->h_ref);  	return (0);  } @@ -550,7 +634,7 @@ history_set_fun(History *h, History *nh)  	if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL ||  	    nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL ||  	    nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || -	    nh->h_ref == NULL) { +	    nh->h_del == NULL || nh->h_ref == NULL) {  		if (h->h_next != history_def_next) {  			history_def_init(&h->h_ref, &ev, 0);  			h->h_first = history_def_first; @@ -562,6 +646,7 @@ history_set_fun(History *h, History *nh)  			h->h_clear = history_def_clear;  			h->h_enter = history_def_enter;  			h->h_add = history_def_add; +			h->h_del = history_def_del;  		}  		return (-1);  	} @@ -578,6 +663,7 @@ history_set_fun(History *h, History *nh)  	h->h_clear = nh->h_clear;  	h->h_enter = nh->h_enter;  	h->h_add = nh->h_add; +	h->h_del = nh->h_del;  	return (0);  } @@ -606,6 +692,8 @@ history_load(History *h, const char *fname)  		goto done;  	ptr = h_malloc(max_size = 1024); +	if (ptr == NULL) +		goto done;  	for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {  		char c = line[sz]; @@ -615,15 +703,24 @@ history_load(History *h, const char *fname)  			line[sz] = '\0';  		if (max_size < sz) { -			max_size = (sz + 1023) & ~1023; -			ptr = h_realloc(ptr, max_size); +			char *nptr; +			max_size = (sz + 1024) & ~1023; +			nptr = h_realloc(ptr, max_size); +			if (nptr == NULL) { +				i = -1; +				goto oomem; +			} +			ptr = nptr;  		}  		(void) strunvis(ptr, line);  		line[sz] = c; -		HENTER(h, &ev, ptr); +		if (HENTER(h, &ev, ptr) == -1) { +			h_free((ptr_t)ptr); +			return -1; +		}  	} -	h_free(ptr); - +oomem: +	h_free((ptr_t)ptr);  done:  	(void) fclose(fp);  	return (i); @@ -638,28 +735,40 @@ history_save(History *h, const char *fname)  {  	FILE *fp;  	HistEvent ev; -	int i = 0, retval; +	int i = -1, retval;  	size_t len, max_size;  	char *ptr;  	if ((fp = fopen(fname, "w")) == NULL)  		return (-1); -	(void) fchmod(fileno(fp), S_IRUSR|S_IWUSR); -	(void) fputs(hist_cookie, fp); +	if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1) +		goto done; +	if (fputs(hist_cookie, fp) == EOF) +		goto done;  	ptr = h_malloc(max_size = 1024); -	for (retval = HLAST(h, &ev); +	if (ptr == NULL) +		goto done; +	for (i = 0, retval = HLAST(h, &ev);  	    retval != -1;  	    retval = HPREV(h, &ev), i++) {  		len = strlen(ev.str) * 4;  		if (len >= max_size) { -			max_size = (len + 1023) & 1023; -			ptr = h_realloc(ptr, max_size); +			char *nptr; +			max_size = (len + 1024) & ~1023; +			nptr = h_realloc(ptr, max_size); +			if (nptr == NULL) { +				i = -1; +				goto oomem; +			} +			ptr = nptr;  		}  		(void) strvis(ptr, ev.str, VIS_WHITE); -		(void) fprintf(fp, "%s\n", ev.str); +		(void) fprintf(fp, "%s\n", ptr);  	} -	h_free(ptr); +oomem: +	h_free((ptr_t)ptr); +done:  	(void) fclose(fp);  	return (i);  } @@ -758,11 +867,23 @@ history(History *h, HistEvent *ev, int fun, ...)  		retval = history_setsize(h, ev, va_arg(va, int));  		break; +	case H_GETUNIQUE: +		retval = history_getunique(h, ev); +		break; + +	case H_SETUNIQUE: +		retval = history_setunique(h, ev, va_arg(va, int)); +		break; +  	case H_ADD:  		str = va_arg(va, const char *);  		retval = HADD(h, ev, str);  		break; +	case H_DEL: +		retval = HDEL(h, ev, va_arg(va, const int)); +		break; +  	case H_ENTER:  		str = va_arg(va, const char *);  		if ((retval = HENTER(h, ev, str)) != -1) @@ -847,6 +968,7 @@ history(History *h, HistEvent *ev, int fun, ...)  		hf.h_clear = va_arg(va, history_vfun_t);  		hf.h_enter = va_arg(va, history_efun_t);  		hf.h_add = va_arg(va, history_efun_t); +		hf.h_del = va_arg(va, history_sfun_t);  		if ((retval = history_set_fun(h, &hf)) == -1)  			he_seterrev(ev, _HE_PARAM_MISSING); @@ -1,4 +1,4 @@ -/*	$NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $	*/ +/*	$NetBSD: key.c,v 1.16 2005/07/06 21:13:02 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,12 +32,12 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)key.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $"); +__RCSID("$NetBSD: key.c,v 1.16 2005/07/06 21:13:02 christos Exp $");  #endif  #endif /* not lint && not SCCSID */ @@ -66,7 +62,6 @@ __RCSID("$NetBSD: key.c,v 1.12 2001/05/17 01:02:17 christos Exp $");   *      1) It is not possible to have one key that is a   *	   substr of another.   */ -#include "sys.h"  #include <string.h>  #include <stdlib.h> @@ -90,9 +85,11 @@ private int		 node_trav(EditLine *, key_node_t *, char *,  private int		 node__try(EditLine *, key_node_t *, const char *,      key_value_t *, int);  private key_node_t	*node__get(int); +private void		 node__free(key_node_t *);  private void		 node__put(EditLine *, key_node_t *); -private int		 node__delete(EditLine *, key_node_t **, char *); -private int		 node_lookup(EditLine *, char *, key_node_t *, int); +private int		 node__delete(EditLine *, key_node_t **, const char *); +private int		 node_lookup(EditLine *, const char *, key_node_t *, +    int);  private int		 node_enum(EditLine *, key_node_t *, int);  private int		 key__decode_char(char *, int, int); @@ -114,7 +111,6 @@ key_init(EditLine *el)  	return (0);  } -  /* key_end():   *	Free the key maps   */ @@ -124,8 +120,7 @@ key_end(EditLine *el)  	el_free((ptr_t) el->el_key.buf);  	el->el_key.buf = NULL; -	/* XXX: provide a function to clear the keys */ -	el->el_key.map = NULL; +	node__free(el->el_key.map);  } @@ -219,7 +214,7 @@ key_add(EditLine *el, const char *key, key_value_t *val, int ntype)   *   */  protected void -key_clear(EditLine *el, el_action_t *map, char *in) +key_clear(EditLine *el, el_action_t *map, const char *in)  {  	if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && @@ -236,7 +231,7 @@ key_clear(EditLine *el, el_action_t *map, char *in)   *      they exists.   */  protected int -key_delete(EditLine *el, char *key) +key_delete(EditLine *el, const char *key)  {  	if (key[0] == '\0') { @@ -257,7 +252,7 @@ key_delete(EditLine *el, char *key)   *	Print entire el->el_key.map if null   */  protected void -key_print(EditLine *el, char *key) +key_print(EditLine *el, const char *key)  {  	/* do nothing if el->el_key.map is empty and null key specified */ @@ -356,7 +351,8 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int  			break;  		case XK_STR:  		case XK_EXE: -			ptr->val.str = strdup(val->str); +			if ((ptr->val.str = el_strdup(val->str)) == NULL) +				return -1;  			break;  		default:  			EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); @@ -376,7 +372,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int   *	Delete node that matches str   */  private int -node__delete(EditLine *el, key_node_t **inptr, char *str) +node__delete(EditLine *el, key_node_t **inptr, const char *str)  {  	key_node_t *ptr;  	key_node_t *prev_ptr = NULL; @@ -471,14 +467,22 @@ node__get(int ch)  	return (ptr);  } - +private void +node__free(key_node_t *k) +{ +	if (k == NULL) +		return; +	node__free(k->sibling); +	node__free(k->next); +	el_free((ptr_t) k); +}  /* node_lookup():   *	look for the str starting at node ptr.   *	Print if last node   */  private int -node_lookup(EditLine *el, char *str, key_node_t *ptr, int cnt) +node_lookup(EditLine *el, const char *str, key_node_t *ptr, int cnt)  {  	int ncnt; @@ -568,7 +572,7 @@ node_enum(EditLine *el, key_node_t *ptr, int cnt)   *	function specified by val   */  protected void -key_kprint(EditLine *el, char *key, key_value_t *val, int ntype) +key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype)  {  	el_bindings_t *fp;  	char unparsbuf[EL_BUFSIZ]; @@ -644,9 +648,10 @@ key__decode_char(char *buf, int cnt, int ch)   *	Make a printable version of the ey   */  protected char * -key__decode_str(char *str, char *buf, char *sep) +key__decode_str(const char *str, char *buf, const char *sep)  { -	char *b, *p; +	char *b; +	const char *p;  	b = buf;  	if (sep[0] != '\0') @@ -1,4 +1,4 @@ -/*	$NetBSD: key.h,v 1.5 2001/01/23 15:55:30 jdolecek Exp $	*/ +/*	$NetBSD: key.h,v 1.8 2003/08/07 16:44:32 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -62,6 +58,10 @@ typedef struct el_key_t {  #define	XK_NOD	2  #define	XK_EXE	3 +#undef key_end +#undef key_clear +#undef key_print +  protected int		 key_init(EditLine *);  protected void		 key_end(EditLine *);  protected key_value_t	*key_map_cmd(EditLine *, int); @@ -69,10 +69,11 @@ protected key_value_t	*key_map_str(EditLine *, char *);  protected void		 key_reset(EditLine *);  protected int		 key_get(EditLine *, char *, key_value_t *);  protected void		 key_add(EditLine *, const char *, key_value_t *, int); -protected void		 key_clear(EditLine *, el_action_t *, char *); -protected int		 key_delete(EditLine *, char *); -protected void		 key_print(EditLine *, char *); -protected void	         key_kprint(EditLine *, char *, key_value_t *, int); -protected char		*key__decode_str(char *, char *, char *); +protected void		 key_clear(EditLine *, el_action_t *, const char *); +protected int		 key_delete(EditLine *, const char *); +protected void		 key_print(EditLine *, const char *); +protected void	         key_kprint(EditLine *, const char *, key_value_t *, +    int); +protected char		*key__decode_str(const char *, char *, const char *);  #endif /* _h_el_key */ @@ -1,5 +1,5 @@  #!/bin/sh - -#	$NetBSD: makelist,v 1.7 2001/01/09 19:22:31 jdolecek Exp $ +#	$NetBSD: makelist,v 1.9 2005/05/16 13:14:43 lukem Exp $  #  # Copyright (c) 1992, 1993  #	The Regents of the University of California.  All rights reserved. @@ -15,11 +15,7 @@  # 2. Redistributions in binary form must reproduce the above copyright  #    notice, this list of conditions and the following disclaimer in the  #    documentation and/or other materials provided with the distribution. -# 3. All advertising materials mentioning features or use of this software -#    must display the following acknowledgement: -#	This product includes software developed by the University of -#	California, Berkeley and its contributors. -# 4. Neither the name of the University nor the names of its contributors +# 3. Neither the name of the University nor the names of its contributors  #    may be used to endorse or promote products derived from this software  #    without specific prior written permission.  # @@ -39,7 +35,7 @@  # makelist.sh: Automatically generate header files... -AWK=/usr/bin/awk +AWK=awk  USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m <filenames>"  if [ "x$1" = "x" ] @@ -1,4 +1,4 @@ -/*	$NetBSD: map.c,v 1.14 2001/01/09 17:22:09 jdolecek Exp $	*/ +/*	$NetBSD: map.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,25 +32,24 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)map.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: map.c,v 1.14 2001/01/09 17:22:09 jdolecek Exp $"); +__RCSID("$NetBSD: map.c,v 1.20 2004/08/13 12:10:39 mycroft Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * map.c: Editor function definitions   */ -#include "sys.h"  #include <stdlib.h>  #include "el.h"  #define	N_KEYS 256 -private void	map_print_key(EditLine *, el_action_t *, char *); +private void	map_print_key(EditLine *, el_action_t *, const char *);  private void	map_print_some_keys(EditLine *, el_action_t *, int, int);  private void	map_print_all_keys(EditLine *);  private void	map_init_nls(EditLine *); @@ -72,7 +67,7 @@ private const el_action_t  el_map_emacs[] = {  	/*   5 */	ED_MOVE_TO_END,		/* ^E */  	/*   6 */	ED_NEXT_CHAR,		/* ^F */  	/*   7 */	ED_UNASSIGNED,		/* ^G */ -	/*   8 */	ED_DELETE_PREV_CHAR,	/* ^H */ +	/*   8 */	EM_DELETE_PREV_CHAR,	/* ^H */  	/*   9 */	ED_UNASSIGNED,		/* ^I */  	/*  10 */	ED_NEWLINE,		/* ^J */  	/*  11 */	ED_KILL_LINE,		/* ^K */ @@ -191,7 +186,7 @@ private const el_action_t  el_map_emacs[] = {  	/* 124 */	ED_INSERT,		/* | */  	/* 125 */	ED_INSERT,		/* } */  	/* 126 */	ED_INSERT,		/* ~ */ -	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */ +	/* 127 */	EM_DELETE_PREV_CHAR,	/* ^? */  	/* 128 */	ED_UNASSIGNED,		/* M-^@ */  	/* 129 */	ED_UNASSIGNED,		/* M-^A */  	/* 130 */	ED_UNASSIGNED,		/* M-^B */ @@ -380,7 +375,7 @@ private const el_action_t  el_map_vi_insert[] = {  	/*   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 */ @@ -500,135 +495,135 @@ private const el_action_t  el_map_vi_insert[] = {  	/* 124 */	ED_INSERT,		/* | */  	/* 125 */	ED_INSERT,		/* } */  	/* 126 */	ED_INSERT,		/* ~ */ -	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */ -	/* 128 */	ED_UNASSIGNED,		/* M-^@ */ -	/* 129 */	ED_UNASSIGNED,		/* M-^A */ -	/* 130 */	ED_UNASSIGNED,		/* M-^B */ -	/* 131 */	ED_UNASSIGNED,		/* M-^C */ -	/* 132 */	ED_UNASSIGNED,		/* M-^D */ -	/* 133 */	ED_UNASSIGNED,		/* M-^E */ -	/* 134 */	ED_UNASSIGNED,		/* M-^F */ -	/* 135 */	ED_UNASSIGNED,		/* M-^G */ -	/* 136 */	ED_UNASSIGNED,		/* M-^H */ -	/* 137 */	ED_UNASSIGNED,		/* M-^I */ -	/* 138 */	ED_UNASSIGNED,		/* M-^J */ -	/* 139 */	ED_UNASSIGNED,		/* M-^K */ -	/* 140 */	ED_UNASSIGNED,		/* M-^L */ -	/* 141 */	ED_UNASSIGNED,		/* M-^M */ -	/* 142 */	ED_UNASSIGNED,		/* M-^N */ -	/* 143 */	ED_UNASSIGNED,		/* M-^O */ -	/* 144 */	ED_UNASSIGNED,		/* M-^P */ -	/* 145 */	ED_UNASSIGNED,		/* M-^Q */ -	/* 146 */	ED_UNASSIGNED,		/* M-^R */ -	/* 147 */	ED_UNASSIGNED,		/* M-^S */ -	/* 148 */	ED_UNASSIGNED,		/* M-^T */ -	/* 149 */	ED_UNASSIGNED,		/* M-^U */ -	/* 150 */	ED_UNASSIGNED,		/* M-^V */ -	/* 151 */	ED_UNASSIGNED,		/* M-^W */ -	/* 152 */	ED_UNASSIGNED,		/* M-^X */ -	/* 153 */	ED_UNASSIGNED,		/* M-^Y */ -	/* 154 */	ED_UNASSIGNED,		/* M-^Z */ -	/* 155 */	ED_UNASSIGNED,		/* M-^[ */ -	/* 156 */	ED_UNASSIGNED,		/* M-^\ */ -	/* 157 */	ED_UNASSIGNED,		/* M-^] */ -	/* 158 */	ED_UNASSIGNED,		/* M-^^ */ -	/* 159 */	ED_UNASSIGNED,		/* M-^_ */ -	/* 160 */	ED_UNASSIGNED,		/* M-SPACE */ -	/* 161 */	ED_UNASSIGNED,		/* M-! */ -	/* 162 */	ED_UNASSIGNED,		/* M-" */ -	/* 163 */	ED_UNASSIGNED,		/* M-# */ -	/* 164 */	ED_UNASSIGNED,		/* M-$ */ -	/* 165 */	ED_UNASSIGNED,		/* M-% */ -	/* 166 */	ED_UNASSIGNED,		/* M-& */ -	/* 167 */	ED_UNASSIGNED,		/* M-' */ -	/* 168 */	ED_UNASSIGNED,		/* M-( */ -	/* 169 */	ED_UNASSIGNED,		/* M-) */ -	/* 170 */	ED_UNASSIGNED,		/* M-* */ -	/* 171 */	ED_UNASSIGNED,		/* M-+ */ -	/* 172 */	ED_UNASSIGNED,		/* M-, */ -	/* 173 */	ED_UNASSIGNED,		/* M-- */ -	/* 174 */	ED_UNASSIGNED,		/* M-. */ -	/* 175 */	ED_UNASSIGNED,		/* M-/ */ -	/* 176 */	ED_UNASSIGNED,		/* M-0 */ -	/* 177 */	ED_UNASSIGNED,		/* M-1 */ -	/* 178 */	ED_UNASSIGNED,		/* M-2 */ -	/* 179 */	ED_UNASSIGNED,		/* M-3 */ -	/* 180 */	ED_UNASSIGNED,		/* M-4 */ -	/* 181 */	ED_UNASSIGNED,		/* M-5 */ -	/* 182 */	ED_UNASSIGNED,		/* M-6 */ -	/* 183 */	ED_UNASSIGNED,		/* M-7 */ -	/* 184 */	ED_UNASSIGNED,		/* M-8 */ -	/* 185 */	ED_UNASSIGNED,		/* M-9 */ -	/* 186 */	ED_UNASSIGNED,		/* M-: */ -	/* 187 */	ED_UNASSIGNED,		/* M-; */ -	/* 188 */	ED_UNASSIGNED,		/* M-< */ -	/* 189 */	ED_UNASSIGNED,		/* M-= */ -	/* 190 */	ED_UNASSIGNED,		/* M-> */ -	/* 191 */	ED_UNASSIGNED,		/* M-? */ -	/* 192 */	ED_UNASSIGNED,		/* M-@ */ -	/* 193 */	ED_UNASSIGNED,		/* M-A */ -	/* 194 */	ED_UNASSIGNED,		/* M-B */ -	/* 195 */	ED_UNASSIGNED,		/* M-C */ -	/* 196 */	ED_UNASSIGNED,		/* M-D */ -	/* 197 */	ED_UNASSIGNED,		/* M-E */ -	/* 198 */	ED_UNASSIGNED,		/* M-F */ -	/* 199 */	ED_UNASSIGNED,		/* M-G */ -	/* 200 */	ED_UNASSIGNED,		/* M-H */ -	/* 201 */	ED_UNASSIGNED,		/* M-I */ -	/* 202 */	ED_UNASSIGNED,		/* M-J */ -	/* 203 */	ED_UNASSIGNED,		/* M-K */ -	/* 204 */	ED_UNASSIGNED,		/* M-L */ -	/* 205 */	ED_UNASSIGNED,		/* M-M */ -	/* 206 */	ED_UNASSIGNED,		/* M-N */ -	/* 207 */	ED_UNASSIGNED,		/* M-O */ -	/* 208 */	ED_UNASSIGNED,		/* M-P */ -	/* 209 */	ED_UNASSIGNED,		/* M-Q */ -	/* 210 */	ED_UNASSIGNED,		/* M-R */ -	/* 211 */	ED_UNASSIGNED,		/* M-S */ -	/* 212 */	ED_UNASSIGNED,		/* M-T */ -	/* 213 */	ED_UNASSIGNED,		/* M-U */ -	/* 214 */	ED_UNASSIGNED,		/* M-V */ -	/* 215 */	ED_UNASSIGNED,		/* M-W */ -	/* 216 */	ED_UNASSIGNED,		/* M-X */ -	/* 217 */	ED_UNASSIGNED,		/* M-Y */ -	/* 218 */	ED_UNASSIGNED,		/* M-Z */ -	/* 219 */	ED_UNASSIGNED,		/* M-[ */ -	/* 220 */	ED_UNASSIGNED,		/* M-\ */ -	/* 221 */	ED_UNASSIGNED,		/* M-] */ -	/* 222 */	ED_UNASSIGNED,		/* M-^ */ -	/* 223 */	ED_UNASSIGNED,		/* M-_ */ -	/* 224 */	ED_UNASSIGNED,		/* M-` */ -	/* 225 */	ED_UNASSIGNED,		/* M-a */ -	/* 226 */	ED_UNASSIGNED,		/* M-b */ -	/* 227 */	ED_UNASSIGNED,		/* M-c */ -	/* 228 */	ED_UNASSIGNED,		/* M-d */ -	/* 229 */	ED_UNASSIGNED,		/* M-e */ -	/* 230 */	ED_UNASSIGNED,		/* M-f */ -	/* 231 */	ED_UNASSIGNED,		/* M-g */ -	/* 232 */	ED_UNASSIGNED,		/* M-h */ -	/* 233 */	ED_UNASSIGNED,		/* M-i */ -	/* 234 */	ED_UNASSIGNED,		/* M-j */ -	/* 235 */	ED_UNASSIGNED,		/* M-k */ -	/* 236 */	ED_UNASSIGNED,		/* M-l */ -	/* 237 */	ED_UNASSIGNED,		/* M-m */ -	/* 238 */	ED_UNASSIGNED,		/* M-n */ -	/* 239 */	ED_UNASSIGNED,		/* M-o */ -	/* 240 */	ED_UNASSIGNED,		/* M-p */ -	/* 241 */	ED_UNASSIGNED,		/* M-q */ -	/* 242 */	ED_UNASSIGNED,		/* M-r */ -	/* 243 */	ED_UNASSIGNED,		/* M-s */ -	/* 244 */	ED_UNASSIGNED,		/* M-t */ -	/* 245 */	ED_UNASSIGNED,		/* M-u */ -	/* 246 */	ED_UNASSIGNED,		/* M-v */ -	/* 247 */	ED_UNASSIGNED,		/* M-w */ -	/* 248 */	ED_UNASSIGNED,		/* M-x */ -	/* 249 */	ED_UNASSIGNED,		/* M-y */ -	/* 250 */	ED_UNASSIGNED,		/* M-z */ -	/* 251 */	ED_UNASSIGNED,		/* M-{ */ -	/* 252 */	ED_UNASSIGNED,		/* M-| */ -	/* 253 */	ED_UNASSIGNED,		/* M-} */ -	/* 254 */	ED_UNASSIGNED,		/* M-~ */ -	/* 255 */	ED_UNASSIGNED		/* M-^? */ +	/* 127 */	VI_DELETE_PREV_CHAR,	/* ^? */ +	/* 128 */	ED_INSERT,		/* M-^@ */ +	/* 129 */	ED_INSERT,		/* M-^A */ +	/* 130 */	ED_INSERT,		/* M-^B */ +	/* 131 */	ED_INSERT,		/* M-^C */ +	/* 132 */	ED_INSERT,		/* M-^D */ +	/* 133 */	ED_INSERT,		/* M-^E */ +	/* 134 */	ED_INSERT,		/* M-^F */ +	/* 135 */	ED_INSERT,		/* M-^G */ +	/* 136 */	ED_INSERT,		/* M-^H */ +	/* 137 */	ED_INSERT,		/* M-^I */ +	/* 138 */	ED_INSERT,		/* M-^J */ +	/* 139 */	ED_INSERT,		/* M-^K */ +	/* 140 */	ED_INSERT,		/* M-^L */ +	/* 141 */	ED_INSERT,		/* M-^M */ +	/* 142 */	ED_INSERT,		/* M-^N */ +	/* 143 */	ED_INSERT,		/* M-^O */ +	/* 144 */	ED_INSERT,		/* M-^P */ +	/* 145 */	ED_INSERT,		/* M-^Q */ +	/* 146 */	ED_INSERT,		/* M-^R */ +	/* 147 */	ED_INSERT,		/* M-^S */ +	/* 148 */	ED_INSERT,		/* M-^T */ +	/* 149 */	ED_INSERT,		/* M-^U */ +	/* 150 */	ED_INSERT,		/* M-^V */ +	/* 151 */	ED_INSERT,		/* M-^W */ +	/* 152 */	ED_INSERT,		/* M-^X */ +	/* 153 */	ED_INSERT,		/* M-^Y */ +	/* 154 */	ED_INSERT,		/* M-^Z */ +	/* 155 */	ED_INSERT,		/* M-^[ */ +	/* 156 */	ED_INSERT,		/* M-^\ */ +	/* 157 */	ED_INSERT,		/* M-^] */ +	/* 158 */	ED_INSERT,		/* M-^^ */ +	/* 159 */	ED_INSERT,		/* M-^_ */ +	/* 160 */	ED_INSERT,		/* M-SPACE */ +	/* 161 */	ED_INSERT,		/* M-! */ +	/* 162 */	ED_INSERT,		/* M-" */ +	/* 163 */	ED_INSERT,		/* M-# */ +	/* 164 */	ED_INSERT,		/* M-$ */ +	/* 165 */	ED_INSERT,		/* M-% */ +	/* 166 */	ED_INSERT,		/* M-& */ +	/* 167 */	ED_INSERT,		/* M-' */ +	/* 168 */	ED_INSERT,		/* M-( */ +	/* 169 */	ED_INSERT,		/* M-) */ +	/* 170 */	ED_INSERT,		/* M-* */ +	/* 171 */	ED_INSERT,		/* M-+ */ +	/* 172 */	ED_INSERT,		/* M-, */ +	/* 173 */	ED_INSERT,		/* M-- */ +	/* 174 */	ED_INSERT,		/* M-. */ +	/* 175 */	ED_INSERT,		/* M-/ */ +	/* 176 */	ED_INSERT,		/* M-0 */ +	/* 177 */	ED_INSERT,		/* M-1 */ +	/* 178 */	ED_INSERT,		/* M-2 */ +	/* 179 */	ED_INSERT,		/* M-3 */ +	/* 180 */	ED_INSERT,		/* M-4 */ +	/* 181 */	ED_INSERT,		/* M-5 */ +	/* 182 */	ED_INSERT,		/* M-6 */ +	/* 183 */	ED_INSERT,		/* M-7 */ +	/* 184 */	ED_INSERT,		/* M-8 */ +	/* 185 */	ED_INSERT,		/* M-9 */ +	/* 186 */	ED_INSERT,		/* M-: */ +	/* 187 */	ED_INSERT,		/* M-; */ +	/* 188 */	ED_INSERT,		/* M-< */ +	/* 189 */	ED_INSERT,		/* M-= */ +	/* 190 */	ED_INSERT,		/* M-> */ +	/* 191 */	ED_INSERT,		/* M-? */ +	/* 192 */	ED_INSERT,		/* M-@ */ +	/* 193 */	ED_INSERT,		/* M-A */ +	/* 194 */	ED_INSERT,		/* M-B */ +	/* 195 */	ED_INSERT,		/* M-C */ +	/* 196 */	ED_INSERT,		/* M-D */ +	/* 197 */	ED_INSERT,		/* M-E */ +	/* 198 */	ED_INSERT,		/* M-F */ +	/* 199 */	ED_INSERT,		/* M-G */ +	/* 200 */	ED_INSERT,		/* M-H */ +	/* 201 */	ED_INSERT,		/* M-I */ +	/* 202 */	ED_INSERT,		/* M-J */ +	/* 203 */	ED_INSERT,		/* M-K */ +	/* 204 */	ED_INSERT,		/* M-L */ +	/* 205 */	ED_INSERT,		/* M-M */ +	/* 206 */	ED_INSERT,		/* M-N */ +	/* 207 */	ED_INSERT,		/* M-O */ +	/* 208 */	ED_INSERT,		/* M-P */ +	/* 209 */	ED_INSERT,		/* M-Q */ +	/* 210 */	ED_INSERT,		/* M-R */ +	/* 211 */	ED_INSERT,		/* M-S */ +	/* 212 */	ED_INSERT,		/* M-T */ +	/* 213 */	ED_INSERT,		/* M-U */ +	/* 214 */	ED_INSERT,		/* M-V */ +	/* 215 */	ED_INSERT,		/* M-W */ +	/* 216 */	ED_INSERT,		/* M-X */ +	/* 217 */	ED_INSERT,		/* M-Y */ +	/* 218 */	ED_INSERT,		/* M-Z */ +	/* 219 */	ED_INSERT,		/* M-[ */ +	/* 220 */	ED_INSERT,		/* M-\ */ +	/* 221 */	ED_INSERT,		/* M-] */ +	/* 222 */	ED_INSERT,		/* M-^ */ +	/* 223 */	ED_INSERT,		/* M-_ */ +	/* 224 */	ED_INSERT,		/* M-` */ +	/* 225 */	ED_INSERT,		/* M-a */ +	/* 226 */	ED_INSERT,		/* M-b */ +	/* 227 */	ED_INSERT,		/* M-c */ +	/* 228 */	ED_INSERT,		/* M-d */ +	/* 229 */	ED_INSERT,		/* M-e */ +	/* 230 */	ED_INSERT,		/* M-f */ +	/* 231 */	ED_INSERT,		/* M-g */ +	/* 232 */	ED_INSERT,		/* M-h */ +	/* 233 */	ED_INSERT,		/* M-i */ +	/* 234 */	ED_INSERT,		/* M-j */ +	/* 235 */	ED_INSERT,		/* M-k */ +	/* 236 */	ED_INSERT,		/* M-l */ +	/* 237 */	ED_INSERT,		/* M-m */ +	/* 238 */	ED_INSERT,		/* M-n */ +	/* 239 */	ED_INSERT,		/* M-o */ +	/* 240 */	ED_INSERT,		/* M-p */ +	/* 241 */	ED_INSERT,		/* M-q */ +	/* 242 */	ED_INSERT,		/* M-r */ +	/* 243 */	ED_INSERT,		/* M-s */ +	/* 244 */	ED_INSERT,		/* M-t */ +	/* 245 */	ED_INSERT,		/* M-u */ +	/* 246 */	ED_INSERT,		/* M-v */ +	/* 247 */	ED_INSERT,		/* M-w */ +	/* 248 */	ED_INSERT,		/* M-x */ +	/* 249 */	ED_INSERT,		/* M-y */ +	/* 250 */	ED_INSERT,		/* M-z */ +	/* 251 */	ED_INSERT,		/* M-{ */ +	/* 252 */	ED_INSERT,		/* M-| */ +	/* 253 */	ED_INSERT,		/* M-} */ +	/* 254 */	ED_INSERT,		/* M-~ */ +	/* 255 */	ED_INSERT		/* M-^? */  };  private const el_action_t el_map_vi_command[] = { @@ -640,7 +635,7 @@ private const el_action_t el_map_vi_command[] = {  	/*   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 */ @@ -667,9 +662,9 @@ private const el_action_t el_map_vi_command[] = {  	/*  32 */	ED_NEXT_CHAR,		/* SPACE */  	/*  33 */	ED_UNASSIGNED,		/* ! */  	/*  34 */	ED_UNASSIGNED,		/* " */ -	/*  35 */	ED_UNASSIGNED,		/* # */ +	/*  35 */	VI_COMMENT_OUT,		/* # */  	/*  36 */	ED_MOVE_TO_END,		/* $ */ -	/*  37 */	ED_UNASSIGNED,		/* % */ +	/*  37 */	VI_MATCH,		/* % */  	/*  38 */	ED_UNASSIGNED,		/* & */  	/*  39 */	ED_UNASSIGNED,		/* ' */  	/*  40 */	ED_UNASSIGNED,		/* ( */ @@ -678,7 +673,7 @@ private const el_action_t el_map_vi_command[] = {  	/*  43 */	ED_NEXT_HISTORY,	/* + */  	/*  44 */	VI_REPEAT_PREV_CHAR,	/* , */  	/*  45 */	ED_PREV_HISTORY,	/* - */ -	/*  46 */	ED_UNASSIGNED,		/* . */ +	/*  46 */	VI_REDO,		/* . */  	/*  47 */	VI_SEARCH_PREV,		/* / */  	/*  48 */	VI_ZERO,		/* 0 */  	/*  49 */	ED_ARGUMENT_DIGIT,	/* 1 */ @@ -696,14 +691,14 @@ private const el_action_t el_map_vi_command[] = {  	/*  61 */	ED_UNASSIGNED,		/* = */  	/*  62 */	ED_UNASSIGNED,		/* > */  	/*  63 */	VI_SEARCH_NEXT,		/* ? */ -	/*  64 */	ED_UNASSIGNED,		/* @ */ +	/*  64 */	VI_ALIAS,		/* @ */  	/*  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 */ +	/*  71 */	VI_TO_HISTORY_LINE,	/* G */  	/*  72 */	ED_UNASSIGNED,		/* H */  	/*  73 */	VI_INSERT_AT_BOL,	/* I */  	/*  74 */	ED_SEARCH_NEXT_HISTORY,	/* J */ @@ -717,17 +712,17 @@ private const el_action_t el_map_vi_command[] = {  	/*  82 */	VI_REPLACE_MODE,	/* R */  	/*  83 */	VI_SUBSTITUTE_LINE,	/* S */  	/*  84 */	VI_TO_PREV_CHAR,	/* T */ -	/*  85 */	ED_UNASSIGNED,		/* U */ +	/*  85 */	VI_UNDO_LINE,		/* 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 */ +	/*  89 */	VI_YANK_END,		/* Y */  	/*  90 */	ED_UNASSIGNED,		/* Z */  	/*  91 */	ED_SEQUENCE_LEAD_IN,	/* [ */  	/*  92 */	ED_UNASSIGNED,		/* \ */  	/*  93 */	ED_UNASSIGNED,		/* ] */  	/*  94 */	ED_MOVE_TO_BEG,		/* ^ */ -	/*  95 */	ED_UNASSIGNED,		/* _ */ +	/*  95 */	VI_HISTORY_WORD,	/* _ */  	/*  96 */	ED_UNASSIGNED,		/* ` */  	/*  97 */	VI_ADD,			/* a */  	/*  98 */	VI_PREV_WORD,		/* b */ @@ -750,13 +745,13 @@ private const el_action_t el_map_vi_command[] = {  	/* 115 */	VI_SUBSTITUTE_CHAR,	/* s */  	/* 116 */	VI_TO_NEXT_CHAR,	/* t */  	/* 117 */	VI_UNDO,		/* u */ -	/* 118 */	ED_UNASSIGNED,		/* v */ +	/* 118 */	VI_HISTEDIT,		/* v */  	/* 119 */	VI_NEXT_WORD,		/* w */  	/* 120 */	ED_DELETE_NEXT_CHAR,	/* x */ -	/* 121 */	ED_UNASSIGNED,		/* y */ +	/* 121 */	VI_YANK,		/* y */  	/* 122 */	ED_UNASSIGNED,		/* z */  	/* 123 */	ED_UNASSIGNED,		/* { */ -	/* 124 */	ED_UNASSIGNED,		/* | */ +	/* 124 */	VI_TO_COLUMN,		/* | */  	/* 125 */	ED_UNASSIGNED,		/* } */  	/* 126 */	VI_CHANGE_CASE,		/* ~ */  	/* 127 */	ED_DELETE_PREV_CHAR,	/* ^? */ @@ -1127,7 +1122,7 @@ map_get_editor(EditLine *el, const char **editor)   *	Print the function description for 1 key   */  private void -map_print_key(EditLine *el, el_action_t *map, char *in) +map_print_key(EditLine *el, el_action_t *map, const char *in)  {  	char outbuf[EL_BUFSIZ];  	el_bindings_t *bp; @@ -1240,14 +1235,14 @@ map_print_all_keys(EditLine *el)   *	Add/remove/change bindings   */  protected int -map_bind(EditLine *el, int argc, char **argv) +map_bind(EditLine *el, int argc, const char **argv)  {  	el_action_t *map;  	int ntype, rem; -	char *p; +	const char *p;  	char inbuf[EL_BUFSIZ];  	char outbuf[EL_BUFSIZ]; -	char *in = NULL; +	const char *in = NULL;  	char *out = NULL;  	el_bindings_t *bp;  	int cmd; @@ -1,4 +1,4 @@ -/*	$NetBSD: map.h,v 1.6 2001/01/09 17:22:09 jdolecek Exp $	*/ +/*	$NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -67,7 +63,7 @@ typedef struct el_map_t {  #define	MAP_EMACS	0  #define	MAP_VI		1 -protected int	map_bind(EditLine *, int, char **); +protected int	map_bind(EditLine *, int, const char **);  protected int	map_init(EditLine *);  protected void	map_end(EditLine *);  protected void	map_init_vi(EditLine *); @@ -1,4 +1,4 @@ -/*	$NetBSD: parse.c,v 1.14 2001/01/23 15:55:30 jdolecek Exp $	*/ +/*	$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,12 +32,12 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: parse.c,v 1.14 2001/01/23 15:55:30 jdolecek Exp $"); +__RCSID("$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $");  #endif  #endif /* not lint && not SCCSID */ @@ -58,19 +54,17 @@ __RCSID("$NetBSD: parse.c,v 1.14 2001/01/23 15:55:30 jdolecek Exp $");   *	settc   *	setty   */ -#include "sys.h"  #include "el.h" -#include "tokenizer.h"  #include <stdlib.h>  private const struct { -	char *name; -	int (*func)(EditLine *, int, char **); +	const char *name; +	int (*func)(EditLine *, int, const char **);  } cmds[] = {  	{ "bind",	map_bind	},  	{ "echotc",	term_echotc	},  	{ "edit",	el_editmode	}, -	{ "history",	hist_list	}, +	{ "history",	hist_command	},  	{ "telltc",	term_telltc	},  	{ "settc",	term_settc	},  	{ "setty",	tty_stty	}, @@ -84,12 +78,12 @@ private const struct {  protected int  parse_line(EditLine *el, const char *line)  { -	char **argv; +	const char **argv;  	int argc;  	Tokenizer *tok;  	tok = tok_init(NULL); -	tok_line(tok, line, &argc, &argv); +	tok_str(tok, line, &argc, &argv);  	argc = el_parse(el, argc, argv);  	tok_end(tok);  	return (argc); @@ -100,9 +94,9 @@ parse_line(EditLine *el, const char *line)   *	Command dispatcher   */  public int -el_parse(EditLine *el, int argc, char *argv[]) +el_parse(EditLine *el, int argc, const char *argv[])  { -	char *ptr; +	const char *ptr;  	int i;  	if (argc < 1) @@ -142,7 +136,7 @@ el_parse(EditLine *el, int argc, char *argv[])   *	the appropriate character or -1 if the escape is not valid   */  protected int -parse__escape(const char **const ptr) +parse__escape(const char **ptr)  {  	const char *p;  	int c; @@ -207,7 +201,7 @@ parse__escape(const char **const ptr)  			c = *p;  			break;  		} -	} else if (*p == '^' && isalpha((unsigned char) p[1])) { +	} else if (*p == '^') {  		p++;  		c = (*p == '?') ? '\177' : (*p & 0237);  	} else @@ -215,6 +209,7 @@ parse__escape(const char **const ptr)  	*ptr = ++p;  	return (c);  } +  /* parse__string():   *	Parse the escapes from in and put the raw string out   */ @@ -237,6 +232,14 @@ parse__string(char *out, const char *in)  			*out++ = n;  			break; +		case 'M': +			if (in[1] == '-' && in[2] != '\0') { +				*out++ = '\033'; +				in += 2; +				break; +			} +			/*FALLTHROUGH*/ +  		default:  			*out++ = *in++;  			break; @@ -1,4 +1,4 @@ -/*	$NetBSD: parse.h,v 1.4 2000/09/04 22:06:31 lukem Exp $	*/ +/*	$NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -45,7 +41,7 @@  #define	_h_el_parse  protected int	 parse_line(EditLine *, const char *); -protected int	 parse__escape(const char ** const); +protected int	 parse__escape(const char **);  protected char	*parse__string(char *, const char *);  protected int	 parse_cmd(EditLine *, const char *); @@ -1,4 +1,4 @@ -/*	$NetBSD: prompt.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $	*/ +/*	$NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)prompt.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: prompt.c,v 1.8 2001/01/10 07:45:41 jdolecek Exp $"); +__RCSID("$NetBSD: prompt.c,v 1.11 2003/08/07 16:44:32 agc Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * prompt.c: Prompt printing functions   */ -#include "sys.h"  #include <stdio.h>  #include "el.h" @@ -60,7 +55,7 @@ private char	*prompt_default_r(EditLine *);   */  private char *  /*ARGSUSED*/ -prompt_default(EditLine *el) +prompt_default(EditLine *el __attribute__((__unused__)))  {  	static char a[3] = {'?', ' ', '\0'}; @@ -73,7 +68,7 @@ prompt_default(EditLine *el)   */  private char *  /*ARGSUSED*/ -prompt_default_r(EditLine *el) +prompt_default_r(EditLine *el __attribute__((__unused__)))  {  	static char a[1] = {'\0'}; @@ -128,7 +123,7 @@ prompt_init(EditLine *el)   */  protected void  /*ARGSUSED*/ -prompt_end(EditLine *el) +prompt_end(EditLine *el __attribute__((__unused__)))  {  } @@ -1,4 +1,4 @@ -/*	$NetBSD: prompt.h,v 1.5 2000/09/04 22:06:31 lukem Exp $	*/ +/*	$NetBSD: prompt.h,v 1.6 2003/08/07 16:44:32 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -1,4 +1,4 @@ -/*	$NetBSD: read.c,v 1.20 2001/09/27 19:29:50 christos Exp $	*/ +/*	$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,12 +32,12 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)read.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: read.c,v 1.20 2001/09/27 19:29:50 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $");  #endif  #endif /* not lint && not SCCSID */ @@ -49,8 +45,8 @@ __RCSID("$NetBSD: read.c,v 1.20 2001/09/27 19:29:50 christos Exp $");   * read.c: Clean this junk up! This is horrible code.   *	   Terminal read functions   */ -#include "sys.h"  #include <errno.h> +#include <fcntl.h>  #include <unistd.h>  #include <stdlib.h>  #include "el.h" @@ -98,6 +94,10 @@ el_read_getfn(EditLine *el)  } +#ifndef MIN +#define MIN(A,B) ((A) < (B) ? (A) : (B)) +#endif +  #ifdef DEBUG_EDIT  private void  read_debug(EditLine *el) @@ -122,7 +122,7 @@ read_debug(EditLine *el)   */  /* ARGSUSED */  private int -read__fixio(int fd, int e) +read__fixio(int fd __attribute__((__unused__)), int e)  {  	switch (e) { @@ -187,10 +187,6 @@ read_preread(EditLine *el)  {  	int chrs = 0; -	if (el->el_chared.c_macro.nline) { -		el_free((ptr_t) el->el_chared.c_macro.nline); -		el->el_chared.c_macro.nline = NULL; -	}  	if (el->el_tty.t_mode == ED_IO)  		return (0); @@ -203,8 +199,7 @@ read_preread(EditLine *el)  		    (size_t) MIN(chrs, EL_BUFSIZ - 1));  		if (chrs > 0) {  			buf[chrs] = '\0'; -			el->el_chared.c_macro.nline = strdup(buf); -			el_push(el, el->el_chared.c_macro.nline); +			el_push(el, buf);  		}  	}  #endif /* FIONREAD */ @@ -217,18 +212,18 @@ read_preread(EditLine *el)   *	Push a macro   */  public void -el_push(EditLine *el, const char *str) +el_push(EditLine *el, char *str)  {  	c_macro_t *ma = &el->el_chared.c_macro;  	if (str != NULL && ma->level + 1 < EL_MAXMACRO) {  		ma->level++; -		/* LINTED const cast */ -		ma->macro[ma->level] = (char *) str; -	} else { -		term_beep(el); -		term__flush(); +		if ((ma->macro[ma->level] = el_strdup(str)) != NULL) +			return; +		ma->level--;  	} +	term_beep(el); +	term__flush();  } @@ -238,10 +233,10 @@ el_push(EditLine *el, const char *str)  private int  read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)  { -	el_action_t cmd = ED_UNASSIGNED; +	el_action_t cmd;  	int num; -	while (cmd == ED_UNASSIGNED || cmd == ED_SEQUENCE_LEAD_IN) { +	do {  		if ((num = el_getc(el, ch)) != 1)	/* if EOF or error */  			return (num); @@ -280,7 +275,7 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)  		}  		if (el->el_map.alt == NULL)  			el->el_map.current = el->el_map.key; -	} +	} while (cmd == ED_SEQUENCE_LEAD_IN);  	*cmdnum = cmd;  	return (OKCMD);  } @@ -325,14 +320,16 @@ el_getc(EditLine *el, char *cp)  		if (ma->level < 0)  			break; -		if (*ma->macro[ma->level] == 0) { -			ma->level--; +		if (ma->macro[ma->level][ma->offset] == '\0') { +			el_free(ma->macro[ma->level--]); +			ma->offset = 0;  			continue;  		} -		*cp = *ma->macro[ma->level]++ & 0377; -		if (*ma->macro[ma->level] == 0) {	/* Needed for QuoteMode -							 * On */ -			ma->level--; +		*cp = ma->macro[ma->level][ma->offset++] & 0377; +		if (ma->macro[ma->level][ma->offset] == '\0') { +			/* Needed for QuoteMode On */ +			el_free(ma->macro[ma->level--]); +			ma->offset = 0;  		}  		return (1);  	} @@ -353,6 +350,35 @@ el_getc(EditLine *el, char *cp)  	return (num_read);  } +protected void +read_prepare(EditLine *el) +{ +	if (el->el_flags & HANDLE_SIGNALS) +		sig_set(el); +	if (el->el_flags & NO_TTY) +		return; +	if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) +		tty_rawmode(el); + +	/* 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, 0); +	re_refresh(el);		/* print the prompt */ + +	if (el->el_flags & UNBUFFERED) +		term__flush(); +} + +protected void +read_finish(EditLine *el) +{ +	if ((el->el_flags & UNBUFFERED) == 0) +		(void) tty_cookedmode(el); +	if (el->el_flags & HANDLE_SIGNALS) +		sig_clr(el); +}  public const char *  el_gets(EditLine *el, int *nread) @@ -361,13 +387,11 @@ el_gets(EditLine *el, int *nread)  	el_action_t cmdnum = 0;  	int num;		/* how many chars we have read at NL */  	char ch; +	int crlf = 0;  #ifdef FIONREAD  	c_macro_t *ma = &el->el_chared.c_macro;  #endif /* FIONREAD */ -	if (el->el_flags & HANDLE_SIGNALS) -		sig_set(el); -  	if (el->el_flags & NO_TTY) {  		char *cp = el->el_line.buffer;  		size_t idx; @@ -381,6 +405,8 @@ el_gets(EditLine *el, int *nread)  				cp = &el->el_line.buffer[idx];  			}  			cp++; +			if (el->el_flags & UNBUFFERED) +				break;  			if (cp[-1] == '\r' || cp[-1] == '\n')  				break;  		} @@ -391,8 +417,7 @@ el_gets(EditLine *el, int *nread)  			*nread = el->el_line.cursor - el->el_line.buffer;  		return (el->el_line.buffer);  	} -	re_clear_display(el);	/* reset the display stuff */ -	ch_reset(el); +  #ifdef FIONREAD  	if (el->el_tty.t_mode == EX_IO && ma->level < 0) { @@ -409,11 +434,16 @@ el_gets(EditLine *el, int *nread)  	}  #endif /* FIONREAD */ -	re_refresh(el);		/* print the prompt */ +	if ((el->el_flags & UNBUFFERED) == 0) +		read_prepare(el);  	if (el->el_flags & EDIT_DISABLED) { -		char *cp = el->el_line.buffer; +		char *cp;  		size_t idx; +		if ((el->el_flags & UNBUFFERED) == 0) +			cp = el->el_line.buffer; +		else +			cp = el->el_line.lastchar;  		term__flush(); @@ -425,8 +455,13 @@ el_gets(EditLine *el, int *nread)  					break;  				cp = &el->el_line.buffer[idx];  			} +			if (*cp == 4)	/* ought to be stty eof */ +				break;  			cp++; -			if (cp[-1] == '\r' || cp[-1] == '\n') +			crlf = cp[-1] == '\r' || cp[-1] == '\n'; +			if (el->el_flags & UNBUFFERED) +				break; +			if (crlf)  				break;  		} @@ -436,6 +471,7 @@ el_gets(EditLine *el, int *nread)  			*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 @@ -449,7 +485,7 @@ el_gets(EditLine *el, int *nread)  #endif /* DEBUG_READ */  			break;  		} -		if ((int) cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */ +		if ((unsigned int)cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */  #ifdef DEBUG_EDIT  			(void) fprintf(el->el_errfile,  			    "ERROR: illegal command from key 0%o\r\n", ch); @@ -471,7 +507,24 @@ el_gets(EditLine *el, int *nread)  				    "Error command = %d\n", cmdnum);  		}  #endif /* DEBUG_READ */ +		/* vi redo needs these way down the levels... */ +		el->el_state.thiscmd = cmdnum; +		el->el_state.thisch = ch; +		if (el->el_map.type == MAP_VI && +		    el->el_map.current == el->el_map.key && +		    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 +			    && isprint((unsigned char)el->el_chared.c_redo.pos[-1])) +				el->el_chared.c_redo.pos--; +			else +				*el->el_chared.c_redo.pos++ = ch; +		}  		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; @@ -479,8 +532,6 @@ el_gets(EditLine *el, int *nread)  		/* use any return value */  		switch (retval) {  		case CC_CURSOR: -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			re_refresh_cursor(el);  			break; @@ -490,29 +541,29 @@ el_gets(EditLine *el, int *nread)  			/* FALLTHROUGH */  		case CC_REFRESH: -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			re_refresh(el);  			break;  		case CC_REFRESH_BEEP: -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			re_refresh(el);  			term_beep(el);  			break;  		case CC_NORM:	/* normal char */ -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			break;  		case CC_ARGHACK:	/* Suggested by Rich Salz */  			/* <rsalz@pineapple.bbn.com> */ -			break;	/* keep going... */ +			continue;	/* keep going... */  		case CC_EOF:	/* end of file typed */ -			num = 0; +			if ((el->el_flags & UNBUFFERED) == 0) +				num = 0; +			else if (num == -1) { +				*el->el_line.lastchar++ = CONTROL('d'); +				el->el_line.cursor = el->el_line.lastchar; +				num = 1; +			}  			break;  		case CC_NEWLINE:	/* normal end of line */ @@ -526,10 +577,8 @@ el_gets(EditLine *el, int *nread)  #endif /* DEBUG_READ */  			/* put (real) cursor in a known place */  			re_clear_display(el);	/* reset the display stuff */ -			ch_reset(el);	/* reset the input pointers */ +			ch_reset(el, 1);	/* reset the input pointers */  			re_refresh(el);	/* print the prompt again */ -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			break;  		case CC_ERROR: @@ -538,20 +587,26 @@ el_gets(EditLine *el, int *nread)  			(void) fprintf(el->el_errfile,  			    "*** editor ERROR ***\r\n\n");  #endif /* DEBUG_READ */ -			el->el_state.argument = 1; -			el->el_state.doingarg = 0;  			term_beep(el);  			term__flush();  			break;  		} +		el->el_state.argument = 1; +		el->el_state.doingarg = 0; +		el->el_chared.c_vcmd.action = NOP; +		if (el->el_flags & UNBUFFERED) +			break;  	} -				/* make sure the tty is set up correctly */ -	(void) tty_cookedmode(el);  	term__flush();		/* flush any buffered output */ -	if (el->el_flags & HANDLE_SIGNALS) -		sig_clr(el); -	if (nread) -		*nread = num; +	/* make sure the tty is set up correctly */ +	if ((el->el_flags & UNBUFFERED) == 0) { +		read_finish(el); +		if (nread) +			*nread = num; +	} else { +		if (nread) +			*nread = el->el_line.lastchar - el->el_line.buffer; +	}  	return (num ? el->el_line.buffer : NULL);  } @@ -1,4 +1,4 @@ -/*	$NetBSD: read.h,v 1.1 2001/09/27 19:29:50 christos Exp $	*/ +/*	$NetBSD: read.h,v 1.4 2004/02/27 14:52:18 christos Exp $	*/  /*-   * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -49,6 +49,8 @@ typedef struct el_read_t {  } el_read_t;  protected int		read_init(EditLine *); +protected void		read_prepare(EditLine *); +protected void		read_finish(EditLine *);  protected int		el_read_setfn(EditLine *, el_rfunc_t);  protected el_rfunc_t	el_read_getfn(EditLine *); diff --git a/readline.c b/readline.c index 660697622402..7c752d12dfc1 100644 --- a/readline.c +++ b/readline.c @@ -1,4 +1,4 @@ -/*	$NetBSD: readline.c,v 1.19 2001/01/10 08:10:45 jdolecek Exp $	*/ +/*	$NetBSD: readline.c,v 1.58 2005/07/14 15:00:58 christos Exp $	*/  /*-   * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -36,9 +36,9 @@   * POSSIBILITY OF SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.19 2001/01/10 08:10:45 jdolecek Exp $"); +__RCSID("$NetBSD: readline.c,v 1.58 2005/07/14 15:00:58 christos Exp $");  #endif /* not lint && not SCCSID */  #include <sys/types.h> @@ -51,45 +51,80 @@ __RCSID("$NetBSD: readline.c,v 1.19 2001/01/10 08:10:45 jdolecek Exp $");  #include <stdlib.h>  #include <unistd.h>  #include <limits.h> -#include "histedit.h" -#include "readline/readline.h" -#include "sys.h" +#include <errno.h> +#include <fcntl.h> +#ifdef HAVE_VIS_H +#include <vis.h> +#else +#include "np/vis.h" +#endif +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif  #include "el.h"  #include "fcns.h"		/* for EL_NUM_FCNS */ +#include "histedit.h" +#include "readline/readline.h" +#include "filecomplete.h"  /* for rl_complete() */ -#define	TAB		'\r' +#define TAB		'\r'  /* see comment at the #ifdef for sense of this */ -#define	GDB_411_HACK +/* #define GDB_411_HACK */  /* readline compatibility stuff - look at readline sources/documentation */  /* to see what these variables mean */  const char *rl_library_version = "EditLine wrapper"; -char *rl_readline_name = ""; +static char empty[] = { '\0' }; +static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' }; +static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', +    '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; +char *rl_readline_name = empty;  FILE *rl_instream = NULL;  FILE *rl_outstream = NULL;  int rl_point = 0;  int rl_end = 0;  char *rl_line_buffer = NULL; +VCPFunction *rl_linefunc = NULL; +int rl_done = 0; +VFunction *rl_event_hook = NULL;  int history_base = 1;		/* probably never subject to change */  int history_length = 0;  int max_input_history = 0;  char history_expansion_char = '!';  char history_subst_char = '^'; -char *history_no_expand_chars = " \t\n=("; +char *history_no_expand_chars = expand_chars;  Function *history_inhibit_expansion_function = NULL; +char *history_arg_extract(int start, int end, const char *str);  int rl_inhibit_completion = 0;  int rl_attempted_completion_over = 0; -char *rl_basic_word_break_characters = " \t\n\"\\'`@$><=;|&{("; +char *rl_basic_word_break_characters = break_chars;  char *rl_completer_word_break_characters = NULL;  char *rl_completer_quote_characters = NULL; -CPFunction *rl_completion_entry_function = NULL; +Function *rl_completion_entry_function = NULL;  CPPFunction *rl_attempted_completion_function = NULL; +Function *rl_pre_input_hook = NULL; +Function *rl_startup1_hook = NULL; +Function *rl_getc_function = NULL; +char *rl_terminal_name = NULL; +int rl_already_prompted = 0; +int rl_filename_completion_desired = 0; +int rl_ignore_completion_duplicates = 0; +int rl_catch_signals = 1; +VFunction *rl_redisplay_function = NULL; +Function *rl_startup_hook = NULL; +VFunction *rl_completion_display_matches_hook = NULL; +VFunction *rl_prep_term_function = NULL; +VFunction *rl_deprep_term_function = NULL;  /* + * The current prompt string. + */ +char *rl_prompt = NULL; +/*   * This is set to character indicating type of completion being done by   * rl_complete_internal(); this is available for application completion   * functions. @@ -107,7 +142,7 @@ int rl_completion_query_items = 100;   * in the parsed text when it is passed to the completion function.   * Shell uses this to help determine what kind of completing to do.   */ -char *rl_special_prefixes = (char *)NULL; +char *rl_special_prefixes = NULL;  /*   * This is the character appended to the completed words if at the end of @@ -117,35 +152,29 @@ int rl_completion_append_character = ' ';  /* stuff below is used internally by libedit for readline emulation */ -/* if not zero, non-unique completions always show list of possible matches */ -static int _rl_complete_show_all = 0; -  static History *h = NULL;  static EditLine *e = NULL; -static int el_rl_complete_cmdnum = 0; +static Function *map[256];  /* internal functions */  static unsigned char	 _el_rl_complete(EditLine *, int); +static unsigned char	 _el_rl_tstp(EditLine *, int);  static char		*_get_prompt(EditLine *);  static HIST_ENTRY	*_move_history(int); -static int		 _history_search_gen(const char *, int, int); -static int		 _history_expand_command(const char *, size_t, char **); +static int		 _history_expand_command(const char *, size_t, size_t, +    char **);  static char		*_rl_compat_sub(const char *, const char *, -			    const char *, int); -static int		 rl_complete_internal(int); -static int		 _rl_qsort_string_compare(const void *, const void *); - -/* - * needed for prompt switching in readline() - */ -static char *el_rl_prompt = NULL; +    const char *, int); +static int		 _rl_event_read_char(EditLine *, char *); +static void		 _rl_update_pos(void);  /* ARGSUSED */  static char * -_get_prompt(EditLine *el) +_get_prompt(EditLine *el __attribute__((__unused__)))  { -	return (el_rl_prompt); +	rl_already_prompted = 1; +	return (rl_prompt);  } @@ -162,7 +191,7 @@ _move_history(int op)  		return (HIST_ENTRY *) NULL;  	rl_he.line = ev.str; -	rl_he.data = ""; +	rl_he.data = NULL;  	return (&rl_he);  } @@ -180,7 +209,6 @@ rl_initialize(void)  {  	HistEvent ev;  	const LineInfo *li; -	int i;  	int editmode = 1;  	struct termios t; @@ -215,33 +243,39 @@ rl_initialize(void)  	el_set(e, EL_HIST, history, h);  	/* for proper prompt printing in readline() */ -	el_rl_prompt = strdup(""); +	rl_prompt = strdup(""); +	if (rl_prompt == NULL) { +		history_end(h); +		el_end(e); +		return -1; +	}  	el_set(e, EL_PROMPT, _get_prompt); -	el_set(e, EL_SIGNAL, 1); +	el_set(e, EL_SIGNAL, rl_catch_signals);  	/* set default mode to "emacs"-style and read setting afterwards */  	/* so this can be overriden */  	el_set(e, EL_EDITOR, "emacs"); +	if (rl_terminal_name != NULL) +		el_set(e, EL_TERMINAL, rl_terminal_name); +	else +		el_get(e, EL_TERMINAL, &rl_terminal_name);  	/* -	 * Word completition - this has to go AFTER rebinding keys +	 * Word completion - this has to go AFTER rebinding keys  	 * to emacs-style.  	 */  	el_set(e, EL_ADDFN, "rl_complete", -	    "ReadLine compatible completition function", +	    "ReadLine compatible completion function",  	    _el_rl_complete);  	el_set(e, EL_BIND, "^I", "rl_complete", NULL);  	/* -	 * Find out where the rl_complete function was added; this is -	 * used later to detect that lastcmd was also rl_complete. +	 * Send TSTP when ^Z is pressed.  	 */ -	for(i=EL_NUM_FCNS; i < e->el_map.nfunc; i++) { -		if (e->el_map.func[i] == _el_rl_complete) { -			el_rl_complete_cmdnum = i; -			break; -		} -	} +	el_set(e, EL_ADDFN, "rl_tstp", +	    "ReadLine compatible suspend function", +	    _el_rl_tstp); +	el_set(e, EL_BIND, "^Z", "rl_tstp", NULL);  	/* read settings from configuration file */  	el_source(e, NULL); @@ -251,9 +285,12 @@ rl_initialize(void)  	 * and rl_line_buffer directly.  	 */  	li = el_line(e); -	/* LINTED const cast */ -	rl_line_buffer = (char *) li->buffer; -	rl_point = rl_end = 0; +	/* a cheesy way to get rid of const cast. */ +	rl_line_buffer = memchr(li->buffer, *li->buffer, 1); +	_rl_update_pos(); + +	if (rl_startup_hook) +		(*rl_startup_hook)(NULL, 0);  	return (0);  } @@ -269,38 +306,58 @@ readline(const char *prompt)  	HistEvent ev;  	int count;  	const char *ret; +	char *buf; +	static int used_event_hook;  	if (e == NULL || h == NULL)  		rl_initialize(); +	rl_done = 0; +  	/* update prompt accordingly to what has been passed */  	if (!prompt)  		prompt = ""; -	if (strcmp(el_rl_prompt, prompt) != 0) { -		free(el_rl_prompt); -		el_rl_prompt = strdup(prompt); +	if (strcmp(rl_prompt, prompt) != 0) { +		free(rl_prompt); +		rl_prompt = strdup(prompt); +		if (rl_prompt == NULL) +			return NULL; +	} + +	if (rl_pre_input_hook) +		(*rl_pre_input_hook)(NULL, 0); + +	if (rl_event_hook && !(e->el_flags&NO_TTY)) { +		el_set(e, EL_GETCFN, _rl_event_read_char); +		used_event_hook = 1; +	} + +	if (!rl_event_hook && used_event_hook) { +		el_set(e, EL_GETCFN, EL_BUILTIN_GETCFN); +		used_event_hook = 0;  	} + +	rl_already_prompted = 0; +  	/* get one line from input stream */  	ret = el_gets(e, &count);  	if (ret && count > 0) { -		char *foo;  		int lastidx; -		foo = strdup(ret); +		buf = strdup(ret); +		if (buf == NULL) +			return NULL;  		lastidx = count - 1; -		if (foo[lastidx] == '\n') -			foo[lastidx] = '\0'; - -		ret = foo; +		if (buf[lastidx] == '\n') +			buf[lastidx] = '\0';  	} else -		ret = NULL; +		buf = NULL;  	history(h, &ev, H_GETSIZE);  	history_length = ev.num; -	/* LINTED const cast */ -	return (char *) ret; +	return buf;  }  /* @@ -321,59 +378,178 @@ using_history(void)  /*   * substitute ``what'' with ``with'', returning resulting string; if - * globally == 1, substitutes all occurences of what, otherwise only the + * globally == 1, substitutes all occurrences of what, otherwise only the   * first one   */  static char *  _rl_compat_sub(const char *str, const char *what, const char *with,      int globally)  { -	char *result; -	const char *temp, *new; -	int len, with_len, what_len, add; -	size_t size, i; +	const	char	*s; +	char	*r, *result; +	size_t	len, with_len, what_len; -	result = malloc((size = 16)); -	temp = str; +	len = strlen(str);  	with_len = strlen(with);  	what_len = strlen(what); -	len = 0; -	do { -		new = strstr(temp, what); -		if (new) { -			i = new - temp; -			add = i + with_len; -			if (i + add + 1 >= size) { -				size += add + 1; -				result = realloc(result, size); -			} -			(void) strncpy(&result[len], temp, i); -			len += i; -			(void) strcpy(&result[len], with);	/* safe */ -			len += with_len; -			temp = new + what_len; -		} else { -			add = strlen(temp); -			if (len + add + 1 >= size) { -				size += add + 1; -				result = realloc(result, size); + +	/* calculate length we need for result */ +	s = str; +	while (*s) { +		if (*s == *what && !strncmp(s, what, what_len)) { +			len += with_len - what_len; +			if (!globally) +				break; +			s += what_len; +		} else +			s++; +	} +	r = result = malloc(len + 1); +	if (result == NULL) +		return NULL; +	s = str; +	while (*s) { +		if (*s == *what && !strncmp(s, what, what_len)) { +			(void)strncpy(r, with, with_len); +			r += with_len; +			s += what_len; +			if (!globally) { +				(void)strcpy(r, s); +				return(result);  			} -			(void) strcpy(&result[len], temp);	/* safe */ -			len += add; -			temp = NULL; +		} else +			*r++ = *s++; +	} +	*r = 0; +	return(result); +} + +static	char	*last_search_pat;	/* last !?pat[?] search pattern */ +static	char	*last_search_match;	/* last !?pat[?] that matched */ + +const char * +get_history_event(const char *cmd, int *cindex, int qchar) +{ +	int idx, sign, sub, num, begin, ret; +	size_t len; +	char	*pat; +	const char *rptr; +	HistEvent ev; + +	idx = *cindex; +	if (cmd[idx++] != history_expansion_char) +		return(NULL); + +	/* find out which event to take */ +	if (cmd[idx] == history_expansion_char || cmd[idx] == 0) { +		if (history(h, &ev, H_FIRST) != 0) +			return(NULL); +		*cindex = cmd[idx]? (idx + 1):idx; +		return(ev.str); +	} +	sign = 0; +	if (cmd[idx] == '-') { +		sign = 1; +		idx++; +	} + +	if ('0' <= cmd[idx] && cmd[idx] <= '9') { +		HIST_ENTRY *rl_he; + +		num = 0; +		while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') { +			num = num * 10 + cmd[idx] - '0'; +			idx++;  		} -	} while (temp && globally); -	result[len] = '\0'; +		if (sign) +			num = history_length - num + 1; -	return (result); -} +		if (!(rl_he = history_get(num))) +			return(NULL); + +		*cindex = idx; +		return(rl_he->line); +	} +	sub = 0; +	if (cmd[idx] == '?') { +		sub = 1; +		idx++; +	} +	begin = idx; +	while (cmd[idx]) { +		if (cmd[idx] == '\n') +			break; +		if (sub && cmd[idx] == '?') +			break; +		if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' +				    || cmd[idx] == '\t' || cmd[idx] == qchar)) +			break; +		idx++; +	} +	len = idx - begin; +	if (sub && cmd[idx] == '?') +		idx++; +	if (sub && len == 0 && last_search_pat && *last_search_pat) +		pat = last_search_pat; +	else if (len == 0) +		return(NULL); +	else { +		if ((pat = malloc(len + 1)) == NULL) +			return NULL; +		(void)strncpy(pat, cmd + begin, len); +		pat[len] = '\0'; +	} + +	if (history(h, &ev, H_CURR) != 0) { +		if (pat != last_search_pat) +			free(pat); +		return (NULL); +	} +	num = ev.num; + +	if (sub) { +		if (pat != last_search_pat) { +			if (last_search_pat) +				free(last_search_pat); +			last_search_pat = pat; +		} +		ret = history_search(pat, -1); +	} else +		ret = history_search_prefix(pat, -1); + +	if (ret == -1) { +		/* restore to end of list on failed search */ +		history(h, &ev, H_FIRST); +		(void)fprintf(rl_outstream, "%s: Event not found\n", pat); +		if (pat != last_search_pat) +			free(pat); +		return(NULL); +	} + +	if (sub && len) { +		if (last_search_match && last_search_match != pat) +			free(last_search_match); +		last_search_match = pat; +	} + +	if (pat != last_search_pat) +		free(pat); + +	if (history(h, &ev, H_CURR) != 0) +		return(NULL); +	*cindex = idx; +	rptr = ev.str; + +	/* roll back to original position */ +	(void)history(h, &ev, H_SET, num); +	return rptr; +}  /*   * the real function doing history expansion - takes as argument command   * to do and data upon which the command should be executed   * does expansion the way I've understood readline documentation - * word designator ``%'' isn't supported (yet ?)   *   * returns 0 if data was not modified, 1 if it was and 2 if the string   * should be only printed and not executed; in case of error, @@ -381,142 +557,145 @@ _rl_compat_sub(const char *str, const char *what, const char *with,   * it's callers responsibility to free() string returned in *result   */  static int -_history_expand_command(const char *command, size_t cmdlen, char **result) +_history_expand_command(const char *command, size_t offs, size_t cmdlen, +    char **result)  { -	char **arr, *tempcmd, *line, *search = NULL, *cmd; -	const char *event_data = NULL; +	char *tmp, *search = NULL, *aptr; +	const char *ptr, *cmd;  	static char *from = NULL, *to = NULL; -	int start = -1, end = -1, max, i, idx; -	int h_on = 0, t_on = 0, r_on = 0, e_on = 0, p_on = 0, g_on = 0; -	int event_num = 0, retval; -	size_t cmdsize; +	int start, end, idx, has_mods = 0; +	int p_on = 0, g_on = 0;  	*result = NULL; +	aptr = NULL; +	ptr = NULL; -	cmd = alloca(cmdlen + 1); -	(void) strncpy(cmd, command, cmdlen); -	cmd[cmdlen] = 0; +	/* First get event specifier */ +	idx = 0; -	idx = 1; -	/* find out which event to take */ -	if (cmd[idx] == history_expansion_char) { -		event_num = history_length; -		idx++; +	if (strchr(":^*$", command[offs + 1])) { +		char str[4]; +		/* +		* "!:" is shorthand for "!!:". +		* "!^", "!*" and "!$" are shorthand for +		* "!!:^", "!!:*" and "!!:$" respectively. +		*/ +		str[0] = str[1] = '!'; +		str[2] = '0'; +		ptr = get_history_event(str, &idx, 0); +		idx = (command[offs + 1] == ':')? 1:0; +		has_mods = 1;  	} else { -		int off, num; -		size_t len; -		off = idx; -		while (cmd[off] && !strchr(":^$*-%", cmd[off])) -			off++; -		num = atoi(&cmd[idx]); -		if (num != 0) { -			event_num = num; -			if (num < 0) -				event_num += history_length + 1; +		if (command[offs + 1] == '#') { +			/* use command so far */ +			if ((aptr = malloc(offs + 1)) == NULL) +				return -1; +			(void)strncpy(aptr, command, offs); +			aptr[offs] = '\0'; +			idx = 1;  		} else { -			int prefix = 1, curr_num; -			HistEvent ev; - -			len = off - idx; -			if (cmd[idx] == '?') { -				idx++, len--; -				if (cmd[off - 1] == '?') -					len--; -				else if (cmd[off] != '\n' && cmd[off] != '\0') -					return (-1); -				prefix = 0; -			} -			search = alloca(len + 1); -			(void) strncpy(search, &cmd[idx], len); -			search[len] = '\0'; - -			if (history(h, &ev, H_CURR) != 0) -				return (-1); -			curr_num = ev.num; +			int	qchar; -			if (prefix) -				retval = history_search_prefix(search, -1); -			else -				retval = history_search(search, -1); +			qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; +			ptr = get_history_event(command + offs, &idx, qchar); +		} +		has_mods = command[offs + idx] == ':'; +	} -			if (retval == -1) { -				fprintf(rl_outstream, "%s: Event not found\n", -				    search); -				return (-1); -			} -			if (history(h, &ev, H_CURR) != 0) -				return (-1); -			event_data = ev.str; +	if (ptr == NULL && aptr == NULL) +		return(-1); -			/* roll back to original position */ -			history(h, &ev, H_NEXT_EVENT, curr_num); -		} -		idx = off; +	if (!has_mods) { +		*result = strdup(aptr? aptr : ptr); +		if (aptr) +			free(aptr); +		return(1);  	} -	if (!event_data && event_num >= 0) { -		HIST_ENTRY *rl_he; -		rl_he = history_get(event_num); -		if (!rl_he) -			return (0); -		event_data = rl_he->line; +	cmd = command + offs + idx + 1; + +	/* Now parse any word designators */ + +	if (*cmd == '%')	/* last word matched by ?pat? */ +		tmp = strdup(last_search_match? last_search_match:""); +	else if (strchr("^*$-0123456789", *cmd)) { +		start = end = -1; +		if (*cmd == '^') +			start = end = 1, cmd++; +		else if (*cmd == '$') +			start = -1, cmd++; +		else if (*cmd == '*') +			start = 1, cmd++; +	       else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { +			start = 0; +			while (*cmd && '0' <= *cmd && *cmd <= '9') +				start = start * 10 + *cmd++ - '0'; + +			if (*cmd == '-') { +				if (isdigit((unsigned char) cmd[1])) { +					cmd++; +					end = 0; +					while (*cmd && '0' <= *cmd && *cmd <= '9') +						end = end * 10 + *cmd++ - '0'; +				} else if (cmd[1] == '$') { +					cmd += 2; +					end = -1; +				} else { +					cmd++; +					end = -2; +				} +			} else if (*cmd == '*') +				end = -1, cmd++; +			else +				end = start; +		} +		tmp = history_arg_extract(start, end, aptr? aptr:ptr); +		if (tmp == NULL) { +			(void)fprintf(rl_outstream, "%s: Bad word specifier", +			    command + offs + idx); +			if (aptr) +				free(aptr); +			return(-1); +		}  	} else -		return (-1); +		tmp = strdup(aptr? aptr:ptr); -	if (cmd[idx] != ':') -		return (-1); -	cmd += idx + 1; - -	/* recognize cmd */ -	if (*cmd == '^') -		start = end = 1, cmd++; -	else if (*cmd == '$') -		start = end = -1, cmd++; -	else if (*cmd == '*') -		start = 1, end = -1, cmd++; -	else if (isdigit((unsigned char) *cmd)) { -		const char *temp; -		int shifted = 0; - -		start = atoi(cmd); -		temp = cmd; -		for (; isdigit((unsigned char) *cmd); cmd++); -		if (temp != cmd) -			shifted = 1; -		if (shifted && *cmd == '-') { -			if (!isdigit((unsigned char) *(cmd + 1))) -				end = -2; -			else { -				end = atoi(cmd + 1); -				for (; isdigit((unsigned char) *cmd); cmd++); -			} -		} else if (shifted && *cmd == '*') -			end = -1, cmd++; -		else if (shifted) -			end = start; +	if (aptr) +		free(aptr); + +	if (*cmd == 0 || (cmd - (command + offs) >= cmdlen)) { +		*result = tmp; +		return(1);  	} -	if (*cmd == ':') -		cmd++; -	line = strdup(event_data);  	for (; *cmd; cmd++) {  		if (*cmd == ':')  			continue; -		else if (*cmd == 'h') -			h_on = 1 | g_on, g_on = 0; -		else if (*cmd == 't') -			t_on = 1 | g_on, g_on = 0; -		else if (*cmd == 'r') -			r_on = 1 | g_on, g_on = 0; -		else if (*cmd == 'e') -			e_on = 1 | g_on, g_on = 0; -		else if (*cmd == 'p') -			p_on = 1 | g_on, g_on = 0; +		else if (*cmd == 'h') {		/* remove trailing path */ +			if ((aptr = strrchr(tmp, '/')) != NULL) +				*aptr = 0; +		} else if (*cmd == 't') {	/* remove leading path */ +			if ((aptr = strrchr(tmp, '/')) != NULL) { +				aptr = strdup(aptr + 1); +				free(tmp); +				tmp = aptr; +			} +		} else if (*cmd == 'r') {	/* remove trailing suffix */ +			if ((aptr = strrchr(tmp, '.')) != NULL) +				*aptr = 0; +		} else if (*cmd == 'e') {	/* remove all but suffix */ +			if ((aptr = strrchr(tmp, '.')) != NULL) { +				aptr = strdup(aptr); +				free(tmp); +				tmp = aptr; +			} +		} else if (*cmd == 'p')		/* print only */ +			p_on = 1;  		else if (*cmd == 'g')  			g_on = 2;  		else if (*cmd == 's' || *cmd == '&') {  			char *what, *with, delim; -			int len, from_len; +			size_t len, from_len;  			size_t size;  			if (*cmd == '&' && (from == NULL || to == NULL)) @@ -525,23 +704,35 @@ _history_expand_command(const char *command, size_t cmdlen, char **result)  				delim = *(++cmd), cmd++;  				size = 16;  				what = realloc(from, size); +				if (what == NULL) { +					free(from); +					return 0; +				}  				len = 0;  				for (; *cmd && *cmd != delim; cmd++) { -					if (*cmd == '\\' -					    && *(cmd + 1) == delim) +					if (*cmd == '\\' && cmd[1] == delim)  						cmd++; -					if (len >= size) -						what = realloc(what, -						    (size <<= 1)); +					if (len >= size) { +						char *nwhat; +						nwhat = realloc(what, +								(size <<= 1)); +						if (nwhat == NULL) { +							free(what); +							return 0; +						} +						what = nwhat; +					}  					what[len++] = *cmd;  				}  				what[len] = '\0';  				from = what;  				if (*what == '\0') {  					free(what); -					if (search) +					if (search) {  						from = strdup(search); -					else { +						if (from == NULL) +							return 0; +					} else {  						from = NULL;  						return (-1);  					} @@ -552,16 +743,26 @@ _history_expand_command(const char *command, size_t cmdlen, char **result)  				size = 16;  				with = realloc(to, size); +				if (with == NULL) { +					free(to); +					return -1; +				}  				len = 0;  				from_len = strlen(from);  				for (; *cmd && *cmd != delim; cmd++) {  					if (len + from_len + 1 >= size) { +						char *nwith;  						size += from_len + 1; -						with = realloc(with, size); +						nwith = realloc(with, size); +						if (nwith == NULL) { +							free(with); +							return -1; +						} +						with = nwith;  					}  					if (*cmd == '&') {  						/* safe */ -						(void) strcpy(&with[len], from); +						(void)strcpy(&with[len], from);  						len += from_len;  						continue;  					} @@ -573,79 +774,18 @@ _history_expand_command(const char *command, size_t cmdlen, char **result)  				}  				with[len] = '\0';  				to = with; - -				tempcmd = _rl_compat_sub(line, from, to, -				    (g_on) ? 1 : 0); -				free(line); -				line = tempcmd; -				g_on = 0;  			} -		} -	} - -	arr = history_tokenize(line); -	free(line);		/* no more needed */ -	if (arr && *arr == NULL) -		free(arr), arr = NULL; -	if (!arr) -		return (-1); - -	/* find out max valid idx to array of array */ -	max = 0; -	for (i = 0; arr[i]; i++) -		max++; -	max--; - -	/* set boundaries to something relevant */ -	if (start < 0) -		start = 1; -	if (end < 0) -		end = max - ((end < -1) ? 1 : 0); - -	/* check boundaries ... */ -	if (start > max || end > max || start > end) -		return (-1); -	for (i = 0; i <= max; i++) { -		char *temp; -		if (h_on && (i == 1 || h_on > 1) && -		    (temp = strrchr(arr[i], '/'))) -			*(temp + 1) = '\0'; -		if (t_on && (i == 1 || t_on > 1) && -		    (temp = strrchr(arr[i], '/'))) -			(void) strcpy(arr[i], temp + 1); -		if (r_on && (i == 1 || r_on > 1) && -		    (temp = strrchr(arr[i], '.'))) -			*temp = '\0'; -		if (e_on && (i == 1 || e_on > 1) && -		    (temp = strrchr(arr[i], '.'))) -			(void) strcpy(arr[i], temp); -	} - -	cmdsize = 1, cmdlen = 0; -	tempcmd = malloc(cmdsize); -	for (i = start; start <= i && i <= end; i++) { -		int arr_len; - -		arr_len = strlen(arr[i]); -		if (cmdlen + arr_len + 1 >= cmdsize) { -			cmdsize += arr_len + 1; -			tempcmd = realloc(tempcmd, cmdsize); +			aptr = _rl_compat_sub(tmp, from, to, g_on); +			if (aptr) { +				free(tmp); +				tmp = aptr; +			} +			g_on = 0;  		} -		(void) strcpy(&tempcmd[cmdlen], arr[i]);	/* safe */ -		cmdlen += arr_len; -		tempcmd[cmdlen++] = ' ';	/* add a space */  	} -	while (cmdlen > 0 && isspace((unsigned char) tempcmd[cmdlen - 1])) -		cmdlen--; -	tempcmd[cmdlen] = '\0'; - -	*result = tempcmd; - -	for (i = 0; i <= max; i++) -		free(arr[i]); -	free(arr), arr = (char **) NULL; -	return (p_on) ? 2 : 1; +	*result = tmp; +	return (p_on? 2:1);  } @@ -655,28 +795,45 @@ _history_expand_command(const char *command, size_t cmdlen, char **result)  int  history_expand(char *str, char **output)  { -	int i, retval = 0, idx; -	size_t size; -	char *temp, *result; +	int ret = 0; +	size_t idx, i, size; +	char *tmp, *result;  	if (h == NULL || e == NULL)  		rl_initialize(); -	*output = strdup(str);	/* do it early */ +	if (history_expansion_char == 0) { +		*output = strdup(str); +		return(0); +	} +	*output = NULL;  	if (str[0] == history_subst_char) {  		/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ -		temp = alloca(4 + strlen(str) + 1); -		temp[0] = temp[1] = history_expansion_char; -		temp[2] = ':'; -		temp[3] = 's'; -		(void) strcpy(temp + 4, str); -		str = temp; +		*output = malloc(strlen(str) + 4 + 1); +		if (*output == NULL) +			return 0; +		(*output)[0] = (*output)[1] = history_expansion_char; +		(*output)[2] = ':'; +		(*output)[3] = 's'; +		(void)strcpy((*output) + 4, str); +		str = *output; +	} else { +		*output = strdup(str); +		if (*output == NULL) +			return 0;  	} -#define	ADD_STRING(what, len) 						\ + +#define ADD_STRING(what, len)						\  	{								\ -		if (idx + len + 1 > size)				\ -			result = realloc(result, (size += len + 1));	\ +		if (idx + len + 1 > size) {				\ +			char *nresult = realloc(result, (size += len + 1));\ +			if (nresult == NULL) {				\ +				free(*output);				\ +				return 0;				\ +			}						\ +			result = nresult;				\ +		}							\  		(void)strncpy(&result[idx], what, len);			\  		idx += len;						\  		result[idx] = '\0';					\ @@ -685,35 +842,35 @@ history_expand(char *str, char **output)  	result = NULL;  	size = idx = 0;  	for (i = 0; str[i];) { -		int start, j, loop_again; -		size_t len; +		int qchar, loop_again; +		size_t len, start, j; +		qchar = 0;  		loop_again = 1;  		start = j = i;  loop:  		for (; str[j]; j++) {  			if (str[j] == '\\' &&  			    str[j + 1] == history_expansion_char) { -				(void) strcpy(&str[j], &str[j + 1]); +				(void)strcpy(&str[j], &str[j + 1]);  				continue;  			}  			if (!loop_again) { -				if (str[j] == '?') { -					while (str[j] && str[++j] != '?'); -					if (str[j] == '?') -						j++; -				} else if (isspace((unsigned char) str[j])) +				if (isspace((unsigned char) str[j]) +				    || str[j] == qchar)  					break;  			}  			if (str[j] == history_expansion_char  			    && !strchr(history_no_expand_chars, str[j + 1])  			    && (!history_inhibit_expansion_function || -			    (*history_inhibit_expansion_function)(str, j) == 0)) +			    (*history_inhibit_expansion_function)(str, +			    (int)j) == 0))  				break;  		} -		if (str[j] && str[j + 1] != '#' && loop_again) { +		if (str[j] && loop_again) {  			i = j; +			qchar = (j > 0 && str[j - 1] == '"' )? '"':0;  			j++;  			if (str[j] == history_expansion_char)  				j++; @@ -721,61 +878,116 @@ loop:  			goto loop;  		}  		len = i - start; -		temp = &str[start]; -		ADD_STRING(temp, len); +		tmp = &str[start]; +		ADD_STRING(tmp, len); -		if (str[i] == '\0' || str[i] != history_expansion_char -		    || str[i + 1] == '#') { +		if (str[i] == '\0' || str[i] != history_expansion_char) {  			len = j - i; -			temp = &str[i]; -			ADD_STRING(temp, len); +			tmp = &str[i]; +			ADD_STRING(tmp, len);  			if (start == 0) -				retval = 0; +				ret = 0;  			else -				retval = 1; +				ret = 1;  			break;  		} -		retval = _history_expand_command(&str[i], (size_t) (j - i), -		    &temp); -		if (retval != -1) { -			len = strlen(temp); -			ADD_STRING(temp, len); +		ret = _history_expand_command (str, i, (j - i), &tmp); +		if (ret > 0 && tmp) { +			len = strlen(tmp); +			ADD_STRING(tmp, len); +			free(tmp);  		}  		i = j; -	}			/* for(i ...) */ +	} -	if (retval == 2) { -		add_history(temp); +	/* ret is 2 for "print only" option */ +	if (ret == 2) { +		add_history(result);  #ifdef GDB_411_HACK  		/* gdb 4.11 has been shipped with readline, where */  		/* history_expand() returned -1 when the line	  */  		/* should not be executed; in readline 2.1+	  */  		/* it should return 2 in such a case		  */ -		retval = -1; +		ret = -1;  #endif  	}  	free(*output);  	*output = result; -	return (retval); +	return (ret);  } +/* +* Return a string consisting of arguments of "str" from "start" to "end". +*/ +char * +history_arg_extract(int start, int end, const char *str) +{ +	size_t  i, len, max; +	char	**arr, *result; + +	arr = history_tokenize(str); +	if (!arr) +		return(NULL); +	if (arr && *arr == NULL) { +		free(arr); +		return(NULL); +	} + +	for (max = 0; arr[max]; max++) +		continue; +	max--; + +	if (start == '$') +		start = max; +	if (end == '$') +		end = max; +	if (end < 0) +		end = max + end + 1; +	if (start < 0) +		start = end; + +	if (start < 0 || end < 0 || start > max || end > max || start > end) +		return(NULL); + +	for (i = start, len = 0; i <= end; i++) +		len += strlen(arr[i]) + 1; +	len++; +	result = malloc(len); +	if (result == NULL) +		return NULL; + +	for (i = start, len = 0; i <= end; i++) { +		(void)strcpy(result + len, arr[i]); +		len += strlen(arr[i]); +		if (i < end) +			result[len++] = ' '; +	} +	result[len] = 0; + +	for (i = 0; arr[i]; i++) +		free(arr[i]); +	free(arr); + +	return(result); +}  /* - * Parse the string into individual tokens, similarily to how shell would do it. + * Parse the string into individual tokens, + * similar to how shell would do it.   */  char **  history_tokenize(const char *str)  { -	int size = 1, result_idx = 0, i, start; +	int size = 1, idx = 0, i, start;  	size_t len;  	char **result = NULL, *temp, delim = '\0'; -	for (i = 0; str[i]; i++) { +	for (i = 0; str[i];) {  		while (isspace((unsigned char) str[i]))  			i++;  		start = i; -		for (; str[i]; i++) { +		for (; str[i];) {  			if (str[i] == '\\') {  				if (str[i+1] != '\0')  					i++; @@ -787,20 +999,35 @@ history_tokenize(const char *str)  				break;  			else if (!delim && strchr("'`\"", str[i]))  				delim = str[i]; +			if (str[i]) +				i++;  		} -		if (result_idx + 2 >= size) { +		if (idx + 2 >= size) { +			char **nresult;  			size <<= 1; -			result = realloc(result, size * sizeof(char *)); +			nresult = realloc(result, size * sizeof(char *)); +			if (nresult == NULL) { +				free(result); +				return NULL; +			} +			result = nresult;  		}  		len = i - start;  		temp = malloc(len + 1); -		(void) strncpy(temp, &str[start], len); +		if (temp == NULL) { +			for (i = 0; i < idx; i++) +				free(result[i]); +			free(result); +			return NULL; +		} +		(void)strncpy(temp, &str[start], len);  		temp[len] = '\0'; -		result[result_idx++] = temp; -		result[result_idx] = NULL; +		result[idx++] = temp; +		result[idx] = NULL; +		if (str[i]) +			i++;  	} -  	return (result);  } @@ -884,28 +1111,29 @@ history_get(int num)  {  	static HIST_ENTRY she;  	HistEvent ev; -	int i = 1, curr_num; +	int curr_num;  	if (h == NULL || e == NULL)  		rl_initialize(); -	/* rewind to beginning */ +	/* save current position */  	if (history(h, &ev, H_CURR) != 0)  		return (NULL);  	curr_num = ev.num; -	if (history(h, &ev, H_LAST) != 0) + +	/* start from most recent */ +	if (history(h, &ev, H_FIRST) != 0)  		return (NULL);	/* error */ -	while (i < num && history(h, &ev, H_PREV) == 0) -		i++; -	if (i != num) -		return (NULL);	/* not so many entries */ + +	/* look backwards for event matching specified offset */ +	if (history(h, &ev, H_NEXT_EVENT, num)) +		return (NULL);  	she.line = ev.str;  	she.data = NULL; -	/* rewind history to the same event it was before */ -	(void) history(h, &ev, H_FIRST); -	(void) history(h, &ev, H_NEXT_EVENT, curr_num); +	/* restore pointer to where it was */ +	(void)history(h, &ev, H_SET, curr_num);  	return (&she);  } @@ -922,11 +1150,33 @@ add_history(const char *line)  	if (h == NULL || e == NULL)  		rl_initialize(); -	(void) history(h, &ev, H_ENTER, line); +	(void)history(h, &ev, H_ENTER, line);  	if (history(h, &ev, H_GETSIZE) == 0)  		history_length = ev.num; -	return (!(history_length > 0));	/* return 0 if all is okay */ +	return (!(history_length > 0)); /* return 0 if all is okay */ +} + + +/* + * remove the specified entry from the history list and return it. + */ +HIST_ENTRY * +remove_history(int num) +{ +	static HIST_ENTRY she; +	HistEvent ev; + +	if (h == NULL || e == NULL) +		rl_initialize(); + +	if (history(h, &ev, H_DEL, num) != 0) +		return NULL; + +	she.line = ev.str; +	she.data = NULL; + +	return &she;  } @@ -1008,22 +1258,17 @@ int  history_set_pos(int pos)  {  	HistEvent ev; -	int off, curr_num; +	int curr_num;  	if (pos > history_length || pos < 0)  		return (-1);  	history(h, &ev, H_CURR);  	curr_num = ev.num; -	history(h, &ev, H_FIRST); -	off = 0; -	while (off < pos && history(h, &ev, H_NEXT) == 0) -		off++; -	if (off != pos) {	/* do a rollback in case of error */ -		history(h, &ev, H_FIRST); -		history(h, &ev, H_NEXT_EVENT, curr_num); -		return (-1); +	if (history(h, &ev, H_SET, pos)) { +		history(h, &ev, H_SET, curr_num); +		return(-1);  	}  	return (0);  } @@ -1052,10 +1297,10 @@ next_history(void)  /* - * generic history search function + * searches for first history event containing the str   */ -static int -_history_search_gen(const char *str, int direction, int pos) +int +history_search(const char *str, int direction)  {  	HistEvent ev;  	const char *strp; @@ -1066,38 +1311,25 @@ _history_search_gen(const char *str, int direction, int pos)  	curr_num = ev.num;  	for (;;) { -		strp = strstr(ev.str, str); -		if (strp && (pos < 0 || &ev.str[pos] == strp)) +		if ((strp = strstr(ev.str, str)) != NULL)  			return (int) (strp - ev.str); -		if (history(h, &ev, direction < 0 ? H_PREV : H_NEXT) != 0) +		if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0)  			break;  	} - -	history(h, &ev, direction < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); - +	history(h, &ev, H_SET, curr_num);  	return (-1);  }  /* - * searches for first history event containing the str - */ -int -history_search(const char *str, int direction) -{ - -	return (_history_search_gen(str, direction, -1)); -} - - -/*   * searches for first history event beginning with str   */  int  history_search_prefix(const char *str, int direction)  { +	HistEvent ev; -	return (_history_search_gen(str, direction, 0)); +	return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str));  } @@ -1107,7 +1339,8 @@ history_search_prefix(const char *str, int direction)   */  /* ARGSUSED */  int -history_search_pos(const char *str, int direction, int pos) +history_search_pos(const char *str, +		   int direction __attribute__((__unused__)), int pos)  {  	HistEvent ev;  	int curr_num, off; @@ -1138,140 +1371,20 @@ history_search_pos(const char *str, int direction, int pos)  /********************************/ -/* completition functions	*/ +/* completion functions */ -/* - * does tilde expansion of strings of type ``~user/foo'' - * if ``user'' isn't valid user name or ``txt'' doesn't start - * w/ '~', returns pointer to strdup()ed copy of ``txt'' - * - * it's callers's responsibility to free() returned string - */  char * -tilde_expand(char *txt) +tilde_expand(char *name)  { -	struct passwd *pass; -	char *temp; -	size_t len = 0; - -	if (txt[0] != '~') -		return (strdup(txt)); - -	temp = strchr(txt + 1, '/'); -	if (temp == NULL) -		temp = strdup(txt + 1); -	else { -		len = temp - txt + 1;	/* text until string after slash */ -		temp = malloc(len); -		(void) strncpy(temp, txt + 1, len - 2); -		temp[len - 2] = '\0'; -	} -	pass = getpwnam(temp); -	free(temp);		/* value no more needed */ -	if (pass == NULL) -		return (strdup(txt)); - -	/* update pointer txt to point at string immedially following */ -	/* first slash */ -	txt += len; - -	temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); -	(void) sprintf(temp, "%s/%s", pass->pw_dir, txt); - -	return (temp); +	return fn_tilde_expand(name);  } - -/* - * return first found file name starting by the ``text'' or NULL if no - * such file can be found - * value of ``state'' is ignored - * - * it's caller's responsibility to free returned string - */  char * -filename_completion_function(const char *text, int state) +filename_completion_function(const char *name, int state)  { -	static DIR *dir = NULL; -	static char *filename = NULL, *dirname = NULL; -	static size_t filename_len = 0; -	struct dirent *entry; -	char *temp; -	size_t len; - -	if (state == 0 || dir == NULL) { -		if (dir != NULL) { -			closedir(dir); -			dir = NULL; -		} -		temp = strrchr(text, '/'); -		if (temp) { -			temp++; -			filename = realloc(filename, strlen(temp) + 1); -			(void) strcpy(filename, temp); -			len = temp - text;	/* including last slash */ -			dirname = realloc(dirname, len + 1); -			(void) strncpy(dirname, text, len); -			dirname[len] = '\0'; -		} else { -			filename = strdup(text); -			dirname = NULL; -		} - -		/* support for ``~user'' syntax */ -		if (dirname && *dirname == '~') { -			temp = tilde_expand(dirname); -			dirname = realloc(dirname, strlen(temp) + 1); -			(void) strcpy(dirname, temp);	/* safe */ -			free(temp);	/* no longer needed */ -		} -		/* will be used in cycle */ -		filename_len = strlen(filename); -		if (filename_len == 0) -			return (NULL);	/* no expansion possible */ - -		dir = opendir(dirname ? dirname : "."); -		if (!dir) -			return (NULL);	/* cannot open the directory */ -	} -	/* find the match */ -	while ((entry = readdir(dir)) != NULL) { -		/* otherwise, get first entry where first */ -		/* filename_len characters are equal	  */ -		if (entry->d_name[0] == filename[0] -#if defined(__SVR4) || defined(__linux__) -		    && strlen(entry->d_name) >= filename_len -#else -		    && entry->d_namlen >= filename_len -#endif -		    && strncmp(entry->d_name, filename, -			filename_len) == 0) -			break; -	} - -	if (entry) {		/* match found */ - -		struct stat stbuf; -#if defined(__SVR4) || defined(__linux__) -		len = strlen(entry->d_name) + -#else -		len = entry->d_namlen + -#endif -		    ((dirname) ? strlen(dirname) : 0) + 1 + 1; -		temp = malloc(len); -		(void) sprintf(temp, "%s%s", -		    dirname ? dirname : "", entry->d_name);	/* safe */ - -		/* test, if it's directory */ -		if (stat(temp, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) -			strcat(temp, "/");	/* safe */ -	} else -		temp = NULL; - -	return (temp); +	return fn_filename_completion_function(name, state);  } -  /*   * a completion generator for usernames; returns _first_ username   * which starts with supplied text @@ -1282,7 +1395,8 @@ filename_completion_function(const char *text, int state)  char *  username_completion_function(const char *text, int state)  { -	struct passwd *pwd; +	struct passwd *pwd, pwres; +	char pwbuf[1024];  	if (text[0] == '\0')  		return (NULL); @@ -1293,7 +1407,8 @@ username_completion_function(const char *text, int state)  	if (state == 0)  		setpwent(); -	while ((pwd = getpwent()) && text[0] == pwd->pw_name[0] +	while (getpwent_r(&pwres, pwbuf, sizeof(pwbuf), &pwd) == 0 +	    && pwd != NULL && text[0] == pwd->pw_name[0]  	    && strcmp(text, pwd->pw_name) == 0);  	if (pwd == NULL) { @@ -1305,81 +1420,14 @@ username_completion_function(const char *text, int state)  /* - * el-compatible wrapper around rl_complete; needed for key binding + * el-compatible wrapper to send TSTP on ^Z   */  /* ARGSUSED */  static unsigned char -_el_rl_complete(EditLine *el, int ch) +_el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__unused__)))  { -	return (unsigned char) rl_complete(0, ch); -} - - -/* - * returns list of completitions for text given - */ -char ** -completion_matches(const char *text, CPFunction *genfunc) -{ -	char **match_list = NULL, *retstr, *prevstr; -	size_t match_list_len, max_equal, which, i; -	int matches; - -	if (h == NULL || e == NULL) -		rl_initialize(); - -	matches = 0; -	match_list_len = 1; -	while ((retstr = (*genfunc) (text, matches)) != NULL) { -		if (matches + 1 >= match_list_len) { -			match_list_len <<= 1; -			match_list = realloc(match_list, -			    match_list_len * sizeof(char *)); -		} -		match_list[++matches] = retstr; -	} - -	if (!match_list) -		return (char **) NULL;	/* nothing found */ - -	/* find least denominator and insert it to match_list[0] */ -	which = 2; -	prevstr = match_list[1]; -	max_equal = strlen(prevstr); -	for (; which <= matches; which++) { -		for (i = 0; i < max_equal && -		    prevstr[i] == match_list[which][i]; i++) -			continue; -		max_equal = i; -	} - -	retstr = malloc(max_equal + 1); -	(void) strncpy(retstr, match_list[1], max_equal); -	retstr[max_equal] = '\0'; -	match_list[0] = retstr; - -	/* 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); -} - -/* - * Sort function for qsort(). Just wrapper around strcasecmp(). - */ -static int -_rl_qsort_string_compare(i1, i2) -	const void *i1, *i2; -{ -	/*LINTED const castaway*/ -	const char *s1 = ((const char **)i1)[0]; -	/*LINTED const castaway*/ -	const char *s2 = ((const char **)i2)[0]; - -	return strcasecmp(s1, s2); +	(void)kill(0, SIGTSTP); +	return CC_NORM;  }  /* @@ -1388,206 +1436,59 @@ _rl_qsort_string_compare(i1, i2)   * 'max' is maximum length of string in 'matches'.   */  void -rl_display_match_list (matches, len, max) -     char **matches; -     int len, max; +rl_display_match_list(char **matches, int len, int max)  { -	int i, idx, limit, count; -	int screenwidth = e->el_term.t_size.h; -	/* -	 * Find out how many entries can be put on one line, count -	 * with two spaces between strings. -	 */ -	limit = screenwidth / (max + 2); -	if (limit == 0) -		limit = 1; - -	/* how many lines of output */ -	count = len / limit; -	if (count * limit < len) -		count++; - -	/* Sort the items if they are not already sorted. */ -	qsort(&matches[1], (size_t)(len - 1), sizeof(char *), -	    _rl_qsort_string_compare); - -	idx = 1; -	for(; count > 0; count--) { -		for(i=0; i < limit && matches[idx]; i++, idx++) -			fprintf(e->el_outfile, "%-*s  ", max, matches[idx]); -		fprintf(e->el_outfile, "\n"); -	} +	fn_display_match_list(e, matches, len, max);  } -/* - * Complete the word at or before point, called by rl_complete() - * 'what_to_do' says what to do with the completion. - * `?' means list the possible completions. - * TAB means do standard completion. - * `*' means insert all of the possible completions. - * `!' means to do standard completion, and list all possible completions if - * there is more than one. - * - * Note: '*' support is not implemented - */ -static int -rl_complete_internal(int what_to_do) +static const char * +/*ARGSUSED*/ +_rl_completion_append_character_function(const char *dummy +    __attribute__((__unused__)))  { -	CPFunction *complet_func; -	const LineInfo *li; -	char *temp, **matches; -	const char *ctemp; -	size_t len; - -	rl_completion_type = what_to_do; - -	if (h == NULL || e == NULL) -		rl_initialize(); - -	complet_func = rl_completion_entry_function; -	if (!complet_func) -		complet_func = filename_completion_function; - -	/* We now look backwards for the start of a filename/variable word */ -	li = el_line(e); -	ctemp = (const char *) li->cursor; -	while (ctemp > li->buffer -	    && !strchr(rl_basic_word_break_characters, ctemp[-1]) -	    && (!rl_special_prefixes -			|| !strchr(rl_special_prefixes, ctemp[-1]) ) ) -		ctemp--; - -	len = li->cursor - ctemp; -	temp = alloca(len + 1); -	(void) strncpy(temp, ctemp, len); -	temp[len] = '\0'; - -	/* these can be used by function called in completion_matches() */ -	/* or (*rl_attempted_completion_function)() */ -	rl_point = li->cursor - li->buffer; -	rl_end = li->lastchar - li->buffer; - -	if (!rl_attempted_completion_function) -		matches = completion_matches(temp, complet_func); -	else { -		int end = li->cursor - li->buffer; -		matches = (*rl_attempted_completion_function) (temp, (int) -		    (end - len), end); -	} - -	if (matches) { -		int i, retval = CC_REFRESH; -		int matches_num, maxlen, match_len, match_display=1; - -		/* -		 * Only replace the completed string with common part of -		 * possible matches if there is possible completion. -		 */ -		if (matches[0][0] != '\0') { -			el_deletestr(e, (int) len); -			el_insertstr(e, matches[0]); -		} - -		if (what_to_do == '?') -			goto display_matches; - -		if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { -			/* -			 * We found exact match. Add a space after -			 * it, unless we do filename completition and the -			 * object is a directory. -			 */ -			size_t alen = strlen(matches[0]); -			if ((complet_func != filename_completion_function -			      || (alen > 0 && (matches[0])[alen - 1] != '/')) -			    && rl_completion_append_character) { -				char buf[2]; -				buf[0] = rl_completion_append_character; -				buf[1] = '\0'; -				el_insertstr(e, buf); -			} -		} else if (what_to_do == '!') { -    display_matches: -			/* -			 * More than one match and requested to list possible -			 * matches. -			 */ - -			for(i=1, maxlen=0; matches[i]; i++) { -				match_len = strlen(matches[i]); -				if (match_len > maxlen) -					maxlen = match_len; -			} -			matches_num = i - 1; -				 -			/* newline to get on next line from command line */ -			fprintf(e->el_outfile, "\n"); - -			/* -			 * If there are too many items, ask user for display -			 * confirmation. -			 */ -			if (matches_num > rl_completion_query_items) { -				fprintf(e->el_outfile, -				"Display all %d possibilities? (y or n) ", -					matches_num); -				fflush(e->el_outfile); -				if (getc(stdin) != 'y') -					match_display = 0; -				fprintf(e->el_outfile, "\n"); -			} - -			if (match_display) -				rl_display_match_list(matches, matches_num, -					maxlen); -			retval = CC_REDISPLAY; -		} else if (matches[0][0]) { -			/* -			 * There was some common match, but the name was -			 * not complete enough. Next tab will print possible -			 * completions. -			 */ -			el_beep(e); -		} else { -			/* lcd is not a valid object - further specification */ -			/* is needed */ -			el_beep(e); -			retval = CC_NORM; -		} - -		/* free elements of array and the array itself */ -		for (i = 0; matches[i]; i++) -			free(matches[i]); -		free(matches), matches = NULL; - -		return (retval); -	} -	return (CC_NORM); +	static char buf[2]; +	buf[1] = rl_completion_append_character; +	return buf;  }  /*   * complete word at current point   */ +/* ARGSUSED */  int -rl_complete(int ignore, int invoking_key) +rl_complete(int ignore __attribute__((__unused__)), int invoking_key)  {  	if (h == NULL || e == NULL)  		rl_initialize();  	if (rl_inhibit_completion) { -		rl_insert(ignore, invoking_key); +		char arr[2]; +		arr[0] = (char)invoking_key; +		arr[1] = '\0'; +		el_insertstr(e, arr);  		return (CC_REFRESH); -	} else if (e->el_state.lastcmd == el_rl_complete_cmdnum) -		return rl_complete_internal('?'); -	else if (_rl_complete_show_all) -		return rl_complete_internal('!'); -	else -		return (rl_complete_internal(TAB)); +	} + +	/* Just look at how many global variables modify this operation! */ +	return fn_complete(e, +	    (CPFunction *)rl_completion_entry_function, +	    rl_attempted_completion_function, +	    rl_basic_word_break_characters, rl_special_prefixes, +	    _rl_completion_append_character_function, rl_completion_query_items, +	    &rl_completion_type, &rl_attempted_completion_over, +	    &rl_point, &rl_end);  } +/* ARGSUSED */ +static unsigned char +_el_rl_complete(EditLine *el __attribute__((__unused__)), int ch) +{ +	return (unsigned char)rl_complete(0, ch); +} +  /*   * misc other functions   */ @@ -1633,7 +1534,7 @@ rl_read_key(void)   */  /* ARGSUSED */  void -rl_reset_terminal(const char *p) +rl_reset_terminal(const char *p __attribute__((__unused__)))  {  	if (h == NULL || e == NULL) @@ -1662,3 +1563,213 @@ rl_insert(int count, int c)  	return (0);  } + +/*ARGSUSED*/ +int +rl_newline(int count, int c) +{ +	/* +	 * Readline-4.0 appears to ignore the args. +	 */ +	return rl_insert(1, '\n'); +} + +/*ARGSUSED*/ +static unsigned char +rl_bind_wrapper(EditLine *el, unsigned char c) +{ +	if (map[c] == NULL) +	    return CC_ERROR; + +	_rl_update_pos(); + +	(*map[c])(NULL, c); + +	/* If rl_done was set by the above call, deal with it here */ +	if (rl_done) +		return CC_EOF; + +	return CC_NORM; +} + +int +rl_add_defun(const char *name, Function *fun, int c) +{ +	char dest[8]; +	if (c >= sizeof(map) / sizeof(map[0]) || c < 0) +		return -1; +	map[(unsigned char)c] = fun; +	el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); +	vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); +	el_set(e, EL_BIND, dest, name); +	return 0; +} + +void +rl_callback_read_char() +{ +	int count = 0, done = 0; +	const char *buf = el_gets(e, &count); +	char *wbuf; + +	if (buf == NULL || count-- <= 0) +		return; +	if (count == 0 && buf[0] == CTRL('d')) +		done = 1; +	if (buf[count] == '\n' || buf[count] == '\r') +		done = 2; + +	if (done && rl_linefunc != NULL) { +		el_set(e, EL_UNBUFFERED, 0); +		if (done == 2) { +		    if ((wbuf = strdup(buf)) != NULL) +			wbuf[count] = '\0'; +		} else +			wbuf = NULL; +		(*(void (*)(const char *))rl_linefunc)(wbuf); +		el_set(e, EL_UNBUFFERED, 1); +	} +} + +void  +rl_callback_handler_install (const char *prompt, VCPFunction *linefunc) +{ +	if (e == NULL) { +		rl_initialize(); +	} +	if (rl_prompt) +		free(rl_prompt); +	rl_prompt = prompt ? strdup(strchr(prompt, *prompt)) : NULL; +	rl_linefunc = linefunc; +	el_set(e, EL_UNBUFFERED, 1); +}    + +void  +rl_callback_handler_remove(void) +{ +	el_set(e, EL_UNBUFFERED, 0); +} + +void +rl_redisplay(void) +{ +	char a[2]; +	a[0] = CTRL('r'); +	a[1] = '\0'; +	el_push(e, a); +} + +int +rl_get_previous_history(int count, int key) +{ +	char a[2]; +	a[0] = key; +	a[1] = '\0'; +	while (count--) +		el_push(e, a); +	return 0; +} + +void +/*ARGSUSED*/ +rl_prep_terminal(int meta_flag) +{ +	el_set(e, EL_PREP_TERM, 1); +} + +void +rl_deprep_terminal() +{ +	el_set(e, EL_PREP_TERM, 0); +} + +int +rl_read_init_file(const char *s) +{ +	return(el_source(e, s)); +} + +int +rl_parse_and_bind(const char *line) +{ +	const char **argv; +	int argc; +	Tokenizer *tok; + +	tok = tok_init(NULL); +	tok_str(tok, line, &argc, &argv); +	argc = el_parse(e, argc, argv); +	tok_end(tok); +	return (argc ? 1 : 0); +} + +int +rl_variable_bind(const char *var, const char *value) +{ +	/* +	 * The proper return value is undocument, but this is what the +	 * readline source seems to do. +	 */ +	return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0); +} + +void +rl_stuff_char(int c) +{ +	char buf[2]; + +	buf[0] = c; +	buf[1] = '\0'; +	el_insertstr(e, buf); +} + +static int +_rl_event_read_char(EditLine *el, char *cp) +{ +	int	n, num_read = 0; + +	*cp = 0; +	while (rl_event_hook) { + +		(*rl_event_hook)(); + +#if defined(FIONREAD) +		if (ioctl(el->el_infd, FIONREAD, &n) < 0) +			return(-1); +		if (n) +			num_read = read(el->el_infd, cp, 1); +		else +			num_read = 0; +#elif defined(F_SETFL) && defined(O_NDELAY) +		if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) +			return(-1); +		if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) +			return(-1); +		num_read = read(el->el_infd, cp, 1); +		if (fcntl(el->el_infd, F_SETFL, n)) +			return(-1); +#else +		/* not non-blocking, but what you gonna do? */ +		num_read = read(el->el_infd, cp, 1); +		return(-1); +#endif + +		if (num_read < 0 && errno == EAGAIN) +			continue; +		if (num_read == 0) +			continue; +		break; +	} +	if (!rl_event_hook) +		el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); +	return(num_read); +} + +static void +_rl_update_pos(void) +{ +	const LineInfo *li = el_line(e); + +	rl_point = li->cursor - li->buffer; +	rl_end = li->lastchar - li->buffer; +} diff --git a/readline/Makefile b/readline/Makefile index ea8f093e174a..3d5111fe3bf2 100644 --- a/readline/Makefile +++ b/readline/Makefile @@ -1,13 +1,13 @@ -#	$NetBSD: Makefile,v 1.4 2001/05/16 07:09:26 enami Exp $	 +#	$NetBSD: Makefile,v 1.7 2003/08/03 09:23:15 lukem Exp $	 -.PATH:	${CURDIR}/.. +NOOBJ=		# defined -INCS=		readline.h -INCSDIR=	/usr/include/readline -SYMLINKS=	readline.h ${INCSDIR}/history.h +.include <bsd.own.mk> -MKOBJ=	no +.PATH:	${NETBSDSRCDIR}/lib/libedit -incinstall:: linksinstall +INCS=		readline.h +INCSDIR=	/usr/include/readline +INCSYMLINKS=	readline.h ${INCSDIR}/history.h  .include <bsd.prog.mk> diff --git a/readline/readline.h b/readline/readline.h index cd59a4cc3b5f..3a7ab6a05570 100644 --- a/readline/readline.h +++ b/readline/readline.h @@ -1,4 +1,4 @@ -/*	$NetBSD: readline.h,v 1.1 2001/01/05 21:15:50 jdolecek Exp $	*/ +/*	$NetBSD: readline.h,v 1.17 2005/07/14 15:00:58 christos Exp $	*/  /*-   * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -36,7 +36,7 @@   * POSSIBILITY OF SUCH DAMAGE.   */  #ifndef _READLINE_H_ -#define	_READLINE_H_ +#define _READLINE_H_  #include <sys/types.h> @@ -45,6 +45,7 @@  /* typedefs */  typedef int	  Function(const char *, int);  typedef void	  VFunction(void); +typedef void	  VCPFunction(char *);  typedef char	 *CPFunction(const char *, int);  typedef char	**CPPFunction(const char *, int, int); @@ -53,8 +54,42 @@ typedef struct _hist_entry {  	const char	*data;  } HIST_ENTRY; +typedef struct _keymap_entry { +	char type; +#define ISFUNC	0 +#define ISKMAP	1 +#define ISMACR	2 +	Function *function; +} KEYMAP_ENTRY; + +#define KEYMAP_SIZE	256 + +typedef KEYMAP_ENTRY KEYMAP_ENTRY_ARRAY[KEYMAP_SIZE]; +typedef KEYMAP_ENTRY *Keymap; + +#define control_character_threshold	0x20 +#define control_character_bit		0x40 + +#ifndef CTRL +#include <sys/ioctl.h> +#if !defined(__sun__) && !defined(__hpux__) +#include <sys/ttydefaults.h> +#endif +#ifndef CTRL +#define CTRL(c)		((c) & 037) +#endif +#endif +#ifndef UNCTRL +#define UNCTRL(c)	(((c) - 'a' + 'A')|control_character_bit) +#endif + +#define RUBOUT		0x7f +#define ABORT_CHAR	CTRL('G') +  /* global variables used by readline enabled applications */ -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif  extern const char	*rl_library_version;  extern char		*rl_readline_name;  extern FILE		*rl_instream; @@ -66,12 +101,32 @@ extern int		 max_input_history;  extern char		*rl_basic_word_break_characters;  extern char		*rl_completer_word_break_characters;  extern char		*rl_completer_quote_characters; -extern CPFunction	*rl_completion_entry_function; +extern Function		*rl_completion_entry_function;  extern CPPFunction	*rl_attempted_completion_function; +extern int		 rl_attempted_completion_over;  extern int		rl_completion_type;  extern int		rl_completion_query_items;  extern char		*rl_special_prefixes;  extern int		rl_completion_append_character; +extern int		rl_inhibit_completion; +extern Function		*rl_pre_input_hook; +extern Function		*rl_startup_hook; +extern char		*rl_terminal_name; +extern int		rl_already_prompted; +extern char		*rl_prompt; +/* + * The following is not implemented + */ +extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, +			emacs_meta_keymap, +			emacs_ctlx_keymap; +extern int		rl_filename_completion_desired; +extern int		rl_ignore_completion_duplicates; +extern Function		*rl_getc_function; +extern VFunction	*rl_redisplay_function; +extern VFunction	*rl_completion_display_matches_hook; +extern VFunction	*rl_prep_term_function; +extern VFunction	*rl_deprep_term_function;  /* supported functions */  char		*readline(const char *); @@ -86,6 +141,7 @@ int		 history_is_stifled(void);  int		 where_history(void);  HIST_ENTRY	*current_history(void);  HIST_ENTRY	*history_get(int); +HIST_ENTRY	*remove_history(int);  int		 history_total_bytes(void);  int		 history_set_pos(int);  HIST_ENTRY	*previous_history(void); @@ -97,6 +153,8 @@ int		 read_history(const char *);  int		 write_history(const char *);  int		 history_expand(char *, char **);  char	       **history_tokenize(const char *); +const char	*get_history_event(const char *, int *, int); +char		*history_arg_extract(int, int, const char *);  char		*tilde_expand(char *);  char		*filename_completion_function(const char *, int); @@ -109,6 +167,29 @@ void		 rl_display_match_list(char **, int, int);  int		 rl_insert(int, int);  void		 rl_reset_terminal(const char *);  int		 rl_bind_key(int, int (*)(int, int)); -__END_DECLS +int		 rl_newline(int, int); +void		 rl_callback_read_char(void); +void		 rl_callback_handler_install(const char *, VCPFunction *); +void		 rl_callback_handler_remove(void); +void		 rl_redisplay(void); +int		 rl_get_previous_history(int, int); +void		 rl_prep_terminal(int); +void		 rl_deprep_terminal(void); +int		 rl_read_init_file(const char *); +int		 rl_parse_and_bind(const char *); +int		 rl_variable_bind(const char *, const char *); +void		 rl_stuff_char(int); +int		 rl_add_defun(const char *, Function *, int); + +/* + * The following are not implemented + */ +Keymap		 rl_get_keymap(void); +Keymap		 rl_make_bare_keymap(void); +int		 rl_generic_bind(int, const char *, const char *, Keymap); +int		 rl_bind_key_in_map(int, Function *, Keymap); +#ifdef __cplusplus +} +#endif  #endif /* _READLINE_H_ */ diff --git a/refresh.c b/refresh.c index b2ef6e4f84b1..dd710034e7ba 100644 --- a/refresh.c +++ b/refresh.c @@ -1,4 +1,4 @@ -/*	$NetBSD: refresh.c,v 1.17 2001/04/13 00:53:11 lukem Exp $	*/ +/*	$NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)refresh.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: refresh.c,v 1.17 2001/04/13 00:53:11 lukem Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.26 2003/08/07 16:44:33 agc Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * refresh.c: Lower level screen refreshing functions   */ -#include "sys.h"  #include <stdio.h>  #include <ctype.h>  #include <unistd.h> @@ -62,24 +57,24 @@ private void	re_insert (EditLine *, char *, int, int, char *, int);  private void	re_delete(EditLine *, char *, int, int, int);  private void	re_fastputc(EditLine *, int);  private void	re__strncopy(char *, char *, size_t); -private void	re__copy_and_pad(char *, char *, size_t); +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)); @@ -210,6 +205,14 @@ re_refresh(EditLine *el)  	el->el_refresh.r_cursor.h = 0;  	el->el_refresh.r_cursor.v = 0; +	if (el->el_line.cursor >= el->el_line.lastchar) { +		if (el->el_map.current == el->el_map.alt +		    && el->el_line.lastchar != el->el_line.buffer) +			el->el_line.cursor = el->el_line.lastchar - 1; +		else +			el->el_line.cursor = el->el_line.lastchar; +	} +  	cur.h = -1;		/* set flag in case I'm not set */  	cur.v = 0; @@ -319,7 +322,6 @@ re_goto_bottom(EditLine *el)  {  	term_move_to_line(el, el->el_refresh.r_oldcv); -	term__putc('\r');  	term__putc('\n');  	re_clear_display(el);  	term__flush(); @@ -332,7 +334,8 @@ re_goto_bottom(EditLine *el)   */  private void  /*ARGSUSED*/ -re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num) +re_insert(EditLine *el __attribute__((__unused__)), +    char *d, int dat, int dlen, char *s, int num)  {  	char *a, *b; @@ -375,7 +378,8 @@ re_insert(EditLine *el, char *d, int dat, int dlen, char *s, int num)   */  private void  /*ARGSUSED*/ -re_delete(EditLine *el, char *d, int dat, int dlen, int num) +re_delete(EditLine *el __attribute__((__unused__)), +    char *d, int dat, int dlen, int num)  {  	char *a, *b; @@ -908,9 +912,9 @@ re_update_line(EditLine *el, char *old, char *new, int i)   *	Copy string and pad with spaces   */  private void -re__copy_and_pad(char *dst, char *src, size_t width) +re__copy_and_pad(char *dst, const char *src, size_t width)  { -	int i; +	size_t i;  	for (i = 0; i < width; i++) {  		if (*src == '\0') @@ -934,6 +938,14 @@ re_refresh_cursor(EditLine *el)  	char *cp, c;  	int h, v, th; +	if (el->el_line.cursor >= el->el_line.lastchar) { +		if (el->el_map.current == el->el_map.alt +		    && el->el_line.lastchar != el->el_line.buffer) +			el->el_line.cursor = el->el_line.lastchar - 1; +		else +			el->el_line.cursor = el->el_line.lastchar; +	} +  	/* first we must find where the cursor is... */  	h = el->el_prompt.p_pos.h;  	v = el->el_prompt.p_pos.v; @@ -1056,8 +1068,8 @@ re_fastaddc(EditLine *el)  		re_fastputc(el, c);  	} else {  		re_fastputc(el, '\\'); -		re_fastputc(el, (int) ((((unsigned int) c >> 6) & 7) + '0')); -		re_fastputc(el, (int) ((((unsigned int) c >> 3) & 7) + '0')); +		re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0')); +		re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0'));  		re_fastputc(el, (c & 7) + '0');  	}  	term__flush(); diff --git a/refresh.h b/refresh.h index 33c0887c1b38..dd2bd02094ba 100644 --- a/refresh.h +++ b/refresh.h @@ -1,4 +1,4 @@ -/*	$NetBSD: refresh.h,v 1.4 2001/01/10 07:45:42 jdolecek Exp $	*/ +/*	$NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -1,4 +1,4 @@ -/*	$NetBSD: search.c,v 1.11 2001/01/23 15:55:31 jdolecek Exp $	*/ +/*	$NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,18 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)search.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: search.c,v 1.11 2001/01/23 15:55:31 jdolecek Exp $"); +__RCSID("$NetBSD: search.c,v 1.20 2004/11/04 01:16:03 christos Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * search.c: History and character search functions   */ -#include "sys.h"  #include <stdlib.h>  #if defined(REGEX)  #include <regex.h> @@ -77,7 +72,8 @@ search_init(EditLine *el)  	el->el_search.patlen = 0;  	el->el_search.patdir = -1;  	el->el_search.chacha = '\0'; -	el->el_search.chadir = -1; +	el->el_search.chadir = CHAR_FWD; +	el->el_search.chatflg = 0;  	return (0);  } @@ -226,8 +222,11 @@ ce_inc_search(EditLine *el, int dir)  		if (el->el_search.patlen == 0) {	/* first round */  			pchar = ':';  #ifdef ANCHOR +#define	LEN	2  			el->el_search.patbuf[el->el_search.patlen++] = '.';  			el->el_search.patbuf[el->el_search.patlen++] = '*'; +#else +#define	LEN	0  #endif  		}  		done = redo = 0; @@ -236,7 +235,7 @@ ce_inc_search(EditLine *el, int dir)  		    *cp; *el->el_line.lastchar++ = *cp++)  			continue;  		*el->el_line.lastchar++ = pchar; -		for (cp = &el->el_search.patbuf[1]; +		for (cp = &el->el_search.patbuf[LEN];  		    cp < &el->el_search.patbuf[el->el_search.patlen];  		    *el->el_line.lastchar++ = *cp++)  			continue; @@ -249,7 +248,7 @@ ce_inc_search(EditLine *el, int dir)  		switch (el->el_map.current[(unsigned char) ch]) {  		case ED_INSERT:  		case ED_DIGIT: -			if (el->el_search.patlen > EL_BUFSIZ - 3) +			if (el->el_search.patlen >= EL_BUFSIZ - LEN)  				term_beep(el);  			else {  				el->el_search.patbuf[el->el_search.patlen++] = @@ -270,8 +269,9 @@ ce_inc_search(EditLine *el, int dir)  			redo++;  			break; +		case EM_DELETE_PREV_CHAR:  		case ED_DELETE_PREV_CHAR: -			if (el->el_search.patlen > 1) +			if (el->el_search.patlen > LEN)  				done++;  			else  				term_beep(el); @@ -286,17 +286,18 @@ ce_inc_search(EditLine *el, int dir)  			case 0027:	/* ^W: Append word */  			/* No can do if globbing characters in pattern */ -				for (cp = &el->el_search.patbuf[1];; cp++) -				    if (cp >= &el->el_search.patbuf[el->el_search.patlen]) { +				for (cp = &el->el_search.patbuf[LEN];; cp++) +				    if (cp >= &el->el_search.patbuf[ +					el->el_search.patlen]) {  					el->el_line.cursor += -					    el->el_search.patlen - 1; +					    el->el_search.patlen - LEN - 1;  					cp = c__next_word(el->el_line.cursor,  					    el->el_line.lastchar, 1,  					    ce__isword);  					while (el->el_line.cursor < cp &&  					    *el->el_line.cursor != '\n') { -						if (el->el_search.patlen > -						    EL_BUFSIZ - 3) { +						if (el->el_search.patlen >= +						    EL_BUFSIZ - LEN) {  							term_beep(el);  							break;  						} @@ -338,13 +339,13 @@ ce_inc_search(EditLine *el, int dir)  			/* Can't search if unmatched '[' */  			for (cp = &el->el_search.patbuf[el->el_search.patlen-1],  			    ch = ']'; -			    cp > el->el_search.patbuf; +			    cp >= &el->el_search.patbuf[LEN];  			    cp--)  				if (*cp == '[' || *cp == ']') {  					ch = *cp;  					break;  				} -			if (el->el_search.patlen > 1 && ch != '[') { +			if (el->el_search.patlen > LEN && ch != '[') {  				if (redo && newdir == dir) {  					if (pchar == '?') { /* wrap around */  						el->el_history.eventno = @@ -374,9 +375,8 @@ ce_inc_search(EditLine *el, int dir)  				    '\0';  				if (el->el_line.cursor < el->el_line.buffer ||  				    el->el_line.cursor > el->el_line.lastchar || -				    (ret = ce_search_line(el, -				    &el->el_search.patbuf[1], -				    newdir)) == CC_ERROR) { +				    (ret = ce_search_line(el, newdir)) +				    == CC_ERROR) {  					/* avoid c_setpat */  					el->el_state.lastcmd =  					    (el_action_t) newdir; @@ -389,11 +389,11 @@ ce_inc_search(EditLine *el, int dir)  						    el->el_line.lastchar :  						    el->el_line.buffer;  						(void) ce_search_line(el, -						    &el->el_search.patbuf[1],  						    newdir);  					}  				} -				el->el_search.patbuf[--el->el_search.patlen] = +				el->el_search.patlen -= LEN; +				el->el_search.patbuf[el->el_search.patlen] =  				    '\0';  				if (ret == CC_ERROR) {  					term_beep(el); @@ -449,29 +449,20 @@ cv_search(EditLine *el, int dir)  	char tmpbuf[EL_BUFSIZ];  	int tmplen; -	tmplen = 0;  #ifdef ANCHOR -	tmpbuf[tmplen++] = '.'; -	tmpbuf[tmplen++] = '*'; +	tmpbuf[0] = '.'; +	tmpbuf[1] = '*';  #endif +	tmplen = LEN; -	el->el_line.buffer[0] = '\0'; -	el->el_line.lastchar = el->el_line.buffer; -	el->el_line.cursor = el->el_line.buffer;  	el->el_search.patdir = dir; -	c_insert(el, 2);	/* prompt + '\n' */ -	*el->el_line.cursor++ = '\n'; -	*el->el_line.cursor++ = dir == ED_SEARCH_PREV_HISTORY ? '/' : '?'; -	re_refresh(el); - -#ifdef ANCHOR -#define	LEN	2 -#else -#define	LEN	0 -#endif +	tmplen = c_gets(el, &tmpbuf[LEN], +		dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" ); +	if (tmplen == -1) +		return CC_REFRESH; -	tmplen = c_gets(el, &tmpbuf[LEN]) + LEN; +	tmplen += LEN;  	ch = tmpbuf[tmplen];  	tmpbuf[tmplen] = '\0'; @@ -480,9 +471,6 @@ cv_search(EditLine *el, int dir)  		 * Use the old pattern, but wild-card it.  		 */  		if (el->el_search.patlen == 0) { -			el->el_line.buffer[0] = '\0'; -			el->el_line.lastchar = el->el_line.buffer; -			el->el_line.cursor = el->el_line.buffer;  			re_refresh(el);  			return (CC_ERROR);  		} @@ -513,19 +501,15 @@ cv_search(EditLine *el, int dir)  	el->el_state.lastcmd = (el_action_t) dir;	/* avoid c_setpat */  	el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer;  	if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : -		ed_search_next_history(el, 0)) == CC_ERROR) { +	    ed_search_next_history(el, 0)) == CC_ERROR) {  		re_refresh(el);  		return (CC_ERROR); -	} else { -		if (ch == 0033) { -			re_refresh(el); -			*el->el_line.lastchar++ = '\n'; -			*el->el_line.lastchar = '\0'; -			re_goto_bottom(el); -			return (CC_NEWLINE); -		} else -			return (CC_REFRESH);  	} +	if (ch == 0033) { +		re_refresh(el); +		return ed_newline(el, 0); +	} +	return (CC_REFRESH);  } @@ -533,24 +517,39 @@ cv_search(EditLine *el, int dir)   *	Look for a pattern inside a line   */  protected el_action_t -ce_search_line(EditLine *el, char *pattern, int dir) +ce_search_line(EditLine *el, int dir)  { -	char *cp; +	char *cp = el->el_line.cursor; +	char *pattern = el->el_search.patbuf; +	char oc, *ocp; +#ifdef ANCHOR +	ocp = &pattern[1]; +	oc = *ocp; +	*ocp = '^'; +#else +	ocp = pattern; +	oc = *ocp; +#endif  	if (dir == ED_SEARCH_PREV_HISTORY) { -		for (cp = el->el_line.cursor; cp >= el->el_line.buffer; cp--) -			if (el_match(cp, pattern)) { +		for (; cp >= el->el_line.buffer; cp--) { +			if (el_match(cp, ocp)) { +				*ocp = oc;  				el->el_line.cursor = cp;  				return (CC_NORM);  			} +		} +		*ocp = oc;  		return (CC_ERROR);  	} else { -		for (cp = el->el_line.cursor; *cp != '\0' && -		    cp < el->el_line.limit; cp++) -			if (el_match(cp, pattern)) { +		for (; *cp != '\0' && cp < el->el_line.limit; cp++) { +			if (el_match(cp, ocp)) { +				*ocp = oc;  				el->el_line.cursor = cp;  				return (CC_NORM);  			} +		} +		*ocp = oc;  		return (CC_ERROR);  	}  } @@ -582,69 +581,53 @@ cv_repeat_srch(EditLine *el, int c)  } -/* cv_csearch_back(): - *	Vi character search reverse +/* cv_csearch(): + *	Vi character search   */  protected el_action_t -cv_csearch_back(EditLine *el, int ch, int count, int tflag) +cv_csearch(EditLine *el, int direction, int ch, int count, int tflag)  {  	char *cp; -	cp = el->el_line.cursor; -	while (count--) { -		if (*cp == ch) -			cp--; -		while (cp > el->el_line.buffer && *cp != ch) -			cp--; -	} +	if (ch == 0) +		return CC_ERROR; -	if (cp < el->el_line.buffer || (cp == el->el_line.buffer && *cp != ch)) -		return (CC_ERROR); - -	if (*cp == ch && tflag) -		cp++; - -	el->el_line.cursor = cp; - -	if (el->el_chared.c_vcmd.action & DELETE) { -		el->el_line.cursor++; -		cv_delfini(el); -		return (CC_REFRESH); +	if (ch == -1) { +		char c; +		if (el_getc(el, &c) != 1) +			return ed_end_of_file(el, 0); +		ch = c;  	} -	re_refresh_cursor(el); -	return (CC_NORM); -} - -/* cv_csearch_fwd(): - *	Vi character search forward - */ -protected el_action_t -cv_csearch_fwd(EditLine *el, int ch, int count, int tflag) -{ -	char *cp; +	/* Save for ';' and ',' commands */ +	el->el_search.chacha = ch; +	el->el_search.chadir = direction; +	el->el_search.chatflg = tflag;  	cp = el->el_line.cursor;  	while (count--) {  		if (*cp == ch) -			cp++; -		while (cp < el->el_line.lastchar && *cp != ch) -			cp++; +			cp += direction; +		for (;;cp += direction) { +			if (cp >= el->el_line.lastchar) +				return CC_ERROR; +			if (cp < el->el_line.buffer) +				return CC_ERROR; +			if (*cp == ch) +				break; +		}  	} -	if (cp >= el->el_line.lastchar) -		return (CC_ERROR); - -	if (*cp == ch && tflag) -		cp--; +	if (tflag) +		cp -= direction;  	el->el_line.cursor = cp; -	if (el->el_chared.c_vcmd.action & DELETE) { -		el->el_line.cursor++; +	if (el->el_chared.c_vcmd.action != NOP) { +		if (direction > 0) +			el->el_line.cursor++;  		cv_delfini(el); -		return (CC_REFRESH); +		return CC_REFRESH;  	} -	re_refresh_cursor(el); -	return (CC_NORM); +	return CC_CURSOR;  } @@ -1,4 +1,4 @@ -/*	$NetBSD: search.h,v 1.5 2000/09/04 22:06:32 lukem Exp $	*/ +/*	$NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -52,6 +48,7 @@ typedef struct el_search_t {  	int	 patdir;		/* Direction of the last search	*/  	int	 chadir;		/* Character search direction	*/  	char	 chacha;		/* Character we are looking for	*/ +	char	 chatflg;		/* 0 if f, 1 if t */  } el_search_t; @@ -62,9 +59,8 @@ protected int		c_hmatch(EditLine *, const char *);  protected void		c_setpat(EditLine *);  protected el_action_t	ce_inc_search(EditLine *, int);  protected el_action_t	cv_search(EditLine *, int); -protected el_action_t	ce_search_line(EditLine *, char *, int); +protected el_action_t	ce_search_line(EditLine *, int);  protected el_action_t	cv_repeat_srch(EditLine *, int); -protected el_action_t	cv_csearch_back(EditLine *, int, int, int); -protected el_action_t	cv_csearch_fwd(EditLine *, int, int, int); +protected el_action_t	cv_csearch(EditLine *, int, int, int, int);  #endif /* _h_el_search */ diff --git a/shlib_version b/shlib_version index 24699bb9eb0d..d79ab7d1f014 100644 --- a/shlib_version +++ b/shlib_version @@ -1,5 +1,5 @@ -#	$NetBSD: shlib_version,v 1.11 2001/01/01 15:54:07 jdolecek Exp $ +#	$NetBSD: shlib_version,v 1.15 2003/12/05 13:37:48 lukem Exp $  #	Remember to update distrib/sets/lists/base/shl.* when changing  #  major=2 -minor=5 +minor=9 @@ -1,4 +1,4 @@ -/*	$NetBSD: sig.c,v 1.8 2001/01/09 17:31:04 jdolecek Exp $	*/ +/*	$NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,12 +32,12 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)sig.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: sig.c,v 1.8 2001/01/09 17:31:04 jdolecek Exp $"); +__RCSID("$NetBSD: sig.c,v 1.11 2003/08/07 16:44:33 agc Exp $");  #endif  #endif /* not lint && not SCCSID */ @@ -50,7 +46,6 @@ __RCSID("$NetBSD: sig.c,v 1.8 2001/01/09 17:31:04 jdolecek Exp $");   *	  our policy is to trap all signals, set a good state   *	  and pass the ball to our caller.   */ -#include "sys.h"  #include "el.h"  #include <stdlib.h> @@ -122,9 +117,9 @@ sig_init(EditLine *el)  #undef	_DO  	    (void) sigprocmask(SIG_BLOCK, &nset, &oset); -#define	SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(sig_t)) +#define	SIGSIZE (sizeof(sighdl) / sizeof(sighdl[0]) * sizeof(el_signalhandler_t)) -	el->el_signal = (sig_t *) el_malloc(SIGSIZE); +	el->el_signal = (el_signalhandler_t *) el_malloc(SIGSIZE);  	if (el->el_signal == NULL)  		return (-1);  	for (i = 0; sighdl[i] != -1; i++) @@ -164,7 +159,7 @@ sig_set(EditLine *el)  	    (void) sigprocmask(SIG_BLOCK, &nset, &oset);  	for (i = 0; sighdl[i] != -1; i++) { -		sig_t s; +		el_signalhandler_t s;  		/* This could happen if we get interrupted */  		if ((s = signal(sighdl[i], sig_handler)) != sig_handler)  			el->el_signal[i] = s; @@ -1,4 +1,4 @@ -/*	$NetBSD: sig.h,v 1.3 2000/09/04 22:06:32 lukem Exp $	*/ +/*	$NetBSD: sig.h,v 1.5 2003/08/07 16:44:33 agc Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -62,7 +58,8 @@  	_DO(SIGCONT)	\  	_DO(SIGWINCH) -typedef sig_t	*el_signal_t; +typedef void (*el_signalhandler_t)(int); +typedef el_signalhandler_t *el_signal_t;  protected void	sig_end(EditLine*);  protected int	sig_init(EditLine*); @@ -1,4 +1,4 @@ -/*	$NetBSD: sys.h,v 1.4 2000/09/04 22:06:32 lukem Exp $	*/ +/*	$NetBSD: sys.h,v 1.9 2004/01/17 17:57:40 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -44,6 +40,24 @@  #ifndef _h_sys  #define	_h_sys +#ifdef HAVE_SYS_CDEFS_H +#include <sys/cdefs.h> +#endif + +#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__)  || __GNUC__ == 2 && __GNUC_MINOR__ < 8) +# define __attribute__(A) +#endif + +#ifndef __BEGIN_DECLS +# ifdef  __cplusplus +#  define __BEGIN_DECLS  extern "C" { +#  define __END_DECLS    } +# else +#  define __BEGIN_DECLS +#  define __END_DECLS +# endif +#endif +   #ifndef public  # define public		/* Externally visible functions/variables */  #endif @@ -57,8 +71,6 @@  			/* When we want to hide everything	*/  #endif -#include <sys/cdefs.h> -  #ifndef _PTR_T  # define _PTR_T  typedef void	*ptr_t; @@ -71,23 +83,42 @@ typedef void	*ioctl_t;  #include <stdio.h> +#ifndef HAVE_STRLCAT +#define	strlcat libedit_strlcat +size_t	strlcat(char *dst, const char *src, size_t size); +#endif + +#ifndef HAVE_STRLCPY +#define	strlcpy libedit_strlcpy +size_t	strlcpy(char *dst, const char *src, size_t size); +#endif + +#ifndef HAVE_FGETLN +#define	fgetln libedit_fgetln +char	*fgetln(FILE *fp, size_t *len); +#endif +  #define	REGEX		/* Use POSIX.2 regular expression functions */  #undef	REGEXP		/* Use UNIX V8 regular expression functions */ -#ifdef SUNOS +#ifdef notdef  # undef REGEX  # undef REGEXP  # include <malloc.h> -typedef void (*sig_t)(int);  # ifdef __GNUC__  /*   * Broken hdrs.   */ +extern int	tgetent(const char *bp, char *name); +extern int	tgetflag(const char *id); +extern int	tgetnum(const char *id); +extern char    *tgetstr(const char *id, char **area); +extern char    *tgoto(const char *cap, int col, int row); +extern int	tputs(const char *str, int affcnt, int (*putc)(int));  extern char    *getenv(const char *);  extern int	fprintf(FILE *, const char *, ...);  extern int	sigsetmask(int);  extern int	sigblock(int); -extern int	ioctl(int, int, void *);  extern int	fputc(int, FILE *);  extern int	fgetc(FILE *);  extern int	fflush(FILE *); @@ -96,7 +127,6 @@ extern int	toupper(int);  extern int	errno, sys_nerr;  extern char	*sys_errlist[];  extern void	perror(const char *); -extern int	read(int, const char*, int);  #  include <string.h>  #  define strerror(e)	sys_errlist[e]  # endif @@ -1,4 +1,4 @@ -/*	$NetBSD: term.c,v 1.32 2001/01/23 15:55:31 jdolecek Exp $	*/ +/*	$NetBSD: term.c,v 1.40 2004/05/22 23:21:28 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,12 +32,12 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)term.c	8.2 (Berkeley) 4/30/95";  #else -__RCSID("$NetBSD: term.c,v 1.32 2001/01/23 15:55:31 jdolecek Exp $"); +__RCSID("$NetBSD: term.c,v 1.40 2004/05/22 23:21:28 christos Exp $");  #endif  #endif /* not lint && not SCCSID */ @@ -50,13 +46,24 @@ __RCSID("$NetBSD: term.c,v 1.32 2001/01/23 15:55:31 jdolecek Exp $");   *	   We have to declare a static variable here, since the   *	   termcap putchar routine does not take an argument!   */ -#include "sys.h"  #include <stdio.h>  #include <signal.h>  #include <string.h>  #include <stdlib.h>  #include <unistd.h> +#ifdef HAVE_TERMCAP_H  #include <termcap.h> +#endif +#ifdef HAVE_CURSES_H +#include <curses.h> +#endif +#ifdef HAVE_NCURSES_H +#include <ncurses.h> +#endif +/* Solaris's term.h does horrid things. */ +#if (defined(HAVE_TERM_H) && !defined(SUNOS)) +#include <term.h> +#endif  #include <sys/types.h>  #include <sys/ioctl.h> @@ -261,7 +268,7 @@ private void	term_setflags(EditLine *);  private int	term_rebuffer_display(EditLine *);  private void	term_free_display(EditLine *);  private int	term_alloc_display(EditLine *); -private void	term_alloc(EditLine *, const struct termcapstr *, char *); +private void	term_alloc(EditLine *, const struct termcapstr *, const char *);  private void	term_init_arrow(EditLine *);  private void	term_reset_arrow(EditLine *); @@ -341,11 +348,11 @@ term_init(EditLine *el)  		return (-1);  	(void) memset(el->el_term.t_val, 0, T_val * sizeof(int));  	term_outfile = el->el_outfile; -	if (term_set(el, NULL) == -1) -		return (-1); +	(void) term_set(el, NULL);  	term_init_arrow(el);  	return (0);  } +  /* term_end():   *	Clean up the terminal stuff   */ @@ -362,6 +369,8 @@ term_end(EditLine *el)  	el->el_term.t_str = NULL;  	el_free((ptr_t) el->el_term.t_val);  	el->el_term.t_val = NULL; +	el_free((ptr_t) el->el_term.t_fkey); +	el->el_term.t_fkey = NULL;  	term_free_display(el);  } @@ -370,7 +379,7 @@ term_end(EditLine *el)   *	Maintain a string pool for termcap strings   */  private void -term_alloc(EditLine *el, const struct termcapstr *t, char *cap) +term_alloc(EditLine *el, const struct termcapstr *t, const char *cap)  {  	char termbuf[TC_BUFSIZE];  	int tlen, clen; @@ -638,7 +647,8 @@ mc_again:  				 * from col 0  				 */  				if (EL_CAN_TAB ? -				    (-del > (((unsigned int) where >> 3) + +				    ((unsigned int)-del > +				    (((unsigned int) where >> 3) +  				     (where & 07)))  				    : (-del > where)) {  					term__putc('\r');	/* do a CR */ @@ -658,7 +668,7 @@ mc_again:   *	Overstrike num characters   */  protected void -term_overwrite(EditLine *el, char *cp, int n) +term_overwrite(EditLine *el, const char *cp, int n)  {  	if (n <= 0)  		return;		/* catch bugs */ @@ -866,12 +876,18 @@ term_clear_to_bottom(EditLine *el)  }  #endif +protected void +term_get(EditLine *el, const char **term) +{ +	*term = el->el_term.t_name; +} +  /* term_set():   *	Read in the terminal capabilities from the requested terminal   */  protected int -term_set(EditLine *el, char *term) +term_set(EditLine *el, const char *term)  {  	int i;  	char buf[TC_BUFSIZE]; @@ -927,8 +943,11 @@ term_set(EditLine *el, char *term)  		/* Get the size */  		Val(T_co) = tgetnum("co");  		Val(T_li) = tgetnum("li"); -		for (t = tstr; t->name != NULL; t++) -			term_alloc(el, t, tgetstr(t->name, &area)); +		for (t = tstr; t->name != NULL; t++) { +			/* XXX: some systems tgetstr needs non const */ +			term_alloc(el, t, tgetstr(strchr(t->name, *t->name), +			    &area)); +		}  	}  	if (Val(T_co) < 2) @@ -947,6 +966,7 @@ term_set(EditLine *el, char *term)  		return (-1);  	(void) sigprocmask(SIG_SETMASK, &oset, NULL);  	term_bind_arrow(el); +	el->el_term.t_name = term;  	return (i <= 0 ? -1 : 0);  } @@ -1102,7 +1122,7 @@ term_reset_arrow(EditLine *el)   *	Set an arrow key binding   */  protected int -term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type) +term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type)  {  	fkey_t *arrow = el->el_term.t_fkey;  	int i; @@ -1121,7 +1141,7 @@ term_set_arrow(EditLine *el, char *name, key_value_t *fun, int type)   *	Clear an arrow key binding   */  protected int -term_clear_arrow(EditLine *el, char *name) +term_clear_arrow(EditLine *el, const char *name)  {  	fkey_t *arrow = el->el_term.t_fkey;  	int i; @@ -1139,7 +1159,7 @@ term_clear_arrow(EditLine *el, char *name)   *	Print the arrow key bindings   */  protected void -term_print_arrow(EditLine *el, char *name) +term_print_arrow(EditLine *el, const char *name)  {  	int i;  	fkey_t *arrow = el->el_term.t_fkey; @@ -1236,7 +1256,8 @@ term__flush(void)   */  protected int  /*ARGSUSED*/ -term_telltc(EditLine *el, int argc, char **argv) +term_telltc(EditLine *el, int argc __attribute__((__unused__)),  +    const char **argv __attribute__((__unused__)))  {  	const struct termcapstr *t;  	char **ts; @@ -1271,11 +1292,12 @@ term_telltc(EditLine *el, int argc, char **argv)   */  protected int  /*ARGSUSED*/ -term_settc(EditLine *el, int argc, char **argv) +term_settc(EditLine *el, int argc __attribute__((__unused__)), +    const char **argv)  {  	const struct termcapstr *ts;  	const struct termcapval *tv; -	char *what, *how; +	const char *what, *how;  	if (argv == NULL || argv[1] == NULL || argv[2] == NULL)  		return (-1); @@ -1347,7 +1369,8 @@ term_settc(EditLine *el, int argc, char **argv)   */  protected int  /*ARGSUSED*/ -term_echotc(EditLine *el, int argc, char **argv) +term_echotc(EditLine *el, int argc __attribute__((__unused__)), +    const char **argv)  {  	char *cap, *scap, *ep;  	int arg_need, arg_cols, arg_rows; @@ -1406,7 +1429,7 @@ term_echotc(EditLine *el, int argc, char **argv)  			}  		(void) fprintf(el->el_outfile, fmtd, 0);  #else -		(void) fprintf(el->el_outfile, fmtd, el->el_tty.t_speed); +		(void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed);  #endif  		return (0);  	} else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { @@ -1425,8 +1448,10 @@ term_echotc(EditLine *el, int argc, char **argv)  			scap = el->el_term.t_str[t - tstr];  			break;  		} -	if (t->name == NULL) -		scap = tgetstr(*argv, &area); +	if (t->name == NULL) { +		/* XXX: some systems tgetstr needs non const */ +		scap = tgetstr(strchr(*argv, **argv), &area); +	}  	if (!scap || scap[0] == '\0') {  		if (!silent)  			(void) fprintf(el->el_errfile, @@ -1,4 +1,4 @@ -/*	$NetBSD: term.h,v 1.12 2001/01/04 15:56:32 christos Exp $	*/ +/*	$NetBSD: term.h,v 1.16 2005/03/15 00:10:40 christos Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -47,13 +43,14 @@  #include "histedit.h"  typedef struct {		/* Symbolic function key bindings	*/ -	char		*name;	/* name of the key			*/ +	const char	*name;	/* name of the key			*/  	int		 key;	/* Index in termcap table		*/  	key_value_t	 fun;	/* Function bound to it			*/  	int		 type;	/* Type of function			*/  } fkey_t;  typedef struct { +	const char *t_name;		/* the terminal name	*/  	coord_t	  t_size;		/* # lines and cols	*/  	int	  t_flags;  #define	TERM_CAN_INSERT		0x001	/* Has insert cap	*/ @@ -87,7 +84,7 @@ typedef struct {  protected void	term_move_to_line(EditLine *, int);  protected void	term_move_to_char(EditLine *, int);  protected void	term_clear_EOL(EditLine *, int); -protected void	term_overwrite(EditLine *, char *, int); +protected void	term_overwrite(EditLine *, const char *, int);  protected void	term_insertwrite(EditLine *, char *, int);  protected void	term_deletechars(EditLine *, int);  protected void	term_clear_screen(EditLine *); @@ -96,14 +93,15 @@ protected int	term_change_size(EditLine *, int, int);  protected int	term_get_size(EditLine *, int *, int *);  protected int	term_init(EditLine *);  protected void	term_bind_arrow(EditLine *); -protected void	term_print_arrow(EditLine *, char *); -protected int	term_clear_arrow(EditLine *, char *); -protected int	term_set_arrow(EditLine *, char *, key_value_t *, int); +protected void	term_print_arrow(EditLine *, const char *); +protected int	term_clear_arrow(EditLine *, const char *); +protected int	term_set_arrow(EditLine *, const char *, key_value_t *, int);  protected void	term_end(EditLine *); -protected int	term_set(EditLine *, char *); -protected int	term_settc(EditLine *, int, char **); -protected int	term_telltc(EditLine *, int, char **); -protected int	term_echotc(EditLine *, int, char **); +protected void	term_get(EditLine *, const char **); +protected int	term_set(EditLine *, const char *); +protected int	term_settc(EditLine *, int, const char **); +protected int	term_telltc(EditLine *, int, const char **); +protected int	term_echotc(EditLine *, int, const char **);  protected int	term__putc(int);  protected void	term__flush(void); @@ -117,6 +115,7 @@ protected void	term__flush(void);  #define	EL_CAN_CEOL		(EL_FLAGS & TERM_CAN_CEOL)  #define	EL_CAN_TAB		(EL_FLAGS & TERM_CAN_TAB)  #define	EL_CAN_ME		(EL_FLAGS & TERM_CAN_ME) +#define EL_CAN_UP		(EL_FLAGS & TERM_CAN_UP)  #define	EL_HAS_META		(EL_FLAGS & TERM_HAS_META)  #define	EL_HAS_AUTO_MARGINS	(EL_FLAGS & TERM_HAS_AUTO_MARGINS)  #define	EL_HAS_MAGIC_MARGINS	(EL_FLAGS & TERM_HAS_MAGIC_MARGINS) diff --git a/tokenizer.c b/tokenizer.c index ed9f3652fa49..b8a263332f8d 100644 --- a/tokenizer.c +++ b/tokenizer.c @@ -1,4 +1,4 @@ -/*	$NetBSD: tokenizer.c,v 1.7 2001/01/04 15:56:32 christos Exp $	*/ +/*	$NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,22 +32,21 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)tokenizer.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: tokenizer.c,v 1.7 2001/01/04 15:56:32 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.14 2003/12/05 13:37:48 lukem Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * tokenize.c: Bourne shell like tokenizer   */ -#include "sys.h"  #include <string.h>  #include <stdlib.h> -#include "tokenizer.h" +#include "histedit.h"  typedef enum {  	Q_none, Q_single, Q_double, Q_one, Q_doubleone @@ -65,6 +60,7 @@ typedef enum {  #define	WINCR		20  #define	AINCR		10 +#define	tok_strdup(a)		strdup(a)  #define	tok_malloc(a)		malloc(a)  #define	tok_free(a)		free(a)  #define	tok_realloc(a, b)	realloc(a, b) @@ -110,16 +106,29 @@ tok_init(const char *ifs)  {  	Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); -	tok->ifs = strdup(ifs ? ifs : IFS); +	if (tok == NULL) +		return NULL; +	tok->ifs = tok_strdup(ifs ? ifs : IFS); +	if (tok->ifs == NULL) { +		tok_free((ptr_t)tok); +		return NULL; +	}  	tok->argc = 0;  	tok->amax = AINCR;  	tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); -	if (tok->argv == NULL) -		return (NULL); +	if (tok->argv == NULL) { +		tok_free((ptr_t)tok->ifs); +		tok_free((ptr_t)tok); +		return NULL; +	}  	tok->argv[0] = NULL;  	tok->wspace = (char *) tok_malloc(WINCR); -	if (tok->wspace == NULL) -		return (NULL); +	if (tok->wspace == NULL) { +		tok_free((ptr_t)tok->argv); +		tok_free((ptr_t)tok->ifs); +		tok_free((ptr_t)tok); +		return NULL; +	}  	tok->wmax = tok->wspace + WINCR;  	tok->wstart = tok->wspace;  	tok->wptr = tok->wspace; @@ -161,21 +170,39 @@ tok_end(Tokenizer *tok)  /* tok_line(): - *	Bourne shell like tokenizing - *	Return: - *		-1: Internal error - *		 3: Quoted return - *		 2: Unmatched double quote - *		 1: Unmatched single quote - *		 0: Ok + *	Bourne shell (sh(1)) like tokenizing + *	Arguments: + *		tok	current tokenizer state (setup with tok_init()) + *		line	line to parse + *	Returns: + *		-1	Internal error + *		 3	Quoted return + *		 2	Unmatched double quote + *		 1	Unmatched single quote + *		 0	Ok + *	Modifies (if return value is 0): + *		argc	number of arguments + *		argv	argument array + *		cursorc	if !NULL, argv element containing cursor + *		cursorv	if !NULL, offset in argv[cursorc] of cursor   */  public int -tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv) +tok_line(Tokenizer *tok, const LineInfo *line, +    int *argc, const char ***argv, int *cursorc, int *cursoro)  {  	const char *ptr; - -	for (;;) { -		switch (*(ptr = line++)) { +	int cc, co; + +	cc = co = -1; +	ptr = line->buffer; +	for (ptr = line->buffer; ;ptr++) { +		if (ptr >= line->lastchar) +			ptr = ""; +		if (ptr == line->cursor) { +			cc = tok->argc; +			co = tok->wptr - tok->wstart; +		} +		switch (*ptr) {  		case '\'':  			tok->flags |= TOK_KEEP;  			tok->flags &= ~TOK_EAT; @@ -274,10 +301,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)  			tok->flags &= ~TOK_EAT;  			switch (tok->quote) {  			case Q_none: -				tok_finish(tok); -				*argv = tok->argv; -				*argc = tok->argc; -				return (0); +				goto tok_line_outok;  			case Q_single:  			case Q_double: @@ -307,10 +331,7 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)  					tok->flags &= ~TOK_EAT;  					return (3);  				} -				tok_finish(tok); -				*argv = tok->argv; -				*argc = tok->argc; -				return (0); +				goto tok_line_outok;  			case Q_single:  				return (1); @@ -370,20 +391,20 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)  		if (tok->wptr >= tok->wmax - 4) {  			size_t size = tok->wmax - tok->wspace + WINCR;  			char *s = (char *) tok_realloc(tok->wspace, size); -			/* SUPPRESS 22 */ -			int offs = s - tok->wspace;  			if (s == NULL)  				return (-1); -			if (offs != 0) { +			if (s != tok->wspace) {  				int i; -				for (i = 0; i < tok->argc; i++) -					tok->argv[i] = tok->argv[i] + offs; -				tok->wptr = tok->wptr + offs; -				tok->wstart = tok->wstart + offs; -				tok->wmax = s + size; +				for (i = 0; i < tok->argc; i++) { +				    tok->argv[i] = +					(tok->argv[i] - tok->wspace) + s; +				} +				tok->wptr = (tok->wptr - tok->wspace) + s; +				tok->wstart = (tok->wstart - tok->wspace) + s;  				tok->wspace = s;  			} +			tok->wmax = s + size;  		}  		if (tok->argc >= tok->amax - 4) {  			char **p; @@ -395,4 +416,32 @@ tok_line(Tokenizer *tok, const char *line, int *argc, char ***argv)  			tok->argv = p;  		}  	} + tok_line_outok: +	if (cc == -1 && co == -1) { +		cc = tok->argc; +		co = tok->wptr - tok->wstart; +	} +	if (cursorc != NULL) +		*cursorc = cc; +	if (cursoro != NULL) +		*cursoro = co; +	tok_finish(tok); +	*argv = (const char **)tok->argv; +	*argc = tok->argc; +	return (0); +} + +/* tok_str(): + *	Simpler version of tok_line, taking a NUL terminated line + *	and splitting into words, ignoring cursor state. + */ +public int +tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv) +{ +	LineInfo li; + +	memset(&li, 0, sizeof(li)); +	li.buffer = line; +	li.cursor = li.lastchar = strchr(line, '\0'); +	return (tok_line(tok, &li, argc, argv, NULL, NULL));  } diff --git a/tokenizer.h b/tokenizer.h deleted file mode 100644 index 775891921327..000000000000 --- a/tokenizer.h +++ /dev/null @@ -1,54 +0,0 @@ -/*	$NetBSD: tokenizer.h,v 1.4 2000/09/04 22:06:33 lukem Exp $	*/ - -/*- - * Copyright (c) 1992, 1993 - *	The Regents of the University of California.  All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Christos Zoulas of Cornell University. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - *    may be used to endorse or promote products derived from this software - *    without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *	@(#)tokenizer.h	8.1 (Berkeley) 6/4/93 - */ - -/* - * tokenizer.h: Header file for tokenizer routines - */ -#ifndef _h_tokenizer -#define	_h_tokenizer - -typedef struct tokenizer Tokenizer; - -Tokenizer	*tok_init(const char *); -void		 tok_reset(Tokenizer *); -void		 tok_end(Tokenizer *); -int		 tok_line(Tokenizer *, const char *, int *, char ***); - -#endif /* _h_tokenizer */ @@ -1,4 +1,4 @@ -/*	$NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $	*/ +/*	$NetBSD: tty.c,v 1.23 2005/06/01 11:37:52 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,32 +32,32 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h"  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)tty.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: tty.c,v 1.15 2001/05/17 01:02:17 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.23 2005/06/01 11:37:52 lukem Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * tty.c: tty interface stuff   */ -#include "sys.h" +#include <assert.h>  #include "tty.h"  #include "el.h"  typedef struct ttymodes_t {  	const char *m_name; -	u_int m_value; +	unsigned int m_value;  	int m_type;  }          ttymodes_t;  typedef struct ttymap_t {  	int nch, och;		/* Internal and termio rep of chars */  	el_action_t bind[3];	/* emacs, vi, and vi-cmd */ -}        ttymap_t; +} ttymap_t;  private const ttyperm_t ttyperm = { @@ -125,11 +121,11 @@ private const ttychar_t ttychar = {  private const ttymap_t tty_map[] = {  #ifdef VERASE  	{C_ERASE, VERASE, -	{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, +	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},  #endif /* VERASE */  #ifdef VERASE2  	{C_ERASE2, VERASE2, -	{ED_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}}, +	{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},  #endif /* VERASE2 */  #ifdef VKILL  	{C_KILL, VKILL, @@ -456,6 +452,7 @@ private const ttymodes_t ttymodes[] = {  #define	tty__geteightbit(td)	(((td)->c_cflag & CSIZE) == CS8)  #define	tty__cooked_mode(td)	((td)->c_lflag & ICANON) +private int	tty__getcharindex(int);  private void	tty__getchar(struct termios *, unsigned char *);  private void	tty__setchar(struct termios *, unsigned char *);  private speed_t	tty__getspeed(struct termios *); @@ -569,7 +566,7 @@ tty_init(EditLine *el)   */  protected void  /*ARGSUSED*/ -tty_end(EditLine *el) +tty_end(EditLine *el __attribute__((__unused__)))  {  	/* XXX: Maybe reset to an initial state? */ @@ -589,6 +586,113 @@ tty__getspeed(struct termios *td)  	return (spd);  } +/* tty__getspeed(): + *	Return the index of the asked char in the c_cc array + */ +private int +tty__getcharindex(int i) +{ +	switch (i) { +#ifdef VINTR +	case C_INTR: +		return VINTR; +#endif /* VINTR */ +#ifdef VQUIT +	case C_QUIT: +		return VQUIT; +#endif /* VQUIT */ +#ifdef VERASE +	case C_ERASE: +		return VERASE; +#endif /* VERASE */ +#ifdef VKILL +	case C_KILL: +		return VKILL; +#endif /* VKILL */ +#ifdef VEOF +	case C_EOF: +		return VEOF; +#endif /* VEOF */ +#ifdef VEOL +	case C_EOL: +		return VEOL; +#endif /* VEOL */ +#ifdef VEOL2 +	case C_EOL2: +		return VEOL2; +#endif /* VEOL2 */ +#ifdef VSWTCH +	case C_SWTCH: +		return VSWTCH; +#endif /* VSWTCH */ +#ifdef VDSWTCH +	case C_DSWTCH: +		return VDSWTCH; +#endif /* VDSWTCH */ +#ifdef VERASE2 +	case C_ERASE2: +		return VERASE2; +#endif /* VERASE2 */ +#ifdef VSTART +	case C_START: +		return VSTART; +#endif /* VSTART */ +#ifdef VSTOP +	case C_STOP: +		return VSTOP; +#endif /* VSTOP */ +#ifdef VWERASE +	case C_WERASE: +		return VWERASE; +#endif /* VWERASE */ +#ifdef VSUSP +	case C_SUSP: +		return VSUSP; +#endif /* VSUSP */ +#ifdef VDSUSP +	case C_DSUSP: +		return VDSUSP; +#endif /* VDSUSP */ +#ifdef VREPRINT +	case C_REPRINT: +		return VREPRINT; +#endif /* VREPRINT */ +#ifdef VDISCARD +	case C_DISCARD: +		return VDISCARD; +#endif /* VDISCARD */ +#ifdef VLNEXT +	case C_LNEXT: +		return VLNEXT; +#endif /* VLNEXT */ +#ifdef VSTATUS +	case C_STATUS: +		return VSTATUS; +#endif /* VSTATUS */ +#ifdef VPAGE +	case C_PAGE: +		return VPAGE; +#endif /* VPAGE */ +#ifdef VPGOFF +	case C_PGOFF: +		return VPGOFF; +#endif /* VPGOFF */ +#ifdef VKILL2 +	case C_KILL2: +		return VKILL2; +#endif /* KILL2 */ +#ifdef VMIN +	case C_MIN: +		return VMIN; +#endif /* VMIN */ +#ifdef VTIME +	case C_TIME: +		return VTIME; +#endif /* VTIME */ +	default: +		return -1; +	} +}  /* tty__getchar():   *	Get the tty characters @@ -1042,13 +1146,14 @@ tty_noquotemode(EditLine *el)   */  protected int  /*ARGSUSED*/ -tty_stty(EditLine *el, int argc, char **argv) +tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv)  {  	const ttymodes_t *m; -	char x, *d; +	char x;  	int aflag = 0; -	char *s; -	char *name; +	const char *s, *d; +	const char *name; +	struct termios *tios = &el->el_tty.t_ex;  	int z = EX_IO;  	if (argv == NULL) @@ -1063,14 +1168,17 @@ tty_stty(EditLine *el, int argc, char **argv)  			break;  		case 'd':  			argv++; +			tios = &el->el_tty.t_ed;  			z = ED_IO;  			break;  		case 'x':  			argv++; +			tios = &el->el_tty.t_ex;  			z = EX_IO;  			break;  		case 'q':  			argv++; +			tios = &el->el_tty.t_ts;  			z = QU_IO;  			break;  		default: @@ -1120,6 +1228,7 @@ tty_stty(EditLine *el, int argc, char **argv)  		return (0);  	}  	while (argv && (s = *argv++)) { +		const char *p;  		switch (*s) {  		case '+':  		case '-': @@ -1130,8 +1239,11 @@ tty_stty(EditLine *el, int argc, char **argv)  			break;  		}  		d = s; +		p = strchr(s, '=');  		for (m = ttymodes; m->m_name; m++) -			if (strcmp(m->m_name, d) == 0) +			if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) : +			    strcmp(m->m_name, d)) == 0 && +			    (p == NULL || m->m_type == MD_CHAR))  				break;  		if (!m->m_name) { @@ -1139,6 +1251,16 @@ tty_stty(EditLine *el, int argc, char **argv)  			    "%s: Invalid argument `%s'.\n", name, d);  			return (-1);  		} +		if (p) { +			int c = ffs((int)m->m_value); +			int v = *++p ? parse__escape((const char **) &p) : +			    el->el_tty.t_vdisable; +			assert(c-- != 0); +			c = tty__getcharindex(c); +			assert(c != -1); +			tios->c_cc[c] = v; +			continue; +		}  		switch (x) {  		case '+':  			el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; @@ -1,4 +1,4 @@ -/*	$NetBSD: tty.h,v 1.8 2000/09/04 22:06:33 lukem Exp $	*/ +/*	$NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -453,16 +449,16 @@  #define	MD_NN	5  typedef struct { -	char	*t_name; -	u_int	 t_setmask; -	u_int	 t_clrmask; +	const char	*t_name; +	unsigned int	 t_setmask; +	unsigned int	 t_clrmask;  } ttyperm_t[NN_IO][MD_NN];  typedef unsigned char ttychar_t[NN_IO][C_NCC];  protected int	tty_init(EditLine *);  protected void	tty_end(EditLine *); -protected int	tty_stty(EditLine *, int, char**); +protected int	tty_stty(EditLine *, int, const char **);  protected int	tty_rawmode(EditLine *);  protected int	tty_cookedmode(EditLine *);  protected int	tty_quotemode(EditLine *); @@ -1,4 +1,4 @@ -/*	$NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $	*/ +/*	$NetBSD: vi.c,v 1.21 2005/04/25 01:06:03 matt Exp $	*/  /*-   * Copyright (c) 1992, 1993 @@ -15,11 +15,7 @@   * 2. Redistributions in binary form must reproduce the above copyright   *    notice, this list of conditions and the following disclaimer in the   *    documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - *    must display the following acknowledgement: - *	This product includes software developed by the University of - *	California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors + * 3. Neither the name of the University nor the names of its contributors   *    may be used to endorse or promote products derived from this software   *    without specific prior written permission.   * @@ -36,19 +32,22 @@   * SUCH DAMAGE.   */ -#include <sys/cdefs.h> +#include "config.h" +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> +  #if !defined(lint) && !defined(SCCSID)  #if 0  static char sccsid[] = "@(#)vi.c	8.1 (Berkeley) 6/4/93";  #else -__RCSID("$NetBSD: vi.c,v 1.8 2000/09/04 22:06:33 lukem Exp $"); +__RCSID("$NetBSD: vi.c,v 1.21 2005/04/25 01:06:03 matt Exp $");  #endif  #endif /* not lint && not SCCSID */  /*   * vi.c: Vi mode commands.   */ -#include "sys.h"  #include "el.h"  private el_action_t	cv_action(EditLine *, int); @@ -60,22 +59,18 @@ private el_action_t	cv_paste(EditLine *, int);  private el_action_t  cv_action(EditLine *el, int c)  { -	char *cp, *kp; -	if (el->el_chared.c_vcmd.action & DELETE) { +	if (el->el_chared.c_vcmd.action != NOP) { +		/* 'cc', 'dd' and (possibly) friends */ +		if (c != el->el_chared.c_vcmd.action) +			return CC_ERROR; + +		if (!(c & YANK)) +			cv_undo(el); +		cv_yank(el, el->el_line.buffer, +			    el->el_line.lastchar - el->el_line.buffer);  		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;  		el->el_line.lastchar = el->el_line.buffer;  		el->el_line.cursor = el->el_line.buffer;  		if (c & INSERT) @@ -86,25 +81,8 @@ cv_action(EditLine *el, int c)  	el->el_chared.c_vcmd.pos = el->el_line.cursor;  	el->el_chared.c_vcmd.action = c;  	return (CC_ARGHACK); - -#ifdef notdef -	/* -         * I don't think that this is needed. But we keep it for now -         */ -	else -	if (el_chared.c_vcmd.action == NOP) { -		el->el_chared.c_vcmd.pos = el->el_line.cursor; -		el->el_chared.c_vcmd.action = c; -		return (CC_ARGHACK); -	} else { -		el->el_chared.c_vcmd.action = 0; -		el->el_chared.c_vcmd.pos = 0; -		return (CC_ERROR); -	} -#endif  } -  /* cv_paste():   *	Paste previous deletion before or after the cursor   */ @@ -112,23 +90,25 @@ private el_action_t  cv_paste(EditLine *el, int c)  {  	char *ptr; -	c_undo_t *un = &el->el_chared.c_undo; +	c_kill_t *k = &el->el_chared.c_kill; +	int len = k->last - k->buf; +	if (k->buf == NULL || len == 0) +		return (CC_ERROR);  #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", len, k->buf);  #endif -	if (un->isize == 0) -		return (CC_ERROR); + +	cv_undo(el);  	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, len); +	if (el->el_line.cursor + len > el->el_line.lastchar)  		return (CC_ERROR); -	(void) memcpy(ptr, un->buf, un->isize); +	(void) memcpy(ptr, k->buf, len +0u);  	return (CC_REFRESH);  } @@ -139,7 +119,7 @@ cv_paste(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_paste_next(EditLine *el, int c) +vi_paste_next(EditLine *el, int c __attribute__((__unused__)))  {  	return (cv_paste(el, 0)); @@ -152,31 +132,31 @@ vi_paste_next(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_paste_prev(EditLine *el, int c) +vi_paste_prev(EditLine *el, int c __attribute__((__unused__)))  {  	return (cv_paste(el, 1));  } -/* 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) { +	if (el->el_chared.c_vcmd.action != NOP) {  		cv_delfini(el);  		return (CC_REFRESH);  	} @@ -186,22 +166,22 @@ vi_prev_space_word(EditLine *el, int c)  /* vi_prev_word():   *	Vi move to the previous word - *	[B] + *	[b]   */  protected el_action_t  /*ARGSUSED*/ -vi_prev_word(EditLine *el, int c) +vi_prev_word(EditLine *el, int c __attribute__((__unused__)))  {  	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) { +	if (el->el_chared.c_vcmd.action != NOP) {  		cv_delfini(el);  		return (CC_REFRESH);  	} @@ -209,25 +189,23 @@ vi_prev_word(EditLine *el, int c)  } -/* 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) +	if (el->el_line.cursor >= el->el_line.lastchar - 1)  		return (CC_ERROR);  	el->el_line.cursor = cv_next_word(el, el->el_line.cursor, -	    el->el_line.lastchar, -	    el->el_state.argument, -	    cv__isword); +	    el->el_line.lastchar, el->el_state.argument, cv__isWord);  	if (el->el_map.type == MAP_VI) -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -241,19 +219,17 @@ vi_next_space_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_next_word(EditLine *el, int c) +vi_next_word(EditLine *el, int c __attribute__((__unused__)))  { -	if (el->el_line.cursor == el->el_line.lastchar) +	if (el->el_line.cursor >= el->el_line.lastchar - 1)  		return (CC_ERROR);  	el->el_line.cursor = cv_next_word(el, el->el_line.cursor, -	    el->el_line.lastchar, -	    el->el_state.argument, -	    ce__isword); +	    el->el_line.lastchar, el->el_state.argument, cv__isword);  	if (el->el_map.type == MAP_VI) -		if (el->el_chared.c_vcmd.action & DELETE) { +		if (el->el_chared.c_vcmd.action != NOP) {  			cv_delfini(el);  			return (CC_REFRESH);  		} @@ -268,19 +244,27 @@ vi_next_word(EditLine *el, int c)  protected el_action_t  vi_change_case(EditLine *el, int c)  { +	int i; -	if (el->el_line.cursor < el->el_line.lastchar) { -		c = *el->el_line.cursor; +	if (el->el_line.cursor >= el->el_line.lastchar) +		return (CC_ERROR); +	cv_undo(el); +	for (i = 0; i < el->el_state.argument; i++) { + +		c = *(unsigned char *)el->el_line.cursor;  		if (isupper(c)) -			*el->el_line.cursor++ = tolower(c); +			*el->el_line.cursor = tolower(c);  		else if (islower(c)) -			*el->el_line.cursor++ = toupper(c); -		else -			el->el_line.cursor++; +			*el->el_line.cursor = toupper(c); + +		if (++el->el_line.cursor >= el->el_line.lastchar) { +			el->el_line.cursor--; +			re_fastaddc(el); +			break; +		}  		re_fastaddc(el); -		return (CC_NORM);  	} -	return (CC_ERROR); +	return CC_NORM;  } @@ -290,7 +274,7 @@ vi_change_case(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_change_meta(EditLine *el, int c) +vi_change_meta(EditLine *el, int c __attribute__((__unused__)))  {  	/* @@ -307,15 +291,11 @@ vi_change_meta(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_insert_at_bol(EditLine *el, int c) +vi_insert_at_bol(EditLine *el, int c __attribute__((__unused__)))  {  	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);  	el->el_map.current = el->el_map.key;  	return (CC_CURSOR);  } @@ -327,16 +307,16 @@ vi_insert_at_bol(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_replace_char(EditLine *el, int c) +vi_replace_char(EditLine *el, int c __attribute__((__unused__)))  { +	if (el->el_line.cursor >= el->el_line.lastchar) +		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); +	return (CC_ARGHACK);  } @@ -346,26 +326,23 @@ vi_replace_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_replace_mode(EditLine *el, int c) +vi_replace_mode(EditLine *el, int c __attribute__((__unused__)))  {  	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);  	return (CC_NORM);  }  /* vi_substitute_char():   *	Vi replace character under the cursor and enter insert mode - *	[r] + *	[s]   */  protected el_action_t  /*ARGSUSED*/ -vi_substitute_char(EditLine *el, int c) +vi_substitute_char(EditLine *el, int c __attribute__((__unused__)))  {  	c_delafter(el, el->el_state.argument); @@ -380,9 +357,12 @@ vi_substitute_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_substitute_line(EditLine *el, int c) +vi_substitute_line(EditLine *el, int c __attribute__((__unused__)))  { +	cv_undo(el); +	cv_yank(el, el->el_line.buffer, +		    el->el_line.lastchar - el->el_line.buffer);  	(void) em_kill_line(el, 0);  	el->el_map.current = el->el_map.key;  	return (CC_REFRESH); @@ -395,9 +375,12 @@ vi_substitute_line(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_change_to_eol(EditLine *el, int c) +vi_change_to_eol(EditLine *el, int c __attribute__((__unused__)))  { +	cv_undo(el); +	cv_yank(el, el->el_line.cursor, +		    el->el_line.lastchar - el->el_line.cursor);  	(void) ed_kill_line(el, 0);  	el->el_map.current = el->el_map.key;  	return (CC_REFRESH); @@ -410,15 +393,11 @@ vi_change_to_eol(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_insert(EditLine *el, int c) +vi_insert(EditLine *el, int c __attribute__((__unused__)))  {  	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);  	return (CC_NORM);  } @@ -429,7 +408,7 @@ vi_insert(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_add(EditLine *el, int c) +vi_add(EditLine *el, int c __attribute__((__unused__)))  {  	int ret; @@ -442,9 +421,7 @@ vi_add(EditLine *el, int c)  	} 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);  	return (ret);  } @@ -456,16 +433,12 @@ vi_add(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_add_at_eol(EditLine *el, int c) +vi_add_at_eol(EditLine *el, int c __attribute__((__unused__)))  {  	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);  	return (CC_CURSOR);  } @@ -476,29 +449,29 @@ vi_add_at_eol(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_delete_meta(EditLine *el, int c) +vi_delete_meta(EditLine *el, int c __attribute__((__unused__)))  {  	return (cv_action(el, DELETE));  } -/* 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) { +	if (el->el_chared.c_vcmd.action != NOP) {  		el->el_line.cursor++;  		cv_delfini(el);  		return (CC_REFRESH); @@ -507,22 +480,22 @@ vi_end_word(EditLine *el, int c)  } -/* 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 __attribute__((__unused__)))  {  	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) { +	if (el->el_chared.c_vcmd.action != NOP) {  		el->el_line.cursor++;  		cv_delfini(el);  		return (CC_REFRESH); @@ -537,102 +510,21 @@ vi_to_end_word(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_undo(EditLine *el, int c) +vi_undo(EditLine *el, int c __attribute__((__unused__)))  { -	char *cp, *kp; -	char temp; -	int i, size; -	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); +	c_undo_t un = el->el_chared.c_undo; -		(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; +	if (un.len == -1) +		return CC_ERROR; -	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; - -	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);  } @@ -644,24 +536,14 @@ vi_undo(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_command_mode(EditLine *el, int c) +vi_command_mode(EditLine *el, int c __attribute__((__unused__)))  { -	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; @@ -681,42 +563,32 @@ protected el_action_t  vi_zero(EditLine *el, int c)  { -	if (el->el_state.doingarg) { -		if (el->el_state.argument > 1000000) -			return (CC_ERROR); -		el->el_state.argument = -		    (el->el_state.argument * 10) + (c - '0'); -		return (CC_ARGHACK); -	} else { -		el->el_line.cursor = el->el_line.buffer; -		if (el->el_chared.c_vcmd.action & DELETE) { -			cv_delfini(el); -			return (CC_REFRESH); -		} -		return (CC_CURSOR); +	if (el->el_state.doingarg) +		return ed_argument_digit(el, c); + +	el->el_line.cursor = el->el_line.buffer; +	if (el->el_chared.c_vcmd.action != NOP) { +		cv_delfini(el); +		return (CC_REFRESH);  	} +	return (CC_CURSOR);  }  /* 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) +vi_delete_prev_char(EditLine *el, int c __attribute__((__unused__)))  { -	if (el->el_chared.c_vcmd.ins == 0) +	if (el->el_line.cursor <= el->el_line.buffer)  		return (CC_ERROR); -	if (el->el_chared.c_vcmd.ins > -	    el->el_line.cursor - el->el_state.argument) -		return (CC_ERROR); - -	c_delbefore(el, el->el_state.argument); -	el->el_line.cursor -= el->el_state.argument; - +	c_delbefore1(el); +	el->el_line.cursor--;  	return (CC_REFRESH);  } @@ -727,23 +599,35 @@ vi_delete_prev_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_list_or_eof(EditLine *el, int c) +vi_list_or_eof(EditLine *el, int c __attribute__((__unused__)))  { -#ifdef notyet -	if (el->el_line.cursor == el->el_line.lastchar && -	    el->el_line.cursor == el->el_line.buffer) { -#endif -		term_overwrite(el, STReof, 4);	/* then do a EOF */ -		term__flush(); -		return (CC_EOF); -#ifdef notyet +	if (el->el_line.cursor == el->el_line.lastchar) { +		if (el->el_line.cursor == el->el_line.buffer) { +			term_overwrite(el, STReof, 4);	/* then do a EOF */ +			term__flush(); +			return (CC_EOF); +		} else { +			/* +			 * Here we could list completions, but it is an +			 * error right now +			 */ +			term_beep(el); +			return (CC_ERROR); +		}  	} else { +#ifdef notyet  		re_goto_bottom(el);  		*el->el_line.lastchar = '\0';	/* just in case */  		return (CC_LIST_CHOICES); -	} +#else +		/* +		 * Just complain for now. +		 */ +		term_beep(el); +		return (CC_ERROR);  #endif +	}  } @@ -753,7 +637,7 @@ vi_list_or_eof(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_kill_line_prev(EditLine *el, int c) +vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__)))  {  	char *kp, *cp; @@ -774,7 +658,7 @@ vi_kill_line_prev(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_search_prev(EditLine *el, int c) +vi_search_prev(EditLine *el, int c __attribute__((__unused__)))  {  	return (cv_search(el, ED_SEARCH_PREV_HISTORY)); @@ -787,7 +671,7 @@ vi_search_prev(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_search_next(EditLine *el, int c) +vi_search_next(EditLine *el, int c __attribute__((__unused__)))  {  	return (cv_search(el, ED_SEARCH_NEXT_HISTORY)); @@ -800,7 +684,7 @@ vi_search_next(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_repeat_search_next(EditLine *el, int c) +vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_search.patlen == 0) @@ -816,7 +700,7 @@ vi_repeat_search_next(EditLine *el, int c)   */  /*ARGSUSED*/  protected el_action_t -vi_repeat_search_prev(EditLine *el, int c) +vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__)))  {  	if (el->el_search.patlen == 0) @@ -834,18 +718,9 @@ vi_repeat_search_prev(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_next_char(EditLine *el, int c) +vi_next_char(EditLine *el, int c __attribute__((__unused__)))  { -	char ch; - -	if (el_getc(el, &ch) != 1) -		return (ed_end_of_file(el, 0)); - -	el->el_search.chadir = CHAR_FWD; -	el->el_search.chacha = ch; - -	return (cv_csearch_fwd(el, ch, el->el_state.argument, 0)); - +	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0);  } @@ -855,17 +730,9 @@ vi_next_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_prev_char(EditLine *el, int c) +vi_prev_char(EditLine *el, int c __attribute__((__unused__)))  { -	char ch; - -	if (el_getc(el, &ch) != 1) -		return (ed_end_of_file(el, 0)); - -	el->el_search.chadir = CHAR_BACK; -	el->el_search.chacha = ch; - -	return (cv_csearch_back(el, ch, el->el_state.argument, 0)); +	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0);  } @@ -875,15 +742,9 @@ vi_prev_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_to_next_char(EditLine *el, int c) +vi_to_next_char(EditLine *el, int c __attribute__((__unused__)))  { -	char ch; - -	if (el_getc(el, &ch) != 1) -		return (ed_end_of_file(el, 0)); - -	return (cv_csearch_fwd(el, ch, el->el_state.argument, 1)); - +	return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1);  } @@ -893,14 +754,9 @@ vi_to_next_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_to_prev_char(EditLine *el, int c) +vi_to_prev_char(EditLine *el, int c __attribute__((__unused__)))  { -	char ch; - -	if (el_getc(el, &ch) != 1) -		return (ed_end_of_file(el, 0)); - -	return (cv_csearch_back(el, ch, el->el_state.argument, 1)); +	return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1);  } @@ -910,17 +766,11 @@ vi_to_prev_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_repeat_next_char(EditLine *el, int c) +vi_repeat_next_char(EditLine *el, int c __attribute__((__unused__)))  { -	if (el->el_search.chacha == 0) -		return (CC_ERROR); - -	return (el->el_search.chadir == CHAR_FWD -	    ? cv_csearch_fwd(el, el->el_search.chacha, -		el->el_state.argument, 0) -	    : cv_csearch_back(el, el->el_search.chacha, -		el->el_state.argument, 0)); +	return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, +		el->el_state.argument, el->el_search.chatflg);  } @@ -930,13 +780,345 @@ vi_repeat_next_char(EditLine *el, int c)   */  protected el_action_t  /*ARGSUSED*/ -vi_repeat_prev_char(EditLine *el, int c) +vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__)))  { +	el_action_t r; +	int dir = el->el_search.chadir; -	if (el->el_search.chacha == 0) -		return (CC_ERROR); +	r = cv_csearch(el, -dir, el->el_search.chacha, +		el->el_state.argument, el->el_search.chatflg); +	el->el_search.chadir = dir; +	return r; +} + + +/* vi_match(): + *	Vi go to matching () {} or [] + *	[%] + */ +protected el_action_t +/*ARGSUSED*/ +vi_match(EditLine *el, int c) +{ +	const char match_chars[] = "()[]{}"; +	char *cp; +	int delta, i, count; +	char o_ch, c_ch; + +	*el->el_line.lastchar = '\0';		/* just in case */ + +	i = strcspn(el->el_line.cursor, match_chars); +	o_ch = el->el_line.cursor[i]; +	if (o_ch == 0) +		return CC_ERROR; +	delta = strchr(match_chars, o_ch) - match_chars; +	c_ch = match_chars[delta ^ 1]; +	count = 1; +	delta = 1 - (delta & 1) * 2; + +	for (cp = &el->el_line.cursor[i]; count; ) { +		cp += delta; +		if (cp < el->el_line.buffer || cp >= el->el_line.lastchar) +			return CC_ERROR; +		if (*cp == o_ch) +			count++; +		else if (*cp == c_ch) +			count--; +	} + +	el->el_line.cursor = cp; + +	if (el->el_chared.c_vcmd.action != NOP) { +		/* NB posix says char under cursor should NOT be deleted +		   for -ve delta - this is different to netbsd vi. */ +		if (delta > 0) +			el->el_line.cursor++; +		cv_delfini(el); +		return (CC_REFRESH); +	} +	return (CC_CURSOR); +} + +/* vi_undo_line(): + *	Vi undo all changes to line + *	[U] + */ +protected el_action_t +/*ARGSUSED*/ +vi_undo_line(EditLine *el, int c) +{ + +	cv_undo(el); +	return hist_get(el); +} + +/* vi_to_column(): + *	Vi go to specified column + *	[|] + * NB netbsd vi goes to screen column 'n', posix says nth character + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_column(EditLine *el, int c) +{ + +	el->el_line.cursor = el->el_line.buffer; +	el->el_state.argument--; +	return ed_next_char(el, 0); +} + +/* vi_yank_end(): + *	Vi yank to end of line + *	[Y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank_end(EditLine *el, int c) +{ + +	cv_yank(el, el->el_line.cursor, +		el->el_line.lastchar - el->el_line.cursor); +	return CC_REFRESH; +} + +/* vi_yank(): + *	Vi yank + *	[y] + */ +protected el_action_t +/*ARGSUSED*/ +vi_yank(EditLine *el, int c) +{ + +	return cv_action(el, YANK); +} + +/* vi_comment_out(): + *	Vi comment out current command + *	[c] + */ +protected el_action_t +/*ARGSUSED*/ +vi_comment_out(EditLine *el, int c) +{ + +	el->el_line.cursor = el->el_line.buffer; +	c_insert(el, 1); +	*el->el_line.cursor = '#'; +	re_refresh(el); +	return ed_newline(el, 0); +} + +/* vi_alias(): + *	Vi include shell alias + *	[@] + * NB: posix impiles that we should enter insert mode, however + * this is against historical precedent... + */ +protected el_action_t +/*ARGSUSED*/ +vi_alias(EditLine *el, int c) +{ +#ifdef __weak_extern +	char alias_name[3]; +	char *alias_text; +	extern char *get_alias_text(const char *); +	__weak_extern(get_alias_text); + +	if (get_alias_text == 0) { +		return CC_ERROR; +	} + +	alias_name[0] = '_'; +	alias_name[2] = 0; +	if (el_getc(el, &alias_name[1]) != 1) +		return CC_ERROR; + +	alias_text = get_alias_text(alias_name); +	if (alias_text != NULL) +		el_push(el, alias_text); +	return CC_NORM; +#else +	return CC_ERROR; +#endif +} + +/* vi_to_history_line(): + *	Vi go to specified history file line. + *	[G] + */ +protected el_action_t +/*ARGSUSED*/ +vi_to_history_line(EditLine *el, int c) +{ +	int sv_event_no = el->el_history.eventno; +	el_action_t rval; + + +	if (el->el_history.eventno == 0) { +		 (void) strncpy(el->el_history.buf, el->el_line.buffer, +		     EL_BUFSIZ); +		 el->el_history.last = el->el_history.buf + +			 (el->el_line.lastchar - el->el_line.buffer); +	} + +	/* Lack of a 'count' means oldest, not 1 */ +	if (!el->el_state.doingarg) { +		el->el_history.eventno = 0x7fffffff; +		hist_get(el); +	} else { +		/* This is brain dead, all the rest of this code counts +		 * upwards going into the past.  Here we need count in the +		 * other direction (to match the output of fc -l). +		 * I could change the world, but this seems to suffice. +		 */ +		el->el_history.eventno = 1; +		if (hist_get(el) == CC_ERROR) +			return CC_ERROR; +		el->el_history.eventno = 1 + el->el_history.ev.num  +					- el->el_state.argument; +		if (el->el_history.eventno < 0) { +			el->el_history.eventno = sv_event_no; +			return CC_ERROR; +		} +	} +	rval = hist_get(el); +	if (rval == CC_ERROR) +		el->el_history.eventno = sv_event_no; +	return rval; +} + +/* vi_histedit(): + *	Vi edit history line with vi + *	[v] + */ +protected el_action_t +/*ARGSUSED*/ +vi_histedit(EditLine *el, int c) +{ +	int fd; +	pid_t pid; +	int st; +	char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; +	char *cp; + +	if (el->el_state.doingarg) { +		if (vi_to_history_line(el, 0) == CC_ERROR) +			return CC_ERROR; +	} + +	fd = mkstemp(tempfile); +	if (fd < 0) +		return CC_ERROR; +	cp = el->el_line.buffer; +	write(fd, cp, el->el_line.lastchar - cp +0u); +	write(fd, "\n", 1); +	pid = fork(); +	switch (pid) { +	case -1: +		close(fd); +		unlink(tempfile); +		return CC_ERROR; +	case 0: +		close(fd); +		execlp("vi", "vi", tempfile, NULL); +		exit(0); +		/*NOTREACHED*/ +	default: +		while (waitpid(pid, &st, 0) != pid) +			continue; +		lseek(fd, 0ll, SEEK_SET); +		st = read(fd, cp, el->el_line.limit - cp +0u); +		if (st > 0 && cp[st - 1] == '\n') +			st--; +		el->el_line.cursor = cp; +		el->el_line.lastchar = cp + st; +		break; +	} + +	close(fd); +	unlink(tempfile); +	/* return CC_REFRESH; */ +	return ed_newline(el, 0); +} + +/* vi_history_word(): + *	Vi append word from previous input line + *	[_] + * Who knows where this one came from! + * '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_' + */ +protected el_action_t +/*ARGSUSED*/ +vi_history_word(EditLine *el, int c) +{ +	const char *wp = HIST_FIRST(el); +	const char *wep, *wsp; +	int len; +	char *cp; +	const char *lim; + +	if (wp == NULL) +		return CC_ERROR; + +	wep = wsp = 0; +	do { +		while (isspace((unsigned char)*wp)) +			wp++; +		if (*wp == 0) +			break; +		wsp = wp; +		while (*wp && !isspace((unsigned char)*wp)) +			wp++; +		wep = wp; +	} while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); + +	if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) +		return CC_ERROR; + +	cv_undo(el); +	len = wep - wsp; +	if (el->el_line.cursor < el->el_line.lastchar) +		el->el_line.cursor++; +	c_insert(el, len + 1); +	cp = el->el_line.cursor; +	lim = el->el_line.limit; +	if (cp < lim) +		*cp++ = ' '; +	while (wsp < wep && cp < lim) +		*cp++ = *wsp++; +	el->el_line.cursor = cp; + +	el->el_map.current = el->el_map.key; +	return CC_REFRESH; +} + +/* vi_redo(): + *	Vi redo last non-motion command + *	[.] + */ +protected el_action_t +/*ARGSUSED*/ +vi_redo(EditLine *el, int c) +{ +	c_redo_t *r = &el->el_chared.c_redo; + +	if (!el->el_state.doingarg && r->count) { +		el->el_state.doingarg = 1; +		el->el_state.argument = r->count; +	} + +	el->el_chared.c_vcmd.pos = el->el_line.cursor; +	el->el_chared.c_vcmd.action = r->action; +	if (r->pos != r->buf) { +		if (r->pos + 1 > r->lim) +			/* sanity */ +			r->pos = r->lim - 1; +		r->pos[0] = 0; +		el_push(el, r->buf); +	} -	return el->el_search.chadir == CHAR_BACK ? -	    cv_csearch_fwd(el, el->el_search.chacha, el->el_state.argument, 0) : -	    cv_csearch_back(el, el->el_search.chacha, el->el_state.argument, 0); +	el->el_state.thiscmd = r->cmd; +	el->el_state.thisch = r->ch; +	return  (*el->el_map.func[r->cmd])(el, r->ch);  } | 
