Update libedit from version 2012-12-13 to 2014-06-20 on vendor branch
authorJohn Marino <draco@marino.st>
Mon, 13 Oct 2014 16:07:36 +0000 (18:07 +0200)
committerJohn Marino <draco@marino.st>
Mon, 13 Oct 2014 16:57:38 +0000 (18:57 +0200)
20 files changed:
contrib/libedit/src/chared.c
contrib/libedit/src/chared.h
contrib/libedit/src/editline/readline.h
contrib/libedit/src/el.c
contrib/libedit/src/eln.c
contrib/libedit/src/filecomplete.c
contrib/libedit/src/hist.h
contrib/libedit/src/histedit.h
contrib/libedit/src/history.c
contrib/libedit/src/map.c
contrib/libedit/src/read.c
contrib/libedit/src/readline.c
contrib/libedit/src/shlib_version
contrib/libedit/src/strlcat.c
contrib/libedit/src/tty.c
contrib/libedit/src/tty.h
contrib/libedit/src/unvis.c
contrib/libedit/src/vi.c
contrib/libedit/src/vis.c
contrib/libedit/src/vis.h

index fb75de8..3934a68 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $     */
+/*     $NetBSD: chared.c,v 1.40 2014/06/18 18:12:28 christos Exp $     */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)chared.c   8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: chared.c,v 1.37 2012/07/18 17:12:39 christos Exp $");
+__RCSID("$NetBSD: chared.c,v 1.40 2014/06/18 18:12:28 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -434,6 +434,8 @@ ch_init(EditLine *el)
        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_chared.c_aliasfun        = NULL;
+       el->el_chared.c_aliasarg        = NULL;
 
        el->el_map.current              = el->el_map.key;
 
@@ -644,6 +646,25 @@ el_deletestr(EditLine *el, int n)
                el->el_line.cursor = el->el_line.buffer;
 }
 
+/* el_cursor():
+ *     Move the cursor to the left or the right of the current position
+ */
+public int
+el_cursor(EditLine *el, int n)
+{
+       if (n == 0)
+               goto out;
+
+       el->el_line.cursor += n;
+
+       if (el->el_line.cursor < el->el_line.buffer)
+               el->el_line.cursor = el->el_line.buffer;
+       if (el->el_line.cursor > el->el_line.lastchar)
+               el->el_line.cursor = el->el_line.lastchar;
+out:
+       return (int)(el->el_line.cursor - el->el_line.buffer);
+}
+
 /* c_gets():
  *     Get a string
  */
@@ -738,3 +759,11 @@ ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
        el->el_chared.c_resizearg = a;
        return 0;
 }
+
+protected int
+ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
+{
+       el->el_chared.c_aliasfun = f;
+       el->el_chared.c_aliasarg = a;
+       return 0;
+}
index 176475a..6d6ef23 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: chared.h,v 1.21 2010/08/28 15:44:59 christos Exp $     */
+/*     $NetBSD: chared.h,v 1.22 2014/06/18 18:12:28 christos Exp $     */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -104,6 +104,7 @@ typedef struct c_kill_t {
 } c_kill_t;
 
 typedef void (*el_zfunc_t)(EditLine *, void *);
+typedef const char *(*el_afunc_t)(void *, const char *);
 
 /*
  * Note that we use both data structures because the user can bind
@@ -116,7 +117,9 @@ typedef struct el_chared_t {
        c_vcmd_t        c_vcmd;
        c_macro_t       c_macro;
        el_zfunc_t      c_resizefun;
+       el_afunc_t      c_aliasfun;
        void *          c_resizearg;
+       void *          c_aliasarg;
 } el_chared_t;
 
 
@@ -165,6 +168,7 @@ 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_aliasfun(EditLine *, el_afunc_t, void *);
 protected int   ch_enlargebufs(EditLine *, size_t);
 protected void  ch_end(EditLine *);
 
index 0d13713..932febb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: readline.h,v 1.33 2012/05/15 17:30:04 christos Exp $   */
+/*     $NetBSD: readline.h,v 1.34 2013/05/28 00:10:34 christos Exp $   */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -125,6 +125,8 @@ extern char         *rl_prompt;
 /*
  * The following is not implemented
  */
+extern int             rl_catch_signals;
+extern int             rl_catch_sigwinch;
 extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
                        emacs_meta_keymap,
                        emacs_ctlx_keymap;
index e4d2687..e3e3bc7 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: el.c,v 1.71 2012/09/11 11:58:53 christos Exp $ */
+/*     $NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $ */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)el.c       8.2 (Berkeley) 1/3/94";
 #else
