summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TEST/Makefile4
-rw-r--r--TEST/test_filecompletion.c553
-rw-r--r--chared.c22
-rw-r--r--chartype.c26
-rw-r--r--common.c12
-rw-r--r--editline.36
-rw-r--r--el.c30
-rw-r--r--el.h4
-rw-r--r--eln.c14
-rw-r--r--filecomplete.c324
-rw-r--r--hist.c8
-rw-r--r--history.c16
-rw-r--r--keymacro.c6
-rw-r--r--literal.c8
-rw-r--r--map.c12
-rw-r--r--parse.c8
-rw-r--r--read.c15
-rw-r--r--readline.c98
-rw-r--r--readline/readline.h21
-rw-r--r--refresh.c18
-rw-r--r--search.c10
-rw-r--r--terminal.c69
-rw-r--r--tty.c39
-rw-r--r--tty.h5
-rw-r--r--vi.c8
25 files changed, 1083 insertions, 253 deletions
diff --git a/TEST/Makefile b/TEST/Makefile
index 1f86d7144174..2e6f8250c3ff 100644
--- a/TEST/Makefile
+++ b/TEST/Makefile
@@ -1,7 +1,7 @@
-# $NetBSD: Makefile,v 1.7 2016/03/23 22:27:48 christos Exp $
+# $NetBSD: Makefile,v 1.8 2017/10/15 18:59:00 abhinav Exp $
NOMAN=1
-PROG=wtc1
+PROG=wtc1 test_filecompletion
CPPFLAGS=-I${.CURDIR}/..
LDADD+=-ledit -ltermlib
DPADD+=${LIBEDIT} ${LIBTERMLIB}
diff --git a/TEST/test_filecompletion.c b/TEST/test_filecompletion.c
new file mode 100644
index 000000000000..11335083df4c
--- /dev/null
+++ b/TEST/test_filecompletion.c
@@ -0,0 +1,553 @@
+/* $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $ */
+
+/*-
+ * Copyright (c) 2017 Abhinav Upadhyay <abhinav@NetBSD.org>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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"
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <histedit.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "filecomplete.h"
+#include "el.h"
+
+typedef struct {
+ const wchar_t *user_typed_text; /* The actual text typed by the user on the terminal */
+ const char *completion_function_input ; /*the text received by fn_filename_completion_function */
+ const char *expanded_text[2]; /* the value to which completion_function_input should be expanded */
+ const wchar_t *escaped_output; /* expected escaped value of expanded_text */
+} test_input;
+
+static test_input inputs[] = {
+ {
+ /* simple test for escaping angular brackets */
+ L"ls ang",
+ "ang",
+ {"ang<ular>test", NULL},
+ L"ls ang\\<ular\\>test "
+ },
+ {
+ /* test angular bracket inside double quotes: ls "dq_ang */
+ L"ls \"dq_ang",
+ "dq_ang",
+ {"dq_ang<ular>test", NULL},
+ L"ls \"dq_ang<ular>test\""
+ },
+ {
+ /* test angular bracket inside singlq quotes: ls "sq_ang */
+ L"ls 'sq_ang",
+ "sq_ang",
+ {"sq_ang<ular>test", NULL},
+ L"ls 'sq_ang<ular>test'"
+ },
+ {
+ /* simple test for backslash */
+ L"ls back",
+ "back",
+ {"backslash\\test", NULL},
+ L"ls backslash\\\\test "
+ },
+ {
+ /* backslash inside single quotes */
+ L"ls 'sback",
+ "sback",
+ {"sbackslash\\test", NULL},
+ L"ls 'sbackslash\\test'"
+ },
+ {
+ /* backslash inside double quotes */
+ L"ls \"dback",
+ "dback",
+ {"dbackslash\\test", NULL},
+ L"ls \"dbackslash\\\\test\""
+ },
+ {
+ /* test braces */
+ L"ls br",
+ "br",
+ {"braces{test}", NULL},
+ L"ls braces\\{test\\} "
+ },
+ {
+ /* test braces inside single quotes */
+ L"ls 'sbr",
+ "sbr",
+ {"sbraces{test}", NULL},
+ L"ls 'sbraces{test}'"
+ },
+ {
+ /* test braces inside double quotes */
+ L"ls \"dbr",
+ "dbr",
+ {"dbraces{test}", NULL},
+ L"ls \"dbraces{test}\""
+ },
+ {
+ /* test dollar */
+ L"ls doll",
+ "doll",
+ {"doll$artest", NULL},
+ L"ls doll\\$artest "
+ },
+ {
+ /* test dollar inside single quotes */
+ L"ls 'sdoll",
+ "sdoll",
+ {"sdoll$artest", NULL},
+ L"ls 'sdoll$artest'"
+ },
+ {
+ /* test dollar inside double quotes */
+ L"ls \"ddoll",
+ "ddoll",
+ {"ddoll$artest", NULL},
+ L"ls \"ddoll\\$artest\""
+ },
+ {
+ /* test equals */
+ L"ls eq",
+ "eq",
+ {"equals==test", NULL},
+ L"ls equals\\=\\=test "
+ },
+ {
+ /* test equals inside sinqle quotes */
+ L"ls 'seq",
+ "seq",
+ {"sequals==test", NULL},
+ L"ls 'sequals==test'"
+ },
+ {
+ /* test equals inside double quotes */
+ L"ls \"deq",
+ "deq",
+ {"dequals==test", NULL},
+ L"ls \"dequals==test\""
+ },
+ {
+ /* test \n */
+ L"ls new",
+ "new",
+ {"new\\nline", NULL},
+ L"ls new\\\\nline "
+ },
+ {
+ /* test \n inside single quotes */
+ L"ls 'snew",
+ "snew",
+ {"snew\nline", NULL},
+ L"ls 'snew\nline'"
+ },
+ {
+ /* test \n inside double quotes */
+ L"ls \"dnew",
+ "dnew",
+ {"dnew\nline", NULL},
+ L"ls \"dnew\nline\""
+ },
+ {
+ /* test single space */
+ L"ls spac",
+ "spac",
+ {"space test", NULL},
+ L"ls space\\ test "
+ },
+ {
+ /* test single space inside singlq quotes */
+ L"ls 's_spac",
+ "s_spac",
+ {"s_space test", NULL},
+ L"ls 's_space test'"
+ },
+ {
+ /* test single space inside double quotes */
+ L"ls \"d_spac",
+ "d_spac",
+ {"d_space test", NULL},
+ L"ls \"d_space test\""
+ },
+ {
+ /* test multiple spaces */
+ L"ls multi",
+ "multi",
+ {"multi space test", NULL},
+ L"ls multi\\ space\\ \\ test "
+ },
+ {
+ /* test multiple spaces inside single quotes */
+ L"ls 's_multi",
+ "s_multi",
+ {"s_multi space test", NULL},
+ L"ls 's_multi space test'"
+ },
+ {
+ /* test multiple spaces inside double quotes */
+ L"ls \"d_multi",
+ "d_multi",
+ {"d_multi space test", NULL},
+ L"ls \"d_multi space test\""
+ },
+ {
+ /* test double quotes */
+ L"ls doub",
+ "doub",
+ {"doub\"quotes", NULL},
+ L"ls doub\\\"quotes "
+ },
+ {
+ /* test double quotes inside single quotes */
+ L"ls 's_doub",
+ "s_doub",
+ {"s_doub\"quotes", NULL},
+ L"ls 's_doub\"quotes'"
+ },
+ {
+ /* test double quotes inside double quotes */
+ L"ls \"d_doub",
+ "d_doub",
+ {"d_doub\"quotes", NULL},
+ L"ls \"d_doub\\\"quotes\""
+ },
+ {
+ /* test multiple double quotes */
+ L"ls mud",
+ "mud",
+ {"mud\"qu\"otes\"", NULL},
+ L"ls mud\\\"qu\\\"otes\\\" "
+ },
+ {
+ /* test multiple double quotes inside single quotes */
+ L"ls 'smud",
+ "smud",
+ {"smud\"qu\"otes\"", NULL},
+ L"ls 'smud\"qu\"otes\"'"
+ },
+ {
+ /* test multiple double quotes inside double quotes */
+ L"ls \"dmud",
+ "dmud",
+ {"dmud\"qu\"otes\"", NULL},
+ L"ls \"dmud\\\"qu\\\"otes\\\"\""
+ },
+ {
+ /* test one single quote */
+ L"ls sing",
+ "sing",
+ {"single'quote", NULL},
+ L"ls single\\'quote "
+ },
+ {
+ /* test one single quote inside single quote */
+ L"ls 'ssing",
+ "ssing",
+ {"ssingle'quote", NULL},
+ L"ls 'ssingle'\\''quote'"
+ },
+ {
+ /* test one single quote inside double quote */
+ L"ls \"dsing",
+ "dsing",
+ {"dsingle'quote", NULL},
+ L"ls \"dsingle'quote\""
+ },
+ {
+ /* test multiple single quotes */
+ L"ls mu_sing",
+ "mu_sing",
+ {"mu_single''quotes''", NULL},
+ L"ls mu_single\\'\\'quotes\\'\\' "
+ },
+ {
+ /* test multiple single quotes inside single quote */
+ L"ls 'smu_sing",
+ "smu_sing",
+ {"smu_single''quotes''", NULL},
+ L"ls 'smu_single'\\'''\\''quotes'\\\'''\\'''"
+ },
+ {
+ /* test multiple single quotes inside double quote */
+ L"ls \"dmu_sing",
+ "dmu_sing",
+ {"dmu_single''quotes''", NULL},
+ L"ls \"dmu_single''quotes''\""
+ },
+ {
+ /* test parenthesis */
+ L"ls paren",
+ "paren",
+ {"paren(test)", NULL},
+ L"ls paren\\(test\\) "
+ },
+ {
+ /* test parenthesis inside single quote */
+ L"ls 'sparen",
+ "sparen",
+ {"sparen(test)", NULL},
+ L"ls 'sparen(test)'"
+ },
+ {
+ /* test parenthesis inside double quote */
+ L"ls \"dparen",
+ "dparen",
+ {"dparen(test)", NULL},
+ L"ls \"dparen(test)\""
+ },
+ {
+ /* test pipe */
+ L"ls pip",
+ "pip",
+ {"pipe|test", NULL},
+ L"ls pipe\\|test "
+ },
+ {
+ /* test pipe inside single quote */
+ L"ls 'spip",
+ "spip",
+ {"spipe|test", NULL},
+ L"ls 'spipe|test'",
+ },
+ {
+ /* test pipe inside double quote */
+ L"ls \"dpip",
+ "dpip",
+ {"dpipe|test", NULL},
+ L"ls \"dpipe|test\""
+ },
+ {
+ /* test tab */
+ L"ls ta",
+ "ta",
+ {"tab\ttest", NULL},
+ L"ls tab\\\ttest "
+ },
+ {
+ /* test tab inside single quote */
+ L"ls 'sta",
+ "sta",
+ {"stab\ttest", NULL},
+ L"ls 'stab\ttest'"
+ },
+ {
+ /* test tab inside double quote */
+ L"ls \"dta",
+ "dta",
+ {"dtab\ttest", NULL},
+ L"ls \"dtab\ttest\""
+ },
+ {
+ /* test back tick */
+ L"ls tic",
+ "tic",
+ {"tick`test`", NULL},
+ L"ls tick\\`test\\` "
+ },
+ {
+ /* test back tick inside single quote */
+ L"ls 'stic",
+ "stic",
+ {"stick`test`", NULL},
+ L"ls 'stick`test`'"
+ },
+ {
+ /* test back tick inside double quote */
+ L"ls \"dtic",
+ "dtic",
+ {"dtick`test`", NULL},
+ L"ls \"dtick\\`test\\`\""
+ },
+ {
+ /* test for @ */
+ L"ls at",
+ "at",
+ {"atthe@rate", NULL},
+ L"ls atthe\\@rate "
+ },
+ {
+ /* test for @ inside single quote */
+ L"ls 'sat",
+ "sat",
+ {"satthe@rate", NULL},
+ L"ls 'satthe@rate'"
+ },
+ {
+ /* test for @ inside double quote */
+ L"ls \"dat",
+ "dat",
+ {"datthe@rate", NULL},
+ L"ls \"datthe@rate\""
+ },
+ {
+ /* test ; */
+ L"ls semi",
+ "semi",
+ {"semi;colon;test", NULL},
+ L"ls semi\\;colon\\;test "
+ },
+ {
+ /* test ; inside single quote */
+ L"ls 'ssemi",
+ "ssemi",
+ {"ssemi;colon;test", NULL},
+ L"ls 'ssemi;colon;test'"
+ },
+ {
+ /* test ; inside double quote */
+ L"ls \"dsemi",
+ "dsemi",
+ {"dsemi;colon;test", NULL},
+ L"ls \"dsemi;colon;test\""
+ },
+ {
+ /* test & */
+ L"ls amp",
+ "amp",
+ {"ampers&and", NULL},
+ L"ls ampers\\&and "
+ },
+ {
+ /* test & inside single quote */
+ L"ls 'samp",
+ "samp",
+ {"sampers&and", NULL},
+ L"ls 'sampers&and'"
+ },
+ {
+ /* test & inside double quote */
+ L"ls \"damp",
+ "damp",
+ {"dampers&and", NULL},
+ L"ls \"dampers&and\""
+ },
+ {
+ /* test completion when cursor at \ */
+ L"ls foo\\",
+ "foo",
+ {"foo bar", NULL},
+ L"ls foo\\ bar "
+ },
+ {
+ /* test completion when cursor at single quote */
+ L"ls foo'",
+ "foo'",
+ {"foo bar", NULL},
+ L"ls foo\\ bar "
+ },
+ {
+ /* test completion when cursor at double quote */
+ L"ls foo\"",
+ "foo\"",
+ {"foo bar", NULL},
+ L"ls foo\\ bar "
+ },
+ {
+ /* test multiple completion matches */
+ L"ls fo",
+ "fo",
+ {"foo bar", "foo baz"},
+ L"ls foo\\ ba"
+ },
+ {
+ L"ls ba",
+ "ba",
+ {"bar <bar>", "bar <baz>"},
+ L"ls bar\\ \\<ba"
+ }
+};
+
+static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
+
+/*
+ * Custom completion function passed to fn_complet, NULLe.
+ * The function returns hardcoded completion matches
+ * based on the test cases present in inputs[] (above)
+ */
+static char *
+mycomplet_func(const char *text, int index)
+{
+ static int last_index = 0;
+ size_t i = 0;
+ if (last_index == 2) {
+ last_index = 0;
+ return NULL;
+ }
+
+ for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
+ if (strcmp(text, inputs[i].completion_function_input) == 0) {
+ if (inputs[i].expanded_text[last_index] != NULL)
+ return strdup(inputs[i].expanded_text[last_index++]);
+ else {
+ last_index = 0;
+ return NULL;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+int
+main(int argc, char **argv)
+{
+ EditLine *el = el_init(argv[0], stdin, stdout, stderr);
+ size_t i;
+ size_t input_len;
+ el_line_t line;
+ wchar_t *buffer = malloc(64 * sizeof(*buffer));
+ if (buffer == NULL)
+ err(EXIT_FAILURE, "malloc failed");
+
+ for (i = 0; i < sizeof(inputs)/sizeof(inputs[0]); i++) {
+ memset(buffer, 0, 64 * sizeof(*buffer));
+ input_len = wcslen(inputs[i].user_typed_text);
+ wmemcpy(buffer, inputs[i].user_typed_text, input_len);
+ buffer[input_len] = 0;
+ line.buffer = buffer;
+ line.cursor = line.buffer + input_len ;
+ line.lastchar = line.cursor - 1;
+ line.limit = line.buffer + 64 * sizeof(*buffer);
+ el->el_line = line;
+ fn_complete(el, mycomplet_func, NULL, break_chars, NULL, NULL, 10, NULL, NULL, NULL, NULL);
+
+ /*
+ * fn_complete would have expanded and escaped the input in el->el_line.buffer.
+ * We need to assert that it matches with the expected value in our test data
+ */
+ printf("User input: %ls\t Expected output: %ls\t Generated output: %ls\n",
+ inputs[i].user_typed_text, inputs[i].escaped_output, el->el_line.buffer);
+ assert(wcscmp(el->el_line.buffer, inputs[i].escaped_output) == 0);
+ }
+ el_end(el);
+ return 0;
+
+}
diff --git a/chared.c b/chared.c
index 9d46ba68feea..a96322aa6883 100644
--- a/chared.c
+++ b/chared.c
@@ -1,4 +1,4 @@
-/* $NetBSD: chared.c,v 1.56 2016/05/22 19:44:26 christos Exp $ */
+/* $NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 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.56 2016/05/22 19:44:26 christos Exp $");
+__RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -174,7 +174,7 @@ c_delbefore(EditLine *el, int num)
wchar_t *cp;
for (cp = el->el_line.cursor - num;
- cp <= el->el_line.lastchar;
+ &cp[num] <= el->el_line.lastchar;
cp++)
*cp = cp[num];
@@ -396,26 +396,22 @@ cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
libedit_private int
ch_init(EditLine *el)
{
- el->el_line.buffer = el_malloc(EL_BUFSIZ *
+ el->el_line.buffer = el_calloc(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 *
+ el->el_chared.c_undo.buf = el_calloc(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 *
+ el->el_chared.c_redo.buf = el_calloc(EL_BUFSIZ,
sizeof(*el->el_chared.c_redo.buf));
if (el->el_chared.c_redo.buf == NULL)
return -1;
@@ -426,12 +422,10 @@ ch_init(EditLine *el)
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 *
+ el->el_chared.c_kill.buf = el_calloc(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;
@@ -591,7 +585,7 @@ ch_end(EditLine *el)
/* el_insertstr():
- * Insert string at cursorI
+ * Insert string at cursor
*/
int
el_winsertstr(EditLine *el, const wchar_t *s)
diff --git a/chartype.c b/chartype.c
index 9288e6b7db26..3df4af69b51a 100644
--- a/chartype.c
+++ b/chartype.c
@@ -1,4 +1,4 @@
-/* $NetBSD: chartype.c,v 1.31 2017/01/09 02:54:18 christos Exp $ */
+/* $NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -31,10 +31,11 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: chartype.c,v 1.31 2017/01/09 02:54:18 christos Exp $");
+__RCSID("$NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $");
#endif /* not lint && not SCCSID */
#include <ctype.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
@@ -156,7 +157,7 @@ ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1)
return NULL;
- wargv = el_malloc((size_t)(argc + 1) * sizeof(*wargv));
+ wargv = el_calloc((size_t)(argc + 1), sizeof(*wargv));
for (i = 0, p = conv->wbuff; i < argc; ++i) {
if (!argv[i]) { /* don't pass null pointers to mbstowcs */
@@ -183,17 +184,14 @@ ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
libedit_private size_t
ct_enc_width(wchar_t 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 */
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ size_t size;
+ memset(&mbs, 0, sizeof(mbs));
+
+ if ((size = wcrtomb(buf, c, &mbs)) == (size_t)-1)
+ return 0;
+ return size;
}
libedit_private ssize_t
diff --git a/common.c b/common.c
index 270860510b80..bc6c057cf51d 100644
--- a/common.c
+++ b/common.c
@@ -1,4 +1,4 @@
-/* $NetBSD: common.c,v 1.47 2016/05/22 19:44:26 christos Exp $ */
+/* $NetBSD: common.c,v 1.48 2018/02/26 17:36:14 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: common.c,v 1.47 2016/05/22 19:44:26 christos Exp $");
+__RCSID("$NetBSD: common.c,v 1.48 2018/02/26 17:36:14 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -363,15 +363,17 @@ ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* [^V] [^V]
*/
libedit_private el_action_t
-ed_quoted_insert(EditLine *el, wint_t c)
+/*ARGSUSED*/
+ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__)))
{
int num;
+ wchar_t ch;
tty_quotemode(el);
- num = el_wgetc(el, &c);
+ num = el_wgetc(el, &ch);
tty_noquotemode(el);
if (num == 1)
- return ed_insert(el, c);
+ return ed_insert(el, ch);
else
return ed_end_of_file(el, 0);
}
diff --git a/editline.3 b/editline.3
index 91788af1d653..feec9a6cac25 100644
--- a/editline.3
+++ b/editline.3
@@ -1,4 +1,4 @@
-.\" $NetBSD: editline.3,v 1.98 2017/09/02 06:48:10 wiz Exp $
+.\" $NetBSD: editline.3,v 1.99 2018/11/18 17:09:39 christos Exp $
.\"
.\" Copyright (c) 1997-2014 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -26,7 +26,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd September 1, 2017
+.Dd November 9, 2018
.Dt EDITLINE 3
.Os
.Sh NAME
@@ -181,8 +181,6 @@ library respects the
locale set by the application program and never uses
.Xr setlocale 3
to change the locale.
-The only locales supported are UTF-8 and the default C or POSIX locale.
-If any other locale is set, behaviour is undefined.
.Sh LINE EDITING FUNCTIONS
The line editing functions use a common data structure,
.Fa EditLine ,
diff --git a/el.c b/el.c
index f0cb6941f086..9ae7af3533d3 100644
--- a/el.c
+++ b/el.c
@@ -1,4 +1,4 @@
-/* $NetBSD: el.c,v 1.95 2017/09/05 18:07:59 christos Exp $ */
+/* $NetBSD: el.c,v 1.99 2019/07/23 10:18:52 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.95 2017/09/05 18:07:59 christos Exp $");
+__RCSID("$NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -71,13 +71,11 @@ libedit_private EditLine *
el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
int fdin, int fdout, int fderr, int flags)
{
- EditLine *el = el_malloc(sizeof(*el));
+ EditLine *el = el_calloc(1, sizeof(*el));
if (el == NULL)
return NULL;
- memset(el, 0, sizeof(EditLine));
-
el->el_infile = fin;
el->el_outfile = fout;
el->el_errfile = ferr;
@@ -96,10 +94,6 @@ el_init_internal(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
* Initialize all the modules. Order is important!!!
*/
el->el_flags = flags;
- if (setlocale(LC_CTYPE, NULL) != NULL){
- if (strcmp(nl_langinfo(CODESET), "UTF-8") == 0)
- el->el_flags |= CHARSET_IS_UTF8;
- }
if (terminal_init(el) == -1) {
el_free(el->el_prog);
@@ -146,7 +140,7 @@ el_end(EditLine *el)
keymacro_end(el);
map_end(el);
if (!(el->el_flags & NO_TTY))
- tty_end(el);
+ tty_end(el, TCSAFLUSH);
ch_end(el);
read_end(el->el_read);
search_end(el);
@@ -301,7 +295,7 @@ el_wset(EditLine *el, int op, ...)
void *ptr = va_arg(ap, void *);
rv = hist_set(el, func, ptr);
- if (!(el->el_flags & CHARSET_IS_UTF8))
+ if (MB_CUR_MAX == 1)
el->el_flags &= ~NARROW_HISTORY;
break;
}
@@ -443,15 +437,11 @@ el_wget(EditLine *el, int op, ...)
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;
-
+ char *argv[3];
argv[0] = name;
- rv = terminal_gettc(el, i, argv);
+ argv[1] = va_arg(ap, char *);
+ argv[2] = va_arg(ap, void *);
+ rv = terminal_gettc(el, 3, argv);
break;
}
@@ -542,7 +532,7 @@ el_source(EditLine *el, const char *fname)
if ((ptr = getenv("HOME")) == NULL)
return -1;
plen += strlen(ptr);
- if ((path = el_malloc(plen * sizeof(*path))) == NULL)
+ if ((path = el_calloc(plen, sizeof(*path))) == NULL)
return -1;
(void)snprintf(path, plen, "%s%s", ptr,
elpath + (*ptr == '\0'));
diff --git a/el.h b/el.h
index eb95a3ed9e8b..b0d174eb62f6 100644
--- a/el.h
+++ b/el.h
@@ -1,4 +1,4 @@
-/* $NetBSD: el.h,v 1.43 2017/09/05 18:07:59 christos Exp $ */
+/* $NetBSD: el.h,v 1.45 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -55,7 +55,6 @@
#define NO_TTY 0x02
#define EDIT_DISABLED 0x04
#define UNBUFFERED 0x08
-#define CHARSET_IS_UTF8 0x10
#define NARROW_HISTORY 0x40
#define NO_RESET 0x80
@@ -90,6 +89,7 @@ typedef struct el_state_t {
* Until we come up with something better...
*/
#define el_malloc(a) malloc(a)
+#define el_calloc(a,b) calloc(a, b)
#define el_realloc(a,b) realloc(a, b)
#define el_free(a) free(a)
diff --git a/eln.c b/eln.c
index aa0a5b565dd7..e980bc5f9d2f 100644
--- a/eln.c
+++ b/eln.c
@@ -1,4 +1,4 @@
-/* $NetBSD: eln.c,v 1.34 2016/05/09 21:37:34 christos Exp $ */
+/* $NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: eln.c,v 1.34 2016/05/09 21:37:34 christos Exp $");
+__RCSID("$NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $");
#endif /* not lint && not SCCSID */
#include <errno.h>
@@ -321,14 +321,12 @@ el_get(EditLine *el, int op, ...)
break;
case EL_GETTC: {
- char *argv[20];
+ char *argv[3];
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);
+ argv[1] = va_arg(ap, char *);
+ argv[2] = va_arg(ap, void *);
+ ret = terminal_gettc(el, 3, argv);
break;
}
diff --git a/filecomplete.c b/filecomplete.c
index 6ccc2719b8ab..8dd14c7f2d44 100644
--- a/filecomplete.c
+++ b/filecomplete.c
@@ -1,4 +1,4 @@
-/* $NetBSD: filecomplete.c,v 1.45 2017/04/21 05:38:03 abhinav Exp $ */
+/* $NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 abhinav Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: filecomplete.c,v 1.45 2017/04/21 05:38:03 abhinav Exp $");
+__RCSID("$NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 abhinav Exp $");
#endif /* not lint && not SCCSID */
#include <sys/types.h>
@@ -83,7 +83,7 @@ fn_tilde_expand(const char *txt)
} else {
/* text until string after slash */
len = (size_t)(temp - txt + 1);
- temp = el_malloc(len * sizeof(*temp));
+ temp = el_calloc(len, sizeof(*temp));
if (temp == NULL)
return NULL;
(void)strncpy(temp, txt + 1, len - 2);
@@ -118,7 +118,7 @@ fn_tilde_expand(const char *txt)
txt += len;
len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
- temp = el_malloc(len * sizeof(*temp));
+ temp = el_calloc(len, sizeof(*temp));
if (temp == NULL)
return NULL;
(void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt);
@@ -126,6 +126,192 @@ fn_tilde_expand(const char *txt)
return temp;
}
+static int
+needs_escaping(char c)
+{
+ switch (c) {
+ case '\'':
+ case '"':
+ case '(':
+ case ')':
+ case '\\':
+ case '<':
+ case '>':
+ case '$':
+ case '#':
+ case ' ':
+ case '\n':
+ case '\t':
+ case '?':
+ case ';':
+ case '`':
+ case '@':
+ case '=':
+ case '|':
+ case '{':
+ case '}':
+ case '&':
+ case '*':
+ case '[':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+needs_dquote_escaping(char c)
+{
+ switch (c) {
+ case '"':
+ case '\\':
+ case '`':
+ case '$':
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+
+static wchar_t *
+unescape_string(const wchar_t *string, size_t length)
+{
+ size_t i;
+ size_t j = 0;
+ wchar_t *unescaped = el_calloc(length + 1, sizeof(*string));
+ if (unescaped == NULL)
+ return NULL;
+ for (i = 0; i < length ; i++) {
+ if (string[i] == '\\')
+ continue;
+ unescaped[j++] = string[i];
+ }
+ unescaped[j] = 0;
+ return unescaped;
+}
+
+static char *
+escape_filename(EditLine * el, const char *filename, int single_match,
+ const char *(*app_func)(const char *))
+{
+ size_t original_len = 0;
+ size_t escaped_character_count = 0;
+ size_t offset = 0;
+ size_t newlen;
+ const char *s;
+ char c;
+ size_t s_quoted = 0; /* does the input contain a single quote */
+ size_t d_quoted = 0; /* does the input contain a double quote */
+ char *escaped_str;
+ wchar_t *temp = el->el_line.buffer;
+ const char *append_char = NULL;
+
+ if (filename == NULL)
+ return NULL;
+
+ while (temp != el->el_line.cursor) {
+ /*
+ * If we see a single quote but have not seen a double quote
+ * so far set/unset s_quote
+ */
+ if (temp[0] == '\'' && !d_quoted)
+ s_quoted = !s_quoted;
+ /*
+ * vice versa to the above condition
+ */
+ else if (temp[0] == '"' && !s_quoted)
+ d_quoted = !d_quoted;
+ temp++;
+ }
+
+ /* Count number of special characters so that we can calculate
+ * number of extra bytes needed in the new string
+ */
+ for (s = filename; *s; s++, original_len++) {
+ c = *s;
+ /* Inside a single quote only single quotes need escaping */
+ if (s_quoted && c == '\'') {
+ escaped_character_count += 3;
+ continue;
+ }
+ /* Inside double quotes only ", \, ` and $ need escaping */
+ if (d_quoted && needs_dquote_escaping(c)) {
+ escaped_character_count++;
+ continue;
+ }
+ if (!s_quoted && !d_quoted && needs_escaping(c))
+ escaped_character_count++;
+ }
+
+ newlen = original_len + escaped_character_count + 1;
+ if (s_quoted || d_quoted)
+ newlen++;
+
+ if (single_match && app_func)
+ newlen++;
+
+ if ((escaped_str = el_malloc(newlen)) == NULL)
+ return NULL;
+
+ for (s = filename; *s; s++) {
+ c = *s;
+ if (!needs_escaping(c)) {
+ /* no escaping is required continue as usual */
+ escaped_str[offset++] = c;
+ continue;
+ }
+
+ /* single quotes inside single quotes require special handling */
+ if (c == '\'' && s_quoted) {
+ escaped_str[offset++] = '\'';
+ escaped_str[offset++] = '\\';
+ escaped_str[offset++] = '\'';
+ escaped_str[offset++] = '\'';
+ continue;
+ }
+
+ /* Otherwise no escaping needed inside single quotes */
+ if (s_quoted) {
+ escaped_str[offset++] = c;
+ continue;
+ }
+
+ /* No escaping needed inside a double quoted string either
+ * unless we see a '$', '\', '`', or '"' (itself)
+ */
+ if (d_quoted && !needs_dquote_escaping(c)) {
+ escaped_str[offset++] = c;
+ continue;
+ }
+
+ /* If we reach here that means escaping is actually needed */
+ escaped_str[offset++] = '\\';
+ escaped_str[offset++] = c;
+ }
+
+ if (single_match && app_func) {
+ escaped_str[offset] = 0;
+ append_char = app_func(escaped_str);
+ /* we want to append space only if we are not inside quotes */
+ if (append_char[0] == ' ') {
+ if (!s_quoted && !d_quoted)
+ escaped_str[offset++] = append_char[0];
+ } else
+ escaped_str[offset++] = append_char[0];
+ }
+
+ /* close the quotes if single match and the match is not a directory */
+ if (single_match && (append_char && append_char[0] == ' ')) {
+ if (s_quoted)
+ escaped_str[offset++] = '\'';
+ else if (d_quoted)
+ escaped_str[offset++] = '"';
+ }
+
+ escaped_str[offset] = 0;
+ return escaped_str;
+}
/*
* return first found file name starting by the ``text'' or NULL if no
@@ -242,7 +428,7 @@ fn_filename_completion_function(const char *text, int state)
#endif
len = strlen(dirname) + len + 1;
- temp = el_malloc(len * sizeof(*temp));
+ temp = el_calloc(len, sizeof(*temp));
if (temp == NULL)
return NULL;
(void)snprintf(temp, len, "%s%s", dirname, entry->d_name);
@@ -318,7 +504,7 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int))
max_equal = i;
}
- retstr = el_malloc((max_equal + 1) * sizeof(*retstr));
+ retstr = el_calloc(max_equal + 1, sizeof(*retstr));
if (retstr == NULL) {
el_free(match_list);
return NULL;
@@ -370,7 +556,7 @@ fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width,
* 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);
+ cols = (size_t)screenwidth / (width + 2);
if (cols == 0)
cols = 1;
@@ -390,7 +576,7 @@ fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width,
break;
(void)fprintf(el->el_outfile, "%s%s%s",
col == 0 ? "" : " ", matches[thisguy],
- append_char_function(matches[thisguy]));
+ (*app_func)(matches[thisguy]));
(void)fprintf(el->el_outfile, "%-*s",
(int) (width - strlen(matches[thisguy])), "");
}
@@ -398,6 +584,60 @@ fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width,
}
}
+static wchar_t *
+find_word_to_complete(const wchar_t * cursor, const wchar_t * buffer,
+ const wchar_t * word_break, const wchar_t * special_prefixes, size_t * length)
+{
+ /* We now look backwards for the start of a filename/variable word */
+ const wchar_t *ctemp = cursor;
+ size_t len;
+
+ /* if the cursor is placed at a slash or a quote, we need to find the
+ * word before it
+ */
+ if (ctemp > buffer) {
+ switch (ctemp[-1]) {
+ case '\\':
+ case '\'':
+ case '"':
+ ctemp--;
+ break;
+ default:
+ break;
+ }
+ }
+
+ for (;;) {
+ if (ctemp <= buffer)
+ break;
+ if (wcschr(word_break, ctemp[-1])) {
+ if (ctemp - buffer >= 2 && ctemp[-2] == '\\') {
+ ctemp -= 2;
+ continue;
+ } else if (ctemp - buffer >= 2 &&
+ (ctemp[-2] == '\'' || ctemp[-2] == '"')) {
+ ctemp--;
+ continue;
+ } else
+ break;
+ }
+ if (special_prefixes && wcschr(special_prefixes, ctemp[-1]))
+ break;
+ ctemp--;
+ }
+
+ len = (size_t) (cursor - ctemp);
+ if (len == 1 && (ctemp[0] == '\'' || ctemp[0] == '"')) {
+ len = 0;
+ ctemp++;
+ }
+ *length = len;
+ wchar_t *unescaped_word = unescape_string(ctemp, len);
+ if (unescaped_word == NULL)
+ return NULL;
+ return unescaped_word;
+}
+
/*
* Complete the word at or before point,
* 'what_to_do' says what to do with the completion.
@@ -420,8 +660,8 @@ fn_complete(EditLine *el,
{
const LineInfoW *li;
wchar_t *temp;
- char **matches;
- const wchar_t *ctemp;
+ char **matches;
+ char *completion;
size_t len;
int what_to_do = '\t';
int retval = CC_NORM;
@@ -438,18 +678,11 @@ fn_complete(EditLine *el,
if (!app_func)
app_func = append_char_function;
- /* We now look backwards for the start of a filename/variable word */
li = el_wline(el);
- ctemp = li->cursor;
- while (ctemp > li->buffer
- && !wcschr(word_break, ctemp[-1])
- && (!special_prefixes || !wcschr(special_prefixes, ctemp[-1]) ) )
- ctemp--;
-
- len = (size_t)(li->cursor - ctemp);
- temp = el_malloc((len + 1) * sizeof(*temp));
- (void)wcsncpy(temp, ctemp, len);
- temp[len] = '\0';
+ temp = find_word_to_complete(li->cursor,
+ li->buffer, word_break, special_prefixes, &len);
+ if (temp == NULL)
+ goto out;
/* these can be used by function called in completion_matches() */
/* or (*attempted_completion_function)() */
@@ -476,30 +709,41 @@ fn_complete(EditLine *el,
if (matches) {
int i;
size_t matches_num, maxlen, match_len, match_display=1;
+ int single_match = matches[2] == NULL &&
+ (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0);
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);
- el_winsertstr(el,
- ct_decode_string(matches[0], &el->el_scratch));
+ el_deletestr(el, (int)len);
+ if (!attempted_completion_function)
+ completion = escape_filename(el, matches[0],
+ single_match, app_func);
+ else
+ completion = strdup(matches[0]);
+ if (completion == NULL)
+ goto out;
+ if (single_match) {
+ /* We found exact match. Add a space after it,
+ * unless we do filename completion and the
+ * object is a directory. Also do necessary
+ * escape quoting
+ */
+ el_winsertstr(el,
+ ct_decode_string(completion, &el->el_scratch));
+ } else {
+ /* Only replace the completed string with
+ * common part of possible matches if there is
+ * possible completion.
+ */
+ el_winsertstr(el,
+ ct_decode_string(completion, &el->el_scratch));
+ }
+ free(completion);
}
- 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
- * object is a directory.
- */
- el_winsertstr(el,
- ct_decode_string((*app_func)(matches[0]),
- &el->el_scratch));
- } else if (what_to_do == '!' || what_to_do == '?') {
+ if (!single_match && (what_to_do == '!' || what_to_do == '?')) {
/*
* More than one match and requested to list possible
* matches.
@@ -562,6 +806,8 @@ fn_complete(EditLine *el,
el_free(matches);
matches = NULL;
}
+
+out:
el_free(temp);
return retval;
}
diff --git a/hist.c b/hist.c
index 3c9db7dcbe71..19ce1c161722 100644
--- a/hist.c
+++ b/hist.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hist.c,v 1.32 2017/03/05 19:23:58 christos Exp $ */
+/* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: hist.c,v 1.32 2017/03/05 19:23:58 christos Exp $");
+__RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -59,10 +59,10 @@ 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;
+ el->el_history.buf = el_calloc(EL_BUFSIZ, sizeof(*el->el_history.buf));
if (el->el_history.buf == NULL)
return -1;
+ el->el_history.sz = EL_BUFSIZ;
el->el_history.last = el->el_history.buf;
return 0;
}
diff --git a/history.c b/history.c
index 47cff4d167eb..227f72c4a102 100644
--- a/history.c
+++ b/history.c
@@ -1,4 +1,4 @@
-/* $NetBSD: history.c,v 1.58 2017/09/01 10:19:10 christos Exp $ */
+/* $NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: history.c,v 1.58 2017/09/01 10:19:10 christos Exp $");
+__RCSID("$NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -775,6 +775,7 @@ history_load(TYPE(History) *h, const char *fname)
char *ptr;
int i = -1;
TYPE(HistEvent) ev;
+ Char *decode_result;
#ifndef NARROWCHAR
static ct_buffer_t conv;
#endif
@@ -807,7 +808,10 @@ history_load(TYPE(History) *h, const char *fname)
ptr = nptr;
}
(void) strunvis(ptr, line);
- if (HENTER(h, &ev, ct_decode_string(ptr, &conv)) == -1) {
+ decode_result = ct_decode_string(ptr, &conv);
+ if (decode_result == NULL)
+ continue;
+ if (HENTER(h, &ev, decode_result) == -1) {
i = -1;
goto oomem;
}
@@ -1082,11 +1086,13 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
break;
case H_NSAVE_FP:
- retval = history_save_fp(h, va_arg(va, size_t),
- va_arg(va, FILE *));
+ {
+ size_t sz = va_arg(va, size_t);
+ retval = history_save_fp(h, sz, 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));
diff --git a/keymacro.c b/keymacro.c
index 13d208930e6b..cef24a1752e6 100644
--- a/keymacro.c
+++ b/keymacro.c
@@ -1,4 +1,4 @@
-/* $NetBSD: keymacro.c,v 1.23 2016/05/24 15:00:45 christos Exp $ */
+/* $NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: keymacro.c,v 1.23 2016/05/24 15:00:45 christos Exp $");
+__RCSID("$NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -105,7 +105,7 @@ libedit_private int
keymacro_init(EditLine *el)
{
- el->el_keymacro.buf = el_malloc(KEY_BUFSIZ *
+ el->el_keymacro.buf = el_calloc(KEY_BUFSIZ,
sizeof(*el->el_keymacro.buf));
if (el->el_keymacro.buf == NULL)
return -1;
diff --git a/literal.c b/literal.c
index 6c2496f2f044..f6eac26937e8 100644
--- a/literal.c
+++ b/literal.c
@@ -1,4 +1,4 @@
-/* $NetBSD: literal.c,v 1.3 2017/06/30 20:26:52 kre Exp $ */
+/* $NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $ */
/*-
* Copyright (c) 2017 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
-__RCSID("$NetBSD: literal.c,v 1.3 2017/06/30 20:26:52 kre Exp $");
+__RCSID("$NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $");
#endif /* not lint && not SCCSID */
/*
@@ -98,8 +98,8 @@ literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp)
return 0;
for (n = 0, i = 0; i < len; i++)
- n += ct_encode_char(b + n, w - n, buf[i]);
- n += ct_encode_char(b + n, w - n, end[1]);
+ n += ct_encode_char(b + n, (size_t)(w - n), buf[i]);
+ n += ct_encode_char(b + n, (size_t)(w - n), end[1]);
b[n] = '\0';
/*
diff --git a/map.c b/map.c
index f72d2724a81e..0c489593335a 100644
--- a/map.c
+++ b/map.c
@@ -1,4 +1,4 @@
-/* $NetBSD: map.c,v 1.51 2016/05/09 21:46:56 christos Exp $ */
+/* $NetBSD: map.c,v 1.52 2019/07/23 10:18:52 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.51 2016/05/09 21:46:56 christos Exp $");
+__RCSID("$NetBSD: map.c,v 1.52 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -913,21 +913,21 @@ map_init(EditLine *el)
EL_ABORT((el->errfile, "Vi insert map incorrect\n"));
#endif
- el->el_map.alt = el_malloc(sizeof(*el->el_map.alt) * N_KEYS);
+ el->el_map.alt = el_calloc(N_KEYS, sizeof(*el->el_map.alt));
if (el->el_map.alt == NULL)
return -1;
- el->el_map.key = el_malloc(sizeof(*el->el_map.key) * N_KEYS);
+ el->el_map.key = el_calloc(N_KEYS, sizeof(*el->el_map.key));
if (el->el_map.key == NULL)
return -1;
el->el_map.emacs = el_map_emacs;
el->el_map.vic = el_map_vi_command;
el->el_map.vii = el_map_vi_insert;
- el->el_map.help = el_malloc(sizeof(*el->el_map.help) * EL_NUM_FCNS);
+ el->el_map.help = el_calloc(EL_NUM_FCNS, sizeof(*el->el_map.help));
if (el->el_map.help == NULL)
return -1;
(void) memcpy(el->el_map.help, el_func_help,
sizeof(*el->el_map.help) * EL_NUM_FCNS);
- el->el_map.func = el_malloc(sizeof(*el->el_map.func) * EL_NUM_FCNS);
+ el->el_map.func = el_calloc(EL_NUM_FCNS, sizeof(*el->el_map.func));
if (el->el_map.func == NULL)
return -1;
memcpy(el->el_map.func, el_func, sizeof(*el->el_map.func)
diff --git a/parse.c b/parse.c
index fdd0d847a79d..2620f41eb1c8 100644
--- a/parse.c
+++ b/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.40 2016/05/09 21:46:56 christos Exp $ */
+/* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: parse.c,v 1.40 2016/05/09 21:46:56 christos Exp $");
+__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -111,8 +111,8 @@ el_wparse(EditLine *el, int argc, const wchar_t *argv[])
if (ptr == argv[0])
return 0;
- l = (size_t)(ptr - argv[0] - 1);
- tprog = el_malloc((l + 1) * sizeof(*tprog));
+ l = (size_t)(ptr - argv[0]);
+ tprog = el_calloc(l + 1, sizeof(*tprog));
if (tprog == NULL)
return 0;
(void) wcsncpy(tprog, argv[0], l);
diff --git a/read.c b/read.c
index 04925c387253..d2095a244efa 100644
--- a/read.c
+++ b/read.c
@@ -1,4 +1,4 @@
-/* $NetBSD: read.c,v 1.103 2017/06/27 23:24:19 christos Exp $ */
+/* $NetBSD: read.c,v 1.106 2019/07/23 10:18:52 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.103 2017/06/27 23:24:19 christos Exp $");
+__RCSID("$NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -89,8 +89,7 @@ read_init(EditLine *el)
return -1;
ma = &el->el_read->macros;
- if ((ma->macro = el_malloc(EL_MAXMACRO *
- sizeof(*ma->macro))) == NULL) {
+ if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL) {
free(el->el_read);
return -1;
}
@@ -335,13 +334,7 @@ read_char(EditLine *el, wchar_t *cp)
goto again;
}
case (size_t)-2:
- /*
- * We don't support other multibyte charsets.
- * The second condition shouldn't happen
- * and is here merely for additional safety.
- */
- if ((el->el_flags & CHARSET_IS_UTF8) == 0 ||
- cbp >= MB_LEN_MAX) {
+ if (cbp >= MB_LEN_MAX) {
errno = EILSEQ;
*cp = L'\0';
return -1;
diff --git a/readline.c b/readline.c
index 80eb8463386a..dc852f5539c1 100644
--- a/readline.c
+++ b/readline.c
@@ -1,4 +1,4 @@
-/* $NetBSD: readline.c,v 1.143 2017/09/05 18:07:59 christos Exp $ */
+/* $NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 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.143 2017/09/05 18:07:59 christos Exp $");
+__RCSID("$NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 christos Exp $");
#endif /* not lint && not SCCSID */
#include <sys/types.h>
@@ -72,7 +72,7 @@ static char empty[] = { '\0' };
static char expand_chars[] = { ' ', '\t', '\n', '=', '(', '\0' };
static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$',
'>', '<', '=', ';', '|', '&', '{', '(', '\0' };
-char *rl_readline_name = empty;
+const char *rl_readline_name = empty;
FILE *rl_instream = NULL;
FILE *rl_outstream = NULL;
int rl_point = 0;
@@ -80,7 +80,7 @@ int rl_end = 0;
char *rl_line_buffer = NULL;
rl_vcpfunc_t *rl_linefunc = NULL;
int rl_done = 0;
-VFunction *rl_event_hook = NULL;
+rl_hook_func_t *rl_event_hook = NULL;
KEYMAP_ENTRY_ARRAY emacs_standard_keymap,
emacs_meta_keymap,
emacs_ctlx_keymap;
@@ -105,9 +105,9 @@ char *history_arg_extract(int start, int end, const char *str);
int rl_inhibit_completion = 0;
int rl_attempted_completion_over = 0;
-char *rl_basic_word_break_characters = break_chars;
+const char *rl_basic_word_break_characters = break_chars;
char *rl_completer_word_break_characters = NULL;
-char *rl_completer_quote_characters = NULL;
+const char *rl_completer_quote_characters = NULL;
rl_compentry_func_t *rl_completion_entry_function = NULL;
char *(*rl_completion_word_break_hook)(void) = NULL;
rl_completion_func_t *rl_attempted_completion_function = NULL;
@@ -150,7 +150,7 @@ int rl_completion_query_items = 100;
* in the parsed text when it is passed to the completion function.
* Shell uses this to help determine what kind of completing to do.
*/
-char *rl_special_prefixes = NULL;
+const char *rl_special_prefixes = NULL;
/*
* This is the character appended to the completed words if at the end of
@@ -258,8 +258,14 @@ rl_set_prompt(const char *prompt)
if (rl_prompt == NULL)
return -1;
- while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL)
- *p = RL_PROMPT_START_IGNORE;
+ while ((p = strchr(rl_prompt, RL_PROMPT_END_IGNORE)) != NULL) {
+ /* Remove adjacent end/start markers to avoid double-escapes. */
+ if (p[1] == RL_PROMPT_START_IGNORE) {
+ memmove(p, p + 2, 1 + strlen(p + 2));
+ } else {
+ *p = RL_PROMPT_START_IGNORE;
+ }
+ }
return 0;
}
@@ -319,7 +325,7 @@ rl_initialize(void)
el_end(e);
return -1;
}
- el_set(e, EL_PROMPT, _get_prompt, RL_PROMPT_START_IGNORE);
+ el_set(e, EL_PROMPT_ESC, _get_prompt, RL_PROMPT_START_IGNORE);
el_set(e, EL_SIGNAL, rl_catch_signals);
/* set default mode to "emacs"-style and read setting afterwards */
@@ -388,7 +394,7 @@ rl_initialize(void)
_resize_fun(e, &rl_line_buffer);
_rl_update_pos();
- tty_end(e);
+ tty_end(e, TCSADRAIN);
return 0;
}
@@ -429,7 +435,7 @@ readline(const char *p)
if (rl_pre_input_hook)
(*rl_pre_input_hook)(NULL, 0);
- if (rl_event_hook && !(e->el_flags&NO_TTY)) {
+ if (rl_event_hook && !(e->el_flags & NO_TTY)) {
el_set(e, EL_GETCFN, _rl_event_read_char);
used_event_hook = 1;
}
@@ -460,7 +466,7 @@ readline(const char *p)
history_length = ev.num;
out:
- tty_end(e);
+ tty_end(e, TCSADRAIN);
return buf;
}
@@ -509,7 +515,7 @@ _rl_compat_sub(const char *str, const char *what, const char *with,
} else
s++;
}
- r = result = el_malloc((len + 1) * sizeof(*r));
+ r = result = el_calloc(len + 1, sizeof(*r));
if (result == NULL)
return NULL;
s = str;
@@ -599,7 +605,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)
else if (len == 0)
return NULL;
else {
- if ((pat = el_malloc((len + 1) * sizeof(*pat))) == NULL)
+ if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL)
return NULL;
(void)strncpy(pat, cmd + begin, len);
pat[len] = '\0';
@@ -693,7 +699,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen,
} else {
if (command[offs + 1] == '#') {
/* use command so far */
- if ((aptr = el_malloc((offs + 1) * sizeof(*aptr)))
+ if ((aptr = el_calloc(offs + 1, sizeof(*aptr)))
== NULL)
return -1;
(void)strncpy(aptr, command, offs);
@@ -927,7 +933,7 @@ history_expand(char *str, char **output)
*output = NULL;
if (str[0] == history_subst_char) {
/* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */
- *output = el_malloc((strlen(str) + 4 + 1) * sizeof(**output));
+ *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output));
if (*output == NULL)
return 0;
(*output)[0] = (*output)[1] = history_expansion_char;
@@ -1075,7 +1081,7 @@ history_arg_extract(int start, int end, const char *str)
for (i = (size_t)start, len = 0; i <= (size_t)end; i++)
len += strlen(arr[i]) + 1;
len++;
- result = el_malloc(len * sizeof(*result));
+ result = el_calloc(len, sizeof(*result));
if (result == NULL)
goto out;
@@ -1137,7 +1143,7 @@ history_tokenize(const char *str)
result = nresult;
}
len = (size_t)i - (size_t)start;
- temp = el_malloc((size_t)(len + 1) * sizeof(*temp));
+ temp = el_calloc(len + 1, sizeof(*temp));
if (temp == NULL) {
for (i = 0; i < idx; i++)
el_free(result[i]);
@@ -1355,8 +1361,14 @@ read_history(const char *filename)
rl_initialize();
if (filename == NULL && (filename = _default_history_file()) == NULL)
return errno;
- return history(h, &ev, H_LOAD, filename) == -1 ?
- (errno ? errno : EINVAL) : 0;
+ errno = 0;
+ if (history(h, &ev, H_LOAD, filename) == -1)
+ return errno ? errno : EINVAL;
+ if (history(h, &ev, H_GETSIZE) == 0)
+ history_length = ev.num;
+ if (history_length < 0)
+ return EINVAL;
+ return 0;
}
@@ -1465,8 +1477,10 @@ add_history(const char *line)
(void)history(h, &ev, H_GETSIZE);
if (ev.num == history_length)
history_base++;
- else
+ else {
+ history_offset++;
history_length = ev.num;
+ }
return 0;
}
@@ -1584,7 +1598,7 @@ history_list(void)
return NULL;
if ((nlp = el_realloc(_history_listp,
- (size_t)history_length * sizeof(*nlp))) == NULL)
+ ((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
return NULL;
_history_listp = nlp;
@@ -1601,6 +1615,7 @@ history_list(void)
if (i++ == history_length)
abort();
} while (history(h, &ev, H_PREV) == 0);
+ _history_listp[i] = NULL;
return _history_listp;
}
@@ -1878,7 +1893,7 @@ int
rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
{
static ct_buffer_t wbreak_conv, sprefix_conv;
- char *breakchars;
+ const char *breakchars;
if (h == NULL || e == NULL)
rl_initialize();
@@ -1964,13 +1979,14 @@ rl_read_key(void)
* reset the terminal
*/
/* ARGSUSED */
-void
+int
rl_reset_terminal(const char *p __attribute__((__unused__)))
{
if (h == NULL || e == NULL)
rl_initialize();
el_reset(e);
+ return 0;
}
@@ -2068,8 +2084,8 @@ rl_callback_read_char(void)
if (done && rl_linefunc != NULL) {
el_set(e, EL_UNBUFFERED, 0);
if (done == 2) {
- if ((wbuf = strdup(buf)) != NULL)
- wbuf[count] = '\0';
+ if ((wbuf = strdup(buf)) != NULL)
+ wbuf[count] = '\0';
} else
wbuf = NULL;
(*(void (*)(const char *))rl_linefunc)(wbuf);
@@ -2159,7 +2175,7 @@ rl_variable_bind(const char *var, const char *value)
return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0;
}
-void
+int
rl_stuff_char(int c)
{
char buf[2];
@@ -2167,6 +2183,7 @@ rl_stuff_char(int c)
buf[0] = (char)c;
buf[1] = '\0';
el_insertstr(e, buf);
+ return 1;
}
static int
@@ -2222,15 +2239,16 @@ _rl_update_pos(void)
rl_point = (int)(li->cursor - li->buffer);
rl_end = (int)(li->lastchar - li->buffer);
+ rl_line_buffer[rl_end] = '\0';
}
void
rl_get_screen_size(int *rows, int *cols)
{
if (rows)
- el_get(e, EL_GETTC, "li", rows, (void *)0);
+ el_get(e, EL_GETTC, "li", rows);
if (cols)
- el_get(e, EL_GETTC, "co", cols, (void *)0);
+ el_get(e, EL_GETTC, "co", cols);
}
void
@@ -2251,7 +2269,7 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun)
len = 1;
max = 10;
- if ((list = el_malloc(max * sizeof(*list))) == NULL)
+ if ((list = el_calloc(max, sizeof(*list))) == NULL)
return NULL;
while ((match = (*fun)(str, (int)(len - 1))) != NULL) {
@@ -2286,7 +2304,7 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun)
if ((list[0] = strdup(str)) == NULL)
goto out;
} else {
- if ((list[0] = el_malloc((min + 1) * sizeof(*list[0]))) == NULL)
+ if ((list[0] = el_calloc(min + 1, sizeof(*list[0]))) == NULL)
goto out;
(void)memcpy(list[0], list[1], min);
list[0][min] = '\0';
@@ -2409,3 +2427,19 @@ rl_resize_terminal(void)
{
el_resize(e);
}
+
+void
+rl_reset_after_signal(void)
+{
+ if (rl_prep_term_function)
+ (*rl_prep_term_function)();
+}
+
+void
+rl_echo_signal_char(int sig)
+{
+ int c = tty_get_signal_character(e, sig);
+ if (c == -1)
+ return;
+ re_putc(e, c, 0);
+}
diff --git a/readline/readline.h b/readline/readline.h
index a2a6c15f74df..7e53f417bc25 100644
--- a/readline/readline.h
+++ b/readline/readline.h
@@ -1,4 +1,4 @@
-/* $NetBSD: readline.h,v 1.42 2017/09/01 10:19:10 christos Exp $ */
+/* $NetBSD: readline.h,v 1.46 2019/06/07 15:19:29 christos Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -38,11 +38,13 @@
/* typedefs */
typedef int Function(const char *, int);
+typedef char *CPFunction(const char *, int);
typedef void VFunction(void);
typedef void rl_vcpfunc_t(char *);
typedef char **rl_completion_func_t(const char *, int, int);
typedef char *rl_compentry_func_t(const char *, int);
typedef int rl_command_func_t(int, int);
+typedef int rl_hook_func_t(void);
/* only supports length */
typedef struct {
@@ -97,23 +99,23 @@ extern "C" {
#endif
extern const char *rl_library_version;
extern int rl_readline_version;
-extern char *rl_readline_name;
+extern const 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 const char *rl_basic_word_break_characters;
extern char *rl_completer_word_break_characters;
-extern char *rl_completer_quote_characters;
+extern const char *rl_completer_quote_characters;
extern rl_compentry_func_t *rl_completion_entry_function;
extern char *(*rl_completion_word_break_hook)(void);
extern rl_completion_func_t *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 const char *rl_special_prefixes;
extern int rl_completion_append_character;
extern int rl_inhibit_completion;
extern Function *rl_pre_input_hook;
@@ -137,6 +139,7 @@ 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 rl_hook_func_t *rl_event_hook;
extern int readline_echoing_p;
extern int _rl_print_completions_horizontally;
@@ -177,12 +180,12 @@ 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 *, rl_compentry_func_t *);
+char **completion_matches(/* const */ char *, rl_compentry_func_t *);
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_reset_terminal(const char *);
void rl_resize_terminal(void);
int rl_bind_key(int, rl_command_func_t *);
int rl_newline(int, int);
@@ -196,7 +199,7 @@ 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_stuff_char(int);
int rl_add_defun(const char *, rl_command_func_t *, int);
HISTORY_STATE *history_get_history_state(void);
void rl_get_screen_size(int *, int *);
@@ -208,6 +211,8 @@ 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);
+void rl_reset_after_signal(void);
+void rl_echo_signal_char(int);
/*
* The following are not implemented
diff --git a/refresh.c b/refresh.c
index fe5187c5f066..584eec624976 100644
--- a/refresh.c
+++ b/refresh.c
@@ -1,4 +1,4 @@
-/* $NetBSD: refresh.c,v 1.54 2017/06/30 20:26:52 kre Exp $ */
+/* $NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: refresh.c,v 1.54 2017/06/30 20:26:52 kre Exp $");
+__RCSID("$NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -1090,7 +1090,10 @@ re_refresh_cursor(EditLine *el)
static void
re_fastputc(EditLine *el, wint_t c)
{
- int w = wcwidth(c);
+ wchar_t *lastline;
+ int w;
+
+ w = wcwidth(c);
while (w > 1 && el->el_cursor.h + w > el->el_terminal.t_size.h)
re_fastputc(el, ' ');
@@ -1112,17 +1115,18 @@ re_fastputc(EditLine *el, wint_t c)
*/
if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) {
int i, lins = el->el_terminal.t_size.v;
- wchar_t *firstline = el->el_display[0];
+ lastline = el->el_display[0];
for(i = 1; i < lins; i++)
el->el_display[i - 1] = el->el_display[i];
- re__copy_and_pad(firstline, L"", (size_t)0);
- el->el_display[i - 1] = firstline;
+ el->el_display[i - 1] = lastline;
} else {
el->el_cursor.v++;
- el->el_refresh.r_oldcv++;
+ lastline = el->el_display[++el->el_refresh.r_oldcv];
}
+ re__copy_and_pad(lastline, L"", (size_t)el->el_terminal.t_size.h);
+
if (EL_HAS_AUTO_MARGINS) {
if (EL_HAS_MAGIC_MARGINS) {
terminal__putc(el, ' ');
diff --git a/search.c b/search.c
index 5226cf5fa6a3..78e15d720cb8 100644
--- a/search.c
+++ b/search.c
@@ -1,4 +1,4 @@
-/* $NetBSD: search.c,v 1.47 2016/05/09 21:46:56 christos Exp $ */
+/* $NetBSD: search.c,v 1.49 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: search.c,v 1.47 2016/05/09 21:46:56 christos Exp $");
+__RCSID("$NetBSD: search.c,v 1.49 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -70,7 +70,7 @@ libedit_private int
search_init(EditLine *el)
{
- el->el_search.patbuf = el_malloc(EL_BUFSIZ *
+ el->el_search.patbuf = el_calloc(EL_BUFSIZ,
sizeof(*el->el_search.patbuf));
if (el->el_search.patbuf == NULL)
return -1;
@@ -603,8 +603,10 @@ cv_csearch(EditLine *el, int direction, wint_t ch, int count, int tflag)
return CC_ERROR;
if (ch == (wint_t)-1) {
- if (el_wgetc(el, &ch) != 1)
+ wchar_t c;
+ if (el_wgetc(el, &c) != 1)
return ed_end_of_file(el, 0);
+ ch = c;
}
/* Save for ';' and ',' commands */
diff --git a/terminal.c b/terminal.c
index 9c74fcdbfb66..c0b9bda67c55 100644
--- a/terminal.c
+++ b/terminal.c
@@ -1,4 +1,4 @@
-/* $NetBSD: terminal.c,v 1.33 2017/06/27 23:23:09 christos Exp $ */
+/* $NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
#else
-__RCSID("$NetBSD: terminal.c,v 1.33 2017/06/27 23:23:09 christos Exp $");
+__RCSID("$NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -269,31 +269,27 @@ libedit_private int
terminal_init(EditLine *el)
{
- el->el_terminal.t_buf = el_malloc(TC_BUFSIZE *
+ el->el_terminal.t_buf = el_calloc(TC_BUFSIZE,
sizeof(*el->el_terminal.t_buf));
if (el->el_terminal.t_buf == NULL)
goto fail1;
- el->el_terminal.t_cap = el_malloc(TC_BUFSIZE *
+ el->el_terminal.t_cap = el_calloc(TC_BUFSIZE,
sizeof(*el->el_terminal.t_cap));
if (el->el_terminal.t_cap == NULL)
goto fail2;
- el->el_terminal.t_fkey = el_malloc(A_K_NKEYS *
+ el->el_terminal.t_fkey = el_calloc(A_K_NKEYS,
sizeof(*el->el_terminal.t_fkey));
if (el->el_terminal.t_fkey == NULL)
goto fail3;
el->el_terminal.t_loc = 0;
- el->el_terminal.t_str = el_malloc(T_str *
+ el->el_terminal.t_str = el_calloc(T_str,
sizeof(*el->el_terminal.t_str));
if (el->el_terminal.t_str == NULL)
goto fail4;
- (void) memset(el->el_terminal.t_str, 0, T_str *
- sizeof(*el->el_terminal.t_str));
- el->el_terminal.t_val = el_malloc(T_val *
+ el->el_terminal.t_val = el_calloc(T_val,
sizeof(*el->el_terminal.t_val));
if (el->el_terminal.t_val == NULL)
goto fail5;
- (void) memset(el->el_terminal.t_val, 0, T_val *
- sizeof(*el->el_terminal.t_val));
(void) terminal_set(el, NULL);
terminal_init_arrow(el);
return 0;
@@ -419,18 +415,18 @@ terminal_rebuffer_display(EditLine *el)
return 0;
}
-static wchar_t **
+static wint_t **
terminal_alloc_buffer(EditLine *el)
{
wint_t **b;
coord_t *c = &el->el_terminal.t_size;
int i;
- b = el_malloc(sizeof(*b) * (size_t)(c->v + 1));
+ b = el_calloc((size_t)(c->v + 1), sizeof(*b));
if (b == NULL)
return NULL;
for (i = 0; i < c->v; i++) {
- b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1));
+ b[i] = el_calloc((size_t)(c->h + 1), sizeof(**b));
if (b[i] == NULL) {
while (--i >= 0)
el_free(b[i]);
@@ -509,37 +505,14 @@ terminal_move_to_line(EditLine *el, int where)
return;
}
if ((del = where - el->el_cursor.v) > 0) {
- while (del > 0) {
- if (EL_HAS_AUTO_MARGINS &&
- el->el_display[el->el_cursor.v][0] != '\0') {
- size_t h = (size_t)
- (el->el_terminal.t_size.h - 1);
- for (; h > 0 &&
- el->el_display[el->el_cursor.v][h] ==
- MB_FILL_CHAR;
- h--)
- continue;
- /* move without newline */
- terminal_move_to_char(el, (int)h);
- terminal_overwrite(el, &el->el_display
- [el->el_cursor.v][el->el_cursor.h],
- (size_t)(el->el_terminal.t_size.h -
- el->el_cursor.h));
- /* updates Cursor */
- del--;
- } else {
- if ((del > 1) && GoodStr(T_DO)) {
- terminal_tputs(el, tgoto(Str(T_DO), del,
- del), del);
- del = 0;
- } else {
- for (; del > 0; del--)
- terminal__putc(el, '\n');
- /* because the \n will become \r\n */
- el->el_cursor.h = 0;
- }
- }
- }
+ /*
+ * We don't use DO here because some terminals are buggy
+ * if the destination is beyond bottom of the screen.
+ */
+ for (; del > 0; del--)
+ terminal__putc(el, '\n');
+ /* because the \n will become \r\n */
+ el->el_cursor.h = 0;
} else { /* del < 0 */
if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
terminal_tputs(el, tgoto(Str(T_UP), -del, -del), -del);
@@ -988,9 +961,10 @@ terminal_get_size(EditLine *el, int *lins, int *cols)
libedit_private int
terminal_change_size(EditLine *el, int lins, int cols)
{
+ coord_t cur = el->el_cursor;
/*
- * Just in case
- */
+ * Just in case
+ */
Val(T_co) = (cols < 2) ? 80 : cols;
Val(T_li) = (lins < 1) ? 24 : lins;
@@ -998,6 +972,7 @@ terminal_change_size(EditLine *el, int lins, int cols)
if (terminal_rebuffer_display(el) == -1)
return -1;
re_clear_display(el);
+ el->el_cursor = cur;
return 0;
}
diff --git a/tty.c b/tty.c
index 2ca785808fe4..743075e08b3f 100644
--- a/tty.c
+++ b/tty.c
@@ -1,4 +1,4 @@
-/* $NetBSD: tty.c,v 1.66 2017/09/05 18:07:59 christos Exp $ */
+/* $NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 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.66 2017/09/05 18:07:59 christos Exp $");
+__RCSID("$NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -586,7 +586,7 @@ tty_init(EditLine *el)
*/
libedit_private void
/*ARGSUSED*/
-tty_end(EditLine *el)
+tty_end(EditLine *el, int how)
{
if (el->el_flags & EDIT_DISABLED)
return;
@@ -594,7 +594,8 @@ tty_end(EditLine *el)
if (!el->el_tty.t_initialized)
return;
- if (tty_setty(el, TCSAFLUSH, &el->el_tty.t_or) == -1) {
+ if (tty_setty(el, how, &el->el_tty.t_or) == -1)
+ {
#ifdef DEBUG_TTY
(void) fprintf(el->el_errfile,
"%s: tty_setty: %s\n", __func__, strerror(errno));
@@ -1340,3 +1341,33 @@ tty_setup_flags(EditLine *el, struct termios *tios, int mode)
*f = tty_update_flag(el, *f, mode, kind);
}
}
+
+libedit_private int
+tty_get_signal_character(EditLine *el, int sig)
+{
+#ifdef ECHOCTL
+ tcflag_t *ed = tty__get_flag(&el->el_tty.t_ed, MD_INP);
+ if ((*ed & ECHOCTL) == 0)
+ return -1;
+#endif
+ switch (sig) {
+#ifdef SIGINT
+ case SIGINT:
+ return el->el_tty.t_c[ED_IO][VINTR];
+#endif
+#ifdef SIGQUIT
+ case SIGQUIT:
+ return el->el_tty.t_c[ED_IO][VQUIT];
+#endif
+#ifdef SIGINFO
+ case SIGINFO:
+ return el->el_tty.t_c[ED_IO][VSTATUS];
+#endif
+#ifdef SIGTSTP
+ case SIGTSTP:
+ return el->el_tty.t_c[ED_IO][VSUSP];
+#endif
+ default:
+ return -1;
+ }
+}
diff --git a/tty.h b/tty.h
index 2603e1ad2d6d..643091961976 100644
--- a/tty.h
+++ b/tty.h
@@ -1,4 +1,4 @@
-/* $NetBSD: tty.h,v 1.21 2016/05/09 21:46:56 christos Exp $ */
+/* $NetBSD: tty.h,v 1.23 2018/12/02 16:58:13 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -457,13 +457,14 @@ typedef struct {
typedef unsigned char ttychar_t[NN_IO][C_NCC];
libedit_private int tty_init(EditLine *);
-libedit_private void tty_end(EditLine *);
+libedit_private void tty_end(EditLine *, int);
libedit_private int tty_stty(EditLine *, int, const wchar_t **);
libedit_private int tty_rawmode(EditLine *);
libedit_private int tty_cookedmode(EditLine *);
libedit_private int tty_quotemode(EditLine *);
libedit_private int tty_noquotemode(EditLine *);
libedit_private void tty_bind_char(EditLine *, int);
+libedit_private int tty_get_signal_character(EditLine *, int);
typedef struct {
ttyperm_t t_t;
diff --git a/vi.c b/vi.c
index 0c37bfb9b2ec..010616cdf1dc 100644
--- a/vi.c
+++ b/vi.c
@@ -1,4 +1,4 @@
-/* $NetBSD: vi.c,v 1.62 2016/05/09 21:46:56 christos Exp $ */
+/* $NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -37,7 +37,7 @@
#if 0
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: vi.c,v 1.62 2016/05/09 21:46:56 christos Exp $");
+__RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
@@ -1019,10 +1019,10 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
return CC_ERROR;
len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
- cp = el_malloc(TMP_BUFSIZ * sizeof(*cp));
+ cp = el_calloc(TMP_BUFSIZ, sizeof(*cp));
if (cp == NULL)
goto error;
- line = el_malloc(len * sizeof(*line) + 1);
+ line = el_calloc(len + 1, sizeof(*line));
if (line == NULL)
goto error;
wcsncpy(line, el->el_line.buffer, len);