diff options
author | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-11-25 20:12:40 +0000 |
---|---|---|
committer | Otto Moerbeek <otto@cvs.openbsd.org> | 2003-11-25 20:12:40 +0000 |
commit | 8dec545c586449d9e5f4a74c285ae295727a6e6d (patch) | |
tree | 24ede7fd8fd6d4bfc330f35ece0d823d276f1a3f /lib | |
parent | 735da5f8c0917e2182e8f693897d286fe0456ef8 (diff) |
Sync libedit to NetBSD libedit as of Nov 8, 2003.
Tested by jmc@ djm@ and myself
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libedit/TEST/Makefile | 10 | ||||
-rw-r--r-- | lib/libedit/chared.c | 10 | ||||
-rw-r--r-- | lib/libedit/chared.h | 6 | ||||
-rw-r--r-- | lib/libedit/editline.3 | 10 | ||||
-rw-r--r-- | lib/libedit/editrc.5 | 7 | ||||
-rw-r--r-- | lib/libedit/el.c | 22 | ||||
-rw-r--r-- | lib/libedit/el.h | 5 | ||||
-rw-r--r-- | lib/libedit/emacs.c | 12 | ||||
-rw-r--r-- | lib/libedit/hist.c | 6 | ||||
-rw-r--r-- | lib/libedit/histedit.h | 5 | ||||
-rw-r--r-- | lib/libedit/history.c | 9 | ||||
-rw-r--r-- | lib/libedit/key.c | 9 | ||||
-rw-r--r-- | lib/libedit/parse.c | 17 | ||||
-rw-r--r-- | lib/libedit/read.c | 44 | ||||
-rw-r--r-- | lib/libedit/readline.c | 987 | ||||
-rw-r--r-- | lib/libedit/readline/readline.h | 27 | ||||
-rw-r--r-- | lib/libedit/search.c | 71 | ||||
-rw-r--r-- | lib/libedit/search.h | 6 | ||||
-rw-r--r-- | lib/libedit/tokenizer.c | 9 | ||||
-rw-r--r-- | lib/libedit/tty.c | 133 |
20 files changed, 909 insertions, 496 deletions
diff --git a/lib/libedit/TEST/Makefile b/lib/libedit/TEST/Makefile new file mode 100644 index 00000000000..2881d408dc4 --- /dev/null +++ b/lib/libedit/TEST/Makefile @@ -0,0 +1,10 @@ +# $OpenBSD: Makefile,v 1.1 2003/11/25 20:12:39 otto Exp $ +# $NetBSD: Makefile,v 1.1 2003/10/16 21:41:46 christos Exp $ + +NOMAN=1 +PROG=test +CPPFLAGS=-I${.CURDIR}/.. +LDADD+=-ledit -ltermcap +DPADD+=${LIBEDIT} ${LIBTERMCAP} + +.include <bsd.prog.mk> diff --git a/lib/libedit/chared.c b/lib/libedit/chared.c index 0275dfe6c81..5320542aea7 100644 --- a/lib/libedit/chared.c +++ b/lib/libedit/chared.c @@ -1,5 +1,5 @@ -/* $OpenBSD: chared.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: chared.c,v 1.19 2003/08/07 16:44:30 agc Exp $ */ +/* $OpenBSD: chared.c,v 1.8 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: chared.c,v 1.21 2003/11/02 20:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: chared.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: chared.c,v 1.8 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -457,8 +457,8 @@ 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.offset = 0; el->el_chared.c_macro.macro = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); if (el->el_chared.c_macro.macro == NULL) @@ -579,7 +579,7 @@ ch_enlargebufs(el, addlen) return 0; /* Safe to set enlarged buffer size */ - el->el_line.limit = &newbuffer[newsz - EL_LEAVE]; + el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; return 1; } diff --git a/lib/libedit/chared.h b/lib/libedit/chared.h index 8192eace5ee..1408237f946 100644 --- a/lib/libedit/chared.h +++ b/lib/libedit/chared.h @@ -1,5 +1,5 @@ -/* $OpenBSD: chared.h,v 1.7 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: chared.h,v 1.12 2003/08/07 16:44:30 agc Exp $ */ +/* $OpenBSD: chared.h,v 1.8 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: chared.h,v 1.13 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -63,8 +63,8 @@ typedef struct c_macro_t { int level; + int offset; char **macro; - char *nline; } c_macro_t; /* diff --git a/lib/libedit/editline.3 b/lib/libedit/editline.3 index 510c2199164..189d5b75862 100644 --- a/lib/libedit/editline.3 +++ b/lib/libedit/editline.3 @@ -1,5 +1,5 @@ -.\" $OpenBSD: editline.3,v 1.18 2003/11/03 05:23:49 jmc Exp $ -.\" $NetBSD: editline.3,v 1.38 2003/09/26 21:09:13 wiz Exp $ +.\" $OpenBSD: editline.3,v 1.19 2003/11/25 20:12:38 otto Exp $ +.\" $NetBSD: editline.3,v 1.42 2003/11/04 13:22:19 christos Exp $ .\" .\" Copyright (c) 1997-1999 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -34,7 +34,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd September 26, 2003 +.Dd October 17, 2003 .Os .Dt EDITLINE 3 .Sh NAME @@ -431,6 +431,8 @@ 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 @@ -609,7 +611,7 @@ the history. .El .Pp .Fn history -returns >= 0 if the operation succeeds +returns \*(Ge 0 if the operation succeeds .Fa op succeeds. Otherwise, \-1 is returned and diff --git a/lib/libedit/editrc.5 b/lib/libedit/editrc.5 index 79485312cf8..4cc6fecf45e 100644 --- a/lib/libedit/editrc.5 +++ b/lib/libedit/editrc.5 @@ -1,5 +1,5 @@ -.\" $OpenBSD: editrc.5,v 1.18 2003/11/01 07:00:07 otto Exp $ -.\" $NetBSD: editrc.5,v 1.16 2003/06/27 18:57:09 wiz Exp $ +.\" $OpenBSD: editrc.5,v 1.19 2003/11/25 20:12:38 otto 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. @@ -34,7 +34,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 @@ -242,6 +242,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 diff --git a/lib/libedit/el.c b/lib/libedit/el.c index d798dad8491..bd61447e2ad 100644 --- a/lib/libedit/el.c +++ b/lib/libedit/el.c @@ -1,5 +1,5 @@ -/* $OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: el.c,v 1.34 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: el.c,v 1.13 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: el.c,v 1.36 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -static const char rcsid[] = "$OpenBSD: el.c,v 1.12 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: el.c,v 1.13 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -69,7 +69,10 @@ 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!!! @@ -77,7 +80,7 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr) el->el_flags = 0; if (term_init(el) == -1) { - free(el->el_prog); + el_free(el->el_prog); el_free(el); return NULL; } @@ -266,6 +269,15 @@ el_set(EditLine *el, int op, ...) rv = 0; break; + case EL_PREP_TERM: + rv = va_arg(va, int); + if (rv) + read_prepare(el); + else + read_finish(el); + rv = 0; + break; + default: rv = -1; break; diff --git a/lib/libedit/el.h b/lib/libedit/el.h index b926292bf40..53c10221be8 100644 --- a/lib/libedit/el.h +++ b/lib/libedit/el.h @@ -1,5 +1,5 @@ -/* $OpenBSD: el.h,v 1.5 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: el.h,v 1.15 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: el.h,v 1.6 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: el.h,v 1.16 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -89,6 +89,7 @@ typedef struct 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) diff --git a/lib/libedit/emacs.c b/lib/libedit/emacs.c index 59b01ac31fc..b0e13cbaa79 100644 --- a/lib/libedit/emacs.c +++ b/lib/libedit/emacs.c @@ -1,5 +1,5 @@ -/* $OpenBSD: emacs.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: emacs.c,v 1.15 2003/08/07 16:44:31 agc Exp $ */ +/* $OpenBSD: emacs.c,v 1.7 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: emacs.c,v 1.16 2003/11/02 20:07:58 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: emacs.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: emacs.c,v 1.7 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -120,10 +120,8 @@ 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) >= diff --git a/lib/libedit/hist.c b/lib/libedit/hist.c index 5d99e27c573..e56206ba745 100644 --- a/lib/libedit/hist.c +++ b/lib/libedit/hist.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hist.c,v 1.6 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: hist.c,v 1.14 2003/08/07 16:44:31 agc Exp $ */ +/* $OpenBSD: hist.c,v 1.7 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: hist.c,v 1.6 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: hist.c,v 1.7 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ diff --git a/lib/libedit/histedit.h b/lib/libedit/histedit.h index 6b2fdee861c..86b372fe284 100644 --- a/lib/libedit/histedit.h +++ b/lib/libedit/histedit.h @@ -1,5 +1,5 @@ -/* $OpenBSD: histedit.h,v 1.8 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: histedit.h,v 1.23 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: histedit.h,v 1.9 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: histedit.h,v 1.24 2003/10/16 22:26:32 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -129,6 +129,7 @@ int el_get(EditLine *, int, void *); #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) diff --git a/lib/libedit/history.c b/lib/libedit/history.c index c9d440b8736..fafdc325a41 100644 --- a/lib/libedit/history.c +++ b/lib/libedit/history.c @@ -1,5 +1,5 @@ -/* $OpenBSD: history.c,v 1.11 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: history.c,v 1.24 2003/08/07 16:44:31 agc Exp $ */ +/* $OpenBSD: history.c,v 1.12 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: history.c,v 1.25 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: history.c,v 1.11 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: history.c,v 1.12 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -88,6 +88,7 @@ struct history { #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 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) @@ -395,7 +396,7 @@ history_def_insert(history_t *h, HistEvent *ev, const char *str) h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); if (h->cursor == NULL) goto oomem; - if ((h->cursor->ev.str = strdup(str)) == NULL) { + if ((h->cursor->ev.str = h_strdup(str)) == NULL) { h_free((ptr_t)h->cursor); goto oomem; } diff --git a/lib/libedit/key.c b/lib/libedit/key.c index 215ee4987dd..eba3dbbcf84 100644 --- a/lib/libedit/key.c +++ b/lib/libedit/key.c @@ -1,5 +1,5 @@ -/* $OpenBSD: key.c,v 1.8 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: key.c,v 1.14 2003/08/07 16:44:31 agc Exp $ */ +/* $OpenBSD: key.c,v 1.9 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: key.c,v 1.15 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: key.c,v 1.8 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: key.c,v 1.9 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -353,7 +353,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)); diff --git a/lib/libedit/parse.c b/lib/libedit/parse.c index a884e8bc866..9dbc09083ae 100644 --- a/lib/libedit/parse.c +++ b/lib/libedit/parse.c @@ -1,5 +1,5 @@ -/* $OpenBSD: parse.c,v 1.7 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: parse.c,v 1.17 2003/08/07 16:44:32 agc Exp $ */ +/* $OpenBSD: parse.c,v 1.8 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: parse.c,v 1.19 2003/11/02 20:06:57 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: parse.c,v 1.7 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: parse.c,v 1.8 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -203,7 +203,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 @@ -211,6 +211,7 @@ parse__escape(const char **const ptr) *ptr = ++p; return (c); } + /* parse__string(): * Parse the escapes from in and put the raw string out */ @@ -233,6 +234,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; diff --git a/lib/libedit/read.c b/lib/libedit/read.c index 0eedfeea778..28686ff81f3 100644 --- a/lib/libedit/read.c +++ b/lib/libedit/read.c @@ -1,5 +1,5 @@ -/* $OpenBSD: read.c,v 1.10 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: read.c,v 1.28 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: read.c,v 1.11 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: read.c,v 1.30 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: read.c,v 1.10 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: read.c,v 1.11 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -188,10 +188,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); @@ -204,8 +200,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 */ @@ -224,11 +219,12 @@ el_push(EditLine *el, char *str) if (str != NULL && ma->level + 1 < EL_MAXMACRO) { ma->level++; - ma->macro[ma->level] = str; - } else { - term_beep(el); - term__flush(); + if ((ma->macro[ma->level] = el_strdup(str)) != NULL) + return; + ma->level--; } + term_beep(el); + term__flush(); } @@ -325,14 +321,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); } @@ -553,7 +551,13 @@ el_gets(EditLine *el, int *nread) 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++ = CTRL('d'); + el->el_line.cursor = el->el_line.lastchar; + num = 1; + } break; case CC_NEWLINE: /* normal end of line */ diff --git a/lib/libedit/readline.c b/lib/libedit/readline.c index 88077a275c6..f0e52ec5b43 100644 --- a/lib/libedit/readline.c +++ b/lib/libedit/readline.c @@ -1,5 +1,5 @@ -/* $OpenBSD: readline.c,v 1.1 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: readline.c,v 1.35 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: readline.c,v 1.2 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: readline.c,v 1.43 2003/11/03 03:22:55 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -39,7 +39,7 @@ #include "config.h" #if !defined(lint) && !defined(SCCSID) -static const char rcsid[] = "$OpenBSD: readline.c,v 1.1 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD"; #endif /* not lint && not SCCSID */ #include <sys/types.h> @@ -52,20 +52,27 @@ static const char rcsid[] = "$OpenBSD: readline.c,v 1.1 2003/10/31 08:42:24 otto #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 "histedit.h" #include "readline/readline.h" #include "el.h" +#include "tokenizer.h" #include "fcns.h" /* for EL_NUM_FCNS */ /* 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 */ @@ -81,6 +88,8 @@ int rl_point = 0; int rl_end = 0; char *rl_line_buffer = NULL; VFunction *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; @@ -89,6 +98,7 @@ char history_expansion_char = '!'; char history_subst_char = '^'; 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; @@ -104,6 +114,7 @@ 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; @@ -154,12 +165,13 @@ static int el_rl_complete_cmdnum = 0; static unsigned char _el_rl_complete(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); + const char *, int); static int rl_complete_internal(int); static int _rl_qsort_string_compare(const void *, const void *); +static int _rl_event_read_char(EditLine *, char *); /* ARGSUSED */ @@ -184,7 +196,7 @@ _move_history(int op) return (HIST_ENTRY *) NULL; rl_he.line = ev.str; - rl_he.data = ""; + rl_he.data = NULL; return (&rl_he); } @@ -244,7 +256,7 @@ rl_initialize(void) 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 */ @@ -303,10 +315,13 @@ readline(const char *prompt) 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 = ""; @@ -320,6 +335,16 @@ readline(const char *prompt) 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 */ @@ -368,66 +393,173 @@ static char * _rl_compat_sub(const char *str, const char *what, const char *with, int globally) { - char *result; - const char *temp, *new; - size_t 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)); - if (result == NULL) - return NULL; - 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) { - char *nresult; - size += add + 1; - nresult = realloc(result, size); - if (nresult == NULL) { - free(result); - return NULL; - } - result = nresult; - } - (void) strncpy(&result[len], temp, i); - len += i; - (void) strlcpy(&result[len], with, size - len); - len += with_len; - temp = new + what_len; - } else { - add = strlen(temp); - if (len + add + 1 >= size) { - char *nresult; - size += add + 1; - nresult = realloc(result, size); - if (nresult == NULL) { - free(result); - return NULL; - } - result = nresult; + + /* 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++; + } + len++; + r = result = malloc(len); + 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; + len -= with_len; + s += what_len; + if (!globally) { + (void)strlcpy(r, s, len); + return(result); } - (void) strlcpy(&result[len], temp, size - len); - 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, @@ -435,139 +567,140 @@ _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'; + int qchar; - if (history(h, &ev, H_CURR) != 0) - return (-1); - curr_num = ev.num; - - 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); - if (line == NULL) - return 0; 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 == '&') { @@ -587,13 +720,12 @@ _history_expand_command(const char *command, size_t cmdlen, char **result) } len = 0; for (; *cmd && *cmd != delim; cmd++) { - if (*cmd == '\\' - && *(cmd + 1) == delim) + if (*cmd == '\\' && cmd[1] == delim) cmd++; if (len >= size) { char *nwhat; nwhat = realloc(what, - (size <<= 1)); + (size <<= 1)); if (nwhat == NULL) { free(what); return 0; @@ -639,9 +771,8 @@ _history_expand_command(const char *command, size_t cmdlen, char **result) with = nwith; } if (*cmd == '&') { - /* safe */ - (void) strlcpy(&with[len], - from, size - len); + (void)strlcpy(&with[len], from, + size - len); len += from_len; continue; } @@ -653,88 +784,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); - if (tempcmd) { - 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) strlcpy(arr[i], temp + 1, strlen(arr[i]) + 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) strlcpy(arr[i], temp, strlen(arr[i]) + 1); - } - cmdsize = 1, cmdlen = 0; - if ((tempcmd = malloc(cmdsize)) == NULL) - return 0; - for (i = start; start <= i && i <= end; i++) { - int arr_len; - - arr_len = strlen(arr[i]); - if (cmdlen + arr_len + 1 >= cmdsize) { - char *ntempcmd; - cmdsize += arr_len + 1; - ntempcmd = realloc(tempcmd, cmdsize); - if (ntempcmd == NULL) { - free(tempcmd); - return 0; + aptr = _rl_compat_sub(tmp, from, to, g_on); + if (aptr) { + free(tmp); + tmp = aptr; } - tempcmd = ntempcmd; + g_on = 0; } - (void) strlcpy(&tempcmd[cmdlen], arr[i], cmdsize); - 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); } @@ -744,28 +805,37 @@ _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 (*output == NULL) - return 0; + 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^ */ size_t sz = 4 + strlen(str) + 1; - temp = alloca(sz); - temp[0] = temp[1] = history_expansion_char; - temp[2] = ':'; - temp[3] = 's'; - (void) strlcpy(temp + 4, str, sz - 4); - str = temp; + *output = malloc(sz); + if (*output == NULL) + return 0; + (*output)[0] = (*output)[1] = history_expansion_char; + (*output)[2] = ':'; + (*output)[3] = 's'; + (void)strlcpy((*output) + 4, str, sz - 4); + 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) { \ char *nresult = realloc(result, (size += len + 1));\ @@ -783,9 +853,10 @@ 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: @@ -793,26 +864,25 @@ loop: if (str[j] == '\\' && str[j + 1] == history_expansion_char) { size_t sz = strlen(&str[j]) + 1; - (void) strlcpy(&str[j], &str[j + 1], sz); + (void)strlcpy(&str[j], &str[j + 1], sz); 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++; @@ -820,61 +890,117 @@ 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++; + max = len; + result = malloc(len); + if (result == NULL) + return NULL; + + for (i = start, len = 0; i <= end; i++) { + (void)strlcpy(result + len, arr[i], max - len); + 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++; @@ -886,9 +1012,11 @@ 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; nresult = realloc(result, size * sizeof(char *)); @@ -901,15 +1029,18 @@ history_tokenize(const char *str) len = i - start; temp = malloc(len + 1); if (temp == NULL) { + for (i = 0; i < idx; i++) + free(result[i]); free(result); return NULL; } - (void) strncpy(temp, &str[start], len); + (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); } @@ -993,28 +1124,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); } @@ -1031,11 +1163,11 @@ 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 */ } @@ -1117,22 +1249,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); } @@ -1161,10 +1288,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; @@ -1175,38 +1302,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)); } @@ -1216,7 +1330,7 @@ history_search_prefix(const char *str, int direction) */ /* ARGSUSED */ int -history_search_pos(const char *str, +history_search_pos(const char *str, int direction __attribute__((__unused__)), int pos) { HistEvent ev; @@ -1248,7 +1362,7 @@ history_search_pos(const char *str, /********************************/ -/* completion functions */ +/* completion functions */ /* * does tilde expansion of strings of type ``~user/foo'' @@ -1277,7 +1391,7 @@ tilde_expand(char *txt) temp = malloc(len); if (temp == NULL) return NULL; - (void) strncpy(temp, txt + 1, len - 2); + (void)strncpy(temp, txt + 1, len - 2); temp[len - 2] = '\0'; } pass = getpwnam(temp); @@ -1293,7 +1407,7 @@ tilde_expand(char *txt) temp = malloc(len); if (temp == NULL) return NULL; - (void) snprintf(temp, len, "%s/%s", pass->pw_dir, txt); + (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt); return (temp); } @@ -1329,7 +1443,7 @@ filename_completion_function(const char *text, int state) return NULL; } filename = nptr; - (void) strlcpy(filename, temp, sz); + (void)strlcpy(filename, temp, sz); len = temp - text; /* including last slash */ nptr = realloc(dirname, len + 1); if (nptr == NULL) { @@ -1337,12 +1451,16 @@ filename_completion_function(const char *text, int state) return NULL; } dirname = nptr; - (void) strncpy(dirname, text, len); + (void)strncpy(dirname, text, len); dirname[len] = '\0'; } else { - filename = strdup(text); - if (filename == NULL) - return NULL; + if (*text == 0) + filename = NULL; + else { + filename = strdup(text); + if (filename == NULL) + return NULL; + } dirname = NULL; } @@ -1353,20 +1471,18 @@ filename_completion_function(const char *text, int state) temp = tilde_expand(dirname); if (temp == NULL) return NULL; - sz = strlen(temp) + 1; + sz = strlen(temp) + 1; nptr = realloc(dirname, sz); if (nptr == NULL) { free(dirname); return NULL; } dirname = nptr; - (void) strlcpy(dirname, temp, sz); + (void)strlcpy(dirname, temp, sz); free(temp); /* no longer needed */ } /* will be used in cycle */ - filename_len = strlen(filename); - if (filename_len == 0) - return (NULL); /* no expansion possible */ + filename_len = filename ? strlen(filename) : 0; if (dir != NULL) { (void)closedir(dir); @@ -1378,6 +1494,12 @@ filename_completion_function(const char *text, int state) } /* 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] @@ -1403,7 +1525,7 @@ filename_completion_function(const char *text, int state) temp = malloc(len); if (temp == NULL) return NULL; - (void) snprintf(temp, len, "%s%s", + (void)snprintf(temp, len, "%s%s", dirname ? dirname : "", entry->d_name); /* test, if it's directory */ @@ -1514,7 +1636,7 @@ completion_matches(const char *text, CPFunction *genfunc) free(match_list); return NULL; } - (void) strncpy(retstr, match_list[1], max_equal); + (void)strncpy(retstr, match_list[1], max_equal); retstr[max_equal] = '\0'; match_list[0] = retstr; @@ -1569,9 +1691,10 @@ rl_display_match_list (matches, len, max) 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"); + for(i = 0; i < limit && matches[idx]; i++, idx++) + (void)fprintf(e->el_outfile, "%-*s ", max, + matches[idx]); + (void)fprintf(e->el_outfile, "\n"); } } @@ -1610,12 +1733,12 @@ rl_complete_internal(int what_to_do) while (ctemp > li->buffer && !strchr(rl_basic_word_break_characters, ctemp[-1]) && (!rl_special_prefixes - || !strchr(rl_special_prefixes, ctemp[-1]) ) ) + || !strchr(rl_special_prefixes, ctemp[-1]) ) ) ctemp--; len = li->cursor - ctemp; temp = alloca(len + 1); - (void) strncpy(temp, ctemp, len); + (void)strncpy(temp, ctemp, len); temp[len] = '\0'; /* these can be used by function called in completion_matches() */ @@ -1623,13 +1746,14 @@ rl_complete_internal(int what_to_do) rl_point = li->cursor - li->buffer; rl_end = li->lastchar - li->buffer; - if (!rl_attempted_completion_function) - matches = completion_matches(temp, (CPFunction *)complet_func); - else { + if (rl_attempted_completion_function) { int end = li->cursor - li->buffer; matches = (*rl_attempted_completion_function) (temp, (int) (end - len), end); - } + } else + matches = 0; + if (!rl_attempted_completion_function || !matches) + matches = completion_matches(temp, (CPFunction *)complet_func); if (matches) { int i, retval = CC_REFRESH; @@ -1678,20 +1802,20 @@ rl_complete_internal(int what_to_do) matches_num = i - 1; /* newline to get on next line from command line */ - fprintf(e->el_outfile, "\n"); + (void)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); + (void)fprintf(e->el_outfile, + "Display all %d possibilities? (y or n) ", + matches_num); + (void)fflush(e->el_outfile); if (getc(stdin) != 'y') match_display = 0; - fprintf(e->el_outfile, "\n"); + (void)fprintf(e->el_outfile, "\n"); } if (match_display) @@ -1836,6 +1960,11 @@ rl_bind_wrapper(EditLine *el, unsigned char c) if (map[c] == NULL) return CC_ERROR; (*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; } @@ -1847,23 +1976,32 @@ rl_add_defun(const char *name, Function *fun, int c) return -1; map[(unsigned char)c] = fun; el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); - el_set(e, EL_BIND, vis(dest, c, VIS_WHITE, 0), name); + 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; + int count = 0, done = 0; const char *buf = el_gets(e, &count); char *wbuf; if (buf == NULL || count-- <= 0) return; - if ((buf[count] == '\n' || buf[count] == '\r') && rl_linefunc != NULL) { + 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 ((wbuf = strdup(buf)) != NULL) - wbuf[count] = '\0'; + if (done == 2) { + if ((wbuf = strdup(buf)) != NULL) + wbuf[count] = '\0'; + } else + wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); } } @@ -1906,3 +2044,88 @@ rl_get_previous_history(int count, int key) 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_line(tok, line, &argc, &argv); + argc = el_parse(e, argc, argv); + tok_end(tok); + return (argc ? 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); +} diff --git a/lib/libedit/readline/readline.h b/lib/libedit/readline/readline.h index 18f70a85d03..b06e499b39d 100644 --- a/lib/libedit/readline/readline.h +++ b/lib/libedit/readline/readline.h @@ -1,5 +1,5 @@ -/* $OpenBSD: readline.h,v 1.1 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: readline.h,v 1.8 2003/09/26 17:44:51 christos Exp $ */ +/* $OpenBSD: readline.h,v 1.2 2003/11/25 20:12:39 otto Exp $ */ +/* $NetBSD: readline.h,v 1.10 2003/10/27 22:26:35 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _READLINE_H_ -#define _READLINE_H_ +#define _READLINE_H_ #include <sys/types.h> @@ -56,9 +56,9 @@ typedef struct _hist_entry { typedef struct _keymap_entry { char type; -#define ISFUNC 0 -#define ISKMAP 1 -#define ISMACR 2 +#define ISFUNC 0 +#define ISKMAP 1 +#define ISMACR 2 Function *function; } KEYMAP_ENTRY; @@ -81,8 +81,8 @@ typedef KEYMAP_ENTRY *Keymap; #define UNCTRL(c) (((c) - 'a' + 'A')|control_character_bit) #endif -#define RUBOUT 0x7f -#define ABORT_CHAR CTRL('G') +#define RUBOUT 0x7f +#define ABORT_CHAR CTRL('G') /* global variables used by readline enabled applications */ #ifdef __cplusplus @@ -110,6 +110,8 @@ extern Function *rl_startup_hook; extern char *rl_terminal_name; extern int rl_already_prompted; extern char *rl_prompt; +extern VFunction *rl_event_hook; + /* * The following is not implemented */ @@ -148,6 +150,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); @@ -166,13 +170,18 @@ void rl_callback_handler_install(const char *, VFunction *); 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 *); +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_add_defun(const char *, Function *, int); int rl_generic_bind(int, const char *, const char *, Keymap); int rl_bind_key_in_map(int, Function *, Keymap); #ifdef __cplusplus diff --git a/lib/libedit/search.c b/lib/libedit/search.c index 84c8c24cf01..74fb5d91b53 100644 --- a/lib/libedit/search.c +++ b/lib/libedit/search.c @@ -1,5 +1,5 @@ -/* $OpenBSD: search.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: search.c,v 1.15 2003/08/07 16:44:33 agc Exp $ */ +/* $OpenBSD: search.c,v 1.10 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: search.c,v 1.19 2003/10/25 06:42:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: search.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: search.c,v 1.10 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -223,8 +223,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; @@ -233,7 +236,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; @@ -246,7 +249,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++] = @@ -268,7 +271,7 @@ ce_inc_search(EditLine *el, int dir) break; case ED_DELETE_PREV_CHAR: - if (el->el_search.patlen > 1) + if (el->el_search.patlen > LEN) done++; else term_beep(el); @@ -283,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; } @@ -335,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 = @@ -371,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; @@ -386,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,9 +452,6 @@ cv_search(EditLine *el, int dir) #ifdef ANCHOR tmpbuf[0] = '.'; tmpbuf[1] = '*'; -#define LEN 2 -#else -#define LEN 0 #endif tmplen = LEN; @@ -517,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); } } diff --git a/lib/libedit/search.h b/lib/libedit/search.h index 8319fa7469e..68f7dcfad74 100644 --- a/lib/libedit/search.h +++ b/lib/libedit/search.h @@ -1,5 +1,5 @@ -/* $OpenBSD: search.h,v 1.6 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: search.h,v 1.7 2003/08/07 16:44:33 agc Exp $ */ +/* $OpenBSD: search.h,v 1.7 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -60,7 +60,7 @@ 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(EditLine *, int, int, int, int); diff --git a/lib/libedit/tokenizer.c b/lib/libedit/tokenizer.c index da1c64fdcb0..07edc46b350 100644 --- a/lib/libedit/tokenizer.c +++ b/lib/libedit/tokenizer.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tokenizer.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: tokenizer.c,v 1.12 2003/08/07 16:44:34 agc Exp $ */ +/* $OpenBSD: tokenizer.c,v 1.10 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: tokenizer.c,v 1.13 2003/10/18 23:48:42 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: tokenizer.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: tokenizer.c,v 1.10 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -61,6 +61,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) @@ -108,7 +109,7 @@ tok_init(const char *ifs) if (tok == NULL) return NULL; - tok->ifs = strdup(ifs ? ifs : IFS); + tok->ifs = tok_strdup(ifs ? ifs : IFS); if (tok->ifs == NULL) { tok_free((ptr_t)tok); return NULL; diff --git a/lib/libedit/tty.c b/lib/libedit/tty.c index b9910427472..18fa5d032da 100644 --- a/lib/libedit/tty.c +++ b/lib/libedit/tty.c @@ -1,5 +1,5 @@ -/* $OpenBSD: tty.c,v 1.9 2003/10/31 08:42:24 otto Exp $ */ -/* $NetBSD: tty.c,v 1.18 2003/08/07 16:44:34 agc Exp $ */ +/* $OpenBSD: tty.c,v 1.10 2003/11/25 20:12:38 otto Exp $ */ +/* $NetBSD: tty.c,v 1.20 2003/10/18 22:37:24 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -38,7 +38,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -static const char rcsid[] = "$OpenBSD: tty.c,v 1.9 2003/10/31 08:42:24 otto Exp $"; +static const char rcsid[] = "$OpenBSD: tty.c,v 1.10 2003/11/25 20:12:38 otto Exp $"; #endif #endif /* not lint && not SCCSID */ @@ -452,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 *); @@ -585,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 @@ -1045,6 +1153,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) int aflag = 0; const char *s, *d; const char *name; + struct termios *tios = &el->el_tty.t_ex; int z = EX_IO; if (argv == NULL) @@ -1059,14 +1168,17 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const 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: @@ -1116,6 +1228,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) return (0); } while (argv && (s = *argv++)) { + char *p; switch (*s) { case '+': case '-': @@ -1126,8 +1239,11 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) break; } d = s; + if ((p = strchr(s, '=')) != NULL) + *p++ = '\0'; for (m = ttymodes; m->m_name; m++) - if (strcmp(m->m_name, d) == 0) + if (strcmp(m->m_name, d) == 0 && + (p == NULL || m->m_type == MD_CHAR)) break; if (!m->m_name) { @@ -1135,6 +1251,15 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const 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 **const) &p) : + el->el_tty.t_vdisable; + c--; + c = tty__getcharindex(c); + tios->c_cc[c] = v; + continue; + } switch (x) { case '+': el->el_tty.t_t[z][m->m_type].t_setmask |= m->m_value; |