Import NetBSD's LibEdit version 2012-03-11 on vendor branch
authorJohn Marino <draco@marino.st>
Thu, 10 May 2012 21:34:55 +0000 (23:34 +0200)
committerJohn Marino <draco@marino.st>
Thu, 10 May 2012 21:34:55 +0000 (23:34 +0200)
50 files changed:
contrib/libedit/COPYING [new file with mode: 0644]
contrib/libedit/src/chared.c [new file with mode: 0644]
contrib/libedit/src/chared.h [new file with mode: 0644]
contrib/libedit/src/chartype.c [new file with mode: 0644]
contrib/libedit/src/chartype.h [new file with mode: 0644]
contrib/libedit/src/common.c [new file with mode: 0644]
contrib/libedit/src/editline/readline.h [new file with mode: 0644]
contrib/libedit/src/el.c [new file with mode: 0644]
contrib/libedit/src/el.h [new file with mode: 0644]
contrib/libedit/src/eln.c [new file with mode: 0644]
contrib/libedit/src/emacs.c [new file with mode: 0644]
contrib/libedit/src/fgetln.c [new file with mode: 0644]
contrib/libedit/src/filecomplete.c [new file with mode: 0644]
contrib/libedit/src/filecomplete.h [new file with mode: 0644]
contrib/libedit/src/hist.c [new file with mode: 0644]
contrib/libedit/src/hist.h [new file with mode: 0644]
contrib/libedit/src/histedit.h [new file with mode: 0644]
contrib/libedit/src/history.c [new file with mode: 0644]
contrib/libedit/src/keymacro.c [new file with mode: 0644]
contrib/libedit/src/keymacro.h [new file with mode: 0644]
contrib/libedit/src/makelist [new file with mode: 0644]
contrib/libedit/src/map.c [new file with mode: 0644]
contrib/libedit/src/map.h [new file with mode: 0644]
contrib/libedit/src/parse.c [new file with mode: 0644]
contrib/libedit/src/parse.h [new file with mode: 0644]
contrib/libedit/src/prompt.c [new file with mode: 0644]
contrib/libedit/src/prompt.h [new file with mode: 0644]
contrib/libedit/src/read.c [new file with mode: 0644]
contrib/libedit/src/read.h [new file with mode: 0644]
contrib/libedit/src/readline.c [new file with mode: 0644]
contrib/libedit/src/refresh.c [new file with mode: 0644]
contrib/libedit/src/refresh.h [new file with mode: 0644]
contrib/libedit/src/search.c [new file with mode: 0644]
contrib/libedit/src/search.h [new file with mode: 0644]
contrib/libedit/src/shlib_version [new file with mode: 0644]
contrib/libedit/src/sig.c [new file with mode: 0644]
contrib/libedit/src/sig.h [new file with mode: 0644]
contrib/libedit/src/strlcat.c [new file with mode: 0644]
contrib/libedit/src/strlcpy.c [new file with mode: 0644]
contrib/libedit/src/sys.h [new file with mode: 0644]
contrib/libedit/src/terminal.c [new file with mode: 0644]
contrib/libedit/src/terminal.h [new file with mode: 0644]
contrib/libedit/src/tokenizer.c [new file with mode: 0644]
contrib/libedit/src/tty.c [new file with mode: 0644]
contrib/libedit/src/tty.h [new file with mode: 0644]
contrib/libedit/src/unvis.c [new file with mode: 0644]
contrib/libedit/src/vi.c [new file with mode: 0644]
contrib/libedit/src/vis.c [new file with mode: 0644]
contrib/libedit/src/vis.h [new file with mode: 0644]
contrib/libedit/src/wcsdup.c [new file with mode: 0644]