-__RCSID("$NetBSD: el.c,v 1.71 2012/09/11 11:58:53 christos Exp $");
+__RCSID("$NetBSD: el.c,v 1.73 2014/06/18 18:12:28 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -58,11 +58,42 @@ __RCSID("$NetBSD: el.c,v 1.71 2012/09/11 11:58:53 christos Exp $");
 #include <langinfo.h>
 #include "el.h"
 
+#ifndef HAVE_SECURE_GETENV
+#      ifdef HAVE___SECURE_GETENV
+#              define secure_getenv __secure_getenv
+#              define HAVE_SECURE_GETENV 1
+#      else
+#              ifdef HAVE_ISSETUGID
+#                      include <unistd.h>
+#              else
+#                      undef issetugid
+#                      define issetugid() 1
+#              endif
+#      endif
+#endif
+
+#ifndef HAVE_SECURE_GETENV
+char *secure_getenv(char const *name)
+{
+       if (issetugid())
+               return 0;
+       return getenv(name);
+}
+#endif
+
 /* el_init():
  *     Initialize editline and set default parameters.
  */
 public EditLine *
 el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
+{
+    return el_init_fd(prog, fin, fout, ferr, fileno(fin), fileno(fout),
+       fileno(ferr));
+}
+
+public EditLine *
+el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
+    int fdin, int fdout, int fderr)
 {
        EditLine *el = el_malloc(sizeof(*el));
 
@@ -75,9 +106,9 @@ el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
        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_infd = fdin;
+       el->el_outfd = fdout;
+       el->el_errfd = fderr;
 
        el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
        if (el->el_prog == NULL) {
@@ -190,6 +221,13 @@ FUN(el,set)(EditLine *el, int op, ...)
                break;
        }
 
+       case EL_ALIAS_TEXT: {
+               el_afunc_t p = va_arg(ap, el_afunc_t);
+               void *arg = va_arg(ap, void *);
+               rv = ch_aliasfun(el, p, arg);
+               break;
+       }
+
        case EL_PROMPT_ESC:
        case EL_RPROMPT_ESC: {
                el_pfunc_t p = va_arg(ap, el_pfunc_t);
@@ -510,24 +548,13 @@ el_source(EditLine *el, const char *fname)
                static const char elpath[] = "/.editrc";
                size_t plen = sizeof(elpath);
 
-#ifdef HAVE_ISSETUGID
-               if (issetugid())
-                       return -1;
-               if ((ptr = getenv("HOME")) == NULL)
+               if ((ptr = secure_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");
index 1b829c2..5bcfb4f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $        */
+/*     $NetBSD: eln.c,v 1.17 2014/06/18 18:12:28 christos Exp $        */
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 #include "config.h"
 #if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: eln.c,v 1.14 2012/03/11 21:15:25 christos Exp $");
+__RCSID("$NetBSD: eln.c,v 1.17 2014/06/18 18:12:28 christos Exp $");
 #endif /* not lint && not SCCSID */
 
 #include "histedit.h"
@@ -125,6 +125,22 @@ el_set(EditLine *el, int op, ...)
                break;
        }
 
+       case EL_ALIAS_TEXT: {
+               el_afunc_t p = va_arg(ap, el_afunc_t);
+               void *arg = va_arg(ap, void *);
+               ret = ch_aliasfun(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);
+
+               ret = prompt_set(el, p, c, op, 0);
+               break;
+       }
+
        case EL_TERMINAL:       /* const char * */
                ret = el_wset(el, op, va_arg(ap, char *));
                break;
@@ -149,10 +165,10 @@ el_set(EditLine *el, int op, ...)
                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)
+               for (i = 1; i < (int)__arraycount(argv) - 1; ++i)
+                       if ((argv[i] = va_arg(ap, const char *)) == NULL)
                            break;
-               argv[0] = NULL;
+               argv[0] = argv[i] = NULL;
                wargv = (const wchar_t **)
                    ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
                if (!wargv) {
@@ -220,27 +236,31 @@ el_set(EditLine *el, int op, ...)
                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);
+
+       case EL_REFRESH:
+               re_clear_display(el);
+               re_refresh(el);
+               terminal__flush(el);
+               ret = 0;
                break;
-       }
+
        default:
                ret = -1;
                break;
index 49f8005..ab74a4b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: filecomplete.c,v 1.31 2011/09/16 16:13:16 plunky Exp $ */
+/*     $NetBSD: filecomplete.c,v 1.32 2014/06/05 22:07:42 christos Exp $       */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -32,7 +32,7 @@
 #include "config.h"
 
 #if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: filecomplete.c,v 1.31 2011/09/16 16:13:16 plunky Exp $");
+__RCSID("$NetBSD: filecomplete.c,v 1.32 2014/06/05 22:07:42 christos Exp $");
 #endif /* not lint && not SCCSID */
 
 #include <sys/types.h>
@@ -486,7 +486,8 @@ fn_complete(EditLine *el,
                if (what_to_do == '?')
                        goto display_matches;
 
-               if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) {
+               if (matches[2] == NULL &&
+                   (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0)) {
                        /*
                         * We found exact match. Add a space after
                         * it, unless we do filename completion and the
index a63be49..58e5876 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: hist.h,v 1.13 2011/07/28 20:50:55 christos Exp $       */
+/*     $NetBSD: hist.h,v 1.14 2014/05/11 01:05:17 christos Exp $       */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -73,6 +73,7 @@ typedef struct el_history_t {
 #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)
+#define        HIST_SAVE_FP(el, fp)    HIST_FUN(el, H_SAVE_FP fp)
 
 protected int          hist_init(EditLine *);
 protected void         hist_end(EditLine *);
index 61f9875..94f33ed 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: histedit.h,v 1.49 2012/05/31 13:16:39 christos Exp $   */
+/*     $NetBSD: histedit.h,v 1.53 2014/06/18 18:12:28 christos Exp $   */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -84,6 +84,8 @@ typedef struct lineinfo {
  * Initialization, cleanup, and resetting
  */
 EditLine       *el_init(const char *, FILE *, FILE *, FILE *);
+EditLine       *el_init_fd(const char *, FILE *, FILE *, FILE *,
+    int, int, int);
 void            el_end(EditLine *);
 void            el_reset(EditLine *);
 
@@ -154,6 +156,7 @@ unsigned char       _el_fn_complete(EditLine *, int);
 #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_ALIAS_TEXT   24      /* , el_afunc_t, void *);             set     */
 
 #define        EL_BUILTIN_GETCFN       (NULL)
 
@@ -222,6 +225,7 @@ int         history(History *, HistEvent *, 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); */
+#define        H_SAVE_FP       26      /* , FILE *);           */
 
 
 
@@ -277,6 +281,7 @@ int          el_wparse(EditLine *, int, const wchar_t **);
 int             el_wset(EditLine *, int, ...);
 int             el_wget(EditLine *, int, ...);
 
+int             el_cursor(EditLine *, int);
 const LineInfoW        *el_wline(EditLine *);
 int             el_winsertstr(EditLine *, const wchar_t *);
 #define          el_wdeletestr  el_deletestr
index c65d4ee..a487527 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: history.c,v 1.46 2011/11/18 20:39:18 christos Exp $    */
+/*     $NetBSD: history.c,v 1.47 2014/05/11 01:05:17 christos Exp $    */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -40,7 +40,7 @@
 #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 $");
+__RCSID("$NetBSD: history.c,v 1.47 2014/05/11 01:05:17 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -108,6 +108,7 @@ 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_save_fp(TYPE(History) *, FILE *);
 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 *);
@@ -787,13 +788,12 @@ done:
 }
 
 
-/* history_save():
+/* history_save_fp():
  *     TYPE(History) save function
  */
 private int
-history_save(TYPE(History) *h, const char *fname)
+history_save_fp(TYPE(History) *h, FILE *fp)
 {
-       FILE *fp;
        TYPE(HistEvent) ev;
        int i = -1, retval;
        size_t len, max_size;
@@ -803,9 +803,6 @@ history_save(TYPE(History) *h, const char *fname)
        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)
@@ -834,11 +831,29 @@ history_save(TYPE(History) *h, const char *fname)
 oomem:
        h_free(ptr);
 done:
-       (void) fclose(fp);
        return i;
 }
 
 
+/* history_save():
+ *    History save function
+ */
+private int
+history_save(TYPE(History) *h, const char *fname)
+{
+    FILE *fp;
+    int i;
+
+    if ((fp = fopen(fname, "w")) == NULL)
+       return -1;
+
+    i = history_save_fp(h, fp);
+
+    (void) fclose(fp);
+    return i;
+}
+
+
 /* history_prev_event():
  *     Find the previous event, with number given
  */
@@ -1019,6 +1034,12 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
                        he_seterrev(ev, _HE_HIST_WRITE);
                break;
 
+       case H_SAVE_FP:
+               retval = history_save_fp(h, va_arg(va, FILE *));
+               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;
index 802c371..b3e11ba 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: map.c,v 1.31 2011/11/18 20:39:18 christos Exp $        */
+/*     $NetBSD: map.c,v 1.33 2013/01/01 15:34:02 christos Exp $        */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
 #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 $");
+__RCSID("$NetBSD: map.c,v 1.33 2013/01/01 15:34:02 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -1249,7 +1249,7 @@ map_bind(EditLine *el, int argc, const Char **argv)
        Char inbuf[EL_BUFSIZ];
        Char outbuf[EL_BUFSIZ];
        const Char *in = NULL;
-       Char *out = NULL;
+       Char *out;
        el_bindings_t *bp, *ep;
        int cmd;
        int key;
@@ -1368,7 +1368,7 @@ map_bind(EditLine *el, int argc, const Char **argv)
                        return -1;
                }
                if (key)
-                       terminal_set_arrow(el, in, keymacro_map_str(el, out), ntype);
+                       terminal_set_arrow(el, in, keymacro_map_cmd(el, cmd), ntype);
                else {
                        if (in[1]) {
                                keymacro_add(el, in, keymacro_map_cmd(el, cmd), ntype);
index 74796b1..df6ac20 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: read.c,v 1.69 2012/09/11 12:31:08 christos Exp $       */
+/*     $NetBSD: read.c,v 1.70 2013/05/27 23:55:55 christos Exp $       */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)read.c     8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: read.c,v 1.69 2012/09/11 12:31:08 christos Exp $");
+__RCSID("$NetBSD: read.c,v 1.70 2013/05/27 23:55:55 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -341,6 +341,13 @@ read_char(EditLine *el, Char *cp)
                }
        }
 
+       /* Test for EOF */
+       if (num_read == 0) {
+               errno = 0;
+               *cp = '\0';
+               return 0;
+       }
+
 #ifdef WIDECHAR
        if (el->el_flags & CHARSET_IS_UTF8) {
                if (!utf8_islead((unsigned char)cbuf[0]))
index befa7a1..f549dfe 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: readline.c,v 1.106 2012/10/12 23:35:02 christos Exp $  */
+/*     $NetBSD: readline.c,v 1.110 2014/01/21 13:51:44 christos Exp $  */
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
 
 #include "config.h"
 #if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: readline.c,v 1.106 2012/10/12 23:35:02 christos Exp $");
+__RCSID("$NetBSD: readline.c,v 1.110 2014/01/21 13:51:44 christos Exp $");
 #endif /* not lint && not SCCSID */
 
 #include <sys/types.h>
@@ -88,6 +88,14 @@ VFunction *rl_event_hook = NULL;
 KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
     emacs_meta_keymap,
     emacs_ctlx_keymap;
+/*
+ * The following is not implemented; we always catch signals in the
+ * libedit fashion: set handlers on entry to el_gets() and clear them
+ * on the way out. This simplistic approach works for most cases; if
+ * it does not work for your application, please let us know.
+ */
+int rl_catch_signals = 1;
+int rl_catch_sigwinch = 1;
 
 int history_base = 1;          /* probably never subject to change */
 int history_length = 0;
@@ -113,7 +121,6 @@ char *rl_terminal_name = NULL;
 int rl_already_prompted = 0;
 int rl_filename_completion_desired = 0;
 int rl_ignore_completion_duplicates = 0;
-int rl_catch_signals = 1;
 int readline_echoing_p = 1;
 int _rl_print_completions_horizontally = 0;
 VFunction *rl_redisplay_function = NULL;
@@ -233,13 +240,20 @@ static const char *
 _default_history_file(void)
 {
        struct passwd *p;
-       static char path[PATH_MAX];
+       static char *path;
+       size_t len;
 
-       if (*path)
+       if (path)
                return path;
+
        if ((p = getpwuid(getuid())) == NULL)
                return NULL;
-       (void)snprintf(path, sizeof(path), "%s/.history", p->pw_dir);
+
+       len = strlen(p->pw_dir) + sizeof("/.history");
+       if ((path = malloc(len)) == NULL)
+               return NULL;
+
+       (void)snprintf(path, len, "%s/.history", p->pw_dir);
        return path;
 }
 
@@ -1472,6 +1486,9 @@ clear_history(void)
 {
        HistEvent ev;
 
+       if (h == NULL || e == NULL)
+               rl_initialize();
+
        (void)history(h, &ev, H_CLEAR);
        history_length = 0;
 }
@@ -2100,9 +2117,9 @@ void
 rl_get_screen_size(int *rows, int *cols)
 {
        if (rows)
-               el_get(e, EL_GETTC, "li", rows, NULL);
+               el_get(e, EL_GETTC, "li", rows, (void *)0);
        if (cols)
-               el_get(e, EL_GETTC, "co", cols, NULL);
+               el_get(e, EL_GETTC, "co", cols, (void *)0);
 }
 
 void
index 778486c..303609d 100644 (file)
@@ -1,5 +1,5 @@
-#      $NetBSD: shlib_version,v 1.18 2009/01/11 03:07:48 christos Exp $
+#      $NetBSD: shlib_version,v 1.19 2013/01/22 20:23:21 christos Exp $
 #      Remember to update distrib/sets/lists/base/shl.* when changing
 #
 major=3
-minor=0
+minor=1
index 1a92fc5..c1ef3a2 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $     */
+/*     $NetBSD: strlcat.c,v 1.4 2013/01/23 07:57:27 matt Exp $ */
 /*     $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $    */
 
 /*
@@ -20,7 +20,7 @@
 #include "config.h"
 
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $");
+__RCSID("$NetBSD: strlcat.c,v 1.4 2013/01/23 07:57:27 matt Exp $");
 #endif /* LIBC_SCCS and not lint */
 
 #include <sys/types.h>
@@ -44,6 +44,7 @@ __weak_alias(strlcat, _strlcat)
 size_t
 strlcat(char *dst, const char *src, size_t siz)
 {
+#if 1
        char *d = dst;
        const char *s = src;
        size_t n = siz;
@@ -70,5 +71,20 @@ strlcat(char *dst, const char *src, size_t siz)
        *d = '\0';
 
        return(dlen + (s - src));       /* count does not include NUL */
+#else
+       _DIAGASSERT(dst != NULL);
+       _DIAGASSERT(src != NULL);
+
+       /*
+        * Find length of string in dst (maxing out at siz).
+        */
+       size_t dlen = strnlen(dst, siz);
+
+       /*
+        * Copy src into any remaining space in dst (truncating if needed).
+        * Note strlcpy(dst, src, 0) returns strlen(src).
+        */
+       return dlen + strlcpy(dst + dlen, src, siz - dlen);
+#endif
 }
 #endif
index 57c8ee8..ce7d86c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tty.c,v 1.42 2012/05/15 15:59:01 christos Exp $        */
+/*     $NetBSD: tty.c,v 1.46 2014/06/18 18:52:49 christos Exp $        */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)tty.c      8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: tty.c,v 1.42 2012/05/15 15:59:01 christos Exp $");
+__RCSID("$NetBSD: tty.c,v 1.46 2014/06/18 18:52:49 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -48,6 +48,7 @@ __RCSID("$NetBSD: tty.c,v 1.42 2012/05/15 15:59:01 christos Exp $");
 #include <errno.h>
 #include <unistd.h>    /* for isatty */
 #include <strings.h>   /* for ffs */
+#include <stdlib.h>    /* for abort */
 #include "el.h"
 #include "tty.h"
 
@@ -459,6 +460,7 @@ private void        tty__getchar(struct termios *, unsigned char *);
 private void   tty__setchar(struct termios *, unsigned char *);
 private speed_t        tty__getspeed(struct termios *);
 private int    tty_setup(EditLine *);
+private void   tty_setup_flags(EditLine *, struct termios *, int);
 
 #define        t_qu    t_ts
 
@@ -517,17 +519,7 @@ tty_setup(EditLine *el)
        el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex);
        el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex);
 
-       el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
-       el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
-
-       el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
-       el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
-
-       el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
-       el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
-
-       el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
-       el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
+       tty_setup_flags(el, &el->el_tty.t_ex, EX_IO);
 
        /*
          * Reset the tty chars to reasonable defaults
@@ -562,17 +554,7 @@ tty_setup(EditLine *el)
                }
        }
 
-       el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
-       el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
-
-       el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
-       el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
-
-       el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
-       el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
-
-       el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
-       el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
+       tty_setup_flags(el, &el->el_tty.t_ed, ED_IO);
 
        tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
        tty_bind_char(el, 1);
@@ -938,6 +920,58 @@ tty_bind_char(EditLine *el, int force)
 }
 
 
+private tcflag_t *
+tty__get_flag(struct termios *t, int kind) {
+       switch (kind) {
+       case MD_INP:
+               return &t->c_iflag;
+       case MD_OUT:
+               return &t->c_oflag;
+       case MD_CTL:
+               return &t->c_cflag;
+       case MD_LIN:
+               return &t->c_lflag;
+       default:
+               abort();
+               /*NOTREACHED*/
+       }
+}
+
+
+private tcflag_t
+tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
+{
+       f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
+       f |= el->el_tty.t_t[mode][kind].t_setmask;
+       return f;
+}
+
+
+private void
+tty_update_flags(EditLine *el, int kind)
+{
+       tcflag_t *tt, *ed, *ex;
+       tt = tty__get_flag(&el->el_tty.t_ts, kind);
+       ed = tty__get_flag(&el->el_tty.t_ed, kind);
+       ex = tty__get_flag(&el->el_tty.t_ex, kind);
+
+       if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) {
+               *ed = tty_update_flag(el, *tt, ED_IO, kind);
+               *ex = tty_update_flag(el, *tt, EX_IO, kind);
+       }
+}
+
+
+private void
+tty_update_char(EditLine *el, int mode, int c) {
+       if (!((el->el_tty.t_t[mode][MD_CHAR].t_setmask & C_SH(c)))
+           && (el->el_tty.t_c[TS_IO][c] != el->el_tty.t_c[EX_IO][c]))
+               el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c];
+       if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c))
+               el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable;
+}
+
+
 /* tty_rawmode():
  *     Set terminal into 1 character at a time mode.
  */
@@ -973,112 +1007,42 @@ tty_rawmode(EditLine *el)
                (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed);
        }
        if (tty__cooked_mode(&el->el_tty.t_ts)) {
-               if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) {
-                       el->el_tty.t_ex.c_cflag =
-                           el->el_tty.t_ts.c_cflag;
-                       el->el_tty.t_ex.c_cflag &=
-                           ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask;
-                       el->el_tty.t_ex.c_cflag |=
-                           el->el_tty.t_t[EX_IO][MD_CTL].t_setmask;
-
-                       el->el_tty.t_ed.c_cflag =
-                           el->el_tty.t_ts.c_cflag;
-                       el->el_tty.t_ed.c_cflag &=
-                           ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask;
-                       el->el_tty.t_ed.c_cflag |=
-                           el->el_tty.t_t[ED_IO][MD_CTL].t_setmask;
-               }
-               if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) &&
-                   (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) {
-                       el->el_tty.t_ex.c_lflag =
-                           el->el_tty.t_ts.c_lflag;
-                       el->el_tty.t_ex.c_lflag &=
-                           ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask;
-                       el->el_tty.t_ex.c_lflag |=
-                           el->el_tty.t_t[EX_IO][MD_LIN].t_setmask;
-
-                       el->el_tty.t_ed.c_lflag =
-                           el->el_tty.t_ts.c_lflag;
-                       el->el_tty.t_ed.c_lflag &=
-                           ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask;
-                       el->el_tty.t_ed.c_lflag |=
-                           el->el_tty.t_t[ED_IO][MD_LIN].t_setmask;
-               }
-               if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) &&
-                   (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) {
-                       el->el_tty.t_ex.c_iflag =
-                           el->el_tty.t_ts.c_iflag;
-                       el->el_tty.t_ex.c_iflag &=
-                           ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask;
-                       el->el_tty.t_ex.c_iflag |=
-                           el->el_tty.t_t[EX_IO][MD_INP].t_setmask;
-
-                       el->el_tty.t_ed.c_iflag =
-                           el->el_tty.t_ts.c_iflag;
-                       el->el_tty.t_ed.c_iflag &=
-                           ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask;
-                       el->el_tty.t_ed.c_iflag |=
-                           el->el_tty.t_t[ED_IO][MD_INP].t_setmask;
-               }
-               if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) &&
-                   (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) {
-                       el->el_tty.t_ex.c_oflag =
-                           el->el_tty.t_ts.c_oflag;
-                       el->el_tty.t_ex.c_oflag &=
-                           ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask;
-                       el->el_tty.t_ex.c_oflag |=
-                           el->el_tty.t_t[EX_IO][MD_OUT].t_setmask;
-
-                       el->el_tty.t_ed.c_oflag =
-                           el->el_tty.t_ts.c_oflag;
-                       el->el_tty.t_ed.c_oflag &=
-                           ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask;
-                       el->el_tty.t_ed.c_oflag |=
-                           el->el_tty.t_t[ED_IO][MD_OUT].t_setmask;
-               }
+               int i;
+
+               for (i = MD_INP; i <= MD_LIN; i++)
+                       tty_update_flags(el, i);
+
                if (tty__gettabs(&el->el_tty.t_ex) == 0)
                        el->el_tty.t_tabs = 0;
                else
                        el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0;
 