diff --git a/contrib/libedit/COPYING b/contrib/libedit/COPYING
new file mode 100644 (file)
index 0000000..742f005
--- /dev/null
@@ -0,0 +1,30 @@
+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. 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.
+
diff --git a/contrib/libedit/src/chared.c b/contrib/libedit/src/chared.c
new file mode 100644 (file)
index 0000000..f816d89
--- /dev/null
@@ -0,0 +1,740 @@
+/*     $NetBSD: chared.c,v 1.36 2011/10/23 17:37:55 christos 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. 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.
+ */
+
+#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.36 2011/10/23 17:37:55 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * chared.c: Character editor utilities
+ */
+#include <stdlib.h>
+#include "el.h"
+
+private void ch__clearmacro (EditLine *);
+
+/* value to leave unused in line buffer */
+#define        EL_LEAVE        2
+
+/* cv_undo():
+ *     Handle state for the vi undo command
+ */
+protected void
+cv_undo(EditLine *el)
+{
+       c_undo_t *vu = &el->el_chared.c_undo;
+       c_redo_t *r = &el->el_chared.c_redo;
+       size_t size;
+
+       /* Save entire line for undo */
+       size = (size_t)(el->el_line.lastchar - el->el_line.buffer);
+       vu->len = (ssize_t)size;
+       vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer);
+       (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf));
+
+       /* 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;
+
+       (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf));
+       k->last = k->buf + size;
+}
+
+
+/* c_insert():
+ *     Insert num characters
+ */
+protected void
+c_insert(EditLine *el, int num)
+{
+       Char *cp;
+
+       if (el->el_line.lastchar + num >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, (size_t)num))
+                       return;         /* can't go past end of buffer */
+       }
+
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               /* if I must move chars */
+               for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--)
+                       cp[num] = *cp;
+       }
+       el->el_line.lastchar += num;
+}
+
+
+/* c_delafter():
+ *     Delete num characters after the cursor
+ */
+protected void
+c_delafter(EditLine *el, int num)
+{
+
+       if (el->el_line.cursor + num > el->el_line.lastchar)
+               num = (int)(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;
+
+               for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= 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
+ */
+protected void
+c_delbefore(EditLine *el, int num)
+{
+
+       if (el->el_line.cursor - num < el->el_line.buffer)
+               num = (int)(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;
+
+               for (cp = el->el_line.cursor - num;
+                   cp <= el->el_line.lastchar;
+                   cp++)
+                       *cp = cp[num];
+
+               el->el_line.lastchar -= 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 Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL;
+}
+
+
+/* cv__isword():
+ *     Return if p is part of a word according to vi
+ */
+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);
+}
+
+
+/* c__prev_word():
+ *     Find the previous word
+ */
+protected Char *
+c__prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
+{
+       p--;
+
+       while (n--) {
+               while ((p >= low) && !(*wtest)(*p))
+                       p--;
+               while ((p >= low) && (*wtest)(*p))
+                       p--;
+       }
+
+       /* cp now points to one character before the word */
+       p++;
+       if (p < low)
+               p = low;
+       /* cp now points where we want it */
+       return p;
+}
+
+
+/* c__next_word():
+ *     Find the next word
+ */
+protected Char *
+c__next_word(Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       while (n--) {
+               while ((p < high) && !(*wtest)(*p))
+                       p++;
+               while ((p < high) && (*wtest)(*p))
+                       p++;
+       }
+       if (p > high)
+               p = high;
+       /* p now points where we want it */
+       return p;
+}
+
+/* cv_next_word():
+ *     Find the next word vi style
+ */
+protected Char *
+cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       int test;
+
+       while (n--) {
+               test = (*wtest)(*p);
+               while ((p < high) && (*wtest)(*p) == test)
+                       p++;
+               /*
+                * vi historically deletes with cw only the word preserving the
+                * trailing whitespace! This is not what 'w' does..
+                */
+               if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
+                       while ((p < high) && Isspace(*p))
+                               p++;
+       }
+
+       /* p now points where we want it */
+       if (p > high)
+               return high;
+       else
+               return p;
+}
+
+
+/* cv_prev_word():
+ *     Find the previous word vi style
+ */
+protected Char *
+cv_prev_word(Char *p, Char *low, int n, int (*wtest)(Int))
+{
+       int test;
+
+       p--;
+       while (n--) {
+               while ((p > low) && Isspace(*p))
+                       p--;
+               test = (*wtest)(*p);
+               while ((p >= low) && (*wtest)(*p) == test)
+                       p--;
+       }
+       p++;
+
+       /* p now points where we want it */
+       if (p < low)
+               return low;
+       else
+               return p;
+}
+
+
+/* cv_delfini():
+ *     Finish vi delete action
+ */
+protected void
+cv_delfini(EditLine *el)
+{
+       int size;
+       int action = el->el_chared.c_vcmd.action;
+
+       if (action & INSERT)
+               el->el_map.current = el->el_map.key;
+
+       if (el->el_chared.c_vcmd.pos == 0)
+               /* sanity */
+               return;
+
+       size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos);
+       if (size == 0)
+               size = 1;
+       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_vcmd.action = NOP;
+}
+
+
+/* cv__endword():
+ *     Go to the end of this word according to vi
+ */
+protected Char *
+cv__endword(Char *p, Char *high, int n, int (*wtest)(Int))
+{
+       int test;
+
+       p++;
+
+       while (n--) {
+               while ((p < high) && Isspace(*p))
+                       p++;
+
+               test = (*wtest)(*p);
+               while ((p < high) && (*wtest)(*p) == test)
+                       p++;
+       }
+       p--;
+       return p;
+}
+
+/* ch_init():
+ *     Initialize the character editor
+ */
+protected int
+ch_init(EditLine *el)
+{
+       c_macro_t *ma = &el->el_chared.c_macro;
+
+       el->el_line.buffer              = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_line.buffer));
+       if (el->el_line.buffer == NULL)
+               return -1;
+
+       (void) memset(el->el_line.buffer, 0, EL_BUFSIZ *
+           sizeof(*el->el_line.buffer));
+       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 - EL_LEAVE];
+
+       el->el_chared.c_undo.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_undo.buf));
+       if (el->el_chared.c_undo.buf == NULL)
+               return -1;
+       (void) memset(el->el_chared.c_undo.buf, 0, EL_BUFSIZ *
+           sizeof(*el->el_chared.c_undo.buf));
+       el->el_chared.c_undo.len        = -1;
+       el->el_chared.c_undo.cursor     = 0;
+       el->el_chared.c_redo.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_redo.buf));
+       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_kill.buf        = el_malloc(EL_BUFSIZ *
+           sizeof(*el->el_chared.c_kill.buf));
+       if (el->el_chared.c_kill.buf == NULL)
+               return -1;
+       (void) memset(el->el_chared.c_kill.buf, 0, EL_BUFSIZ *
+           sizeof(*el->el_chared.c_kill.buf));
+       el->el_chared.c_kill.mark       = el->el_line.buffer;
+       el->el_chared.c_kill.last       = el->el_chared.c_kill.buf;
+       el->el_chared.c_resizefun       = NULL;
+       el->el_chared.c_resizearg       = NULL;
+
+       el->el_map.current              = el->el_map.key;
+
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
+
+       ma->level       = -1;
+       ma->offset      = 0;
+       ma->macro       = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
+       if (ma->macro == NULL)
+               return -1;
+       return 0;
+}
+
+/* ch_reset():
+ *     Reset the character editor
+ */
+protected void
+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.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_kill.mark       = el->el_line.buffer;
+
+       el->el_map.current              = el->el_map.key;
+
+       el->el_state.inputmode          = MODE_INSERT; /* XXX: save a default */
+       el->el_state.doingarg           = 0;
+       el->el_state.metanext           = 0;
+       el->el_state.argument           = 1;
+       el->el_state.lastcmd            = ED_UNASSIGNED;
+
+       el->el_history.eventno          = 0;
+
+       if (mclear)
+               ch__clearmacro(el);
+}
+
+private void
+ch__clearmacro(EditLine *el)
+{
+       c_macro_t *ma = &el->el_chared.c_macro;
+       while (ma->level >= 0)
+               el_free(ma->macro[ma->level--]);
+}
+
+/* ch_enlargebufs():
+ *     Enlarge line buffer to be able to hold twice as much characters.
+ *     Returns 1 if successful, 0 if not.
+ */
+protected int
+ch_enlargebufs(EditLine *el, size_t addlen)
+{
+       size_t sz, newsz;
+       Char *newbuffer, *oldbuf, *oldkbuf;
+
+       sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
+       newsz = sz * 2;
+       /*
+        * If newly required length is longer than current buffer, we need
+        * to make the buffer big enough to hold both old and new stuff.
+        */
+       if (addlen > sz) {
+               while(newsz - sz < addlen)
+                       newsz *= 2;
+       }
+
+       /*
+        * Reallocate line buffer.
+        */
+       newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+           
+       oldbuf = el->el_line.buffer;
+
+       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);
+       /* don't set new size until all buffers are enlarged */
+       el->el_line.limit  = &newbuffer[sz - EL_LEAVE];
+
+       /*
+        * Reallocate kill buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz *
+           sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+
+       oldkbuf = el->el_chared.c_kill.buf;
+
+       el->el_chared.c_kill.buf = newbuffer;
+       el->el_chared.c_kill.last = newbuffer +
+                                       (el->el_chared.c_kill.last - oldkbuf);
+       el->el_chared.c_kill.mark = el->el_line.buffer +
+                                       (el->el_chared.c_kill.mark - oldbuf);
+
+       /*
+        * Reallocate undo buffer.
+        */
+       newbuffer = el_realloc(el->el_chared.c_undo.buf,
+           newsz * sizeof(*newbuffer));
+       if (!newbuffer)
+               return 0;
+
+       /* zero the newly added memory, leave old data in */
+       (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer));
+       el->el_chared.c_undo.buf = newbuffer;
+
+       newbuffer = el_realloc(el->el_chared.c_redo.buf,
+           newsz * sizeof(*newbuffer));
+       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];
+       if (el->el_chared.c_resizefun)
+               (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg);
+       return 1;
+}
+
+/* ch_end():
+ *     Free the data structures used by the editor
+ */
+protected void
+ch_end(EditLine *el)
+{
+       el_free(el->el_line.buffer);
+       el->el_line.buffer = NULL;
+       el->el_line.limit = NULL;
+       el_free(el->el_chared.c_undo.buf);
+       el->el_chared.c_undo.buf = NULL;
+       el_free(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(el->el_chared.c_kill.buf);
+       el->el_chared.c_kill.buf = NULL;
+       ch_reset(el, 1);
+       el_free(el->el_chared.c_macro.macro);
+       el->el_chared.c_macro.macro = NULL;
+}
+
+
+/* el_insertstr():
+ *     Insert string at cursorI
+ */
+public int
+FUN(el,insertstr)(EditLine *el, const Char *s)
+{
+       size_t len;
+
+       if ((len = Strlen(s)) == 0)
+               return -1;
+       if (el->el_line.lastchar + len >= el->el_line.limit) {
+               if (!ch_enlargebufs(el, len))
+                       return -1;
+       }
+
+       c_insert(el, (int)len);
+       while (*s)
+               *el->el_line.cursor++ = *s++;
+       return 0;
+}
+
+
+/* el_deletestr():
+ *     Delete num characters before the cursor
+ */
+public void
+el_deletestr(EditLine *el, int n)
+{
+       if (n <= 0)
+               return;
+
+       if (el->el_line.cursor < &el->el_line.buffer[n])
+               return;
+
+       c_delbefore(el, n);             /* delete before dot */
+       el->el_line.cursor -= n;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+}
+
+/* c_gets():
+ *     Get a string
+ */
+protected int
+c_gets(EditLine *el, Char *buf, const Char *prompt)
+{
+       Char ch;
+       ssize_t len;
+       Char *cp = el->el_line.buffer;
+
+       if (prompt) {
+               len = (ssize_t)Strlen(prompt);
+               (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
+               cp += len;
+       }
+       len = 0;
+
+       for (;;) {
+               el->el_line.cursor = cp;
+               *cp = ' ';
+               el->el_line.lastchar = cp + 1;
+               re_refresh(el);
+
+               if (FUN(el,getc)(el, &ch) != 1) {
+                       ed_end_of_file(el, 0);
+                       len = -1;
+                       break;
+               }
+
+               switch (ch) {
+
+               case 0010:      /* Delete and backspace */
+               case 0177:
+                       if (len == 0) {
+                               len = -1;
+                               break;
+                       }
+                       cp--;
+                       continue;
+
+               case 0033:      /* ESC */
+               case '\r':      /* Newline */
+               case '\n':
+                       buf[len] = ch;
+                       break;
+
+               default:
+                       if (len >= (ssize_t)(EL_BUFSIZ - 16))
+                               terminal_beep(el);
+                       else {
+                               buf[len++] = ch;
+                               *cp++ = ch;
+                       }
+                       continue;
+               }
+               break;
+       }
+
+       el->el_line.buffer[0] = '\0';
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return (int)len;
+}
+
+
+/* c_hpos():
+ *     Return the current horizontal position of the cursor
+ */
+protected int
+c_hpos(EditLine *el)
+{
+       Char *ptr;
+
+       /*
+        * Find how many characters till the beginning of this line.
+        */
+       if (el->el_line.cursor == el->el_line.buffer)
+               return 0;
+       else {
+               for (ptr = el->el_line.cursor - 1;
+                    ptr >= el->el_line.buffer && *ptr != '\n';
+                    ptr--)
+                       continue;
+               return (int)(el->el_line.cursor - ptr - 1);
+       }
+}
+
+protected int
+ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
+{
+       el->el_chared.c_resizefun = f;
+       el->el_chared.c_resizearg = a;
+       return 0;
+}
diff --git a/contrib/libedit/src/chared.h b/contrib/libedit/src/chared.h
new file mode 100644 (file)
index 0000000..176475a
--- /dev/null
@@ -0,0 +1,171 @@
+/*     $NetBSD: chared.h,v 1.21 2010/08/28 15:44:59 christos 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. 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.
+ *
+ *     @(#)chared.h    8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.chared.h: Character editor interface
+ */
+#ifndef _h_el_chared
+#define        _h_el_chared
+
+#include <ctype.h>
+#include <string.h>
+
+#include "histedit.h"
+
+#define        EL_MAXMACRO     10
+
+/*
+ * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works
+ * like real vi: i.e. the transition from command<->insert modes moves
+ * the cursor.
+ *
+ * On the other hand we really don't want to move the cursor, because
+ * all the editing commands don't include the character under the cursor.
+ * Probably the best fix is to make all the editing commands aware of
+ * this fact.
+ */
+#define        VI_MOVE
+
+
+typedef struct c_macro_t {
+       int       level;
+       int       offset;
+       Char    **macro;
+} c_macro_t;
+
+/*
+ * Undo information for vi - no undo in emacs (yet)
+ */
+typedef struct c_undo_t {
+       ssize_t  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;
+} c_vcmd_t;
+
+/*
+ * Kill buffer for emacs
+ */
+typedef struct c_kill_t {
+       Char    *buf;
+       Char    *last;
+       Char    *mark;
+} c_kill_t;
+
+typedef void (*el_zfunc_t)(EditLine *, void *);
+
+/*
+ * Note that we use both data structures because the user can bind
+ * commands from both editors!
+ */
+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_zfunc_t      c_resizefun;
+       void *          c_resizearg;
+} el_chared_t;
+
+
+#define        STRQQ           "\"\""
+
+#define        isglob(a)       (strchr("*[]?", (a)) != NULL)
+
+#define        NOP             0x00
+#define        DELETE          0x01
+#define        INSERT          0x02
+#define        YANK            0x04
+
+#define        CHAR_FWD        (+1)
+#define        CHAR_BACK       (-1)
+
+#define        MODE_INSERT     0
+#define        MODE_REPLACE    1
+#define        MODE_REPLACE_1  2
+
+#include "common.h"
+#include "vi.h"
+#include "emacs.h"
+#include "search.h"
+#include "fcns.h"
+
+
+protected int   cv__isword(Int);
+protected int   cv__isWord(Int);
+protected void  cv_delfini(EditLine *);
+protected Char *cv__endword(Char *, Char *, int, int (*)(Int));
+protected int   ce__isword(Int);
+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(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 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 *, int);
+protected int   ch_resizefun(EditLine *, el_zfunc_t, void *);
+protected int   ch_enlargebufs(EditLine *, size_t);
+protected void  ch_end(EditLine *);
+
+#endif /* _h_el_chared */
diff --git a/contrib/libedit/src/chartype.c b/contrib/libedit/src/chartype.c
new file mode 100644 (file)
index 0000000..8766aac
--- /dev/null
@@ -0,0 +1,356 @@
+/*     $NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $   */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+/*
+ * chartype.c: character classification and meta information
+ */
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+__RCSID("$NetBSD: chartype.c,v 1.10 2011/08/16 16:25:15 christos Exp $");
+#endif /* not lint && not SCCSID */
+#include "el.h"
+#include <stdlib.h>
+
+#define CT_BUFSIZ ((size_t)1024)
+
+#ifdef WIDECHAR
+protected void
+ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
+{
+       void *p;
+       if (mincsize > conv->csize) {
+               conv->csize = mincsize;
+               p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff));
+               if (p == NULL) {
+                       conv->csize = 0;
+                       el_free(conv->cbuff);
+                       conv->cbuff = NULL;
+               } else 
+                       conv->cbuff = p;
+       }
+
+       if (minwsize > conv->wsize) {
+               conv->wsize = minwsize;
+               p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff));
+               if (p == NULL) {
+                       conv->wsize = 0;
+                       el_free(conv->wbuff);
+                       conv->wbuff = NULL;
+               } else
+                       conv->wbuff = p;
+       }
+}
+
+
+public char *
+ct_encode_string(const Char *s, ct_buffer_t *conv)
+{
+       char *dst;
+       ssize_t used = 0;
+
+       if (!s)
+               return NULL;
+       if (!conv->cbuff)
+               ct_conv_buff_resize(conv, CT_BUFSIZ, (size_t)0);
+       if (!conv->cbuff)
+               return NULL;
+
+       dst = conv->cbuff;
+       while (*s) {
+               used = (ssize_t)(conv->csize - (size_t)(dst - conv->cbuff));
+               if (used < 5) {
+                       used = dst - conv->cbuff;
+                       ct_conv_buff_resize(conv, conv->csize + CT_BUFSIZ,
+                           (size_t)0);
+                       if (!conv->cbuff)
+                               return NULL;
+                       dst = conv->cbuff + used;
+               }
+               used = ct_encode_char(dst, (size_t)5, *s);
+               if (used == -1) /* failed to encode, need more buffer space */
+                       abort();
+               ++s;
+               dst += used;
+       }
+       *dst = '\0';
+       return conv->cbuff;
+}
+
+public Char *
+ct_decode_string(const char *s, ct_buffer_t *conv)
+{
+       size_t len = 0;
+
+       if (!s)
+               return NULL;
+       if (!conv->wbuff)
+               ct_conv_buff_resize(conv, (size_t)0, CT_BUFSIZ);
+       if (!conv->wbuff)
+               return NULL;
+
+       len = ct_mbstowcs(NULL, s, (size_t)0);
+       if (len == (size_t)-1)
+               return NULL;
+       if (len > conv->wsize)
+               ct_conv_buff_resize(conv, (size_t)0, len + 1);
+       if (!conv->wbuff)
+               return NULL;
+       ct_mbstowcs(conv->wbuff, s, conv->wsize);
+       return conv->wbuff;
+}
+
+
+protected Char **
+ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
+{
+       size_t bufspace;
+       int i;
+       Char *p;
+       Char **wargv;
+       ssize_t bytes;
+
+       /* Make sure we have enough space in the conversion buffer to store all
+        * the argv strings. */
+       for (i = 0, bufspace = 0; i < argc; ++i)
+               bufspace += argv[i] ? strlen(argv[i]) + 1 : 0;
+       ct_conv_buff_resize(conv, (size_t)0, bufspace);
+       if (!conv->wsize)
+               return NULL;
+
+       wargv = el_malloc((size_t)argc * sizeof(*wargv));
+
+       for (i = 0, p = conv->wbuff; i < argc; ++i) {
+               if (!argv[i]) {   /* don't pass null pointers to mbstowcs */
+                       wargv[i] = NULL;
+                       continue;
+               } else {
+                       wargv[i] = p;
+                       bytes = (ssize_t)mbstowcs(p, argv[i], bufspace);
+               }
+               if (bytes == -1) {
+                       el_free(wargv);
+                       return NULL;
+               } else
+                       bytes++;  /* include '\0' in the count */
+               bufspace -= (size_t)bytes;
+               p += bytes;
+       }
+
+       return wargv;
+}
+
+
+protected size_t
+ct_enc_width(Char c)
+{
+       /* UTF-8 encoding specific values */
+       if (c < 0x80)
+               return 1;
+       else if (c < 0x0800)
+               return 2;
+       else if (c < 0x10000)
+               return 3;
+       else if (c < 0x110000)
+               return 4;
+       else
+               return 0; /* not a valid codepoint */
+}
+
+protected ssize_t
+ct_encode_char(char *dst, size_t len, Char c)
+{
+       ssize_t l = 0;
+       if (len < ct_enc_width(c))
+               return -1;
+       l = ct_wctomb(dst, c);
+
+       if (l < 0) {
+               ct_wctomb_reset;
+               l = 0;
+       }
+       return l;
+}
+#endif
+
+protected const Char *
+ct_visual_string(const Char *s)
+{
+       static Char *buff = NULL;
+       static size_t buffsize = 0;
+       void *p;
+       Char *dst;
+       ssize_t used = 0;
+
+       if (!s)
+               return NULL;
+       if (!buff) {
+           buffsize = CT_BUFSIZ;
+           buff = el_malloc(buffsize * sizeof(*buff));
+       }
+       dst = buff;
+       while (*s) {
+               used = ct_visual_char(dst, buffsize - (size_t)(dst - buff), *s);
+               if (used == -1) { /* failed to encode, need more buffer space */
+                       used = dst - buff;
+                       buffsize += CT_BUFSIZ;
+                       p = el_realloc(buff, buffsize * sizeof(*buff));
+                       if (p == NULL)
+                               goto out;
+                       buff = p;
+                       dst = buff + used;
+                       /* don't increment s here - we want to retry it! */
+               }
+               else
+                   ++s;
+               dst += used;
+       }
+       if (dst >= (buff + buffsize)) { /* sigh */
+               buffsize += 1;
+               p = el_realloc(buff, buffsize * sizeof(*buff));
+               if (p == NULL)
+                       goto out;
+               buff = p;
+               dst = buff + buffsize - 1;
+       }
+       *dst = 0;
+       return buff;
+out:
+       el_free(buff);
+       buffsize = 0;
+       return NULL;
+}
+
+
+
+protected int
+ct_visual_width(Char c)
+{
+       int t = ct_chr_class(c);
+       switch (t) {
+       case CHTYPE_ASCIICTL:
+               return 2; /* ^@ ^? etc. */
+       case CHTYPE_TAB:
+               return 1; /* Hmm, this really need to be handled outside! */
+       case CHTYPE_NL:
+               return 0; /* Should this be 1 instead? */
+#ifdef WIDECHAR
+       case CHTYPE_PRINT:
+               return wcwidth(c);
+       case CHTYPE_NONPRINT:
+               if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+                       return 8; /* \U+12345 */
+               else
+                       return 7; /* \U+1234 */
+#else
+       case CHTYPE_PRINT:
+               return 1;
+       case CHTYPE_NONPRINT:
+               return 4; /* \123 */
+#endif
+       default:
+               return 0; /* should not happen */
+       }
+}
+
+
+protected ssize_t
+ct_visual_char(Char *dst, size_t len, Char c)
+{
+       int t = ct_chr_class(c);
+       switch (t) {
+       case CHTYPE_TAB:
+       case CHTYPE_NL:
+       case CHTYPE_ASCIICTL:
+               if (len < 2)
+                       return -1;   /* insufficient space */
+               *dst++ = '^';
+               if (c == '\177')
+                       *dst = '?'; /* DEL -> ^? */
+               else
+                       *dst = c | 0100;    /* uncontrolify it */
+               return 2;
+       case CHTYPE_PRINT:
+               if (len < 1)
+                       return -1;  /* insufficient space */
+               *dst = c;
+               return 1;
+       case CHTYPE_NONPRINT:
+               /* we only use single-width glyphs for display,
+                * so this is right */
+               if ((ssize_t)len < ct_visual_width(c))
+                       return -1;   /* insufficient space */
+#ifdef WIDECHAR
+               *dst++ = '\\';
+               *dst++ = 'U';
+               *dst++ = '+';
+#define tohexdigit(v) "0123456789ABCDEF"[v]
+               if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */
+                       *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >>  8) & 0xf);
+               *dst++ = tohexdigit(((unsigned int) c >>  4) & 0xf);
+               *dst   = tohexdigit(((unsigned int) c      ) & 0xf);
+               return c > 0xffff ? 8 : 7;
+#else
+               *dst++ = '\\';
+#define tooctaldigit(v) ((v) + '0')
+               *dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7);
+               *dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7);
+               *dst++ = tooctaldigit(((unsigned int) c     ) & 0x7);
+#endif
+               /*FALLTHROUGH*/
+       /* these two should be handled outside this function */
+       default:            /* we should never hit the default */
+               return 0;
+       }
+}
+
+
+
+
+protected int
+ct_chr_class(Char c)
+{
+       if (c == '\t')
+               return CHTYPE_TAB;
+       else if (c == '\n')
+               return CHTYPE_NL;
+       else if (IsASCII(c) && Iscntrl(c))
+               return CHTYPE_ASCIICTL;
+       else if (Isprint(c))
+               return CHTYPE_PRINT;
+       else
+               return CHTYPE_NONPRINT;
+}
diff --git a/contrib/libedit/src/chartype.h b/contrib/libedit/src/chartype.h
new file mode 100644 (file)
index 0000000..12fa9ac
--- /dev/null
@@ -0,0 +1,254 @@
+/*     $NetBSD: chartype.h,v 1.10 2011/11/16 01:45:10 christos Exp $   */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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 _h_chartype_f
+#define _h_chartype_f
+
+
+
+#ifdef WIDECHAR
+
+/* Ideally we should also test the value of the define to see if it
+ * supports non-BMP code points without requiring UTF-16, but nothing
+ * seems to actually advertise this properly, despite Unicode 3.1 having
+ * been around since 2001... */
+#if !defined(__NetBSD__) && !defined(__sun) && !(defined(__APPLE__) && defined(__MACH__))
+#ifndef __STDC_ISO_10646__
+/* In many places it is assumed that the first 127 code points are ASCII
+ * compatible, so ensure wchar_t indeed does ISO 10646 and not some other
+ * funky encoding that could break us in weird and wonderful ways. */
+       #error wchar_t must store ISO 10646 characters
+#endif
+#endif
+
+/* Oh for a <uchar.h> with char32_t and __STDC_UTF_32__ in it...
+ * ref: ISO/IEC DTR 19769
+ */
+#if WCHAR_MAX < INT32_MAX
+#warning Build environment does not support non-BMP characters
+#endif
+
+#ifndef HAVE_WCSDUP
+wchar_t *wcsdup(const wchar_t *s);
+#endif
+
+#define ct_mbtowc            mbtowc
+#define ct_mbtowc_reset      mbtowc(0,0,(size_t)0)
+#define ct_wctomb            wctomb
+#define ct_wctomb_reset      wctomb(0,0)
+#define ct_wcstombs          wcstombs
+#define ct_mbstowcs          mbstowcs
+
+#define Char                   wchar_t
+#define Int                    wint_t
+#define FUN(prefix,rest)       prefix ## _w ## rest
+#define FUNW(type)             type ## _w
+#define TYPE(type)             type ## W
+#define FSTR                   "%ls"
+#define STR(x)                         L ## x
+#define UC(c)                  c
+#define Isalpha(x)  iswalpha(x)
+#define Isalnum(x)  iswalnum(x)
+#define Isgraph(x)  iswgraph(x)
+#define Isspace(x)  iswspace(x)
+#define Isdigit(x)  iswdigit(x)
+#define Iscntrl(x)  iswcntrl(x)
+#define Isprint(x)  iswprint(x)
+
+#define Isupper(x)  iswupper(x)
+#define Islower(x)  iswlower(x)
+#define Toupper(x)  towupper(x)
+#define Tolower(x)  towlower(x)
+
+#define IsASCII(x)  (x < 0x100)
+
+#define Strlen(x)       wcslen(x)
+#define Strchr(s,c)     wcschr(s,c)
+#define Strrchr(s,c)    wcsrchr(s,c)
+#define Strstr(s,v)     wcsstr(s,v)
+#define Strdup(x)       wcsdup(x)
+#define Strcpy(d,s)     wcscpy(d,s)
+#define Strncpy(d,s,n)  wcsncpy(d,s,n)
+#define Strncat(d,s,n)  wcsncat(d,s,n)
+
+#define Strcmp(s,v)     wcscmp(s,v)
+#define Strncmp(s,v,n)  wcsncmp(s,v,n)
+#define Strcspn(s,r)    wcscspn(s,r)
+
+#define Strtol(p,e,b)   wcstol(p,e,b)
+
+static inline int
+Width(wchar_t c)
+{
+       int w = wcwidth(c);
+       return w < 0 ? 0 : w;
+}
+
+#else /* NARROW */
+
+#define ct_mbtowc            error
+#define ct_mbtowc_reset      
+#define ct_wctomb            error
+#define ct_wctomb_reset      
+#define ct_wcstombs(a, b, c)    (strncpy(a, b, c), strlen(a))
+#define ct_mbstowcs(a, b, c)    (strncpy(a, b, c), strlen(a))
+
+#define Char                   char
+#define Int                    int
+#define FUN(prefix,rest)       prefix ## _ ## rest
+#define FUNW(type)             type
+#define TYPE(type)             type
+#define FSTR                   "%s"
+#define STR(x)                         x
+#define UC(c)                  (unsigned char)(c)
+
+#define Isalpha(x)  isalpha((unsigned char)x)
+#define Isalnum(x)  isalnum((unsigned char)x)
+#define Isgraph(x)  isgraph((unsigned char)x)
+#define Isspace(x)  isspace((unsigned char)x)
+#define Isdigit(x)  isdigit((unsigned char)x)
+#define Iscntrl(x)  iscntrl((unsigned char)x)
+#define Isprint(x)  isprint((unsigned char)x)
+
+#define Isupper(x)  isupper((unsigned char)x)
+#define Islower(x)  islower((unsigned char)x)
+#define Toupper(x)  toupper((unsigned char)x)
+#define Tolower(x)  tolower((unsigned char)x)
+
+#define IsASCII(x)  isascii((unsigned char)x)
+
+#define Strlen(x)       strlen(x)
+#define Strchr(s,c)     strchr(s,c)
+#define Strrchr(s,c)    strrchr(s,c)
+#define Strstr(s,v)     strstr(s,v)
+#define Strdup(x)       strdup(x)
+#define Strcpy(d,s)     strcpy(d,s)
+#define Strncpy(d,s,n)  strncpy(d,s,n)
+#define Strncat(d,s,n)  strncat(d,s,n)
+
+#define Strcmp(s,v)     strcmp(s,v)
+#define Strncmp(s,v,n)  strncmp(s,v,n)
+#define Strcspn(s,r)    strcspn(s,r)
+
+#define Strtol(p,e,b)   strtol(p,e,b)
+
+#define Width(c)       1
+
+#endif
+
+
+#ifdef WIDECHAR
+/*
+ * Conversion buffer
+ */
+typedef struct ct_buffer_t {
+        char    *cbuff;
+        size_t  csize;
+        Char *wbuff;
+        size_t  wsize;
+} ct_buffer_t;
+
+#define ct_encode_string __ct_encode_string
+/* Encode a wide-character string and return the UTF-8 encoded result. */
+public char *ct_encode_string(const Char *, ct_buffer_t *);
+
+#define ct_decode_string __ct_decode_string
+/* Decode a (multi)?byte string and return the wide-character string result. */
+public Char *ct_decode_string(const char *, ct_buffer_t *);
+
+/* Decode a (multi)?byte argv string array.
+ * The pointer returned must be free()d when done. */
+protected Char **ct_decode_argv(int, const char *[],  ct_buffer_t *);
+
+/* Resizes the conversion buffer(s) if needed. */
+protected void ct_conv_buff_resize(ct_buffer_t *, size_t, size_t);
+protected ssize_t ct_encode_char(char *, size_t, Char);
+protected size_t ct_enc_width(Char);
+
+#define ct_free_argv(s)        el_free(s)
+
+#else
+#define        ct_encode_string(s, b)  (s)
+#define ct_decode_string(s, b) (s)
+#define ct_decode_argv(l, s, b)        (s)
+#define ct_conv_buff_resize(b, os, ns)
+#define ct_encode_char(d, l, s)        (*d = s, 1)
+#define ct_free_argv(s)
+#endif
+
+#ifndef NARROWCHAR
+/* Encode a characted into the destination buffer, provided there is sufficent
+ * buffer space available. Returns the number of bytes used up (zero if the
+ * character cannot be encoded, -1 if there was not enough space available). */
+
+/* The maximum buffer size to hold the most unwieldly visual representation,
+ * in this case \U+nnnnn. */
+#define VISUAL_WIDTH_MAX ((size_t)8)
+
+/* The terminal is thought of in terms of X columns by Y lines. In the cases
+ * where a wide character takes up more than one column, the adjacent 
+ * occupied column entries will contain this faux character. */
+#define MB_FILL_CHAR ((Char)-1)
+
+/* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn
+ * style visual expansions. */
+protected int ct_visual_width(Char);
+
+/* Turn the given character into the appropriate visual format, matching
+ * the width given by ct_visual_width(). Returns the number of characters used
+ * up, or -1 if insufficient space. Buffer length is in count of Char's. */
+protected ssize_t ct_visual_char(Char *, size_t, Char);
+
+/* Convert the given string into visual format, using the ct_visual_char()
+ * function. Uses a static buffer, so not threadsafe. */
+protected const Char *ct_visual_string(const Char *);
+
+
+/* printable character, use ct_visual_width() to find out display width */
+#define CHTYPE_PRINT        ( 0)
+/* control character found inside the ASCII portion of the charset */
+#define CHTYPE_ASCIICTL     (-1)
+/* a \t */
+#define CHTYPE_TAB          (-2)
+/* a \n */
+#define CHTYPE_NL           (-3)
+/* non-printable character */
+#define CHTYPE_NONPRINT     (-4)
+/* classification of character c, as one of the above defines */
+protected int ct_chr_class(Char c);
+#endif
+
+
+#endif /* _chartype_f */
diff --git a/contrib/libedit/src/common.c b/contrib/libedit/src/common.c
new file mode 100644 (file)
index 0000000..d8e8b4f
--- /dev/null
@@ -0,0 +1,922 @@
+/*     $NetBSD: common.c,v 1.28 2011/07/29 20:58:07 christos 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. 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.
+ */
+
+#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.28 2011/07/29 20:58:07 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * common.c: Common Editor functions
+ */
+#include "el.h"
+
+/* ed_end_of_file():
+ *     Indicate end of file
+ *     [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_end_of_file(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar = '\0';
+       return CC_EOF;
+}
+
+
+/* ed_insert():
+ *     Add character to the line
+ *     Insert a character [bound to all insert keys]
+ */
+protected el_action_t
+ed_insert(EditLine *el, Int c)
+{
+       int count = el->el_state.argument;
+
+       if (c == '\0')
+               return CC_ERROR;
+
+       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) count))
+                       return CC_ERROR;        /* error allocating more */
+       }
+
+       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;
+               re_fastaddc(el);                /* fast refresh for one char. */
+       } else {
+               if (el->el_state.inputmode != MODE_REPLACE_1)
+                       c_insert(el, 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)
+               return vi_command_mode(el, 0);
+
+       return CC_NORM;
+}
+
+
+/* ed_delete_prev_word():
+ *     Delete from beginning of current word to cursor
+ *     [M-^?] [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *p, *kp;
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
+
+       for (p = cp, kp = el->el_chared.c_kill.buf; p < el->el_line.cursor; p++)
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
+
+       c_delbefore(el, (int)(el->el_line.cursor - cp));/* delete before dot */
+       el->el_line.cursor = cp;
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer; /* bounds check */
+       return CC_REFRESH;
+}
+
+
+/* ed_delete_next_char():
+ *     Delete character under cursor
+ *     [^D] [x]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+#ifdef DEBUG_EDIT
+#define        EL      el->el_line
+       (void) fprintf(el->el_errlfile,
+           "\nD(b: %x(%s)  c: %x(%s) last: %x(%s) limit: %x(%s)\n",
+           EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
+           EL.lastchar, EL.limit, EL.limit);
+#endif
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                       /* if I'm at the end */
+               if (el->el_map.type == MAP_VI) {
+                       if (el->el_line.cursor == el->el_line.buffer) {
+                               /* if I'm also at the beginning */
+#ifdef KSHVI
+                               return CC_ERROR;
+#else
+                               /* then do an EOF */
+                               terminal_writec(el, c);
+                               return CC_EOF;
+#endif
+                       } else {
+#ifdef KSHVI
+                               el->el_line.cursor--;
+#else
+                               return CC_ERROR;
+#endif
+                       }
+               } else {
+                       if (el->el_line.cursor != el->el_line.buffer)
+                               el->el_line.cursor--;
+                       else
+                               return CC_ERROR;
+               }
+       }
+       c_delafter(el, el->el_state.argument);  /* delete after dot */
+       if (el->el_line.cursor >= el->el_line.lastchar &&
+           el->el_line.cursor > el->el_line.buffer)
+                       /* bounds check */
+               el->el_line.cursor = el->el_line.lastchar - 1;
+       return CC_REFRESH;
+}
+
+
+/* ed_kill_line():
+ *     Cut to the end of line
+ *     [^K] [^K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_kill_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       cp = el->el_line.cursor;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                       /* zap! -- delete to end */
+       el->el_line.lastchar = el->el_line.cursor;
+       return CC_REFRESH;
+}
+
+
+/* ed_move_to_end():
+ *     Move cursor to the end of line
+ *     [^E] [^E]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_end(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.lastchar;
+       if (el->el_map.type == MAP_VI) {
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+#ifdef VI_MOVE
+               el->el_line.cursor--;
+#endif
+       }
+       return CC_CURSOR;
+}
+
+
+/* ed_move_to_beg():
+ *     Move cursor to the beginning of line
+ *     [^A] [^A]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_move_to_beg(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_line.cursor = el->el_line.buffer;
+
+       if (el->el_map.type == MAP_VI) {
+                       /* We want FIRST non space character */
+               while (Isspace(*el->el_line.cursor))
+                       el->el_line.cursor++;
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       }
+       return CC_CURSOR;
+}
+
+
+/* ed_transpose_chars():
+ *     Exchange the character to the left of the cursor with the one under it
+ *     [^T] [^T]
+ */
+protected el_action_t
+ed_transpose_chars(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor < el->el_line.lastchar) {
+               if (el->el_line.lastchar <= &el->el_line.buffer[1])
+                       return CC_ERROR;
+               else
+                       el->el_line.cursor++;
+       }
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return CC_REFRESH;
+       } else
+               return CC_ERROR;
+}
+
+
+/* ed_next_char():
+ *     Move to the right one character
+ *     [^F] [^F]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *lim = 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 > lim)
+               el->el_line.cursor = lim;
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* ed_prev_word():
+ *     Move to the beginning of the current word
+ *     [M-b] [b]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       el->el_line.cursor = c__prev_word(el->el_line.cursor,
+           el->el_line.buffer,
+           el->el_state.argument,
+           ce__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* ed_prev_char():
+ *     Move to the left one character
+ *     [^B] [^B]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor > el->el_line.buffer) {
+               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;
+
+               if (el->el_map.type == MAP_VI)
+                       if (el->el_chared.c_vcmd.action != NOP) {
+                               cv_delfini(el);
+                               return CC_REFRESH;
+                       }
+               return CC_CURSOR;
+       } else
+               return CC_ERROR;
+}
+
+
+/* ed_quoted_insert():
+ *     Add the next character typed verbatim
+ *     [^V] [^V]
+ */
+protected el_action_t
+ed_quoted_insert(EditLine *el, Int c)
+{
+       int num;
+       Char tc;
+
+       tty_quotemode(el);
+       num = FUN(el,getc)(el, &tc);
+       c = tc;
+       tty_noquotemode(el);
+       if (num == 1)
+               return ed_insert(el, c);
+       else
+               return ed_end_of_file(el, 0);
+}
+
+
+/* ed_digit():
+ *     Adds to argument or enters a digit
+ */
+protected el_action_t
+ed_digit(EditLine *el, Int c)
+{
+
+       if (!Isdigit(c))
+               return CC_ERROR;
+
+       if (el->el_state.doingarg) {
+                       /* if doing an arg, add this in... */
+               if (el->el_state.lastcmd == EM_UNIVERSAL_ARGUMENT)
+                       el->el_state.argument = c - '0';
+               else {
+                       if (el->el_state.argument > 1000000)
+                               return CC_ERROR;
+                       el->el_state.argument =
+                           (el->el_state.argument * 10) + (c - '0');
+               }
+               return CC_ARGHACK;
+       }
+
+       return ed_insert(el, c);
+}
+
+
+/* ed_argument_digit():
+ *     Digit that starts argument
+ *     For ESC-n
+ */
+protected el_action_t
+ed_argument_digit(EditLine *el, Int c)
+{
+
+       if (!Isdigit(c))
+               return CC_ERROR;
+
+       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');
+       } else {                /* else starting an argument */
+               el->el_state.argument = c - '0';
+               el->el_state.doingarg = 1;
+       }
+       return CC_ARGHACK;
+}
+
+
+/* ed_unassigned():
+ *     Indicates unbound character
+ *     Bound to keys that are not assigned
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_unassigned(EditLine *el __attribute__((__unused__)),
+    Int c __attribute__((__unused__)))
+{
+
+       return CC_ERROR;
+}
+
+
+/**
+ ** TTY key handling.
+ **/
+
+/* ed_tty_sigint():
+ *     Tty interrupt character
+ *     [^C]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigint(EditLine *el __attribute__((__unused__)), 
+             Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_dsusp():
+ *     Tty delayed suspend character
+ *     [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_dsusp(EditLine *el __attribute__((__unused__)), 
+            Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_flush_output():
+ *     Tty flush output characters
+ *     [^O]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_flush_output(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_sigquit():
+ *     Tty quit character
+ *     [^\]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigquit(EditLine *el __attribute__((__unused__)), 
+              Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_sigtstp():
+ *     Tty suspend character
+ *     [^Z]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_sigtstp(EditLine *el __attribute__((__unused__)), 
+              Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_stop_output():
+ *     Tty disallow output characters
+ *     [^S]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_stop_output(EditLine *el __attribute__((__unused__)), 
+                  Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_tty_start_output():
+ *     Tty allow output characters
+ *     [^Q]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_tty_start_output(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_newline():
+ *     Execute command
+ *     [^J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_newline(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       re_goto_bottom(el);
+       *el->el_line.lastchar++ = '\n';
+       *el->el_line.lastchar = '\0';
+       return CC_NEWLINE;
+}
+
+
+/* ed_delete_prev_char():
+ *     Delete the character to the left of the cursor
+ *     [^?]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_delete_prev_char(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       if (el->el_line.cursor <= el->el_line.buffer)
+               return CC_ERROR;
+
+       c_delbefore(el, el->el_state.argument);
+       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;
+}
+
+
+/* ed_clear_screen():
+ *     Clear screen leaving current line at the top
+ *     [^L]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_clear_screen(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       terminal_clear_screen(el);      /* clear the whole real screen */
+       re_clear_display(el);   /* reset everything */
+       return CC_REFRESH;
+}
+
+
+/* ed_redisplay():
+ *     Redisplay everything
+ *     ^R
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_redisplay(EditLine *el __attribute__((__unused__)), 
+            Int c __attribute__((__unused__)))
+{
+
+       return CC_REDISPLAY;
+}
+
+
+/* ed_start_over():
+ *     Erase current line and start from scratch
+ *     [^G]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_start_over(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       ch_reset(el, 0);
+       return CC_REFRESH;
+}
+
+
+/* ed_sequence_lead_in():
+ *     First character in a bound sequence
+ *     Placeholder for external keys
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), 
+                   Int c __attribute__((__unused__)))
+{
+
+       return CC_NORM;
+}
+
+
+/* ed_prev_history():
+ *     Move to the previous history line
+ *     [^P] [k]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       char beep = 0;
+       int sv_event = el->el_history.eventno;
+
+       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
+                                                * away */
+               (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);
+       }
+       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;
+                       
+               }
+               beep = 1;
+               /* el->el_history.eventno was fixed by first call */
+               (void) hist_get(el);
+       }
+       if (beep)
+               return CC_REFRESH_BEEP;
+       return CC_REFRESH;
+}
+
+
+/* ed_next_history():
+ *     Move to the next history line
+ *     [^N] [j]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_history(EditLine *el, Int c __attribute__((__unused__)))
+{
+       el_action_t beep = CC_REFRESH, rval;
+
+       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;
+               beep = CC_REFRESH_BEEP;
+       }
+       rval = hist_get(el);
+       if (rval == CC_REFRESH)
+               return beep;
+       return rval;
+
+}
+
+
+/* ed_search_prev_history():
+ *     Search previous in history for a line matching the current
+ *     next search history [M-P] [K]
+ */
+protected el_action_t
+/*ARGSUSED*/
+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.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+       if (el->el_history.eventno < 0) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile,
+                   "e_prev_search_hist(): eventno < 0;\n");
+#endif
+               el->el_history.eventno = 0;
+               return CC_ERROR;
+       }
+       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);
+       }
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return CC_ERROR;
+
+       c_setpat(el);           /* Set search pattern !! */
+
+       for (h = 1; h <= el->el_history.eventno; h++)
+               hp = HIST_NEXT(el);
+
+       while (hp != NULL) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+               if ((Strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp)) {
+                       found++;
+                       break;
+               }
+               h++;
+               hp = HIST_NEXT(el);
+       }
+
+       if (!found) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "not found\n");
+#endif
+               return CC_ERROR;
+       }
+       el->el_history.eventno = h;
+
+       return hist_get(el);
+}
+
+
+/* ed_search_next_history():
+ *     Search next in history for a line matching the current
+ *     [M-N] [J]
+ */
+protected el_action_t
+/*ARGSUSED*/
+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.len = -1;
+       *el->el_line.lastchar = '\0';   /* just in case */
+
+       if (el->el_history.eventno == 0)
+               return CC_ERROR;
+
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+       if (hp == NULL)
+               return CC_ERROR;
+
+       c_setpat(el);           /* Set search pattern !! */
+
+       for (h = 1; h < el->el_history.eventno && hp; h++) {
+#ifdef SDEBUG
+               (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
+#endif
+               if ((Strncmp(hp, el->el_line.buffer, (size_t)
+                           (el->el_line.lastchar - el->el_line.buffer)) ||
+                       hp[el->el_line.lastchar - el->el_line.buffer]) &&
+                   c_hmatch(el, hp))
+                       found = h;
+               hp = HIST_NEXT(el);
+       }
+
+       if (!found) {           /* is it the current history number? */
+               if (!c_hmatch(el, el->el_history.buf)) {
+#ifdef SDEBUG
+                       (void) fprintf(el->el_errfile, "not found\n");
+#endif
+                       return CC_ERROR;
+               }
+       }
+       el->el_history.eventno = found;
+
+       return hist_get(el);
+}
+
+
+/* ed_prev_line():
+ *     Move up one line
+ *     Could be [k] [^p]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_prev_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *ptr;
+       int nchars = c_hpos(el);
+
+       /*
+         * Move to the line requested
+         */
+       if (*(ptr = el->el_line.cursor) == '\n')
+               ptr--;
+
+       for (; ptr >= el->el_line.buffer; ptr--)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
+
+       if (el->el_state.argument > 0)
+               return CC_ERROR;
+
+       /*
+         * Move to the beginning of the line
+         */
+       for (ptr--; ptr >= el->el_line.buffer && *ptr != '\n'; ptr--)
+               continue;
+
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
+
+       el->el_line.cursor = ptr;
+       return CC_CURSOR;
+}
+
+
+/* ed_next_line():
+ *     Move down one line
+ *     Could be [j] [^n]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_next_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *ptr;
+       int nchars = c_hpos(el);
+
+       /*
+         * Move to the line requested
+         */
+       for (ptr = el->el_line.cursor; ptr < el->el_line.lastchar; ptr++)
+               if (*ptr == '\n' && --el->el_state.argument <= 0)
+                       break;
+
+       if (el->el_state.argument > 0)
+               return CC_ERROR;
+
+       /*
+         * Move to the character requested
+         */
+       for (ptr++;
+           nchars-- > 0 && ptr < el->el_line.lastchar && *ptr != '\n';
+           ptr++)
+               continue;
+
+       el->el_line.cursor = ptr;
+       return CC_CURSOR;
+}
+
+
+/* ed_command():
+ *     Editline extended command
+ *     [M-X] [:]
+ */
+protected el_action_t
+/*ARGSUSED*/
+ed_command(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char tmpbuf[EL_BUFSIZ];
+       int tmplen;
+
+       tmplen = c_gets(el, tmpbuf, STR("\n: "));
+       terminal__putc(el, '\n');
+
+       if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)
+               terminal_beep(el);
+
+       el->el_map.current = el->el_map.key;
+       re_clear_display(el);
+       return CC_REFRESH;
+}
diff --git a/contrib/libedit/src/editline/readline.h b/contrib/libedit/src/editline/readline.h
new file mode 100644 (file)
index 0000000..4c4d65a
--- /dev/null
@@ -0,0 +1,221 @@
+/*     $NetBSD: readline.h,v 1.32 2010/09/16 20:08:52 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.
+ *
+ * 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 _READLINE_H_
+#define _READLINE_H_
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/* list of readline stuff supported by editline library's readline wrapper */
+
+/* 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);
+typedef char     *rl_compentry_func_t(const char *, int);
+typedef int      rl_command_func_t(int, int);
+
+/* only supports length */
+typedef struct {
+       int length;
+} HISTORY_STATE;
+
+typedef void *histdata_t;
+
+typedef struct _hist_entry {
+       const char      *line;
+       histdata_t       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) && !defined(_AIX)
+#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')
+#define RL_READLINE_VERSION    0x0402
+#define RL_PROMPT_START_IGNORE '\1'
+#define RL_PROMPT_END_IGNORE   '\2'
+
+/* global variables used by readline enabled applications */
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern const char      *rl_library_version;
+extern int             rl_readline_version; 
+extern char            *rl_readline_name;
+extern FILE            *rl_instream;
+extern FILE            *rl_outstream;
+extern char            *rl_line_buffer;
+extern int              rl_point, rl_end;
+extern int              history_base, history_length;
+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 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 int             (*rl_getc_function)(FILE *);
+extern VFunction       *rl_redisplay_function;
+extern VFunction       *rl_completion_display_matches_hook;
+extern VFunction       *rl_prep_term_function;
+extern VFunction       *rl_deprep_term_function;
+extern int             readline_echoing_p;
+extern int             _rl_print_completions_horizontally;
+
+/* supported functions */
+char           *readline(const char *);
+int             rl_initialize(void);
+
+void            using_history(void);
+int             add_history(const char *);
+void            clear_history(void);
+void            stifle_history(int);
+int             unstifle_history(void);
+int             history_is_stifled(void);
+int             where_history(void);
+HIST_ENTRY     *current_history(void);
+HIST_ENTRY     *history_get(int);
+HIST_ENTRY     *remove_history(int);
+HIST_ENTRY     *replace_history_entry(int, const char *, histdata_t);
+int             history_total_bytes(void);
+int             history_set_pos(int);
+HIST_ENTRY     *previous_history(void);
+HIST_ENTRY     *next_history(void);
+int             history_search(const char *, int);
+int             history_search_prefix(const char *, int);
+int             history_search_pos(const char *, int, int);
+int             read_history(const char *);
+int             write_history(const char *);
+int             history_truncate_file (const char *, int);
+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);
+char           *username_completion_function(const char *, int);
+int             rl_complete(int, int);
+int             rl_read_key(void);
+char          **completion_matches(const char *, CPFunction *);
+void            rl_display_match_list(char **, int, int);
+
+int             rl_insert(int, int);
+int             rl_insert_text(const char *);
+void            rl_reset_terminal(const char *);
+int             rl_bind_key(int, rl_command_func_t *);
+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);
+HISTORY_STATE  *history_get_history_state(void);
+void            rl_get_screen_size(int *, int *);
+void            rl_set_screen_size(int, int);
+char           *rl_filename_completion_function (const char *, int);
+int             _rl_abort_internal(void);
+int             _rl_qsort_string_compare(char **, char **);
+char          **rl_completion_matches(const char *, rl_compentry_func_t *);
+void            rl_forced_update_display(void);
+int             rl_set_prompt(const char *);
+int             rl_on_new_line(void);
+
+/*
+ * The following are not implemented
+ */
+int             rl_kill_text(int, int);
+Keymap          rl_get_keymap(void);
+void            rl_set_keymap(Keymap);
+Keymap          rl_make_bare_keymap(void);
+int             rl_generic_bind(int, const char *, const char *, Keymap);
+int             rl_bind_key_in_map(int, rl_command_func_t *, Keymap);
+void            rl_cleanup_after_signal(void);
+void            rl_free_line_state(void);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _READLINE_H_ */
diff --git a/contrib/libedit/src/el.c b/contrib/libedit/src/el.c
new file mode 100644 (file)
index 0000000..b11607a
--- /dev/null
@@ -0,0 +1,621 @@
+/*     $NetBSD: el.c,v 1.70 2012/03/11 21:14:56 christos 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. 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.
+ */
+
+#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.70 2012/03/11 21:14:56 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 4096
+#endif
+
+/*
+ * el.c: EditLine interface functions
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <locale.h>
+#include <langinfo.h>
+#include "el.h"
+
+/* el_init():
+ *     Initialize editline and set default parameters.
+ */
+public EditLine *
+el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
+{
+       EditLine *el = el_malloc(sizeof(*el));
+
+       if (el == NULL)
+               return NULL;
+
+       memset(el, 0, sizeof(EditLine));
+
+       el->el_infile = fin;
+       el->el_outfile = fout;
+       el->el_errfile = ferr;
+
+       el->el_infd = fileno(fin);
+       el->el_outfd = fileno(fout);
+       el->el_errfd = fileno(ferr);
+
+       el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
+       if (el->el_prog == NULL) {
+               el_free(el);
+               return NULL;
+       }
+
+       /*
+         * Initialize all the modules. Order is important!!!
+         */
+       el->el_flags = 0;
+#ifdef WIDECHAR
+       if (setlocale(LC_CTYPE, NULL) != NULL){
+               if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
+                       el->el_flags |= CHARSET_IS_UTF8;
+       }
+#endif
+
+       if (terminal_init(el) == -1) {
+               el_free(el->el_prog);
+               el_free(el);
+               return NULL;
+       }
+       (void) keymacro_init(el);
+       (void) map_init(el);
+       if (tty_init(el) == -1)
+               el->el_flags |= NO_TTY;
+       (void) ch_init(el);
+       (void) search_init(el);
+       (void) hist_init(el);
+       (void) prompt_init(el);
+       (void) sig_init(el);
+       (void) read_init(el);
+
+       return el;
+}
+
+
+/* el_end():
+ *     Clean up.
+ */
+public void
+el_end(EditLine *el)
+{
+
+       if (el == NULL)
+               return;
+
+       el_reset(el);
+
+       terminal_end(el);
+       keymacro_end(el);
+       map_end(el);
+       tty_end(el);
+       ch_end(el);
+       search_end(el);
+       hist_end(el);
+       prompt_end(el);
+       sig_end(el);
+
+       el_free(el->el_prog);
+#ifdef WIDECHAR
+       el_free(el->el_scratch.cbuff);
+       el_free(el->el_scratch.wbuff);
+       el_free(el->el_lgcyconv.cbuff);
+       el_free(el->el_lgcyconv.wbuff);
+#endif
+       el_free(el);
+}
+
+
+/* el_reset():
+ *     Reset the tty and the parser
+ */
+public void
+el_reset(EditLine *el)
+{
+
+       tty_cookedmode(el);
+       ch_reset(el, 0);                /* XXX: Do we want that? */
+}
+
+
+/* el_set():
+ *     set the editline parameters
+ */
+public int
+FUN(el,set)(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int rv = 0;
+
+       if (el == NULL)
+               return -1;
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+
+               rv = prompt_set(el, p, 0, op, 1);
+               break;
+       }
+
+       case EL_RESIZE: {
+               el_zfunc_t p = va_arg(ap, el_zfunc_t);
+               void *arg = va_arg(ap, void *);
+               rv = ch_resizefun(el, p, arg);
+               break;
+       }
+
+       case EL_PROMPT_ESC:
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               int c = va_arg(ap, int);
+
+               rv = prompt_set(el, p, c, op, 1);
+               break;
+       }
+
+       case EL_TERMINAL:
+               rv = terminal_set(el, va_arg(ap, char *));
+               break;
+
+       case EL_EDITOR:
+               rv = map_set_editor(el, va_arg(ap, Char *));
+               break;
+
+       case EL_SIGNAL:
+               if (va_arg(ap, int))
+                       el->el_flags |= HANDLE_SIGNALS;
+               else
+                       el->el_flags &= ~HANDLE_SIGNALS;
+               break;
+
+       case EL_BIND:
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY:
+       {
+               const Char *argv[20];
+               int i;
+
+               for (i = 1; i < (int)__arraycount(argv); i++)
+                       if ((argv[i] = va_arg(ap, Char *)) == NULL)
+                               break;
+
+               switch (op) {
+               case EL_BIND:
+                       argv[0] = STR("bind");
+                       rv = map_bind(el, i, argv);
+                       break;
+
+               case EL_TELLTC:
+                       argv[0] = STR("telltc");
+                       rv = terminal_telltc(el, i, argv);
+                       break;
+
+               case EL_SETTC:
+                       argv[0] = STR("settc");
+                       rv = terminal_settc(el, i, argv);
+                       break;
+
+               case EL_ECHOTC:
+                       argv[0] = STR("echotc");
+                       rv = terminal_echotc(el, i, argv);
+                       break;
+
+               case EL_SETTY:
+                       argv[0] = STR("setty");
+                       rv = tty_stty(el, i, argv);
+                       break;
+
+               default:
+                       rv = -1;
+                       EL_ABORT((el->el_errfile, "Bad op %d\n", op));
+                       break;
+               }
+               break;
+       }
+
+       case EL_ADDFN:
+       {
+               Char *name = va_arg(ap, Char *);
+               Char *help = va_arg(ap, Char *);
+               el_func_t func = va_arg(ap, el_func_t);
+
+               rv = map_addfunc(el, name, help, func);
+               break;
+       }
+
+       case EL_HIST:
+       {
+               hist_fun_t func = va_arg(ap, hist_fun_t);
+               void *ptr = va_arg(ap, void *);
+
+               rv = hist_set(el, func, ptr);
+               if (!(el->el_flags & CHARSET_IS_UTF8))
+                       el->el_flags &= ~NARROW_HISTORY;
+               break;
+       }
+
+       case EL_EDITMODE:
+               if (va_arg(ap, int))
+                       el->el_flags &= ~EDIT_DISABLED;
+               else
+                       el->el_flags |= EDIT_DISABLED;
+               rv = 0;
+               break;
+
+       case EL_GETCFN:
+       {
+               el_rfunc_t rc = va_arg(ap, el_rfunc_t);
+               rv = el_read_setfn(el, rc);
+               el->el_flags &= ~NARROW_READ;
+               break;
+       }
+
+       case EL_CLIENTDATA:
+               el->el_data = va_arg(ap, void *);
+               break;
+
+       case EL_UNBUFFERED:
+               rv = va_arg(ap, 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(ap, int);
+               if (rv)
+                       (void) tty_rawmode(el);
+               else
+                       (void) tty_cookedmode(el);
+               rv = 0;
+               break;
+
+       case EL_SETFP:
+       {
+               FILE *fp;
+               int what;
+
+               what = va_arg(ap, int);
+               fp = va_arg(ap, FILE *);
+
+               rv = 0;
+               switch (what) {
+               case 0:
+                       el->el_infile = fp;
+                       el->el_infd = fileno(fp);
+                       break;
+               case 1:
+                       el->el_outfile = fp;
+                       el->el_outfd = fileno(fp);
+                       break;
+               case 2:
+                       el->el_errfile = fp;
+                       el->el_errfd = fileno(fp);
+                       break;
+               default:
+                       rv = -1;
+                       break;
+               }
+               break;
+       }
+
+       case EL_REFRESH:
+               re_clear_display(el);
+               re_refresh(el);
+               terminal__flush(el);
+               break;
+
+       default:
+               rv = -1;
+               break;
+       }
+
+       va_end(ap);
+       return rv;
+}
+
+
+/* el_get():
+ *     retrieve the editline parameters
+ */
+public int
+FUN(el,get)(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int rv;
+
+       if (el == NULL)
+               return -1;
+
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:
+       case EL_RPROMPT: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               rv = prompt_get(el, p, 0, op);
+               break;
+       }
+       case EL_PROMPT_ESC:
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               Char *c = va_arg(ap, Char *);
+
+               rv = prompt_get(el, p, c, op);
+               break;
+       }
+
+       case EL_EDITOR:
+               rv = map_get_editor(el, va_arg(ap, const Char **));
+               break;
+
+       case EL_SIGNAL:
+               *va_arg(ap, int *) = (el->el_flags & HANDLE_SIGNALS);
+               rv = 0;
+               break;
+
+       case EL_EDITMODE:
+               *va_arg(ap, int *) = !(el->el_flags & EDIT_DISABLED);
+               rv = 0;
+               break;
+
+       case EL_TERMINAL:
+               terminal_get(el, va_arg(ap, const char **));
+               rv = 0;
+               break;
+
+       case EL_GETTC:
+       {
+               static char name[] = "gettc";
+               char *argv[20];
+               int i;
+
+               for (i = 1; i < (int)__arraycount(argv); i++)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                               break;
+
+               argv[0] = name;
+               rv = terminal_gettc(el, i, argv);
+               break;
+       }
+
+       case EL_GETCFN:
+               *va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
+               rv = 0;
+               break;
+
+       case EL_CLIENTDATA:
+               *va_arg(ap, void **) = el->el_data;
+               rv = 0;
+               break;
+
+       case EL_UNBUFFERED:
+               *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED));
+               rv = 0;
+               break;
+
+       case EL_GETFP:
+       {
+               int what;
+               FILE **fpp;
+
+               what = va_arg(ap, int);
+               fpp = va_arg(ap, FILE **);
+               rv = 0;
+               switch (what) {
+               case 0:
+                       *fpp = el->el_infile;
+                       break;
+               case 1:
+                       *fpp = el->el_outfile;
+                       break;
+               case 2:
+                       *fpp = el->el_errfile;
+                       break;
+               default:
+                       rv = -1;
+                       break;
+               }
+               break;
+       }
+       default:
+               rv = -1;
+               break;
+       }
+       va_end(ap);
+
+       return rv;
+}
+
+
+/* el_line():
+ *     Return editing info
+ */
+public const TYPE(LineInfo) *
+FUN(el,line)(EditLine *el)
+{
+
+       return (const TYPE(LineInfo) *)(void *)&el->el_line;
+}
+
+
+/* el_source():
+ *     Source a file
+ */
+public int
+el_source(EditLine *el, const char *fname)
+{
+       FILE *fp;
+       size_t len;
+       char *ptr;
+       char *path = NULL;
+       const Char *dptr;
+       int error = 0;
+
+       fp = NULL;
+       if (fname == NULL) {
+               static const char elpath[] = "/.editrc";
+               size_t plen = sizeof(elpath);
+
+#ifdef HAVE_ISSETUGID
+               if (issetugid())
+                       return -1;
+               if ((ptr = getenv("HOME")) == NULL)
+                       return -1;
+               plen += strlen(ptr);
+               if ((path = el_malloc(plen * sizeof(*path))) == NULL)
+                       return -1;
+               (void)snprintf(path, plen, "%s%s", ptr, elpath);
+               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");
+       if (fp == NULL) {
+               el_free(path);
+               return -1;
+       }
+
+       while ((ptr = fgetln(fp, &len)) != NULL) {
+               if (*ptr == '\n')
+                       continue;       /* Empty line. */
+               dptr = ct_decode_string(ptr, &el->el_scratch);
+               if (!dptr)
+                       continue;
+               if (len > 0 && dptr[len - 1] == '\n')
+                       --len;
+
+               /* loop until first non-space char or EOL */
+               while (*dptr != '\0' && Isspace(*dptr))
+                       dptr++;
+               if (*dptr == '#')
+                       continue;   /* ignore, this is a comment line */
+               if ((error = parse_line(el, dptr)) == -1)
+                       break;
+       }
+
+       el_free(path);
+       (void) fclose(fp);
+       return error;
+}
+
+
+/* el_resize():
+ *     Called from program when terminal is resized
+ */
+public void
+el_resize(EditLine *el)
+{
+       int lins, cols;
+       sigset_t oset, nset;
+
+       (void) sigemptyset(&nset);
+       (void) sigaddset(&nset, SIGWINCH);
+       (void) sigprocmask(SIG_BLOCK, &nset, &oset);
+
+       /* get the correct window size */
+       if (terminal_get_size(el, &lins, &cols))
+               terminal_change_size(el, lins, cols);
+
+       (void) sigprocmask(SIG_SETMASK, &oset, NULL);
+}
+
+
+/* el_beep():
+ *     Called from the program to beep
+ */
+public void
+el_beep(EditLine *el)
+{
+
+       terminal_beep(el);
+}
+
+
+/* el_editmode()
+ *     Set the state of EDIT_DISABLED from the `edit' command.
+ */
+protected int
+/*ARGSUSED*/
+el_editmode(EditLine *el, int argc, const Char **argv)
+{
+       const Char *how;
+
+       if (argv == NULL || argc != 2 || argv[1] == NULL)
+               return -1;
+
+       how = argv[1];
+       if (Strcmp(how, STR("on")) == 0) {
+               el->el_flags &= ~EDIT_DISABLED;
+               tty_rawmode(el);
+       } else if (Strcmp(how, STR("off")) == 0) {
+               tty_cookedmode(el);
+               el->el_flags |= EDIT_DISABLED;
+       }
+       else {
+               (void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",
+                   how);
+               return -1;
+       }
+       return 0;
+}
diff --git a/contrib/libedit/src/el.h b/contrib/libedit/src/el.h
new file mode 100644 (file)
index 0000000..70c67b8
--- /dev/null
@@ -0,0 +1,163 @@
+/*     $NetBSD: el.h,v 1.25 2011/07/29 23:44:44 christos 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. 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.
+ *
+ *     @(#)el.h        8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.h: Internal structures.
+ */
+#ifndef _h_el
+#define        _h_el
+/*
+ * Local defaults
+ */
+#define        KSHVI
+#define        VIDEFAULT
+#define        ANCHOR
+
+#include "histedit.h"
+#include "chartype.h"
+#include <stdio.h>
+#include <sys/types.h>
+
+#define        EL_BUFSIZ       ((size_t)1024)  /* Maximum line size            */
+
+#define        HANDLE_SIGNALS  0x01
+#define        NO_TTY          0x02
+#define        EDIT_DISABLED   0x04
+#define        UNBUFFERED      0x08
+#define        CHARSET_IS_UTF8 0x10
+#define        IGNORE_EXTCHARS 0x20            /* Ignore characters read > 0xff */
+#define        NARROW_HISTORY  0x40
+#define        NARROW_READ     0x80
+
+typedef int bool_t;                    /* True or not                  */
+
+typedef unsigned char el_action_t;     /* Index to command array       */
+
+typedef struct coord_t {               /* Position on the screen       */
+       int     h;
+       int     v;
+} coord_t;
+
+typedef struct el_line_t {
+       Char            *buffer;        /* Input line                   */
+       Char            *cursor;        /* Cursor position              */
+       Char            *lastchar;      /* Last character               */
+       const Char      *limit;         /* Max position                 */
+} el_line_t;
+
+/*
+ * Editor state
+ */
+typedef struct el_state_t {
+       int             inputmode;      /* What mode are we in?         */
+       int             doingarg;       /* Are we getting an argument?  */
+       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_malloc(a)    malloc(a)
+#define        el_realloc(a,b) realloc(a, b)
+#define        el_free(a)      free(a)
+
+#include "tty.h"
+#include "prompt.h"
+#include "keymacro.h"
+#include "terminal.h"
+#include "refresh.h"
+#include "chared.h"
+#include "common.h"
+#include "search.h"
+#include "hist.h"
+#include "map.h"
+#include "parse.h"
+#include "sig.h"
+#include "help.h"
+#include "read.h"
+
+struct editline {
+       Char             *el_prog;      /* the program name             */
+       FILE             *el_infile;    /* Stdio stuff                  */
+       FILE             *el_outfile;   /* Stdio stuff                  */
+       FILE             *el_errfile;   /* Stdio stuff                  */
+       int               el_infd;      /* Input file descriptor        */
+       int               el_outfd;     /* Output file descriptor       */
+       int               el_errfd;     /* Error file descriptor        */
+       int               el_flags;     /* Various flags.               */
+       int               el_errno;     /* Local copy of errno          */
+       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_terminal_t     el_terminal;  /* Terminal dependent stuff     */
+       el_tty_t          el_tty;       /* Tty dependent stuff          */
+       el_refresh_t      el_refresh;   /* Refresh stuff                */
+       el_prompt_t       el_prompt;    /* Prompt stuff                 */
+       el_prompt_t       el_rprompt;   /* Prompt stuff                 */
+       el_chared_t       el_chared;    /* Characted editor stuff       */
+       el_map_t          el_map;       /* Key mapping stuff            */
+       el_keymacro_t     el_keymacro;  /* Key binding stuff            */
+       el_history_t      el_history;   /* History stuff                */
+       el_search_t       el_search;    /* Search stuff                 */
+       el_signal_t       el_signal;    /* Signal handling stuff        */
+       el_read_t         el_read;      /* Character reading stuff      */
+#ifdef WIDECHAR
+       ct_buffer_t       el_scratch;   /* Scratch conversion buffer    */
+       ct_buffer_t       el_lgcyconv;  /* Buffer for legacy wrappers   */
+       LineInfo          el_lgcylinfo; /* Legacy LineInfo buffer       */
+#endif
+};
+
+protected int  el_editmode(EditLine *, int, const Char **);
+
+#ifdef DEBUG
+#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
+#endif /* _h_el */
diff --git a/contrib/libedit/src/eln.c b/contrib/libedit/src/eln.c
new file mode 100644 (file)
index 0000000..1b829c2
--- /dev/null
@@ -0,0 +1,371 @@
+/*     $NetBSD: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $        */
+
+/*-
+ * Copyright (c) 2009 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * 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: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $");
+#endif /* not lint && not SCCSID */
+
+#include "histedit.h"
+#include "el.h"
+#include "read.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+public int
+el_getc(EditLine *el, char *cp)
+{
+       int num_read;
+       wchar_t wc = 0;
+
+       if (!(el->el_flags & CHARSET_IS_UTF8))
+               el->el_flags |= IGNORE_EXTCHARS;
+       num_read = el_wgetc (el, &wc);
+       if (!(el->el_flags & CHARSET_IS_UTF8))
+               el->el_flags &= ~IGNORE_EXTCHARS;
+
+       if (num_read > 0)
+               *cp = (char)wc;
+       return num_read;
+}
+
+
+public void
+el_push(EditLine *el, const char *str)
+{
+       /* Using multibyte->wide string decoding works fine under single-byte
+        * character sets too, and Does The Right Thing. */
+       el_wpush(el, ct_decode_string(str, &el->el_lgcyconv));
+}
+
+
+public const char *
+el_gets(EditLine *el, int *nread)
+{
+       const wchar_t *tmp;
+
+       el->el_flags |= IGNORE_EXTCHARS;
+       tmp = el_wgets(el, nread);
+       el->el_flags &= ~IGNORE_EXTCHARS;
+       return ct_encode_string(tmp, &el->el_lgcyconv);
+}
+
+
+public int
+el_parse(EditLine *el, int argc, const char *argv[])
+{
+       int ret;
+       const wchar_t **wargv;
+
+       wargv = (const wchar_t **)
+           ct_decode_argv(argc, argv, &el->el_lgcyconv);
+       if (!wargv)
+               return -1;
+       ret = el_wparse(el, argc, wargv);
+       ct_free_argv(wargv);
+
+       return ret;
+}
+
+
+public int
+el_set(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int ret;
+
+       if (!el)
+               return -1;
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:         /* el_pfunc_t */
+       case EL_RPROMPT: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               ret = prompt_set(el, p, 0, op, 0);
+               break;
+       }
+
+       case EL_RESIZE: {
+               el_zfunc_t p = va_arg(ap, el_zfunc_t);
+               void *arg = va_arg(ap, void *);
+               ret = ch_resizefun(el, p, arg);
+               break;
+       }
+
+       case EL_TERMINAL:       /* const char * */
+               ret = el_wset(el, op, va_arg(ap, char *));
+               break;
+
+       case EL_EDITOR:         /* const wchar_t * */
+               ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *),
+                   &el->el_lgcyconv));
+               break;
+
+       case EL_SIGNAL:         /* int */
+       case EL_EDITMODE:
+       case EL_UNBUFFERED:
+       case EL_PREP_TERM:
+               ret = el_wset(el, op, va_arg(ap, int));
+               break;
+
+       case EL_BIND:   /* const char * list -> const wchar_t * list */
+       case EL_TELLTC:
+       case EL_SETTC:
+       case EL_ECHOTC:
+       case EL_SETTY: {
+               const char *argv[20];
+               int i;
+               const wchar_t **wargv;
+               for (i = 1; i < (int)__arraycount(argv); ++i)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                           break;
+               argv[0] = NULL;
+               wargv = (const wchar_t **)
+                   ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
+               if (!wargv) {
+                   ret = -1;
+                   goto out;
+               }
+               /*
+                * AFAIK we can't portably pass through our new wargv to
+                * el_wset(), so we have to reimplement the body of
+                * el_wset() for these ops.
+                */
+               switch (op) {
+               case EL_BIND:
+                       wargv[0] = STR("bind");
+                       ret = map_bind(el, i, wargv);
+                       break;
+               case EL_TELLTC:
+                       wargv[0] = STR("telltc");
+                       ret = terminal_telltc(el, i, wargv);
+                       break;
+               case EL_SETTC:
+                       wargv[0] = STR("settc");
+                       ret = terminal_settc(el, i, wargv);
+                       break;
+               case EL_ECHOTC:
+                       wargv[0] = STR("echotc");
+                       ret = terminal_echotc(el, i, wargv);
+                       break;
+               case EL_SETTY:
+                       wargv[0] = STR("setty");
+                       ret = tty_stty(el, i, wargv);
+                       break;
+               default:
+                       ret = -1;
+               }
+               ct_free_argv(wargv);
+               break;
+       }
+
+       /* XXX: do we need to change el_func_t too? */
+       case EL_ADDFN: {          /* const char *, const char *, el_func_t */
+               const char *args[2];
+               el_func_t func;
+               wchar_t **wargv;
+
+               args[0] = va_arg(ap, const char *);
+               args[1] = va_arg(ap, const char *);
+               func = va_arg(ap, el_func_t);
+
+               wargv = ct_decode_argv(2, args, &el->el_lgcyconv);
+               if (!wargv) {
+                   ret = -1;
+                   goto out;
+               }
+               // XXX: The two strdup's leak
+               ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
+                   func);
+               ct_free_argv(wargv);
+               break;
+       }
+       case EL_HIST: {           /* hist_fun_t, const char * */
+               hist_fun_t fun = va_arg(ap, hist_fun_t);
+               void *ptr = va_arg(ap, void *);
+               ret = hist_set(el, fun, ptr);
+               el->el_flags |= NARROW_HISTORY;
+               break;
+       }
+       /* XXX: do we need to change el_rfunc_t? */
+       case EL_GETCFN:         /* el_rfunc_t */
+               ret = el_wset(el, op, va_arg(ap, el_rfunc_t));
+               el->el_flags |= NARROW_READ;
+               break;
+       case EL_CLIENTDATA:     /* void * */
+               ret = el_wset(el, op, va_arg(ap, void *));
+               break;
+       case EL_SETFP: {          /* int, FILE * */
+               int what = va_arg(ap, int);
+               FILE *fp = va_arg(ap, FILE *);
+               ret = el_wset(el, op, what, fp);
+               break;
+       }
+       case EL_PROMPT_ESC: /* el_pfunc_t, char */
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t p = va_arg(ap, el_pfunc_t);
+               char c = (char)va_arg(ap, int);
+               ret = prompt_set(el, p, c, op, 0);
+               break;
+       }
+       default:
+               ret = -1;
+               break;
+       }
+
+out:
+       va_end(ap);
+       return ret;
+}
+
+
+public int
+el_get(EditLine *el, int op, ...)
+{
+       va_list ap;
+       int ret;
+
+       if (!el)
+               return -1;
+
+       va_start(ap, op);
+
+       switch (op) {
+       case EL_PROMPT:         /* el_pfunc_t * */
+       case EL_RPROMPT: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               ret = prompt_get(el, p, 0, op);
+               break;
+       }
+
+       case EL_PROMPT_ESC: /* el_pfunc_t *, char **/
+       case EL_RPROMPT_ESC: {
+               el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
+               char *c = va_arg(ap, char *);
+               wchar_t wc = 0;
+               ret = prompt_get(el, p, &wc, op);
+               *c = (char)wc;
+               break;
+       }
+
+       case EL_EDITOR: {
+               const char **p = va_arg(ap, const char **);
+               const wchar_t *pw;
+               ret = el_wget(el, op, &pw);
+               *p = ct_encode_string(pw, &el->el_lgcyconv);
+               if (!el->el_lgcyconv.csize)
+                       ret = -1;
+               break;
+       }
+
+       case EL_TERMINAL:       /* const char ** */
+               ret = el_wget(el, op, va_arg(ap, const char **));
+               break;
+
+       case EL_SIGNAL:         /* int * */
+       case EL_EDITMODE:
+       case EL_UNBUFFERED:
+       case EL_PREP_TERM:
+               ret = el_wget(el, op, va_arg(ap, int *));
+               break;
+
+       case EL_GETTC: {
+               char *argv[20];
+               static char gettc[] = "gettc";
+               int i;
+               for (i = 1; i < (int)__arraycount(argv); ++i)
+                       if ((argv[i] = va_arg(ap, char *)) == NULL)
+                               break;
+               argv[0] = gettc;
+               ret = terminal_gettc(el, i, argv);
+               break;
+       }
+
+       /* XXX: do we need to change el_rfunc_t? */
+       case EL_GETCFN:         /* el_rfunc_t */
+               ret = el_wget(el, op, va_arg(ap, el_rfunc_t *));
+               break;
+
+       case EL_CLIENTDATA:     /* void ** */
+               ret = el_wget(el, op, va_arg(ap, void **));
+               break;
+
+       case EL_GETFP: {          /* int, FILE ** */
+               int what = va_arg(ap, int);
+               FILE **fpp = va_arg(ap, FILE **);
+               ret = el_wget(el, op, what, fpp);
+               break;
+       }
+
+       default:
+               ret = -1;
+               break;
+       }
+
+       va_end(ap);
+       return ret;
+}
+
+
+const LineInfo *
+el_line(EditLine *el)
+{
+       const LineInfoW *winfo = el_wline(el);
+       LineInfo *info = &el->el_lgcylinfo;
+       size_t offset;
+       const Char *p;
+
+       info->buffer   = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
+
+       offset = 0;
+       for (p = winfo->buffer; p < winfo->cursor; p++)
+               offset += ct_enc_width(*p);
+       info->cursor = info->buffer + offset;
+
+       offset = 0;
+       for (p = winfo->buffer; p < winfo->lastchar; p++)
+               offset += ct_enc_width(*p);
+       info->lastchar = info->buffer + offset;
+
+       return info;
+}
+
+
+int
+el_insertstr(EditLine *el, const char *str)
+{
+       return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
+}
diff --git a/contrib/libedit/src/emacs.c b/contrib/libedit/src/emacs.c
new file mode 100644 (file)
index 0000000..ab1e2df
--- /dev/null
@@ -0,0 +1,508 @@
+/*     $NetBSD: emacs.c,v 1.25 2011/07/29 15:16:33 christos 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. 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.
+ */
+
+#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.25 2011/07/29 15:16:33 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * emacs.c: Emacs functions
+ */
+#include "el.h"
+
+/* em_delete_or_list():
+ *     Delete character under cursor or list completions if at end of line
+ *     [^D]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_or_list(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor == el->el_line.lastchar) {
+                                       /* if I'm at the end */
+               if (el->el_line.cursor == el->el_line.buffer) {
+                                       /* and the beginning */
+                       terminal_writec(el, c); /* then do an EOF */
+                       return CC_EOF;
+               } else {
+                       /*
+                        * Here we could list completions, but it is an
+                        * error right now
+                        */
+                       terminal_beep(el);
+                       return CC_ERROR;
+               }
+       } else {
+               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 */
+               return CC_REFRESH;
+       }
+}
+
+
+/* em_delete_next_word():
+ *     Cut from cursor to end of current word
+ *     [M-d]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_delete_next_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *p, *kp;
+
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       cp = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (p = el->el_line.cursor, kp = el->el_chared.c_kill.buf; p < cp; p++)
+                               /* save the text */
+               *kp++ = *p;
+       el->el_chared.c_kill.last = kp;
+
+       c_delafter(el, (int)(cp - el->el_line.cursor)); /* delete after dot */
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+                               /* bounds check */
+       return CC_REFRESH;
+}
+
+
+/* em_yank():
+ *     Paste cut buffer at cursor position
+ *     [^Y]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_yank(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       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) >=
+           el->el_line.limit)
+               return CC_ERROR;
+
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       cp = el->el_line.cursor;
+
+       /* open the space, */
+       c_insert(el,
+           (int)(el->el_chared.c_kill.last - el->el_chared.c_kill.buf));
+       /* copy the chars */
+       for (kp = el->el_chared.c_kill.buf; kp < el->el_chared.c_kill.last; kp++)
+               *cp++ = *kp;
+
+       /* if an arg, cursor at beginning else cursor at end */
+       if (el->el_state.argument == 1)
+               el->el_line.cursor = cp;
+
+       return CC_REFRESH;
+}
+
+
+/* em_kill_line():
+ *     Cut the entire line and save in cut buffer
+ *     [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_line(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       cp = el->el_line.buffer;
+       kp = el->el_chared.c_kill.buf;
+       while (cp < el->el_line.lastchar)
+               *kp++ = *cp++;  /* copy it */
+       el->el_chared.c_kill.last = kp;
+                               /* zap! -- delete all of it */
+       el->el_line.lastchar = el->el_line.buffer;
+       el->el_line.cursor = el->el_line.buffer;
+       return CC_REFRESH;
+}
+
+
+/* em_kill_region():
+ *     Cut area between mark and cursor and save in cut buffer
+ *     [^W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_kill_region(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return CC_ERROR;
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delafter(el, (int)(cp - el->el_line.cursor));
+       } else {                /* mark is before cursor */
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+               c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark));
+               el->el_line.cursor = el->el_chared.c_kill.mark;
+       }
+       return CC_REFRESH;
+}
+
+
+/* em_copy_region():
+ *     Copy area between mark and cursor to cut buffer
+ *     [M-W]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_region(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *kp, *cp;
+
+       if (!el->el_chared.c_kill.mark)
+               return CC_ERROR;
+
+       if (el->el_chared.c_kill.mark > el->el_line.cursor) {
+               cp = el->el_line.cursor;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_chared.c_kill.mark)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       } else {
+               cp = el->el_chared.c_kill.mark;
+               kp = el->el_chared.c_kill.buf;
+               while (cp < el->el_line.cursor)
+                       *kp++ = *cp++;  /* copy it */
+               el->el_chared.c_kill.last = kp;
+       }
+       return CC_NORM;
+}
+
+
+/* em_gosmacs_transpose():
+ *     Exchange the two characters before the cursor
+ *     Gosling emacs transpose chars [^T]
+ */
+protected el_action_t
+em_gosmacs_transpose(EditLine *el, Int c)
+{
+
+       if (el->el_line.cursor > &el->el_line.buffer[1]) {
+               /* must have at least two chars entered */
+               c = el->el_line.cursor[-2];
+               el->el_line.cursor[-2] = el->el_line.cursor[-1];
+               el->el_line.cursor[-1] = c;
+               return CC_REFRESH;
+       } else
+               return CC_ERROR;
+}
+
+
+/* em_next_word():
+ *     Move next to end of current word
+ *     [M-f]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_next_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       if (el->el_line.cursor == el->el_line.lastchar)
+               return CC_ERROR;
+
+       el->el_line.cursor = c__next_word(el->el_line.cursor,
+           el->el_line.lastchar,
+           el->el_state.argument,
+           ce__isword);
+
+       if (el->el_map.type == MAP_VI)
+               if (el->el_chared.c_vcmd.action != NOP) {
+                       cv_delfini(el);
+                       return CC_REFRESH;
+               }
+       return CC_CURSOR;
+}
+
+
+/* em_upper_case():
+ *     Uppercase the characters from cursor to end of current word
+ *     [M-u]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_upper_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (Islower(*cp))
+                       *cp = Toupper(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_capitol_case():
+ *     Capitalize the characters from cursor to end of current word
+ *     [M-c]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_capitol_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++) {
+               if (Isalpha(*cp)) {
+                       if (Islower(*cp))
+                               *cp = Toupper(*cp);
+                       cp++;
+                       break;
+               }
+       }
+       for (; cp < ep; cp++)
+               if (Isupper(*cp))
+                       *cp = Tolower(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_lower_case():
+ *     Lowercase the characters from cursor to end of current word
+ *     [M-l]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_lower_case(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *ep;
+
+       ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
+           el->el_state.argument, ce__isword);
+
+       for (cp = el->el_line.cursor; cp < ep; cp++)
+               if (Isupper(*cp))
+                       *cp = Tolower(*cp);
+
+       el->el_line.cursor = ep;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+       return CC_REFRESH;
+}
+
+
+/* em_set_mark():
+ *     Set the mark at cursor
+ *     [^@]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_set_mark(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_chared.c_kill.mark = el->el_line.cursor;
+       return CC_NORM;
+}
+
+
+/* em_exchange_mark():
+ *     Exchange the cursor and mark
+ *     [^X^X]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_exchange_mark(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp;
+
+       cp = el->el_line.cursor;
+       el->el_line.cursor = el->el_chared.c_kill.mark;
+       el->el_chared.c_kill.mark = cp;
+       return CC_CURSOR;
+}
+
+
+/* em_universal_argument():
+ *     Universal argument (argument times 4)
+ *     [^U]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_universal_argument(EditLine *el, Int c __attribute__((__unused__)))
+{                              /* multiply current argument by 4 */
+
+       if (el->el_state.argument > 1000000)
+               return CC_ERROR;
+       el->el_state.doingarg = 1;
+       el->el_state.argument *= 4;
+       return CC_ARGHACK;
+}
+
+
+/* em_meta_next():
+ *     Add 8th bit to next character typed
+ *     [<ESC>]
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_meta_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_state.metanext = 1;
+       return CC_ARGHACK;
+}
+
+
+/* em_toggle_overwrite():
+ *     Switch from insert to overwrite mode or vice versa
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_toggle_overwrite(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ?
+           MODE_REPLACE : MODE_INSERT;
+       return CC_NORM;
+}
+
+
+/* em_copy_prev_word():
+ *     Copy current word to cursor
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_copy_prev_word(EditLine *el, Int c __attribute__((__unused__)))
+{
+       Char *cp, *oldc, *dp;
+
+       if (el->el_line.cursor == el->el_line.buffer)
+               return CC_ERROR;
+
+       oldc = el->el_line.cursor;
+       /* does a bounds check */
+       cp = c__prev_word(el->el_line.cursor, el->el_line.buffer,
+           el->el_state.argument, ce__isword);
+
+       c_insert(el, (int)(oldc - cp));
+       for (dp = oldc; cp < oldc && dp < el->el_line.lastchar; cp++)
+               *dp++ = *cp;
+
+       el->el_line.cursor = dp;/* put cursor at end */
+
+       return CC_REFRESH;
+}
+
+
+/* em_inc_search_next():
+ *     Emacs incremental next search
+ */
+protected el_action_t
+/*ARGSUSED*/
+em_inc_search_next(EditLine *el, Int c __attribute__((__unused__)))
+{
+
+       el->el_search.patlen = 0;
+       return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY);
+}
+
+
+/* em_inc_search_prev():
+ *     Emacs incremental reverse search
+ */
+protected el_action_t
+/*ARGSUSED*/
+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/contrib/libedit/src/fgetln.c b/contrib/libedit/src/fgetln.c
new file mode 100644 (file)
index 0000000..6c4f320
--- /dev/null
@@ -0,0 +1,107 @@
+/*     $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $        */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#if !HAVE_FGETLN
+#include "config.h"
+#include <stdlib.h>
+#ifndef HAVE_NBTOOL_CONFIG_H
+/* These headers are required, but included from nbtool_config.h */
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#endif
+
+char *
+fgetln(FILE *fp, size_t *len)
+{
+       static char *buf = NULL;
+       static size_t bufsiz = 0;
+       char *ptr;
+
+
+       if (buf == NULL) {
+               bufsiz = BUFSIZ;
+               if ((buf = malloc(bufsiz)) == NULL)
+                       return NULL;
+       }
+
+       if (fgets(buf, bufsiz, fp) == NULL)
+               return NULL;
+
+       *len = 0;
+       while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
+               size_t nbufsiz = bufsiz + BUFSIZ;
+               char *nbuf = realloc(buf, nbufsiz);
+
+               if (nbuf == NULL) {
+                       int oerrno = errno;
+                       free(buf);
+                       errno = oerrno;
+                       buf = NULL;
+                       return NULL;
+               } else
+                       buf = nbuf;
+
+               if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) {
+                       buf[bufsiz] = '\0';
+                       *len = strlen(buf);
+                       return buf;
+               }
+
+               *len = bufsiz;
+               bufsiz = nbufsiz;
+       }
+
+       *len = (ptr - buf) + 1;
+       return buf;
+}
+
+#endif
+
+#ifdef TEST
+int
+main(int argc, char *argv[])
+{
+       char *p;
+       size_t len;
+
+       while ((p = fgetln(stdin, &len)) != NULL) {
+               (void)printf("%zu %s", len, p);
+               free(p);
+       }
+       return 0;
+}
+#endif
diff --git a/contrib/libedit/src/filecomplete.c b/contrib/libedit/src/filecomplete.c
new file mode 100644 (file)
index 0000000..49f8005
--- /dev/null
@@ -0,0 +1,576 @@
+/*     $NetBSD: filecomplete.c,v 1.31 2011/09/16 16:13:16 plunky 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.
+ *
+ * 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.31 2011/09/16 16:13:16 plunky 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>
+#include <vis.h>
+
+#include "el.h"
+#include "fcns.h"              /* for EL_NUM_FCNS */
+#include "histedit.h"
+#include "filecomplete.h"
+
+static const 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)
+{
+#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
+       struct passwd pwres;
+       char pwbuf[1024];
+#endif
+       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);
+               if (temp == NULL)
+                       return NULL;
+       } else {
+               /* text until string after slash */
+               len = (size_t)(temp - txt + 1);
+               temp = el_malloc(len * sizeof(*temp));
+               if (temp == NULL)
+                       return NULL;
+               (void)strncpy(temp, txt + 1, len - 2);
+               temp[len - 2] = '\0';
+       }
+       if (temp[0] == 0) {
+#ifdef HAVE_GETPW_R_POSIX
+               if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
+                   &pass) != 0)
+                       pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+               pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf));
+#else
+               pass = getpwuid(getuid());
+#endif
+       } else {
+#ifdef HAVE_GETPW_R_POSIX
+               if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
+                       pass = NULL;
+#elif HAVE_GETPW_R_DRAFT
+               pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf));
+#else
+               pass = getpwnam(temp);
+#endif
+       }
+       el_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;
+
+       len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
+       temp = el_malloc(len * sizeof(*temp));
+       if (temp == NULL)
+               return NULL;
+       (void)snprintf(temp, len, "%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 = el_realloc(filename, (strlen(temp) + 1) *
+                           sizeof(*nptr));
+                       if (nptr == NULL) {
+                               el_free(filename);
+                               filename = NULL;
+                               return NULL;
+                       }
+                       filename = nptr;
+                       (void)strcpy(filename, temp);
+                       len = (size_t)(temp - text);    /* including last slash */
+
+                       nptr = el_realloc(dirname, (len + 1) *
+                           sizeof(*nptr));
+                       if (nptr == NULL) {
+                               el_free(dirname);
+                               dirname = NULL;
+                               return NULL;
+                       }
+                       dirname = nptr;
+                       (void)strncpy(dirname, text, len);
+                       dirname[len] = '\0';
+               } else {
+                       el_free(filename);
+                       if (*text == 0)
+                               filename = NULL;
+                       else {
+                               filename = strdup(text);
+                               if (filename == NULL)
+                                       return NULL;
+                       }
+                       el_free(dirname);
+                       dirname = NULL;
+               }
+
+               if (dir != NULL) {
+                       (void)closedir(dir);
+                       dir = NULL;
+               }
+
+               /* support for ``~user'' syntax */
+
+               el_free(dirpath);
+               dirpath = NULL;
+               if (dirname == NULL) {
+                       if ((dirname = strdup("")) == NULL)
+                               return NULL;
+                       dirpath = strdup("./");
+               } else 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]
+          /* Some dirents have d_namlen, but it is not portable. */
+                   && strlen(entry->d_name) >= filename_len
+                   && strncmp(entry->d_name, filename,
+                       filename_len) == 0)
+                       break;
+       }
+
+       if (entry) {            /* match found */
+
+       /* Some dirents have d_namlen, but it is not portable. */
+               len = strlen(entry->d_name);
+
+               len = strlen(dirname) + len + 1;
+               temp = el_malloc(len * sizeof(*temp));
+               if (temp == NULL)
+                       return NULL;
+               (void)snprintf(temp, len, "%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)
+               el_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 = el_realloc(match_list,
+                           match_list_len * sizeof(*nmatch_list));
+                       if (nmatch_list == NULL) {
+                               el_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 = el_malloc((max_equal + 1) * sizeof(*retstr));
+       if (retstr == NULL) {
+               el_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] = 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, 'num' is number of strings in 'matches',
+ * 'width' is maximum length of string in 'matches'.
+ *
+ * matches[0] is not one of the match strings, but it is counted in
+ * num, so the strings are matches[1] *through* matches[num-1].
+ */
+void
+fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
+{
+       size_t line, lines, col, cols, thisguy;
+       int screenwidth = el->el_terminal.t_size.h;
+
+       /* Ignore matches[0]. Avoid 1-based array logic below. */
+       matches++;
+       num--;
+
+       /*
+        * Find out how many entries can be put on one line; count
+        * with one space between strings the same way it's printed.
+        */
+       cols = (size_t)screenwidth / (width + 1);
+       if (cols == 0)
+               cols = 1;
+
+       /* how many lines of output, rounded up */
+       lines = (num + cols - 1) / cols;
+
+       /* Sort the items. */
+       qsort(matches, num, sizeof(char *), _fn_qsort_string_compare);
+
+       /*
+        * On the ith line print elements i, i+lines, i+lines*2, etc.
+        */
+       for (line = 0; line < lines; line++) {
+               for (col = 0; col < cols; col++) {
+                       thisguy = line + col * lines;
+                       if (thisguy >= num)
+                               break;
+                       (void)fprintf(el->el_outfile, "%s%-*s",
+                           col == 0 ? "" : " ", (int)width, matches[thisguy]);
+               }
+               (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 *), size_t query_items,
+       int *completion_type, int *over, int *point, int *end)
+{
+       const TYPE(LineInfo) *li;
+       Char *temp;
+        char **matches;
+       const Char *ctemp;
+       size_t len;
+       int what_to_do = '\t';
+       int retval = CC_NORM;
+
+       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 = FUN(el,line)(el);
+       ctemp = li->cursor;
+       while (ctemp > li->buffer
+           && !Strchr(word_break, ctemp[-1])
+           && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
+               ctemp--;
+
+       len = (size_t)(li->cursor - ctemp);
+       temp = el_malloc((len + 1) * sizeof(*temp));
+       (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 = (int)(li->cursor - li->buffer);
+       if (end != NULL)
+               *end = (int)(li->lastchar - li->buffer);
+
+       if (attempted_completion_function) {
+               int cur_off = (int)(li->cursor - li->buffer);
+               matches = (*attempted_completion_function)(
+                   ct_encode_string(temp, &el->el_scratch),
+                   cur_off - (int)len, cur_off);
+       } else
+               matches = 0;
+       if (!attempted_completion_function || 
+           (over != NULL && !*over && !matches))
+               matches = completion_matches(
+                   ct_encode_string(temp, &el->el_scratch), complet_func);
+
+       if (over != NULL)
+               *over = 0;
+
+       if (matches) {
+               int i;
+               size_t matches_num, maxlen, match_len, match_display=1;
+
+               retval = CC_REFRESH;
+               /*
+                * 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);
+                       FUN(el,insertstr)(el,
+                           ct_decode_string(matches[0], &el->el_scratch));
+               }
+
+               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.
+                        */
+                       FUN(el,insertstr)(el,
+                           ct_decode_string((*app_func)(matches[0]),
+                           &el->el_scratch));
+               } 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[1] through matches[i-1] are available */
+                       matches_num = (size_t)(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 %zu 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) {
+                               /*
+                                * Interface of this function requires the
+                                * strings be matches[1..num-1] for compat.
+                                * We have matches_num strings not counting
+                                * the prefix in matches[0], so we need to
+                                * add 1 to matches_num for the call.
+                                */
+                               fn_display_match_list(el, matches,
+                                   matches_num+1, 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++)
+                       el_free(matches[i]);
+               el_free(matches);
+               matches = NULL;
+       }
+       el_free(temp);
+       return retval;
+}
+
+/*
+ * 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, (size_t)100,
+           NULL, NULL, NULL, NULL);
+}
diff --git a/contrib/libedit/src/filecomplete.h b/contrib/libedit/src/filecomplete.h
new file mode 100644 (file)
index 0000000..971e6e0
--- /dev/null
@@ -0,0 +1,44 @@
+/*     $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 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.
+ *
+ * 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 *), size_t,
+    int *, int *, int *, int *);
+
+void fn_display_match_list(EditLine *, char **, size_t, size_t);
+char *fn_tilde_expand(const char *);
+char *fn_filename_completion_function(const char *, int);
+
+#endif
diff --git a/contrib/libedit/src/hist.c b/contrib/libedit/src/hist.c
new file mode 100644 (file)
index 0000000..77dbaab
--- /dev/null
@@ -0,0 +1,223 @@
+/*     $NetBSD: hist.c,v 1.20 2011/07/29 15:16:33 christos 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. 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.
+ */
+
+#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.20 2011/07/29 15:16:33 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: History access functions
+ */
+#include <stdlib.h>
+#include "el.h"
+
+/* hist_init():
+ *     Initialization function.
+ */
+protected int
+hist_init(EditLine *el)
+{
+
+       el->el_history.fun = NULL;
+       el->el_history.ref = NULL;
+       el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
+       el->el_history.sz  = EL_BUFSIZ;
+       if (el->el_history.buf == NULL)
+               return -1;
+       el->el_history.last = el->el_history.buf;
+       return 0;
+}
+
+
+/* hist_end():
+ *     clean up history;
+ */
+protected void
+hist_end(EditLine *el)
+{
+
+       el_free(el->el_history.buf);
+       el->el_history.buf = NULL;
+}
+
+
+/* hist_set():
+ *     Set new history interface
+ */
+protected int
+hist_set(EditLine *el, hist_fun_t fun, void *ptr)
+{
+
+       el->el_history.ref = ptr;
+       el->el_history.fun = fun;
+       return 0;
+}
+
+
+/* hist_get():
+ *     Get a history line and update it in the buffer.
+ *     eventno tells us the event to get.
+ */
+protected el_action_t
+hist_get(EditLine *el)
+{
+       const Char *hp;
+       int h;
+
+       if (el->el_history.eventno == 0) {      /* if really the current line */
+               (void) Strncpy(el->el_line.buffer, el->el_history.buf,
+                   el->el_history.sz);
+               el->el_line.lastchar = el->el_line.buffer +
+                   (el->el_history.last - el->el_history.buf);
+
+#ifdef KSHVI
+               if (el->el_map.type == MAP_VI)
+                       el->el_line.cursor = el->el_line.buffer;
+               else
+#endif /* KSHVI */
+                       el->el_line.cursor = el->el_line.lastchar;
+
+               return CC_REFRESH;
+       }
+       if (el->el_history.ref == NULL)
+               return CC_ERROR;
+
+       hp = HIST_FIRST(el);
+
+       if (hp == NULL)
+               return CC_ERROR;
+
+       for (h = 1; h < el->el_history.eventno; h++)
+               if ((hp = HIST_NEXT(el)) == NULL) {
+                       el->el_history.eventno = h;
+                       return CC_ERROR;
+               }
+       (void) Strncpy(el->el_line.buffer, hp,
+                       (size_t)(el->el_line.limit - el->el_line.buffer));
+       el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
+       el->el_line.lastchar = el->el_line.buffer + Strlen(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;
+       else
+#endif /* KSHVI */
+               el->el_line.cursor = el->el_line.lastchar;
+
+       return CC_REFRESH;
+}
+
+
+/* hist_command()
+ *     process a history command
+ */
+protected int
+hist_command(EditLine *el, int argc, const Char **argv)
+{
+       const Char *str;
+       int num;
+       TYPE(HistEvent) ev;
+
+       if (el->el_history.ref == NULL)
+               return -1;
+
+       if (argc == 1 || Strcmp(argv[1], STR("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, ct_encode_string(str, &el->el_scratch));
+               return 0;
+       }
+
+       if (argc != 3)
+               return -1;
+
+       num = (int)Strtol(argv[2], NULL, 0);
+
+       if (Strcmp(argv[1], STR("size")) == 0)
+               return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num);
+
+       if (Strcmp(argv[1], STR("unique")) == 0)
+               return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num);
+
+       return -1;
+}
+
+/* hist_enlargebuf()
+ *     Enlarge history buffer to specified value. Called from el_enlargebufs().
+ *     Return 0 for failure, 1 for success.
+ */
+protected int
+/*ARGSUSED*/
+hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
+{
+       Char *newbuf;
+
+       newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
+       if (!newbuf)
+               return 0;
+
+       (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf));
+
+       el->el_history.last = newbuf +
+                               (el->el_history.last - el->el_history.buf);
+       el->el_history.buf = newbuf;
+       el->el_history.sz  = newsz;
+
+       return 1;
+}
+
+#ifdef WIDECHAR
+protected wchar_t *
+hist_convert(EditLine *el, int fn, void *arg)
+{
+       HistEventW ev;
+       if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1)
+               return NULL;
+       return ct_decode_string((const char *)(const void *)ev.str,
+           &el->el_scratch);
+}
+#endif
diff --git a/contrib/libedit/src/hist.h b/contrib/libedit/src/hist.h
new file mode 100644 (file)
index 0000000..a63be49
--- /dev/null
@@ -0,0 +1,87 @@
+/*     $NetBSD: hist.h,v 1.13 2011/07/28 20:50:55 christos 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. 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.
+ *
+ *     @(#)hist.h      8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.hist.c: History functions
+ */
+#ifndef _h_el_hist
+#define        _h_el_hist
+
+#include "histedit.h"
+
+typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...);
+
+typedef struct el_history_t {
+       Char            *buf;           /* The history buffer           */
+       size_t          sz;             /* Size of history buffer       */
+       Char            *last;          /* The last character           */
+       int              eventno;       /* Event we are looking for     */
+       void *           ref;           /* Argument for history fcns    */
+       hist_fun_t       fun;           /* Event access                 */
+       TYPE(HistEvent)  ev;            /* Event cookie                 */
+} el_history_t;
+
+#define        HIST_FUN_INTERNAL(el, fn, arg)  \
+    ((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
+       fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
+#ifdef WIDECHAR
+#define HIST_FUN(el, fn, arg) \
+    (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \
+       HIST_FUN_INTERNAL(el, fn, arg))
+#else
+#define HIST_FUN(el, fn, arg) HIST_FUN_INTERNAL(el, fn, arg)
+#endif
+
+
+#define        HIST_NEXT(el)           HIST_FUN(el, H_NEXT, NULL)
+#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_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)
+
+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, void *);
+protected int          hist_command(EditLine *, int, const Char **);
+protected int          hist_enlargebuf(EditLine *, size_t, size_t);
+#ifdef WIDECHAR
+protected wchar_t      *hist_convert(EditLine *, int, void *);
+#endif
+
+#endif /* _h_el_hist */
diff --git a/contrib/libedit/src/histedit.h b/contrib/libedit/src/histedit.h
new file mode 100644 (file)
index 0000000..b066593
--- /dev/null
@@ -0,0 +1,319 @@
+/*     $NetBSD: histedit.h,v 1.48 2011/07/28 20:50:55 christos 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. 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.
+ *
+ *     @(#)histedit.h  8.2 (Berkeley) 1/3/94
+ */
+
+/*
+ * histedit.h: Line editor and history interface.
+ */
+#ifndef _HISTEDIT_H_
+#define        _HISTEDIT_H_
+
+#define        LIBEDIT_MAJOR 2
+#define        LIBEDIT_MINOR 11
+
+#include <stdint.h>
+
+#include <sys/types.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * ==== Editing ====
+ */
+
+typedef struct editline EditLine;
+
+/*
+ * For user-defined function interface
+ */
+typedef struct lineinfo {
+       const char      *buffer;
+       const char      *cursor;
+       const char      *lastchar;
+} LineInfo;
+
+/*
+ * EditLine editor function return codes.
+ * For user-defined function interface
+ */
+#define        CC_NORM         0
+#define        CC_NEWLINE      1
+#define        CC_EOF          2
+#define        CC_ARGHACK      3
+#define        CC_REFRESH      4
+#define        CC_CURSOR       5
+#define        CC_ERROR        6
+#define        CC_FATAL        7
+#define        CC_REDISPLAY    8
+#define        CC_REFRESH_BEEP 9
+
+/*
+ * Initialization, cleanup, and resetting
+ */
+EditLine       *el_init(const char *, FILE *, FILE *, FILE *);
+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 *);
+
+/*
+ * Beep!
+ */
+void            el_beep(EditLine *);
+
+/*
+ * High level function internals control
+ * Parses argc, argv array and executes builtin editline commands
+ */
+int             el_parse(EditLine *, int, const char **);
+
+/*
+ * Low level editline access functions
+ */
+int             el_set(EditLine *, int, ...);
+int             el_get(EditLine *, int, ...);
+unsigned char  _el_fn_complete(EditLine *, int);
+
+/*
+ * el_set/el_get parameters
+ *
+ * When using el_wset/el_wget (as opposed to el_set/el_get):
+ *   Char is wchar_t, otherwise it is char.
+ *   prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t .
+
+ * Prompt function prototypes are:
+ *   typedef char    *(*el_pfunct_t)  (EditLine *);
+ *   typedef wchar_t *(*el_wpfunct_t) (EditLine *);
+ *
+ * For operations that support set or set/get, the argument types listed are for
+ * the "set" operation. For "get", each listed type must be a pointer.
+ * E.g. EL_EDITMODE takes an int when set, but an int* when get.
+ * 
+ * Operations that only support "get" have the correct argument types listed.
+ */
+#define        EL_PROMPT       0       /* , prompt_func);                    set/get */
+#define        EL_TERMINAL     1       /* , const char *);                   set/get */
+#define        EL_EDITOR       2       /* , const Char *);                   set/get */
+#define        EL_SIGNAL       3       /* , int);                            set/get */
+#define        EL_BIND         4       /* , const Char *, ..., NULL);        set     */
+#define        EL_TELLTC       5       /* , const Char *, ..., NULL);        set     */
+#define        EL_SETTC        6       /* , const Char *, ..., NULL);        set     */
+#define        EL_ECHOTC       7       /* , const Char *, ..., NULL);        set     */
+#define        EL_SETTY        8       /* , const Char *, ..., NULL);        set     */
+#define        EL_ADDFN        9       /* , const Char *, const Char,        set     */
+                               /*   el_func_t);                              */
+#define        EL_HIST         10      /* , hist_fun_t, const void *);       set     */
+#define        EL_EDITMODE     11      /* , int);                            set/get */
+#define        EL_RPROMPT      12      /* , prompt_func);                    set/get */
+#define        EL_GETCFN       13      /* , el_rfunc_t);                     set/get */
+#define        EL_CLIENTDATA   14      /* , void *);                         set/get */
+#define        EL_UNBUFFERED   15      /* , int);                            set/get */
+#define        EL_PREP_TERM    16      /* , int);                            set     */
+#define        EL_GETTC        17      /* , const Char *, ..., NULL);            get */
+#define        EL_GETFP        18      /* , int, FILE **);                       get */
+#define        EL_SETFP        19      /* , int, FILE *);                    set     */
+#define        EL_REFRESH      20      /* , void);                           set     */
+#define        EL_PROMPT_ESC   21      /* , prompt_func, Char);              set/get */
+#define        EL_RPROMPT_ESC  22      /* , prompt_func, Char);              set/get */
+#define        EL_RESIZE       23      /* , el_zfunc_t, void *);             set     */
+
+#define        EL_BUILTIN_GETCFN       (NULL)
+
+/*
+ * Source named file or $PWD/.editrc or $HOME/.editrc
+ */
+int            el_source(EditLine *, const char *);
+
+/*
+ * Must be called when the terminal changes size; If EL_SIGNAL
+ * is set this is done automatically otherwise it is the responsibility
+ * of the application
+ */
+void            el_resize(EditLine *);
+
+/*
+ * User-defined function interface.
+ */
+const LineInfo *el_line(EditLine *);
+int             el_insertstr(EditLine *, const char *);
+void            el_deletestr(EditLine *, int);
+
+
+/*
+ * ==== History ====
+ */
+
+typedef struct history History;
+
+typedef struct HistEvent {
+       int              num;
+       const char      *str;
+} HistEvent;
+
+/*
+ * History access functions.
+ */
+History *      history_init(void);
+void           history_end(History *);
+
+int            history(History *, HistEvent *, int, ...);
+
+#define        H_FUNC           0      /* , UTSL               */
+#define        H_SETSIZE        1      /* , const int);        */
+#define        H_GETSIZE        2      /* , void);             */
+#define        H_FIRST          3      /* , void);             */
+#define        H_LAST           4      /* , void);             */
+#define        H_PREV           5      /* , void);             */
+#define        H_NEXT           6      /* , void);             */
+#define        H_CURR           8      /* , const int);        */
+#define        H_SET            7      /* , int);              */
+#define        H_ADD            9      /* , const wchar_t *);  */
+#define        H_ENTER         10      /* , const wchar_t *);  */
+#define        H_APPEND        11      /* , const wchar_t *);  */
+#define        H_END           12      /* , void);             */
+#define        H_NEXT_STR      13      /* , const wchar_t *);  */
+#define        H_PREV_STR      14      /* , const wchar_t *);  */
+#define        H_NEXT_EVENT    15      /* , const int);        */
+#define        H_PREV_EVENT    16      /* , const 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);              */
+#define        H_NEXT_EVDATA   23      /* , const int, histdata_t *);  */
+#define        H_DELDATA       24      /* , int, histdata_t *);*/
+#define        H_REPLACE       25      /* , const char *, histdata_t); */
+
+
+
+/*
+ * ==== 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 ***);
+
+/*
+ * Begin Wide Character Support
+ */
+#ifdef __linux__
+/* Apparently we need _GNU_SOURCE defined to get access to wcsdup on Linux */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#endif
+
+#include <wchar.h>
+#include <wctype.h>
+
+/*
+ * Wide character versions
+ */
+
+/*
+ * ==== Editing ====
+ */
+typedef struct lineinfow {
+       const wchar_t   *buffer;
+       const wchar_t   *cursor;
+       const wchar_t   *lastchar;
+} LineInfoW;
+
+const wchar_t  *el_wgets(EditLine *, int *);
+int             el_wgetc(EditLine *, wchar_t *);
+void            el_wpush(EditLine *, const wchar_t *);
+
+int             el_wparse(EditLine *, int, const wchar_t **);
+
+int             el_wset(EditLine *, int, ...);
+int             el_wget(EditLine *, int, ...);
+
+const LineInfoW        *el_wline(EditLine *);
+int             el_winsertstr(EditLine *, const wchar_t *);
+#define          el_wdeletestr  el_deletestr
+
+/*
+ * ==== History ====
+ */
+typedef struct histeventW {
+       int              num;
+       const wchar_t   *str;
+} HistEventW;
+
+typedef struct historyW HistoryW;
+
+HistoryW *     history_winit(void);
+void           history_wend(HistoryW *);
+
+int            history_w(HistoryW *, HistEventW *, int, ...);
+
+/*
+ * ==== Tokenization ====
+ */
+typedef struct tokenizerW TokenizerW;
+
+/* Wide character tokenizer support */
+TokenizerW     *tok_winit(const wchar_t *);
+void            tok_wend(TokenizerW *);
+void            tok_wreset(TokenizerW *);
+int             tok_wline(TokenizerW *, const LineInfoW *,
+                   int *, const wchar_t ***, int *, int *);
+int             tok_wstr(TokenizerW *, const wchar_t *,
+                   int *, const wchar_t ***);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HISTEDIT_H_ */
diff --git a/contrib/libedit/src/history.c b/contrib/libedit/src/history.c
new file mode 100644 (file)
index 0000000..c65d4ee
--- /dev/null
@@ -0,0 +1,1103 @@
+/*     $NetBSD: history.c,v 1.46 2011/11/18 20:39:18 christos 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. 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.
+ */
+
+#ifndef NARROWCHAR
+#include "config.h"
+#endif
+
+#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.46 2011/11/18 20:39:18 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * hist.c: TYPE(History) access functions
+ */
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <vis.h>
+#include <sys/stat.h>
+
+static const char hist_cookie[] = "_HiStOrY_V2_\n";
+
+#include "histedit.h"
+#include "chartype.h"
+
+typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
+typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
+typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
+typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int);
+
+struct TYPE(history) {
+       void *h_ref;            /* Argument for history fcns     */
+       int h_ent;              /* Last entry point for history  */
+       history_gfun_t h_first; /* Get the first element         */
+       history_gfun_t h_next;  /* Get the next element          */
+       history_gfun_t h_last;  /* Get the last element          */
+       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)
+#define        HLAST(h, ev)            (*(h)->h_last)((h)->h_ref, ev)
+#define        HCURR(h, ev)            (*(h)->h_curr)((h)->h_ref, ev)
+#define        HSET(h, ev, n)          (*(h)->h_set)((h)->h_ref, ev, n)
+#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(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
+private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
+private int history_set_fun(TYPE(History) *, TYPE(History) *);
+private int history_load(TYPE(History) *, const char *);
+private int history_save(TYPE(History) *, const char *);
+private int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
+private int history_next_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
+private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
+
+
+/***********************************************************************/
+
+/*
+ * Builtin- history implementation
+ */
+typedef struct hentry_t {
+       TYPE(HistEvent) ev;             /* What we return                */
+       void *data;             /* data                          */
+       struct hentry_t *next;  /* Next entry                    */
+       struct hentry_t *prev;  /* Previous entry                */
+} 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     */
+       int eventid;            /* For generation of unique event id     */
+       int flags;              /* TYPE(History) flags          */
+#define H_UNIQUE       1       /* Store only unique elements   */
+} history_t;
+
+private int history_def_next(void *, TYPE(HistEvent) *);
+private int history_def_first(void *, TYPE(HistEvent) *);
+private int history_def_prev(void *, TYPE(HistEvent) *);
+private int history_def_last(void *, TYPE(HistEvent) *);
+private int history_def_curr(void *, TYPE(HistEvent) *);
+private int history_def_set(void *, TYPE(HistEvent) *, const int);
+private void history_def_clear(void *, TYPE(HistEvent) *);
+private int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
+private int history_def_add(void *, TYPE(HistEvent) *, const Char *);
+private int history_def_del(void *, TYPE(HistEvent) *, const int);
+
+private int history_def_init(void **, TYPE(HistEvent) *, int);
+private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
+private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
+
+private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
+private int history_set_nth(void *, TYPE(HistEvent) *, int);
+
+#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)  {\
+                                   evp->num = code;\
+                                   evp->str = he_strerror(code);\
+                               }
+
+/* error messages */
+static const Char *const he_errlist[] = {
+       STR("OK"),
+       STR("unknown error"),
+       STR("malloc() failed"),
+       STR("first event not found"),
+       STR("last event not found"),
+       STR("empty list"),
+       STR("no next event"),
+       STR("no previous event"),
+       STR("current event is invalid"),
+       STR("event not found"),
+       STR("can't read history from file"),
+       STR("can't write history"),
+       STR("required parameter(s) not supplied"),
+       STR("history size negative"),
+       STR("function not allowed with other history-functions-set the default"),
+       STR("bad parameters")
+};
+/* error codes */
+#define        _HE_OK                   0
+#define        _HE_UNKNOWN              1
+#define        _HE_MALLOC_FAILED        2
+#define        _HE_FIRST_NOTFOUND       3
+#define        _HE_LAST_NOTFOUND        4
+#define        _HE_EMPTY_LIST           5
+#define        _HE_END_REACHED          6
+#define        _HE_START_REACHED        7
+#define        _HE_CURR_INVALID         8
+#define        _HE_NOT_FOUND            9
+#define        _HE_HIST_READ           10
+#define        _HE_HIST_WRITE          11
+#define        _HE_PARAM_MISSING       12
+#define        _HE_SIZE_NEGATIVE       13
+#define        _HE_NOT_ALLOWED         14
+#define        _HE_BAD_PARAM           15
+
+/* history_def_first():
+ *     Default function to return the first event in the history.
+ */
+private int
+history_def_first(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.next;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_FIRST_NOTFOUND);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_last():
+ *     Default function to return the last event in the history.
+ */
+private int
+history_def_last(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       h->cursor = h->list.prev;
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev, _HE_LAST_NOTFOUND);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_next():
+ *     Default function to return the next event in the history.
+ */
+private int
+history_def_next(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       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;
+}
+
+
+/* history_def_prev():
+ *     Default function to return the previous event in the history.
+ */
+private int
+history_def_prev(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor == &h->list) {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       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;
+}
+
+
+/* history_def_curr():
+ *     Default function to return the current event in the history.
+ */
+private int
+history_def_curr(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cursor != &h->list)
+               *ev = h->cursor->ev;
+       else {
+               he_seterrev(ev,
+                   (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST);
+               return -1;
+       }
+
+       return 0;
+}
+
+
+/* history_def_set():
+ *     Default function to set the current event in the history to the
+ *     given one.
+ */
+private int
+history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cur == 0) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+       if (h->cursor == &h->list || h->cursor->ev.num != n) {
+               for (h->cursor = h->list.next; h->cursor != &h->list;
+                   h->cursor = h->cursor->next)
+                       if (h->cursor->ev.num == n)
+                               break;
+       }
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_NOT_FOUND);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_set_nth():
+ *     Default function to set the current event in the history to the
+ *     n-th one.
+ */
+private int
+history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
+{
+       history_t *h = (history_t *) p;
+
+       if (h->cur == 0) {
+               he_seterrev(ev, _HE_EMPTY_LIST);
+               return -1;
+       }
+       for (h->cursor = h->list.prev; h->cursor != &h->list;
+           h->cursor = h->cursor->prev)
+               if (n-- <= 0)
+                       break;
+       if (h->cursor == &h->list) {
+               he_seterrev(ev, _HE_NOT_FOUND);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_def_add():
+ *     Append string to element
+ */
+private int
+history_def_add(void *p, TYPE(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(evp->str) + Strlen(str) + 1;
+       s = h_malloc(len * sizeof(*s));
+       if (s == NULL) {
+               he_seterrev(ev, _HE_MALLOC_FAILED);
+               return -1;
+       }
+       (void) Strncpy(s, h->cursor->ev.str, len);
+        s[len - 1] = '\0';
+       (void) Strncat(s, str, len - Strlen(s) - 1);
+       h_free(evp->str);
+       evp->str = s;
+       *ev = h->cursor->ev;
+       return 0;
+}
+
+
+private int
+history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
+    int num, void **data)
+{
+       if (history_set_nth(h, ev, num) != 0)
+               return -1;
+       /* magic value to skip delete (just set to n-th history) */
+       if (data == (void **)-1)
+               return 0;
+       ev->str = Strdup(h->cursor->ev.str);
+       ev->num = h->cursor->ev.num;
+       if (data)
+               *data = h->cursor->data;
+       history_def_delete(h, ev, h->cursor);
+       return 0;
+}
+
+
+/* history_def_del():
+ *     Delete element hp of the h list
+ */
+/* ARGSUSED */
+private int
+history_def_del(void *p, TYPE(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, 
+                  TYPE(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;
+               if (h->cursor == &h->list)
+                       h->cursor = hp->next;
+       }
+       hp->prev->next = hp->next;
+       hp->next->prev = hp->prev;
+       h_free(evp->str);
+       h_free(hp);
+       h->cur--;
+}
+
+
+/* history_def_insert():
+ *     Insert element with string str in the h list
+ */
+private int
+history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       hentry_t *c;
+
+       c = h_malloc(sizeof(*c));
+       if (c == NULL)
+               goto oomem;
+       if ((c->ev.str = h_strdup(str)) == NULL) {
+               h_free(c);
+               goto oomem;
+       }
+       c->data = NULL;
+       c->ev.num = ++h->eventid;
+       c->next = h->list.next;
+       c->prev = &h->list;
+       h->list.next->prev = c;
+       h->list.next = c;
+       h->cur++;
+       h->cursor = c;
+
+       *ev = c->ev;
+       return 0;
+oomem:
+       he_seterrev(ev, _HE_MALLOC_FAILED);
+       return -1;
+}
+
+
+/* history_def_enter():
+ *     Default function to enter an item in the history
+ */
+private int
+history_def_enter(void *p, TYPE(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 */
+
+       /*
+         * Always keep at least one entry.
+         * This way we don't have to check for the empty list.
+         */
+       while (h->cur > h->max && h->cur > 0)
+               history_def_delete(h, ev, h->list.prev);
+
+       return 1;
+}
+
+
+/* history_def_init():
+ *     Default history initialization function
+ */
+/* ARGSUSED */
+private int
+history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
+{
+       history_t *h = (history_t *) h_malloc(sizeof(*h));
+       if (h == NULL)
+               return -1;
+
+       if (n <= 0)
+               n = 0;
+       h->eventid = 0;
+       h->cur = 0;
+       h->max = n;
+       h->list.next = h->list.prev = &h->list;
+       h->list.ev.str = NULL;
+       h->list.ev.num = 0;
+       h->cursor = &h->list;
+       h->flags = 0;
+       *p = h;
+       return 0;
+}
+
+
+/* history_def_clear():
+ *     Default history cleanup function
+ */
+private void
+history_def_clear(void *p, TYPE(HistEvent) *ev)
+{
+       history_t *h = (history_t *) p;
+
+       while (h->list.prev != &h->list)
+               history_def_delete(h, ev, h->list.prev);
+       h->cursor = &h->list;
+       h->eventid = 0;
+       h->cur = 0;
+}
+
+
+
+
+/************************************************************************/
+
+/* history_init():
+ *     Initialization function.
+ */
+public TYPE(History) *
+FUN(history,init)(void)
+{
+       TYPE(HistEvent) ev;
+       TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h));
+       if (h == NULL)
+               return NULL;
+
+       if (history_def_init(&h->h_ref, &ev, 0) == -1) {
+               h_free(h);
+               return NULL;
+       }
+       h->h_ent = -1;
+       h->h_next = history_def_next;
+       h->h_first = history_def_first;
+       h->h_last = history_def_last;
+       h->h_prev = history_def_prev;
+       h->h_curr = history_def_curr;
+       h->h_set = history_def_set;
+       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;
+}
+
+
+/* history_end():
+ *     clean up history;
+ */
+public void
+FUN(history,end)(TYPE(History) *h)
+{
+       TYPE(HistEvent) ev;
+
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+       h_free(h->h_ref);
+       h_free(h);
+}
+
+
+
+/* history_setsize():
+ *     Set history number of events
+ */
+private int
+history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       if (num < 0) {
+               he_seterrev(ev, _HE_BAD_PARAM);
+               return -1;
+       }
+       history_def_setsize(h->h_ref, num);
+       return 0;
+}
+
+
+/* history_getsize():
+ *      Get number of events currently in history
+ */
+private int
+history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
+{
+       if (h->h_next != history_def_next) {
+               he_seterrev(ev, _HE_NOT_ALLOWED);
+               return -1;
+       }
+       ev->num = history_def_getsize(h->h_ref);
+       if (ev->num < -1) {
+               he_seterrev(ev, _HE_SIZE_NEGATIVE);
+               return -1;
+       }
+       return 0;
+}
+
+
+/* history_setunique():
+ *     Set if adjacent equal events should not be entered in history.
+ */
+private int
+history_setunique(TYPE(History) *h, TYPE(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(TYPE(History) *h, TYPE(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;
+}
+
+
+/* history_set_fun():
+ *     Set history functions
+ */
+private int
+history_set_fun(TYPE(History) *h, TYPE(History) *nh)
+{
+       TYPE(HistEvent) ev;
+
+       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_del == NULL || nh->h_ref == NULL) {
+               if (h->h_next != history_def_next) {
+                       if (history_def_init(&h->h_ref, &ev, 0) == -1)
+                               return -1;
+                       h->h_first = history_def_first;
+                       h->h_next = history_def_next;
+                       h->h_last = history_def_last;
+                       h->h_prev = history_def_prev;
+                       h->h_curr = history_def_curr;
+                       h->h_set = history_def_set;
+                       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;
+       }
+       if (h->h_next == history_def_next)
+               history_def_clear(h->h_ref, &ev);
+
+       h->h_ent = -1;
+       h->h_first = nh->h_first;
+       h->h_next = nh->h_next;
+       h->h_last = nh->h_last;
+       h->h_prev = nh->h_prev;
+       h->h_curr = nh->h_curr;
+       h->h_set = nh->h_set;
+       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;
+}
+
+
+/* history_load():
+ *     TYPE(History) load function
+ */
+private int
+history_load(TYPE(History) *h, const char *fname)
+{
+       FILE *fp;
+       char *line;
+       size_t sz, max_size;
+       char *ptr;
+       int i = -1;
+       TYPE(HistEvent) ev;
+#ifdef WIDECHAR
+       static ct_buffer_t conv;
+#endif
+
+       if ((fp = fopen(fname, "r")) == NULL)
+               return i;
+
+       if ((line = fgetln(fp, &sz)) == NULL)
+               goto done;
+
+       if (strncmp(line, hist_cookie, sz) != 0)
+               goto done;
+
+       ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
+       if (ptr == NULL)
+               goto done;
+       for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) {
+               char c = line[sz];
+
+               if (sz != 0 && line[sz - 1] == '\n')
+                       line[--sz] = '\0';
+               else
+                       line[sz] = '\0';
+
+               if (max_size < sz) {
+                       char *nptr;
+                       max_size = (sz + 1024) & (size_t)~1023;
+                       nptr = h_realloc(ptr, max_size * sizeof(*ptr));
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strunvis(ptr, line);
+               line[sz] = c;
+               if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
+                       i = -1;
+                       goto oomem;
+               }
+       }
+oomem:
+       h_free(ptr);
+done:
+       (void) fclose(fp);
+       return i;
+}
+
+
+/* history_save():
+ *     TYPE(History) save function
+ */
+private int
+history_save(TYPE(History) *h, const char *fname)
+{
+       FILE *fp;
+       TYPE(HistEvent) ev;
+       int i = -1, retval;
+       size_t len, max_size;
+       char *ptr;
+       const char *str;
+#ifdef WIDECHAR
+       static ct_buffer_t conv;
+#endif
+
+       if ((fp = fopen(fname, "w")) == NULL)
+               return -1;
+
+       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) * sizeof(*ptr));
+       if (ptr == NULL)
+               goto done;
+       for (i = 0, retval = HLAST(h, &ev);
+           retval != -1;
+           retval = HPREV(h, &ev), i++) {
+               str = ct_encode_string(ev.str, &conv);
+               len = strlen(str) * 4;
+               if (len >= max_size) {
+                       char *nptr;
+                       max_size = (len + 1024) & (size_t)~1023;
+                       nptr = h_realloc(ptr, max_size * sizeof(*ptr));
+                       if (nptr == NULL) {
+                               i = -1;
+                               goto oomem;
+                       }
+                       ptr = nptr;
+               }
+               (void) strvis(ptr, str, VIS_WHITE);
+               (void) fprintf(fp, "%s\n", ptr);
+       }
+oomem:
+       h_free(ptr);
+done:
+       (void) fclose(fp);
+       return i;
+}
+
+
+/* history_prev_event():
+ *     Find the previous event, with number given
+ */
+private int
+history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (ev->num == num)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+private int
+history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (ev->num == num) {
+                       if (d)
+                               *d = ((history_t *)h->h_ref)->cursor->data;
+                       return 0;
+               }
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_next_event():
+ *     Find the next event, with number given
+ */
+private int
+history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
+{
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (ev->num == num)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_prev_string():
+ *     Find the previous event beginning with string
+ */
+private int
+history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       size_t len = Strlen(str);
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev))
+               if (Strncmp(str, ev->str, len) == 0)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history_next_string():
+ *     Find the next event beginning with string
+ */
+private int
+history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
+{
+       size_t len = Strlen(str);
+       int retval;
+
+       for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev))
+               if (Strncmp(str, ev->str, len) == 0)
+                       return 0;
+
+       he_seterrev(ev, _HE_NOT_FOUND);
+       return -1;
+}
+
+
+/* history():
+ *     User interface to history functions.
+ */
+int
+FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
+{
+       va_list va;
+       const Char *str;
+       int retval;
+
+       va_start(va, fun);
+
+       he_seterrev(ev, _HE_OK);
+
+       switch (fun) {
+       case H_GETSIZE:
+               retval = history_getsize(h, ev);
+               break;
+
+       case H_SETSIZE:
+               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)
+                       h->h_ent = ev->num;
+               break;
+
+       case H_APPEND:
+               str = va_arg(va, const Char *);
+               if ((retval = HSET(h, ev, h->h_ent)) != -1)
+                       retval = HADD(h, ev, str);
+               break;
+
+       case H_FIRST:
+               retval = HFIRST(h, ev);
+               break;
+
+       case H_NEXT:
+               retval = HNEXT(h, ev);
+               break;
+
+       case H_LAST:
+               retval = HLAST(h, ev);
+               break;
+
+       case H_PREV:
+               retval = HPREV(h, ev);
+               break;
+
+       case H_CURR:
+               retval = HCURR(h, ev);
+               break;
+
+       case H_SET:
+               retval = HSET(h, ev, va_arg(va, const int));
+               break;
+
+       case H_CLEAR:
+               HCLEAR(h, ev);
+               retval = 0;
+               break;
+
+       case H_LOAD:
+               retval = history_load(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_READ);
+               break;
+
+       case H_SAVE:
+               retval = history_save(h, va_arg(va, const char *));
+               if (retval == -1)
+                       he_seterrev(ev, _HE_HIST_WRITE);
+               break;
+
+       case H_PREV_EVENT:
+               retval = history_prev_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_NEXT_EVENT:
+               retval = history_next_event(h, ev, va_arg(va, int));
+               break;
+
+       case H_PREV_STR:
+               retval = history_prev_string(h, ev, va_arg(va, const Char *));
+               break;
+
+       case H_NEXT_STR:
+               retval = history_next_string(h, ev, va_arg(va, const Char *));
+               break;
+
+       case H_FUNC:
+       {
+               TYPE(History) hf;
+
+               hf.h_ref = va_arg(va, void *);
+               h->h_ent = -1;
+               hf.h_first = va_arg(va, history_gfun_t);
+               hf.h_next = va_arg(va, history_gfun_t);
+               hf.h_last = va_arg(va, history_gfun_t);
+               hf.h_prev = va_arg(va, history_gfun_t);
+               hf.h_curr = va_arg(va, history_gfun_t);
+               hf.h_set = va_arg(va, history_sfun_t);
+               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);
+               break;
+       }
+
+       case H_END:
+               FUN(history,end)(h);
+               retval = 0;
+               break;
+
+       case H_NEXT_EVDATA:
+       {
+               int num = va_arg(va, int);
+               void **d = va_arg(va, void **);
+               retval = history_next_evdata(h, ev, num, d);
+               break;
+       }
+
+       case H_DELDATA:
+       {
+               int num = va_arg(va, int);
+               void **d = va_arg(va, void **);
+               retval = history_deldata_nth((history_t *)h->h_ref, ev, num, d);
+               break;
+       }
+
+       case H_REPLACE: /* only use after H_NEXT_EVDATA */
+       {
+               const Char *line = va_arg(va, const Char *);
+               void *d = va_arg(va, void *);
+               const Char *s;
+               if(!line || !(s = Strdup(line))) {
+                       retval = -1;
+                       break;
+               }
+               ((history_t *)h->h_ref)->cursor->ev.str = s;
+               ((history_t *)h->h_ref)->cursor->data = d;
+               retval = 0;
+               break;
+       }
+
+       default:
+               retval = -1;
+               he_seterrev(ev, _HE_UNKNOWN);
+               break;
+       }
+       va_end(va);
+       return retval;
+}
diff --git a/contrib/libedit/src/keymacro.c b/contrib/libedit/src/keymacro.c
new file mode 100644 (file)
index 0000000..1cab508
--- /dev/null
@@ -0,0 +1,671 @@
+/*     $NetBSD: keymacro.c,v 1.7 2011/08/16 16:25:15 christos 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. 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.
+ */
+
+#include "config.h"
+#if !defined(lint) && !defined(SCCSID)
+#if 0
+static char sccsid[] = "@(#)key.c      8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: keymacro.c,v 1.7 2011/08/16 16:25:15 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * keymacro.c: This module contains the procedures for maintaining
+ *            the extended-key map.
+ *
+ *      An extended-key (key) is a sequence of keystrokes introduced
+ *     with a sequence introducer and consisting of an arbitrary
+ *     number of characters.  This module maintains a map (the
+ *     el->el_keymacro.map)
+ *     to convert these extended-key sequences into input strs
+ *     (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
+ *
+ *      Warning:
+ *       If key is a substr of some other keys, then the longer
+ *       keys are lost!!  That is, if the keys "abcd" and "abcef"
+ *       are in el->el_keymacro.map, adding the key "abc" will cause
+ *       the first two definitions to be lost.
+ *
+ *      Restrictions:
+ *      -------------
+ *      1) It is not possible to have one key that is a
+ *        substr of another.
+ */
+#include <string.h>
+#include <stdlib.h>
+
+#include "el.h"
+
+/*
+ * The Nodes of the el->el_keymacro.map.  The el->el_keymacro.map is a
+ * linked list of these node elements
+ */
+struct keymacro_node_t {
+       Char             ch;            /* single character of key       */
+       int              type;          /* node type                     */
+       keymacro_value_t val;           /* command code or pointer to str,  */
+                                       /* if this is a leaf             */
+       struct keymacro_node_t *next;   /* ptr to next char of this key  */
+       struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/
+};
+
+private int             node_trav(EditLine *, keymacro_node_t *, Char *,
+    keymacro_value_t *);
+private int             node__try(EditLine *, keymacro_node_t *, const Char *,
+    keymacro_value_t *, int);
+private keymacro_node_t        *node__get(Int);
+private void            node__free(keymacro_node_t *);
+private void            node__put(EditLine *, keymacro_node_t *);
+private int             node__delete(EditLine *, keymacro_node_t **,
+    const Char *);
+private int             node_lookup(EditLine *, const Char *,
+    keymacro_node_t *, size_t);
+private int             node_enum(EditLine *, keymacro_node_t *, size_t);
+
+#define        KEY_BUFSIZ      EL_BUFSIZ
+
+
+/* keymacro_init():
+ *     Initialize the key maps
+ */
+protected int
+keymacro_init(EditLine *el)
+{
+
+       el->el_keymacro.buf = el_malloc(KEY_BUFSIZ *
+           sizeof(*el->el_keymacro.buf));
+       if (el->el_keymacro.buf == NULL)
+               return -1;
+       el->el_keymacro.map = NULL;
+       keymacro_reset(el);
+       return 0;
+}
+
+/* keymacro_end():
+ *     Free the key maps
+ */
+protected void
+keymacro_end(EditLine *el)
+{
+
+       el_free(el->el_keymacro.buf);
+       el->el_keymacro.buf = NULL;
+       node__free(el->el_keymacro.map);
+}
+
+
+/* keymacro_map_cmd():
+ *     Associate cmd with a key value
+ */
+protected keymacro_value_t *
+keymacro_map_cmd(EditLine *el, int cmd)
+{
+
+       el->el_keymacro.val.cmd = (el_action_t) cmd;
+       return &el->el_keymacro.val;
+}
+
+
+/* keymacro_map_str():
+ *     Associate str with a key value
+ */
+protected keymacro_value_t *
+keymacro_map_str(EditLine *el, Char *str)
+{
+
+       el->el_keymacro.val.str = str;
+       return &el->el_keymacro.val;
+}
+
+
+/* keymacro_reset():
+ *     Takes all nodes on el->el_keymacro.map and puts them on free list.
+ *     Then initializes el->el_keymacro.map with arrow keys
+ *     [Always bind the ansi arrow keys?]
+ */
+protected void
+keymacro_reset(EditLine *el)
+{
+
+       node__put(el, el->el_keymacro.map);
+       el->el_keymacro.map = NULL;
+       return;
+}
+
+
+/* keymacro_get():
+ *     Calls the recursive function with entry point el->el_keymacro.map
+ *      Looks up *ch in map and then reads characters until a
+ *      complete match is found or a mismatch occurs. Returns the
+ *      type of the match found (XK_STR, XK_CMD, or XK_EXE).
+ *      Returns NULL in val.str and XK_STR for no match.
+ *      The last character read is returned in *ch.
+ */
+protected int
+keymacro_get(EditLine *el, Char *ch, keymacro_value_t *val)
+{
+
+       return node_trav(el, el->el_keymacro.map, ch, val);
+}
+
+
+/* keymacro_add():
+ *      Adds key to the el->el_keymacro.map and associates the value in
+ *     val with it. If key is already is in el->el_keymacro.map, the new
+ *     code is applied to the existing key. Ntype specifies if code is a
+ *     command, an out str or a unix command.
+ */
+protected void
+keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
+{
+
+       if (key[0] == '\0') {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_add: Null extended-key not allowed.\n");
+               return;
+       }
+       if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_add: sequence-lead-in command not allowed\n");
+               return;
+       }
+       if (el->el_keymacro.map == NULL)
+               /* tree is initially empty.  Set up new node to match key[0] */
+               el->el_keymacro.map = node__get(key[0]);
+                       /* it is properly initialized */
+
+       /* Now recurse through el->el_keymacro.map */
+       (void) node__try(el, el->el_keymacro.map, key, val, ntype);
+       return;
+}
+
+
+/* keymacro_clear():
+ *
+ */
+protected void
+keymacro_clear(EditLine *el, el_action_t *map, const Char *in)
+{
+#ifdef WIDECHAR
+        if (*in > N_KEYS) /* can't be in the map */
+                return;
+#endif
+       if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
+           ((map == el->el_map.key &&
+           el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) ||
+           (map == el->el_map.alt &&
+           el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN)))
+               (void) keymacro_delete(el, in);
+}
+
+
+/* keymacro_delete():
+ *      Delete the key and all longer keys staring with key, if
+ *      they exists.
+ */
+protected int
+keymacro_delete(EditLine *el, const Char *key)
+{
+
+       if (key[0] == '\0') {
+               (void) fprintf(el->el_errfile,
+                   "keymacro_delete: Null extended-key not allowed.\n");
+               return -1;
+       }
+       if (el->el_keymacro.map == NULL)
+               return 0;
+
+       (void) node__delete(el, &el->el_keymacro.map, key);
+       return 0;
+}
+
+
+/* keymacro_print():
+ *     Print the binding associated with key key.
+ *     Print entire el->el_keymacro.map if null
+ */
+protected void
+keymacro_print(EditLine *el, const Char *key)
+{
+
+       /* do nothing if el->el_keymacro.map is empty and null key specified */
+       if (el->el_keymacro.map == NULL && *key == 0)
+               return;
+
+       el->el_keymacro.buf[0] = '"';
+       if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1)
+               /* key is not bound */
+               (void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR
+                   "\"\n", key);
+       return;
+}
+
+
+/* node_trav():
+ *     recursively traverses node in tree until match or mismatch is
+ *     found.  May read in more characters.
+ */
+private int
+node_trav(EditLine *el, keymacro_node_t *ptr, Char *ch, keymacro_value_t *val)
+{
+
+       if (ptr->ch == *ch) {
+               /* match found */
+               if (ptr->next) {
+                       /* key not complete so get next char */
+                       if (FUN(el,getc)(el, ch) != 1) {/* if EOF or error */
+                               val->cmd = ED_END_OF_FILE;
+                               return XK_CMD;
+                               /* PWP: Pretend we just read an end-of-file */
+                       }
+                       return node_trav(el, ptr->next, ch, val);
+               } else {
+                       *val = ptr->val;
+                       if (ptr->type != XK_CMD)
+                               *ch = '\0';
+                       return ptr->type;
+               }
+       } else {
+               /* no match found here */
+               if (ptr->sibling) {
+                       /* try next sibling */
+                       return node_trav(el, ptr->sibling, ch, val);
+               } else {
+                       /* no next sibling -- mismatch */
+                       val->str = NULL;
+                       return XK_STR;
+               }
+       }
+}
+
+
+/* node__try():
+ *     Find a node that matches *str or allocate a new one
+ */
+private int
+node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
+    keymacro_value_t *val, int ntype)
+{
+
+       if (ptr->ch != *str) {
+               keymacro_node_t *xm;
+
+               for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+                       if (xm->sibling->ch == *str)
+                               break;
+               if (xm->sibling == NULL)
+                       xm->sibling = node__get(*str);  /* setup new node */
+               ptr = xm->sibling;
+       }
+       if (*++str == '\0') {
+               /* we're there */
+               if (ptr->next != NULL) {
+                       node__put(el, ptr->next);
+                               /* lose longer keys with this prefix */
+                       ptr->next = NULL;
+               }
+               switch (ptr->type) {
+               case XK_CMD:
+               case XK_NOD:
+                       break;
+               case XK_STR:
+               case XK_EXE:
+                       if (ptr->val.str)
+                               el_free(ptr->val.str);
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n",
+                           ptr->type));
+                       break;
+               }
+
+               switch (ptr->type = ntype) {
+               case XK_CMD:
+                       ptr->val = *val;
+                       break;
+               case XK_STR:
+               case XK_EXE:
+                       if ((ptr->val.str = Strdup(val->str)) == NULL)
+                               return -1;
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+                       break;
+               }
+       } else {
+               /* still more chars to go */
+               if (ptr->next == NULL)
+                       ptr->next = node__get(*str);    /* setup new node */
+               (void) node__try(el, ptr->next, str, val, ntype);
+       }
+       return 0;
+}
+
+
+/* node__delete():
+ *     Delete node that matches str
+ */
+private int
+node__delete(EditLine *el, keymacro_node_t **inptr, const Char *str)
+{
+       keymacro_node_t *ptr;
+       keymacro_node_t *prev_ptr = NULL;
+
+       ptr = *inptr;
+
+       if (ptr->ch != *str) {
+               keymacro_node_t *xm;
+
+               for (xm = ptr; xm->sibling != NULL; xm = xm->sibling)
+                       if (xm->sibling->ch == *str)
+                               break;
+               if (xm->sibling == NULL)
+                       return 0;
+               prev_ptr = xm;
+               ptr = xm->sibling;
+       }
+       if (*++str == '\0') {
+               /* we're there */
+               if (prev_ptr == NULL)
+                       *inptr = ptr->sibling;
+               else
+                       prev_ptr->sibling = ptr->sibling;
+               ptr->sibling = NULL;
+               node__put(el, ptr);
+               return 1;
+       } else if (ptr->next != NULL &&
+           node__delete(el, &ptr->next, str) == 1) {
+               if (ptr->next != NULL)
+                       return 0;
+               if (prev_ptr == NULL)
+                       *inptr = ptr->sibling;
+               else
+                       prev_ptr->sibling = ptr->sibling;
+               ptr->sibling = NULL;
+               node__put(el, ptr);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
+
+/* node__put():
+ *     Puts a tree of nodes onto free list using free(3).
+ */
+private void
+node__put(EditLine *el, keymacro_node_t *ptr)
+{
+       if (ptr == NULL)
+               return;
+
+       if (ptr->next != NULL) {
+               node__put(el, ptr->next);
+               ptr->next = NULL;
+       }
+       node__put(el, ptr->sibling);
+
+       switch (ptr->type) {
+       case XK_CMD:
+       case XK_NOD:
+               break;
+       case XK_EXE:
+       case XK_STR:
+               if (ptr->val.str != NULL)
+                       el_free(ptr->val.str);
+               break;
+       default:
+               EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type));
+               break;
+       }
+       el_free(ptr);
+}
+
+
+/* node__get():
+ *     Returns pointer to a keymacro_node_t for ch.
+ */
+private keymacro_node_t *
+node__get(Int ch)
+{
+       keymacro_node_t *ptr;
+
+       ptr = el_malloc(sizeof(*ptr));
+       if (ptr == NULL)
+               return NULL;
+       ptr->ch = ch;
+       ptr->type = XK_NOD;
+       ptr->val.str = NULL;
+       ptr->next = NULL;
+       ptr->sibling = NULL;
+       return ptr;
+}
+
+private void
+node__free(keymacro_node_t *k)
+{
+       if (k == NULL)
+               return;
+       node__free(k->sibling);
+       node__free(k->next);
+       el_free(k);
+}
+
+/* node_lookup():
+ *     look for the str starting at node ptr.
+ *     Print if last node
+ */
+private int
+node_lookup(EditLine *el, const Char *str, keymacro_node_t *ptr, size_t cnt)
+{
+       ssize_t used;
+
+       if (ptr == NULL)
+               return -1;      /* cannot have null ptr */
+
+       if (!str || *str == 0) {
+               /* no more chars in str.  node_enum from here. */
+               (void) node_enum(el, ptr, cnt);
+               return 0;
+       } else {
+               /* If match put this char into el->el_keymacro.buf.  Recurse */
+               if (ptr->ch == *str) {
+                       /* match found */
+                       used = ct_visual_char(el->el_keymacro.buf + cnt,
+                           KEY_BUFSIZ - cnt, ptr->ch);
+                       if (used == -1)
+                               return -1; /* ran out of buffer space */
+                       if (ptr->next != NULL)
+                               /* not yet at leaf */
+                               return (node_lookup(el, str + 1, ptr->next,
+                                   (size_t)used + cnt));
+                       else {
+                           /* next node is null so key should be complete */
+                               if (str[1] == 0) {
+                                       size_t px = cnt + (size_t)used;
+                                       el->el_keymacro.buf[px] = '"';
+                                       el->el_keymacro.buf[px + 1] = '\0';
+                                       keymacro_kprint(el, el->el_keymacro.buf,
+                                           &ptr->val, ptr->type);
+                                       return 0;
+                               } else
+                                       return -1;
+                                       /* mismatch -- str still has chars */
+                       }
+               } else {
+                       /* no match found try sibling */
+                       if (ptr->sibling)
+                               return (node_lookup(el, str, ptr->sibling,
+                                   cnt));
+                       else
+                               return -1;
+               }
+       }
+}
+
+
+/* node_enum():
+ *     Traverse the node printing the characters it is bound in buffer
+ */
+private int
+node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt)
+{
+        ssize_t used;
+
+       if (cnt >= KEY_BUFSIZ - 5) {    /* buffer too small */
+               el->el_keymacro.buf[++cnt] = '"';
+               el->el_keymacro.buf[++cnt] = '\0';
+               (void) fprintf(el->el_errfile,
+                   "Some extended keys too long for internal print buffer");
+               (void) fprintf(el->el_errfile, " \"" FSTR "...\"\n",
+                   el->el_keymacro.buf);
+               return 0;
+       }
+       if (ptr == NULL) {
+#ifdef DEBUG_EDIT
+               (void) fprintf(el->el_errfile,
+                   "node_enum: BUG!! Null ptr passed\n!");
+#endif
+               return -1;
+       }
+       /* put this char at end of str */
+        used = ct_visual_char(el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt,
+           ptr->ch);
+       if (ptr->next == NULL) {
+               /* print this key and function */
+               el->el_keymacro.buf[cnt + (size_t)used   ] = '"';
+               el->el_keymacro.buf[cnt + (size_t)used + 1] = '\0';
+               keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type);
+       } else
+               (void) node_enum(el, ptr->next, cnt + (size_t)used);
+
+       /* go to sibling if there is one */
+       if (ptr->sibling)
+               (void) node_enum(el, ptr->sibling, cnt);
+       return 0;
+}
+
+
+/* keymacro_kprint():
+ *     Print the specified key and its associated
+ *     function specified by val
+ */
+protected void
+keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
+{
+       el_bindings_t *fp;
+       char unparsbuf[EL_BUFSIZ];
+       static const char fmt[] = "%-15s->  %s\n";
+
+       if (val != NULL)
+               switch (ntype) {
+               case XK_STR:
+               case XK_EXE:
+                       (void) keymacro__decode_str(val->str, unparsbuf,
+                           sizeof(unparsbuf), 
+                           ntype == XK_STR ? "\"\"" : "[]");
+                       (void) fprintf(el->el_outfile, fmt,
+                           ct_encode_string(key, &el->el_scratch), unparsbuf);
+                       break;
+               case XK_CMD:
+                       for (fp = el->el_map.help; fp->name; fp++)
+                               if (val->cmd == fp->func) {
+                    ct_wcstombs(unparsbuf, fp->name, sizeof(unparsbuf));
+                    unparsbuf[sizeof(unparsbuf) -1] = '\0';
+                                       (void) fprintf(el->el_outfile, fmt,
+                        ct_encode_string(key, &el->el_scratch), unparsbuf);
+                                       break;
+                               }
+#ifdef DEBUG_KEY
+                       if (fp->name == NULL)
+                               (void) fprintf(el->el_outfile,
+                                   "BUG! Command not found.\n");
+#endif
+
+                       break;
+               default:
+                       EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype));
+                       break;
+               }
+       else
+               (void) fprintf(el->el_outfile, fmt, ct_encode_string(key,
+                   &el->el_scratch), "no input");
+}
+
+
+#define ADDC(c) \
+       if (b < eb) \
+               *b++ = c; \
+       else \
+               b++
+/* keymacro__decode_str():
+ *     Make a printable version of the ey
+ */
+protected size_t
+keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep)
+{
+       char *b = buf, *eb = b + len;
+       const Char *p;
+
+       b = buf;
+       if (sep[0] != '\0') {
+               ADDC(sep[0]);
+       }
+       if (*str == '\0') {
+               ADDC('^');
+               ADDC('@');
+               goto add_endsep;
+       }
+       for (p = str; *p != 0; p++) {
+               Char dbuf[VISUAL_WIDTH_MAX];
+               Char *p2 = dbuf;
+               ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p);
+               while (l-- > 0) {
+                       ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++);
+                       if (n == -1) /* ran out of space */
+                               goto add_endsep;
+                       else
+                               b += n;
+               }
+       }
+add_endsep:
+       if (sep[0] != '\0' && sep[1] != '\0') {
+               ADDC(sep[1]);
+       }
+       ADDC('\0');
+       if ((size_t)(b - buf) >= len)
+           buf[len - 1] = '\0';
+       return (size_t)(b - buf);
+}
diff --git a/contrib/libedit/src/keymacro.h b/contrib/libedit/src/keymacro.h
new file mode 100644 (file)
index 0000000..2445de5
--- /dev/null
@@ -0,0 +1,76 @@
+/*     $NetBSD: keymacro.h,v 1.2 2011/07/28 03:44:36 christos 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. 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.
+ *
+ *     @(#)key.h       8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * el.keymacro.h: Key macro header
+ */
+#ifndef _h_el_keymacro
+#define        _h_el_keymacro
+
+typedef union keymacro_value_t {
+       el_action_t      cmd;   /* If it is a command the #     */
+       Char            *str;   /* If it is a string...         */
+} keymacro_value_t;
+
+typedef struct keymacro_node_t keymacro_node_t;
+
+typedef struct el_keymacromacro_t {
+       Char            *buf;   /* Key print buffer             */
+       keymacro_node_t *map;   /* Key map                      */
+       keymacro_value_t val;   /* Local conversion buffer      */
+} el_keymacro_t;
+
+#define        XK_CMD  0
+#define        XK_STR  1
+#define        XK_NOD  2
+#define        XK_EXE  3
+
+protected int keymacro_init(EditLine *);
+protected void keymacro_end(EditLine *);
+protected keymacro_value_t *keymacro_map_cmd(EditLine *, int);
+protected keymacro_value_t *keymacro_map_str(EditLine *, Char *);
+protected void keymacro_reset(EditLine *);
+protected int keymacro_get(EditLine *, Char *, keymacro_value_t *);
+protected void keymacro_add(EditLine *, const Char *, keymacro_value_t *, int);
+protected void keymacro_clear(EditLine *, el_action_t *, const Char *);
+protected int keymacro_delete(EditLine *, const Char *);
+protected void keymacro_print(EditLine *, const Char *);
+protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *,
+    int);
+protected size_t keymacro__decode_str(const Char *, char *, size_t,
+    const char *);
+
+#endif /* _h_el_keymacro */
diff --git a/contrib/libedit/src/makelist b/contrib/libedit/src/makelist
new file mode 100644 (file)
index 0000000..7ba5a30
--- /dev/null
@@ -0,0 +1,258 @@
+#!/bin/sh -
+#      $NetBSD: makelist,v 1.17 2011/07/28 00:43:53 christos 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. 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.
+#
+#      @(#)makelist    5.3 (Berkeley) 6/4/93
+
+# makelist.sh: Automatically generate header files...
+
+USAGE="Usage: $0 -n|-h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
+
+if [ "x$1" = "x" ]
+then
+    echo $USAGE 1>&2
+    exit 1
+fi
+
+FLAG="$1"
+shift
+
+FILES="$@"
+
+case $FLAG in
+
+#      generate foo.h file from foo.c
+#
+-n)
+    cat << _EOF
+#include "config.h"
+#undef WIDECHAR
+#define NARROWCHAR
+#include "${FILES}"
+_EOF
+    ;;
+    
+-h)
+    set - `echo $FILES | sed -e 's/\\./_/g'`
+    hdr="_h_`basename $1`"
+    cat $FILES | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef %s\n#define %s\n", "'$hdr'", "'$hdr'");
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+#
+# XXX: need a space between name and prototype so that -fc and -fh
+#      parsing is much easier
+#
+               printf("protected el_action_t\t%s (EditLine *, Int);\n", name);
+           }
+       }
+       END {
+           printf("#endif /* %s */\n", "'$hdr'");
+       }'
+       ;;
+
+#      generate help.c from various .c files
+#
+-bc)
+    cat $FILES | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#include \"config.h\"\n#include \"el.h\"\n");
+           printf("#include \"chartype.h\"\n");
+           printf("private const struct el_bindings_t el_func_help[] = {\n");
+           low = "abcdefghijklmnopqrstuvwxyz_";
+           high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
+           for (i = 1; i <= length(low); i++)
+               tr[substr(low, i, 1)] = substr(high, i, 1);
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+               uname = "";
+               fname = "";
+               for (i = 1; i <= length(name); i++) {
+                   s = substr(name, i, 1);
+                   uname = uname tr[s];
+                   if (s == "_")
+                       s = "-";
+                   fname = fname s;
+               }
+
+               printf("    { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ",");
+               ok = 1;
+           }
+       }
+       /^ \*/ {
+           if (ok) {
+               printf("      STR(\"");
+               for (i = 2; i < NF; i++)
+                   printf("%s ", $i);
+               printf("%s\") },\n", $i);
+               ok = 0;
+           }
+       }
+       END {
+           printf("};\n");
+           printf("\nprotected const el_bindings_t* help__get()");
+           printf("{ return el_func_help; }\n");
+       }'
+       ;;
+
+#      generate help.h from various .c files
+#
+-bh)
+    $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef _h_help_c\n#define _h_help_c\n");
+           printf("protected const el_bindings_t *help__get(void);\n");
+           printf("#endif /* _h_help_c */\n");
+       }' /dev/null
+       ;;
+
+#      generate fcns.h from various .h files
+#
+-fh)
+    cat $FILES | $AWK '/el_action_t/ { print $3 }' | \
+    sort | tr '[a-z]' '[A-Z]' | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
+           count = 0;
+       }
+       {
+           printf("#define\t%-30.30s\t%3d\n", $1, count++);
+       }
+       END {
+           printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
+
+           printf("typedef el_action_t (*el_func_t)(EditLine *, Int);");
+           printf("\nprotected const el_func_t* func__get(void);\n");
+           printf("#endif /* _h_fcns_c */\n");
+       }'
+       ;;
+
+#      generate fcns.c from various .h files
+#
+-fc)
+    cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#include \"config.h\"\n#include \"el.h\"\n");
+           printf("private const el_func_t el_func[] = {");
+           maxlen = 80;
+           needn = 1;
+           len = 0;
+       }
+       {
+           clen = 25 + 2;
+           len += clen;
+           if (len >= maxlen)
+               needn = 1;
+           if (needn) {
+               printf("\n    ");
+               needn = 0;
+               len = 4 + clen;
+           }
+           s = $1 ",";
+           printf("%-26.26s ", s);
+       }
+       END {
+           printf("\n};\n");
+           printf("\nprotected const el_func_t* func__get() { return el_func; }\n");
+       }'
+       ;;
+
+#      generate editline.c from various .c files
+#
+-e)
+       echo "$FILES" | tr ' ' '\012' | $AWK '
+       BEGIN {
+           printf("/* Automatically generated file, do not edit */\n");
+           printf("#define protected static\n");
+           printf("#define SCCSID\n");
+       }
+       {
+           printf("#include \"%s\"\n", $1);
+       }'
+       ;;
+
+#      generate man page fragment from various .c files
+#
+-m)
+    cat $FILES | $AWK '
+       BEGIN {
+           printf(".\\\" Section automatically generated with makelist\n");
+           printf(".Bl -tag -width 4n\n");
+       }
+       /\(\):/ {
+           pr = substr($2, 1, 2);
+           if (pr == "vi" || pr == "em" || pr == "ed") {
+               name = substr($2, 1, length($2) - 3);
+               fname = "";
+               for (i = 1; i <= length(name); i++) {
+                   s = substr(name, i, 1);
+                   if (s == "_")
+                       s = "-";
+                   fname = fname s;
+               }
+
+               printf(".It Ic %s\n", fname);
+               ok = 1;
+           }
+       }
+       /^ \*/ {
+           if (ok) {
+               for (i = 2; i < NF; i++)
+                   printf("%s ", $i);
+               printf("%s.\n", $i);
+               ok = 0;
+           }
+       }
+       END {
+           printf(".El\n");
+           printf(".\\\" End of section automatically generated with makelist\n");
+       }'
+       ;;
+
+*)
+    echo $USAGE 1>&2
+    exit 1
+    ;;
+
+esac
diff --git a/contrib/libedit/src/map.c b/contrib/libedit/src/map.c
new file mode 100644 (file)
index 0000000..802c371
--- /dev/null
@@ -0,0 +1,1422 @@
+/*     $NetBSD: map.c,v 1.31 2011/11/18 20:39:18 christos 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. 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.
+ */
+
+#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.31 2011/11/18 20:39:18 christos Exp $");
+#endif
+#endif /* not lint && not SCCSID */
+
+/*
+ * map.c: Editor function definitions
+ */
+#include <stdlib.h>
+#include "el.h"
+
+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 *);
+private void   map_init_meta(EditLine *);
+
+/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */
+
+
+private const el_action_t  el_map_emacs[] = {
+       /*   0 */       EM_SET_MARK,            /* ^@ */
+       /*   1 */       ED_MOVE_TO_BEG,         /* ^A */
+       /*   2 */       ED_PREV_CHAR,           /* ^B */
+       /*   3 */       ED_TTY_SIGINT,          /* ^C */
+       /*   4 */       EM_DELETE_OR_LIST,      /* ^D */
+       /*   5 */       ED_MOVE_TO_END,         /* ^E */
+       /*   6 */       ED_NEXT_CHAR,           /* ^F */
+       /*   7 */       ED_UNASSIGNED,          /* ^G */
+       /*   8 */       EM_DELETE_PREV_CHAR,    /* ^H */
+       /*   9 */       ED_UNASSIGNED,          /* ^I */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_KILL_LINE,           /* ^K */
+       /*  12 */       ED_CLEAR_SCREEN,        /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_NEXT_HISTORY,        /* ^N */
+       /*  15 */       ED_TTY_FLUSH_OUTPUT,    /* ^O */
+       /*  16 */       ED_PREV_HISTORY,        /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_REDISPLAY,           /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_TRANSPOSE_CHARS,     /* ^T */
+       /*  21 */       EM_KILL_LINE,           /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       EM_KILL_REGION,         /* ^W */
+       /*  24 */       ED_SEQUENCE_LEAD_IN,    /* ^X */
+       /*  25 */       EM_YANK,                /* ^Y */
+       /*  26 */       ED_TTY_SIGTSTP,         /* ^Z */
+       /*  27 */       EM_META_NEXT,           /* ^[ */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_TTY_DSUSP,           /* ^] */
+       /*  30 */       ED_UNASSIGNED,          /* ^^ */
+       /*  31 */       ED_UNASSIGNED,          /* ^_ */
+       /*  32 */       ED_INSERT,              /* SPACE */
+       /*  33 */       ED_INSERT,              /* ! */
+       /*  34 */       ED_INSERT,              /* " */
+       /*  35 */       ED_INSERT,              /* # */
+       /*  36 */       ED_INSERT,              /* $ */
+       /*  37 */       ED_INSERT,              /* % */
+       /*  38 */       ED_INSERT,              /* & */
+       /*  39 */       ED_INSERT,              /* ' */
+       /*  40 */       ED_INSERT,              /* ( */
+       /*  41 */       ED_INSERT,              /* ) */
+       /*  42 */       ED_INSERT,              /* * */
+       /*  43 */       ED_INSERT,              /* + */
+       /*  44 */       ED_INSERT,              /* , */
+       /*  45 */       ED_INSERT,              /* - */
+       /*  46 */       ED_INSERT,              /* . */
+       /*  47 */       ED_INSERT,              /* / */
+       /*  48 */       ED_DIGIT,               /* 0 */
+       /*  49 */       ED_DIGIT,               /* 1 */
+       /*  50 */       ED_DIGIT,               /* 2 */
+       /*  51 */       ED_DIGIT,               /* 3 */
+       /*  52 */       ED_DIGIT,               /* 4 */
+       /*  53 */       ED_DIGIT,               /* 5 */
+       /*  54 */       ED_DIGIT,               /* 6 */
+       /*  55 */       ED_DIGIT,               /* 7 */
+       /*  56 */       ED_DIGIT,               /* 8 */
+       /*  57 */       ED_DIGIT,               /* 9 */
+       /*  58 */       ED_INSERT,              /* : */
+       /*  59 */       ED_INSERT,              /* ; */
+       /*  60 */       ED_INSERT,              /* < */
+       /*  61 */       ED_INSERT,              /* = */
+       /*  62 */       ED_INSERT,              /* > */
+       /*  63 */       ED_INSERT,              /* ? */
+       /*  64 */       ED_INSERT,              /* @ */
+       /*  65 */       ED_INSERT,              /* A */
+       /*  66 */       ED_INSERT,              /* B */
+       /*  67 */       ED_INSERT,              /* C */
+       /*  68 */       ED_INSERT,              /* D */
+       /*  69 */       ED_INSERT,              /* E */
+       /*  70 */       ED_INSERT,              /* F */
+       /*  71 */       ED_INSERT,              /* G */
+       /*  72 */       ED_INSERT,              /* H */
+       /*  73 */       ED_INSERT,              /* I */
+       /*  74 */       ED_INSERT,              /* J */
+       /*  75 */       ED_INSERT,              /* K */
+       /*  76 */       ED_INSERT,              /* L */
+       /*  77 */       ED_INSERT,              /* M */
+       /*  78 */       ED_INSERT,              /* N */
+       /*  79 */       ED_INSERT,              /* O */
+       /*  80 */       ED_INSERT,              /* P */
+       /*  81 */       ED_INSERT,              /* Q */
+       /*  82 */       ED_INSERT,              /* R */
+       /*  83 */       ED_INSERT,              /* S */
+       /*  84 */       ED_INSERT,              /* T */
+       /*  85 */       ED_INSERT,              /* U */
+       /*  86 */       ED_INSERT,              /* V */
+       /*  87 */       ED_INSERT,              /* W */
+       /*  88 */       ED_INSERT,              /* X */
+       /*  89 */       ED_INSERT,              /* Y */
+       /*  90 */       ED_INSERT,              /* Z */
+       /*  91 */       ED_INSERT,              /* [ */
+       /*  92 */       ED_INSERT,              /* \ */
+       /*  93 */       ED_INSERT,              /* ] */
+       /*  94 */       ED_INSERT,              /* ^ */
+       /*  95 */       ED_INSERT,              /* _ */
+       /*  96 */       ED_INSERT,              /* ` */
+       /*  97 */       ED_INSERT,              /* a */
+       /*  98 */       ED_INSERT,              /* b */
+       /*  99 */       ED_INSERT,              /* c */
+       /* 100 */       ED_INSERT,              /* d */
+       /* 101 */       ED_INSERT,              /* e */
+       /* 102 */       ED_INSERT,              /* f */
+       /* 103 */       ED_INSERT,              /* g */
+       /* 104 */       ED_INSERT,              /* h */
+       /* 105 */       ED_INSERT,              /* i */
+       /* 106 */       ED_INSERT,              /* j */
+       /* 107 */       ED_INSERT,              /* k */
+       /* 108 */       ED_INSERT,              /* l */
+       /* 109 */       ED_INSERT,              /* m */
+       /* 110 */       ED_INSERT,              /* n */
+       /* 111 */       ED_INSERT,              /* o */
+       /* 112 */       ED_INSERT,              /* p */
+       /* 113 */       ED_INSERT,              /* q */
+       /* 114 */       ED_INSERT,              /* r */
+       /* 115 */       ED_INSERT,              /* s */
+       /* 116 */       ED_INSERT,              /* t */
+       /* 117 */       ED_INSERT,              /* u */
+       /* 118 */       ED_INSERT,              /* v */
+       /* 119 */       ED_INSERT,              /* w */
+       /* 120 */       ED_INSERT,              /* x */
+       /* 121 */       ED_INSERT,              /* y */
+       /* 122 */       ED_INSERT,              /* z */
+       /* 123 */       ED_INSERT,              /* { */
+       /* 124 */       ED_INSERT,              /* | */
+       /* 125 */       ED_INSERT,              /* } */
+       /* 126 */       ED_INSERT,              /* ~ */
+       /* 127 */       EM_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_DELETE_PREV_WORD,    /* M-^H */
+       /* 137 */       ED_UNASSIGNED,          /* M-^I */
+       /* 138 */       ED_UNASSIGNED,          /* M-^J */
+       /* 139 */       ED_UNASSIGNED,          /* M-^K */
+       /* 140 */       ED_CLEAR_SCREEN,        /* 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 */       EM_COPY_PREV_WORD,      /* 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_ARGUMENT_DIGIT,      /* M-0 */
+       /* 177 */       ED_ARGUMENT_DIGIT,      /* M-1 */
+       /* 178 */       ED_ARGUMENT_DIGIT,      /* M-2 */
+       /* 179 */       ED_ARGUMENT_DIGIT,      /* M-3 */
+       /* 180 */       ED_ARGUMENT_DIGIT,      /* M-4 */
+       /* 181 */       ED_ARGUMENT_DIGIT,      /* M-5 */
+       /* 182 */       ED_ARGUMENT_DIGIT,      /* M-6 */
+       /* 183 */       ED_ARGUMENT_DIGIT,      /* M-7 */
+       /* 184 */       ED_ARGUMENT_DIGIT,      /* M-8 */
+       /* 185 */       ED_ARGUMENT_DIGIT,      /* 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_PREV_WORD,           /* M-B */
+       /* 195 */       EM_CAPITOL_CASE,        /* M-C */
+       /* 196 */       EM_DELETE_NEXT_WORD,    /* M-D */
+       /* 197 */       ED_UNASSIGNED,          /* M-E */
+       /* 198 */       EM_NEXT_WORD,           /* 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 */       EM_LOWER_CASE,          /* M-L */
+       /* 205 */       ED_UNASSIGNED,          /* M-M */
+       /* 206 */       ED_SEARCH_NEXT_HISTORY, /* M-N */
+       /* 207 */       ED_SEQUENCE_LEAD_IN,    /* M-O */
+       /* 208 */       ED_SEARCH_PREV_HISTORY, /* M-P */
+       /* 209 */       ED_UNASSIGNED,          /* M-Q */
+       /* 210 */       ED_UNASSIGNED,          /* M-R */
+       /* 211 */       ED_UNASSIGNED,          /* M-S */
+       /* 212 */       ED_UNASSIGNED,          /* M-T */
+       /* 213 */       EM_UPPER_CASE,          /* M-U */
+       /* 214 */       ED_UNASSIGNED,          /* M-V */
+       /* 215 */       EM_COPY_REGION,         /* M-W */
+       /* 216 */       ED_COMMAND,             /* M-X */
+       /* 217 */       ED_UNASSIGNED,          /* M-Y */
+       /* 218 */       ED_UNASSIGNED,          /* M-Z */
+       /* 219 */       ED_SEQUENCE_LEAD_IN,    /* M-[ */
+       /* 220 */       ED_UNASSIGNED,          /* M-\ */
+       /* 221 */       ED_UNASSIGNED,          /* M-] */
+       /* 222 */       ED_UNASSIGNED,          /* M-^ */
+       /* 223 */       ED_UNASSIGNED,          /* M-_ */
+       /* 223 */       ED_UNASSIGNED,          /* M-` */
+       /* 224 */       ED_UNASSIGNED,          /* M-a */
+       /* 225 */       ED_PREV_WORD,           /* M-b */
+       /* 226 */       EM_CAPITOL_CASE,        /* M-c */
+       /* 227 */       EM_DELETE_NEXT_WORD,    /* M-d */
+       /* 228 */       ED_UNASSIGNED,          /* M-e */
+       /* 229 */       EM_NEXT_WORD,           /* M-f */
+       /* 230 */       ED_UNASSIGNED,          /* M-g */
+       /* 231 */       ED_UNASSIGNED,          /* M-h */
+       /* 232 */       ED_UNASSIGNED,          /* M-i */
+       /* 233 */       ED_UNASSIGNED,          /* M-j */
+       /* 234 */       ED_UNASSIGNED,          /* M-k */
+       /* 235 */       EM_LOWER_CASE,          /* M-l */
+       /* 236 */       ED_UNASSIGNED,          /* M-m */
+       /* 237 */       ED_SEARCH_NEXT_HISTORY, /* M-n */
+       /* 238 */       ED_UNASSIGNED,          /* M-o */
+       /* 239 */       ED_SEARCH_PREV_HISTORY, /* M-p */
+       /* 240 */       ED_UNASSIGNED,          /* M-q */
+       /* 241 */       ED_UNASSIGNED,          /* M-r */
+       /* 242 */       ED_UNASSIGNED,          /* M-s */
+       /* 243 */       ED_UNASSIGNED,          /* M-t */
+       /* 244 */       EM_UPPER_CASE,          /* M-u */
+       /* 245 */       ED_UNASSIGNED,          /* M-v */
+       /* 246 */       EM_COPY_REGION,         /* M-w */
+       /* 247 */       ED_COMMAND,             /* M-x */
+       /* 248 */       ED_UNASSIGNED,          /* M-y */
+       /* 249 */       ED_UNASSIGNED,          /* M-z */
+       /* 250 */       ED_UNASSIGNED,          /* M-{ */
+       /* 251 */       ED_UNASSIGNED,          /* M-| */
+       /* 252 */       ED_UNASSIGNED,          /* M-} */
+       /* 253 */       ED_UNASSIGNED,          /* M-~ */
+       /* 254 */       ED_DELETE_PREV_WORD     /* M-^? */
+       /* 255 */
+};
+
+
+/*
+ * keymap table for vi.  Each index into above tbl; should be
+ * N_KEYS entries long.  Vi mode uses a sticky-extend to do command mode:
+ * insert mode characters are in the normal keymap, and command mode
+ * in the extended keymap.
+ */
+private const el_action_t  el_map_vi_insert[] = {
+#ifdef KSHVI
+       /*   0 */       ED_UNASSIGNED,          /* ^@ */
+       /*   1 */       ED_INSERT,              /* ^A */
+       /*   2 */       ED_INSERT,              /* ^B */
+       /*   3 */       ED_INSERT,              /* ^C */
+       /*   4 */       VI_LIST_OR_EOF,         /* ^D */
+       /*   5 */       ED_INSERT,              /* ^E */
+       /*   6 */       ED_INSERT,              /* ^F */
+       /*   7 */       ED_INSERT,              /* ^G */
+       /*   8 */       VI_DELETE_PREV_CHAR,    /* ^H */   /* BackSpace key */
+       /*   9 */       ED_INSERT,              /* ^I */   /* Tab Key  */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_INSERT,              /* ^K */
+       /*  12 */       ED_INSERT,              /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_INSERT,              /* ^N */
+       /*  15 */       ED_INSERT,              /* ^O */
+       /*  16 */       ED_INSERT,              /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_INSERT,              /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_INSERT,              /* ^T */
+       /*  21 */       VI_KILL_LINE_PREV,      /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       ED_DELETE_PREV_WORD,    /* ^W */
+               /* ED_DELETE_PREV_WORD: Only until strt edit pos */
+       /*  24 */       ED_INSERT,              /* ^X */
+       /*  25 */       ED_INSERT,              /* ^Y */
+       /*  26 */       ED_INSERT,              /* ^Z */
+       /*  27 */       VI_COMMAND_MODE,        /* ^[ */  /* [ Esc ] key */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_INSERT,              /* ^] */
+       /*  30 */       ED_INSERT,              /* ^^ */
+       /*  31 */       ED_INSERT,              /* ^_ */
+#else /* !KSHVI */
+                               /*
+                                * NOTE: These mappings do NOT Correspond well
+                                * to the KSH VI editing assignments.
+                                * On the other and they are convenient and
+                                * many people have have gotten used to them.
+                                */
+       /*   0 */       ED_UNASSIGNED,          /* ^@ */
+       /*   1 */       ED_MOVE_TO_BEG,         /* ^A */
+       /*   2 */       ED_PREV_CHAR,           /* ^B */
+       /*   3 */       ED_TTY_SIGINT,          /* ^C */
+       /*   4 */       VI_LIST_OR_EOF,         /* ^D */
+       /*   5 */       ED_MOVE_TO_END,         /* ^E */
+       /*   6 */       ED_NEXT_CHAR,           /* ^F */
+       /*   7 */       ED_UNASSIGNED,          /* ^G */
+       /*   8 */       VI_DELETE_PREV_CHAR,    /* ^H */   /* BackSpace key */
+       /*   9 */       ED_UNASSIGNED,          /* ^I */   /* Tab Key */
+       /*  10 */       ED_NEWLINE,             /* ^J */
+       /*  11 */       ED_KILL_LINE,           /* ^K */
+       /*  12 */       ED_CLEAR_SCREEN,        /* ^L */
+       /*  13 */       ED_NEWLINE,             /* ^M */
+       /*  14 */       ED_NEXT_HISTORY,        /* ^N */
+       /*  15 */       ED_TTY_FLUSH_OUTPUT,    /* ^O */
+       /*  16 */       ED_PREV_HISTORY,        /* ^P */
+       /*  17 */       ED_TTY_START_OUTPUT,    /* ^Q */
+       /*  18 */       ED_REDISPLAY,           /* ^R */
+       /*  19 */       ED_TTY_STOP_OUTPUT,     /* ^S */
+       /*  20 */       ED_TRANSPOSE_CHARS,     /* ^T */
+       /*  21 */       VI_KILL_LINE_PREV,      /* ^U */
+       /*  22 */       ED_QUOTED_INSERT,       /* ^V */
+       /*  23 */       ED_DELETE_PREV_WORD,    /* ^W */
+       /*  24 */       ED_UNASSIGNED,          /* ^X */
+       /*  25 */       ED_TTY_DSUSP,           /* ^Y */
+       /*  26 */       ED_TTY_SIGTSTP,         /* ^Z */
+       /*  27 */       VI_COMMAND_MODE,        /* ^[ */
+       /*  28 */       ED_TTY_SIGQUIT,         /* ^\ */
+       /*  29 */       ED_UNASSIGNED,          /* ^] */
+       /*  30 */       ED_UNASSIGNED,          /* ^^ */
+       /*  31 */       ED_UNASSIGNED,          /* ^_ */
+#endif  /* KSHVI */
+       /*  32 */       ED_INSERT,              /* SPACE */
+       /*  33 */       ED_INSERT,              /* ! */
+       /*  34 */       ED_INSERT,              /* " */
+       /*  35 */       ED_INSERT,              /* # */
+       /*  36 */       ED_INSERT,              /* $ */
+       /*  37 */       ED_INSERT,              /* % */
+       /*  38 */       ED_INSERT,              /* & */
+       /*  39 */       ED_INSERT,              /* ' */
+       /*  40 */       ED_INSERT,              /* ( */
+       /*  41 */       ED_INSERT,              /* ) */
+       /*  42 */       ED_INSERT,              /* * */
+       /*  43 */       ED_INSERT,              /* + */
+       /*  44 */       ED_INSERT,              /* , */
+       /*  45 */       ED_INSERT,              /* - */
+       /*  46 */       ED_INSERT,              /* . */
+       /*  47 */       ED_INSERT,              /* / */
+       /*  48 */       ED_INSERT,              /* 0 */
+       /*  49 */       ED_INSERT,              /* 1 */
+       /*  50 */       ED_INSERT,              /* 2 */
+       /*  51 */       ED_INSERT,              /* 3 */
+       /*  52 */       ED_INSERT,              /* 4 */
+       /*  53 */       ED_INSERT,              /* 5 */
+       /*  54 */       ED_INSERT,              /* 6 */
+       /*  55 */       ED_INSERT,              /* 7 */
+       /*  56 */       ED_INSERT,              /* 8 */
+       /*  57 */       ED_INSERT,              /* 9 */
+       /*  58 */       ED_INSERT,              /* : */
+       /*  59 */       ED_INSERT,              /* ; */
+       /*  60 */       ED_INSERT,              /* < */
+       /*  61 */       ED_INSERT,              /* = */
+       /*  62 */       ED_INSERT,              /* > */
+       /*  63 */       ED_INSERT,              /* ? */
+       /*  64 */       ED_INSERT,              /* @ */
+       /*  65 */       ED_INSERT,              /* A */
+       /*  66 */       ED_INSERT,              /* B */
+       /*  67 */       ED_INSERT,              /* C */
+       /*  68 */       ED_INSERT,              /* D */
+       /*  69 */       ED_INSERT,              /* E */
+       /*  70 */       ED_INSERT,              /* F */
+       /*  71 */       ED_INSERT,              /* G */
+       /*  72 */       ED_INSERT,              /* H */
+       /*  73 */       ED_INSERT,              /* I */
+       /*  74 */       ED_INSERT,              /* J */
+       /*  75 */       ED_INSERT,              /* K */
+       /*  76 */       ED_INSERT,              /* L */
+       /*  77 */       ED_INSERT,              /* M */
+       /*  78 */       ED_INSERT,              /* N */
+       /*  79 */       ED_INSERT,              /* O */
+       /*  80 */       ED_INSERT,              /* P */
+       /*  81 */       ED_INSERT,              /* Q */
+       /*  82 */       ED_INSERT,              /* R */
+       /*  83 */       ED_INSERT,              /* S */
+       /*  84 */       ED_INSERT,              /* T */
+       /*  85 */       ED_INSERT,              /* U */
+       /*  86 */       ED_INSERT,              /* V */
+       /*  87 */       ED_INSERT,              /* W */
+       /*  88 */       ED_INSERT,              /* X */
+       /*  89 */       ED_INSERT,              /* Y */
+       /*  90 */       ED_INSERT,              /* Z */
+       /*  91 */       ED_INSERT,              /* [ */
+       /*  92 */       ED_INSERT,              /* \ */
+       /*  93 */       ED_INSERT,              /* ] */
+       /*  94 */       ED_INSERT,              /* ^ */
+       /*  95 */       ED_INSERT,              /* _ */
+       /*  96 */       ED_INSERT,              /* ` */
+       /*  97 */       ED_INSERT,              /* a */
+       /*  98 */       ED_INSERT,              /* b */
+       /*  99 */       ED_INSERT,              /* c */
+       /* 100 */       ED_INSERT,              /* d */
+       /* 101 */       ED_INSERT,              /* e */
+       /* 102 */       ED_INSERT,              /* f */
+       /* 103 */       ED_INSERT,              /* g */
+       /* 104 */       ED_INSERT,              /* h */
+       /* 105 */       ED_INSERT,              /* i */
+       /* 106 */       ED_INSERT,              /* j */
+       /* 107 */       ED_INSERT,              /* k */
+       /* 108 */       ED_INSERT,              /* l */
+       /* 109 */       ED_INSERT,              /* m */
+       /* 110 */       ED_INSERT,              /* n */
+       /* 111 */       ED_INSERT,              /* o */
+       /* 112 */       ED_INSERT,              /* p */
+       /* 113 */       ED_INSERT,              /* q */
+       /* 114 */       ED_INSERT,              /* r */
+       /* 115 */       ED_INSERT,              /* s */
+       /* 116 */       ED_INSERT,              /* t */
+       /* 117 */       ED_INSERT,              /* u */
+       /* 118 */       ED_INSERT,              /* v */
+       /* 119 */       ED_INSERT,              /* w */
+       /* 120 */       ED_INSERT,              /* x */
+       /* 121 */       ED_INSERT,              /* y */
+       /* 122 */       ED_INSERT,              /* z */
+       /* 123 */       ED_INSERT,              /* { */
+       /* 124 */       ED_INSERT,              /* | */
+       /* 125 */       ED_INSERT,              /* } */
+       /* 126 */       ED_INSERT,              /* ~ */
+       /* 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-} */
+