-               {
-                       int i;
+               tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+               /*
+                * Check if the user made any changes.
+                * If he did, then propagate the changes to the
+                * edit and execute data structures.
+                */
+               for (i = 0; i < C_NCC; i++)
+                       if (el->el_tty.t_c[TS_IO][i] !=
+                           el->el_tty.t_c[EX_IO][i])
+                               break;
 
-                       tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]);
+               if (i != C_NCC) {
                        /*
-                        * Check if the user made any changes.
-                        * If he did, then propagate the changes to the
-                        * edit and execute data structures.
-                        */
+                        * Propagate changes only to the unprotected
+                        * chars that have been modified just now.
+                        */
                        for (i = 0; i < C_NCC; i++)
-                               if (el->el_tty.t_c[TS_IO][i] !=
-                                   el->el_tty.t_c[EX_IO][i])
-                                       break;
-
-                       if (i != C_NCC) {
-                               /*
-                                * Propagate changes only to the unprotected
-                                * chars that have been modified just now.
-                                */
-                               for (i = 0; i < C_NCC; i++) {
-                                       if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i)))
-                                           && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
-                                               el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i];
-                                       if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i))
-                                               el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable;
-                               }
-                               tty_bind_char(el, 0);
-                               tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
-
-                               for (i = 0; i < C_NCC; i++) {
-                                       if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i)))
-                                           && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i]))
-                                               el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i];
-                                       if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i))
-                                               el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable;
-                               }
-                               tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
-                       }
+                               tty_update_char(el, ED_IO, i);
+
+                       tty_bind_char(el, 0);
+                       tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]);
+
+                       for (i = 0; i < C_NCC; i++)
+                               tty_update_char(el, EX_IO, i);
+
+                       tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]);
                }
        }
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) {
@@ -1129,17 +1093,7 @@ tty_quotemode(EditLine *el)
 
        el->el_tty.t_qu = el->el_tty.t_ed;
 
-       el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask;
-       el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask;
-
-       el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask;
-       el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask;
-
-       el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask;
-       el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask;
-
-       el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask;
-       el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask;
+       tty_setup_flags(el, &el->el_tty.t_qu, QU_IO);
 
        if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) {
 #ifdef DEBUG_TTY
@@ -1320,6 +1274,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
                }
        }
 
+       tty_setup_flags(el, tios, z);
        if (el->el_tty.t_mode == z) {
                if (tty_setty(el, TCSADRAIN, tios) == -1) {
 #ifdef DEBUG_TTY
@@ -1357,3 +1312,14 @@ tty_printchar(EditLine *el, unsigned char *s)
        (void) fprintf(el->el_errfile, "\n");
 }
 #endif /* notyet */
+
+
+private void
+tty_setup_flags(EditLine *el, struct termios *tios, int mode)
+{
+       int kind;
+       for (kind = MD_INP; kind <= MD_LIN; kind++) {
+               tcflag_t *f = tty__get_flag(tios, kind);
+               *f = tty_update_flag(el, *f, mode, kind);
+       }
+}
index 7bdb0b2..0bf4b64 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: tty.h,v 1.14 2012/05/15 15:59:01 christos Exp $        */
+/*     $NetBSD: tty.h,v 1.15 2014/05/19 19:54:12 christos Exp $        */
 
 /*-
  * Copyright (c) 1992, 1993
 #define        QU_IO   2       /* used only for quoted chars   */
 #define        NN_IO   3       /* The number of entries        */
 
+/* Don't re-order */
 #define        MD_INP  0
 #define        MD_OUT  1
 #define        MD_CTL  2
index c6536ca..4bbc7bc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $      */
+/*     $NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $  */
 
 /*-
  * Copyright (c) 1989, 1993
@@ -34,7 +34,7 @@
 #if 0
 static char sccsid[] = "@(#)unvis.c    8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: unvis.c,v 1.39 2012/03/13 21:13:37 christos Exp $");
+__RCSID("$NetBSD: unvis.c,v 1.41 2012/12/15 04:29:53 matt Exp $");
 #endif
 #endif /* LIBC_SCCS and not lint */
 
@@ -82,7 +82,7 @@ __weak_alias(strnunvisx,_strnunvisx)
  * RFC 1866
  */
 static const struct nv {
-       const char *name;
+       char name[7];
        uint8_t value;
 } nv[] = {
        { "AElig",      198 }, /* capital AE diphthong (ligature)  */
index ec9abbd..483066e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vi.c,v 1.43 2012/01/16 14:57:45 christos Exp $ */
+/*     $NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $ */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -42,7 +42,7 @@
 #if 0
 static char sccsid[] = "@(#)vi.c       8.1 (Berkeley) 6/4/93";
 #else
-__RCSID("$NetBSD: vi.c,v 1.43 2012/01/16 14:57:45 christos Exp $");
+__RCSID("$NetBSD: vi.c,v 1.45 2014/06/18 18:12:28 christos Exp $");
 #endif
 #endif /* not lint && not SCCSID */
 
@@ -918,34 +918,26 @@ vi_comment_out(EditLine *el, Int c __attribute__((__unused__)))
  * NB: posix implies that we should enter insert mode, however
  * this is against historical precedent...
  */
-#ifdef __weak_reference
-__weakref_visible char *my_get_alias_text(const char *)
-    __weak_reference(get_alias_text);
-#endif
 protected el_action_t
 /*ARGSUSED*/
-vi_alias(EditLine *el, Int c __attribute__((__unused__)))
+vi_alias(EditLine *el __attribute__((__unused__)), Int c __attribute__((__unused__)))
 {
-#ifdef __weak_reference
        char alias_name[3];
-       char *alias_text;
+       const char *alias_text;
 
-       if (my_get_alias_text == 0) {
+       if (el->el_chared.c_aliasfun == NULL)
                return CC_ERROR;
-       }
 
        alias_name[0] = '_';
        alias_name[2] = 0;
        if (el_getc(el, &alias_name[1]) != 1)
                return CC_ERROR;
 
-       alias_text = my_get_alias_text(alias_name);
+       alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg,
+           alias_name);
        if (alias_text != NULL)
                FUN(el,push)(el, ct_decode_string(alias_text, &el->el_scratch));
        return CC_NORM;
-#else
-       return CC_ERROR;
-#endif
 }
 
 /* vi_to_history_line():
index 5a9005f..880eacb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $        */
+/*     $NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $   */
 
 /*-
  * Copyright (c) 1989, 1993
 #include "config.h"
 
 #if defined(LIBC_SCCS) && !defined(lint)
-__RCSID("$NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $");
+__RCSID("$NetBSD: vis.c,v 1.60 2013/02/21 16:21:20 joerg Exp $");
 #endif /* LIBC_SCCS and not lint */
+#ifdef __FBSDID
+__FBSDID("$FreeBSD$");
+#endif
 
 #include <sys/types.h>
+#include <sys/param.h>
 
+#include <stdint.h>
 #include <assert.h>
 #include <vis.h>
 #include <errno.h>
 #include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
 
 #ifdef __weak_alias
 __weak_alias(strvisx,_strvisx)
@@ -78,59 +85,68 @@ __weak_alias(strvisx,_strvisx)
 #include <stdio.h>
 #include <string.h>
 
-static char *do_svis(char *, size_t *, int, int, int, const char *);
+/*
+ * The reason for going through the trouble to deal with character encodings
+ * in vis(3), is that we use this to safe encode output of commands. This
+ * safe encoding varies depending on the character set. For example if we
+ * display ps output in French, we don't want to display French characters
+ * as M-foo.
+ */
+
+static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *);
 
 #undef BELL
-#define BELL '\a'
-
-#define isoctal(c)     (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
-#define iswhite(c)     (c == ' ' || c == '\t' || c == '\n')
-#define issafe(c)      (c == '\b' || c == BELL || c == '\r')
-#define xtoa(c)                "0123456789abcdef"[c]
-#define XTOA(c)                "0123456789ABCDEF"[c]
-
-#define MAXEXTRAS      5
-
-#define MAKEEXTRALIST(flag, extra, orig_str)                                 \
-do {                                                                         \
-       const char *orig = orig_str;                                          \
-       const char *o = orig;                                                 \
-       char *e;                                                              \
-       while (*o++)                                                          \
-               continue;                                                     \
-       extra = malloc((size_t)((o - orig) + MAXEXTRAS));                     \
-       if (!extra) break;                                                    \
-       for (o = orig, e = extra; (*e++ = *o++) != '\0';)                     \
-               continue;                                                     \
-       e--;                                                                  \
-       if (flag & VIS_SP) *e++ = ' ';                                        \
-       if (flag & VIS_TAB) *e++ = '\t';                                      \
-       if (flag & VIS_NL) *e++ = '\n';                                       \
-       if ((flag & VIS_NOSLASH) == 0) *e++ = '\\';                           \
-       *e = '\0';                                                            \
-} while (/*CONSTCOND*/0)
+#define BELL L'\a'
+
+#define iswoctal(c)    (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7')
+#define iswwhite(c)    (c == L' ' || c == L'\t' || c == L'\n')
+#define iswsafe(c)     (c == L'\b' || c == BELL || c == L'\r')
+#define xtoa(c)                L"0123456789abcdef"[c]
+#define XTOA(c)                L"0123456789ABCDEF"[c]
+
+#define MAXEXTRAS      10
+
+#if !HAVE_NBTOOL_CONFIG_H
+#ifndef __NetBSD__
+/*
+ * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer
+ * integral type and it is probably wrong, since currently the maximum
+ * number of bytes and character needs is 6. Until this is fixed, the
+ * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and
+ * the assertion is commented out.
+ */
+#ifdef __FreeBSD__
+/*
+ * On FreeBSD including <sys/systm.h> for CTASSERT only works in kernel
+ * mode.
+ */
+#ifndef CTASSERT
+#define CTASSERT(x)             _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y)         __CTASSERT(x, y)
+#define __CTASSERT(x, y)        typedef char __assert ## y[(x) ? 1 : -1]
+#endif
+#endif /* __FreeBSD__ */
+/*
+CTASSERT(MB_LEN_MAX <= sizeof(uint64_t));
+*/
+#endif /* !__NetBSD__ */
+#endif
 
 /*
  * This is do_hvis, for HTTP style (RFC 1808)
  */
-static char *
-do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
+static wchar_t *
+do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
 {
-
-       if ((isascii(c) && isalnum(c))
+       if (iswalnum(c)
            /* safe */
-           || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
+           || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+'
            /* extra */
-           || c == '!' || c == '*' || c == '\'' || c == '(' || c == ')'
-           || c == ',') {
-               dst = do_svis(dst, dlen, c, flag, nextc, extra);
-       } else {
-               if (dlen) {
-                       if (*dlen < 3)
-                               return NULL;
-                       *dlen -= 3;
-               }
-               *dst++ = '%';
+           || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')'
+           || c == L',')
+               dst = do_svis(dst, c, flags, nextc, extra);
+       else {
+               *dst++ = L'%';
                *dst++ = xtoa(((unsigned int)c >> 4) & 0xf);
                *dst++ = xtoa((unsigned int)c & 0xf);
        }
@@ -142,312 +158,448 @@ do_hvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
  * This is do_mvis, for Quoted-Printable MIME (RFC 2045)
  * NB: No handling of long lines or CRLF.
  */
-static char *
-do_mvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
+static wchar_t *
+do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
 {
-       if ((c != '\n') &&
+       if ((c != L'\n') &&
            /* Space at the end of the line */
-           ((isspace(c) && (nextc == '\r' || nextc == '\n')) ||
+           ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) ||
            /* Out of range */
-           (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
-           /* Specific char to be escaped */ 
-           strchr("#$@[\\]^`{|}~", c) != NULL)) {
-               if (dlen) {
-                       if (*dlen < 3)
-                               return NULL;
-                       *dlen -= 3;
-               }
-               *dst++ = '=';
+           (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) ||
+           /* Specific char to be escaped */
+           wcschr(L"#$@[\\]^`{|}~", c) != NULL)) {
+               *dst++ = L'=';
                *dst++ = XTOA(((unsigned int)c >> 4) & 0xf);
                *dst++ = XTOA((unsigned int)c & 0xf);
-       } else {
-               dst = do_svis(dst, dlen, c, flag, nextc, extra);
-       }
+       } else
+               dst = do_svis(dst, c, flags, nextc, extra);
        return dst;
 }
 
 /*
- * This is do_vis, the central code of vis.
- * dst:              Pointer to the destination buffer
- * c:        Character to encode
- * flag:      Flag word
- * nextc:     The character following 'c'
- * extra:     Pointer to the list of extra characters to be
- *           backslash-protected.
+ * Output single byte of multibyte character.
  */
-static char *
-do_svis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
+static wchar_t *
+do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra)
 {
-       int isextra;
-       size_t odlen = dlen ? *dlen : 0;
-
-       isextra = strchr(extra, c) != NULL;
-#define HAVE(x) \
-       do { \
-               if (dlen) { \
-                       if (*dlen < (x)) \
-                               goto out; \
-                       *dlen -= (x); \
-               } \
-       } while (/*CONSTCOND*/0)
-       if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) ||
-           ((flag & VIS_SAFE) && issafe(c)))) {
-               HAVE(1);
-               *dst++ = c;
-               return dst;
-       }
-       if (flag & VIS_CSTYLE) {
-               HAVE(2);
+       if (flags & VIS_CSTYLE) {
                switch (c) {
-               case '\n':
-                       *dst++ = '\\'; *dst++ = 'n';
+               case L'\n':
+                       *dst++ = L'\\'; *dst++ = L'n';
                        return dst;
-               case '\r':
-                       *dst++ = '\\'; *dst++ = 'r';
+               case L'\r':
+                       *dst++ = L'\\'; *dst++ = L'r';
                        return dst;
-               case '\b':
-                       *dst++ = '\\'; *dst++ = 'b';
+               case L'\b':
+                       *dst++ = L'\\'; *dst++ = L'b';
                        return dst;
                case BELL:
-                       *dst++ = '\\'; *dst++ = 'a';
+                       *dst++ = L'\\'; *dst++ = L'a';
                        return dst;
-               case '\v':
-                       *dst++ = '\\'; *dst++ = 'v';
+               case L'\v':
+                       *dst++ = L'\\'; *dst++ = L'v';
                        return dst;
-               case '\t':
-                       *dst++ = '\\'; *dst++ = 't';
+               case L'\t':
+                       *dst++ = L'\\'; *dst++ = L't';
                        return dst;
-               case '\f':
-                       *dst++ = '\\'; *dst++ = 'f';
+               case L'\f':
+                       *dst++ = L'\\'; *dst++ = L'f';
                        return dst;
-               case ' ':
-                       *dst++ = '\\'; *dst++ = 's';
+               case L' ':
+                       *dst++ = L'\\'; *dst++ = L's';
                        return dst;
-               case '\0':
-                       *dst++ = '\\'; *dst++ = '0';
-                       if (isoctal(nextc)) {
-                               HAVE(2);
-                               *dst++ = '0';
-                               *dst++ = '0';
+               case L'\0':
+                       *dst++ = L'\\'; *dst++ = L'0';
+                       if (iswoctal(nextc)) {
+                               *dst++ = L'0';
+                               *dst++ = L'0';
                        }
                        return dst;
                default:
-                       if (isgraph(c)) {
-                               *dst++ = '\\'; *dst++ = c;
+                       if (iswgraph(c)) {
+                               *dst++ = L'\\';
+                               *dst++ = c;
                                return dst;
                        }
-                       if (dlen)
-                               *dlen = odlen;
                }
        }
-       if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
-               HAVE(4);
-               *dst++ = '\\';
-               *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0';
-               *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0';
-               *dst++ =                             (c       & 07) + '0';
+       if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) {
+               *dst++ = L'\\';
+               *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0';
+               *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0';
+               *dst++ =                             (c       & 07) + L'0';
        } else {
-               if ((flag & VIS_NOSLASH) == 0) {
-                       HAVE(1);
-                       *dst++ = '\\';
-               }
+               if ((flags & VIS_NOSLASH) == 0)
+                       *dst++ = L'\\';
 
                if (c & 0200) {
-                       HAVE(1);
-                       c &= 0177; *dst++ = 'M';
+                       c &= 0177;
+                       *dst++ = L'M';
                }
 
-               if (iscntrl(c)) {
-                       HAVE(2);
-                       *dst++ = '^';
+               if (iswcntrl(c)) {
+                       *dst++ = L'^';
                        if (c == 0177)
-                               *dst++ = '?';
+                               *dst++ = L'?';
                        else
-                               *dst++ = c + '@';
+                               *dst++ = c + L'@';
                } else {
-                       HAVE(2);
-                       *dst++ = '-'; *dst++ = c;
+                       *dst++ = L'-';
+                       *dst++ = c;
                }
        }
+
+       return dst;
+}
+
+/*
+ * This is do_vis, the central code of vis.
+ * dst:              Pointer to the destination buffer
+ * c:        Character to encode
+ * flags:     Flags word
+ * nextc:     The character following 'c'
+ * extra:     Pointer to the list of extra characters to be
+ *           backslash-protected.
+ */
+static wchar_t *
+do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra)
+{
+       int iswextra, i, shft;
+       uint64_t bmsk, wmsk;
+
+       iswextra = wcschr(extra, c) != NULL;
+       if (!iswextra && (iswgraph(c) || iswwhite(c) ||
+           ((flags & VIS_SAFE) && iswsafe(c)))) {
+               *dst++ = c;
+               return dst;
+       }
+
+       /* See comment in istrsenvisx() output loop, below. */
+       wmsk = 0;
+       for (i = sizeof(wmsk) - 1; i >= 0; i--) {
+               shft = i * NBBY;
+               bmsk = (uint64_t)0xffLL << shft;
+               wmsk |= bmsk;
+               if ((c & wmsk) || i == 0)
+                       dst = do_mbyte(dst, (wint_t)(
+                           (uint64_t)(c & bmsk) >> shft),
+                           flags, nextc, iswextra);
+       }
+
        return dst;
-out:
-       *dlen = odlen;
-       return NULL;
 }
 
-typedef char *(*visfun_t)(char *, size_t *, int, int, int, const char *);
+typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *);
 
 /*
  * Return the appropriate encoding function depending on the flags given.
  */
 static visfun_t
-getvisfun(int flag)
+getvisfun(int flags)
 {
-       if (flag & VIS_HTTPSTYLE)
+       if (flags & VIS_HTTPSTYLE)
                return do_hvis;
-       if (flag & VIS_MIMESTYLE)
+       if (flags & VIS_MIMESTYLE)
                return do_mvis;
        return do_svis;
 }
 
 /*
- * isnvis - visually encode characters, also encoding the characters
- *       pointed to by `extra'
+ * Expand list of extra characters to not visually encode.
  */
-static char *
-isnvis(char *dst, size_t *dlen, int c, int flag, int nextc, const char *extra)
+static wchar_t *
+makeextralist(int flags, const char *src)
 {
-       char *nextra = NULL;
-       visfun_t f;
+       wchar_t *dst, *d;
+       size_t len;
 
-       _DIAGASSERT(dst != NULL);
-       _DIAGASSERT(extra != NULL);
-       MAKEEXTRALIST(flag, nextra, extra);
-       if (!nextra) {
-               if (dlen && *dlen == 0) {
-                       errno = ENOSPC;
-                       return NULL;
-               }
-               *dst = '\0';            /* can't create nextra, return "" */
-               return dst;
-       }
-       f = getvisfun(flag);
-       dst = (*f)(dst, dlen, c, flag, nextc, nextra);
-       free(nextra);
-       if (dst == NULL || (dlen && *dlen == 0)) {
-               errno = ENOSPC;
+       len = strlen(src);
+       if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL)
                return NULL;
+
+       if (mbstowcs(dst, src, len) == (size_t)-1) {
+               size_t i;
+               for (i = 0; i < len; i++)
+                       dst[i] = (wint_t)(u_char)src[i];
+               d = dst + len;
+       } else
+               d = dst + wcslen(dst);
+
+       if (flags & VIS_GLOB) {
+               *d++ = L'*';
+               *d++ = L'?';
+               *d++ = L'[';
+               *d++ = L'#';
        }
-       *dst = '\0';
-       return dst;
-}
 
-char *
-svis(char *dst, int c, int flag, int nextc, const char *extra)
-{
-       return isnvis(dst, NULL, c, flag, nextc, extra);
-}
+       if (flags & VIS_SP) *d++ = L' ';
+       if (flags & VIS_TAB) *d++ = L'\t';
+       if (flags & VIS_NL) *d++ = L'\n';
+       if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\';
+       *d = L'\0';
 
-char *
-snvis(char *dst, size_t dlen, int c, int flag, int nextc, const char *extra)
-{
-       return isnvis(dst, &dlen, c, flag, nextc, extra);
+       return dst;
 }
 
-
 /*
- * strsvis, strsvisx - visually encode characters from src into dst
- *
- *     Extra is a pointer to a \0-terminated list of characters to
- *     be encoded, too. These functions are useful e. g. to
- *     encode strings in such a way so that they are not interpreted
- *     by a shell.
- *
- *     Dst must be 4 times the size of src to account for possible
- *     expansion.  The length of dst, not including the trailing NULL,
- *     is returned.
- *
- *     Strsvisx encodes exactly len bytes from src into dst.
- *     This is useful for encoding a block of data.
+ * istrsenvisx()
+ *     The main internal function.
+ *     All user-visible functions call this one.
  */
 static int
-istrsnvis(char *dst, size_t *dlen, const char *csrc, int flag, const char *extra)
+istrsenvisx(char *mbdst, size_t *dlen, const char *mbsrc, size_t mblength,
+    int flags, const char *mbextra, int *cerr_ptr)
 {
-       int c;
-       char *start;
-       char *nextra = NULL;
-       const unsigned char *src = (const unsigned char *)csrc;
+       wchar_t *dst, *src, *pdst, *psrc, *start, *extra;
+       size_t len, olen;
+       uint64_t bmsk, wmsk;
+       wint_t c;
        visfun_t f;
-
-       _DIAGASSERT(dst != NULL);
-       _DIAGASSERT(src != NULL);
-       _DIAGASSERT(extra != NULL);
-       MAKEEXTRALIST(flag, nextra, extra);
-       if (!nextra) {
-               *dst = '\0';            /* can't create nextra, return "" */
-               return 0;
+       int clen = 0, cerr = 0, error = -1, i, shft;
+       ssize_t mbslength, maxolen;
+
+       _DIAGASSERT(mbdst != NULL);
+       _DIAGASSERT(mbsrc != NULL);
+       _DIAGASSERT(mbextra != NULL);
+
+       /*
+        * Input (mbsrc) is a char string considered to be multibyte
+        * characters.  The input loop will read this string pulling
+        * one character, possibly multiple bytes, from mbsrc and
+        * converting each to wchar_t in src.
+        *
+        * The vis conversion will be done using the wide char
+        * wchar_t string.
+        *
+        * This will then be converted back to a multibyte string to
+        * return to the caller.
+        */
+
+       /* Allocate space for the wide char strings */
+       psrc = pdst = extra = NULL;
+       if (!mblength)
+               mblength = strlen(mbsrc);
+       if ((psrc = calloc(mblength + 1, sizeof(*psrc))) == NULL)
+               return -1;
+       if ((pdst = calloc((4 * mblength) + 1, sizeof(*pdst))) == NULL)
+               goto out;
+       dst = pdst;
+       src = psrc;
+
+       /* Use caller's multibyte conversion error flag. */
+       if (cerr_ptr)
+               cerr = *cerr_ptr;
+
+       /*
+        * Input loop.
+        * Handle up to mblength characters (not bytes).  We do not
+        * stop at NULs because we may be processing a block of data
+        * that includes NULs.
+        */
+       mbslength = (ssize_t)mblength;
+       /*
+        * When inputing a single character, must also read in the
+        * next character for nextc, the look-ahead character.
+        */
+       if (mbslength == 1)
+               mbslength++;
+       while (mbslength > 0) {
+               /* Convert one multibyte character to wchar_t. */
+               if (!cerr)
+                       clen = mbtowc(src, mbsrc, MB_LEN_MAX);
+               if (cerr || clen < 0) {
+                       /* Conversion error, process as a byte instead. */
+                       *src = (wint_t)(u_char)*mbsrc;
+                       clen = 1;
+                       cerr = 1;
+               }
+               if (clen == 0)
+                       /*
+                        * NUL in input gives 0 return value. process
+                        * as single NUL byte and keep going.
+                        */
+                       clen = 1;
+               /* Advance buffer character pointer. */
+               src++;
+               /* Advance input pointer by number of bytes read. */
+               mbsrc += clen;
+               /* Decrement input byte count. */
+               mbslength -= clen;
+       }
+       len = src - psrc;
+       src = psrc;
+       /*
+        * In the single character input case, we will have actually
+        * processed two characters, c and nextc.  Reset len back to
+        * just a single character.
+        */
+       if (mblength < len)
+               len = mblength;
+
+       /* Convert extra argument to list of characters for this mode. */
+       extra = makeextralist(flags, mbextra);
+       if (!extra) {
+               if (dlen && *dlen == 0) {
+                       errno = ENOSPC;
+                       goto out;
+               }
+               *mbdst = '\0';          /* can't create extra, return "" */
+               error = 0;
+               goto out;
        }
-       f = getvisfun(flag);
-       for (start = dst; (c = *src++) != '\0'; /* empty */) {
-               dst = (*f)(dst, dlen, c, flag, *src, nextra);
+
+       /* Look up which processing function to call. */
+       f = getvisfun(flags);
+
+       /*
+        * Main processing loop.
+        * Call do_Xvis processing function one character at a time
+        * with next character available for look-ahead.
+        */
+       for (start = dst; len > 0; len--) {
+               c = *src++;
+               dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra);
                if (dst == NULL) {
                        errno = ENOSPC;
-                       return -1;
+                       goto out;
                }
        }
-       free(nextra);
-       if (dlen && *dlen == 0) {
-               errno = ENOSPC;
-               return -1;
+
+       /* Terminate the string in the buffer. */
+       *dst = L'\0';
+
+       /*
+        * Output loop.
+        * Convert wchar_t string back to multibyte output string.
+        * If we have hit a multi-byte conversion error on input,
+        * output byte-by-byte here.  Else use wctomb().
+        */
+       len = wcslen(start);
+       maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1);
+       olen = 0;
+       for (dst = start; len > 0; len--) {
+               if (!cerr)
+                       clen = wctomb(mbdst, *dst);
+               if (cerr || clen < 0) {
+                       /*
+                        * Conversion error, process as a byte(s) instead.
+                        * Examine each byte and higher-order bytes for
+                        * data.  E.g.,
+                        *      0x000000000000a264 -> a2 64
+                        *      0x000000001f00a264 -> 1f 00 a2 64
+                        */
+                       clen = 0;
+                       wmsk = 0;
+                       for (i = sizeof(wmsk) - 1; i >= 0; i--) {
+                               shft = i * NBBY;
+                               bmsk = (uint64_t)0xffLL << shft;
+                               wmsk |= bmsk;
+                               if ((*dst & wmsk) || i == 0)
+                                       mbdst[clen++] = (char)(
+                                           (uint64_t)(*dst & bmsk) >>
+                                           shft);
+                       }
+                       cerr = 1;
+               }
+               /* If this character would exceed our output limit, stop. */
+               if (olen + clen > (size_t)maxolen)
+                       break;
+               /* Advance output pointer by number of bytes written. */
+               mbdst += clen;
+               /* Advance buffer character pointer. */
+               dst++;
+               /* Incrment output character count. */
+               olen += clen;
        }
-       *dst = '\0';
-       return (int)(dst - start);
+
+       /* Terminate the output string. */
+       *mbdst = '\0';
+
+       /* Pass conversion error flag out. */
+       if (cerr_ptr)
+               *cerr_ptr = cerr;
+
+       free(extra);
+       free(pdst);
+       free(psrc);
+
+       return (int)olen;
+out:
+       free(extra);
+       free(pdst);
+       free(psrc);
+       return error;
 }
+#endif
 
-int
-strsvis(char *dst, const char *csrc, int flag, const char *extra)
+#if !HAVE_SVIS
+/*
+ *     The "svis" variants all take an "extra" arg that is a pointer
+ *     to a NUL-terminated list of characters to be encoded, too.
+ *     These functions are useful e. g. to encode strings in such a
+ *     way so that they are not interpreted by a shell.
+ */
+
+char *
+svis(char *mbdst, int c, int flags, int nextc, const char *mbextra)
 {
-       return istrsnvis(dst, NULL, csrc, flag, extra);
+       char cc[2];
+       int ret;
+
+       cc[0] = c;
+       cc[1] = nextc;
+
+       ret = istrsenvisx(mbdst, NULL, cc, 1, flags, mbextra, NULL);
+       if (ret < 0)
+               return NULL;
+       return mbdst + ret;
 }
 
-int
-strsnvis(char *dst, size_t dlen, const char *csrc, int flag, const char *extra)
+char *
+snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra)
 {
-       return istrsnvis(dst, &dlen, csrc, flag, extra);
+       char cc[2];
+       int ret;
+
+       cc[0] = c;
+       cc[1] = nextc;
+
+       ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, mbextra, NULL);
+       if (ret < 0)
+               return NULL;
+       return mbdst + ret;
 }
 
-static int
-istrsnvisx(char *dst, size_t *dlen, const char *csrc, size_t len, int flag,
-    const char *extra)
+int
+strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra)
 {
-       unsigned char c;
-       char *start;
-       char *nextra = NULL;
-       const unsigned char *src = (const unsigned char *)csrc;
-       visfun_t f;
+       return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, mbextra, NULL);
+}
 
-       _DIAGASSERT(dst != NULL);
-       _DIAGASSERT(src != NULL);
-       _DIAGASSERT(extra != NULL);
-       MAKEEXTRALIST(flag, nextra, extra);
-       if (! nextra) {
-               if (dlen && *dlen == 0) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-               *dst = '\0';            /* can't create nextra, return "" */
-               return 0;
-       }
+int
+strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra)
+{
+       return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, mbextra, NULL);
+}
 
-       f = getvisfun(flag);
-       for (start = dst; len > 0; len--) {
-               c = *src++;
-               dst = (*f)(dst, dlen, c, flag, len > 1 ? *src : '\0', nextra);
-               if (dst == NULL) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-       }
-       free(nextra);
-       if (dlen && *dlen == 0) {
-               errno = ENOSPC;
-               return -1;
-       }
-       *dst = '\0';
-       return (int)(dst - start);
+int
+strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra)
+{
+       return istrsenvisx(mbdst, NULL, mbsrc, len, flags, mbextra, NULL);
 }
 
 int
-strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra)
+strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
+    const char *mbextra)
 {
-       return istrsnvisx(dst, NULL, csrc, len, flag, extra);
+       return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, NULL);
 }
 
 int
-strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag,
-    const char *extra)
+strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
+    const char *mbextra, int *cerr_ptr)
 {
-       return istrsnvisx(dst, &dlen, csrc, len, flag, extra);
+       return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr);
 }
 #endif
 
@@ -455,120 +607,83 @@ strsnvisx(char *dst, size_t dlen, const char *csrc, size_t len, int flag,
 /*
  * vis - visually encode characters
  */
-static char *
-invis(char *dst, size_t *dlen, int c, int flag, int nextc)
+char *
+vis(char *mbdst, int c, int flags, int nextc)
 {
-       char *extra = NULL;
-       unsigned char uc = (unsigned char)c;
-       visfun_t f;
+       char cc[2];
+       int ret;
 
-       _DIAGASSERT(dst != NULL);
+       cc[0] = c;
+       cc[1] = nextc;
 
-       MAKEEXTRALIST(flag, extra, "");
-       if (! extra) {
-               if (dlen && *dlen == 0) {
-                       errno = ENOSPC;
-                       return NULL;
-               }
-               *dst = '\0';            /* can't create extra, return "" */
-               return dst;
-       }
-       f = getvisfun(flag);
-       dst = (*f)(dst, dlen, uc, flag, nextc, extra);
-       free(extra);
-       if (dst == NULL || (dlen && *dlen == 0)) {
-               errno = ENOSPC;
+       ret = istrsenvisx(mbdst, NULL, cc, 1, flags, "", NULL);
+       if (ret < 0)
                return NULL;
-       }
-       *dst = '\0';
-       return dst;
+       return mbdst + ret;
 }
 
 char *
-vis(char *dst, int c, int flag, int nextc)
+nvis(char *mbdst, size_t dlen, int c, int flags, int nextc)
 {
-       return invis(dst, NULL, c, flag, nextc);
-}
+       char cc[2];
+       int ret;
 
-char *
-nvis(char *dst, size_t dlen, int c, int flag, int nextc)
-{
-       return invis(dst, &dlen, c, flag, nextc);
-}
+       cc[0] = c;
+       cc[1] = nextc;
 
+       ret = istrsenvisx(mbdst, &dlen, cc, 1, flags, "", NULL);
+       if (ret < 0)
+               return NULL;
+       return mbdst + ret;
+}
 
 /*
- * strvis, strvisx - visually encode characters from src into dst
+ * strvis - visually encode characters from src into dst
  *
  *     Dst must be 4 times the size of src to account for possible
  *     expansion.  The length of dst, not including the trailing NULL,
  *     is returned.
- *
- *     Strvisx encodes exactly len bytes from src into dst.
- *     This is useful for encoding a block of data.
  */
-static int
-istrnvis(char *dst, size_t *dlen, const char *src, int flag)
-{
-       char *extra = NULL;
-       int rv;
-
-       MAKEEXTRALIST(flag, extra, "");
-       if (!extra) {
-               if (dlen && *dlen == 0) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-               *dst = '\0';            /* can't create extra, return "" */
-               return 0;
-       }
-       rv = istrsnvis(dst, dlen, src, flag, extra);
-       free(extra);
-       return rv;
-}
 
 int
-strvis(char *dst, const char *src, int flag)
+strvis(char *mbdst, const char *mbsrc, int flags)
 {
-       return istrnvis(dst, NULL, src, flag);
+       return istrsenvisx(mbdst, NULL, mbsrc, 0, flags, "", NULL);
 }
 
 int
-strnvis(char *dst, size_t dlen, const char *src, int flag)
+strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags)
 {
-       return istrnvis(dst, &dlen, src, flag);
+       return istrsenvisx(mbdst, &dlen, mbsrc, 0, flags, "", NULL);
 }
 
-static int
-istrnvisx(char *dst, size_t *dlen, const char *src, size_t len, int flag)
-{
-       char *extra = NULL;
-       int rv;
+/*
+ * strvisx - visually encode characters from src into dst
+ *
+ *     Dst must be 4 times the size of src to account for possible
+ *     expansion.  The length of dst, not including the trailing NULL,
+ *     is returned.
+ *
+ *     Strvisx encodes exactly len characters from src into dst.
+ *     This is useful for encoding a block of data.
+ */
 
-       MAKEEXTRALIST(flag, extra, "");
-       if (!extra) {
-               if (dlen && *dlen == 0) {
-                       errno = ENOSPC;
-                       return -1;
-               }
-               *dst = '\0';            /* can't create extra, return "" */
-               return 0;
-       }
-       rv = istrsnvisx(dst, dlen, src, len, flag, extra);
-       free(extra);
-       return rv;
+int
+strvisx(char *mbdst, const char *mbsrc, size_t len, int flags)
+{
+       return istrsenvisx(mbdst, NULL, mbsrc, len, flags, "", NULL);
 }
 
 int
-strvisx(char *dst, const char *src, size_t len, int flag)
+strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags)
 {
-       return istrnvisx(dst, NULL, src, len, flag);
+       return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", NULL);
 }
 
 int
-strnvisx(char *dst, size_t dlen, const char *src, size_t len, int flag)
+strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags,
+    int *cerr_ptr)
 {
-       return istrnvisx(dst, &dlen, src, len, flag);
+       return istrsenvisx(mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr);
 }
-
 #endif
index 298aa2a..93e758e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $NetBSD: vis.h,v 1.19 2011/03/12 19:52:45 christos Exp $        */
+/*     $NetBSD: vis.h,v 1.21 2013/02/20 17:01:15 christos Exp $        */
 
 /*-
  * Copyright (c) 1990, 1993
 /*
  * to select alternate encoding format
  */
-#define        VIS_OCTAL       0x00  /* use octal \ddd format */
-#define        VIS_CSTYLE      0x00  /* use \[nrft0..] where appropiate */
+#define        VIS_OCTAL       0x0001  /* use octal \ddd format */
+#define        VIS_CSTYLE      0x0002  /* use \[nrft0..] where appropiate */
 
 /*
  * to alter set of characters encoded (default is to encode all
  * non-graphic except space, tab, and newline).
  */
-#define        VIS_SP          0x00  /* also encode space */
-#define        VIS_TAB         0x00  /* also encode tab */
-#define        VIS_NL          0x010   /* also encode newline */
+#define        VIS_SP          0x0004  /* also encode space */
+#define        VIS_TAB         0x0008  /* also encode tab */
+#define        VIS_NL          0x0010  /* also encode newline */
 #define        VIS_WHITE       (VIS_SP | VIS_TAB | VIS_NL)
-#define        VIS_SAFE        0x020   /* only encode "unsafe" characters */
+#define        VIS_SAFE        0x0020  /* only encode "unsafe" characters */
 
 /*
  * other
  */
-#define        VIS_NOSLASH     0x040   /* inhibit printing '\' */
-#define        VIS_HTTP1808    0x080   /* http-style escape % hex hex */
-#define        VIS_HTTPSTYLE   0x080   /* http-style escape % hex hex */
-#define        VIS_MIMESTYLE   0x100   /* mime-style escape = HEX HEX */
-#define        VIS_HTTP1866    0x200   /* http-style &#num; or &string; */
-#define        VIS_NOESCAPE    0x400   /* don't decode `\' */
-#define        _VIS_END        0x800   /* for unvis */
+#define        VIS_NOSLASH     0x0040  /* inhibit printing '\' */
+#define        VIS_HTTP1808    0x0080  /* http-style escape % hex hex */
+#define        VIS_HTTPSTYLE   0x0080  /* http-style escape % hex hex */
+#define        VIS_MIMESTYLE   0x0100  /* mime-style escape = HEX HEX */
+#define        VIS_HTTP1866    0x0200  /* http-style &#num; or &string; */
+#define        VIS_NOESCAPE    0x0400  /* don't decode `\' */
+#define        _VIS_END        0x0800  /* for unvis */
+#define        VIS_GLOB        0x1000  /* encode glob(3) magic characters */
 
 /*
  * unvis return codes
@@ -90,9 +91,12 @@ int  strsnvis(char *, size_t, const char *, int, const char *);
 
 int    strvisx(char *, const char *, size_t, int);
 int    strnvisx(char *, size_t, const char *, size_t, int);
+int    strenvisx(char *, size_t, const char *, size_t, int, int *);
 
 int    strsvisx(char *, const char *, size_t, int, const char *);
 int    strsnvisx(char *, size_t, const char *, size_t, int, const char *);
+int    strsenvisx(char *, size_t, const char *, size_t , int, const char *,
+    int *);
 
 int    strunvis(char *, const char *);
 int    strnunvis(char *, size_t, const char *);