Merge ^/head r352105 through r352307.

This commit is contained in:
Dimitry Andric 2019-09-13 21:15:01 +00:00
commit 61c1328eb0
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang900-import/; revision=352308
1088 changed files with 14330 additions and 31175 deletions

View file

@ -198,6 +198,11 @@ OLD_FILES+=usr/include/c++/v1/experimental/string_view
OLD_FILES+=usr/include/c++/v1/experimental/system_error
OLD_FILES+=usr/include/c++/v1/experimental/tuple
OLD_FILES+=usr/lib/libc++fs.a
# 20190910: mklocale(1) and colldef(1) removed
OLD_FILES+=usr/bin/mklocale
OLD_FILES+=usr/share/man/man1/mklocale.1.gz
OLD_FILES+=usr/bin/colldef
OLD_FILES+=usr/share/man/man1/colldef.1.gz
# 20190904: Remove boot1.efifat
OLD_FILES+=boot/boot1.efifat
# 20190903: pc-sysinstall(8) removed

View file

@ -10,6 +10,10 @@ newline. Entries should be separated by a newline.
Changes to this file should not be MFCed.
r352304:
ntpd is no longer by default locked in memory. rlimit memlock 32
or rlimit memlock 0 can be used to restore this behaviour.
r351522:
Add kernel-side support for in-kernel Transport Layer Security
(KTLS). KTLS permits using sendfile(2) over sockets using

View file

@ -26,6 +26,12 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 13.x IS SLOW:
disable the most expensive debugging functionality run
"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
20190913:
ntpd no longer by default locks its pages in memory, allowing them
to be paged out by the kernel. Use rlimit memlock to restore
historic BSD behaviour. For example, add "rlimit memlock 32"
to ntp.conf to lock up to 32 MB of ntpd address space in memory.
20190823:
Several of ping6's options have been renamed for better consistency
with ping. If you use any of -ARWXaghmrtwx, you must update your

View file

@ -21,7 +21,6 @@
#include "defs.h"
#include "readline/readline.h"
#include "readline/tilde.h"
#include "completer.h"
#include "target.h" /* For baud_rate, remote_debug and remote_timeout */
#include "gdb_wait.h" /* For shell escape implementation */

View file

@ -18,7 +18,6 @@
Boston, MA 02111-1307, USA. */
#include "defs.h"
#include "readline/tilde.h"
#include "value.h"
#include <ctype.h>
#include "gdb_string.h"

View file

@ -34,7 +34,6 @@
/* readline include files */
#include "readline/readline.h"
#include "readline/history.h"
/* readline defines this. */
#undef savestring

View file

@ -48,7 +48,6 @@
/* readline include files */
#include "readline/readline.h"
#include "readline/history.h"
/* readline defines this. */
#undef savestring

View file

@ -45,7 +45,6 @@
/* readline include files */
#include "readline/readline.h"
#include "readline/history.h"
/* readline defines this. */
#undef savestring

View file

@ -20,6 +20,9 @@
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* For uint32_t and uint64_t */
#include <stdint.h>
/**
* ARM-specific unwind definitions. These are taken from the ARM EHABI
* specification.

139
contrib/libedit/Makefile Normal file
View file

@ -0,0 +1,139 @@
# $NetBSD: Makefile,v 1.65 2017/06/30 20:26:52 kre Exp $
# @(#)Makefile 8.1 (Berkeley) 6/4/93
USE_SHLIBDIR= yes
WARNS?= 5
LIB= edit
LIBDPLIBS+= terminfo ${.CURDIR}/../libterminfo
.include "bsd.own.mk"
COPTS+= -Wunused-parameter
CWARNFLAGS.gcc+= -Wconversion
CWARNFLAGS.clang+= -Wno-cast-qual
SRCS = chared.c chartype.c common.c el.c eln.c emacs.c filecomplete.c \
hist.c history.c historyn.c keymacro.c literal.c map.c \
parse.c prompt.c read.c readline.c refresh.c search.c sig.c \
terminal.c tokenizer.c tokenizern.c tty.c vi.c
MAN= editline.3 editrc.5 editline.7
MLINKS= \
editline.3 el_deletestr.3 \
editline.3 el_end.3 \
editline.3 el_get.3 \
editline.3 el_getc.3 \
editline.3 el_gets.3 \
editline.3 el_init.3 \
editline.3 el_init_fd.3 \
editline.3 el_insertstr.3 \
editline.3 el_line.3 \
editline.3 el_parse.3 \
editline.3 el_push.3 \
editline.3 el_reset.3 \
editline.3 el_resize.3 \
editline.3 el_set.3 \
editline.3 el_source.3 \
editline.3 history.3 \
editline.3 history_end.3 \
editline.3 history_init.3 \
editline.3 tok_end.3 \
editline.3 tok_init.3 \
editline.3 tok_line.3 \
editline.3 tok_reset.3 \
editline.3 tok_str.3
MLINKS+= \
editline.3 el_wdeletestr.3 \
editline.3 el_wget.3 \
editline.3 el_wgetc.3 \
editline.3 el_wgets.3 \
editline.3 el_winsertstr.3 \
editline.3 el_wline.3 \
editline.3 el_wparse.3 \
editline.3 el_wpush.3 \
editline.3 el_wset.3 \
editline.3 history_w.3 \
editline.3 history_wend.3 \
editline.3 history_winit.3 \
editline.3 tok_wend.3 \
editline.3 tok_winit.3 \
editline.3 tok_wline.3 \
editline.3 tok_wreset.3 \
editline.3 tok_wstr.3
LIBEDITDIR?=${.CURDIR}
INCS= histedit.h
INCSDIR=/usr/include
CLEANFILES+=common.h.tmp emacs.h.tmp fcns.h.tmp func.h.tmp
CLEANFILES+=help.h.tmp vi.h.tmp tc1.o tc1 .depend
CPPFLAGS+=-I. -I${LIBEDITDIR}
CPPFLAGS+=-I. -I${.CURDIR}
#CPPFLAGS+=-DDEBUG_TTY -DDEBUG_KEY -DDEBUG -DDEBUG_REFRESH
#CPPFLAGS+=-DDEBUG_PASTE -DDEBUG_EDIT
AHDR=vi.h emacs.h common.h
ASRC=${LIBEDITDIR}/vi.c ${LIBEDITDIR}/emacs.c ${LIBEDITDIR}/common.c
DPSRCS+= ${AHDR} fcns.h func.h help.h
CLEANFILES+= ${AHDR} fcns.h func.h help.h
SUBDIR= readline
.depend: ${AHDR} fcns.h func.h help.h
vi.h: vi.c makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/vi.c \
> ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
emacs.h: emacs.c makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/emacs.c \
> ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
common.h: common.c makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -h ${LIBEDITDIR}/common.c \
> ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
fcns.h: ${AHDR} makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -fh ${AHDR} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
func.h: ${AHDR} makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -fc ${AHDR} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
help.h: ${ASRC} makelist Makefile
${_MKTARGET_CREATE}
${HOST_SH} ${LIBEDITDIR}/makelist -bh ${ASRC} > ${.TARGET}.tmp && \
mv ${.TARGET}.tmp ${.TARGET}
tc1.o: ${LIBEDITDIR}/TEST/tc1.c
tc1: libedit.a tc1.o
${_MKTARGET_LINK}
${CC} ${LDFLAGS} ${.ALLSRC} -o ${.TARGET} libedit.a ${LDADD} -ltermlib
.include <bsd.lib.mk>
.include <bsd.subdir.mk>
# XXX
.if defined(HAVE_GCC)
COPTS.editline.c+= -Wno-cast-qual
COPTS.literal.c+= -Wno-sign-conversion
COPTS.tokenizer.c+= -Wno-cast-qual
COPTS.tokenizern.c+= -Wno-cast-qual
.endif

View file

@ -0,0 +1,13 @@
# $NetBSD: Makefile,v 1.8 2017/10/15 18:59:00 abhinav Exp $
NOMAN=1
PROG=wtc1 test_filecompletion
CPPFLAGS=-I${.CURDIR}/..
LDADD+=-ledit -ltermlib
DPADD+=${LIBEDIT} ${LIBTERMLIB}
.ifdef DEBUG
CPPFLAGS+=-DDEBUG
.endif
.include <bsd.prog.mk>

View file

@ -33,7 +33,6 @@
#if !defined(lint)
__RCSID("$NetBSD: rl1.c,v 1.2 2016/02/29 00:54:19 christos Exp $");
#endif /* not lint */
__FBSDID("$FreeBSD$");
/*
* test.c: A little test program

View file

@ -45,7 +45,6 @@ static char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93";
__RCSID("$NetBSD: tc1.c,v 1.7 2016/02/17 19:47:49 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
__FBSDID("$FreeBSD$");
/*
* test.c: A little test program
@ -276,7 +275,7 @@ main(int argc, char *argv[])
} else if (el_parse(el, ac, av) == -1) {
switch (fork()) {
case 0:
execvp(av[0], __DECONST(char **, av));
execvp(av[0], (char *const *)__UNCONST(av));
perror(av[0]);
_exit(1);
/*NOTREACHED*/

View file

@ -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;
}

View file

@ -1,9 +1,3 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
#include <dirent.h>

View file

@ -1,4 +1,4 @@
/* $NetBSD: chared.c,v 1.49 2016/02/24 14:29:21 christos Exp $ */
/* $NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: chared.c,v 1.49 2016/02/24 14:29:21 christos Exp $");
__RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* chared.c: Character editor utilities
@ -52,8 +50,7 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "common.h"
private void ch__clearmacro (EditLine *);
#include "fcns.h"
/* value to leave unused in line buffer */
#define EL_LEAVE 2
@ -61,7 +58,7 @@ private void ch__clearmacro (EditLine *);
/* cv_undo():
* Handle state for the vi undo command
*/
protected void
libedit_private void
cv_undo(EditLine *el)
{
c_undo_t *vu = &el->el_chared.c_undo;
@ -85,8 +82,8 @@ cv_undo(EditLine *el)
/* cv_yank():
* Save yank/delete data for paste
*/
protected void
cv_yank(EditLine *el, const Char *ptr, int size)
libedit_private void
cv_yank(EditLine *el, const wchar_t *ptr, int size)
{
c_kill_t *k = &el->el_chared.c_kill;
@ -98,10 +95,10 @@ cv_yank(EditLine *el, const Char *ptr, int size)
/* c_insert():
* Insert num characters
*/
protected void
libedit_private void
c_insert(EditLine *el, int num)
{
Char *cp;
wchar_t *cp;
if (el->el_line.lastchar + num >= el->el_line.limit) {
if (!ch_enlargebufs(el, (size_t)num))
@ -120,7 +117,7 @@ c_insert(EditLine *el, int num)
/* c_delafter():
* Delete num characters after the cursor
*/
protected void
libedit_private void
c_delafter(EditLine *el, int num)
{
@ -133,7 +130,7 @@ c_delafter(EditLine *el, int num)
}
if (num > 0) {
Char *cp;
wchar_t *cp;
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[num];
@ -146,10 +143,10 @@ c_delafter(EditLine *el, int num)
/* c_delafter1():
* Delete the character after the cursor, do not yank
*/
protected void
libedit_private void
c_delafter1(EditLine *el)
{
Char *cp;
wchar_t *cp;
for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++)
*cp = cp[1];
@ -161,7 +158,7 @@ c_delafter1(EditLine *el)
/* c_delbefore():
* Delete num characters before the cursor
*/
protected void
libedit_private void
c_delbefore(EditLine *el, int num)
{
@ -174,10 +171,10 @@ c_delbefore(EditLine *el, int num)
}
if (num > 0) {
Char *cp;
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];
@ -189,10 +186,10 @@ c_delbefore(EditLine *el, int num)
/* c_delbefore1():
* Delete the character before the cursor, do not yank
*/
protected void
libedit_private void
c_delbefore1(EditLine *el)
{
Char *cp;
wchar_t *cp;
for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++)
*cp = cp[1];
@ -204,22 +201,22 @@ c_delbefore1(EditLine *el)
/* ce__isword():
* Return if p is part of a word according to emacs
*/
protected int
libedit_private int
ce__isword(wint_t p)
{
return Isalnum(p) || Strchr(STR("*?_-.[]~="), p) != NULL;
return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL;
}
/* cv__isword():
* Return if p is part of a word according to vi
*/
protected int
libedit_private int
cv__isword(wint_t p)
{
if (Isalnum(p) || p == '_')
if (iswalnum(p) || p == L'_')
return 1;
if (Isgraph(p))
if (iswgraph(p))
return 2;
return 0;
}
@ -228,18 +225,18 @@ cv__isword(wint_t p)
/* cv__isWord():
* Return if p is part of a big word according to vi
*/
protected int
libedit_private int
cv__isWord(wint_t p)
{
return !Isspace(p);
return !iswspace(p);
}
/* c__prev_word():
* Find the previous word
*/
protected Char *
c__prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
libedit_private wchar_t *
c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
{
p--;
@ -262,8 +259,8 @@ c__prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
/* c__next_word():
* Find the next word
*/
protected Char *
c__next_word(Char *p, Char *high, int n, int (*wtest)(wint_t))
libedit_private wchar_t *
c__next_word(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
{
while (n--) {
while ((p < high) && !(*wtest)(*p))
@ -280,8 +277,9 @@ c__next_word(Char *p, Char *high, int n, int (*wtest)(wint_t))
/* cv_next_word():
* Find the next word vi style
*/
protected Char *
cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t))
libedit_private wchar_t *
cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n,
int (*wtest)(wint_t))
{
int test;
@ -294,7 +292,7 @@ cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t))
* trailing whitespace! This is not what 'w' does..
*/
if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT))
while ((p < high) && Isspace(*p))
while ((p < high) && iswspace(*p))
p++;
}
@ -309,14 +307,14 @@ cv_next_word(EditLine *el, Char *p, Char *high, int n, int (*wtest)(wint_t))
/* cv_prev_word():
* Find the previous word vi style
*/
protected Char *
cv_prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
libedit_private wchar_t *
cv_prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t))
{
int test;
p--;
while (n--) {
while ((p > low) && Isspace(*p))
while ((p > low) && iswspace(*p))
p--;
test = (*wtest)(*p);
while ((p >= low) && (*wtest)(*p) == test)
@ -335,7 +333,7 @@ cv_prev_word(Char *p, Char *low, int n, int (*wtest)(wint_t))
/* cv_delfini():
* Finish vi delete action
*/
protected void
libedit_private void
cv_delfini(EditLine *el)
{
int size;
@ -373,15 +371,15 @@ cv_delfini(EditLine *el)
/* cv__endword():
* Go to the end of this word according to vi
*/
protected Char *
cv__endword(Char *p, Char *high, int n, int (*wtest)(wint_t))
libedit_private wchar_t *
cv__endword(wchar_t *p, wchar_t *high, int n, int (*wtest)(wint_t))
{
int test;
p++;
while (n--) {
while ((p < high) && Isspace(*p))
while ((p < high) && iswspace(*p))
p++;
test = (*wtest)(*p);
@ -395,31 +393,25 @@ cv__endword(Char *p, Char *high, int n, int (*wtest)(wint_t))
/* ch_init():
* Initialize the character editor
*/
protected int
libedit_private int
ch_init(EditLine *el)
{
c_macro_t *ma = &el->el_chared.c_macro;
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;
@ -430,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;
@ -451,19 +441,14 @@ ch_init(EditLine *el)
el->el_state.argument = 1;
el->el_state.lastcmd = ED_UNASSIGNED;
ma->level = -1;
ma->offset = 0;
ma->macro = el_malloc(EL_MAXMACRO * sizeof(*ma->macro));
if (ma->macro == NULL)
return -1;
return 0;
}
/* ch_reset():
* Reset the character editor
*/
protected void
ch_reset(EditLine *el, int mclear)
libedit_private void
ch_reset(EditLine *el)
{
el->el_line.cursor = el->el_line.buffer;
el->el_line.lastchar = el->el_line.buffer;
@ -485,28 +470,17 @@ ch_reset(EditLine *el, int mclear)
el->el_state.lastcmd = ED_UNASSIGNED;
el->el_history.eventno = 0;
if (mclear)
ch__clearmacro(el);
}
private void
ch__clearmacro(EditLine *el)
{
c_macro_t *ma = &el->el_chared.c_macro;
while (ma->level >= 0)
el_free(ma->macro[ma->level--]);
}
/* ch_enlargebufs():
* Enlarge line buffer to be able to hold twice as much characters.
* Returns 1 if successful, 0 if not.
*/
protected int
libedit_private int
ch_enlargebufs(EditLine *el, size_t addlen)
{
size_t sz, newsz;
Char *newbuffer, *oldbuf, *oldkbuf;
wchar_t *newbuffer, *oldbuf, *oldkbuf;
sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE);
newsz = sz * 2;
@ -591,7 +565,7 @@ ch_enlargebufs(EditLine *el, size_t addlen)
/* ch_end():
* Free the data structures used by the editor
*/
protected void
libedit_private void
ch_end(EditLine *el)
{
el_free(el->el_line.buffer);
@ -606,21 +580,19 @@ ch_end(EditLine *el)
el->el_chared.c_redo.cmd = ED_UNASSIGNED;
el_free(el->el_chared.c_kill.buf);
el->el_chared.c_kill.buf = NULL;
ch_reset(el, 1);
el_free(el->el_chared.c_macro.macro);
el->el_chared.c_macro.macro = NULL;
ch_reset(el);
}
/* el_insertstr():
* Insert string at cursorI
* Insert string at cursor
*/
public int
FUN(el,insertstr)(EditLine *el, const Char *s)
int
el_winsertstr(EditLine *el, const wchar_t *s)
{
size_t len;
if (s == NULL || (len = Strlen(s)) == 0)
if (s == NULL || (len = wcslen(s)) == 0)
return -1;
if (el->el_line.lastchar + len >= el->el_line.limit) {
if (!ch_enlargebufs(el, len))
@ -637,7 +609,7 @@ FUN(el,insertstr)(EditLine *el, const Char *s)
/* el_deletestr():
* Delete num characters before the cursor
*/
public void
void
el_deletestr(EditLine *el, int n)
{
if (n <= 0)
@ -655,7 +627,7 @@ el_deletestr(EditLine *el, int n)
/* el_cursor():
* Move the cursor to the left or the right of the current position
*/
public int
int
el_cursor(EditLine *el, int n)
{
if (n == 0)
@ -674,15 +646,14 @@ el_cursor(EditLine *el, int n)
/* c_gets():
* Get a string
*/
protected int
c_gets(EditLine *el, Char *buf, const Char *prompt)
libedit_private int
c_gets(EditLine *el, wchar_t *buf, const wchar_t *prompt)
{
wchar_t wch;
ssize_t len;
Char *cp = el->el_line.buffer, ch;
wchar_t *cp = el->el_line.buffer, ch;
if (prompt) {
len = (ssize_t)Strlen(prompt);
len = (ssize_t)wcslen(prompt);
(void)memcpy(cp, prompt, (size_t)len * sizeof(*cp));
cp += len;
}
@ -694,12 +665,11 @@ c_gets(EditLine *el, Char *buf, const Char *prompt)
el->el_line.lastchar = cp + 1;
re_refresh(el);
if (el_wgetc(el, &wch) != 1) {
if (el_wgetc(el, &ch) != 1) {
ed_end_of_file(el, 0);
len = -1;
break;
}
ch = (Char)wch;
switch (ch) {
@ -741,10 +711,10 @@ c_gets(EditLine *el, Char *buf, const Char *prompt)
/* c_hpos():
* Return the current horizontal position of the cursor
*/
protected int
libedit_private int
c_hpos(EditLine *el)
{
Char *ptr;
wchar_t *ptr;
/*
* Find how many characters till the beginning of this line.
@ -760,7 +730,7 @@ c_hpos(EditLine *el)
}
}
protected int
libedit_private int
ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
{
el->el_chared.c_resizefun = f;
@ -768,7 +738,7 @@ ch_resizefun(EditLine *el, el_zfunc_t f, void *a)
return 0;
}
protected int
libedit_private int
ch_aliasfun(EditLine *el, el_afunc_t f, void *a)
{
el->el_chared.c_aliasfun = f;

View file

@ -1,4 +1,4 @@
/* $NetBSD: chared.h,v 1.27 2016/02/16 22:53:14 christos Exp $ */
/* $NetBSD: chared.h,v 1.30 2016/05/22 19:44:26 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)chared.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -41,8 +40,6 @@
#ifndef _h_el_chared
#define _h_el_chared
#define EL_MAXMACRO 10
/*
* This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works
* like real vi: i.e. the transition from command<->insert modes moves
@ -55,29 +52,22 @@
*/
#define VI_MOVE
typedef struct c_macro_t {
int level;
int offset;
Char **macro;
} c_macro_t;
/*
* Undo information for vi - no undo in emacs (yet)
*/
typedef struct c_undo_t {
ssize_t len; /* length of saved line */
int cursor; /* position of saved cursor */
Char *buf; /* full saved text */
wchar_t *buf; /* full saved text */
} c_undo_t;
/* redo for vi */
typedef struct c_redo_t {
Char *buf; /* redo insert key sequence */
Char *pos;
Char *lim;
wchar_t *buf; /* redo insert key sequence */
wchar_t *pos;
wchar_t *lim;
el_action_t cmd; /* command to redo */
Char ch; /* char that invoked it */
wchar_t ch; /* char that invoked it */
int count;
int action; /* from cv_action() */
} c_redo_t;
@ -87,16 +77,16 @@ typedef struct c_redo_t {
*/
typedef struct c_vcmd_t {
int action;
Char *pos;
wchar_t *pos;
} c_vcmd_t;
/*
* Kill buffer for emacs
*/
typedef struct c_kill_t {
Char *buf;
Char *last;
Char *mark;
wchar_t *buf;
wchar_t *last;
wchar_t *mark;
} c_kill_t;
typedef void (*el_zfunc_t)(EditLine *, void *);
@ -111,7 +101,6 @@ typedef struct el_chared_t {
c_kill_t c_kill;
c_redo_t c_redo;
c_vcmd_t c_vcmd;
c_macro_t c_macro;
el_zfunc_t c_resizefun;
el_afunc_t c_aliasfun;
void * c_resizearg;
@ -136,30 +125,31 @@ typedef struct el_chared_t {
#define MODE_REPLACE_1 2
protected int cv__isword(wint_t);
protected int cv__isWord(wint_t);
protected void cv_delfini(EditLine *);
protected Char *cv__endword(Char *, Char *, int, int (*)(wint_t));
protected int ce__isword(wint_t);
protected void cv_undo(EditLine *);
protected void cv_yank(EditLine *, const Char *, int);
protected Char *cv_next_word(EditLine*, Char *, Char *, int, int (*)(wint_t));
protected Char *cv_prev_word(Char *, Char *, int, int (*)(wint_t));
protected Char *c__next_word(Char *, Char *, int, int (*)(wint_t));
protected Char *c__prev_word(Char *, Char *, int, int (*)(wint_t));
protected void c_insert(EditLine *, int);
protected void c_delbefore(EditLine *, int);
protected void c_delbefore1(EditLine *);
protected void c_delafter(EditLine *, int);
protected void c_delafter1(EditLine *);
protected int c_gets(EditLine *, Char *, const Char *);
protected int c_hpos(EditLine *);
libedit_private int cv__isword(wint_t);
libedit_private int cv__isWord(wint_t);
libedit_private void cv_delfini(EditLine *);
libedit_private wchar_t *cv__endword(wchar_t *, wchar_t *, int, int (*)(wint_t));
libedit_private int ce__isword(wint_t);
libedit_private void cv_undo(EditLine *);
libedit_private void cv_yank(EditLine *, const wchar_t *, int);
libedit_private wchar_t *cv_next_word(EditLine*, wchar_t *, wchar_t *, int,
int (*)(wint_t));
libedit_private wchar_t *cv_prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t));
libedit_private wchar_t *c__next_word(wchar_t *, wchar_t *, int, int (*)(wint_t));
libedit_private wchar_t *c__prev_word(wchar_t *, wchar_t *, int, int (*)(wint_t));
libedit_private void c_insert(EditLine *, int);
libedit_private void c_delbefore(EditLine *, int);
libedit_private void c_delbefore1(EditLine *);
libedit_private void c_delafter(EditLine *, int);
libedit_private void c_delafter1(EditLine *);
libedit_private int c_gets(EditLine *, wchar_t *, const wchar_t *);
libedit_private 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 *);
libedit_private int ch_init(EditLine *);
libedit_private void ch_reset(EditLine *);
libedit_private int ch_resizefun(EditLine *, el_zfunc_t, void *);
libedit_private int ch_aliasfun(EditLine *, el_afunc_t, void *);
libedit_private int ch_enlargebufs(EditLine *, size_t);
libedit_private void ch_end(EditLine *);
#endif /* _h_el_chared */

View file

@ -1,4 +1,4 @@
/* $NetBSD: chartype.c,v 1.23 2016/02/28 23:02:24 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,8 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: chartype.c,v 1.23 2016/02/28 23:02:24 christos Exp $");
__RCSID("$NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $");
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <ctype.h>
#include <limits.h>
@ -45,8 +43,10 @@ __FBSDID("$FreeBSD$");
#define CT_BUFSIZ ((size_t)1024)
#ifdef WIDECHAR
protected int
static int ct_conv_cbuff_resize(ct_buffer_t *, size_t);
static int ct_conv_wbuff_resize(ct_buffer_t *, size_t);
static int
ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize)
{
void *p;
@ -67,7 +67,7 @@ ct_conv_cbuff_resize(ct_buffer_t *conv, size_t csize)
return 0;
}
protected int
static int
ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize)
{
void *p;
@ -89,8 +89,8 @@ ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize)
}
public char *
ct_encode_string(const Char *s, ct_buffer_t *conv)
char *
ct_encode_string(const wchar_t *s, ct_buffer_t *conv)
{
char *dst;
ssize_t used;
@ -119,7 +119,7 @@ ct_encode_string(const Char *s, ct_buffer_t *conv)
return conv->cbuff;
}
public Char *
wchar_t *
ct_decode_string(const char *s, ct_buffer_t *conv)
{
size_t len;
@ -127,7 +127,7 @@ ct_decode_string(const char *s, ct_buffer_t *conv)
if (!s)
return NULL;
len = ct_mbstowcs(NULL, s, (size_t)0);
len = mbstowcs(NULL, s, (size_t)0);
if (len == (size_t)-1)
return NULL;
@ -135,18 +135,18 @@ ct_decode_string(const char *s, ct_buffer_t *conv)
if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1)
return NULL;
ct_mbstowcs(conv->wbuff, s, conv->wsize);
mbstowcs(conv->wbuff, s, conv->wsize);
return conv->wbuff;
}
protected Char **
libedit_private wchar_t **
ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
{
size_t bufspace;
int i;
Char *p;
Char **wargv;
wchar_t *p;
wchar_t **wargv;
ssize_t bytes;
/* Make sure we have enough space in the conversion buffer to store all
@ -157,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 */
@ -181,109 +181,79 @@ ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv)
}
protected size_t
ct_enc_width(Char c)
libedit_private size_t
ct_enc_width(wchar_t c)
{
mbstate_t ps = (mbstate_t){{0}};
size_t len;
char cbuf[MB_LEN_MAX];
len = ct_wcrtomb(cbuf, c, &ps);
if (len == (size_t)-1)
return (0);
return (len);
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;
}
protected ssize_t
ct_encode_char(char *dst, size_t len, Char c)
libedit_private ssize_t
ct_encode_char(char *dst, size_t len, wchar_t c)
{
ssize_t l = 0;
if (len < ct_enc_width(c))
return -1;
l = ct_wctomb(dst, c);
l = wctomb(dst, c);
if (l < 0) {
ct_wctomb_reset;
wctomb(NULL, L'\0');
l = 0;
}
return l;
}
size_t
ct_mbrtowc(wchar_t *wc, const char *s, size_t n)
libedit_private const wchar_t *
ct_visual_string(const wchar_t *s, ct_buffer_t *conv)
{
mbstate_t mbs;
/* This only works because UTF-8 is stateless */
memset(&mbs, 0, sizeof(mbs));
return mbrtowc(wc, s, n, &mbs);
}
#else
size_t
ct_mbrtowc(wchar_t *wc, const char *s, size_t n)
{
if (s == NULL)
return 0;
if (n == 0)
return (size_t)-2;
if (wc != NULL)
*wc = *s;
return *s != '\0';
}
#endif
protected const Char *
ct_visual_string(const Char *s)
{
static Char *buff = NULL;
static size_t buffsize = 0;
void *p;
Char *dst;
ssize_t used = 0;
wchar_t *dst;
ssize_t used;
if (!s)
return NULL;
if (!buff) {
buffsize = CT_BUFSIZ;
buff = el_malloc(buffsize * sizeof(*buff));
}
dst = buff;
if (ct_conv_wbuff_resize(conv, CT_BUFSIZ) == -1)
return NULL;
used = 0;
dst = conv->wbuff;
while (*s) {
used = ct_visual_char(dst, buffsize - (size_t)(dst - buff), *s);
if (used == -1) { /* failed to encode, need more buffer space */
used = dst - buff;
buffsize += CT_BUFSIZ;
p = el_realloc(buff, buffsize * sizeof(*buff));
if (p == NULL)
goto out;
buff = p;
dst = buff + used;
/* don't increment s here - we want to retry it! */
used = ct_visual_char(dst,
conv->wsize - (size_t)(dst - conv->wbuff), *s);
if (used != -1) {
++s;
dst += used;
continue;
}
else
++s;
dst += used;
/* failed to encode, need more buffer space */
used = dst - conv->wbuff;
if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1)
return NULL;
dst = conv->wbuff + used;
}
if (dst >= (buff + buffsize)) { /* sigh */
buffsize += 1;
p = el_realloc(buff, buffsize * sizeof(*buff));
if (p == NULL)
goto out;
buff = p;
dst = buff + buffsize - 1;
if (dst >= (conv->wbuff + conv->wsize)) { /* sigh */
used = dst - conv->wbuff;
if (ct_conv_wbuff_resize(conv, conv->wsize + CT_BUFSIZ) == -1)
return NULL;
dst = conv->wbuff + used;
}
*dst = 0;
return buff;
out:
el_free(buff);
buffsize = 0;
return NULL;
*dst = L'\0';
return conv->wbuff;
}
protected int
ct_visual_width(Char c)
libedit_private int
ct_visual_width(wchar_t c)
{
int t = ct_chr_class(c);
switch (t) {
@ -293,7 +263,6 @@ ct_visual_width(Char c)
return 1; /* Hmm, this really need to be handled outside! */
case CHTYPE_NL:
return 0; /* Should this be 1 instead? */
#ifdef WIDECHAR
case CHTYPE_PRINT:
return wcwidth(c);
case CHTYPE_NONPRINT:
@ -301,20 +270,14 @@ ct_visual_width(Char c)
return 8; /* \U+12345 */
else
return 7; /* \U+1234 */
#else
case CHTYPE_PRINT:
return 1;
case CHTYPE_NONPRINT:
return 4; /* \123 */
#endif
default:
return 0; /* should not happen */
}
}
protected ssize_t
ct_visual_char(Char *dst, size_t len, Char c)
libedit_private ssize_t
ct_visual_char(wchar_t *dst, size_t len, wchar_t c)
{
int t = ct_chr_class(c);
switch (t) {
@ -339,7 +302,6 @@ ct_visual_char(Char *dst, size_t len, Char c)
* so this is right */
if ((ssize_t)len < ct_visual_width(c))
return -1; /* insufficient space */
#ifdef WIDECHAR
*dst++ = '\\';
*dst++ = 'U';
*dst++ = '+';
@ -351,13 +313,6 @@ ct_visual_char(Char *dst, size_t len, Char c)
*dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf);
*dst = tohexdigit(((unsigned int) c ) & 0xf);
return c > 0xffff ? 8 : 7;
#else
*dst++ = '\\';
#define tooctaldigit(v) (Char)((v) + '0')
*dst++ = tooctaldigit(((unsigned int) c >> 6) & 0x7);
*dst++ = tooctaldigit(((unsigned int) c >> 3) & 0x7);
*dst++ = tooctaldigit(((unsigned int) c ) & 0x7);
#endif
/*FALLTHROUGH*/
/* these two should be handled outside this function */
default: /* we should never hit the default */
@ -368,16 +323,16 @@ ct_visual_char(Char *dst, size_t len, Char c)
protected int
ct_chr_class(Char c)
libedit_private int
ct_chr_class(wchar_t c)
{
if (c == '\t')
return CHTYPE_TAB;
else if (c == '\n')
return CHTYPE_NL;
else if (IsASCII(c) && Iscntrl(c))
else if (c < 0x100 && iswcntrl(c))
return CHTYPE_ASCIICTL;
else if (Isprint(c))
else if (iswprint(c))
return CHTYPE_PRINT;
else
return CHTYPE_NONPRINT;

119
contrib/libedit/chartype.h Normal file
View file

@ -0,0 +1,119 @@
/* $NetBSD: chartype.h,v 1.35 2017/05/22 19:16:25 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _h_chartype_f
#define _h_chartype_f
/* Ideally we should also test the value of the define to see if it
* supports non-BMP code points without requiring UTF-16, but nothing
* seems to actually advertise this properly, despite Unicode 3.1 having
* been around since 2001... */
#if !defined(__NetBSD__) && \
!defined(__sun) && \
!(defined(__APPLE__) && defined(__MACH__)) && \
!defined(__OpenBSD__) && \
!defined(__FreeBSD__) && \
!defined(__DragonFly__)
#ifndef __STDC_ISO_10646__
/* In many places it is assumed that the first 127 code points are ASCII
* compatible, so ensure wchar_t indeed does ISO 10646 and not some other
* funky encoding that could break us in weird and wonderful ways. */
#error wchar_t must store ISO 10646 characters
#endif
#endif
/* Oh for a <uchar.h> with char32_t and __STDC_UTF_32__ in it...
* ref: ISO/IEC DTR 19769
*/
#if WCHAR_MAX < INT32_MAX
#warning Build environment does not support non-BMP characters
#endif
/*
* Conversion buffer
*/
typedef struct ct_buffer_t {
char *cbuff;
size_t csize;
wchar_t *wbuff;
size_t wsize;
} ct_buffer_t;
/* Encode a wide-character string and return the UTF-8 encoded result. */
char *ct_encode_string(const wchar_t *, ct_buffer_t *);
/* Decode a (multi)?byte string and return the wide-character string result. */
wchar_t *ct_decode_string(const char *, ct_buffer_t *);
/* Decode a (multi)?byte argv string array.
* The pointer returned must be free()d when done. */
libedit_private wchar_t **ct_decode_argv(int, const char *[], ct_buffer_t *);
/* Encode a character into the destination buffer, provided there is sufficient
* buffer space available. Returns the number of bytes used up (zero if the
* character cannot be encoded, -1 if there was not enough space available). */
libedit_private ssize_t ct_encode_char(char *, size_t, wchar_t);
libedit_private size_t ct_enc_width(wchar_t);
/* The maximum buffer size to hold the most unwieldy visual representation,
* in this case \U+nnnnn. */
#define VISUAL_WIDTH_MAX ((size_t)8)
/* The terminal is thought of in terms of X columns by Y lines. In the cases
* where a wide character takes up more than one column, the adjacent
* occupied column entries will contain this faux character. */
#define MB_FILL_CHAR ((wchar_t)-1)
/* Visual width of character c, taking into account ^? , \0177 and \U+nnnnn
* style visual expansions. */
libedit_private int ct_visual_width(wchar_t);
/* Turn the given character into the appropriate visual format, matching
* the width given by ct_visual_width(). Returns the number of characters used
* up, or -1 if insufficient space. Buffer length is in count of wchar_t's. */
libedit_private ssize_t ct_visual_char(wchar_t *, size_t, wchar_t);
/* Convert the given string into visual format, using the ct_visual_char()
* function. Uses a static buffer, so not threadsafe. */
libedit_private const wchar_t *ct_visual_string(const wchar_t *, ct_buffer_t *);
/* printable character, use ct_visual_width() to find out display width */
#define CHTYPE_PRINT ( 0)
/* control character found inside the ASCII portion of the charset */
#define CHTYPE_ASCIICTL (-1)
/* a \t */
#define CHTYPE_TAB (-2)
/* a \n */
#define CHTYPE_NL (-3)
/* non-printable character */
#define CHTYPE_NONPRINT (-4)
/* classification of character c, as one of the above defines */
libedit_private int ct_chr_class(wchar_t c);
#endif /* _chartype_f */

View file

@ -1,4 +1,4 @@
/* $NetBSD: common.c,v 1.40 2016/03/02 19:24:20 christos Exp $ */
/* $NetBSD: common.c,v 1.48 2018/02/26 17:36:14 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: common.c,v 1.40 2016/03/02 19:24:20 christos Exp $");
__RCSID("$NetBSD: common.c,v 1.48 2018/02/26 17:36:14 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* common.c: Common Editor functions
@ -51,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "common.h"
#include "fcns.h"
#include "parse.h"
#include "vi.h"
@ -58,7 +57,7 @@ __FBSDID("$FreeBSD$");
* Indicate end of file
* [^D]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -73,7 +72,7 @@ ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__)))
* Add character to the line
* Insert a character [bound to all insert keys]
*/
protected el_action_t
libedit_private el_action_t
ed_insert(EditLine *el, wint_t c)
{
int count = el->el_state.argument;
@ -93,14 +92,14 @@ ed_insert(EditLine *el, wint_t c)
|| el->el_line.cursor >= el->el_line.lastchar)
c_insert(el, 1);
*el->el_line.cursor++ = (Char)c;
*el->el_line.cursor++ = c;
re_fastaddc(el); /* fast refresh for one char. */
} else {
if (el->el_state.inputmode != MODE_REPLACE_1)
c_insert(el, el->el_state.argument);
while (count-- && el->el_line.cursor < el->el_line.lastchar)
*el->el_line.cursor++ = (Char)c;
*el->el_line.cursor++ = c;
re_refresh(el);
}
@ -115,11 +114,11 @@ ed_insert(EditLine *el, wint_t c)
* Delete from beginning of current word to cursor
* [M-^?] [^W]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *p, *kp;
wchar_t *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
@ -143,15 +142,14 @@ ed_delete_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Delete character under cursor
* [^D] [x]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
#ifdef DEBUG_EDIT
#define EL el->el_line
(void) fprintf(el->el_errfile,
"\nD(b: %p(" FSTR ") c: %p(" FSTR ") last: %p(" FSTR
") limit: %p(" FSTR ")\n",
"\nD(b: %p(%ls) c: %p(%ls) last: %p(%ls) limit: %p(%ls)\n",
EL.buffer, EL.buffer, EL.cursor, EL.cursor, EL.lastchar,
EL.lastchar, EL.limit, EL.limit);
#endif
@ -191,11 +189,11 @@ ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Cut to the end of line
* [^K] [^K]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
cp = el->el_line.cursor;
kp = el->el_chared.c_kill.buf;
@ -212,7 +210,7 @@ ed_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Move cursor to the end of line
* [^E] [^E]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -235,7 +233,7 @@ ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__)))
* Move cursor to the beginning of line
* [^A] [^A]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -244,7 +242,7 @@ ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
if (el->el_map.type == MAP_VI) {
/* We want FIRST non space character */
while (Isspace(*el->el_line.cursor))
while (iswspace(*el->el_line.cursor))
el->el_line.cursor++;
if (el->el_chared.c_vcmd.action != NOP) {
cv_delfini(el);
@ -259,7 +257,7 @@ ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__)))
* Exchange the character to the left of the cursor with the one under it
* [^T] [^T]
*/
protected el_action_t
libedit_private el_action_t
ed_transpose_chars(EditLine *el, wint_t c)
{
@ -273,7 +271,7 @@ ed_transpose_chars(EditLine *el, wint_t c)
/* must have at least two chars entered */
c = el->el_line.cursor[-2];
el->el_line.cursor[-2] = el->el_line.cursor[-1];
el->el_line.cursor[-1] = (Char)c;
el->el_line.cursor[-1] = c;
return CC_REFRESH;
} else
return CC_ERROR;
@ -284,11 +282,11 @@ ed_transpose_chars(EditLine *el, wint_t c)
* Move to the right one character
* [^F] [^F]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *lim = el->el_line.lastchar;
wchar_t *lim = el->el_line.lastchar;
if (el->el_line.cursor >= lim ||
(el->el_line.cursor == lim - 1 &&
@ -313,7 +311,7 @@ ed_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Move to the beginning of the current word
* [M-b] [b]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -339,7 +337,7 @@ ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Move to the left one character
* [^B] [^B]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -364,16 +362,18 @@ ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Add the next character typed verbatim
* [^V] [^V]
*/
protected el_action_t
ed_quoted_insert(EditLine *el, wint_t c)
libedit_private el_action_t
/*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);
}
@ -382,11 +382,11 @@ ed_quoted_insert(EditLine *el, wint_t c)
/* ed_digit():
* Adds to argument or enters a digit
*/
protected el_action_t
libedit_private el_action_t
ed_digit(EditLine *el, wint_t c)
{
if (!Isdigit(c))
if (!iswdigit(c))
return CC_ERROR;
if (el->el_state.doingarg) {
@ -410,11 +410,11 @@ ed_digit(EditLine *el, wint_t c)
* Digit that starts argument
* For ESC-n
*/
protected el_action_t
libedit_private el_action_t
ed_argument_digit(EditLine *el, wint_t c)
{
if (!Isdigit(c))
if (!iswdigit(c))
return CC_ERROR;
if (el->el_state.doingarg) {
@ -434,7 +434,7 @@ ed_argument_digit(EditLine *el, wint_t c)
* Indicates unbound character
* Bound to keys that are not assigned
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_unassigned(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
@ -444,17 +444,13 @@ ed_unassigned(EditLine *el __attribute__((__unused__)),
}
/**
** TTY key handling.
**/
/* ed_tty_sigint():
* Tty interrupt character
* [^C]
/* ed_ignore():
* Input characters that have no effect
* [^C ^O ^Q ^S ^Z ^\ ^]] [^C ^O ^Q ^S ^\]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_tty_sigint(EditLine *el __attribute__((__unused__)),
ed_ignore(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
@ -462,95 +458,11 @@ ed_tty_sigint(EditLine *el __attribute__((__unused__)),
}
/* ed_tty_dsusp():
* Tty delayed suspend character
* [^Y]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_dsusp(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_tty_flush_output():
* Tty flush output characters
* [^O]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_flush_output(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_tty_sigquit():
* Tty quit character
* [^\]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigquit(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_tty_sigtstp():
* Tty suspend character
* [^Z]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_sigtstp(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_tty_stop_output():
* Tty disallow output characters
* [^S]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_stop_output(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_tty_start_output():
* Tty allow output characters
* [^Q]
*/
protected el_action_t
/*ARGSUSED*/
ed_tty_start_output(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
{
return CC_NORM;
}
/* ed_newline():
* Execute command
* [^J]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -566,7 +478,7 @@ ed_newline(EditLine *el, wint_t c __attribute__((__unused__)))
* Delete the character to the left of the cursor
* [^?]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -586,7 +498,7 @@ ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Clear screen leaving current line at the top
* [^L]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -601,7 +513,7 @@ ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__)))
* Redisplay everything
* ^R
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_redisplay(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
@ -615,12 +527,12 @@ ed_redisplay(EditLine *el __attribute__((__unused__)),
* Erase current line and start from scratch
* [^G]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
{
ch_reset(el, 0);
ch_reset(el);
return CC_REFRESH;
}
@ -629,7 +541,7 @@ ed_start_over(EditLine *el, wint_t c __attribute__((__unused__)))
* First character in a bound sequence
* Placeholder for external keys
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
wint_t c __attribute__((__unused__)))
@ -643,7 +555,7 @@ ed_sequence_lead_in(EditLine *el __attribute__((__unused__)),
* Move to the previous history line
* [^P] [k]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -655,7 +567,7 @@ ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
if (el->el_history.eventno == 0) { /* save the current buffer
* away */
(void) Strncpy(el->el_history.buf, el->el_line.buffer,
(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
EL_BUFSIZ);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
@ -680,7 +592,7 @@ ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
* Move to the next history line
* [^N] [j]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -707,11 +619,11 @@ ed_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
* Search previous in history for a line matching the current
* next search history [M-P] [K]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
{
const Char *hp;
const wchar_t *hp;
int h;
int found = 0;
@ -727,7 +639,7 @@ ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
return CC_ERROR;
}
if (el->el_history.eventno == 0) {
(void) Strncpy(el->el_history.buf, el->el_line.buffer,
(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
EL_BUFSIZ);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
@ -748,7 +660,7 @@ ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
if ((Strncmp(hp, el->el_line.buffer, (size_t)
if ((wcsncmp(hp, el->el_line.buffer, (size_t)
(el->el_line.lastchar - el->el_line.buffer)) ||
hp[el->el_line.lastchar - el->el_line.buffer]) &&
c_hmatch(el, hp)) {
@ -775,11 +687,11 @@ ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__)))
* Search next in history for a line matching the current
* [M-N] [J]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
{
const Char *hp;
const wchar_t *hp;
int h;
int found = 0;
@ -803,7 +715,7 @@ ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp);
#endif
if ((Strncmp(hp, el->el_line.buffer, (size_t)
if ((wcsncmp(hp, el->el_line.buffer, (size_t)
(el->el_line.lastchar - el->el_line.buffer)) ||
hp[el->el_line.lastchar - el->el_line.buffer]) &&
c_hmatch(el, hp))
@ -829,11 +741,11 @@ ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__)))
* Move up one line
* Could be [k] [^p]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *ptr;
wchar_t *ptr;
int nchars = c_hpos(el);
/*
@ -872,11 +784,11 @@ ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Move down one line
* Could be [j] [^n]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *ptr;
wchar_t *ptr;
int nchars = c_hpos(el);
/*
@ -906,14 +818,14 @@ ed_next_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Editline extended command
* [M-X] [:]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
ed_command(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char tmpbuf[EL_BUFSIZ];
wchar_t tmpbuf[EL_BUFSIZ];
int tmplen;
tmplen = c_gets(el, tmpbuf, STR("\n: "));
tmplen = c_gets(el, tmpbuf, L"\n: ");
terminal__putc(el, '\n');
if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1)

View file

@ -1,4 +1,3 @@
/* $FreeBSD$ */
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
@ -48,13 +47,13 @@
/* #undef HAVE_LIBCURSES */
/* Define to 1 if you have the `ncurses' library (-lncurses). */
#define HAVE_LIBNCURSES 1
/* #undef HAVE_LIBNCURSES */
/* Define to 1 if you have the `termcap' library (-ltermcap). */
/* #undef HAVE_LIBTERMCAP */
/* Define to 1 if you have the `terminfo' library (-lterminfo). */
/* #undef HAVE_LIBTERMINFO */
#define HAVE_LIBTERMINFO 1
/* Define to 1 if you have the `termlib' library (-ltermlib). */
/* #undef HAVE_LIBTERMLIB */
@ -75,7 +74,7 @@
#define HAVE_MEMSET 1
/* Define to 1 if you have the <ncurses.h> header file. */
#define HAVE_NCURSES_H 1
/* #undef HAVE_NCURSES_H */
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
/* #undef HAVE_NDIR_H */
@ -257,9 +256,6 @@
/* Define to 1 if the system provides the SIZE_MAX constant */
#define HAVE_SIZE_MAX 1
/* Define to 1 if you want wide-character code */
/* #undef WIDECHAR */
/* Define to 1 if on MINIX. */
/* #undef _MINIX */
@ -284,7 +280,7 @@
#include "sys.h"
#undef SCCSID
#undef LIBC_SCCS
#undef lint
#undef SIZE_T_MAX
/* #undef SCCSID */
/* #undef LIBC_SCCS */
/* #undef lint */

View file

@ -1,4 +1,4 @@
.\" $NetBSD: editline.3,v 1.88 2016/02/25 14:59:22 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,9 +26,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd April 28, 2017
.Dd November 9, 2018
.Dt EDITLINE 3
.Os
.Sh NAME
@ -94,11 +92,11 @@
.Ft int
.Fn el_getc "EditLine *e" "char *ch"
.Ft int
.Fn el_wgetc "EditLine *e" "wchar_t *ch"
.Fn el_wgetc "EditLine *e" "wchar_t *wc"
.Ft void
.Fn el_push "EditLine *e" "const char *str"
.Fn el_push "EditLine *e" "const char *mbs"
.Ft void
.Fn el_wpush "EditLine *e" "const wchar_t *str"
.Fn el_wpush "EditLine *e" "const wchar_t *wcs"
.Ft int
.Fn el_parse "EditLine *e" "int argc" "const char *argv[]"
.Ft int
@ -115,7 +113,7 @@
.Fn el_source "EditLine *e" "const char *file"
.Ft void
.Fn el_resize "EditLine *e"
.Fn int
.Ft int
.Fn el_cursor "EditLine *e" "int count"
.Ft const LineInfo *
.Fn el_line "EditLine *e"
@ -183,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 ,
@ -252,18 +248,16 @@ The return value may not remain valid across calls to
and must be copied if the data is to be retained.
.It Fn el_wgetc
Read a wide character from the tty, respecting the current locale,
or from the input stream written by
.Fn el_wpush
and
.Fn el_push
or from the input queue described in
.Xr editline 7
if that is not empty, and store it in
.Fa ch .
.Fa wc .
If an invalid or incomplete character is found, it is discarded,
.Va errno
is set to
.Er EILSEQ ,
and the next character is read and stored in
.Fa ch .
.Fa wc .
Returns 1 if a valid character was read, 0 on end of file, or \-1 on
.Xr read 2
failure.
@ -286,17 +280,23 @@ to
and return \-1.
In the C or POSIX locale, this simply reads a byte, but for any other
locale, including UTF-8, this is rarely useful.
.It Fn el_wpush
Push the wide character string
.Fa wcs
back onto the input queue described in
.Xr editline 7 .
If the queue overflows, for example due to a recursive macro,
or if an error occurs, for example because
.Fa wcs
is
.Dv NULL
or memory allocation fails, the function beeps at the user,
but does not report the problem to the caller.
.It Fn el_push
Pushes
.Fa str
back onto the input stream.
This is used by the macro expansion mechanism.
Refer to the description of
.Ic bind
.Fl s
in
.Xr editrc 5
for more information.
Use the current locale to convert the multibyte string
.Fa mbs
to a wide character string, and pass the result to
.Fn el_wpush .
.It Fn el_parse
Parses the
.Fa argv
@ -356,6 +356,8 @@ terminal without affecting the state of the current line.
A subsequent second start/stop literal character ends this behavior.
This is typically used to embed literal escape sequences that change the
color/style of the terminal in the prompt.
Note that the literal escape character cannot be the last character in the
prompt, as the escape sequence is attached to the next character in the prompt.
.Dv 0
unsets it.
.It Dv EL_REFRESH
@ -505,18 +507,31 @@ unbuffered mode is disabled (the default).
In unbuffered mode,
.Fn el_gets
will return immediately after processing a single character.
.It Dv EL_GETCFN , Fa "int (*f)(EditLine *, char *c)"
Define the character reading function as
.Fa f ,
which is to return the number of characters read and store them in
.Fa c .
This function is called internally by
.Fn el_gets
.It Dv EL_GETCFN , Fa "el_rfunc_t f"
Whenever reading a character, use the function
.Bd -ragged -offset indent -compact
.Ft int
.Fo f
.Fa "EditLine *e"
.Fa "wchar_t *wc"
.Fc
.Ed
which stores the character in
.Fa wc
and returns 1 on success, 0 on end of file, or \-1 on I/O or encoding
errors.
Functions internally using it include
.Fn el_wgets ,
.Fn el_wgetc ,
.Fn el_gets ,
and
.Fn el_getc .
The builtin function can be set or restored with the special function
name
.Dq Dv EL_BUILTIN_GETCFN .
Initially, a builtin function is installed, and replacing it
is discouraged because writing such a function is very error prone.
The builtin function can be restored at any time by passing the
special value
.Dv EL_BUILTIN_GETCFN
instead of a function pointer.
.It Dv EL_CLIENTDATA , Fa "void *data"
Register
.Fa data
@ -560,7 +575,7 @@ are supported, along with actual type of
.Bl -tag -width 4n
.It Dv EL_PROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
Set
.Fa f .
.Fa f
to a pointer to the function that displays the prompt.
If
.Fa c
@ -569,7 +584,7 @@ is not
set it to the start/stop literal prompt character.
.It Dv EL_RPROMPT , Fa "char *(*f)(EditLine *)" , Fa "char *c"
Set
.Fa f .
.Fa f
to a pointer to the function that displays the prompt.
If
.Fa c
@ -594,7 +609,7 @@ to the current value of that capability.
.It Dv EL_SIGNAL , Fa "int *s"
Set
.Fa s
to non zero if
to non-zero if
.Nm
has installed private signal handlers (see
.Fn el_get
@ -603,10 +618,12 @@ above).
Set
.Fa c
to non-zero if editing is enabled.
.It Dv EL_GETCFN , Fa "int (**f)(EditLine *, char *)"
Return a pointer to the function that read characters, which is equal to
.Dq Dv EL_BUILTIN_GETCFN
in the case of the default builtin function.
.It Dv EL_GETCFN , Fa "el_rfunc_t *f"
Set
.Fa f
to a pointer to the function that reads characters, or to
.Dv EL_BUILTIN_GETCFN
if the builtin function is in use.
.It Dv EL_CLIENTDATA , Fa "void **data"
Set
.Fa data
@ -650,6 +667,8 @@ If
is
.Dv NULL ,
try
.Pa $EDITRC
and if that is not set
.Pa $HOME/.editrc .
Refer to
.Xr editrc 5
@ -763,8 +782,10 @@ Return the first element in the history.
Return the last element in the history.
.It Dv H_PREV
Return the previous element in the history.
It is newer than the current one.
.It Dv H_NEXT
Return the next element in the history.
It is older than the current one.
.It Dv H_CURR
Return the current element in the history.
.It Dv H_SET , Fa "int position"
@ -820,6 +841,13 @@ Save the history list to the opened
.Ft FILE
pointer
.Fa fp .
.It Dv H_NSAVE_FP , Fa "size_t n" , Fa "FILE *fp"
Save the last
.Ft n
history entries to the opened
.Ft FILE
pointer
.Fa fp .
.It Dv H_SETUNIQUE , Fa "int unique"
Set flag that adjacent identical event strings should not be entered
into the history.
@ -830,14 +858,14 @@ be entered into the history.
Delete the event numbered
.Fa e .
This function is only provided for
.Xr readline 3
.Nm readline
compatibility.
The caller is responsible for free'ing the string in the returned
.Fa HistEvent .
.El
.Pp
.Fn history
returns \*[Gt]= 0 if the operation
returns >= 0 if the operation
.Fa op
succeeds.
Otherwise, \-1 is returned and
@ -923,7 +951,8 @@ is a NUL terminated string to tokenize.
.Xr signal 3 ,
.Xr termcap 3 ,
.Xr editrc 5 ,
.Xr termcap 5
.Xr termcap 5 ,
.Xr editline 7
.Sh HISTORY
The
.Nm

935
contrib/libedit/editline.7 Normal file
View file

@ -0,0 +1,935 @@
.\" $NetBSD: editline.7,v 1.5 2016/05/09 21:27:55 christos Exp $
.\" $OpenBSD: editline.7,v 1.1 2016/04/20 01:11:45 schwarze Exp $
.\"
.\" Copyright (c) 2016 Ingo Schwarze <schwarze@openbsd.org>
.\"
.\" Permission to use, copy, modify, and distribute this software for any
.\" purpose with or without fee is hereby granted, provided that the above
.\" copyright notice and this permission notice appear in all copies.
.\"
.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd May 7, 2016
.Dt EDITLINE 7
.Os
.Sh NAME
.Nm editline
.Nd line editing user interface
.Sh DESCRIPTION
When a program using the
.Xr editline 3
library prompts for an input string using the function
.Xr el_wgets 3 ,
it reads characters from the terminal.
Invalid input bytes that do not form characters are silently
discarded.
For each character read, one editor command is executed.
The mapping of input characters to editor commands depends on the
editing mode.
There are three editing modes: vi insert mode, vi command mode,
and emacs mode.
The default is vi insert mode.
The program can switch the default to emacs mode by using the
.Xr el_set 3
or
.Xr el_parse 3
functions, and the user can switch to emacs mode either in the
.Xr editrc 5
configuration file or interactively with the
.Ic ed-command
editor command, in all three cases executing the
.Ic bind Fl e
builtin command.
.Pp
If trying to read from the terminal results in end of file or an
error, the library signals end of file to the program and does not
return a string.
.Ss Input character bindings
All default bindings described below can be overridden by individual
programs and can be changed with the
.Xr editrc 5
.Ic bind
builtin command.
.Pp
In the following tables,
.Sq Ctrl-
indicates a character with the bit 0x40 flipped, and
.Sq Meta-
indicates a character with the bit 0x80 set.
In vi insert mode and in emacs mode, all Meta-characters considered
printable by the current
.Xr locale 1
are bound to
.Ic ed-insert
instead of to the editor command listed below.
Consequently, in UTF-8 mode, most of the Meta-characters are not
directly accessible because their code points are occupied by
printable Unicode characters, and Meta-characters are usually input
using the
.Ic em-meta-next
editor command.
For example, to enter
.Sq Meta-B
in order to call the
.Ic ed-prev-word
editor command in emacs mode, call
.Ic em-meta-next
by pressing and releasing the escape key (or equivalently, Ctrl-[),
then press and release the
.Sq B
key.
If you have configured a Meta-key on your keyboard, for example
with
.Ql setxkbmap -option altwin:left_meta_win ,
the Ctrl-Meta-characters are directly accessible.
For example, to enter
.Sq Ctrl-Meta-H
in order to call the
.Ic ed-delete-prev-word
editor command in emacs mode, hold down the keys
.Sq Ctrl ,
.Sq Meta ,
and
.Sq H
at the same time.
Alternatively, press and release the escape key, then press and
release
.Sq Ctrl-H .
.Pp
In vi input mode, input characters are bound to the following editor
commands by default:
.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history"
.It Ctrl-D, EOF Ta Ic vi-list-or-eof
.It Ctrl-H, BS Ta Ic vi-delete-prev-char
.It Ctrl-J, LF Ta Ic ed-newline
.It Ctrl-M, CR Ta Ic ed-newline
.It Ctrl-Q Ta Ic ed-tty-start-output
.It Ctrl-S Ta Ic ed-tty-stop-output
.It Ctrl-U Ta Ic vi-kill-line-prev
.It Ctrl-V Ta Ic ed-quoted-insert
.It Ctrl-W Ta Ic ed-delete-prev-word
.It Ctrl-[, ESC Ta Ic vi-command-mode
.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit
.It Ctrl-?, DEL Ta Ic vi-delete-prev-char
.El
.Pp
All other input characters except the NUL character (Ctrl-@) are
bound to
.Ic ed-insert .
.Pp
In vi command mode, input characters are bound to the following
editor commands by default:
.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history"
.It Ctrl-A Ta Ic ed-move-to-beg
.It Ctrl-C, INT Ta Ic ed-tty-sigint
.It Ctrl-E Ta Ic ed-move-to-end
.It Ctrl-H, BS Ta Ic ed-delete-prev-char
.It Ctrl-J, LF Ta Ic ed-newline
.It Ctrl-K Ta Ic ed-kill-line
.It Ctrl-L, FF Ta Ic ed-clear-screen
.It Ctrl-M, CR Ta Ic ed-newline
.It Ctrl-N Ta Ic ed-next-history
.It Ctrl-O Ta Ic ed-tty-flush-output
.It Ctrl-P Ta Ic ed-prev-history
.It Ctrl-Q Ta Ic ed-tty-start-output
.It Ctrl-R Ta Ic ed-redisplay
.It Ctrl-S Ta Ic ed-tty-stop-output
.It Ctrl-U Ta Ic vi-kill-line-prev
.It Ctrl-W Ta Ic ed-delete-prev-word
.It Ctrl-[, ESC Ta Ic em-meta-next
.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit
.It Space Ta Ic ed-next-char
.It # Ta Ic vi-comment-out
.It $ Ta Ic ed-move-to-end
.It % Ta Ic vi-match
.It + Ta Ic ed-next-history
.It \&, Ta Ic vi-repeat-prev-char
.It - Ta Ic ed-prev-history
.It \&. Ta Ic vi-redo
.It / Ta Ic vi-search-prev
.It 0 Ta Ic vi-zero
.It 1 to 9 Ta Ic ed-argument-digit
.It \&: Ta Ic ed-command
.It \&; Ta Ic vi-repeat-next-char
.It \&? Ta Ic vi-search-next
.It @ Ta Ic vi-alias
.It A Ta Ic vi-add-at-eol
.It B Ta Ic vi-prev-big-word
.It C Ta Ic vi-change-to-eol
.It D Ta Ic ed-kill-line
.It E Ta Ic vi-end-big-word
.It F Ta Ic vi-prev-char
.It G Ta Ic vi-to-history-line
.It I Ta Ic vi-insert-at-bol
.It J Ta Ic ed-search-next-history
.It K Ta Ic ed-search-prev-history
.It N Ta Ic vi-repeat-search-prev
.It O Ta Ic ed-sequence-lead-in
.It P Ta Ic vi-paste-prev
.It R Ta Ic vi-replace-mode
.It S Ta Ic vi-substitute-line
.It T Ta Ic vi-to-prev-char
.It U Ta Ic vi-undo-line
.It W Ta Ic vi-next-big-word
.It X Ta Ic ed-delete-prev-char
.It Y Ta Ic vi-yank-end
.It \&[ Ta Ic ed-sequence-lead-in
.It ^ Ta Ic ed-move-to-beg
.It _ Ta Ic vi-history-word
.It a Ta Ic vi-add
.It b Ta Ic vi-prev-word
.It c Ta Ic vi-change-meta
.It d Ta Ic vi-delete-meta
.It e Ta Ic vi-end-word
.It f Ta Ic vi-next-char
.It h Ta Ic ed-prev-char
.It i Ta Ic vi-insert
.It j Ta Ic ed-next-history
.It k Ta Ic ed-prev-history
.It l Ta Ic ed-next-char
.It n Ta Ic vi-repeat-search-next
.It p Ta Ic vi-paste-next
.It r Ta Ic vi-replace-char
.It s Ta Ic vi-substitute-char
.It t Ta Ic vi-to-next-char
.It u Ta Ic vi-undo
.It v Ta Ic vi-histedit
.It w Ta Ic vi-next-word
.It x Ta Ic ed-delete-next-char
.It y Ta Ic vi-yank
.It \&| Ta Ic vi-to-column
.It ~ Ta Ic vi-change-case
.It Ctrl-?, DEL Ta Ic ed-delete-prev-char
.It Meta-O Ta Ic ed-sequence-lead-in
.It Meta-[ Ta Ic ed-sequence-lead-in
.El
.Pp
In emacs mode, input characters are bound to the following editor
commands by default:
.Bl -column -offset indent "Ctrl-Z, TSTP" "ed-search-next-history"
.It 0 to 9 Ta Ic ed-digit
.It Ctrl-@, NUL Ta Ic em-set-mark
.It Ctrl-A Ta Ic ed-move-to-beg
.It Ctrl-B Ta Ic ed-prev-char
.It Ctrl-C, INT Ta Ic ed-tty-sigint
.It Ctrl-D, EOF Ta Ic em-delete-or-list
.It Ctrl-E Ta Ic ed-move-to-end
.It Ctrl-F Ta Ic ed-next-char
.It Ctrl-H, BS Ta Ic em-delete-prev-char
.It Ctrl-J, LF Ta Ic ed-newline
.It Ctrl-K Ta Ic ed-kill-line
.It Ctrl-L, FF Ta Ic ed-clear-screen
.It Ctrl-M, CR Ta Ic ed-newline
.It Ctrl-N Ta Ic ed-next-history
.It Ctrl-O Ta Ic ed-tty-flush-output
.It Ctrl-P Ta Ic ed-prev-history
.It Ctrl-Q Ta Ic ed-tty-start-output
.It Ctrl-R Ta Ic ed-redisplay
.It Ctrl-S Ta Ic ed-tty-stop-output
.It Ctrl-T Ta Ic ed-transpose-chars
.It Ctrl-U Ta Ic ed-kill-line
.It Ctrl-V Ta Ic ed-quoted-insert
.It Ctrl-W Ta Ic em-kill-region
.It Ctrl-X Ta Ic ed-sequence-lead-in
.It Ctrl-Y Ta Ic em-yank
.It Ctrl-Z, TSTP Ta Ic ed-tty-sigtstp
.It Ctrl-[, ESC Ta Ic em-meta-next
.It Ctrl-\e, QUIT Ta Ic ed-tty-sigquit
.It Ctrl-] Ta Ic ed-tty-dsusp
.It Ctrl-?, DEL Ta Ic em-delete-prev-char
.It Ctrl-Meta-H Ta Ic ed-delete-prev-word
.It Ctrl-Meta-L Ta Ic ed-clear-screen
.It Ctrl-Meta-_ Ta Ic em-copy-prev-word
.It Meta-0 to 9 Ta Ic ed-argument-digit
.It Meta-B Ta Ic ed-prev-word
.It Meta-C Ta Ic em-capitol-case
.It Meta-D Ta Ic em-delete-next-word
.It Meta-F Ta Ic em-next-word
.It Meta-L Ta Ic em-lower-case
.It Meta-N Ta Ic ed-search-next-history
.It Meta-O Ta Ic ed-sequence-lead-in
.It Meta-P Ta Ic ed-search-prev-history
.It Meta-U Ta Ic em-upper-case
.It Meta-W Ta Ic em-copy-region
.It Meta-X Ta Ic ed-command
.It Meta-[ Ta Ic ed-sequence-lead-in
.It Meta-b Ta Ic ed-prev-word
.It Meta-c Ta Ic em-capitol-case
.It Meta-d Ta Ic em-delete-next-word
.It Meta-f Ta Ic em-next-word
.It Meta-l Ta Ic em-lower-case
.It Meta-n Ta Ic ed-search-next-history
.It Meta-p Ta Ic ed-search-prev-history
.It Meta-u Ta Ic em-upper-case
.It Meta-w Ta Ic em-copy-region
.It Meta-x Ta Ic ed-command
.It Ctrl-Meta-? Ta Ic ed-delete-prev-word
.El
.Pp
The remaining
.Xr ascii 7
characters in the range 0x20 to 0x7e are bound to
.Ic ed-insert .
.Pp
If standard output is not connected to a terminal device
or
.Xr el_set 3
was used to set
.Dv EL_EDITMODE
to 0, all input character bindings are disabled and all characters
typed are appended to the edit buffer.
In that case, the edit buffer is returned to the program after a
newline or carriage return character is typed, or after the first
character typed if
.Xr el_set 3
was used to set
.Dv EL_UNBUFFERED
to non-zero.
.Ss Editor commands
Most editor commands accept an optional argument.
The argument is entered by prefixing the editor command with one
or more of the editor commands
.Ic ed-argument-digit ,
.Ic ed-digit ,
.Ic em-universal-argument ,
or
.Ic vi-zero .
When an argument is not provided, it defaults to 1.
For most editor commands, the effect of an argument is to repeatedly
execute the command that number of times.
.Pp
When talking about a character string from a left character to a
right character, the left character is included in the string, while
the right character is not included.
.Pp
If an editor command causes an error, the input character is discarded,
no action occurs, and the terminal bell is rung.
In case of a non-fatal error, the terminal bell is also rung,
but the editor command takes effect anyway.
.Pp
In the following list, the default key bindings are listed after
each editor command.
.Bl -tag -width 4n
.It Ic ed-argument-digit Pq vi command: 1 to 9; emacs: Meta-0 to Meta-9
If in argument input mode, append the input digit to the argument
being read.
Otherwise, switch to argument input mode and use the input digit
as the most significant digit of the argument.
It is an error if the input character is not a digit or if the
existing argument is already greater than a million.
.It Ic ed-clear-screen Pq vi command: Ctrl-L; emacs: Ctrl-L, Ctrl-Meta-L
Clear the screen and display the edit buffer at the top.
Ignore any argument.
.It Ic ed-command Pq vi command: So \&: Sc ; emacs: Meta-X, Meta-x
Read a line from the terminal bypassing the normal line editing
functionality and execute that line as an
.Xr editrc 5
builtin command.
If in vi command mode, also switch back to vi insert mode.
Ignore any argument.
.It Ic ed-delete-next-char Pq vi command: x
Delete the character at the cursor position.
With an argument, delete that number of characters.
In emacs mode, it is an error if the cursor is at the end of the
edit buffer.
In vi mode, the last character in the edit buffer is deleted in
that case, and it is an error if the buffer is empty.
.It Ic ed-delete-prev-char Pq vi command: X, Ctrl-H, BS, Ctrl-?, DEL
Delete the character to the left of the cursor position.
With an argument, delete that number of characters.
It is an error if the cursor is at the beginning of the edit buffer.
.It Ic ed-delete-prev-word Pq vi: Ctrl-W; emacs: Ctrl-Meta-H, Ctrl-Meta-?
Move to the left to the closest beginning of a word, delete the
string from that position to the cursor, and save it to the cut
buffer.
With an argument, delete that number of words.
It is an error if the cursor is at the beginning of the edit buffer.
.It Ic ed-digit Pq emacs: 0 to 9
If in argument input mode, append the input digit to the argument
being read.
Otherwise, call
.Ic ed-insert .
It is an error if the input character is not a digit or if the
existing argument is already greater than a million.
.It Ic ed-end-of-file Pq not bound by default
Discard the edit buffer and indicate end of file to the program.
Ignore any argument.
.It Ic ed-ignore Pq various
Discard the input character and do nothing.
.It Ic ed-insert Pq vi input: almost all; emacs: printable characters
In insert mode, insert the input character left of the cursor
position.
In replace mode, overwrite the character at the cursor and move the
cursor to the right by one character position.
Accept an argument to do this repeatedly.
It is an error if the input character is the NUL character (Ctrl-@).
Failure to enlarge the edit buffer also results in an error.
.It Ic ed-kill-line Pq vi command: D, Ctrl-K; emacs: Ctrl-K, Ctrl-U
Delete the string from the cursor position to the end of the line
and save it to the cut buffer.
Ignore any argument.
.It Ic ed-move-to-beg Pq vi command: ^, Ctrl-A; emacs: Ctrl-A
In vi mode, move the cursor to the first non-space character in the
edit buffer.
In emacs mode, move the cursor to the beginning of the edit buffer.
Ignore any argument.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.It Ic ed-move-to-end Pq vi command: $, Ctrl-E; emacs: Ctrl-E
Move the cursor to the end of the edit buffer.
Ignore any argument.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.It Ic ed-newline Pq all modes: Ctrl-J, LF, Ctrl-M, CR
Append a newline character to the edit buffer and return the edit
buffer to the program.
Ignore any argument.
.It Ic ed-next-char Pq vi command: Space, l; emacs: Ctrl-F
Move the cursor one character position to the right.
With an argument, move by that number of characters.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer.
.It Ic ed-next-history Pq vi command: j, +, Ctrl-N; emacs: Ctrl-N
Replace the edit buffer with the next history line.
That line is older than the current line.
With an argument, go forward by that number of history lines.
It is a non-fatal error to advance by more lines than are available.
.It Ic ed-next-line Pq not bound by default
Move the cursor down one line.
With an argument, move down by that number of lines.
It is an error if the edit buffer does not contain enough newline
characters to the right of the cursor position.
.It Ic ed-prev-char Pq vi command: h; emacs: Ctrl-B
Move the cursor one character position to the left.
With an argument, move by that number of characters.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the beginning of the
edit buffer.
.It Ic ed-prev-history Pq vi command: k, -, Ctrl-P; emacs: Ctrl-P
Replace the edit buffer with the previous history line.
That line is newer than the current line.
With an argument, go back by that number of lines.
It is a non-fatal error to back up by more lines than are available.
.It Ic ed-prev-line Pq not bound by default
Move the cursor up one line.
With an argument, move up by that number of lines.
It is an error if the edit buffer does not contain enough newline
characters to the left of the cursor position.
.It Ic ed-prev-word Pq emacs: Meta-B, Meta-b
Move the cursor to the left to the closest beginning of a word.
With an argument, repeat that number of times.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the beginning of the
edit buffer.
.It Ic ed-quoted-insert Pq vi insert, emacs: Ctrl-V
Read one character from the terminal bypassing the normal line
editing functionality and call
.Ic ed-insert
on it.
If trying to read the character returns end of file or an error,
call
.Ic ed-end-of-file
instead.
.It Ic ed-redisplay Pq vi command, emacs: Ctrl-R
Redisplay everything.
Ignore any argument.
.It Ic ed-search-next-history Pq vi command: J; emacs: Meta-N, Meta-n
Replace the edit buffer with the next matching history entry.
.It Ic ed-search-prev-history Pq vi command: K; emacs: Meta-P, Meta-p
Replace the edit buffer with the previous matching history entry.
.It Ic ed-sequence-lead-in Pq vi cmd: O, \&[; emacs: Ctrl-X;\
both: Meta-O, Meta-[
Call a macro.
See the section about
.Sx Macros
below for details.
.It Ic ed-start-over Pq not bound by default
Discard the contents of the edit buffer and start from scratch.
Ignore any argument.
.It Ic ed-transpose-chars Pq emacs: Ctrl-T
Exchange the character at the cursor position with the one to the
left of it and move the cursor to the character to the right of the
two exchanged characters.
Ignore any argument.
It is an error if the cursor is at the beginning of the edit buffer
or if the edit buffer contains less than two characters.
.It Ic ed-unassigned Pq all characters not listed
This editor command always results in an error.
.It Ic em-capitol-case Pq emacs: Meta-C, Meta-c
Capitalize the string from the cursor to the end of the current
word.
That is, if it contains at least one alphabetic character, convert
the first alphabetic character to upper case, and convert all
characters to the right of it to lower case.
In any case, move the cursor to the next character after the end
of the current word.
.It Ic em-copy-prev-word Pq emacs: Ctrl-Meta-_
Copy the string from the beginning of the current word to the cursor
and insert it to the left of the cursor.
Move the cursor to the character after the inserted string.
It is an error if the cursor is at the beginning of the edit buffer.
.It Ic em-copy-region Pq emacs: Meta-W, Meta-w
Copy the string from the cursor to the mark to the cut buffer.
It is an error if the mark is not set.
.It Ic em-delete-next-word Pq emacs: Meta-D, Meta-d
Delete the string from the cursor to the end of the current word
and save it to the cut buffer.
It is an error if the cursor is at the end of the edit buffer.
.It Ic em-delete-or-list Pq emacs: Ctrl-D, EOF
If the cursor is not at the end of the line, delete the character
at the cursor.
If the edit buffer is empty, indicate end of file to the program.
It is an error if the cursor is at the end of the edit buffer and
the edit buffer is not empty.
.It Ic em-delete-prev-char Pq emacs: Ctrl-H, BS, Ctrl-?, DEL
Delete the character to the left of the cursor.
It is an error if the cursor is at the beginning of the edit buffer.
.It Ic em-exchange-mark Pq not bound by default
Exchange the cursor and the mark.
.It Ic em-gosmacs-transpose Pq not bound by default
Exchange the two characters to the left of the cursor.
It is an error if the cursor is on the first or second character
of the edit buffer.
.It Ic em-inc-search-next Pq not bound by default
Emacs incremental next search.
.It Ic em-inc-search-prev Pq not bound by default
Emacs incremental reverse search.
.It Ic em-kill-line Pq not bound by default
Delete the entire contents of the edit buffer and save it to the
cut buffer.
.It Ic em-kill-region Pq emacs: Ctrl-W
Delete the string from the cursor to the mark and save it to the
cut buffer.
It is an error if the mark is not set.
.It Ic em-lower-case Pq emacs: Meta-L, Meta-l
Convert the characters from the cursor to the end of the current
word to lower case.
.It Ic em-meta-next Pq vi command, emacs: Ctrl-[, ESC
Set the bit 0x80 on the next character typed.
Unless the resulting code point is printable, holding down the
.Sq Meta-
key while typing that character is a simpler way to achieve the
same effect.
.It Ic em-next-word Pq Meta-F, Meta-f
Move the cursor to the end of the current word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer.
.It Ic em-set-mark Pq emacs: Ctrl-Q, NUL
Set the mark at the current cursor position.
.It Ic em-toggle-overwrite Pq not bound by default
Switch from insert to overwrite mode or vice versa.
.It Ic em-universal-argument Pq not bound by default
If in argument input mode, multiply the argument by 4.
Otherwise, switch to argument input mode and set the argument to 4.
It is an error if the existing argument is already greater than a
million.
.It Ic em-upper-case Pq emacs: Meta-U, Meta-u
Convert the characters from the cursor to the end of the current
word to upper case.
.It Ic em-yank Pq emacs: Ctrl-Y
Paste the cut buffer to the left of the cursor.
.It Ic vi-add Pq vi command: a
Switch to vi insert mode.
Unless the cursor is already at the end of the edit buffer, move
it one character position to the right.
.It Ic vi-add-at-eol Pq vi command: A
Switch to vi insert mode and move the cursor to the end of the edit
buffer.
.It Ic vi-alias Pq vi command: @
If an alias function was defined by calling the
.Xr el_set 3
or
.Xr el_wset 3
function with the argument
.Dv EL_ALIAS_TEXT ,
read one character from the terminal bypassing the normal line
editing functionality, call the alias function passing the argument that was specified with
.Dv EL_ALIAS_TEXT
as the first argument and the character read, with an underscore
prepended, as the second argument, and pass the string returned
from the alias function to
.Xr el_wpush 3 .
It is an error if no alias function is defined or if trying to read
the character results in end of file or an error.
.It Ic vi-change-case Pq vi command: ~
Change the case of the character at the cursor and move the cursor
one character position to the right.
It is an error if the cursor is already at the end of the edit
buffer.
.It Ic vi-change-meta Pq vi command: c
Delete the string from the cursor to the position specified by the
following movement command and save a copy of it to the cut buffer.
When given twice in a row, instead delete the whole contents of the
edit buffer and save a copy of it to the cut buffer.
In either case, switch to vi insert mode after that.
.It Ic vi-change-to-eol Pq vi command: C
Delete the string from the cursor position to the end of the line
and save it to the cut buffer, then switch to vi insert mode.
.It Ic vi-command-mode Pq vi insert: Ctrl-[, ESC
Discard pending actions and arguments and switch to vi command mode.
Unless the cursor is already at the beginning of the edit buffer,
move it to the left by one character position.
.It Ic vi-comment-out Pq vi command: #
Insert a
.Sq #
character at the beginning of the edit buffer and return the edit
buffer to the program.
.It Ic vi-delete-meta Pq vi command: d
Delete the string from the cursor to the position specified by the
following movement command and save a copy of it to the cut buffer.
When given twice in a row, instead delete the whole contents of the
edit buffer and save a copy of it to the cut buffer.
.It Ic vi-delete-prev-char Pq vi insert: Ctrl-H, BS, Ctrl-?, DEL
Delete the character to the left of the cursor.
It is an error if the cursor is already at the beginning of the
edit buffer.
.It Ic vi-end-big-word Pq vi command: E
Move the cursor to the end of the current space delimited word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer.
.It Ic vi-end-word Pq vi command: e
Move the cursor to the end of the current word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer.
.It Ic vi-history-word Pq vi command: _
Insert the first word from the most recent history entry after the
cursor, move the cursor after to the character after the inserted
word, and switch to vi insert mode.
It is an error if there is no history entry or the most recent
history entry is empty.
.It Ic vi-insert Pq vi command: i
Enter insert mode.
.It Ic vi-insert-at-bol Pq vi command: I
Move the cursor to the beginning of the edit buffer and switch to
vi insert mode.
.It Ic vi-kill-line-prev Pq vi: Ctrl-U
Delete the string from the beginning of the edit buffer to the
cursor and save it to the cut buffer.
.It Ic vi-list-or-eof Pq vi insert: Ctrl-D, EOF
If the edit buffer is empty, indicate end of file to the program.
It is an error if the edit buffer is not empty.
.It Ic vi-match Pq vi command: %
Consider opening and closing parentheses, braces, and brackets as
delimiters.
If the cursor is not at a delimiter, move it to the right until it
gets to one, then move it to the matching delimiter.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if there is no delimiter at the cursor or in the
string to the right of the cursor, or if the first such delimiter
has no matching delimiter.
.It Ic vi-next-big-word Pq vi command: W
Move the cursor to the right to the beginning of the next space
delimited word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer or on its last character.
.It Ic vi-next-char Pq vi command: f
Read one character from the terminal bypassing the normal line
editing functionality and move the cursor to the right to the next
instance of that character in the edit buffer.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
If trying to read the character results in end of file or an error,
call
.Ic ed-end-of-file
instead.
It is an error if the character is not found searching to the right
in the edit buffer.
.It Ic vi-next-word Pq vi command: w
Move the cursor to the right to the beginning of the next word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the end of the edit
buffer or on its last character.
.It Ic vi-paste-next Pq vi command: p
Insert a copy of the cut buffer to the right of the cursor.
It is an error if the cut buffer is empty.
.It Ic vi-paste-prev Pq vi command: P
Insert a copy of the cut buffer to the left of the cursor.
It is an error if the cut buffer is empty.
.It Ic vi-prev-big-word Pq vi command: B
Move the cursor to the left to the next beginning of a space delimited
word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the beginning of the
edit buffer.
.It Ic vi-prev-char Pq vi command: F
Read one character from the terminal bypassing the normal line
editing functionality and move the cursor to the left to the next
instance of that character in the edit buffer.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
If trying to read the character results in end of file or an error,
call
.Ic ed-end-of-file
instead.
It is an error if the character is not found searching to the left
in the edit buffer.
.It Ic vi-prev-word Pq vi command: b
Move the cursor to the left to the next beginning of a word.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
It is an error if the cursor is already at the beginning of the
edit buffer.
.It Ic vi-redo Pq vi command: Sq \&.
Redo the last non-motion command.
.It Ic vi-repeat-next-char Pq vi command: Sq \&;
Repeat the most recent character search in the same search direction.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.It Ic vi-repeat-prev-char Pq vi command: Sq \&,
Repeat the most recent character search in the opposite search
direction.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.It Ic vi-repeat-search-next Pq vi command: n
Repeat the most recent history search in the same search direction.
.It Ic vi-repeat-search-prev Pq vi command: N
Repeat the most recent history search in the opposite search
direction.
.It Ic vi-replace-char Pq vi command: r
Switch to vi replace mode, and automatically switch back to vi
command mode after the next character typed.
See
.Ic ed-insert
for a description of replace mode.
It is an error if the cursor is at the end of the edit buffer.
.It Ic vi-replace-mode Pq vi command: R
Switch to vi replace mode.
This is a variant of vi insert mode; see
.Ic ed-insert
for the difference.
.It Ic vi-search-next Pq vi command: \&?
Replace the edit buffer with the next matching history entry.
.It Ic vi-search-prev Pq vi command: /
Replace the edit buffer with the previous matching history entry.
.It Ic vi-substitute-char Pq vi command: s
Delete the character at the cursor and switch to vi insert mode.
.It Ic vi-substitute-line Pq vi command: S
Delete the entire contents of the edit buffer, save a copy of it
in the cut buffer, and enter vi insert mode.
.It Ic vi-to-column Pq vi command: \&|
Move the cursor to the column specified as the argument.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.It Ic vi-to-history-line Pq vi command: G
Replace the edit buffer with the specified history entry.
.It Ic vi-to-next-char Pq vi command: t
Read one character from the terminal bypassing the normal line
editing functionality and move the cursor to the right to the
character before the next instance of that character in the edit
buffer.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
If trying to read the character results in end of file or an error,
call
.Ic ed-end-of-file
instead.
It is an error if the character is not found searching to the right
in the edit buffer.
.It Ic vi-to-prev-char Pq vi command: T
Read one character from the terminal bypassing the normal line
editing functionality and move the cursor to the left to the character
after the next instance of that character in the edit buffer.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
If trying to read the character results in end of file or an error,
call
.Ic ed-end-of-file
instead.
It is an error if the character is not found searching to the left
in the edit buffer.
.It Ic vi-undo Pq vi command: u
Undo the last change.
.It Ic vi-undo-line Pq vi command: U
Undo all changes to the edit buffer.
.It Ic vi-yank Pq vi command: y
Copy the string from the cursor to the position specified by the
following movement command to the cut buffer.
When given twice in a row, instead copy the whole contents of the
edit buffer to the cut buffer.
.It Ic vi-yank-end Pq vi command: Y
Copy the string from the cursor to the end of the edit buffer to
the cut buffer.
.It Ic vi-zero Pq vi command: 0
If in argument input mode, multiply the argument by ten.
Otherwise, move the cursor to the beginning of the edit buffer.
Can be used as a movement command after
.Ic vi_change_meta ,
.Ic vi_delete_meta ,
or
.Ic vi_yank .
.El
.Ss Macros
If an input character is bound to the editor command
.Ic ed-sequence-lead-in ,
.Nm
attempts to call a macro.
If the input character by itself forms the name of a macro, that
macro is executed.
Otherwise, additional input characters are read until the string
read forms the name of a macro, in which case that macro is executed,
or until the string read matches the beginning of none of the existing
macro names, in which case the string including the final, mismatching
character is discarded and the terminal bell is rung.
.Pp
There are two kinds of macros.
Command macros execute a single editor command.
Keyboard macros return a string of characters that is appended
as a new line to the
.Sx Input Queue .
.Pp
The following command macros are defined by default in vi command
mode and in emacs mode:
.Bl -column -offset indent "Esc O A, Esc O A" "em-exchange-mark"
.It Esc \&[ A, Esc O A Ta Ic ed-prev-history
.It Esc \&[ B, Esc O B Ta Ic ed-next-history
.It Esc \&[ C, Esc O C Ta Ic ed-next-char
.It Esc \&[ D, Esc O D Ta Ic ed-prev-char
.It Esc \&[ F, Esc O F Ta Ic ed-move-to-end
.It Esc \&[ H, Esc O H Ta Ic ed-move-to-beg
.El
.Pp
In vi command mode, they are also defined by default without the
initial escape character.
.Pp
In addition, the
.Nm
library tries to bind the strings generated by the arrow keys
as reported by the
.Xr terminfo 5
database to these editor commands, unless that would clobber
user settings.
.Pp
In emacs mode, the two-character string
.Dq Ctrl-X Ctrl-X
is bound to the
.Ic em-exchange-mark
editor command.
.Ss Input Queue
The
.Nm
library maintains an input queue operated in FIFO mode.
Whenever it needs an input character, it takes the first character
from the first line of the input queue.
When the queue is empty, it reads from the terminal.
.Pp
A line can be appended to the end of the input queue in several ways:
.Bl -dash -offset indent
.It
By calling one of the keyboard
.Sx Macros .
.It
By calling the editor command
.Ic vi-redo .
.It
By calling the editor command
.Ic vi-alias .
.It
By pressing a key in emacs incremental search mode that doesn't
have a special meaning in that mode but returns to normal emacs
mode.
.It
If an application program directly calls the functions
.Xr el_push 3
or
.Xr el_wpush 3 ,
it can provide additional, program-specific ways
of appending to the input queue.
.El
.Sh SEE ALSO
.Xr mg 1 ,
.Xr vi 1 ,
.Xr editline 3 ,
.Xr el_wgets 3 ,
.Xr el_wpush 3 ,
.Xr el_wset 3 ,
.Xr editrc 5
.Sh HISTORY
This manual page first appeared in
.Ox 6.0
and
.Nx 8 .
.Sh AUTHORS
.An -nosplit
This manual page was written by
.An Ingo Schwarze Aq Mt schwarze@openbsd.org .

325
contrib/libedit/editrc.5 Normal file
View file

@ -0,0 +1,325 @@
.\" $NetBSD: editrc.5,v 1.33 2017/06/27 01:22:58 kre Exp $
.\"
.\" Copyright (c) 1997-2000 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd May 22, 2016
.Dt EDITRC 5
.Os
.Sh NAME
.Nm editrc
.Nd configuration file for editline library
.Sh SYNOPSIS
.Nm
.Sh DESCRIPTION
The
.Nm
file defines various settings to be used by the
.Xr editline 3
library.
.Pp
The format of each line is:
.Pp
.Dl [prog:]command [arg ...]
.Pp
.Ar command
is one of the
.Xr editline 3
builtin commands.
Refer to
.Sx BUILTIN COMMANDS
for more information.
.Pp
.Ar prog
is the program name string that a program defines when it calls
.Xr el_init 3
to set up
.Xr editline 3 ,
which is usually
.Va argv[0] .
.Ar command
will be executed for any program which matches
.Ar prog .
.Pp
.Ar prog
may also be a
.Xr regex 3
style
regular expression, in which case
.Ar command
will be executed for any program that matches the regular expression.
.Pp
If
.Ar prog
is absent,
.Ar command
is executed for all programs.
.Sh BUILTIN COMMANDS
The
.Nm editline
library has some builtin commands, which affect the way
that the line editing and history functions operate.
These are based on similar named builtins present in the
.Xr tcsh 1
shell.
.Pp
The following builtin commands are available:
.Bl -tag -width 4n
.It Ic bind Oo Fl aeklrsv Oc Op Ar key Op Ar command
Without options and arguments, list all bound keys and macros, and
the editor command or input string to which each one is bound.
If only
.Ar key
is supplied, show the binding for that key or macro.
If
.Ar key command
is supplied, bind the editor
.Ar command
to that key or macro.
.Pp
The options are as follows:
.Bl -tag -width 4n
.It Fl a
List or change key bindings in the
.Xr vi 1
mode alternate (command mode) key map.
.It Fl e
Bind all keys to the standard GNU Emacs-like bindings.
.It Fl k
.Ar key
is interpreted as a symbolic arrow key name, which may be one of
.Sq up ,
.Sq down ,
.Sq left
or
.Sq right .
.It Fl l
List all editor commands and a short description of each.
.It Fl r
Remove the binding of the key or macro
.Ar key .
.It Fl s
Define a keyboard macro rather than a key binding or command macro:
.Ar command
is taken as a literal string and appended to the input queue whenever
.Ar key
is typed.
Bound keys and macros in
.Ar command
are themselves reinterpreted, and this continues for ten levels of
interpretation.
.It Fl v
Bind all keys to the standard
.Xr vi 1 Ns -like
bindings.
.El
.Pp
The
.Xr editline 7
manual documents all editor commands and contains more information
about macros and the input queue.
.Pp
.Ar key
and
.Ar command
can contain control characters of the form
.Sm off
.Sq No ^ Ar character
.Sm on
.Po
e.g.\&
.Sq ^A
.Pc ,
and the following backslashed escape sequences:
.Pp
.Bl -tag -compact -offset indent -width 4n
.It Ic \ea
Bell
.It Ic \eb
Backspace
.It Ic \ee
Escape
.It Ic \ef
Formfeed
.It Ic \en
Newline
.It Ic \er
Carriage return
.It Ic \et
Horizontal tab
.It Ic \ev
Vertical tab
.Sm off
.It Sy \e Ar nnn
.Sm on
The ASCII character corresponding to the octal number
.Ar nnn .
.El
.Pp
.Sq \e
nullifies the special meaning of the following character,
if it has any, notably
.Sq \e
and
.Sq ^ .
.It Ic echotc Oo Fl sv Oc Ar arg Ar ...
Exercise terminal capabilities given in
.Ar arg ... .
If
.Ar arg
is
.Sq baud ,
.Sq cols ,
.Sq lines ,
.Sq rows ,
.Sq meta ,
or
.Sq tabs ,
the value of that capability is printed, with
.Dq yes
or
.Dq no
indicating that the terminal does or does not have that capability.
.Pp
.Fl s
returns an empty string for non-existent capabilities, rather than
causing an error.
.Fl v
causes messages to be verbose.
.It Ic edit Op Li on | Li off
Enable or disable the
.Nm editline
functionality in a program.
.It Ic history Ar list | Ar size Dv n | Ar unique Dv n
The
.Ar list
command lists all entries in the history.
The
.Ar size
command sets the history size to
.Dv n
entries.
The
.Ar unique
command controls if history should keep duplicate entries.
If
.Dv n
is non zero, only keep unique history entries.
If
.Dv n
is zero, then keep all entries (the default).
.It Ic settc Ar cap Ar val
Set the terminal capability
.Ar cap
to
.Ar val ,
as defined in
.Xr termcap 5 .
No sanity checking is done.
.It Ic setty Oo Fl a Oc Oo Fl d Oc Oo Fl q Oc Oo Fl x Oc Oo Ar +mode Oc \
Oo Ar -mode Oc Oo Ar mode Oc Oo Ar char=c Oc
Control which tty modes that
.Nm
won't allow the user to change.
.Fl d ,
.Fl q
or
.Fl x
tells
.Ic setty
to act on the
.Sq edit ,
.Sq quote
or
.Sq execute
set of tty modes respectively; defaulting to
.Fl x .
.Pp
Without other arguments,
.Ic setty
lists the modes in the chosen set which are fixed on
.Po
.Sq +mode
.Pc
or off
.Po
.Sq -mode
.Pc .
.Fl a
lists all tty modes in the chosen set regardless of the setting.
With
.Ar +mode ,
.Ar -mode
or
.Ar mode ,
fixes
.Ar mode
on or off or removes control of
.Ar mode
in the chosen set.
.Pp
.Ic Setty
can also be used to set tty characters to particular values using
.Ar char=value .
If
.Ar value
is empty
then the character is set to
.Dv _POSIX_VDISABLE .
.It Ic telltc
List the values of all the terminal capabilities (see
.Xr termcap 5 ) .
.El
.Sh ENVIRONMENT
.Bl -tag -width "~/.editrcXXX"
.It Ev EDITRC
Names the default configuration file for the
.Xr editline 3
library.
.El
.Sh FILES
.Bl -tag -width "~/.editrcXXX"
.It Pa ~/.editrc
Last resort, if no other file is specified,
user configuration file for the
.Xr editline 3
library.
.El
.Sh SEE ALSO
.Xr editline 3 ,
.Xr regex 3 ,
.Xr termcap 5 ,
.Xr editline 7
.Sh AUTHORS
.An -nosplit
The
.Nm editline
library was written by
.An Christos Zoulas ,
and this manual was written by
.An Luke Mewburn ,
with some sections inspired by
.Xr tcsh 1 .

View file

@ -1,4 +1,4 @@
/* $NetBSD: el.c,v 1.83 2016/02/24 17:13:22 christos Exp $ */
/* $NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94";
#else
__RCSID("$NetBSD: el.c,v 1.83 2016/02/24 17:13:22 christos Exp $");
__RCSID("$NetBSD: el.c,v 1.99 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* el.c: EditLine interface functions
@ -49,38 +47,35 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/param.h>
#include <ctype.h>
#include <langinfo.h>
#include <locale.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#ifdef WIDECHAR
#include <locale.h>
#include <langinfo.h>
#endif
#include "el.h"
#include "parse.h"
#include "read.h"
/* el_init():
* Initialize editline and set default parameters.
*/
public EditLine *
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)
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;
@ -89,7 +84,7 @@ el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
el->el_outfd = fdout;
el->el_errfd = fderr;
el->el_prog = Strdup(ct_decode_string(prog, &el->el_scratch));
el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch));
if (el->el_prog == NULL) {
el_free(el);
return NULL;
@ -98,7 +93,7 @@ el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
/*
* Initialize all the modules. Order is important!!!
*/
el->el_flags = 0;
el->el_flags = flags;
if (terminal_init(el) == -1) {
el_free(el->el_prog);
@ -114,16 +109,25 @@ el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
(void) hist_init(el);
(void) prompt_init(el);
(void) sig_init(el);
(void) read_init(el);
(void) literal_init(el);
if (read_init(el) == -1) {
el_end(el);
return NULL;
}
return el;
}
EditLine *
el_init_fd(const char *prog, FILE *fin, FILE *fout, FILE *ferr,
int fdin, int fdout, int fderr)
{
return el_init_internal(prog, fin, fout, ferr, fdin, fdout, fderr, 0);
}
/* el_end():
* Clean up.
*/
public void
void
el_end(EditLine *el)
{
@ -136,20 +140,22 @@ 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);
hist_end(el);
prompt_end(el);
sig_end(el);
literal_end(el);
el_free(el->el_prog);
#ifdef WIDECHAR
el_free(el->el_visual.cbuff);
el_free(el->el_visual.wbuff);
el_free(el->el_scratch.cbuff);
el_free(el->el_scratch.wbuff);
el_free(el->el_lgcyconv.cbuff);
el_free(el->el_lgcyconv.wbuff);
#endif
el_free(el);
}
@ -157,20 +163,20 @@ el_end(EditLine *el)
/* el_reset():
* Reset the tty and the parser
*/
public void
void
el_reset(EditLine *el)
{
tty_cookedmode(el);
ch_reset(el, 0); /* XXX: Do we want that? */
ch_reset(el); /* XXX: Do we want that? */
}
/* el_set():
* set the editline parameters
*/
public int
FUN(el,set)(EditLine *el, int op, ...)
int
el_wset(EditLine *el, int op, ...)
{
va_list ap;
int rv = 0;
@ -207,7 +213,7 @@ FUN(el,set)(EditLine *el, int op, ...)
el_pfunc_t p = va_arg(ap, el_pfunc_t);
int c = va_arg(ap, int);
rv = prompt_set(el, p, (Char)c, op, 1);
rv = prompt_set(el, p, (wchar_t)c, op, 1);
break;
}
@ -216,7 +222,7 @@ FUN(el,set)(EditLine *el, int op, ...)
break;
case EL_EDITOR:
rv = map_set_editor(el, va_arg(ap, Char *));
rv = map_set_editor(el, va_arg(ap, wchar_t *));
break;
case EL_SIGNAL:
@ -232,36 +238,36 @@ FUN(el,set)(EditLine *el, int op, ...)
case EL_ECHOTC:
case EL_SETTY:
{
const Char *argv[20];
const wchar_t *argv[20];
int i;
for (i = 1; i < (int)__arraycount(argv); i++)
if ((argv[i] = va_arg(ap, Char *)) == NULL)
if ((argv[i] = va_arg(ap, wchar_t *)) == NULL)
break;
switch (op) {
case EL_BIND:
argv[0] = STR("bind");
argv[0] = L"bind";
rv = map_bind(el, i, argv);
break;
case EL_TELLTC:
argv[0] = STR("telltc");
argv[0] = L"telltc";
rv = terminal_telltc(el, i, argv);
break;
case EL_SETTC:
argv[0] = STR("settc");
argv[0] = L"settc";
rv = terminal_settc(el, i, argv);
break;
case EL_ECHOTC:
argv[0] = STR("echotc");
argv[0] = L"echotc";
rv = terminal_echotc(el, i, argv);
break;
case EL_SETTY:
argv[0] = STR("setty");
argv[0] = L"setty";
rv = tty_stty(el, i, argv);
break;
@ -275,8 +281,8 @@ FUN(el,set)(EditLine *el, int op, ...)
case EL_ADDFN:
{
Char *name = va_arg(ap, Char *);
Char *help = va_arg(ap, Char *);
wchar_t *name = va_arg(ap, wchar_t *);
wchar_t *help = va_arg(ap, wchar_t *);
el_func_t func = va_arg(ap, el_func_t);
rv = map_addfunc(el, name, help, func);
@ -305,7 +311,7 @@ FUN(el,set)(EditLine *el, int op, ...)
case EL_GETCFN:
{
el_rfunc_t rc = va_arg(ap, el_rfunc_t);
rv = el_read_setfn(el, rc);
rv = el_read_setfn(el->el_read, rc);
break;
}
@ -382,8 +388,8 @@ FUN(el,set)(EditLine *el, int op, ...)
/* el_get():
* retrieve the editline parameters
*/
public int
FUN(el,get)(EditLine *el, int op, ...)
int
el_wget(EditLine *el, int op, ...)
{
va_list ap;
int rv;
@ -403,14 +409,14 @@ FUN(el,get)(EditLine *el, int op, ...)
case EL_PROMPT_ESC:
case EL_RPROMPT_ESC: {
el_pfunc_t *p = va_arg(ap, el_pfunc_t *);
Char *c = va_arg(ap, Char *);
wchar_t *c = va_arg(ap, wchar_t *);
rv = prompt_get(el, p, c, op);
break;
}
case EL_EDITOR:
rv = map_get_editor(el, va_arg(ap, const Char **));
rv = map_get_editor(el, va_arg(ap, const wchar_t **));
break;
case EL_SIGNAL:
@ -431,20 +437,16 @@ FUN(el,get)(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;
}
case EL_GETCFN:
*va_arg(ap, el_rfunc_t *) = el_read_getfn(el);
*va_arg(ap, el_rfunc_t *) = el_read_getfn(el->el_read);
rv = 0;
break;
@ -495,18 +497,18 @@ FUN(el,get)(EditLine *el, int op, ...)
/* el_line():
* Return editing info
*/
public const TYPE(LineInfo) *
FUN(el,line)(EditLine *el)
const LineInfoW *
el_wline(EditLine *el)
{
return (const TYPE(LineInfo) *)(void *)&el->el_line;
return (const LineInfoW *)(void *)&el->el_line;
}
/* el_source():
* Source a file
*/
public int
int
el_source(EditLine *el, const char *fname)
{
FILE *fp;
@ -514,24 +516,28 @@ el_source(EditLine *el, const char *fname)
ssize_t slen;
char *ptr;
char *path = NULL;
const Char *dptr;
const wchar_t *dptr;
int error = 0;
fp = NULL;
if (fname == NULL) {
#ifdef HAVE_ISSETUGID
static const char elpath[] = "/.editrc";
size_t plen = sizeof(elpath);
if (issetugid())
return -1;
if ((ptr = getenv("HOME")) == NULL)
return -1;
plen += strlen(ptr);
if ((path = el_malloc(plen * sizeof(*path))) == NULL)
return -1;
(void)snprintf(path, plen, "%s%s", ptr, elpath);
fname = path;
if ((fname = getenv("EDITRC")) == NULL) {
static const char elpath[] = "/.editrc";
size_t plen = sizeof(elpath);
if ((ptr = getenv("HOME")) == NULL)
return -1;
plen += strlen(ptr);
if ((path = el_calloc(plen, sizeof(*path))) == NULL)
return -1;
(void)snprintf(path, plen, "%s%s", ptr,
elpath + (*ptr == '\0'));
fname = path;
}
#else
/*
* If issetugid() is missing, always return an error, in order
@ -541,6 +547,9 @@ el_source(EditLine *el, const char *fname)
return -1;
#endif
}
if (fname[0] == '\0')
return -1;
if (fp == NULL)
fp = fopen(fname, "r");
if (fp == NULL) {
@ -560,7 +569,7 @@ el_source(EditLine *el, const char *fname)
if (!dptr)
continue;
/* loop until first non-space char or EOL */
while (*dptr != '\0' && Isspace(*dptr))
while (*dptr != '\0' && iswspace(*dptr))
dptr++;
if (*dptr == '#')
continue; /* ignore, this is a comment line */
@ -578,7 +587,7 @@ el_source(EditLine *el, const char *fname)
/* el_resize():
* Called from program when terminal is resized
*/
public void
void
el_resize(EditLine *el)
{
int lins, cols;
@ -599,7 +608,7 @@ el_resize(EditLine *el)
/* el_beep():
* Called from the program to beep
*/
public void
void
el_beep(EditLine *el)
{
@ -610,25 +619,25 @@ el_beep(EditLine *el)
/* el_editmode()
* Set the state of EDIT_DISABLED from the `edit' command.
*/
protected int
libedit_private int
/*ARGSUSED*/
el_editmode(EditLine *el, int argc, const Char **argv)
el_editmode(EditLine *el, int argc, const wchar_t **argv)
{
const Char *how;
const wchar_t *how;
if (argv == NULL || argc != 2 || argv[1] == NULL)
return -1;
how = argv[1];
if (Strcmp(how, STR("on")) == 0) {
if (wcscmp(how, L"on") == 0) {
el->el_flags &= ~EDIT_DISABLED;
tty_rawmode(el);
} else if (Strcmp(how, STR("off")) == 0) {
} else if (wcscmp(how, L"off") == 0) {
tty_cookedmode(el);
el->el_flags |= EDIT_DISABLED;
}
else {
(void) fprintf(el->el_errfile, "edit: Bad value `" FSTR "'.\n",
(void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n",
how);
return -1;
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: el.h,v 1.34 2016/02/24 17:13:22 christos Exp $ */
/* $NetBSD: el.h,v 1.45 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)el.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -57,6 +56,7 @@
#define EDIT_DISABLED 0x04
#define UNBUFFERED 0x08
#define NARROW_HISTORY 0x40
#define NO_RESET 0x80
typedef unsigned char el_action_t; /* Index to command array */
@ -66,10 +66,10 @@ typedef struct coord_t { /* Position on the screen */
} coord_t;
typedef struct el_line_t {
Char *buffer; /* Input line */
Char *cursor; /* Cursor position */
Char *lastchar; /* Last character */
const Char *limit; /* Max position */
wchar_t *buffer; /* Input line */
wchar_t *cursor; /* Cursor position */
wchar_t *lastchar; /* Last character */
const wchar_t *limit; /* Max position */
} el_line_t;
/*
@ -82,31 +82,33 @@ typedef struct el_state_t {
int metanext; /* Is the next char a meta char */
el_action_t lastcmd; /* Previous command */
el_action_t thiscmd; /* this command */
Char thisch; /* char that generated it */
wchar_t thisch; /* char that generated it */
} 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)
#include "tty.h"
#include "prompt.h"
#include "literal.h"
#include "keymacro.h"
#include "terminal.h"
#include "refresh.h"
#include "chared.h"
#include "search.h"
#include "hist.h"
#include "fcns.h" /* el_func_t is needed for map.h */
#include "map.h"
#include "sig.h"
#include "read.h"
struct el_read_t;
struct editline {
Char *el_prog; /* the program name */
wchar_t *el_prog; /* the program name */
FILE *el_infile; /* Stdio stuff */
FILE *el_outfile; /* Stdio stuff */
FILE *el_errfile; /* Stdio stuff */
@ -114,10 +116,9 @@ struct editline {
int el_outfd; /* Output file descriptor */
int el_errfd; /* Error file descriptor */
int el_flags; /* Various flags. */
int el_errno; /* Local copy of errno */
coord_t el_cursor; /* Cursor location */
Char **el_display; /* Real screen image = what is there */
Char **el_vdisplay; /* Virtual screen image = what we see */
wint_t **el_display; /* Real screen image = what is there */
wint_t **el_vdisplay; /* Virtual screen image = what we see */
void *el_data; /* Client data */
el_line_t el_line; /* The current line information */
el_state_t el_state; /* Current editor state */
@ -126,21 +127,23 @@ struct editline {
el_refresh_t el_refresh; /* Refresh stuff */
el_prompt_t el_prompt; /* Prompt stuff */
el_prompt_t el_rprompt; /* Prompt stuff */
el_literal_t el_literal; /* prompt literal bits */
el_chared_t el_chared; /* Characted editor stuff */
el_map_t el_map; /* Key mapping stuff */
el_keymacro_t el_keymacro; /* Key binding stuff */
el_history_t el_history; /* History stuff */
el_search_t el_search; /* Search stuff */
el_signal_t el_signal; /* Signal handling stuff */
el_read_t el_read; /* Character reading stuff */
#ifdef WIDECHAR
struct el_read_t *el_read; /* Character reading stuff */
ct_buffer_t el_visual; /* Buffer for displayable str */
ct_buffer_t el_scratch; /* Scratch conversion buffer */
ct_buffer_t el_lgcyconv; /* Buffer for legacy wrappers */
LineInfo el_lgcylinfo; /* Legacy LineInfo buffer */
#endif
};
protected int el_editmode(EditLine *, int, const Char **);
libedit_private int el_editmode(EditLine *, int, const wchar_t **);
libedit_private EditLine *el_init_internal(const char *, FILE *, FILE *,
FILE *, int, int, int, int);
#ifdef DEBUG
#define EL_ABORT(a) do { \

View file

@ -1,4 +1,4 @@
/* $NetBSD: eln.c,v 1.28 2016/02/28 23:02:24 christos Exp $ */
/* $NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $ */
/*-
* Copyright (c) 2009 The NetBSD Foundation, Inc.
@ -27,10 +27,8 @@
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: eln.c,v 1.28 2016/02/28 23:02:24 christos Exp $");
__RCSID("$NetBSD: eln.c,v 1.35 2019/04/26 16:56:57 christos Exp $");
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <errno.h>
#include <stdarg.h>
@ -39,7 +37,7 @@ __FBSDID("$FreeBSD$");
#include "el.h"
public int
int
el_getc(EditLine *el, char *cp)
{
int num_read;
@ -49,7 +47,7 @@ el_getc(EditLine *el, char *cp)
*cp = '\0';
if (num_read <= 0)
return num_read;
num_read = ct_wctob(wc);
num_read = wctob(wc);
if (num_read == EOF) {
errno = ERANGE;
return -1;
@ -60,8 +58,7 @@ el_getc(EditLine *el, char *cp)
}
#ifdef WIDECHAR
public void
void
el_push(EditLine *el, const char *str)
{
/* Using multibyte->wide string decoding works fine under single-byte
@ -70,7 +67,7 @@ el_push(EditLine *el, const char *str)
}
public const char *
const char *
el_gets(EditLine *el, int *nread)
{
const wchar_t *tmp;
@ -88,24 +85,23 @@ el_gets(EditLine *el, int *nread)
}
public int
int
el_parse(EditLine *el, int argc, const char *argv[])
{
int ret;
const wchar_t **wargv;
wargv = (const wchar_t **)
ct_decode_argv(argc, argv, &el->el_lgcyconv);
wargv = (void *)ct_decode_argv(argc, argv, &el->el_lgcyconv);
if (!wargv)
return -1;
ret = el_wparse(el, argc, wargv);
ct_free_argv(wargv);
el_free(wargv);
return ret;
}
public int
int
el_set(EditLine *el, int op, ...)
{
va_list ap;
@ -174,8 +170,7 @@ el_set(EditLine *el, int op, ...)
if ((argv[i] = va_arg(ap, const char *)) == NULL)
break;
argv[0] = argv[i] = NULL;
wargv = (const wchar_t **)
ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
wargv = (void *)ct_decode_argv(i + 1, argv, &el->el_lgcyconv);
if (!wargv) {
ret = -1;
goto out;
@ -187,29 +182,29 @@ el_set(EditLine *el, int op, ...)
*/
switch (op) {
case EL_BIND:
wargv[0] = STR("bind");
wargv[0] = L"bind";
ret = map_bind(el, i, wargv);
break;
case EL_TELLTC:
wargv[0] = STR("telltc");
wargv[0] = L"telltc";
ret = terminal_telltc(el, i, wargv);
break;
case EL_SETTC:
wargv[0] = STR("settc");
wargv[0] = L"settc";
ret = terminal_settc(el, i, wargv);
break;
case EL_ECHOTC:
wargv[0] = STR("echotc");
wargv[0] = L"echotc";
ret = terminal_echotc(el, i, wargv);
break;
case EL_SETTY:
wargv[0] = STR("setty");
wargv[0] = L"setty";
ret = tty_stty(el, i, wargv);
break;
default:
ret = -1;
}
ct_free_argv(wargv);
el_free(wargv);
break;
}
@ -229,9 +224,9 @@ el_set(EditLine *el, int op, ...)
goto out;
}
/* XXX: The two strdup's leak */
ret = map_addfunc(el, Strdup(wargv[0]), Strdup(wargv[1]),
ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]),
func);
ct_free_argv(wargv);
el_free(wargv);
break;
}
case EL_HIST: { /* hist_fun_t, const char * */
@ -275,7 +270,7 @@ el_set(EditLine *el, int op, ...)
}
public int
int
el_get(EditLine *el, int op, ...)
{
va_list ap;
@ -326,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;
}
@ -368,7 +361,7 @@ el_line(EditLine *el)
const LineInfoW *winfo = el_wline(el);
LineInfo *info = &el->el_lgcylinfo;
size_t offset;
const Char *p;
const wchar_t *p;
info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv);
@ -391,4 +384,3 @@ el_insertstr(EditLine *el, const char *str)
{
return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv));
}
#endif /* WIDECHAR */

View file

@ -1,4 +1,4 @@
/* $NetBSD: emacs.c,v 1.32 2016/02/16 22:53:14 christos Exp $ */
/* $NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: emacs.c,v 1.32 2016/02/16 22:53:14 christos Exp $");
__RCSID("$NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* emacs.c: Emacs functions
@ -50,12 +48,13 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "emacs.h"
#include "fcns.h"
/* em_delete_or_list():
* Delete character under cursor or list completions if at end of line
* [^D]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_delete_or_list(EditLine *el, wint_t c)
{
@ -91,11 +90,11 @@ em_delete_or_list(EditLine *el, wint_t c)
* Cut from cursor to end of current word
* [M-d]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_delete_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *p, *kp;
wchar_t *cp, *p, *kp;
if (el->el_line.cursor == el->el_line.lastchar)
return CC_ERROR;
@ -120,11 +119,11 @@ em_delete_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Paste cut buffer at cursor position
* [^Y]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_yank(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
if (el->el_chared.c_kill.last == el->el_chared.c_kill.buf)
return CC_NORM;
@ -156,11 +155,11 @@ em_yank(EditLine *el, wint_t c __attribute__((__unused__)))
* Cut the entire line and save in cut buffer
* [^U]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
@ -178,11 +177,11 @@ em_kill_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Cut area between mark and cursor and save in cut buffer
* [^W]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_kill_region(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
if (!el->el_chared.c_kill.mark)
return CC_ERROR;
@ -211,11 +210,11 @@ em_kill_region(EditLine *el, wint_t c __attribute__((__unused__)))
* Copy area between mark and cursor to cut buffer
* [M-W]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_copy_region(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
if (!el->el_chared.c_kill.mark)
return CC_ERROR;
@ -241,7 +240,7 @@ em_copy_region(EditLine *el, wint_t c __attribute__((__unused__)))
* Exchange the two characters before the cursor
* Gosling emacs transpose chars [^T]
*/
protected el_action_t
libedit_private el_action_t
em_gosmacs_transpose(EditLine *el, wint_t c)
{
@ -249,7 +248,7 @@ em_gosmacs_transpose(EditLine *el, wint_t c)
/* must have at least two chars entered */
c = el->el_line.cursor[-2];
el->el_line.cursor[-2] = el->el_line.cursor[-1];
el->el_line.cursor[-1] = (Char)c;
el->el_line.cursor[-1] = c;
return CC_REFRESH;
} else
return CC_ERROR;
@ -260,7 +259,7 @@ em_gosmacs_transpose(EditLine *el, wint_t c)
* Move next to end of current word
* [M-f]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -285,18 +284,18 @@ em_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Uppercase the characters from cursor to end of current word
* [M-u]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_upper_case(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *ep;
wchar_t *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
if (Islower(*cp))
*cp = Toupper(*cp);
if (iswlower(*cp))
*cp = towupper(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@ -309,26 +308,26 @@ em_upper_case(EditLine *el, wint_t c __attribute__((__unused__)))
* Capitalize the characters from cursor to end of current word
* [M-c]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_capitol_case(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *ep;
wchar_t *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++) {
if (Isalpha(*cp)) {
if (Islower(*cp))
*cp = Toupper(*cp);
if (iswalpha(*cp)) {
if (iswlower(*cp))
*cp = towupper(*cp);
cp++;
break;
}
}
for (; cp < ep; cp++)
if (Isupper(*cp))
*cp = Tolower(*cp);
if (iswupper(*cp))
*cp = towlower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@ -341,18 +340,18 @@ em_capitol_case(EditLine *el, wint_t c __attribute__((__unused__)))
* Lowercase the characters from cursor to end of current word
* [M-l]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_lower_case(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *ep;
wchar_t *cp, *ep;
ep = c__next_word(el->el_line.cursor, el->el_line.lastchar,
el->el_state.argument, ce__isword);
for (cp = el->el_line.cursor; cp < ep; cp++)
if (Isupper(*cp))
*cp = Tolower(*cp);
if (iswupper(*cp))
*cp = towlower(*cp);
el->el_line.cursor = ep;
if (el->el_line.cursor > el->el_line.lastchar)
@ -365,7 +364,7 @@ em_lower_case(EditLine *el, wint_t c __attribute__((__unused__)))
* Set the mark at cursor
* [^@]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_set_mark(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -379,11 +378,11 @@ em_set_mark(EditLine *el, wint_t c __attribute__((__unused__)))
* Exchange the cursor and mark
* [^X^X]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_exchange_mark(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp;
wchar_t *cp;
cp = el->el_line.cursor;
el->el_line.cursor = el->el_chared.c_kill.mark;
@ -396,7 +395,7 @@ em_exchange_mark(EditLine *el, wint_t c __attribute__((__unused__)))
* Universal argument (argument times 4)
* [^U]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__)))
{ /* multiply current argument by 4 */
@ -413,7 +412,7 @@ em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__)))
* Add 8th bit to next character typed
* [<ESC>]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_meta_next(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -426,7 +425,7 @@ em_meta_next(EditLine *el, wint_t c __attribute__((__unused__)))
/* em_toggle_overwrite():
* Switch from insert to overwrite mode or vice versa
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -440,11 +439,11 @@ em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__)))
/* em_copy_prev_word():
* Copy current word to cursor
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_copy_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *cp, *oldc, *dp;
wchar_t *cp, *oldc, *dp;
if (el->el_line.cursor == el->el_line.buffer)
return CC_ERROR;
@ -467,7 +466,7 @@ em_copy_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
/* em_inc_search_next():
* Emacs incremental next search
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -480,7 +479,7 @@ em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
/* em_inc_search_prev():
* Emacs incremental reverse search
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -494,7 +493,7 @@ em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
* Delete the character to the left of the cursor
* [^?]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
em_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{

View file

@ -1,4 +1,4 @@
/* $NetBSD: filecomplete.c,v 1.40 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 abhinav Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -31,10 +31,8 @@
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: filecomplete.c,v 1.40 2016/02/17 19:47:49 christos Exp $");
__RCSID("$NetBSD: filecomplete.c,v 1.58 2019/09/08 05:50:58 abhinav Exp $");
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
@ -51,11 +49,7 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "filecomplete.h"
static const Char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@',
'$', '>', '<', '=', ';', '|', '&', '{', '(', '\0' };
/* Tilde is deliberately omitted here, we treat it specially. */
static const Char extra_quote_chars[] = { ')', '}', '*', '?', '[', '$', '\0' };
static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{(";
/********************************/
/* completion functions */
@ -89,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);
@ -124,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);
@ -132,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
@ -248,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);
@ -324,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;
@ -360,10 +540,13 @@ _fn_qsort_string_compare(const void *i1, const void *i2)
* num, so the strings are matches[1] *through* matches[num-1].
*/
void
fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width,
const char *(*app_func) (const char *))
{
size_t line, lines, col, cols, thisguy;
int screenwidth = el->el_terminal.t_size.h;
if (app_func == NULL)
app_func = append_char_function;
/* Ignore matches[0]. Avoid 1-based array logic below. */
matches++;
@ -373,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;
@ -391,13 +574,70 @@ fn_display_match_list (EditLine *el, char **matches, size_t num, size_t width)
thisguy = line + col * lines;
if (thisguy >= num)
break;
(void)fprintf(el->el_outfile, "%s%-*s",
col == 0 ? "" : " ", (int)width, matches[thisguy]);
(void)fprintf(el->el_outfile, "%s%s%s",
col == 0 ? "" : " ", matches[thisguy],
(*app_func)(matches[thisguy]));
(void)fprintf(el->el_outfile, "%-*s",
(int) (width - strlen(matches[thisguy])), "");
}
(void)fprintf(el->el_outfile, "\n");
}
}
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.
@ -414,18 +654,14 @@ int
fn_complete(EditLine *el,
char *(*complet_func)(const char *, int),
char **(*attempted_completion_function)(const char *, int, int),
const Char *word_break, const Char *special_prefixes,
const wchar_t *word_break, const wchar_t *special_prefixes,
const char *(*app_func)(const char *), size_t query_items,
int *completion_type, int *over, int *point, int *end,
const Char *(*find_word_start_func)(const Char *, const Char *),
Char *(*dequoting_func)(const Char *),
char *(*quoting_func)(const char *))
int *completion_type, int *over, int *point, int *end)
{
const TYPE(LineInfo) *li;
Char *temp;
Char *dequoted_temp;
char **matches;
const Char *ctemp;
const LineInfoW *li;
wchar_t *temp;
char **matches;
char *completion;
size_t len;
int what_to_do = '\t';
int retval = CC_NORM;
@ -442,29 +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 = FUN(el,line)(el);
if (find_word_start_func)
ctemp = find_word_start_func(li->buffer, li->cursor);
else {
ctemp = li->cursor;
while (ctemp > li->buffer
&& !Strchr(word_break, ctemp[-1])
&& (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
ctemp--;
}
len = (size_t)(li->cursor - ctemp);
temp = el_malloc((len + 1) * sizeof(*temp));
(void)Strncpy(temp, ctemp, len);
temp[len] = '\0';
if (dequoting_func) {
dequoted_temp = dequoting_func(temp);
if (dequoted_temp == NULL)
return retval;
} else
dequoted_temp = NULL;
li = el_wline(el);
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,16 +694,14 @@ fn_complete(EditLine *el,
if (attempted_completion_function) {
int cur_off = (int)(li->cursor - li->buffer);
matches = (*attempted_completion_function)(
ct_encode_string(dequoted_temp ? dequoted_temp : temp,
&el->el_scratch),
ct_encode_string(temp, &el->el_scratch),
cur_off - (int)len, cur_off);
} else
matches = NULL;
if (!attempted_completion_function ||
(over != NULL && !*over && !matches))
matches = completion_matches(
ct_encode_string(dequoted_temp ? dequoted_temp : temp,
&el->el_scratch), complet_func);
ct_encode_string(temp, &el->el_scratch), complet_func);
if (over != NULL)
*over = 0;
@ -493,41 +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') {
char *quoted_match;
if (quoting_func) {
quoted_match = quoting_func(matches[0]);
if (quoted_match == NULL)
goto free_matches;
} else
quoted_match = NULL;
el_deletestr(el, (int) len);
FUN(el,insertstr)(el,
ct_decode_string(quoted_match ? quoted_match :
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 (what_to_do == '?')
goto display_matches;
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.
*/
FUN(el,insertstr)(el,
ct_decode_string((*app_func)(matches[0]),
&el->el_scratch));
} else if (what_to_do == '!') {
display_matches:
if (!single_match && (what_to_do == '!' || what_to_do == '?')) {
/*
* More than one match and requested to list possible
* matches.
@ -567,7 +783,7 @@ fn_complete(EditLine *el,
* add 1 to matches_num for the call.
*/
fn_display_match_list(el, matches,
matches_num+1, maxlen);
matches_num+1, maxlen, app_func);
}
retval = CC_REDISPLAY;
} else if (matches[0][0]) {
@ -584,14 +800,14 @@ fn_complete(EditLine *el,
retval = CC_NORM;
}
free_matches:
/* free elements of array and the array itself */
for (i = 0; matches[i]; i++)
el_free(matches[i]);
el_free(matches);
matches = NULL;
}
free(dequoted_temp);
out:
el_free(temp);
return retval;
}
@ -605,93 +821,15 @@ _el_fn_complete(EditLine *el, int ch __attribute__((__unused__)))
{
return (unsigned char)fn_complete(el, NULL, NULL,
break_chars, NULL, NULL, (size_t)100,
NULL, NULL, NULL, NULL,
NULL, NULL, NULL);
}
static const Char *
sh_find_word_start(const Char *buffer, const Char *cursor)
{
const Char *word_start = buffer;
while (buffer < cursor) {
if (*buffer == '\\')
buffer++;
else if (Strchr(break_chars, *buffer))
word_start = buffer + 1;
buffer++;
}
return word_start;
}
static char *
sh_quote(const char *str)
{
const char *src;
int extra_len = 0;
char *quoted_str, *dst;
for (src = str; *src != '\0'; src++)
if (Strchr(break_chars, *src) ||
Strchr(extra_quote_chars, *src))
extra_len++;
quoted_str = malloc(sizeof(*quoted_str) *
(strlen(str) + extra_len + 1));
if (quoted_str == NULL)
return NULL;
dst = quoted_str;
for (src = str; *src != '\0'; src++) {
if (Strchr(break_chars, *src) ||
Strchr(extra_quote_chars, *src))
*dst++ = '\\';
*dst++ = *src;
}
*dst = '\0';
return quoted_str;
}
static Char *
sh_dequote(const Char *str)
{
Char *dequoted_str, *dst;
/* save extra space to replace \~ with ./~ */
dequoted_str = malloc(sizeof(*dequoted_str) * (Strlen(str) + 1 + 1));
if (dequoted_str == NULL)
return NULL;
dst = dequoted_str;
/* dequote \~ at start as ./~ */
if (*str == '\\' && str[1] == '~') {
str++;
*dst++ = '.';
*dst++ = '/';
}
while (*str) {
if (*str == '\\')
str++;
if (*str)
*dst++ = *str++;
}
*dst = '\0';
return dequoted_str;
NULL, NULL, NULL, NULL);
}
/*
* completion function using sh quoting rules; for key binding
* el-compatible wrapper around rl_complete; needed for key binding
*/
/* ARGSUSED */
unsigned char
_el_fn_sh_complete(EditLine *el, int ch __attribute__((__unused__)))
_el_fn_sh_complete(EditLine *el, int ch)
{
return (unsigned char)fn_complete(el, NULL, NULL,
break_chars, NULL, NULL, 100,
NULL, NULL, NULL, NULL,
sh_find_word_start, sh_dequote, sh_quote);
return _el_fn_complete(el, ch);
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: filecomplete.h,v 1.9 2009/12/30 22:37:40 christos Exp $ */
/* $NetBSD: filecomplete.h,v 1.11 2017/04/21 05:38:03 abhinav Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -27,8 +27,6 @@
* 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.
*
* $FreeBSD$
*/
#ifndef _FILECOMPLETE_H_
#define _FILECOMPLETE_H_
@ -36,13 +34,11 @@
int fn_complete(EditLine *,
char *(*)(const char *, int),
char **(*)(const char *, int, int),
const Char *, const Char *, const char *(*)(const char *), size_t,
int *, int *, int *, int *,
const Char *(*)(const Char *, const Char *),
Char *(*)(const Char *),
char *(*)(const char *));
const wchar_t *, const wchar_t *, const char *(*)(const char *), size_t,
int *, int *, int *, int *);
void fn_display_match_list(EditLine *, char **, size_t, size_t);
void fn_display_match_list(EditLine *, char **, size_t, size_t,
const char *(*)(const char *));
char *fn_tilde_expand(const char *);
char *fn_filename_completion_function(const char *, int);

View file

@ -1,4 +1,4 @@
/* $NetBSD: hist.c,v 1.24 2016/02/16 22:53:14 christos Exp $ */
/* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,33 +37,32 @@
#if 0
static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: hist.c,v 1.24 2016/02/16 22:53:14 christos Exp $");
__RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* hist.c: History access functions
*/
#include <stdlib.h>
#include <string.h>
#include <vis.h>
#include "el.h"
/* hist_init():
* Initialization function.
*/
protected int
libedit_private int
hist_init(EditLine *el)
{
el->el_history.fun = NULL;
el->el_history.ref = NULL;
el->el_history.buf = el_malloc(EL_BUFSIZ * sizeof(*el->el_history.buf));
el->el_history.sz = EL_BUFSIZ;
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;
}
@ -72,7 +71,7 @@ hist_init(EditLine *el)
/* hist_end():
* clean up history;
*/
protected void
libedit_private void
hist_end(EditLine *el)
{
@ -84,7 +83,7 @@ hist_end(EditLine *el)
/* hist_set():
* Set new history interface
*/
protected int
libedit_private int
hist_set(EditLine *el, hist_fun_t fun, void *ptr)
{
@ -98,14 +97,15 @@ hist_set(EditLine *el, hist_fun_t fun, void *ptr)
* Get a history line and update it in the buffer.
* eventno tells us the event to get.
*/
protected el_action_t
libedit_private el_action_t
hist_get(EditLine *el)
{
const Char *hp;
const wchar_t *hp;
int h;
size_t blen, hlen;
if (el->el_history.eventno == 0) { /* if really the current line */
(void) Strncpy(el->el_line.buffer, el->el_history.buf,
(void) wcsncpy(el->el_line.buffer, el->el_history.buf,
el->el_history.sz);
el->el_line.lastchar = el->el_line.buffer +
(el->el_history.last - el->el_history.buf);
@ -128,14 +128,16 @@ hist_get(EditLine *el)
return CC_ERROR;
for (h = 1; h < el->el_history.eventno; h++)
if ((hp = HIST_NEXT(el)) == NULL) {
el->el_history.eventno = h;
return CC_ERROR;
}
(void) Strncpy(el->el_line.buffer, hp,
(size_t)(el->el_line.limit - el->el_line.buffer));
el->el_line.buffer[el->el_line.limit - el->el_line.buffer - 1] = '\0';
el->el_line.lastchar = el->el_line.buffer + Strlen(el->el_line.buffer);
if ((hp = HIST_NEXT(el)) == NULL)
goto out;
hlen = wcslen(hp) + 1;
blen = (size_t)(el->el_line.limit - el->el_line.buffer);
if (hlen > blen && !ch_enlargebufs(el, hlen))
goto out;
memcpy(el->el_line.buffer, hp, hlen * sizeof(*hp));
el->el_line.lastchar = el->el_line.buffer + hlen - 1;
if (el->el_line.lastchar > el->el_line.buffer
&& el->el_line.lastchar[-1] == '\n')
@ -151,41 +153,66 @@ hist_get(EditLine *el)
el->el_line.cursor = el->el_line.lastchar;
return CC_REFRESH;
out:
el->el_history.eventno = h;
return CC_ERROR;
}
/* hist_command()
* process a history command
*/
protected int
hist_command(EditLine *el, int argc, const Char **argv)
libedit_private int
hist_command(EditLine *el, int argc, const wchar_t **argv)
{
const Char *str;
const wchar_t *str;
int num;
TYPE(HistEvent) ev;
HistEventW ev;
if (el->el_history.ref == NULL)
return -1;
if (argc == 1 || Strcmp(argv[1], STR("list")) == 0) {
if (argc == 1 || wcscmp(argv[1], L"list") == 0) {
size_t maxlen = 0;
char *buf = NULL;
int hno = 1;
/* List history entries */
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el))
(void) fprintf(el->el_outfile, "%d %s",
el->el_history.ev.num, ct_encode_string(str, &el->el_scratch));
for (str = HIST_LAST(el); str != NULL; str = HIST_PREV(el)) {
char *ptr =
ct_encode_string(str, &el->el_scratch);
size_t len = strlen(ptr);
if (len > 0 && ptr[len - 1] == '\n')
ptr[--len] = '\0';
len = len * 4 + 1;
if (len >= maxlen) {
maxlen = len + 1024;
char *nbuf = el_realloc(buf, maxlen);
if (nbuf == NULL) {
el_free(buf);
return -1;
}
buf = nbuf;
}
strvis(buf, ptr, VIS_NL);
(void) fprintf(el->el_outfile, "%d\t%s\n",
hno++, buf);
}
el_free(buf);
return 0;
}
if (argc != 3)
return -1;
num = (int)Strtol(argv[2], NULL, 0);
num = (int)wcstol(argv[2], NULL, 0);
if (Strcmp(argv[1], STR("size")) == 0)
return FUNW(history)(el->el_history.ref, &ev, H_SETSIZE, num);
if (wcscmp(argv[1], L"size") == 0)
return history_w(el->el_history.ref, &ev, H_SETSIZE, num);
if (Strcmp(argv[1], STR("unique")) == 0)
return FUNW(history)(el->el_history.ref, &ev, H_SETUNIQUE, num);
if (wcscmp(argv[1], L"unique") == 0)
return history_w(el->el_history.ref, &ev, H_SETUNIQUE, num);
return -1;
}
@ -194,11 +221,11 @@ hist_command(EditLine *el, int argc, const Char **argv)
* Enlarge history buffer to specified value. Called from el_enlargebufs().
* Return 0 for failure, 1 for success.
*/
protected int
libedit_private int
/*ARGSUSED*/
hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
{
Char *newbuf;
wchar_t *newbuf;
newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf));
if (!newbuf)
@ -214,8 +241,7 @@ hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz)
return 1;
}
#ifdef WIDECHAR
protected wchar_t *
libedit_private wchar_t *
hist_convert(EditLine *el, int fn, void *arg)
{
HistEventW ev;
@ -224,4 +250,3 @@ hist_convert(EditLine *el, int fn, void *arg)
return ct_decode_string((const char *)(const void *)ev.str,
&el->el_scratch);
}
#endif

View file

@ -1,4 +1,4 @@
/* $NetBSD: hist.h,v 1.18 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: hist.h,v 1.23 2017/09/01 10:19:10 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)hist.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -41,47 +40,41 @@
#ifndef _h_el_hist
#define _h_el_hist
typedef int (*hist_fun_t)(void *, TYPE(HistEvent) *, int, ...);
typedef int (*hist_fun_t)(void *, HistEventW *, int, ...);
typedef struct el_history_t {
Char *buf; /* The history buffer */
wchar_t *buf; /* The history buffer */
size_t sz; /* Size of history buffer */
Char *last; /* The last character */
wchar_t *last; /* The last character */
int eventno; /* Event we are looking for */
void *ref; /* Argument for history fcns */
hist_fun_t fun; /* Event access */
TYPE(HistEvent) ev; /* Event cookie */
HistEventW ev; /* Event cookie */
} el_history_t;
#define HIST_FUN_INTERNAL(el, fn, arg) \
((((*(el)->el_history.fun) ((el)->el_history.ref, &(el)->el_history.ev, \
fn, arg)) == -1) ? NULL : (el)->el_history.ev.str)
#ifdef WIDECHAR
#define HIST_FUN(el, fn, arg) \
(((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \
HIST_FUN_INTERNAL(el, fn, arg))
#else
#define HIST_FUN(el, fn, arg) HIST_FUN_INTERNAL(el, fn, arg)
#endif
#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
#define HIST_SET(el, num) HIST_FUN(el, H_SET, num)
#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
#define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP, fp)
#define HIST_NSAVE_FP(el, n, fp) HIST_FUN(el, H_NSAVE_FP, n, fp)
#define HIST_NEXT(el) HIST_FUN(el, H_NEXT, NULL)
#define HIST_FIRST(el) HIST_FUN(el, H_FIRST, NULL)
#define HIST_LAST(el) HIST_FUN(el, H_LAST, NULL)
#define HIST_PREV(el) HIST_FUN(el, H_PREV, NULL)
#define HIST_SET(el, num) HIST_FUN(el, H_SET, num)
#define HIST_LOAD(el, fname) HIST_FUN(el, H_LOAD fname)
#define HIST_SAVE(el, fname) HIST_FUN(el, H_SAVE fname)
#define HIST_SAVE_FP(el, fp) HIST_FUN(el, H_SAVE_FP fp)
protected int hist_init(EditLine *);
protected void hist_end(EditLine *);
protected el_action_t hist_get(EditLine *);
protected int hist_set(EditLine *, hist_fun_t, void *);
protected int hist_command(EditLine *, int, const Char **);
protected int hist_enlargebuf(EditLine *, size_t, size_t);
#ifdef WIDECHAR
protected wchar_t *hist_convert(EditLine *, int, void *);
#endif
libedit_private int hist_init(EditLine *);
libedit_private void hist_end(EditLine *);
libedit_private el_action_t hist_get(EditLine *);
libedit_private int hist_set(EditLine *, hist_fun_t, void *);
libedit_private int hist_command(EditLine *, int, const wchar_t **);
libedit_private int hist_enlargebuf(EditLine *, size_t, size_t);
libedit_private wchar_t *hist_convert(EditLine *, int, void *);
#endif /* _h_el_hist */

View file

@ -1,4 +1,4 @@
/* $NetBSD: histedit.h,v 1.55 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: histedit.h,v 1.57 2017/09/01 10:19:10 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)histedit.h 8.2 (Berkeley) 1/3/94
* $FreeBSD$
*/
/*
@ -228,6 +227,7 @@ int history(History *, HistEvent *, int, ...);
#define H_DELDATA 24 /* , int, histdata_t *);*/
#define H_REPLACE 25 /* , const char *, histdata_t); */
#define H_SAVE_FP 26 /* , FILE *); */
#define H_NSAVE_FP 27 /* , size_t, FILE *); */
@ -263,6 +263,8 @@ typedef struct lineinfow {
const wchar_t *lastchar;
} LineInfoW;
typedef int (*el_rfunc_t)(EditLine *, wchar_t *);
const wchar_t *el_wgets(EditLine *, int *);
int el_wgetc(EditLine *, wchar_t *);
void el_wpush(EditLine *, const wchar_t *);

View file

@ -1,4 +1,4 @@
/* $NetBSD: history.c,v 1.52 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: history.c,v 1.52 2016/02/17 19:47:49 christos Exp $");
__RCSID("$NetBSD: history.c,v 1.62 2018/09/13 09:03:40 kre Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* hist.c: TYPE(History) access functions
@ -55,8 +53,44 @@ __FBSDID("$FreeBSD$");
static const char hist_cookie[] = "_HiStOrY_V2_\n";
#include "histedit.h"
#ifdef NARROWCHAR
#define Char char
#define FUN(prefix, rest) prefix ## _ ## rest
#define FUNW(type) type
#define TYPE(type) type
#define STR(x) x
#define Strlen(s) strlen(s)
#define Strdup(s) strdup(s)
#define Strcmp(d, s) strcmp(d, s)
#define Strncmp(d, s, n) strncmp(d, s, n)
#define Strncpy(d, s, n) strncpy(d, s, n)
#define Strncat(d, s, n) strncat(d, s, n)
#define ct_decode_string(s, b) (s)
#define ct_encode_string(s, b) (s)
#else
#include "chartype.h"
#define Char wchar_t
#define FUN(prefix, rest) prefix ## _w ## rest
#define FUNW(type) type ## _w
#define TYPE(type) type ## W
#define STR(x) L ## x
#define Strlen(s) wcslen(s)
#define Strdup(s) wcsdup(s)
#define Strcmp(d, s) wcscmp(d, s)
#define Strncmp(d, s, n) wcsncmp(d, s, n)
#define Strncpy(d, s, n) wcsncpy(d, s, n)
#define Strncat(d, s, n) wcsncat(d, s, n)
#endif
typedef int (*history_gfun_t)(void *, TYPE(HistEvent) *);
typedef int (*history_efun_t)(void *, TYPE(HistEvent) *, const Char *);
typedef void (*history_vfun_t)(void *, TYPE(HistEvent) *);
@ -99,19 +133,20 @@ typedef struct {
} HistEventPrivate;
private int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
private int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
private int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
private int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
private int history_set_fun(TYPE(History) *, TYPE(History) *);
private int history_load(TYPE(History) *, const char *);
private int history_save(TYPE(History) *, const char *);
private int history_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 *);
private int history_prev_string(TYPE(History) *, TYPE(HistEvent) *, const Char *);
static int history_setsize(TYPE(History) *, TYPE(HistEvent) *, int);
static int history_getsize(TYPE(History) *, TYPE(HistEvent) *);
static int history_setunique(TYPE(History) *, TYPE(HistEvent) *, int);
static int history_getunique(TYPE(History) *, TYPE(HistEvent) *);
static int history_set_fun(TYPE(History) *, TYPE(History) *);
static int history_load(TYPE(History) *, const char *);
static int history_save(TYPE(History) *, const char *);
static int history_save_fp(TYPE(History) *, size_t, FILE *);
static int history_prev_event(TYPE(History) *, TYPE(HistEvent) *, int);
static int history_next_event(TYPE(History) *, TYPE(HistEvent) *, int);
static int history_next_string(TYPE(History) *, TYPE(HistEvent) *,
const Char *);
static int history_prev_string(TYPE(History) *, TYPE(HistEvent) *,
const Char *);
/***********************************************************************/
@ -136,23 +171,23 @@ typedef struct history_t {
#define H_UNIQUE 1 /* Store only unique elements */
} history_t;
private int history_def_next(void *, TYPE(HistEvent) *);
private int history_def_first(void *, TYPE(HistEvent) *);
private int history_def_prev(void *, TYPE(HistEvent) *);
private int history_def_last(void *, TYPE(HistEvent) *);
private int history_def_curr(void *, TYPE(HistEvent) *);
private int history_def_set(void *, TYPE(HistEvent) *, const int);
private void history_def_clear(void *, TYPE(HistEvent) *);
private int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
private int history_def_add(void *, TYPE(HistEvent) *, const Char *);
private int history_def_del(void *, TYPE(HistEvent) *, const int);
static int history_def_next(void *, TYPE(HistEvent) *);
static int history_def_first(void *, TYPE(HistEvent) *);
static int history_def_prev(void *, TYPE(HistEvent) *);
static int history_def_last(void *, TYPE(HistEvent) *);
static int history_def_curr(void *, TYPE(HistEvent) *);
static int history_def_set(void *, TYPE(HistEvent) *, const int);
static void history_def_clear(void *, TYPE(HistEvent) *);
static int history_def_enter(void *, TYPE(HistEvent) *, const Char *);
static int history_def_add(void *, TYPE(HistEvent) *, const Char *);
static int history_def_del(void *, TYPE(HistEvent) *, const int);
private int history_def_init(void **, TYPE(HistEvent) *, int);
private int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
private void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
static int history_def_init(void **, TYPE(HistEvent) *, int);
static int history_def_insert(history_t *, TYPE(HistEvent) *, const Char *);
static void history_def_delete(history_t *, TYPE(HistEvent) *, hentry_t *);
private int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
private int history_set_nth(void *, TYPE(HistEvent) *, int);
static int history_deldata_nth(history_t *, TYPE(HistEvent) *, int, void **);
static int history_set_nth(void *, TYPE(HistEvent) *, int);
#define history_def_setsize(p, num)(void) (((history_t *)p)->max = (num))
#define history_def_getsize(p) (((history_t *)p)->cur)
@ -209,7 +244,7 @@ static const Char *const he_errlist[] = {
/* history_def_first():
* Default function to return the first event in the history.
*/
private int
static int
history_def_first(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -229,7 +264,7 @@ history_def_first(void *p, TYPE(HistEvent) *ev)
/* history_def_last():
* Default function to return the last event in the history.
*/
private int
static int
history_def_last(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -249,7 +284,7 @@ history_def_last(void *p, TYPE(HistEvent) *ev)
/* history_def_next():
* Default function to return the next event in the history.
*/
private int
static int
history_def_next(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -274,7 +309,7 @@ history_def_next(void *p, TYPE(HistEvent) *ev)
/* history_def_prev():
* Default function to return the previous event in the history.
*/
private int
static int
history_def_prev(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -300,7 +335,7 @@ history_def_prev(void *p, TYPE(HistEvent) *ev)
/* history_def_curr():
* Default function to return the current event in the history.
*/
private int
static int
history_def_curr(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -321,7 +356,7 @@ history_def_curr(void *p, TYPE(HistEvent) *ev)
* Default function to set the current event in the history to the
* given one.
*/
private int
static int
history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
{
history_t *h = (history_t *) p;
@ -348,7 +383,7 @@ history_def_set(void *p, TYPE(HistEvent) *ev, const int n)
* Default function to set the current event in the history to the
* n-th one.
*/
private int
static int
history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
{
history_t *h = (history_t *) p;
@ -372,7 +407,7 @@ history_set_nth(void *p, TYPE(HistEvent) *ev, int n)
/* history_def_add():
* Append string to element
*/
private int
static int
history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
{
history_t *h = (history_t *) p;
@ -398,7 +433,7 @@ history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str)
}
private int
static int
history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
int num, void **data)
{
@ -420,7 +455,7 @@ history_deldata_nth(history_t *h, TYPE(HistEvent) *ev,
* Delete element hp of the h list
*/
/* ARGSUSED */
private int
static int
history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
const int num)
{
@ -438,7 +473,7 @@ history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)),
* Delete element hp of the h list
*/
/* ARGSUSED */
private void
static void
history_def_delete(history_t *h,
TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp)
{
@ -461,7 +496,7 @@ history_def_delete(history_t *h,
/* history_def_insert():
* Insert element with string str in the h list
*/
private int
static int
history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
{
hentry_t *c;
@ -493,7 +528,7 @@ history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str)
/* history_def_enter():
* Default function to enter an item in the history
*/
private int
static int
history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
{
history_t *h = (history_t *) p;
@ -520,7 +555,7 @@ history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str)
* Default history initialization function
*/
/* ARGSUSED */
private int
static int
history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n)
{
history_t *h = (history_t *) h_malloc(sizeof(*h));
@ -545,7 +580,7 @@ history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int
/* history_def_clear():
* Default history cleanup function
*/
private void
static void
history_def_clear(void *p, TYPE(HistEvent) *ev)
{
history_t *h = (history_t *) p;
@ -565,7 +600,7 @@ history_def_clear(void *p, TYPE(HistEvent) *ev)
/* history_init():
* Initialization function.
*/
public TYPE(History) *
TYPE(History) *
FUN(history,init)(void)
{
TYPE(HistEvent) ev;
@ -596,7 +631,7 @@ FUN(history,init)(void)
/* history_end():
* clean up history;
*/
public void
void
FUN(history,end)(TYPE(History) *h)
{
TYPE(HistEvent) ev;
@ -612,7 +647,7 @@ FUN(history,end)(TYPE(History) *h)
/* history_setsize():
* Set history number of events
*/
private int
static int
history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
@ -632,7 +667,7 @@ history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
/* history_getsize():
* Get number of events currently in history
*/
private int
static int
history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
{
if (h->h_next != history_def_next) {
@ -651,7 +686,7 @@ history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev)
/* history_setunique():
* Set if adjacent equal events should not be entered in history.
*/
private int
static int
history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
{
@ -667,7 +702,7 @@ history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni)
/* history_getunique():
* Get if adjacent equal events should not be entered in history.
*/
private int
static int
history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
{
if (h->h_next != history_def_next) {
@ -682,7 +717,7 @@ history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev)
/* history_set_fun():
* Set history functions
*/
private int
static int
history_set_fun(TYPE(History) *h, TYPE(History) *nh)
{
TYPE(HistEvent) ev;
@ -729,7 +764,7 @@ history_set_fun(TYPE(History) *h, TYPE(History) *nh)
/* history_load():
* TYPE(History) load function
*/
private int
static int
history_load(TYPE(History) *h, const char *fname)
{
FILE *fp;
@ -740,7 +775,8 @@ history_load(TYPE(History) *h, const char *fname)
char *ptr;
int i = -1;
TYPE(HistEvent) ev;
#ifdef WIDECHAR
Char *decode_result;
#ifndef NARROWCHAR
static ct_buffer_t conv;
#endif
@ -772,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;
}
@ -789,28 +828,36 @@ history_load(TYPE(History) *h, const char *fname)
/* history_save_fp():
* TYPE(History) save function
*/
private int
history_save_fp(TYPE(History) *h, FILE *fp)
static int
history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp)
{
TYPE(HistEvent) ev;
int i = -1, retval;
size_t len, max_size;
char *ptr;
const char *str;
#ifdef WIDECHAR
#ifndef NARROWCHAR
static ct_buffer_t conv;
#endif
if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) == -1)
goto done;
if (fputs(hist_cookie, fp) == EOF)
if (ftell(fp) == 0 && fputs(hist_cookie, fp) == EOF)
goto done;
ptr = h_malloc((max_size = 1024) * sizeof(*ptr));
if (ptr == NULL)
goto done;
for (i = 0, retval = HLAST(h, &ev);
retval != -1;
retval = HPREV(h, &ev), i++) {
if (nelem != (size_t)-1) {
for (retval = HFIRST(h, &ev); retval != -1 && nelem-- > 0;
retval = HNEXT(h, &ev))
continue;
} else
retval = -1;
if (retval == -1)
retval = HLAST(h, &ev);
for (i = 0; retval != -1; retval = HPREV(h, &ev), i++) {
str = ct_encode_string(ev.str, &conv);
len = strlen(str) * 4 + 1;
if (len > max_size) {
@ -836,7 +883,7 @@ history_save_fp(TYPE(History) *h, FILE *fp)
/* history_save():
* History save function
*/
private int
static int
history_save(TYPE(History) *h, const char *fname)
{
FILE *fp;
@ -845,7 +892,7 @@ history_save(TYPE(History) *h, const char *fname)
if ((fp = fopen(fname, "w")) == NULL)
return -1;
i = history_save_fp(h, fp);
i = history_save_fp(h, (size_t)-1, fp);
(void) fclose(fp);
return i;
@ -855,7 +902,7 @@ history_save(TYPE(History) *h, const char *fname)
/* history_prev_event():
* Find the previous event, with number given
*/
private int
static int
history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
int retval;
@ -869,7 +916,7 @@ history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
}
private int
static int
history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
{
int retval;
@ -889,7 +936,7 @@ history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d)
/* history_next_event():
* Find the next event, with number given
*/
private int
static int
history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
{
int retval;
@ -906,7 +953,7 @@ history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num)
/* history_prev_string():
* Find the previous event beginning with string
*/
private int
static int
history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
{
size_t len = Strlen(str);
@ -924,7 +971,7 @@ history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
/* history_next_string():
* Find the next event beginning with string
*/
private int
static int
history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str)
{
size_t len = Strlen(str);
@ -1033,11 +1080,20 @@ FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...)
break;
case H_SAVE_FP:
retval = history_save_fp(h, va_arg(va, FILE *));
retval = history_save_fp(h, (size_t)-1, va_arg(va, FILE *));
if (retval == -1)
he_seterrev(ev, _HE_HIST_WRITE);
break;
case H_NSAVE_FP:
{
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));
break;

View file

@ -0,0 +1,3 @@
#include "config.h"
#define NARROWCHAR
#include "history.c"

View file

@ -1,4 +1,4 @@
/* $NetBSD: keymacro.c,v 1.14 2016/02/24 14:25:38 christos Exp $ */
/* $NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: keymacro.c,v 1.14 2016/02/24 14:25:38 christos Exp $");
__RCSID("$NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* keymacro.c: This module contains the procedures for maintaining
@ -52,7 +50,7 @@ __FBSDID("$FreeBSD$");
* number of characters. This module maintains a map (the
* el->el_keymacro.map)
* to convert these extended-key sequences into input strs
* (XK_STR), editor functions (XK_CMD), or unix commands (XK_EXE).
* (XK_STR) or editor functions (XK_CMD).
*
* Warning:
* If key is a substr of some other keys, then the longer
@ -69,13 +67,14 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include "el.h"
#include "fcns.h"
/*
* The Nodes of the el->el_keymacro.map. The el->el_keymacro.map is a
* linked list of these node elements
*/
struct keymacro_node_t {
Char ch; /* single character of key */
wchar_t ch; /* single character of key */
int type; /* node type */
keymacro_value_t val; /* command code or pointer to str, */
/* if this is a leaf */
@ -83,18 +82,18 @@ struct keymacro_node_t {
struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/
};
private int node_trav(EditLine *, keymacro_node_t *, Char *,
static int node_trav(EditLine *, keymacro_node_t *, wchar_t *,
keymacro_value_t *);
private int node__try(EditLine *, keymacro_node_t *, const Char *,
keymacro_value_t *, int);
private keymacro_node_t *node__get(wint_t);
private void node__free(keymacro_node_t *);
private void node__put(EditLine *, keymacro_node_t *);
private int node__delete(EditLine *, keymacro_node_t **,
const Char *);
private int node_lookup(EditLine *, const Char *,
static int node__try(EditLine *, keymacro_node_t *,
const wchar_t *, keymacro_value_t *, int);
static keymacro_node_t *node__get(wint_t);
static void node__free(keymacro_node_t *);
static void node__put(EditLine *, keymacro_node_t *);
static int node__delete(EditLine *, keymacro_node_t **,
const wchar_t *);
static int node_lookup(EditLine *, const wchar_t *,
keymacro_node_t *, size_t);
private int node_enum(EditLine *, keymacro_node_t *, size_t);
static int node_enum(EditLine *, keymacro_node_t *, size_t);
#define KEY_BUFSIZ EL_BUFSIZ
@ -102,11 +101,11 @@ private int node_enum(EditLine *, keymacro_node_t *, size_t);
/* keymacro_init():
* Initialize the key maps
*/
protected int
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;
@ -118,7 +117,7 @@ keymacro_init(EditLine *el)
/* keymacro_end():
* Free the key maps
*/
protected void
libedit_private void
keymacro_end(EditLine *el)
{
@ -131,7 +130,7 @@ keymacro_end(EditLine *el)
/* keymacro_map_cmd():
* Associate cmd with a key value
*/
protected keymacro_value_t *
libedit_private keymacro_value_t *
keymacro_map_cmd(EditLine *el, int cmd)
{
@ -143,8 +142,8 @@ keymacro_map_cmd(EditLine *el, int cmd)
/* keymacro_map_str():
* Associate str with a key value
*/
protected keymacro_value_t *
keymacro_map_str(EditLine *el, Char *str)
libedit_private keymacro_value_t *
keymacro_map_str(EditLine *el, wchar_t *str)
{
el->el_keymacro.val.str = str;
@ -157,7 +156,7 @@ keymacro_map_str(EditLine *el, Char *str)
* Then initializes el->el_keymacro.map with arrow keys
* [Always bind the ansi arrow keys?]
*/
protected void
libedit_private void
keymacro_reset(EditLine *el)
{
@ -171,12 +170,13 @@ keymacro_reset(EditLine *el)
* Calls the recursive function with entry point el->el_keymacro.map
* Looks up *ch in map and then reads characters until a
* complete match is found or a mismatch occurs. Returns the
* type of the match found (XK_STR, XK_CMD, or XK_EXE).
* type of the match found (XK_STR or XK_CMD).
* Returns NULL in val.str and XK_STR for no match.
* Returns XK_NOD for end of file or read error.
* The last character read is returned in *ch.
*/
protected int
keymacro_get(EditLine *el, Char *ch, keymacro_value_t *val)
libedit_private int
keymacro_get(EditLine *el, wchar_t *ch, keymacro_value_t *val)
{
return node_trav(el, el->el_keymacro.map, ch, val);
@ -189,8 +189,9 @@ keymacro_get(EditLine *el, Char *ch, keymacro_value_t *val)
* code is applied to the existing key. Ntype specifies if code is a
* command, an out str or a unix command.
*/
protected void
keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
libedit_private void
keymacro_add(EditLine *el, const wchar_t *key, keymacro_value_t *val,
int ntype)
{
if (key[0] == '\0') {
@ -217,13 +218,11 @@ keymacro_add(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
/* keymacro_clear():
*
*/
protected void
keymacro_clear(EditLine *el, el_action_t *map, const Char *in)
libedit_private void
keymacro_clear(EditLine *el, el_action_t *map, const wchar_t *in)
{
#ifdef WIDECHAR
if (*in > N_KEYS) /* can't be in the map */
return;
#endif
if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) &&
((map == el->el_map.key &&
el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) ||
@ -237,8 +236,8 @@ keymacro_clear(EditLine *el, el_action_t *map, const Char *in)
* Delete the key and all longer keys staring with key, if
* they exists.
*/
protected int
keymacro_delete(EditLine *el, const Char *key)
libedit_private int
keymacro_delete(EditLine *el, const wchar_t *key)
{
if (key[0] == '\0') {
@ -258,8 +257,8 @@ keymacro_delete(EditLine *el, const Char *key)
* Print the binding associated with key key.
* Print entire el->el_keymacro.map if null
*/
protected void
keymacro_print(EditLine *el, const Char *key)
libedit_private void
keymacro_print(EditLine *el, const wchar_t *key)
{
/* do nothing if el->el_keymacro.map is empty and null key specified */
@ -269,7 +268,7 @@ keymacro_print(EditLine *el, const Char *key)
el->el_keymacro.buf[0] = '"';
if (node_lookup(el, key, el->el_keymacro.map, (size_t)1) <= -1)
/* key is not bound */
(void) fprintf(el->el_errfile, "Unbound extended key \"" FSTR
(void) fprintf(el->el_errfile, "Unbound extended key \"%ls"
"\"\n", key);
return;
}
@ -279,21 +278,17 @@ keymacro_print(EditLine *el, const Char *key)
* recursively traverses node in tree until match or mismatch is
* found. May read in more characters.
*/
private int
node_trav(EditLine *el, keymacro_node_t *ptr, Char *ch, keymacro_value_t *val)
static int
node_trav(EditLine *el, keymacro_node_t *ptr, wchar_t *ch,
keymacro_value_t *val)
{
wchar_t wc;
if (ptr->ch == *ch) {
/* match found */
if (ptr->next) {
/* key not complete so get next char */
if (el_wgetc(el, &wc) != 1) {/* if EOF or error */
val->cmd = ED_END_OF_FILE;
return XK_CMD;
/* PWP: Pretend we just read an end-of-file */
}
*ch = (Char)wc;
if (el_wgetc(el, ch) != 1)
return XK_NOD;
return node_trav(el, ptr->next, ch, val);
} else {
*val = ptr->val;
@ -318,8 +313,8 @@ node_trav(EditLine *el, keymacro_node_t *ptr, Char *ch, keymacro_value_t *val)
/* node__try():
* Find a node that matches *str or allocate a new one
*/
private int
node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
static int
node__try(EditLine *el, keymacro_node_t *ptr, const wchar_t *str,
keymacro_value_t *val, int ntype)
{
@ -345,7 +340,6 @@ node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
case XK_NOD:
break;
case XK_STR:
case XK_EXE:
if (ptr->val.str)
el_free(ptr->val.str);
break;
@ -360,8 +354,7 @@ node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
ptr->val = *val;
break;
case XK_STR:
case XK_EXE:
if ((ptr->val.str = Strdup(val->str)) == NULL)
if ((ptr->val.str = wcsdup(val->str)) == NULL)
return -1;
break;
default:
@ -381,8 +374,8 @@ node__try(EditLine *el, keymacro_node_t *ptr, const Char *str,
/* node__delete():
* Delete node that matches str
*/
private int
node__delete(EditLine *el, keymacro_node_t **inptr, const Char *str)
static int
node__delete(EditLine *el, keymacro_node_t **inptr, const wchar_t *str)
{
keymacro_node_t *ptr;
keymacro_node_t *prev_ptr = NULL;
@ -429,7 +422,7 @@ node__delete(EditLine *el, keymacro_node_t **inptr, const Char *str)
/* node__put():
* Puts a tree of nodes onto free list using free(3).
*/
private void
static void
node__put(EditLine *el, keymacro_node_t *ptr)
{
if (ptr == NULL)
@ -445,7 +438,6 @@ node__put(EditLine *el, keymacro_node_t *ptr)
case XK_CMD:
case XK_NOD:
break;
case XK_EXE:
case XK_STR:
if (ptr->val.str != NULL)
el_free(ptr->val.str);
@ -461,7 +453,7 @@ node__put(EditLine *el, keymacro_node_t *ptr)
/* node__get():
* Returns pointer to a keymacro_node_t for ch.
*/
private keymacro_node_t *
static keymacro_node_t *
node__get(wint_t ch)
{
keymacro_node_t *ptr;
@ -469,7 +461,7 @@ node__get(wint_t ch)
ptr = el_malloc(sizeof(*ptr));
if (ptr == NULL)
return NULL;
ptr->ch = (Char)ch;
ptr->ch = ch;
ptr->type = XK_NOD;
ptr->val.str = NULL;
ptr->next = NULL;
@ -477,7 +469,7 @@ node__get(wint_t ch)
return ptr;
}
private void
static void
node__free(keymacro_node_t *k)
{
if (k == NULL)
@ -491,8 +483,9 @@ node__free(keymacro_node_t *k)
* look for the str starting at node ptr.
* Print if last node
*/
private int
node_lookup(EditLine *el, const Char *str, keymacro_node_t *ptr, size_t cnt)
static int
node_lookup(EditLine *el, const wchar_t *str, keymacro_node_t *ptr,
size_t cnt)
{
ssize_t used;
@ -543,7 +536,7 @@ node_lookup(EditLine *el, const Char *str, keymacro_node_t *ptr, size_t cnt)
/* node_enum():
* Traverse the node printing the characters it is bound in buffer
*/
private int
static int
node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt)
{
ssize_t used;
@ -553,7 +546,7 @@ node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt)
el->el_keymacro.buf[++cnt] = '\0';
(void) fprintf(el->el_errfile,
"Some extended keys too long for internal print buffer");
(void) fprintf(el->el_errfile, " \"" FSTR "...\"\n",
(void) fprintf(el->el_errfile, " \"%ls...\"\n",
el->el_keymacro.buf);
return 0;
}
@ -586,8 +579,9 @@ node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt)
* Print the specified key and its associated
* function specified by val
*/
protected void
keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
libedit_private void
keymacro_kprint(EditLine *el, const wchar_t *key, keymacro_value_t *val,
int ntype)
{
el_bindings_t *fp;
char unparsbuf[EL_BUFSIZ];
@ -596,7 +590,6 @@ keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
if (val != NULL)
switch (ntype) {
case XK_STR:
case XK_EXE:
(void) keymacro__decode_str(val->str, unparsbuf,
sizeof(unparsbuf),
ntype == XK_STR ? "\"\"" : "[]");
@ -606,7 +599,7 @@ keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
case XK_CMD:
for (fp = el->el_map.help; fp->name; fp++)
if (val->cmd == fp->func) {
ct_wcstombs(unparsbuf, fp->name, sizeof(unparsbuf));
wcstombs(unparsbuf, fp->name, sizeof(unparsbuf));
unparsbuf[sizeof(unparsbuf) -1] = '\0';
(void) fprintf(el->el_outfile, fmt,
ct_encode_string(key, &el->el_scratch), unparsbuf);
@ -637,11 +630,12 @@ keymacro_kprint(EditLine *el, const Char *key, keymacro_value_t *val, int ntype)
/* keymacro__decode_str():
* Make a printable version of the ey
*/
protected size_t
keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep)
libedit_private size_t
keymacro__decode_str(const wchar_t *str, char *buf, size_t len,
const char *sep)
{
char *b = buf, *eb = b + len;
const Char *p;
const wchar_t *p;
b = buf;
if (sep[0] != '\0') {
@ -653,8 +647,8 @@ keymacro__decode_str(const Char *str, char *buf, size_t len, const char *sep)
goto add_endsep;
}
for (p = str; *p != 0; p++) {
Char dbuf[VISUAL_WIDTH_MAX];
Char *p2 = dbuf;
wchar_t dbuf[VISUAL_WIDTH_MAX];
wchar_t *p2 = dbuf;
ssize_t l = ct_visual_char(dbuf, VISUAL_WIDTH_MAX, *p);
while (l-- > 0) {
ssize_t n = ct_encode_char(b, (size_t)(eb - b), *p2++);

View file

@ -1,4 +1,4 @@
/* $NetBSD: keymacro.h,v 1.3 2016/01/29 19:59:11 christos Exp $ */
/* $NetBSD: keymacro.h,v 1.6 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)key.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -43,13 +42,13 @@
typedef union keymacro_value_t {
el_action_t cmd; /* If it is a command the # */
Char *str; /* If it is a string... */
wchar_t *str; /* If it is a string... */
} keymacro_value_t;
typedef struct keymacro_node_t keymacro_node_t;
typedef struct el_keymacro_t {
Char *buf; /* Key print buffer */
wchar_t *buf; /* Key print buffer */
keymacro_node_t *map; /* Key map */
keymacro_value_t val; /* Local conversion buffer */
} el_keymacro_t;
@ -57,21 +56,21 @@ typedef struct el_keymacro_t {
#define XK_CMD 0
#define XK_STR 1
#define XK_NOD 2
#define XK_EXE 3
protected int keymacro_init(EditLine *);
protected void keymacro_end(EditLine *);
protected keymacro_value_t *keymacro_map_cmd(EditLine *, int);
protected keymacro_value_t *keymacro_map_str(EditLine *, Char *);
protected void keymacro_reset(EditLine *);
protected int keymacro_get(EditLine *, Char *, keymacro_value_t *);
protected void keymacro_add(EditLine *, const Char *, keymacro_value_t *, int);
protected void keymacro_clear(EditLine *, el_action_t *, const Char *);
protected int keymacro_delete(EditLine *, const Char *);
protected void keymacro_print(EditLine *, const Char *);
protected void keymacro_kprint(EditLine *, const Char *, keymacro_value_t *,
int);
protected size_t keymacro__decode_str(const Char *, char *, size_t,
libedit_private int keymacro_init(EditLine *);
libedit_private void keymacro_end(EditLine *);
libedit_private keymacro_value_t *keymacro_map_cmd(EditLine *, int);
libedit_private keymacro_value_t *keymacro_map_str(EditLine *, wchar_t *);
libedit_private void keymacro_reset(EditLine *);
libedit_private int keymacro_get(EditLine *, wchar_t *, keymacro_value_t *);
libedit_private void keymacro_add(EditLine *, const wchar_t *,
keymacro_value_t *, int);
libedit_private void keymacro_clear(EditLine *, el_action_t *, const wchar_t *);
libedit_private int keymacro_delete(EditLine *, const wchar_t *);
libedit_private void keymacro_print(EditLine *, const wchar_t *);
libedit_private void keymacro_kprint(EditLine *, const wchar_t *,
keymacro_value_t *, int);
libedit_private size_t keymacro__decode_str(const wchar_t *, char *, size_t,
const char *);
#endif /* _h_el_keymacro */

136
contrib/libedit/literal.c Normal file
View file

@ -0,0 +1,136 @@
/* $NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $ */
/*-
* Copyright (c) 2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $");
#endif /* not lint && not SCCSID */
/*
* literal.c: Literal sequences handling.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "el.h"
libedit_private void
literal_init(EditLine *el)
{
el_literal_t *l = &el->el_literal;
memset(l, 0, sizeof(*l));
}
libedit_private void
literal_end(EditLine *el)
{
literal_clear(el);
}
libedit_private void
literal_clear(EditLine *el)
{
el_literal_t *l = &el->el_literal;
size_t i;
if (l->l_len == 0)
return;
for (i = 0; i < l->l_idx; i++)
el_free(l->l_buf[i]);
el_free(l->l_buf);
l->l_buf = NULL;
l->l_len = 0;
l->l_idx = 0;
}
libedit_private wint_t
literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp)
{
el_literal_t *l = &el->el_literal;
size_t i, len;
ssize_t w, n;
char *b;
w = wcwidth(end[1]); /* column width of the visible char */
*wp = (int)w;
if (w <= 0) /* we require something to be printed */
return 0;
len = (size_t)(end - buf);
for (w = 0, i = 0; i < len; i++)
w += ct_enc_width(buf[i]);
w += ct_enc_width(end[1]);
b = el_malloc((size_t)(w + 1));
if (b == NULL)
return 0;
for (n = 0, i = 0; i < len; i++)
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';
/*
* Then save this literal string in the list of such strings,
* and return a "magic character" to put into the terminal buffer.
* When that magic char is 'printed' the saved string (which includes
* the char that belongs in that position) gets sent instead.
*/
if (l->l_idx == l->l_len) {
char **bp;
l->l_len += 4;
bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * l->l_len);
if (bp == NULL) {
free(b);
l->l_len -= 4;
return 0;
}
l->l_buf = bp;
}
l->l_buf[l->l_idx++] = b;
return EL_LITERAL | (wint_t)(l->l_idx - 1);
}
libedit_private const char *
literal_get(EditLine *el, wint_t idx)
{
el_literal_t *l = &el->el_literal;
assert(idx & EL_LITERAL);
idx &= ~EL_LITERAL;
assert(l->l_idx > (size_t)idx);
return l->l_buf[idx];
}

View file

@ -1,11 +1,11 @@
/* $NetBSD: literal.h,v 1.2 2017/06/30 20:26:52 kre Exp $ */
/*-
* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2017 The NetBSD Foundation, Inc.
* All rights reserved.
*
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Paul Borman at Krystal Technologies.
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@ -15,9 +15,6 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -30,26 +27,27 @@
* 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.
*
* @(#)ldef.h 8.1 (Berkeley) 6/6/93
* $FreeBSD$
*/
#include <sys/types.h>
#include "runefile.h"
/*
* This should look a LOT like a _RuneEntry
* el.literal.h: Literal character
*/
typedef struct rune_list {
int32_t min;
int32_t max;
int32_t map;
uint32_t *types;
struct rune_list *next;
} rune_list;
#ifndef _h_el_literal
#define _h_el_literal
typedef struct rune_map {
uint32_t map[_CACHED_RUNES];
rune_list *root;
} rune_map;
#define EL_LITERAL ((wint_t)0x80000000)
typedef struct el_literal_t {
char **l_buf; /* array of buffers */
size_t l_idx; /* max in use */
size_t l_len; /* max allocated */
} el_literal_t;
libedit_private void literal_init(EditLine *);
libedit_private void literal_end(EditLine *);
libedit_private void literal_clear(EditLine *);
libedit_private wint_t literal_add(EditLine *, const wchar_t *,
const wchar_t *, int *);
libedit_private const char *literal_get(EditLine *, wint_t);
#endif /* _h_el_literal */

View file

@ -1,6 +1,5 @@
#!/bin/sh -
# $FreeBSD$
# $NetBSD: makelist,v 1.18 2012/03/21 05:34:54 matt Exp $
# $NetBSD: makelist,v 1.29 2016/05/09 21:46:56 christos Exp $
#
# Copyright (c) 1992, 1993
# The Regents of the University of California. All rights reserved.
@ -37,7 +36,7 @@
# makelist.sh: Automatically generate header files...
AWK=awk
USAGE="Usage: $0 -n|-h|-e|-fc|-fh|-bc|-bh|-m <filenames>"
USAGE="Usage: $0 -h|-fc|-fh|-bh <filenames>"
if [ "x$1" = "x" ]
then
@ -52,17 +51,6 @@ FILES="$@"
case $FLAG in
# generate foo.h file from foo.c
#
-n)
cat << _EOF
#include "config.h"
#undef WIDECHAR
#define NARROWCHAR
#include "${FILES}"
_EOF
;;
-h)
set - `echo $FILES | sed -e 's/\\./_/g'`
hdr="_h_`basename $1`"
@ -79,7 +67,7 @@ _EOF
# XXX: need a space between name and prototype so that -fc and -fh
# parsing is much easier
#
printf("protected el_action_t\t%s (EditLine *, wint_t);\n",
printf("libedit_private el_action_t\t%s (EditLine *, wint_t);\n",
name);
}
}
@ -88,15 +76,13 @@ _EOF
}'
;;
# generate help.c from various .c files
# generate help.h from various .c files
#
-bc)
-bh)
cat $FILES | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"config.h\"\n#include \"el.h\"\n");
printf("#include \"help.h\"\n");
printf("private const struct el_bindings_t el_func_help[] = {\n");
printf("static const struct el_bindings_t el_func_help[] = {\n");
low = "abcdefghijklmnopqrstuvwxyz_";
high = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_";
for (i = 1; i <= length(low); i++)
@ -116,38 +102,24 @@ _EOF
fname = fname s;
}
printf(" { %-30.30s %-30.30s\n","STR(\"" fname "\"),", uname ",");
printf(" { %-30.30s %-30.30s\n","L\"" fname "\",", uname ",");
ok = 1;
}
}
/^ \*/ {
if (ok) {
printf(" STR(\"");
printf(" L\"");
for (i = 2; i < NF; i++)
printf("%s ", $i);
printf("%s\") },\n", $i);
printf("%s\" },\n", $i);
ok = 0;
}
}
END {
printf("};\n");
printf("\nprotected const el_bindings_t* help__get(void)");
printf("{ return el_func_help; }\n");
}'
;;
# generate help.h from various .c files
#
-bh)
$AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_help_c\n#define _h_help_c\n");
printf("protected const el_bindings_t *help__get(void);\n");
printf("#endif /* _h_help_c */\n");
}' /dev/null
;;
# generate fcns.h from various .h files
#
-fh)
@ -155,7 +127,6 @@ _EOF
sort | tr '[:lower:]' '[:upper:]' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#ifndef _h_fcns_c\n#define _h_fcns_c\n");
count = 0;
}
{
@ -163,24 +134,16 @@ _EOF
}
END {
printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count);
printf("typedef el_action_t (*el_func_t)(EditLine *, wint_t);");
printf("\nprotected const el_func_t* func__get(void);\n");
printf("#endif /* _h_fcns_c */\n");
}'
;;
# generate fcns.c from various .h files
# generate func.h from various .h files
#
-fc)
cat $FILES | $AWK '/el_action_t/ { print $3 }' | sort | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#include \"config.h\"\n#include \"el.h\"\n");
printf("#include \"common.h\"\n");
printf("#include \"emacs.h\"\n");
printf("#include \"vi.h\"\n");
printf("private const el_func_t el_func[] = {");
printf("static const el_func_t el_func[] = {");
maxlen = 80;
needn = 1;
len = 0;
@ -200,59 +163,6 @@ _EOF
}
END {
printf("\n};\n");
printf("\nprotected const el_func_t* func__get(void) { return el_func; }\n");
}'
;;
# generate editline.c from various .c files
#
-e)
echo "$FILES" | tr ' ' '\012' | $AWK '
BEGIN {
printf("/* Automatically generated file, do not edit */\n");
printf("#define protected static\n");
printf("#define SCCSID\n");
}
{
printf("#include \"%s\"\n", $1);
}'
;;
# generate man page fragment from various .c files
#
-m)
cat $FILES | $AWK '
BEGIN {
printf(".\\\" Section automatically generated with makelist\n");
printf(".Bl -tag -width 4n\n");
}
/\(\):/ {
pr = substr($2, 1, 2);
if (pr == "vi" || pr == "em" || pr == "ed") {
name = substr($2, 1, length($2) - 3);
fname = "";
for (i = 1; i <= length(name); i++) {
s = substr(name, i, 1);
if (s == "_")
s = "-";
fname = fname s;
}
printf(".It Ic %s\n", fname);
ok = 1;
}
}
/^ \*/ {
if (ok) {
for (i = 2; i < NF; i++)
printf("%s ", $i);
printf("%s.\n", $i);
ok = 0;
}
}
END {
printf(".El\n");
printf(".\\\" End of section automatically generated with makelist\n");
}'
;;

View file

@ -1,4 +1,4 @@
/* $NetBSD: map.c,v 1.43 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: map.c,v 1.52 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: map.c,v 1.43 2016/02/17 19:47:49 christos Exp $");
__RCSID("$NetBSD: map.c,v 1.52 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* map.c: Editor function definitions
@ -51,23 +49,28 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include "el.h"
#include "common.h"
#include "emacs.h"
#include "vi.h"
#include "fcns.h"
#include "func.h"
#include "help.h"
#include "parse.h"
private void map_print_key(EditLine *, el_action_t *, const Char *);
private void map_print_some_keys(EditLine *, el_action_t *, wint_t, wint_t);
private void map_print_all_keys(EditLine *);
private void map_init_nls(EditLine *);
private void map_init_meta(EditLine *);
static void map_print_key(EditLine *, el_action_t *, const wchar_t *);
static void map_print_some_keys(EditLine *, el_action_t *, wint_t, wint_t);
static void map_print_all_keys(EditLine *);
static void map_init_nls(EditLine *);
static void map_init_meta(EditLine *);
/* keymap tables ; should be N_KEYS*sizeof(KEYCMD) bytes long */
private const el_action_t el_map_emacs[] = {
static const el_action_t el_map_emacs[] = {
/* 0 */ EM_SET_MARK, /* ^@ */
/* 1 */ ED_MOVE_TO_BEG, /* ^A */
/* 2 */ ED_PREV_CHAR, /* ^B */
/* 3 */ ED_TTY_SIGINT, /* ^C */
/* 3 */ ED_IGNORE, /* ^C */
/* 4 */ EM_DELETE_OR_LIST, /* ^D */
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_NEXT_CHAR, /* ^F */
@ -79,21 +82,21 @@ private const el_action_t el_map_emacs[] = {
/* 12 */ ED_CLEAR_SCREEN, /* ^L */
/* 13 */ ED_NEWLINE, /* ^M */
/* 14 */ ED_NEXT_HISTORY, /* ^N */
/* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
/* 15 */ ED_IGNORE, /* ^O */
/* 16 */ ED_PREV_HISTORY, /* ^P */
/* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
/* 17 */ ED_IGNORE, /* ^Q */
/* 18 */ ED_REDISPLAY, /* ^R */
/* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
/* 19 */ ED_IGNORE, /* ^S */
/* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
/* 21 */ EM_KILL_LINE, /* ^U */
/* 22 */ ED_QUOTED_INSERT, /* ^V */
/* 23 */ EM_KILL_REGION, /* ^W */
/* 24 */ ED_SEQUENCE_LEAD_IN, /* ^X */
/* 25 */ EM_YANK, /* ^Y */
/* 26 */ ED_TTY_SIGTSTP, /* ^Z */
/* 26 */ ED_IGNORE, /* ^Z */
/* 27 */ EM_META_NEXT, /* ^[ */
/* 28 */ ED_TTY_SIGQUIT, /* ^\ */
/* 29 */ ED_TTY_DSUSP, /* ^] */
/* 28 */ ED_IGNORE, /* ^\ */
/* 29 */ ED_IGNORE, /* ^] */
/* 30 */ ED_UNASSIGNED, /* ^^ */
/* 31 */ ED_UNASSIGNED, /* ^_ */
/* 32 */ ED_INSERT, /* SPACE */
@ -330,7 +333,7 @@ private const el_action_t el_map_emacs[] = {
* insert mode characters are in the normal keymap, and command mode
* in the extended keymap.
*/
private const el_action_t el_map_vi_insert[] = {
static const el_action_t el_map_vi_insert[] = {
#ifdef KSHVI
/* 0 */ ED_UNASSIGNED, /* ^@ */
/* 1 */ ED_INSERT, /* ^A */
@ -349,9 +352,9 @@ private const el_action_t el_map_vi_insert[] = {
/* 14 */ ED_INSERT, /* ^N */
/* 15 */ ED_INSERT, /* ^O */
/* 16 */ ED_INSERT, /* ^P */
/* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
/* 17 */ ED_IGNORE, /* ^Q */
/* 18 */ ED_INSERT, /* ^R */
/* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
/* 19 */ ED_IGNORE, /* ^S */
/* 20 */ ED_INSERT, /* ^T */
/* 21 */ VI_KILL_LINE_PREV, /* ^U */
/* 22 */ ED_QUOTED_INSERT, /* ^V */
@ -361,7 +364,7 @@ private const el_action_t el_map_vi_insert[] = {
/* 25 */ ED_INSERT, /* ^Y */
/* 26 */ ED_INSERT, /* ^Z */
/* 27 */ VI_COMMAND_MODE, /* ^[ */ /* [ Esc ] key */
/* 28 */ ED_TTY_SIGQUIT, /* ^\ */
/* 28 */ ED_IGNORE, /* ^\ */
/* 29 */ ED_INSERT, /* ^] */
/* 30 */ ED_INSERT, /* ^^ */
/* 31 */ ED_INSERT, /* ^_ */
@ -370,12 +373,12 @@ private const el_action_t el_map_vi_insert[] = {
* NOTE: These mappings do NOT Correspond well
* to the KSH VI editing assignments.
* On the other and they are convenient and
* many people have gotten used to them.
* many people have have gotten used to them.
*/
/* 0 */ ED_UNASSIGNED, /* ^@ */
/* 1 */ ED_MOVE_TO_BEG, /* ^A */
/* 2 */ ED_PREV_CHAR, /* ^B */
/* 3 */ ED_TTY_SIGINT, /* ^C */
/* 3 */ ED_IGNORE, /* ^C */
/* 4 */ VI_LIST_OR_EOF, /* ^D */
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_NEXT_CHAR, /* ^F */
@ -387,20 +390,20 @@ private const el_action_t el_map_vi_insert[] = {
/* 12 */ ED_CLEAR_SCREEN, /* ^L */
/* 13 */ ED_NEWLINE, /* ^M */
/* 14 */ ED_NEXT_HISTORY, /* ^N */
/* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
/* 15 */ ED_IGNORE, /* ^O */
/* 16 */ ED_PREV_HISTORY, /* ^P */
/* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
/* 17 */ ED_IGNORE, /* ^Q */
/* 18 */ ED_REDISPLAY, /* ^R */
/* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
/* 19 */ ED_IGNORE, /* ^S */
/* 20 */ ED_TRANSPOSE_CHARS, /* ^T */
/* 21 */ VI_KILL_LINE_PREV, /* ^U */
/* 22 */ ED_QUOTED_INSERT, /* ^V */
/* 23 */ ED_DELETE_PREV_WORD, /* ^W */
/* 24 */ ED_UNASSIGNED, /* ^X */
/* 25 */ ED_TTY_DSUSP, /* ^Y */
/* 26 */ ED_TTY_SIGTSTP, /* ^Z */
/* 25 */ ED_IGNORE, /* ^Y */
/* 26 */ ED_IGNORE, /* ^Z */
/* 27 */ VI_COMMAND_MODE, /* ^[ */
/* 28 */ ED_TTY_SIGQUIT, /* ^\ */
/* 28 */ ED_IGNORE, /* ^\ */
/* 29 */ ED_UNASSIGNED, /* ^] */
/* 30 */ ED_UNASSIGNED, /* ^^ */
/* 31 */ ED_UNASSIGNED, /* ^_ */
@ -631,11 +634,11 @@ private const el_action_t el_map_vi_insert[] = {
/* 255 */ ED_INSERT /* M-^? */
};
private const el_action_t el_map_vi_command[] = {
static const el_action_t el_map_vi_command[] = {
/* 0 */ ED_UNASSIGNED, /* ^@ */
/* 1 */ ED_MOVE_TO_BEG, /* ^A */
/* 2 */ ED_UNASSIGNED, /* ^B */
/* 3 */ ED_TTY_SIGINT, /* ^C */
/* 3 */ ED_IGNORE, /* ^C */
/* 4 */ ED_UNASSIGNED, /* ^D */
/* 5 */ ED_MOVE_TO_END, /* ^E */
/* 6 */ ED_UNASSIGNED, /* ^F */
@ -647,11 +650,11 @@ private const el_action_t el_map_vi_command[] = {
/* 12 */ ED_CLEAR_SCREEN, /* ^L */
/* 13 */ ED_NEWLINE, /* ^M */
/* 14 */ ED_NEXT_HISTORY, /* ^N */
/* 15 */ ED_TTY_FLUSH_OUTPUT, /* ^O */
/* 15 */ ED_IGNORE, /* ^O */
/* 16 */ ED_PREV_HISTORY, /* ^P */
/* 17 */ ED_TTY_START_OUTPUT, /* ^Q */
/* 17 */ ED_IGNORE, /* ^Q */
/* 18 */ ED_REDISPLAY, /* ^R */
/* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */
/* 19 */ ED_IGNORE, /* ^S */
/* 20 */ ED_UNASSIGNED, /* ^T */
/* 21 */ VI_KILL_LINE_PREV, /* ^U */
/* 22 */ ED_UNASSIGNED, /* ^V */
@ -660,7 +663,7 @@ private const el_action_t el_map_vi_command[] = {
/* 25 */ ED_UNASSIGNED, /* ^Y */
/* 26 */ ED_UNASSIGNED, /* ^Z */
/* 27 */ EM_META_NEXT, /* ^[ */
/* 28 */ ED_TTY_SIGQUIT, /* ^\ */
/* 28 */ ED_IGNORE, /* ^\ */
/* 29 */ ED_UNASSIGNED, /* ^] */
/* 30 */ ED_UNASSIGNED, /* ^^ */
/* 31 */ ED_UNASSIGNED, /* ^_ */
@ -894,7 +897,7 @@ private const el_action_t el_map_vi_command[] = {
/* map_init():
* Initialize and allocate the maps
*/
protected int
libedit_private int
map_init(EditLine *el)
{
@ -910,24 +913,24 @@ 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, help__get(),
(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, func__get(), sizeof(*el->el_map.func)
memcpy(el->el_map.func, el_func, sizeof(*el->el_map.func)
* EL_NUM_FCNS);
el->el_map.nfunc = EL_NUM_FCNS;
@ -943,7 +946,7 @@ map_init(EditLine *el)
/* map_end():
* Free the space taken by the editor maps
*/
protected void
libedit_private void
map_end(EditLine *el)
{
@ -964,7 +967,7 @@ map_end(EditLine *el)
/* map_init_nls():
* Find all the printable keys and bind them to self insert
*/
private void
static void
map_init_nls(EditLine *el)
{
int i;
@ -972,7 +975,7 @@ map_init_nls(EditLine *el)
el_action_t *map = el->el_map.key;
for (i = 0200; i <= 0377; i++)
if (Isprint(i))
if (iswprint(i))
map[i] = ED_INSERT;
}
@ -980,10 +983,10 @@ map_init_nls(EditLine *el)
/* map_init_meta():
* Bind all the meta keys to the appropriate ESC-<key> sequence
*/
private void
static void
map_init_meta(EditLine *el)
{
Char buf[3];
wchar_t buf[3];
int i;
el_action_t *map = el->el_map.key;
el_action_t *alt = el->el_map.alt;
@ -1001,7 +1004,7 @@ map_init_meta(EditLine *el)
} else
map = alt;
}
buf[0] = (Char) i;
buf[0] = (wchar_t)i;
buf[2] = 0;
for (i = 0200; i <= 0377; i++)
switch (map[i]) {
@ -1021,7 +1024,7 @@ map_init_meta(EditLine *el)
/* map_init_vi():
* Initialize the vi bindings
*/
protected void
libedit_private void
map_init_vi(EditLine *el)
{
int i;
@ -1051,11 +1054,11 @@ map_init_vi(EditLine *el)
/* map_init_emacs():
* Initialize the emacs bindings
*/
protected void
libedit_private void
map_init_emacs(EditLine *el)
{
int i;
Char buf[3];
wchar_t buf[3];
el_action_t *key = el->el_map.key;
el_action_t *alt = el->el_map.alt;
const el_action_t *emacs = el->el_map.emacs;
@ -1085,15 +1088,15 @@ map_init_emacs(EditLine *el)
/* map_set_editor():
* Set the editor
*/
protected int
map_set_editor(EditLine *el, Char *editor)
libedit_private int
map_set_editor(EditLine *el, wchar_t *editor)
{
if (Strcmp(editor, STR("emacs")) == 0) {
if (wcscmp(editor, L"emacs") == 0) {
map_init_emacs(el);
return 0;
}
if (Strcmp(editor, STR("vi")) == 0) {
if (wcscmp(editor, L"vi") == 0) {
map_init_vi(el);
return 0;
}
@ -1104,18 +1107,18 @@ map_set_editor(EditLine *el, Char *editor)
/* map_get_editor():
* Retrieve the editor
*/
protected int
map_get_editor(EditLine *el, const Char **editor)
libedit_private int
map_get_editor(EditLine *el, const wchar_t **editor)
{
if (editor == NULL)
return -1;
switch (el->el_map.type) {
case MAP_EMACS:
*editor = STR("emacs");
*editor = L"emacs";
return 0;
case MAP_VI:
*editor = STR("vi");
*editor = L"vi";
return 0;
}
return -1;
@ -1125,8 +1128,8 @@ map_get_editor(EditLine *el, const Char **editor)
/* map_print_key():
* Print the function description for 1 key
*/
private void
map_print_key(EditLine *el, el_action_t *map, const Char *in)
static void
map_print_key(EditLine *el, el_action_t *map, const wchar_t *in)
{
char outbuf[EL_BUFSIZ];
el_bindings_t *bp, *ep;
@ -1137,7 +1140,7 @@ map_print_key(EditLine *el, el_action_t *map, const Char *in)
for (bp = el->el_map.help; bp < ep; bp++)
if (bp->func == map[(unsigned char) *in]) {
(void) fprintf(el->el_outfile,
"%s\t->\t" FSTR "\n", outbuf, bp->name);
"%s\t->\t%ls\n", outbuf, bp->name);
return;
}
} else
@ -1148,16 +1151,16 @@ map_print_key(EditLine *el, el_action_t *map, const Char *in)
/* map_print_some_keys():
* Print keys from first to last
*/
private void
static void
map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last)
{
el_bindings_t *bp, *ep;
Char firstbuf[2], lastbuf[2];
wchar_t firstbuf[2], lastbuf[2];
char unparsbuf[EL_BUFSIZ], extrabuf[EL_BUFSIZ];
firstbuf[0] = (Char)first;
firstbuf[0] = first;
firstbuf[1] = 0;
lastbuf[0] = (Char)last;
lastbuf[0] = last;
lastbuf[1] = 0;
if (map[first] == ED_UNASSIGNED) {
if (first == last) {
@ -1174,7 +1177,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last)
if (first == last) {
(void) keymacro__decode_str(firstbuf, unparsbuf,
sizeof(unparsbuf), STRQQ);
(void) fprintf(el->el_outfile, "%-15s-> " FSTR "\n",
(void) fprintf(el->el_outfile, "%-15s-> %ls\n",
unparsbuf, bp->name);
} else {
(void) keymacro__decode_str(firstbuf, unparsbuf,
@ -1182,7 +1185,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last)
(void) keymacro__decode_str(lastbuf, extrabuf,
sizeof(extrabuf), STRQQ);
(void) fprintf(el->el_outfile,
"%-4s to %-7s-> " FSTR "\n",
"%-4s to %-7s-> %ls\n",
unparsbuf, extrabuf, bp->name);
}
return;
@ -1212,7 +1215,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, wint_t first, wint_t last)
/* map_print_all_keys():
* Print the function description for all keys.
*/
private void
static void
map_print_all_keys(EditLine *el)
{
int prev, i;
@ -1238,25 +1241,25 @@ map_print_all_keys(EditLine *el)
map_print_some_keys(el, el->el_map.alt, prev, i - 1);
(void) fprintf(el->el_outfile, "Multi-character bindings\n");
keymacro_print(el, STR(""));
keymacro_print(el, L"");
(void) fprintf(el->el_outfile, "Arrow key bindings\n");
terminal_print_arrow(el, STR(""));
terminal_print_arrow(el, L"");
}
/* map_bind():
* Add/remove/change bindings
*/
protected int
map_bind(EditLine *el, int argc, const Char **argv)
libedit_private int
map_bind(EditLine *el, int argc, const wchar_t **argv)
{
el_action_t *map;
int ntype, rem;
const Char *p;
Char inbuf[EL_BUFSIZ];
Char outbuf[EL_BUFSIZ];
const Char *in = NULL;
Char *out;
const wchar_t *p;
wchar_t inbuf[EL_BUFSIZ];
wchar_t outbuf[EL_BUFSIZ];
const wchar_t *in = NULL;
wchar_t *out;
el_bindings_t *bp, *ep;
int cmd;
int key;
@ -1277,11 +1280,6 @@ map_bind(EditLine *el, int argc, const Char **argv)
case 's':
ntype = XK_STR;
break;
#ifdef notyet
case 'c':
ntype = XK_EXE;
break;
#endif
case 'k':
key = 1;
break;
@ -1302,12 +1300,12 @@ map_bind(EditLine *el, int argc, const Char **argv)
ep = &el->el_map.help[el->el_map.nfunc];
for (bp = el->el_map.help; bp < ep; bp++)
(void) fprintf(el->el_outfile,
"" FSTR "\n\t" FSTR "\n",
"%ls\n\t%ls\n",
bp->name, bp->description);
return 0;
default:
(void) fprintf(el->el_errfile,
"" FSTR ": Invalid switch `%lc'.\n",
"%ls: Invalid switch `%lc'.\n",
argv[0], (wint_t)p[1]);
}
else
@ -1321,7 +1319,7 @@ map_bind(EditLine *el, int argc, const Char **argv)
in = argv[argc++];
else if ((in = parse__string(inbuf, argv[argc++])) == NULL) {
(void) fprintf(el->el_errfile,
"" FSTR ": Invalid \\ or ^ in instring.\n",
"%ls: Invalid \\ or ^ in instring.\n",
argv[0]);
return -1;
}
@ -1354,10 +1352,9 @@ map_bind(EditLine *el, int argc, const Char **argv)
switch (ntype) {
case XK_STR:
case XK_EXE:
if ((out = parse__string(outbuf, argv[argc])) == NULL) {
(void) fprintf(el->el_errfile,
"" FSTR ": Invalid \\ or ^ in outstring.\n", argv[0]);
"%ls: Invalid \\ or ^ in outstring.\n", argv[0]);
return -1;
}
if (key)
@ -1370,7 +1367,7 @@ map_bind(EditLine *el, int argc, const Char **argv)
case XK_CMD:
if ((cmd = parse_cmd(el, argv[argc])) == -1) {
(void) fprintf(el->el_errfile,
"" FSTR ": Invalid command `" FSTR "'.\n",
"%ls: Invalid command `%ls'.\n",
argv[0], argv[argc]);
return -1;
}
@ -1399,8 +1396,9 @@ map_bind(EditLine *el, int argc, const Char **argv)
/* map_addfunc():
* add a user defined function
*/
protected int
map_addfunc(EditLine *el, const Char *name, const Char *help, el_func_t func)
libedit_private int
map_addfunc(EditLine *el, const wchar_t *name, const wchar_t *help,
el_func_t func)
{
void *p;
size_t nf = el->el_map.nfunc + 1;

View file

@ -1,4 +1,4 @@
/* $NetBSD: map.h,v 1.10 2014/07/06 18:15:34 christos Exp $ */
/* $NetBSD: map.h,v 1.13 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)map.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -41,12 +40,13 @@
#ifndef _h_el_map
#define _h_el_map
typedef struct el_bindings_t { /* for the "bind" shell command */
const Char *name; /* function name for bind command */
int func; /* function numeric value */
const Char *description; /* description of function */
} el_bindings_t;
typedef el_action_t (*el_func_t)(EditLine *, wint_t);
typedef struct el_bindings_t { /* for the "bind" shell command */
const wchar_t *name; /* function name for bind command */
int func; /* function numeric value */
const wchar_t *description; /* description of function */
} el_bindings_t;
typedef struct el_map_t {
el_action_t *alt; /* The current alternate key map */
@ -66,13 +66,14 @@ typedef struct el_map_t {
#define N_KEYS 256
protected int map_bind(EditLine *, int, const Char **);
protected int map_init(EditLine *);
protected void map_end(EditLine *);
protected void map_init_vi(EditLine *);
protected void map_init_emacs(EditLine *);
protected int map_set_editor(EditLine *, Char *);
protected int map_get_editor(EditLine *, const Char **);
protected int map_addfunc(EditLine *, const Char *, const Char *, el_func_t);
libedit_private int map_bind(EditLine *, int, const wchar_t **);
libedit_private int map_init(EditLine *);
libedit_private void map_end(EditLine *);
libedit_private void map_init_vi(EditLine *);
libedit_private void map_init_emacs(EditLine *);
libedit_private int map_set_editor(EditLine *, wchar_t *);
libedit_private int map_get_editor(EditLine *, const wchar_t **);
libedit_private int map_addfunc(EditLine *, const wchar_t *, const wchar_t *,
el_func_t);
#endif /* _h_el_map */

View file

@ -1,4 +1,4 @@
/* $NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: parse.c,v 1.35 2016/02/17 19:47:49 christos Exp $");
__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* parse.c: parse an editline extended command
@ -62,35 +60,35 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "parse.h"
private const struct {
const Char *name;
int (*func)(EditLine *, int, const Char **);
static const struct {
const wchar_t *name;
int (*func)(EditLine *, int, const wchar_t **);
} cmds[] = {
{ STR("bind"), map_bind },
{ STR("echotc"), terminal_echotc },
{ STR("edit"), el_editmode },
{ STR("history"), hist_command },
{ STR("telltc"), terminal_telltc },
{ STR("settc"), terminal_settc },
{ STR("setty"), tty_stty },
{ NULL, NULL }
{ L"bind", map_bind },
{ L"echotc", terminal_echotc },
{ L"edit", el_editmode },
{ L"history", hist_command },
{ L"telltc", terminal_telltc },
{ L"settc", terminal_settc },
{ L"setty", tty_stty },
{ NULL, NULL }
};
/* parse_line():
* Parse a line and dispatch it
*/
protected int
parse_line(EditLine *el, const Char *line)
libedit_private int
parse_line(EditLine *el, const wchar_t *line)
{
const Char **argv;
const wchar_t **argv;
int argc;
TYPE(Tokenizer) *tok;
TokenizerW *tok;
tok = FUN(tok,init)(NULL);
FUN(tok,str)(tok, line, &argc, &argv);
argc = FUN(el,parse)(el, argc, argv);
FUN(tok,end)(tok);
tok = tok_winit(NULL);
tok_wstr(tok, line, &argc, &argv);
argc = el_wparse(el, argc, argv);
tok_wend(tok);
return argc;
}
@ -98,26 +96,26 @@ parse_line(EditLine *el, const Char *line)
/* el_parse():
* Command dispatcher
*/
public int
FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
int
el_wparse(EditLine *el, int argc, const wchar_t *argv[])
{
const Char *ptr;
const wchar_t *ptr;
int i;
if (argc < 1)
return -1;
ptr = Strchr(argv[0], ':');
ptr = wcschr(argv[0], L':');
if (ptr != NULL) {
Char *tprog;
wchar_t *tprog;
size_t l;
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) Strncpy(tprog, argv[0], l);
(void) wcsncpy(tprog, argv[0], l);
tprog[l] = '\0';
ptr++;
l = (size_t)el_match(el->el_prog, tprog);
@ -128,7 +126,7 @@ FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
ptr = argv[0];
for (i = 0; cmds[i].name != NULL; i++)
if (Strcmp(cmds[i].name, ptr) == 0) {
if (wcscmp(cmds[i].name, ptr) == 0) {
i = (*cmds[i].func) (el, argc, argv);
return -i;
}
@ -140,10 +138,10 @@ FUN(el,parse)(EditLine *el, int argc, const Char *argv[])
* Parse a string of the form ^<char> \<odigit> \<char> \U+xxxx and return
* the appropriate character or -1 if the escape is not valid
*/
protected int
parse__escape(const Char **ptr)
libedit_private int
parse__escape(const wchar_t **ptr)
{
const Char *p;
const wchar_t *p;
wint_t c;
p = *ptr;
@ -178,28 +176,28 @@ parse__escape(const Char **ptr)
case 'e':
c = '\033'; /* Escape */
break;
case 'U': /* Unicode \U+xxxx or \U+xxxxx format */
{
int i;
const Char hex[] = STR("0123456789ABCDEF");
const Char *h;
++p;
if (*p++ != '+')
return -1;
case 'U': /* Unicode \U+xxxx or \U+xxxxx format */
{
int i;
const wchar_t hex[] = L"0123456789ABCDEF";
const wchar_t *h;
++p;
if (*p++ != '+')
return -1;
c = 0;
for (i = 0; i < 5; ++i) {
h = Strchr(hex, *p++);
if (!h && i < 4)
return -1;
else if (h)
c = (c << 4) | ((int)(h - hex));
else
--p;
}
if (c > 0x10FFFF) /* outside valid character range */
return -1;
break;
}
for (i = 0; i < 5; ++i) {
h = wcschr(hex, *p++);
if (!h && i < 4)
return -1;
else if (h)
c = (c << 4) | ((int)(h - hex));
else
--p;
}
if (c > 0x10FFFF) /* outside valid character range */
return -1;
break;
}
case '0':
case '1':
case '2':
@ -240,10 +238,10 @@ parse__escape(const Char **ptr)
/* parse__string():
* Parse the escapes from in and put the raw string out
*/
protected Char *
parse__string(Char *out, const Char *in)
libedit_private wchar_t *
parse__string(wchar_t *out, const wchar_t *in)
{
Char *rv = out;
wchar_t *rv = out;
int n;
for (;;)
@ -256,7 +254,7 @@ parse__string(Char *out, const Char *in)
case '^':
if ((n = parse__escape(&in)) == -1)
return NULL;
*out++ = (Char)n;
*out++ = (wchar_t)n;
break;
case 'M':
@ -278,14 +276,14 @@ parse__string(Char *out, const Char *in)
* Return the command number for the command string given
* or -1 if one is not found
*/
protected int
parse_cmd(EditLine *el, const Char *cmd)
libedit_private int
parse_cmd(EditLine *el, const wchar_t *cmd)
{
el_bindings_t *b = el->el_map.help;
size_t i;
for (i = 0; i < el->el_map.nfunc; i++)
if (Strcmp(b[i].name, cmd) == 0)
if (wcscmp(b[i].name, cmd) == 0)
return b[i].func;
return -1;
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: parse.h,v 1.7 2009/12/30 22:37:40 christos Exp $ */
/* $NetBSD: parse.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)parse.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -41,9 +40,9 @@
#ifndef _h_el_parse
#define _h_el_parse
protected int parse_line(EditLine *, const Char *);
protected int parse__escape(const Char **);
protected Char *parse__string(Char *, const Char *);
protected int parse_cmd(EditLine *, const Char *);
libedit_private int parse_line(EditLine *, const wchar_t *);
libedit_private int parse__escape(const wchar_t **);
libedit_private wchar_t *parse__string(wchar_t *, const wchar_t *);
libedit_private int parse_cmd(EditLine *, const wchar_t *);
#endif /* _h_el_parse */

View file

@ -1,4 +1,4 @@
/* $NetBSD: prompt.c,v 1.23 2016/02/16 15:53:48 christos Exp $ */
/* $NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: prompt.c,v 1.23 2016/02/16 15:53:48 christos Exp $");
__RCSID("$NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* prompt.c: Prompt printing functions
@ -49,17 +47,17 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include "el.h"
private Char *prompt_default(EditLine *);
private Char *prompt_default_r(EditLine *);
static wchar_t *prompt_default(EditLine *);
static wchar_t *prompt_default_r(EditLine *);
/* prompt_default():
* Just a default prompt, in case the user did not provide one
*/
private Char *
static wchar_t *
/*ARGSUSED*/
prompt_default(EditLine *el __attribute__((__unused__)))
{
static Char a[3] = {'?', ' ', '\0'};
static wchar_t a[3] = L"? ";
return a;
}
@ -68,11 +66,11 @@ prompt_default(EditLine *el __attribute__((__unused__)))
/* prompt_default_r():
* Just a default rprompt, in case the user did not provide one
*/
private Char *
static wchar_t *
/*ARGSUSED*/
prompt_default_r(EditLine *el __attribute__((__unused__)))
{
static Char a[1] = {'\0'};
static wchar_t a[1] = L"";
return a;
}
@ -81,12 +79,11 @@ prompt_default_r(EditLine *el __attribute__((__unused__)))
/* prompt_print():
* Print the prompt and update the prompt position.
*/
protected void
libedit_private void
prompt_print(EditLine *el, int op)
{
el_prompt_t *elp;
Char *p;
int ignore = 0;
wchar_t *p;
if (op == EL_PROMPT)
elp = &el->el_prompt;
@ -101,13 +98,17 @@ prompt_print(EditLine *el, int op)
for (; *p; p++) {
if (elp->p_ignore == *p) {
ignore = !ignore;
wchar_t *litstart = ++p;
while (*p && *p != elp->p_ignore)
p++;
if (!*p || !p[1]) {
// XXX: We lose the last literal
break;
}
re_putliteral(el, litstart, p++);
continue;
}
if (ignore)
terminal__putc(el, *p);
else
re_putc(el, *p, 1);
re_putc(el, *p, 1);
}
elp->p_pos.v = el->el_refresh.r_cursor.v;
@ -118,7 +119,7 @@ prompt_print(EditLine *el, int op)
/* prompt_init():
* Initialize the prompt stuff
*/
protected int
libedit_private int
prompt_init(EditLine *el)
{
@ -137,7 +138,7 @@ prompt_init(EditLine *el)
/* prompt_end():
* Clean up the prompt stuff
*/
protected void
libedit_private void
/*ARGSUSED*/
prompt_end(EditLine *el __attribute__((__unused__)))
{
@ -147,8 +148,8 @@ prompt_end(EditLine *el __attribute__((__unused__)))
/* prompt_set():
* Install a prompt printing function
*/
protected int
prompt_set(EditLine *el, el_pfunc_t prf, Char c, int op, int wide)
libedit_private int
prompt_set(EditLine *el, el_pfunc_t prf, wchar_t c, int op, int wide)
{
el_prompt_t *p;
@ -179,8 +180,8 @@ prompt_set(EditLine *el, el_pfunc_t prf, Char c, int op, int wide)
/* prompt_get():
* Retrieve the prompt printing function
*/
protected int
prompt_get(EditLine *el, el_pfunc_t *prf, Char *c, int op)
libedit_private int
prompt_get(EditLine *el, el_pfunc_t *prf, wchar_t *c, int op)
{
el_prompt_t *p;

View file

@ -1,4 +1,4 @@
/* $NetBSD: prompt.h,v 1.13 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: prompt.h,v 1.15 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)prompt.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -41,19 +40,19 @@
#ifndef _h_el_prompt
#define _h_el_prompt
typedef Char *(*el_pfunc_t)(EditLine *);
typedef wchar_t *(*el_pfunc_t)(EditLine *);
typedef struct el_prompt_t {
el_pfunc_t p_func; /* Function to return the prompt */
coord_t p_pos; /* position in the line after prompt */
Char p_ignore; /* character to start/end literal */
wchar_t p_ignore; /* character to start/end literal */
int p_wide;
} el_prompt_t;
protected void prompt_print(EditLine *, int);
protected int prompt_set(EditLine *, el_pfunc_t, Char, int, int);
protected int prompt_get(EditLine *, el_pfunc_t *, Char *, int);
protected int prompt_init(EditLine *);
protected void prompt_end(EditLine *);
libedit_private void prompt_print(EditLine *, int);
libedit_private int prompt_set(EditLine *, el_pfunc_t, wchar_t, int, int);
libedit_private int prompt_get(EditLine *, el_pfunc_t *, wchar_t *, int);
libedit_private int prompt_init(EditLine *);
libedit_private void prompt_end(EditLine *);
#endif /* _h_el_prompt */

View file

@ -1,4 +1,4 @@
/* $NetBSD: read.c,v 1.86 2016/03/02 19:24:20 christos Exp $ */
/* $NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,15 +37,12 @@
#if 0
static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: read.c,v 1.86 2016/03/02 19:24:20 christos Exp $");
__RCSID("$NetBSD: read.c,v 1.106 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* read.c: Clean this junk up! This is horrible code.
* Terminal read functions
* read.c: Terminal read functions
*/
#include <ctype.h>
#include <errno.h>
@ -56,35 +53,74 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
#include "el.h"
#include "fcns.h"
#include "read.h"
#define OKCMD -1 /* must be -1! */
#define EL_MAXMACRO 10
private int read__fixio(int, int);
private int read_preread(EditLine *);
private int read_char(EditLine *, wchar_t *);
private int read_getcmd(EditLine *, el_action_t *, Char *);
private void read_pop(c_macro_t *);
struct macros {
wchar_t **macro;
int level;
int offset;
};
struct el_read_t {
struct macros macros;
el_rfunc_t read_char; /* Function to read a character. */
int read_errno;
};
static int read__fixio(int, int);
static int read_char(EditLine *, wchar_t *);
static int read_getcmd(EditLine *, el_action_t *, wchar_t *);
static void read_clearmacros(struct macros *);
static void read_pop(struct macros *);
static const wchar_t *noedit_wgets(EditLine *, int *);
/* read_init():
* Initialize the read stuff
*/
protected int
libedit_private int
read_init(EditLine *el)
{
struct macros *ma;
if ((el->el_read = el_malloc(sizeof(*el->el_read))) == NULL)
return -1;
ma = &el->el_read->macros;
if ((ma->macro = el_calloc(EL_MAXMACRO, sizeof(*ma->macro))) == NULL) {
free(el->el_read);
return -1;
}
ma->level = -1;
ma->offset = 0;
/* builtin read_char */
el->el_read.read_char = read_char;
el->el_read->read_char = read_char;
return 0;
}
/* el_read_end():
* Free the data structures used by the read stuff.
*/
libedit_private void
read_end(struct el_read_t *el_read)
{
read_clearmacros(&el_read->macros);
el_free(el_read->macros.macro);
el_read->macros.macro = NULL;
el_free(el_read);
}
/* el_read_setfn():
* Set the read char function to the one provided.
* If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
*/
protected int
el_read_setfn(EditLine *el, el_rfunc_t rc)
libedit_private int
el_read_setfn(struct el_read_t *el_read, el_rfunc_t rc)
{
el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
el_read->read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
return 0;
}
@ -93,42 +129,19 @@ el_read_setfn(EditLine *el, el_rfunc_t rc)
* return the current read char function, or EL_BUILTIN_GETCFN
* if it is the default one
*/
protected el_rfunc_t
el_read_getfn(EditLine *el)
libedit_private el_rfunc_t
el_read_getfn(struct el_read_t *el_read)
{
return el->el_read.read_char == read_char ?
EL_BUILTIN_GETCFN : el->el_read.read_char;
return el_read->read_char == read_char ?
EL_BUILTIN_GETCFN : el_read->read_char;
}
#ifndef MIN
#define MIN(A,B) ((A) < (B) ? (A) : (B))
#endif
#ifdef DEBUG_EDIT
private void
read_debug(EditLine *el)
{
if (el->el_line.cursor > el->el_line.lastchar)
(void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
if (el->el_line.cursor < el->el_line.buffer)
(void) fprintf(el->el_errfile, "cursor < buffer\r\n");
if (el->el_line.cursor > el->el_line.limit)
(void) fprintf(el->el_errfile, "cursor > limit\r\n");
if (el->el_line.lastchar > el->el_line.limit)
(void) fprintf(el->el_errfile, "lastchar > limit\r\n");
if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
(void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
}
#endif /* DEBUG_EDIT */
/* read__fixio():
* Try to recover from a read error
*/
/* ARGSUSED */
private int
static int
read__fixio(int fd __attribute__((__unused__)), int e)
{
@ -186,49 +199,17 @@ read__fixio(int fd __attribute__((__unused__)), int e)
}
/* read_preread():
* Try to read the stuff in the input queue;
*/
private int
read_preread(EditLine *el)
{
int chrs = 0;
if (el->el_tty.t_mode == ED_IO)
return 0;
#ifndef WIDECHAR
/* FIONREAD attempts to buffer up multiple bytes, and to make that work
* properly with partial wide/UTF-8 characters would need some careful work. */
#ifdef FIONREAD
(void) ioctl(el->el_infd, FIONREAD, &chrs);
if (chrs > 0) {
char buf[EL_BUFSIZ];
chrs = read(el->el_infd, buf,
(size_t) MIN(chrs, EL_BUFSIZ - 1));
if (chrs > 0) {
buf[chrs] = '\0';
el_push(el, buf);
}
}
#endif /* FIONREAD */
#endif
return chrs > 0;
}
/* el_push():
* Push a macro
*/
public void
FUN(el,push)(EditLine *el, const Char *str)
void
el_wpush(EditLine *el, const wchar_t *str)
{
c_macro_t *ma = &el->el_chared.c_macro;
struct macros *ma = &el->el_read->macros;
if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
ma->level++;
if ((ma->macro[ma->level] = Strdup(str)) != NULL)
if ((ma->macro[ma->level] = wcsdup(str)) != NULL)
return;
ma->level--;
}
@ -238,24 +219,19 @@ FUN(el,push)(EditLine *el, const Char *str)
/* read_getcmd():
* Get next command from the input stream, return OKCMD on success.
* Get next command from the input stream,
* return 0 on success or -1 on EOF or error.
* Character values > 255 are not looked up in the map, but inserted.
*/
private int
read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
static int
read_getcmd(EditLine *el, el_action_t *cmdnum, wchar_t *ch)
{
static const Char meta = (Char)0x80;
static const wchar_t meta = (wchar_t)0x80;
el_action_t cmd;
wchar_t wc;
int num;
el->el_errno = 0;
do {
if ((num = el_wgetc(el, &wc)) != 1) {/* if EOF or error */
el->el_errno = num == 0 ? 0 : errno;
return 0; /* not OKCMD */
}
*ch = (Char)wc;
if (el_wgetc(el, ch) != 1)
return -1;
#ifdef KANJI
if ((*ch & meta)) {
@ -269,11 +245,9 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
el->el_state.metanext = 0;
*ch |= meta;
}
#ifdef WIDECHAR
if (*ch >= N_KEYS)
cmd = ED_INSERT;
else
#endif
cmd = el->el_map.current[(unsigned char) *ch];
if (cmd == ED_SEQUENCE_LEAD_IN) {
keymacro_value_t val;
@ -282,30 +256,24 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
cmd = val.cmd;
break;
case XK_STR:
FUN(el,push)(el, val.str);
el_wpush(el, val.str);
break;
#ifdef notyet
case XK_EXE:
/* XXX: In the future to run a user function */
RunCommand(val.str);
break;
#endif
case XK_NOD:
return -1;
default:
EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
break;
}
}
if (el->el_map.alt == NULL)
el->el_map.current = el->el_map.key;
} while (cmd == ED_SEQUENCE_LEAD_IN);
*cmdnum = cmd;
return OKCMD;
return 0;
}
/* read_char():
* Read a character from the tty.
*/
private int
static int
read_char(EditLine *el, wchar_t *cp)
{
ssize_t num_read;
@ -320,7 +288,7 @@ read_char(EditLine *el, wchar_t *cp)
int e = errno;
switch (el->el_signal->sig_no) {
case SIGCONT:
FUN(el,set)(el, EL_REFRESH);
el_wset(el, EL_REFRESH);
/*FALLTHROUGH*/
case SIGWINCH:
sig_set(el);
@ -345,9 +313,12 @@ read_char(EditLine *el, wchar_t *cp)
}
for (;;) {
mbstate_t mbs;
++cbp;
switch (ct_mbrtowc(cp, cbuf, cbp)) {
/* This only works because UTF8 is stateless. */
memset(&mbs, 0, sizeof(mbs));
switch (mbrtowc(cp, cbuf, cbp, &mbs)) {
case (size_t)-1:
if (cbp > 1) {
/*
@ -380,8 +351,8 @@ read_char(EditLine *el, wchar_t *cp)
/* read_pop():
* Pop a macro from the stack
*/
private void
read_pop(c_macro_t *ma)
static void
read_pop(struct macros *ma)
{
int i;
@ -392,22 +363,25 @@ read_pop(c_macro_t *ma)
ma->offset = 0;
}
static void
read_clearmacros(struct macros *ma)
{
while (ma->level >= 0)
el_free(ma->macro[ma->level--]);
ma->offset = 0;
}
/* el_wgetc():
* Read a wide character
*/
public int
int
el_wgetc(EditLine *el, wchar_t *cp)
{
struct macros *ma = &el->el_read->macros;
int num_read;
c_macro_t *ma = &el->el_chared.c_macro;
terminal__flush(el);
for (;;) {
if (ma->level < 0) {
if (!read_preread(el))
break;
}
if (ma->level < 0)
break;
@ -426,25 +400,23 @@ el_wgetc(EditLine *el, wchar_t *cp)
return 1;
}
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Turning raw mode on\n");
#endif /* DEBUG_READ */
if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
return 0;
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Reading a character\n");
#endif /* DEBUG_READ */
num_read = (*el->el_read.read_char)(el, cp);
num_read = (*el->el_read->read_char)(el, cp);
/*
* Remember the original reason of a read failure
* such that el_wgets() can restore it after doing
* various cleanup operation that might change errno.
*/
if (num_read < 0)
el->el_errno = errno;
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile, "Got it %lc\n", *cp);
#endif /* DEBUG_READ */
el->el_read->read_errno = errno;
return num_read;
}
protected void
libedit_private void
read_prepare(EditLine *el)
{
if (el->el_flags & HANDLE_SIGNALS)
@ -458,14 +430,14 @@ read_prepare(EditLine *el)
we have the wrong size. */
el_resize(el);
re_clear_display(el); /* reset the display stuff */
ch_reset(el, 0);
ch_reset(el);
re_refresh(el); /* print the prompt */
if (el->el_flags & UNBUFFERED)
terminal__flush(el);
}
protected void
libedit_private void
read_finish(EditLine *el)
{
if ((el->el_flags & UNBUFFERED) == 0)
@ -474,56 +446,52 @@ read_finish(EditLine *el)
sig_clr(el);
}
public const Char *
FUN(el,gets)(EditLine *el, int *nread)
static const wchar_t *
noedit_wgets(EditLine *el, int *nread)
{
el_line_t *lp = &el->el_line;
int num;
while ((num = (*el->el_read->read_char)(el, lp->lastchar)) == 1) {
if (lp->lastchar + 1 >= lp->limit &&
!ch_enlargebufs(el, (size_t)2))
break;
lp->lastchar++;
if (el->el_flags & UNBUFFERED ||
lp->lastchar[-1] == '\r' ||
lp->lastchar[-1] == '\n')
break;
}
if (num == -1 && errno == EINTR)
lp->lastchar = lp->buffer;
lp->cursor = lp->lastchar;
*lp->lastchar = '\0';
*nread = (int)(lp->lastchar - lp->buffer);
return *nread ? lp->buffer : NULL;
}
const wchar_t *
el_wgets(EditLine *el, int *nread)
{
int retval;
el_action_t cmdnum = 0;
int num; /* how many chars we have read at NL */
wchar_t wc;
Char ch, *cp;
int crlf = 0;
wchar_t ch;
int nrb;
#ifdef FIONREAD
c_macro_t *ma = &el->el_chared.c_macro;
#endif /* FIONREAD */
if (nread == NULL)
nread = &nrb;
*nread = 0;
el->el_read->read_errno = 0;
if (el->el_flags & NO_TTY) {
size_t idx;
cp = el->el_line.buffer;
while ((num = (*el->el_read.read_char)(el, &wc)) == 1) {
*cp = (Char)wc;
/* make sure there is space for next character */
if (cp + 1 >= el->el_line.limit) {
idx = (size_t)(cp - el->el_line.buffer);
if (!ch_enlargebufs(el, (size_t)2))
break;
cp = &el->el_line.buffer[idx];
}
cp++;
if (el->el_flags & UNBUFFERED)
break;
if (cp[-1] == '\r' || cp[-1] == '\n')
break;
}
if (num == -1) {
if (errno == EINTR)
cp = el->el_line.buffer;
el->el_errno = errno;
}
goto noedit;
el->el_line.lastchar = el->el_line.buffer;
return noedit_wgets(el, nread);
}
#ifdef FIONREAD
if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
long chrs = 0;
if (el->el_tty.t_mode == EX_IO && el->el_read->macros.level < 0) {
int chrs = 0;
(void) ioctl(el->el_infd, FIONREAD, &chrs);
if (chrs == 0) {
@ -540,83 +508,19 @@ FUN(el,gets)(EditLine *el, int *nread)
read_prepare(el);
if (el->el_flags & EDIT_DISABLED) {
size_t idx;
if ((el->el_flags & UNBUFFERED) == 0)
cp = el->el_line.buffer;
else
cp = el->el_line.lastchar;
el->el_line.lastchar = el->el_line.buffer;
terminal__flush(el);
while ((num = (*el->el_read.read_char)(el, &wc)) == 1) {
*cp = (Char)wc;
/* make sure there is space next character */
if (cp + 1 >= el->el_line.limit) {
idx = (size_t)(cp - el->el_line.buffer);
if (!ch_enlargebufs(el, (size_t)2))
break;
cp = &el->el_line.buffer[idx];
}
cp++;
crlf = cp[-1] == '\r' || cp[-1] == '\n';
if (el->el_flags & UNBUFFERED)
break;
if (crlf)
break;
}
if (num == -1) {
if (errno == EINTR)
cp = el->el_line.buffer;
el->el_errno = errno;
}
goto noedit;
return noedit_wgets(el, nread);
}
for (num = OKCMD; num == OKCMD;) { /* while still editing this
* line */
#ifdef DEBUG_EDIT
read_debug(el);
#endif /* DEBUG_EDIT */
for (num = -1; num == -1;) { /* while still editing this line */
/* if EOF or error */
if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
num = -1;
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile,
"Returning from el_gets %d\n", num);
#endif /* DEBUG_READ */
if (read_getcmd(el, &cmdnum, &ch) == -1)
break;
}
if (el->el_errno == EINTR) {
el->el_line.buffer[0] = '\0';
el->el_line.lastchar =
el->el_line.cursor = el->el_line.buffer;
break;
}
if ((size_t)cmdnum >= el->el_map.nfunc) { /* BUG CHECK command */
#ifdef DEBUG_EDIT
(void) fprintf(el->el_errfile,
"ERROR: illegal command from key 0%o\r\n", ch);
#endif /* DEBUG_EDIT */
if ((size_t)cmdnum >= el->el_map.nfunc) /* BUG CHECK command */
continue; /* try again */
}
/* now do the real command */
#ifdef DEBUG_READ
{
el_bindings_t *b;
for (b = el->el_map.help; b->name; b++)
if (b->func == cmdnum)
break;
if (b->name)
(void) fprintf(el->el_errfile,
"Executing " FSTR "\n", b->name);
else
(void) fprintf(el->el_errfile,
"Error command = %d\n", cmdnum);
}
#endif /* DEBUG_READ */
/* vi redo needs these way down the levels... */
el->el_state.thiscmd = cmdnum;
el->el_state.thisch = ch;
@ -625,16 +529,12 @@ FUN(el,gets)(EditLine *el, int *nread)
el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
if (cmdnum == VI_DELETE_PREV_CHAR &&
el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
&& Isprint(el->el_chared.c_redo.pos[-1]))
&& iswprint(el->el_chared.c_redo.pos[-1]))
el->el_chared.c_redo.pos--;
else
*el->el_chared.c_redo.pos++ = ch;
}
retval = (*el->el_map.func[cmdnum]) (el, ch);
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile,
"Returned state %d\n", retval );
#endif /* DEBUG_READ */
/* save the last command here */
el->el_state.lastcmd = cmdnum;
@ -681,22 +581,15 @@ FUN(el,gets)(EditLine *el, int *nread)
break;
case CC_FATAL: /* fatal error, reset to known state */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile,
"*** editor fatal ERROR ***\r\n\n");
#endif /* DEBUG_READ */
/* put (real) cursor in a known place */
re_clear_display(el); /* reset the display stuff */
ch_reset(el, 1); /* reset the input pointers */
ch_reset(el); /* reset the input pointers */
read_clearmacros(&el->el_read->macros);
re_refresh(el); /* print the prompt again */
break;
case CC_ERROR:
default: /* functions we don't know about */
#ifdef DEBUG_READ
(void) fprintf(el->el_errfile,
"*** editor ERROR ***\r\n\n");
#endif /* DEBUG_READ */
terminal_beep(el);
terminal__flush(el);
break;
@ -713,19 +606,14 @@ FUN(el,gets)(EditLine *el, int *nread)
if ((el->el_flags & UNBUFFERED) == 0) {
read_finish(el);
*nread = num != -1 ? num : 0;
} else {
} else
*nread = (int)(el->el_line.lastchar - el->el_line.buffer);
}
goto done;
noedit:
el->el_line.cursor = el->el_line.lastchar = cp;
*cp = '\0';
*nread = (int)(el->el_line.cursor - el->el_line.buffer);
done:
if (*nread == 0) {
if (num == -1) {
*nread = -1;
errno = el->el_errno;
if (el->el_read->read_errno)
errno = el->el_read->read_errno;
}
return NULL;
} else

View file

@ -1,4 +1,4 @@
/* $NetBSD: read.h,v 1.9 2016/02/24 17:13:22 christos Exp $ */
/* $NetBSD: read.h,v 1.12 2016/05/22 19:44:26 christos Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -27,8 +27,6 @@
* 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.
*
* $FreeBSD$
*/
/*
@ -37,16 +35,11 @@
#ifndef _h_el_read
#define _h_el_read
typedef int (*el_rfunc_t)(EditLine *, wchar_t *);
typedef struct el_read_t {
el_rfunc_t read_char; /* Function to read a character */
} el_read_t;
protected int read_init(EditLine *);
protected void read_prepare(EditLine *);
protected void read_finish(EditLine *);
protected int el_read_setfn(EditLine *, el_rfunc_t);
protected el_rfunc_t el_read_getfn(EditLine *);
libedit_private int read_init(EditLine *);
libedit_private void read_end(struct el_read_t *);
libedit_private void read_prepare(EditLine *);
libedit_private void read_finish(EditLine *);
libedit_private int el_read_setfn(struct el_read_t *, el_rfunc_t);
libedit_private el_rfunc_t el_read_getfn(struct el_read_t *);
#endif /* _h_el_read */

View file

@ -1,4 +1,4 @@
/* $NetBSD: readline.c,v 1.126 2016/02/24 17:13:22 christos Exp $ */
/* $NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 christos Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -31,10 +31,8 @@
#include "config.h"
#if !defined(lint) && !defined(SCCSID)
__RCSID("$NetBSD: readline.c,v 1.126 2016/02/24 17:13:22 christos Exp $");
__RCSID("$NetBSD: readline.c,v 1.157 2019/08/21 11:11:48 christos Exp $");
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/stat.h>
@ -54,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include "readline/readline.h"
#include "el.h"
#include "fcns.h"
#include "filecomplete.h"
void rl_prep_terminal(int);
@ -73,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;
@ -81,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;
@ -96,6 +95,7 @@ int rl_catch_sigwinch = 1;
int history_base = 1; /* probably never subject to change */
int history_length = 0;
int history_offset = 0;
int max_input_history = 0;
char history_expansion_char = '!';
char history_subst_char = '^';
@ -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;
@ -122,6 +122,7 @@ int readline_echoing_p = 1;
int _rl_print_completions_horizontally = 0;
VFunction *rl_redisplay_function = NULL;
Function *rl_startup_hook = NULL;
int rl_did_startup_hook = 0;
VFunction *rl_completion_display_matches_hook = NULL;
VFunction *rl_prep_term_function = (VFunction *)rl_prep_terminal;
VFunction *rl_deprep_term_function = (VFunction *)rl_deprep_terminal;
@ -149,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
@ -169,7 +170,6 @@ static unsigned char _el_rl_complete(EditLine *, int);
static unsigned char _el_rl_tstp(EditLine *, int);
static char *_get_prompt(EditLine *);
static int _getc_function(EditLine *, wchar_t *);
static HIST_ENTRY *_move_history(int);
static int _history_expand_command(const char *, size_t, size_t,
char **);
static char *_rl_compat_sub(const char *, const char *,
@ -177,6 +177,7 @@ static char *_rl_compat_sub(const char *, const char *,
static int _rl_event_read_char(EditLine *, wchar_t *);
static void _rl_update_pos(void);
static HIST_ENTRY rl_he;
/* ARGSUSED */
static char *
@ -187,25 +188,6 @@ _get_prompt(EditLine *el __attribute__((__unused__)))
}
/*
* generic function for moving around history
*/
static HIST_ENTRY *
_move_history(int op)
{
HistEvent ev;
static HIST_ENTRY rl_he;
if (history(h, &ev, op) != 0)
return NULL;
rl_he.line = ev.str;
rl_he.data = NULL;
return &rl_he;
}
/*
* read one key from user defined input function
*/
@ -215,7 +197,7 @@ _getc_function(EditLine *el __attribute__((__unused__)), wchar_t *c)
{
int i;
i = (*rl_getc_function)(NULL);
i = (*rl_getc_function)(rl_instream);
if (i == -1)
return 0;
*c = (wchar_t)i;
@ -276,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;
}
@ -308,7 +296,9 @@ rl_initialize(void)
if (tcgetattr(fileno(rl_instream), &t) != -1 && (t.c_lflag & ECHO) == 0)
editmode = 0;
e = el_init(rl_readline_name, rl_instream, rl_outstream, stderr);
e = el_init_internal(rl_readline_name, rl_instream, rl_outstream,
stderr, fileno(rl_instream), fileno(rl_outstream), fileno(stderr),
NO_RESET);
if (!editmode)
el_set(e, EL_EDITMODE, 0);
@ -335,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 */
@ -404,8 +394,7 @@ rl_initialize(void)
_resize_fun(e, &rl_line_buffer);
_rl_update_pos();
if (rl_startup_hook)
(*rl_startup_hook)(NULL, 0);
tty_end(e, TCSADRAIN);
return 0;
}
@ -427,19 +416,26 @@ readline(const char *p)
if (e == NULL || h == NULL)
rl_initialize();
if (rl_did_startup_hook == 0 && rl_startup_hook) {
rl_did_startup_hook = 1;
(*rl_startup_hook)(NULL, 0);
}
tty_init(e);
rl_done = 0;
(void)setjmp(topbuf);
buf = NULL;
/* update prompt accordingly to what has been passed */
if (rl_set_prompt(prompt) == -1)
return NULL;
goto out;
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;
}
@ -459,7 +455,7 @@ readline(const char *p)
buf = strdup(ret);
if (buf == NULL)
return NULL;
goto out;
lastidx = count - 1;
if (buf[lastidx] == '\n')
buf[lastidx] = '\0';
@ -469,6 +465,8 @@ readline(const char *p)
history(h, &ev, H_GETSIZE);
history_length = ev.num;
out:
tty_end(e, TCSADRAIN);
return buf;
}
@ -485,6 +483,7 @@ using_history(void)
{
if (h == NULL || e == NULL)
rl_initialize();
history_offset = history_length;
}
@ -516,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;
@ -566,7 +565,7 @@ get_history_event(const char *cmd, int *cindex, int qchar)
}
if ('0' <= cmd[idx] && cmd[idx] <= '9') {
HIST_ENTRY *rl_he;
HIST_ENTRY *he;
num = 0;
while (cmd[idx] && '0' <= cmd[idx] && cmd[idx] <= '9') {
@ -574,13 +573,13 @@ get_history_event(const char *cmd, int *cindex, int qchar)
idx++;
}
if (sign)
num = history_length - num + 1;
num = history_length - num + history_base;
if (!(rl_he = history_get(num)))
if (!(he = history_get(num)))
return NULL;
*cindex = idx;
return rl_he->line;
return he->line;
}
sub = 0;
if (cmd[idx] == '?') {
@ -606,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';
@ -700,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);
@ -934,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;
@ -1082,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;
@ -1144,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]);
@ -1169,12 +1168,22 @@ void
stifle_history(int max)
{
HistEvent ev;
HIST_ENTRY *he;
if (h == NULL || e == NULL)
rl_initialize();
if (history(h, &ev, H_SETSIZE, max) == 0)
if (history(h, &ev, H_SETSIZE, max) == 0) {
max_input_history = max;
if (history_length > max)
history_base = history_length - max;
while (history_length > max) {
he = remove_history(0);
el_free(he->data);
el_free((void *)(unsigned long)he->line);
el_free(he);
}
}
}
@ -1352,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;
}
@ -1373,6 +1388,28 @@ write_history(const char *filename)
(errno ? errno : EINVAL) : 0;
}
int
append_history(int n, const char *filename)
{
HistEvent ev;
FILE *fp;
if (h == NULL || e == NULL)
rl_initialize();
if (filename == NULL && (filename = _default_history_file()) == NULL)
return errno;
if ((fp = fopen(filename, "a")) == NULL)
return errno;
if (history(h, &ev, H_NSAVE_FP, (size_t)n, fp) == -1) {
int serrno = errno ? errno : EINVAL;
fclose(fp);
return serrno;
}
fclose(fp);
return 0;
}
/*
* returns history ``num''th event
@ -1389,25 +1426,37 @@ history_get(int num)
if (h == NULL || e == NULL)
rl_initialize();
if (num < history_base)
return NULL;
/* save current position */
if (history(h, &ev, H_CURR) != 0)
return NULL;
curr_num = ev.num;
/* start from the oldest */
if (history(h, &ev, H_LAST) != 0)
return NULL; /* error */
/* look forwards for event matching specified offset */
if (history(h, &ev, H_NEXT_EVDATA, num, &she.data))
return NULL;
/*
* use H_DELDATA to set to nth history (without delete) by passing
* (void **)-1 -- as in history_set_pos
*/
if (history(h, &ev, H_DELDATA, num - history_base, (void **)-1) != 0)
goto out;
/* get current entry */
if (history(h, &ev, H_CURR) != 0)
goto out;
if (history(h, &ev, H_NEXT_EVDATA, ev.num, &she.data) != 0)
goto out;
she.line = ev.str;
/* restore pointer to where it was */
(void)history(h, &ev, H_SET, curr_num);
return &she;
out:
/* restore pointer to where it was */
(void)history(h, &ev, H_SET, curr_num);
return NULL;
}
@ -1419,17 +1468,20 @@ add_history(const char *line)
{
HistEvent ev;
if (line == NULL)
return 0;
if (h == NULL || e == NULL)
rl_initialize();
(void)history(h, &ev, H_ENTER, line);
if (history(h, &ev, H_GETSIZE) == 0)
history_length = ev.num;
if (history(h, &ev, H_ENTER, line) == -1)
return 0;
return !(history_length > 0); /* return 0 if all is okay */
(void)history(h, &ev, H_GETSIZE);
if (ev.num == history_length)
history_base++;
else {
history_offset++;
history_length = ev.num;
}
return 0;
}
@ -1519,7 +1571,7 @@ clear_history(void)
rl_initialize();
(void)history(h, &ev, H_CLEAR);
history_length = 0;
history_offset = history_length = 0;
}
@ -1529,21 +1581,43 @@ clear_history(void)
int
where_history(void)
{
HistEvent ev;
int curr_num, off;
if (history(h, &ev, H_CURR) != 0)
return 0;
curr_num = ev.num;
(void)history(h, &ev, H_FIRST);
off = 1;
while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0)
off++;
return off;
return history_offset;
}
static HIST_ENTRY **_history_listp;
static HIST_ENTRY *_history_list;
HIST_ENTRY **
history_list(void)
{
HistEvent ev;
HIST_ENTRY **nlp, *nl;
int i;
if (history(h, &ev, H_LAST) != 0)
return NULL;
if ((nlp = el_realloc(_history_listp,
((size_t)history_length + 1) * sizeof(*nlp))) == NULL)
return NULL;
_history_listp = nlp;
if ((nl = el_realloc(_history_list,
(size_t)history_length * sizeof(*nl))) == NULL)
return NULL;
_history_list = nl;
i = 0;
do {
_history_listp[i] = &_history_list[i];
_history_list[i].line = ev.str;
_history_list[i].data = NULL;
if (i++ == history_length)
abort();
} while (history(h, &ev, H_PREV) == 0);
_history_listp[i] = NULL;
return _history_listp;
}
/*
* returns current history event or NULL if there is no such event
@ -1551,8 +1625,14 @@ where_history(void)
HIST_ENTRY *
current_history(void)
{
HistEvent ev;
return _move_history(H_CURR);
if (history(h, &ev, H_PREV_EVENT, history_offset + 1) != 0)
return NULL;
rl_he.line = ev.str;
rl_he.data = NULL;
return &rl_he;
}
@ -1589,35 +1669,31 @@ history_total_bytes(void)
int
history_set_pos(int pos)
{
HistEvent ev;
int curr_num;
if (pos >= history_length || pos < 0)
return -1;
return 0;
(void)history(h, &ev, H_CURR);
curr_num = ev.num;
/*
* use H_DELDATA to set to nth history (without delete) by passing
* (void **)-1
*/
if (history(h, &ev, H_DELDATA, pos, (void **)-1)) {
(void)history(h, &ev, H_SET, curr_num);
return -1;
}
return 0;
history_offset = pos;
return 1;
}
/*
* returns previous event in history and shifts pointer accordingly
* Note that readline and editline define directions in opposite ways.
*/
HIST_ENTRY *
previous_history(void)
{
HistEvent ev;
return _move_history(H_PREV);
if (history_offset == 0)
return NULL;
if (history(h, &ev, H_LAST) != 0)
return NULL;
history_offset--;
return current_history();
}
@ -1627,8 +1703,16 @@ previous_history(void)
HIST_ENTRY *
next_history(void)
{
HistEvent ev;
return _move_history(H_NEXT);
if (history_offset >= history_length)
return NULL;
if (history(h, &ev, H_LAST) != 0)
return NULL;
history_offset++;
return current_history();
}
@ -1689,7 +1773,7 @@ history_search_pos(const char *str,
return -1;
curr_num = ev.num;
if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0)
if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0)
return -1;
for (;;) {
@ -1776,18 +1860,6 @@ _el_rl_tstp(EditLine *el __attribute__((__unused__)), int ch __attribute__((__un
return CC_NORM;
}
/*
* Display list of strings in columnar format on readline's output stream.
* 'matches' is list of strings, 'len' is number of strings in 'matches',
* 'max' is maximum length of string in 'matches'.
*/
void
rl_display_match_list(char **matches, int len, int max)
{
fn_display_match_list(e, matches, (size_t)len, (size_t)max);
}
static const char *
/*ARGSUSED*/
_rl_completion_append_character_function(const char *dummy
@ -1800,6 +1872,19 @@ _rl_completion_append_character_function(const char *dummy
}
/*
* Display list of strings in columnar format on readline's output stream.
* 'matches' is list of strings, 'len' is number of strings in 'matches',
* 'max' is maximum length of string in 'matches'.
*/
void
rl_display_match_list(char **matches, int len, int max)
{
fn_display_match_list(e, matches, (size_t)len, (size_t)max,
_rl_completion_append_character_function);
}
/*
* complete word at current point
*/
@ -1807,10 +1892,8 @@ _rl_completion_append_character_function(const char *dummy
int
rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
{
#ifdef WIDECHAR
static ct_buffer_t wbreak_conv, sprefix_conv;
#endif
char *breakchars;
const char *breakchars;
if (h == NULL || e == NULL)
rl_initialize();
@ -1839,7 +1922,7 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key)
_rl_completion_append_character_function,
(size_t)rl_completion_query_items,
&rl_completion_type, &rl_attempted_completion_over,
&rl_point, &rl_end, NULL, NULL, NULL);
&rl_point, &rl_end);
}
@ -1896,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;
}
@ -2000,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);
@ -2023,8 +2107,9 @@ rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc)
void
rl_callback_handler_remove(void)
{
el_set(e, EL_UNBUFFERED, 0);
rl_linefunc = NULL;
el_end(e);
e = NULL;
}
void
@ -2090,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];
@ -2098,6 +2183,7 @@ rl_stuff_char(int c)
buf[0] = (char)c;
buf[1] = '\0';
el_insertstr(e, buf);
return 1;
}
static int
@ -2153,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
@ -2182,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) {
@ -2217,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';
@ -2334,3 +2421,25 @@ rl_set_keyboard_input_timeout(int u __attribute__((__unused__)))
{
return 0;
}
void
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);
}

View file

@ -0,0 +1,13 @@
# $NetBSD: Makefile,v 1.8 2016/02/17 19:47:49 christos Exp $
NOOBJ= # defined
.include <bsd.own.mk>
.PATH: ${NETBSDSRCDIR}/lib/libedit
INCS= readline.h
INCSDIR= /usr/include/readline
INCSYMLINKS= readline.h ${INCSDIR}/history.h
.include <bsd.prog.mk>

View file

@ -1,4 +1,4 @@
/* $NetBSD: readline.h,v 1.39 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: readline.h,v 1.46 2019/06/07 15:19:29 christos Exp $ */
/*-
* Copyright (c) 1997 The NetBSD Foundation, Inc.
@ -27,8 +27,6 @@
* 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.
*
* $FreeBSD$
*/
#ifndef _READLINE_H_
#define _READLINE_H_
@ -40,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 {
@ -99,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;
@ -123,6 +123,7 @@ extern Function *rl_startup_hook;
extern char *rl_terminal_name;
extern int rl_already_prompted;
extern char *rl_prompt;
extern int rl_done;
/*
* The following is not implemented
*/
@ -138,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;
@ -148,6 +150,7 @@ int rl_initialize(void);
void using_history(void);
int add_history(const char *);
void clear_history(void);
int append_history(int, const char *);
void stifle_history(int);
int unstifle_history(void);
int history_is_stifled(void);
@ -160,6 +163,7 @@ int history_total_bytes(void);
int history_set_pos(int);
HIST_ENTRY *previous_history(void);
HIST_ENTRY *next_history(void);
HIST_ENTRY **history_list(void);
int history_search(const char *, int);
int history_search_prefix(const char *, int);
int history_search_pos(const char *, int, int);
@ -176,12 +180,13 @@ 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);
void rl_callback_read_char(void);
@ -194,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 *);
@ -206,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

View file

@ -1,4 +1,4 @@
/* $NetBSD: refresh.c,v 1.45 2016/03/02 19:24:20 christos Exp $ */
/* $NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: refresh.c,v 1.45 2016/03/02 19:24:20 christos Exp $");
__RCSID("$NetBSD: refresh.c,v 1.56 2019/01/04 03:03:44 uwe Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* refresh.c: Lower level screen refreshing functions
@ -52,18 +50,18 @@ __FBSDID("$FreeBSD$");
#include "el.h"
private void re_nextline(EditLine *);
private void re_addc(EditLine *, wint_t);
private void re_update_line(EditLine *, Char *, Char *, int);
private void re_insert (EditLine *, Char *, int, int, Char *, int);
private void re_delete(EditLine *, Char *, int, int, int);
private void re_fastputc(EditLine *, wint_t);
private void re_clear_eol(EditLine *, int, int, int);
private void re__strncopy(Char *, Char *, size_t);
private void re__copy_and_pad(Char *, const Char *, size_t);
static void re_nextline(EditLine *);
static void re_addc(EditLine *, wint_t);
static void re_update_line(EditLine *, wchar_t *, wchar_t *, int);
static void re_insert (EditLine *, wchar_t *, int, int, wchar_t *, int);
static void re_delete(EditLine *, wchar_t *, int, int, int);
static void re_fastputc(EditLine *, wint_t);
static void re_clear_eol(EditLine *, int, int, int);
static void re__strncopy(wchar_t *, wchar_t *, size_t);
static void re__copy_and_pad(wchar_t *, const wchar_t *, size_t);
#ifdef DEBUG_REFRESH
private void re_printstr(EditLine *, const char *, Char *, Char *);
static void re_printstr(EditLine *, const char *, wchar_t *, wchar_t *);
#define __F el->el_errfile
#define ELRE_ASSERT(a, b, c) do \
if (/*CONSTCOND*/ a) { \
@ -76,8 +74,8 @@ private void re_printstr(EditLine *, const char *, Char *, Char *);
/* re_printstr():
* Print a string on the debugging pty
*/
private void
re_printstr(EditLine *el, const char *str, Char *f, Char *t)
static void
re_printstr(EditLine *el, const char *str, wchar_t *f, wchar_t *t)
{
ELRE_DEBUG(1, (__F, "%s:\"", str));
@ -93,7 +91,7 @@ re_printstr(EditLine *el, const char *str, Char *f, Char *t)
/* re_nextline():
* Move to the next line or scroll
*/
private void
static void
re_nextline(EditLine *el)
{
el->el_refresh.r_cursor.h = 0; /* reset it. */
@ -106,7 +104,7 @@ re_nextline(EditLine *el)
*/
if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) {
int i, lins = el->el_terminal.t_size.v;
Char *firstline = el->el_vdisplay[0];
wchar_t *firstline = el->el_vdisplay[0];
for(i = 1; i < lins; i++)
el->el_vdisplay[i - 1] = el->el_vdisplay[i];
@ -125,10 +123,10 @@ re_nextline(EditLine *el)
/* re_addc():
* Draw c, expanding tabs, control chars etc.
*/
private void
static void
re_addc(EditLine *el, wint_t c)
{
switch (ct_chr_class((Char)c)) {
switch (ct_chr_class(c)) {
case CHTYPE_TAB: /* expand the tab */
for (;;) {
re_putc(el, ' ', 1);
@ -147,9 +145,9 @@ re_addc(EditLine *el, wint_t c)
re_putc(el, c, 1);
break;
default: {
Char visbuf[VISUAL_WIDTH_MAX];
wchar_t visbuf[VISUAL_WIDTH_MAX];
ssize_t i, n =
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
for (i = 0; n-- > 0; ++i)
re_putc(el, visbuf[i], 1);
break;
@ -157,35 +155,66 @@ re_addc(EditLine *el, wint_t c)
}
}
/* re_putliteral():
* Place the literal string given
*/
libedit_private void
re_putliteral(EditLine *el, const wchar_t *begin, const wchar_t *end)
{
coord_t *cur = &el->el_refresh.r_cursor;
wint_t c;
int sizeh = el->el_terminal.t_size.h;
int i, w;
c = literal_add(el, begin, end, &w);
if (c == 0 || w <= 0)
return;
el->el_vdisplay[cur->v][cur->h] = c;
i = w;
if (i > sizeh - cur->h) /* avoid overflow */
i = sizeh - cur->h;
while (--i > 0)
el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
cur->h += w;
if (cur->h >= sizeh) {
/* assure end of line */
el->el_vdisplay[cur->v][sizeh] = '\0';
re_nextline(el);
}
}
/* re_putc():
* Draw the character given
*/
protected void
libedit_private void
re_putc(EditLine *el, wint_t c, int shift)
{
int i, w = Width(c);
ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c));
coord_t *cur = &el->el_refresh.r_cursor;
int i, w = wcwidth(c);
int sizeh = el->el_terminal.t_size.h;
while (shift && (el->el_refresh.r_cursor.h + w > el->el_terminal.t_size.h))
ELRE_DEBUG(1, (__F, "printing %5x '%lc'\r\n", c, c));
if (w == -1)
w = 0;
while (shift && (cur->h + w > sizeh))
re_putc(el, ' ', 1);
el->el_vdisplay[el->el_refresh.r_cursor.v]
[el->el_refresh.r_cursor.h] = (Char)c;
el->el_vdisplay[cur->v][cur->h] = c;
/* assumes !shift is only used for single-column chars */
i = w;
while (--i > 0)
el->el_vdisplay[el->el_refresh.r_cursor.v]
[el->el_refresh.r_cursor.h + i] = MB_FILL_CHAR;
el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR;
if (!shift)
return;
el->el_refresh.r_cursor.h += w; /* advance to next place */
if (el->el_refresh.r_cursor.h >= el->el_terminal.t_size.h) {
cur->h += w; /* advance to next place */
if (cur->h >= sizeh) {
/* assure end of line */
el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_terminal.t_size.h]
= '\0';
el->el_vdisplay[cur->v][sizeh] = '\0';
re_nextline(el);
}
}
@ -197,23 +226,26 @@ re_putc(EditLine *el, wint_t c, int shift)
* virtual image. The routine to re-draw a line can be replaced
* easily in hopes of a smarter one being placed there.
*/
protected void
libedit_private void
re_refresh(EditLine *el)
{
int i, rhdiff;
Char *cp, *st;
wchar_t *cp, *st;
coord_t cur;
#ifdef notyet
size_t termsz;
#endif
ELRE_DEBUG(1, (__F, "el->el_line.buffer = :" FSTR ":\r\n",
ELRE_DEBUG(1, (__F, "el->el_line.buffer = :%ls:\r\n",
el->el_line.buffer));
literal_clear(el);
/* reset the Drawing cursor */
el->el_refresh.r_cursor.h = 0;
el->el_refresh.r_cursor.v = 0;
terminal_move_to_char(el, 0);
/* temporarily draw rprompt to calculate its size */
prompt_print(el, EL_RPROMPT);
@ -253,7 +285,7 @@ re_refresh(EditLine *el)
for (cp = st; cp < el->el_line.lastchar; cp++) {
if (cp == el->el_line.cursor) {
int w = Width(*cp);
int w = wcwidth(*cp);
/* save for later */
cur.h = el->el_refresh.r_cursor.h;
cur.v = el->el_refresh.r_cursor.v;
@ -321,10 +353,10 @@ re_refresh(EditLine *el)
for (; i <= el->el_refresh.r_oldcv; i++) {
terminal_move_to_line(el, i);
terminal_move_to_char(el, 0);
/* This Strlen should be safe even with MB_FILL_CHARs */
terminal_clear_EOL(el, (int) Strlen(el->el_display[i]));
/* This wcslen should be safe even with MB_FILL_CHARs */
terminal_clear_EOL(el, (int) wcslen(el->el_display[i]));
#ifdef DEBUG_REFRESH
terminal_overwrite(el, STR("C\b"), 2);
terminal_overwrite(el, L"C\b", 2);
#endif /* DEBUG_REFRESH */
el->el_display[i][0] = '\0';
}
@ -342,7 +374,7 @@ re_refresh(EditLine *el)
/* re_goto_bottom():
* used to go to last used screen line
*/
protected void
libedit_private void
re_goto_bottom(EditLine *el)
{
@ -357,12 +389,12 @@ re_goto_bottom(EditLine *el)
* insert num characters of s into d (in front of the character)
* at dat, maximum length of d is dlen
*/
private void
static void
/*ARGSUSED*/
re_insert(EditLine *el __attribute__((__unused__)),
Char *d, int dat, int dlen, Char *s, int num)
wchar_t *d, int dat, int dlen, wchar_t *s, int num)
{
Char *a, *b;
wchar_t *a, *b;
if (num <= 0)
return;
@ -408,12 +440,12 @@ re_insert(EditLine *el __attribute__((__unused__)),
/* re_delete():
* delete num characters d at dat, maximum length of d is dlen
*/
private void
static void
/*ARGSUSED*/
re_delete(EditLine *el __attribute__((__unused__)),
Char *d, int dat, int dlen, int num)
wchar_t *d, int dat, int dlen, int num)
{
Char *a, *b;
wchar_t *a, *b;
if (num <= 0)
return;
@ -442,8 +474,8 @@ re_delete(EditLine *el __attribute__((__unused__)),
/* re__strncopy():
* Like strncpy without padding.
*/
private void
re__strncopy(Char *a, Char *b, size_t n)
static void
re__strncopy(wchar_t *a, wchar_t *b, size_t n)
{
while (n-- && *b)
@ -457,7 +489,7 @@ re__strncopy(Char *a, Char *b, size_t n)
* in the first or second diff, diff is the difference between the
* number of characters between the new and old line.
*/
private void
static void
re_clear_eol(EditLine *el, int fx, int sx, int diff)
{
@ -501,12 +533,12 @@ new: eddie> Oh, my little buggy says to me, as lurgid as
*/
#define MIN_END_KEEP 4
private void
re_update_line(EditLine *el, Char *old, Char *new, int i)
static void
re_update_line(EditLine *el, wchar_t *old, wchar_t *new, int i)
{
Char *o, *n, *p, c;
Char *ofd, *ols, *oe, *nfd, *nls, *ne;
Char *osb, *ose, *nsb, *nse;
wchar_t *o, *n, *p, c;
wchar_t *ofd, *ols, *oe, *nfd, *nls, *ne;
wchar_t *osb, *ose, *nsb, *nse;
int fx, sx;
size_t len;
@ -971,8 +1003,8 @@ re_update_line(EditLine *el, Char *old, Char *new, int i)
/* re__copy_and_pad():
* Copy string and pad with spaces
*/
private void
re__copy_and_pad(Char *dst, const Char *src, size_t width)
static void
re__copy_and_pad(wchar_t *dst, const wchar_t *src, size_t width)
{
size_t i;
@ -992,10 +1024,10 @@ re__copy_and_pad(Char *dst, const Char *src, size_t width)
/* re_refresh_cursor():
* Move to the new cursor position
*/
protected void
libedit_private void
re_refresh_cursor(EditLine *el)
{
Char *cp;
wchar_t *cp;
int h, v, th, w;
if (el->el_line.cursor >= el->el_line.lastchar) {
@ -1023,7 +1055,7 @@ re_refresh_cursor(EditLine *el)
continue;
break;
default:
w = Width(*cp);
w = wcwidth(*cp);
if (w > 1 && h + w > th) { /* won't fit on line */
h = 0;
v++;
@ -1039,7 +1071,7 @@ re_refresh_cursor(EditLine *el)
}
/* if we have a next character, and it's a doublewidth one, we need to
* check whether we need to linebreak for it to fit */
if (cp < el->el_line.lastchar && (w = Width(*cp)) > 1)
if (cp < el->el_line.lastchar && (w = wcwidth(*cp)) > 1)
if (h + w > th) {
h = 0;
v++;
@ -1055,15 +1087,18 @@ re_refresh_cursor(EditLine *el)
/* re_fastputc():
* Add a character fast.
*/
private void
static void
re_fastputc(EditLine *el, wint_t c)
{
int w = Width((Char)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, ' ');
terminal__putc(el, c);
el->el_display[el->el_cursor.v][el->el_cursor.h++] = (Char)c;
el->el_display[el->el_cursor.v][el->el_cursor.h++] = c;
while (--w > 0)
el->el_display[el->el_cursor.v][el->el_cursor.h++]
= MB_FILL_CHAR;
@ -1080,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;
Char *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, STR(""), (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, ' ');
@ -1108,10 +1144,10 @@ re_fastputc(EditLine *el, wint_t c)
* we added just one char, handle it fast.
* Assumes that screen cursor == real cursor
*/
protected void
libedit_private void
re_fastaddc(EditLine *el)
{
Char c;
wchar_t c;
int rhdiff;
c = el->el_line.cursor[-1];
@ -1135,9 +1171,9 @@ re_fastaddc(EditLine *el)
break;
case CHTYPE_ASCIICTL:
case CHTYPE_NONPRINT: {
Char visbuf[VISUAL_WIDTH_MAX];
wchar_t visbuf[VISUAL_WIDTH_MAX];
ssize_t i, n =
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
for (i = 0; n-- > 0; ++i)
re_fastputc(el, visbuf[i]);
break;
@ -1148,9 +1184,9 @@ re_fastaddc(EditLine *el)
/* re_clear_display():
* clear the screen buffers so that new prompt starts fresh.
* clear the screen buffers so that new new prompt starts fresh.
*/
protected void
libedit_private void
re_clear_display(EditLine *el)
{
int i;
@ -1166,7 +1202,7 @@ re_clear_display(EditLine *el)
/* re_clear_lines():
* Make sure all lines are *really* blank
*/
protected void
libedit_private void
re_clear_lines(EditLine *el)
{

View file

@ -1,4 +1,4 @@
/* $NetBSD: refresh.h,v 1.9 2016/02/16 15:53:48 christos Exp $ */
/* $NetBSD: refresh.h,v 1.11 2017/06/27 23:23:48 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)refresh.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -47,12 +46,14 @@ typedef struct {
int r_newcv;
} el_refresh_t;
protected void re_putc(EditLine *, wint_t, int);
protected void re_clear_lines(EditLine *);
protected void re_clear_display(EditLine *);
protected void re_refresh(EditLine *);
protected void re_refresh_cursor(EditLine *);
protected void re_fastaddc(EditLine *);
protected void re_goto_bottom(EditLine *);
libedit_private void re_putc(EditLine *, wint_t, int);
libedit_private void re_putliteral(EditLine *, const wchar_t *,
const wchar_t *);
libedit_private void re_clear_lines(EditLine *);
libedit_private void re_clear_display(EditLine *);
libedit_private void re_refresh(EditLine *);
libedit_private void re_refresh_cursor(EditLine *);
libedit_private void re_fastaddc(EditLine *);
libedit_private void re_goto_bottom(EditLine *);
#endif /* _h_el_refresh */

View file

@ -1,4 +1,4 @@
/* $NetBSD: search.c,v 1.39 2016/02/24 14:25:38 christos Exp $ */
/* $NetBSD: search.c,v 1.49 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: search.c,v 1.39 2016/02/24 14:25:38 christos Exp $");
__RCSID("$NetBSD: search.c,v 1.49 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* search.c: History and character search functions
@ -56,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "common.h"
#include "fcns.h"
/*
* Adjust cursor in vi mode to include the character under it
@ -67,17 +66,18 @@ __FBSDID("$FreeBSD$");
/* search_init():
* Initialize the search stuff
*/
protected int
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;
el->el_search.patbuf[0] = L'\0';
el->el_search.patlen = 0;
el->el_search.patdir = -1;
el->el_search.chacha = '\0';
el->el_search.chacha = L'\0';
el->el_search.chadir = CHAR_FWD;
el->el_search.chatflg = 0;
return 0;
@ -87,7 +87,7 @@ search_init(EditLine *el)
/* search_end():
* Initialize the search stuff
*/
protected void
libedit_private void
search_end(EditLine *el)
{
@ -100,7 +100,7 @@ search_end(EditLine *el)
/* regerror():
* Handle regular expression errors
*/
public void
void
/*ARGSUSED*/
regerror(const char *msg)
{
@ -111,12 +111,10 @@ regerror(const char *msg)
/* el_match():
* Return if string matches pattern
*/
protected int
el_match(const Char *str, const Char *pat)
libedit_private int
el_match(const wchar_t *str, const wchar_t *pat)
{
#ifdef WIDECHAR
static ct_buffer_t conv;
#endif
#if defined (REGEX)
regex_t re;
int rv;
@ -128,7 +126,7 @@ el_match(const Char *str, const Char *pat)
extern int re_exec(const char *);
#endif
if (Strstr(str, pat) != 0)
if (wcsstr(str, pat) != 0)
return 1;
#if defined(REGEX)
@ -160,8 +158,8 @@ el_match(const Char *str, const Char *pat)
/* c_hmatch():
* return True if the pattern matches the prefix
*/
protected int
c_hmatch(EditLine *el, const Char *str)
libedit_private int
c_hmatch(EditLine *el, const wchar_t *str)
{
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "match `%s' with `%s'\n",
@ -175,7 +173,7 @@ c_hmatch(EditLine *el, const Char *str)
/* c_setpat():
* Set the history seatch pattern
*/
protected void
libedit_private void
c_setpat(EditLine *el)
{
if (el->el_state.lastcmd != ED_SEARCH_PREV_HISTORY &&
@ -185,11 +183,11 @@ c_setpat(EditLine *el)
if (el->el_search.patlen >= EL_BUFSIZ)
el->el_search.patlen = EL_BUFSIZ - 1;
if (el->el_search.patlen != 0) {
(void) Strncpy(el->el_search.patbuf, el->el_line.buffer,
(void) wcsncpy(el->el_search.patbuf, el->el_line.buffer,
el->el_search.patlen);
el->el_search.patbuf[el->el_search.patlen] = '\0';
} else
el->el_search.patlen = Strlen(el->el_search.patbuf);
el->el_search.patlen = wcslen(el->el_search.patbuf);
}
#ifdef SDEBUG
(void) fprintf(el->el_errfile, "\neventno = %d\n",
@ -207,16 +205,14 @@ c_setpat(EditLine *el)
/* ce_inc_search():
* Emacs incremental search
*/
protected el_action_t
libedit_private el_action_t
ce_inc_search(EditLine *el, int dir)
{
static const Char STRfwd[] = {'f', 'w', 'd', '\0'},
STRbck[] = {'b', 'c', 'k', '\0'};
static Char pchar = ':';/* ':' = normal, '?' = failed */
static Char endcmd[2] = {'\0', '\0'};
Char *ocursor = el->el_line.cursor, oldpchar = pchar, ch;
const Char *cp;
wchar_t wch;
static const wchar_t STRfwd[] = L"fwd", STRbck[] = L"bck";
static wchar_t pchar = L':'; /* ':' = normal, '?' = failed */
static wchar_t endcmd[2] = {'\0', '\0'};
wchar_t *ocursor = el->el_line.cursor, oldpchar = pchar, ch;
const wchar_t *cp;
el_action_t ret = CC_NORM;
@ -255,11 +251,9 @@ ce_inc_search(EditLine *el, int dir)
*el->el_line.lastchar = '\0';
re_refresh(el);
if (el_wgetc(el, &wch) != 1)
if (el_wgetc(el, &ch) != 1)
return ed_end_of_file(el, 0);
ch = (Char)wch;
switch (el->el_map.current[(unsigned char) ch]) {
case ED_INSERT:
case ED_DIGIT:
@ -333,7 +327,7 @@ ce_inc_search(EditLine *el, int dir)
default: /* Terminate and execute cmd */
endcmd[0] = ch;
FUN(el,push)(el, endcmd);
el_wpush(el, endcmd);
/* FALLTHROUGH */
case 0033: /* ESC: Terminate */
@ -458,11 +452,11 @@ ce_inc_search(EditLine *el, int dir)
/* cv_search():
* Vi search.
*/
protected el_action_t
libedit_private el_action_t
cv_search(EditLine *el, int dir)
{
Char ch;
Char tmpbuf[EL_BUFSIZ];
wchar_t ch;
wchar_t tmpbuf[EL_BUFSIZ];
ssize_t tmplen;
#ifdef ANCHOR
@ -474,7 +468,7 @@ cv_search(EditLine *el, int dir)
el->el_search.patdir = dir;
tmplen = c_gets(el, &tmpbuf[LEN],
dir == ED_SEARCH_PREV_HISTORY ? STR("\n/") : STR("\n?") );
dir == ED_SEARCH_PREV_HISTORY ? L"\n/" : L"\n?" );
if (tmplen == -1)
return CC_REFRESH;
@ -493,11 +487,11 @@ cv_search(EditLine *el, int dir)
#ifdef ANCHOR
if (el->el_search.patbuf[0] != '.' &&
el->el_search.patbuf[0] != '*') {
(void) Strncpy(tmpbuf, el->el_search.patbuf,
(void) wcsncpy(tmpbuf, el->el_search.patbuf,
sizeof(tmpbuf) / sizeof(*tmpbuf) - 1);
el->el_search.patbuf[0] = '.';
el->el_search.patbuf[1] = '*';
(void) Strncpy(&el->el_search.patbuf[2], tmpbuf,
(void) wcsncpy(&el->el_search.patbuf[2], tmpbuf,
EL_BUFSIZ - 3);
el->el_search.patlen++;
el->el_search.patbuf[el->el_search.patlen++] = '.';
@ -511,7 +505,7 @@ cv_search(EditLine *el, int dir)
tmpbuf[tmplen++] = '*';
#endif
tmpbuf[tmplen] = '\0';
(void) Strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
(void) wcsncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1);
el->el_search.patlen = (size_t)tmplen;
}
el->el_state.lastcmd = (el_action_t) dir; /* avoid c_setpat */
@ -532,12 +526,12 @@ cv_search(EditLine *el, int dir)
/* ce_search_line():
* Look for a pattern inside a line
*/
protected el_action_t
libedit_private el_action_t
ce_search_line(EditLine *el, int dir)
{
Char *cp = el->el_line.cursor;
Char *pattern = el->el_search.patbuf;
Char oc, *ocp;
wchar_t *cp = el->el_line.cursor;
wchar_t *pattern = el->el_search.patbuf;
wchar_t oc, *ocp;
#ifdef ANCHOR
ocp = &pattern[1];
oc = *ocp;
@ -574,7 +568,7 @@ ce_search_line(EditLine *el, int dir)
/* cv_repeat_srch():
* Vi repeat search
*/
protected el_action_t
libedit_private el_action_t
cv_repeat_srch(EditLine *el, wint_t c)
{
@ -600,21 +594,23 @@ cv_repeat_srch(EditLine *el, wint_t c)
/* cv_csearch():
* Vi character search
*/
protected el_action_t
libedit_private el_action_t
cv_csearch(EditLine *el, int direction, wint_t ch, int count, int tflag)
{
Char *cp;
wchar_t *cp;
if (ch == 0)
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 */
el->el_search.chacha = (Char)ch;
el->el_search.chacha = ch;
el->el_search.chadir = direction;
el->el_search.chatflg = (char)tflag;

View file

@ -1,4 +1,4 @@
/* $NetBSD: search.h,v 1.12 2016/02/16 15:53:48 christos Exp $ */
/* $NetBSD: search.h,v 1.14 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)search.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -42,24 +41,24 @@
#define _h_el_search
typedef struct el_search_t {
Char *patbuf; /* The pattern buffer */
wchar_t *patbuf; /* The pattern buffer */
size_t patlen; /* Length of the pattern buffer */
int patdir; /* Direction of the last search */
int chadir; /* Character search direction */
Char chacha; /* Character we are looking for */
wchar_t chacha; /* Character we are looking for */
char chatflg; /* 0 if f, 1 if t */
} el_search_t;
protected int el_match(const Char *, const Char *);
protected int search_init(EditLine *);
protected void search_end(EditLine *);
protected int c_hmatch(EditLine *, const Char *);
protected void c_setpat(EditLine *);
protected el_action_t ce_inc_search(EditLine *, int);
protected el_action_t cv_search(EditLine *, int);
protected el_action_t ce_search_line(EditLine *, int);
protected el_action_t cv_repeat_srch(EditLine *, wint_t);
protected el_action_t cv_csearch(EditLine *, int, wint_t, int, int);
libedit_private int el_match(const wchar_t *, const wchar_t *);
libedit_private int search_init(EditLine *);
libedit_private void search_end(EditLine *);
libedit_private int c_hmatch(EditLine *, const wchar_t *);
libedit_private void c_setpat(EditLine *);
libedit_private el_action_t ce_inc_search(EditLine *, int);
libedit_private el_action_t cv_search(EditLine *, int);
libedit_private el_action_t ce_search_line(EditLine *, int);
libedit_private el_action_t cv_repeat_srch(EditLine *, wint_t);
libedit_private el_action_t cv_csearch(EditLine *, int, wint_t, int, int);
#endif /* _h_el_search */

View file

@ -0,0 +1,5 @@
# $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=1

View file

@ -1,4 +1,4 @@
/* $NetBSD: sig.c,v 1.24 2016/02/16 19:08:41 christos Exp $ */
/* $NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: sig.c,v 1.24 2016/02/16 19:08:41 christos Exp $");
__RCSID("$NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* sig.c: Signal handling stuff.
@ -54,23 +52,23 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "common.h"
private EditLine *sel = NULL;
static EditLine *sel = NULL;
private const int sighdl[] = {
static const int sighdl[] = {
#define _DO(a) (a),
ALLSIGS
#undef _DO
- 1
};
private void sig_handler(int);
static void sig_handler(int);
/* sig_handler():
* This is the handler called for all signals
* XXX: we cannot pass any data so we just store the old editline
* state in a private variable
*/
private void
static void
sig_handler(int signo)
{
int i, save_errno;
@ -117,7 +115,7 @@ sig_handler(int signo)
/* sig_init():
* Initialize all signal stuff
*/
protected int
libedit_private int
sig_init(EditLine *el)
{
size_t i;
@ -149,7 +147,7 @@ sig_init(EditLine *el)
/* sig_end():
* Clear all signal stuff
*/
protected void
libedit_private void
sig_end(EditLine *el)
{
@ -161,7 +159,7 @@ sig_end(EditLine *el)
/* sig_set():
* set all the signal handlers
*/
protected void
libedit_private void
sig_set(EditLine *el)
{
size_t i;
@ -188,7 +186,7 @@ sig_set(EditLine *el)
/* sig_clr():
* clear all the signal handlers
*/
protected void
libedit_private void
sig_clr(EditLine *el)
{
size_t i;

View file

@ -1,4 +1,4 @@
/* $NetBSD: sig.h,v 1.10 2016/02/16 15:53:48 christos Exp $ */
/* $NetBSD: sig.h,v 1.11 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)sig.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -63,9 +62,9 @@ typedef struct {
volatile sig_atomic_t sig_no;
} *el_signal_t;
protected void sig_end(EditLine*);
protected int sig_init(EditLine*);
protected void sig_set(EditLine*);
protected void sig_clr(EditLine*);
libedit_private void sig_end(EditLine*);
libedit_private int sig_init(EditLine*);
libedit_private void sig_set(EditLine*);
libedit_private void sig_clr(EditLine*);
#endif /* _h_el_sig */

View file

@ -1,4 +1,4 @@
/* $NetBSD: sys.h,v 1.23 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: sys.h,v 1.27 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)sys.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -59,18 +58,8 @@
# endif
#endif
#ifndef public
# define public /* Externally visible functions/variables */
#endif
#ifndef private
# define private static /* Always hidden internals */
#endif
#ifndef protected
# define protected /* Redefined from elsewhere to "static" */
/* When we want to hide everything */
#endif
/* If your compiler does not support this, define it to be empty. */
#define libedit_private __attribute__((__visibility__("hidden")))
#ifndef __arraycount
# define __arraycount(a) (sizeof(a) / sizeof(*(a)))
@ -112,11 +101,6 @@ typedef unsigned int u_int32_t;
#define REGEX /* Use POSIX.2 regular expression functions */
#undef REGEXP /* Use UNIX V8 regular expression functions */
#ifndef WIDECHAR
#define setlocale(c, l) /*LINTED*/NULL
#define nl_langinfo(i) ""
#endif
#if defined(__sun)
extern int tgetent(char *, const char *);
extern int tgetflag(char *);

View file

@ -1,4 +1,4 @@
/* $NetBSD: terminal.c,v 1.24 2016/03/22 01:38:17 christos Exp $ */
/* $NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95";
#else
__RCSID("$NetBSD: terminal.c,v 1.24 2016/03/22 01:38:17 christos Exp $");
__RCSID("$NetBSD: terminal.c,v 1.39 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* terminal.c: Editor/termcap-curses interface
@ -75,6 +73,7 @@ __FBSDID("$FreeBSD$");
#endif
#include "el.h"
#include "fcns.h"
/*
* IMPORTANT NOTE: these routines are allowed to look at the current screen
@ -90,7 +89,7 @@ __FBSDID("$FreeBSD$");
#define Str(a) el->el_terminal.t_str[a]
#define Val(a) el->el_terminal.t_val[a]
private const struct termcapstr {
static const struct termcapstr {
const char *name;
const char *long_name;
} tstr[] = {
@ -176,7 +175,7 @@ private const struct termcapstr {
{ NULL, NULL }
};
private const struct termcapval {
static const struct termcapval {
const char *name;
const char *long_name;
} tval[] = {
@ -201,27 +200,27 @@ private const struct termcapval {
};
/* do two or more of the attributes use me */
private void terminal_setflags(EditLine *);
private int terminal_rebuffer_display(EditLine *);
private void terminal_free_display(EditLine *);
private int terminal_alloc_display(EditLine *);
private void terminal_alloc(EditLine *, const struct termcapstr *,
static void terminal_setflags(EditLine *);
static int terminal_rebuffer_display(EditLine *);
static void terminal_free_display(EditLine *);
static int terminal_alloc_display(EditLine *);
static void terminal_alloc(EditLine *, const struct termcapstr *,
const char *);
private void terminal_init_arrow(EditLine *);
private void terminal_reset_arrow(EditLine *);
private int terminal_putc(int);
private void terminal_tputs(EditLine *, const char *, int);
static void terminal_init_arrow(EditLine *);
static void terminal_reset_arrow(EditLine *);
static int terminal_putc(int);
static void terminal_tputs(EditLine *, const char *, int);
#ifdef _REENTRANT
private pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
private FILE *terminal_outfile = NULL;
static FILE *terminal_outfile = NULL;
/* terminal_setflags():
* Set the terminal capability flags
*/
private void
static void
terminal_setflags(EditLine *el)
{
EL_FLAGS = 0;
@ -266,35 +265,31 @@ terminal_setflags(EditLine *el)
/* terminal_init():
* Initialize the terminal stuff
*/
protected int
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;
@ -317,7 +312,7 @@ terminal_init(EditLine *el)
/* terminal_end():
* Clean up the terminal stuff
*/
protected void
libedit_private void
terminal_end(EditLine *el)
{
@ -339,7 +334,7 @@ terminal_end(EditLine *el)
/* terminal_alloc():
* Maintain a string pool for termcap strings
*/
private void
static void
terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
{
char termbuf[TC_BUFSIZE];
@ -405,7 +400,7 @@ terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap)
/* terminal_rebuffer_display():
* Rebuffer the display after the screen changed size
*/
private int
static int
terminal_rebuffer_display(EditLine *el)
{
coord_t *c = &el->el_terminal.t_size;
@ -420,46 +415,58 @@ terminal_rebuffer_display(EditLine *el)
return 0;
}
static wint_t **
terminal_alloc_buffer(EditLine *el)
{
wint_t **b;
coord_t *c = &el->el_terminal.t_size;
int i;
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_calloc((size_t)(c->h + 1), sizeof(**b));
if (b[i] == NULL) {
while (--i >= 0)
el_free(b[i]);
el_free(b);
return NULL;
}
}
b[c->v] = NULL;
return b;
}
static void
terminal_free_buffer(wint_t ***bp)
{
wint_t **b;
wint_t **bufp;
if (*bp == NULL)
return;
b = *bp;
*bp = NULL;
for (bufp = b; *bufp != NULL; bufp++)
el_free(*bufp);
el_free(b);
}
/* terminal_alloc_display():
* Allocate a new display.
*/
private int
static int
terminal_alloc_display(EditLine *el)
{
int i;
Char **b;
coord_t *c = &el->el_terminal.t_size;
b = el_malloc(sizeof(*b) * (size_t)(c->v + 1));
if (b == NULL)
el->el_display = terminal_alloc_buffer(el);
if (el->el_display == NULL)
goto done;
for (i = 0; i < c->v; i++) {
b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1));
if (b[i] == NULL) {
while (--i >= 0)
el_free(b[i]);
el_free(b);
goto done;
}
}
b[c->v] = NULL;
el->el_display = b;
b = el_malloc(sizeof(*b) * (size_t)(c->v + 1));
if (b == NULL)
el->el_vdisplay = terminal_alloc_buffer(el);
if (el->el_vdisplay == NULL)
goto done;
for (i = 0; i < c->v; i++) {
b[i] = el_malloc(sizeof(**b) * (size_t)(c->h + 1));
if (b[i] == NULL) {
while (--i >= 0)
el_free(b[i]);
el_free(b);
goto done;
}
}
b[c->v] = NULL;
el->el_vdisplay = b;
return 0;
done:
terminal_free_display(el);
@ -470,26 +477,11 @@ terminal_alloc_display(EditLine *el)
/* terminal_free_display():
* Free the display buffers
*/
private void
static void
terminal_free_display(EditLine *el)
{
Char **b;
Char **bufp;
b = el->el_display;
el->el_display = NULL;
if (b != NULL) {
for (bufp = b; *bufp != NULL; bufp++)
el_free(*bufp);
el_free(b);
}
b = el->el_vdisplay;
el->el_vdisplay = NULL;
if (b != NULL) {
for (bufp = b; *bufp != NULL; bufp++)
el_free(*bufp);
el_free(b);
}
terminal_free_buffer(&el->el_display);
terminal_free_buffer(&el->el_vdisplay);
}
@ -497,7 +489,7 @@ terminal_free_display(EditLine *el)
* move to line <where> (first line == 0)
* as efficiently as possible
*/
protected void
libedit_private void
terminal_move_to_line(EditLine *el, int where)
{
int del;
@ -513,39 +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);
#ifdef WIDECHAR
for (; h > 0 &&
el->el_display[el->el_cursor.v][h] ==
MB_FILL_CHAR;
h--)
continue;
#endif
/* 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);
@ -562,7 +529,7 @@ terminal_move_to_line(EditLine *el, int where)
/* terminal_move_to_char():
* Move to the character position specified
*/
protected void
libedit_private void
terminal_move_to_char(EditLine *el, int where)
{
int del, i;
@ -598,11 +565,9 @@ terminal_move_to_char(EditLine *el, int where)
if (EL_CAN_TAB) {
if ((el->el_cursor.h & 0370) !=
(where & ~0x7)
#ifdef WIDECHAR
&& (el->el_display[
el->el_cursor.v][where & 0370] !=
MB_FILL_CHAR)
#endif
) {
/* if not within tab stop */
for (i =
@ -659,8 +624,8 @@ terminal_move_to_char(EditLine *el, int where)
* Overstrike num characters
* Assumes MB_FILL_CHARs are present to keep the column count correct
*/
protected void
terminal_overwrite(EditLine *el, const Char *cp, size_t n)
libedit_private void
terminal_overwrite(EditLine *el, const wchar_t *cp, size_t n)
{
if (n == 0)
return;
@ -686,15 +651,13 @@ terminal_overwrite(EditLine *el, const Char *cp, size_t n)
if (EL_HAS_MAGIC_MARGINS) {
/* force the wrap to avoid the "magic"
* situation */
Char c;
wchar_t c;
if ((c = el->el_display[el->el_cursor.v]
[el->el_cursor.h]) != '\0') {
terminal_overwrite(el, &c, (size_t)1);
#ifdef WIDECHAR
while (el->el_display[el->el_cursor.v]
[el->el_cursor.h] == MB_FILL_CHAR)
el->el_cursor.h++;
#endif
} else {
terminal__putc(el, ' ');
el->el_cursor.h = 1;
@ -709,7 +672,7 @@ terminal_overwrite(EditLine *el, const Char *cp, size_t n)
/* terminal_deletechars():
* Delete num characters
*/
protected void
libedit_private void
terminal_deletechars(EditLine *el, int num)
{
if (num <= 0)
@ -751,8 +714,8 @@ terminal_deletechars(EditLine *el, int num)
* characters in the line
* Assumes MB_FILL_CHARs are present to keep column count correct
*/
protected void
terminal_insertwrite(EditLine *el, Char *cp, int num)
libedit_private void
terminal_insertwrite(EditLine *el, wchar_t *cp, int num)
{
if (num <= 0)
return;
@ -810,7 +773,7 @@ terminal_insertwrite(EditLine *el, Char *cp, int num)
/* terminal_clear_EOL():
* clear to end of line. There are num characters to clear
*/
protected void
libedit_private void
terminal_clear_EOL(EditLine *el, int num)
{
int i;
@ -828,7 +791,7 @@ terminal_clear_EOL(EditLine *el, int num)
/* terminal_clear_screen():
* Clear the screen
*/
protected void
libedit_private void
terminal_clear_screen(EditLine *el)
{ /* clear the whole screen and home */
@ -849,7 +812,7 @@ terminal_clear_screen(EditLine *el)
/* terminal_beep():
* Beep the way the terminal wants us
*/
protected void
libedit_private void
terminal_beep(EditLine *el)
{
if (GoodStr(T_bl))
@ -860,7 +823,7 @@ terminal_beep(EditLine *el)
}
protected void
libedit_private void
terminal_get(EditLine *el, const char **term)
{
*term = el->el_terminal.t_name;
@ -870,7 +833,7 @@ terminal_get(EditLine *el, const char **term)
/* terminal_set():
* Read in the terminal capabilities from the requested terminal
*/
protected int
libedit_private int
terminal_set(EditLine *el, const char *term)
{
int i;
@ -959,7 +922,7 @@ terminal_set(EditLine *el, const char *term)
* Return the new window size in lines and cols, and
* true if the size was changed.
*/
protected int
libedit_private int
terminal_get_size(EditLine *el, int *lins, int *cols)
{
@ -995,12 +958,13 @@ terminal_get_size(EditLine *el, int *lins, int *cols)
/* terminal_change_size():
* Change the size of the terminal
*/
protected int
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;
@ -1008,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;
}
@ -1015,42 +980,42 @@ terminal_change_size(EditLine *el, int lins, int cols)
/* terminal_init_arrow():
* Initialize the arrow key bindings from termcap
*/
private void
static void
terminal_init_arrow(EditLine *el)
{
funckey_t *arrow = el->el_terminal.t_fkey;
arrow[A_K_DN].name = STR("down");
arrow[A_K_DN].name = L"down";
arrow[A_K_DN].key = T_kd;
arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY;
arrow[A_K_DN].type = XK_CMD;
arrow[A_K_UP].name = STR("up");
arrow[A_K_UP].name = L"up";
arrow[A_K_UP].key = T_ku;
arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY;
arrow[A_K_UP].type = XK_CMD;
arrow[A_K_LT].name = STR("left");
arrow[A_K_LT].name = L"left";
arrow[A_K_LT].key = T_kl;
arrow[A_K_LT].fun.cmd = ED_PREV_CHAR;
arrow[A_K_LT].type = XK_CMD;
arrow[A_K_RT].name = STR("right");
arrow[A_K_RT].name = L"right";
arrow[A_K_RT].key = T_kr;
arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR;
arrow[A_K_RT].type = XK_CMD;
arrow[A_K_HO].name = STR("home");
arrow[A_K_HO].name = L"home";
arrow[A_K_HO].key = T_kh;
arrow[A_K_HO].fun.cmd = ED_MOVE_TO_BEG;
arrow[A_K_HO].type = XK_CMD;
arrow[A_K_EN].name = STR("end");
arrow[A_K_EN].name = L"end";
arrow[A_K_EN].key = T_at7;
arrow[A_K_EN].fun.cmd = ED_MOVE_TO_END;
arrow[A_K_EN].type = XK_CMD;
arrow[A_K_DE].name = STR("delete");
arrow[A_K_DE].name = L"delete";
arrow[A_K_DE].key = T_kD;
arrow[A_K_DE].fun.cmd = ED_DELETE_NEXT_CHAR;
arrow[A_K_DE].type = XK_CMD;
@ -1060,22 +1025,22 @@ terminal_init_arrow(EditLine *el)
/* terminal_reset_arrow():
* Reset arrow key bindings
*/
private void
static void
terminal_reset_arrow(EditLine *el)
{
funckey_t *arrow = el->el_terminal.t_fkey;
static const Char strA[] = {033, '[', 'A', '\0'};
static const Char strB[] = {033, '[', 'B', '\0'};
static const Char strC[] = {033, '[', 'C', '\0'};
static const Char strD[] = {033, '[', 'D', '\0'};
static const Char strH[] = {033, '[', 'H', '\0'};
static const Char strF[] = {033, '[', 'F', '\0'};
static const Char stOA[] = {033, 'O', 'A', '\0'};
static const Char stOB[] = {033, 'O', 'B', '\0'};
static const Char stOC[] = {033, 'O', 'C', '\0'};
static const Char stOD[] = {033, 'O', 'D', '\0'};
static const Char stOH[] = {033, 'O', 'H', '\0'};
static const Char stOF[] = {033, 'O', 'F', '\0'};
static const wchar_t strA[] = L"\033[A";
static const wchar_t strB[] = L"\033[B";
static const wchar_t strC[] = L"\033[C";
static const wchar_t strD[] = L"\033[D";
static const wchar_t strH[] = L"\033[H";
static const wchar_t strF[] = L"\033[F";
static const wchar_t stOA[] = L"\033OA";
static const wchar_t stOB[] = L"\033OB";
static const wchar_t stOC[] = L"\033OC";
static const wchar_t stOD[] = L"\033OD";
static const wchar_t stOH[] = L"\033OH";
static const wchar_t stOF[] = L"\033OF";
keymacro_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
keymacro_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
@ -1110,15 +1075,15 @@ terminal_reset_arrow(EditLine *el)
/* terminal_set_arrow():
* Set an arrow key binding
*/
protected int
terminal_set_arrow(EditLine *el, const Char *name, keymacro_value_t *fun,
libedit_private int
terminal_set_arrow(EditLine *el, const wchar_t *name, keymacro_value_t *fun,
int type)
{
funckey_t *arrow = el->el_terminal.t_fkey;
int i;
for (i = 0; i < A_K_NKEYS; i++)
if (Strcmp(name, arrow[i].name) == 0) {
if (wcscmp(name, arrow[i].name) == 0) {
arrow[i].fun = *fun;
arrow[i].type = type;
return 0;
@ -1130,14 +1095,14 @@ terminal_set_arrow(EditLine *el, const Char *name, keymacro_value_t *fun,
/* terminal_clear_arrow():
* Clear an arrow key binding
*/
protected int
terminal_clear_arrow(EditLine *el, const Char *name)
libedit_private int
terminal_clear_arrow(EditLine *el, const wchar_t *name)
{
funckey_t *arrow = el->el_terminal.t_fkey;
int i;
for (i = 0; i < A_K_NKEYS; i++)
if (Strcmp(name, arrow[i].name) == 0) {
if (wcscmp(name, arrow[i].name) == 0) {
arrow[i].type = XK_NOD;
return 0;
}
@ -1148,14 +1113,14 @@ terminal_clear_arrow(EditLine *el, const Char *name)
/* terminal_print_arrow():
* Print the arrow key bindings
*/
protected void
terminal_print_arrow(EditLine *el, const Char *name)
libedit_private void
terminal_print_arrow(EditLine *el, const wchar_t *name)
{
int i;
funckey_t *arrow = el->el_terminal.t_fkey;
for (i = 0; i < A_K_NKEYS; i++)
if (*name == '\0' || Strcmp(name, arrow[i].name) == 0)
if (*name == '\0' || wcscmp(name, arrow[i].name) == 0)
if (arrow[i].type != XK_NOD)
keymacro_kprint(el, arrow[i].name,
&arrow[i].fun, arrow[i].type);
@ -1165,7 +1130,7 @@ terminal_print_arrow(EditLine *el, const Char *name)
/* terminal_bind_arrow():
* Bind the arrow keys
*/
protected void
libedit_private void
terminal_bind_arrow(EditLine *el)
{
el_action_t *map;
@ -1184,8 +1149,8 @@ terminal_bind_arrow(EditLine *el)
terminal_reset_arrow(el);
for (i = 0; i < A_K_NKEYS; i++) {
Char wt_str[VISUAL_WIDTH_MAX];
Char *px;
wchar_t wt_str[VISUAL_WIDTH_MAX];
wchar_t *px;
size_t n;
p = el->el_terminal.t_str[arrow[i].key];
@ -1230,7 +1195,7 @@ terminal_bind_arrow(EditLine *el)
/* terminal_putc():
* Add a character
*/
private int
static int
terminal_putc(int c)
{
if (terminal_outfile == NULL)
@ -1238,7 +1203,7 @@ terminal_putc(int c)
return fputc(c, terminal_outfile);
}
private void
static void
terminal_tputs(EditLine *el, const char *cap, int affcnt)
{
#ifdef _REENTRANT
@ -1254,14 +1219,16 @@ terminal_tputs(EditLine *el, const char *cap, int affcnt)
/* terminal__putc():
* Add a character
*/
protected int
libedit_private int
terminal__putc(EditLine *el, wint_t c)
{
char buf[MB_LEN_MAX +1];
ssize_t i;
if (c == (wint_t)MB_FILL_CHAR)
return 0;
i = ct_encode_char(buf, (size_t)MB_LEN_MAX, (Char)c);
if (c & EL_LITERAL)
return fputs(literal_get(el, c), el->el_outfile);
i = ct_encode_char(buf, (size_t)MB_LEN_MAX, c);
if (i <= 0)
return (int)i;
buf[i] = '\0';
@ -1271,7 +1238,7 @@ terminal__putc(EditLine *el, wint_t c)
/* terminal__flush():
* Flush output
*/
protected void
libedit_private void
terminal__flush(EditLine *el)
{
@ -1281,11 +1248,11 @@ terminal__flush(EditLine *el)
/* terminal_writec():
* Write the given character out, in a human readable form
*/
protected void
libedit_private void
terminal_writec(EditLine *el, wint_t c)
{
Char visbuf[VISUAL_WIDTH_MAX +1];
ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, (Char)c);
wchar_t visbuf[VISUAL_WIDTH_MAX +1];
ssize_t vcnt = ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c);
if (vcnt < 0)
vcnt = 0;
visbuf[vcnt] = '\0';
@ -1297,10 +1264,10 @@ terminal_writec(EditLine *el, wint_t c)
/* terminal_telltc():
* Print the current termcap characteristics
*/
protected int
libedit_private int
/*ARGSUSED*/
terminal_telltc(EditLine *el, int argc __attribute__((__unused__)),
const Char **argv __attribute__((__unused__)))
const wchar_t **argv __attribute__((__unused__)))
{
const struct termcapstr *t;
char **ts;
@ -1323,8 +1290,8 @@ terminal_telltc(EditLine *el, int argc __attribute__((__unused__)),
const char *ub;
if (*ts && **ts) {
ub = ct_encode_string(ct_visual_string(
ct_decode_string(*ts, &el->el_scratch)),
&el->el_scratch);
ct_decode_string(*ts, &el->el_scratch),
&el->el_visual), &el->el_scratch);
} else {
ub = "(empty)";
}
@ -1339,10 +1306,10 @@ terminal_telltc(EditLine *el, int argc __attribute__((__unused__)),
/* terminal_settc():
* Change the current terminal characteristics
*/
protected int
libedit_private int
/*ARGSUSED*/
terminal_settc(EditLine *el, int argc __attribute__((__unused__)),
const Char **argv)
const wchar_t **argv)
{
const struct termcapstr *ts;
const struct termcapval *tv;
@ -1386,7 +1353,7 @@ terminal_settc(EditLine *el, int argc __attribute__((__unused__)),
el->el_terminal.t_val[tv - tval] = 0;
else {
(void) fprintf(el->el_errfile,
"" FSTR ": Bad value `%s'.\n", argv[0], how);
"%ls: Bad value `%s'.\n", argv[0], how);
return -1;
}
terminal_setflags(el);
@ -1400,7 +1367,7 @@ terminal_settc(EditLine *el, int argc __attribute__((__unused__)),
i = strtol(how, &ep, 10);
if (*ep != '\0') {
(void) fprintf(el->el_errfile,
"" FSTR ": Bad value `%s'.\n", argv[0], how);
"%ls: Bad value `%s'.\n", argv[0], how);
return -1;
}
el->el_terminal.t_val[tv - tval] = (int) i;
@ -1418,7 +1385,7 @@ terminal_settc(EditLine *el, int argc __attribute__((__unused__)),
/* terminal_gettc():
* Get the current terminal characteristics
*/
protected int
libedit_private int
/*ARGSUSED*/
terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv)
{
@ -1472,13 +1439,13 @@ terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv)
/* terminal_echotc():
* Print the termcap string out with variable substitution
*/
protected int
libedit_private int
/*ARGSUSED*/
terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
const Char **argv)
const wchar_t **argv)
{
char *cap, *scap;
Char *ep;
wchar_t *ep;
int arg_need, arg_cols, arg_rows;
int verbose = 0, silent = 0;
char *area;
@ -1509,28 +1476,28 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
}
if (!*argv || *argv[0] == '\0')
return 0;
if (Strcmp(*argv, STR("tabs")) == 0) {
if (wcscmp(*argv, L"tabs") == 0) {
(void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no");
return 0;
} else if (Strcmp(*argv, STR("meta")) == 0) {
} else if (wcscmp(*argv, L"meta") == 0) {
(void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no");
return 0;
} else if (Strcmp(*argv, STR("xn")) == 0) {
} else if (wcscmp(*argv, L"xn") == 0) {
(void) fprintf(el->el_outfile, fmts, EL_HAS_MAGIC_MARGINS ?
"yes" : "no");
return 0;
} else if (Strcmp(*argv, STR("am")) == 0) {
} else if (wcscmp(*argv, L"am") == 0) {
(void) fprintf(el->el_outfile, fmts, EL_HAS_AUTO_MARGINS ?
"yes" : "no");
return 0;
} else if (Strcmp(*argv, STR("baud")) == 0) {
} else if (wcscmp(*argv, L"baud") == 0) {
(void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed);
return 0;
} else if (Strcmp(*argv, STR("rows")) == 0 ||
Strcmp(*argv, STR("lines")) == 0) {
} else if (wcscmp(*argv, L"rows") == 0 ||
wcscmp(*argv, L"lines") == 0) {
(void) fprintf(el->el_outfile, fmtd, Val(T_li));
return 0;
} else if (Strcmp(*argv, STR("cols")) == 0) {
} else if (wcscmp(*argv, L"cols") == 0) {
(void) fprintf(el->el_outfile, fmtd, Val(T_co));
return 0;
}
@ -1551,7 +1518,7 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (!scap || scap[0] == '\0') {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Termcap parameter `" FSTR "' not found.\n",
"echotc: Termcap parameter `%ls' not found.\n",
*argv);
return -1;
}
@ -1594,7 +1561,7 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `" FSTR "'.\n",
"echotc: Warning: Extra argument `%ls'.\n",
*argv);
return -1;
}
@ -1609,11 +1576,11 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
return -1;
}
arg_cols = 0;
i = Strtol(*argv, &ep, 10);
i = wcstol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Bad value `" FSTR "' for rows.\n",
"echotc: Bad value `%ls' for rows.\n",
*argv);
return -1;
}
@ -1622,7 +1589,7 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `" FSTR
"echotc: Warning: Extra argument `%ls"
"'.\n", *argv);
return -1;
}
@ -1643,11 +1610,11 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
"echotc: Warning: Missing argument.\n");
return -1;
}
i = Strtol(*argv, &ep, 10);
i = wcstol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Bad value `" FSTR "' for cols.\n",
"echotc: Bad value `%ls' for cols.\n",
*argv);
return -1;
}
@ -1659,11 +1626,11 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
"echotc: Warning: Missing argument.\n");
return -1;
}
i = Strtol(*argv, &ep, 10);
i = wcstol(*argv, &ep, 10);
if (*ep != '\0' || i < 0) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Bad value `" FSTR "' for rows.\n",
"echotc: Bad value `%ls' for rows.\n",
*argv);
return -1;
}
@ -1671,14 +1638,14 @@ terminal_echotc(EditLine *el, int argc __attribute__((__unused__)),
if (*ep != '\0') {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Bad value `" FSTR "'.\n", *argv);
"echotc: Bad value `%ls'.\n", *argv);
return -1;
}
argv++;
if (*argv && *argv[0]) {
if (!silent)
(void) fprintf(el->el_errfile,
"echotc: Warning: Extra argument `" FSTR
"echotc: Warning: Extra argument `%ls"
"'.\n", *argv);
return -1;
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: terminal.h,v 1.7 2016/02/16 15:53:48 christos Exp $ */
/* $NetBSD: terminal.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)term.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -42,7 +41,7 @@
#define _h_el_terminal
typedef struct { /* Symbolic function key bindings */
const Char *name; /* name of the key */
const wchar_t *name; /* name of the key */
int key; /* Index in termcap table */
keymacro_value_t fun; /* Function bound to it */
int type; /* Type of function */
@ -81,31 +80,32 @@ typedef struct {
#define A_K_DE 6
#define A_K_NKEYS 7
protected void terminal_move_to_line(EditLine *, int);
protected void terminal_move_to_char(EditLine *, int);
protected void terminal_clear_EOL(EditLine *, int);
protected void terminal_overwrite(EditLine *, const Char *, size_t);
protected void terminal_insertwrite(EditLine *, Char *, int);
protected void terminal_deletechars(EditLine *, int);
protected void terminal_clear_screen(EditLine *);
protected void terminal_beep(EditLine *);
protected int terminal_change_size(EditLine *, int, int);
protected int terminal_get_size(EditLine *, int *, int *);
protected int terminal_init(EditLine *);
protected void terminal_bind_arrow(EditLine *);
protected void terminal_print_arrow(EditLine *, const Char *);
protected int terminal_clear_arrow(EditLine *, const Char *);
protected int terminal_set_arrow(EditLine *, const Char *, keymacro_value_t *, int);
protected void terminal_end(EditLine *);
protected void terminal_get(EditLine *, const char **);
protected int terminal_set(EditLine *, const char *);
protected int terminal_settc(EditLine *, int, const Char **);
protected int terminal_gettc(EditLine *, int, char **);
protected int terminal_telltc(EditLine *, int, const Char **);
protected int terminal_echotc(EditLine *, int, const Char **);
protected void terminal_writec(EditLine *, wint_t);
protected int terminal__putc(EditLine *, wint_t);
protected void terminal__flush(EditLine *);
libedit_private void terminal_move_to_line(EditLine *, int);
libedit_private void terminal_move_to_char(EditLine *, int);
libedit_private void terminal_clear_EOL(EditLine *, int);
libedit_private void terminal_overwrite(EditLine *, const wchar_t *, size_t);
libedit_private void terminal_insertwrite(EditLine *, wchar_t *, int);
libedit_private void terminal_deletechars(EditLine *, int);
libedit_private void terminal_clear_screen(EditLine *);
libedit_private void terminal_beep(EditLine *);
libedit_private int terminal_change_size(EditLine *, int, int);
libedit_private int terminal_get_size(EditLine *, int *, int *);
libedit_private int terminal_init(EditLine *);
libedit_private void terminal_bind_arrow(EditLine *);
libedit_private void terminal_print_arrow(EditLine *, const wchar_t *);
libedit_private int terminal_clear_arrow(EditLine *, const wchar_t *);
libedit_private int terminal_set_arrow(EditLine *, const wchar_t *,
keymacro_value_t *, int);
libedit_private void terminal_end(EditLine *);
libedit_private void terminal_get(EditLine *, const char **);
libedit_private int terminal_set(EditLine *, const char *);
libedit_private int terminal_settc(EditLine *, int, const wchar_t **);
libedit_private int terminal_gettc(EditLine *, int, char **);
libedit_private int terminal_telltc(EditLine *, int, const wchar_t **);
libedit_private int terminal_echotc(EditLine *, int, const wchar_t **);
libedit_private void terminal_writec(EditLine *, wint_t);
libedit_private int terminal__putc(EditLine *, wint_t);
libedit_private void terminal__flush(EditLine *);
/*
* Easy access macros

View file

@ -1,4 +1,4 @@
/* $NetBSD: tokenizer.c,v 1.24 2016/02/17 19:47:49 christos Exp $ */
/* $NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: tokenizer.c,v 1.24 2016/02/17 19:47:49 christos Exp $");
__RCSID("$NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* We build this file twice, once as NARROW, once as WIDE. */
/*
@ -51,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include "histedit.h"
#include "chartype.h"
typedef enum {
Q_none, Q_single, Q_double, Q_one, Q_doubleone
@ -68,8 +65,22 @@ typedef enum {
#define tok_malloc(a) malloc(a)
#define tok_free(a) free(a)
#define tok_realloc(a, b) realloc(a, b)
#define tok_strdup(a) Strdup(a)
#ifdef NARROWCHAR
#define Char char
#define FUN(prefix, rest) prefix ## _ ## rest
#define TYPE(type) type
#define STR(x) x
#define Strchr(s, c) strchr(s, c)
#define tok_strdup(s) strdup(s)
#else
#define Char wchar_t
#define FUN(prefix, rest) prefix ## _w ## rest
#define TYPE(type) type ## W
#define STR(x) L ## x
#define Strchr(s, c) wcschr(s, c)
#define tok_strdup(s) wcsdup(s)
#endif
struct TYPE(tokenizer) {
Char *ifs; /* In field separator */
@ -83,13 +94,13 @@ struct TYPE(tokenizer) {
};
private void FUN(tok,finish)(TYPE(Tokenizer) *);
static void FUN(tok,finish)(TYPE(Tokenizer) *);
/* FUN(tok,finish)():
* Finish a word in the tokenizer.
*/
private void
static void
FUN(tok,finish)(TYPE(Tokenizer) *tok)
{
@ -106,7 +117,7 @@ FUN(tok,finish)(TYPE(Tokenizer) *tok)
/* FUN(tok,init)():
* Initialize the tokenizer
*/
public TYPE(Tokenizer) *
TYPE(Tokenizer) *
FUN(tok,init)(const Char *ifs)
{
TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok));
@ -147,7 +158,7 @@ FUN(tok,init)(const Char *ifs)
/* FUN(tok,reset)():
* Reset the tokenizer
*/
public void
void
FUN(tok,reset)(TYPE(Tokenizer) *tok)
{
@ -162,7 +173,7 @@ FUN(tok,reset)(TYPE(Tokenizer) *tok)
/* FUN(tok,end)():
* Clean up
*/
public void
void
FUN(tok,end)(TYPE(Tokenizer) *tok)
{
@ -191,7 +202,7 @@ FUN(tok,end)(TYPE(Tokenizer) *tok)
* cursorc if !NULL, argv element containing cursor
* cursorv if !NULL, offset in argv[cursorc] of cursor
*/
public int
int
FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line,
int *argc, const Char ***argv, int *cursorc, int *cursoro)
{
@ -442,7 +453,7 @@ FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line,
* Simpler version of tok_line, taking a NUL terminated line
* and splitting into words, ignoring cursor state.
*/
public int
int
FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc,
const Char ***argv)
{

View file

@ -0,0 +1,3 @@
#include "config.h"
#define NARROWCHAR
#include "tokenizer.c"

View file

@ -1,4 +1,4 @@
/* $NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $ */
/* $NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: tty.c,v 1.59 2016/03/22 01:34:32 christos Exp $");
__RCSID("$NetBSD: tty.c,v 1.68 2018/12/02 16:58:13 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* tty.c: tty interface stuff
@ -54,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h> /* for isatty */
#include "el.h"
#include "fcns.h"
#include "parse.h"
typedef struct ttymodes_t {
@ -68,7 +67,7 @@ typedef struct ttymap_t {
} ttymap_t;
private const ttyperm_t ttyperm = {
static const ttyperm_t ttyperm = {
{
{"iflag:", ICRNL, (INLCR | IGNCR)},
{"oflag:", (OPOST | ONLCR), ONLRET},
@ -96,7 +95,7 @@ private const ttyperm_t ttyperm = {
}
};
private const ttychar_t ttychar = {
static const ttychar_t ttychar = {
{
CINTR, CQUIT, CERASE, CKILL,
CEOF, CEOL, CEOL2, CSWTCH,
@ -126,7 +125,7 @@ private const ttychar_t ttychar = {
}
};
private const ttymap_t tty_map[] = {
static const ttymap_t tty_map[] = {
#ifdef VERASE
{C_ERASE, VERASE,
{EM_DELETE_PREV_CHAR, VI_DELETE_PREV_CHAR, ED_PREV_CHAR}},
@ -163,7 +162,7 @@ private const ttymap_t tty_map[] = {
{ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}}
};
private const ttymodes_t ttymodes[] = {
static const ttymodes_t ttymodes[] = {
#ifdef IGNBRK
{"ignbrk", IGNBRK, MD_INP},
#endif /* IGNBRK */
@ -457,21 +456,21 @@ private const ttymodes_t ttymodes[] = {
#define tty__geteightbit(td) (((td)->c_cflag & CSIZE) == CS8)
#define tty__cooked_mode(td) ((td)->c_lflag & ICANON)
private int tty_getty(EditLine *, struct termios *);
private int tty_setty(EditLine *, int, const struct termios *);
private int tty__getcharindex(int);
private void tty__getchar(struct termios *, unsigned char *);
private void tty__setchar(struct termios *, unsigned char *);
private speed_t tty__getspeed(struct termios *);
private int tty_setup(EditLine *);
private void tty_setup_flags(EditLine *, struct termios *, int);
static int tty_getty(EditLine *, struct termios *);
static int tty_setty(EditLine *, int, const struct termios *);
static int tty__getcharindex(int);
static void tty__getchar(struct termios *, unsigned char *);
static void tty__setchar(struct termios *, unsigned char *);
static speed_t tty__getspeed(struct termios *);
static int tty_setup(EditLine *);
static void tty_setup_flags(EditLine *, struct termios *, int);
#define t_qu t_ts
/* tty_getty():
* Wrapper for tcgetattr to handle EINTR
*/
private int
static int
tty_getty(EditLine *el, struct termios *t)
{
int rv;
@ -483,7 +482,7 @@ tty_getty(EditLine *el, struct termios *t)
/* tty_setty():
* Wrapper for tcsetattr to handle EINTR
*/
private int
static int
tty_setty(EditLine *el, int action, const struct termios *t)
{
int rv;
@ -495,10 +494,10 @@ tty_setty(EditLine *el, int action, const struct termios *t)
/* tty_setup():
* Get the tty parameters and initialize the editing state
*/
private int
static int
tty_setup(EditLine *el)
{
int rst = 1;
int rst = (el->el_flags & NO_RESET) == 0;
if (el->el_flags & EDIT_DISABLED)
return 0;
@ -569,7 +568,7 @@ tty_setup(EditLine *el)
return 0;
}
protected int
libedit_private int
tty_init(EditLine *el)
{
@ -585,9 +584,9 @@ tty_init(EditLine *el)
/* tty_end():
* Restore the tty to its original settings
*/
protected void
libedit_private void
/*ARGSUSED*/
tty_end(EditLine *el)
tty_end(EditLine *el, int how)
{
if (el->el_flags & EDIT_DISABLED)
return;
@ -595,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));
@ -607,7 +607,7 @@ tty_end(EditLine *el)
/* tty__getspeed():
* Get the tty speed
*/
private speed_t
static speed_t
tty__getspeed(struct termios *td)
{
speed_t spd;
@ -620,7 +620,7 @@ tty__getspeed(struct termios *td)
/* tty__getspeed():
* Return the index of the asked char in the c_cc array
*/
private int
static int
tty__getcharindex(int i)
{
switch (i) {
@ -728,7 +728,7 @@ tty__getcharindex(int i)
/* tty__getchar():
* Get the tty characters
*/
private void
static void
tty__getchar(struct termios *td, unsigned char *s)
{
@ -810,7 +810,7 @@ tty__getchar(struct termios *td, unsigned char *s)
/* tty__setchar():
* Set the tty characters
*/
private void
static void
tty__setchar(struct termios *td, unsigned char *s)
{
@ -892,13 +892,13 @@ tty__setchar(struct termios *td, unsigned char *s)
/* tty_bind_char():
* Rebind the editline functions
*/
protected void
libedit_private void
tty_bind_char(EditLine *el, int force)
{
unsigned char *t_n = el->el_tty.t_c[ED_IO];
unsigned char *t_o = el->el_tty.t_ed.c_cc;
Char new[2], old[2];
wchar_t new[2], old[2];
const ttymap_t *tp;
el_action_t *map, *alt;
const el_action_t *dmap, *dalt;
@ -915,27 +915,29 @@ tty_bind_char(EditLine *el, int force)
}
for (tp = tty_map; tp->nch != (wint_t)-1; tp++) {
new[0] = (Char)t_n[tp->nch];
old[0] = (Char)t_o[tp->och];
new[0] = (wchar_t)t_n[tp->nch];
old[0] = (wchar_t)t_o[tp->och];
if (new[0] == old[0] && !force)
continue;
/* Put the old default binding back, and set the new binding */
keymacro_clear(el, map, old);
map[UC(old[0])] = dmap[UC(old[0])];
map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]];
keymacro_clear(el, map, new);
/* MAP_VI == 1, MAP_EMACS == 0... */
map[UC(new[0])] = tp->bind[el->el_map.type];
map[(unsigned char)new[0]] = tp->bind[el->el_map.type];
if (dalt) {
keymacro_clear(el, alt, old);
alt[UC(old[0])] = dalt[UC(old[0])];
alt[(unsigned char)old[0]] =
dalt[(unsigned char)old[0]];
keymacro_clear(el, alt, new);
alt[UC(new[0])] = tp->bind[el->el_map.type + 1];
alt[(unsigned char)new[0]] =
tp->bind[el->el_map.type + 1];
}
}
}
private tcflag_t *
static tcflag_t *
tty__get_flag(struct termios *t, int kind) {
switch (kind) {
case MD_INP:
@ -953,7 +955,7 @@ tty__get_flag(struct termios *t, int kind) {
}
private tcflag_t
static tcflag_t
tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
{
f &= ~el->el_tty.t_t[mode][kind].t_clrmask;
@ -962,7 +964,7 @@ tty_update_flag(EditLine *el, tcflag_t f, int mode, int kind)
}
private void
static void
tty_update_flags(EditLine *el, int kind)
{
tcflag_t *tt, *ed, *ex;
@ -977,7 +979,7 @@ tty_update_flags(EditLine *el, int kind)
}
private void
static 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]))
@ -990,7 +992,7 @@ tty_update_char(EditLine *el, int mode, int c) {
/* tty_rawmode():
* Set terminal into 1 character at a time mode.
*/
protected int
libedit_private int
tty_rawmode(EditLine *el)
{
@ -1045,7 +1047,7 @@ tty_rawmode(EditLine *el)
if (i != C_NCC) {
/*
* Propagate changes only to the unprotected
* Propagate changes only to the unlibedit_private
* chars that have been modified just now.
*/
for (i = 0; i < C_NCC; i++)
@ -1075,7 +1077,7 @@ tty_rawmode(EditLine *el)
/* tty_cookedmode():
* Set the tty back to normal mode
*/
protected int
libedit_private int
tty_cookedmode(EditLine *el)
{ /* set tty in normal setup */
@ -1100,7 +1102,7 @@ tty_cookedmode(EditLine *el)
/* tty_quotemode():
* Turn on quote mode
*/
protected int
libedit_private int
tty_quotemode(EditLine *el)
{
if (el->el_tty.t_mode == QU_IO)
@ -1125,7 +1127,7 @@ tty_quotemode(EditLine *el)
/* tty_noquotemode():
* Turn off quote mode
*/
protected int
libedit_private int
tty_noquotemode(EditLine *el)
{
@ -1146,14 +1148,15 @@ tty_noquotemode(EditLine *el)
/* tty_stty():
* Stty builtin
*/
protected int
libedit_private int
/*ARGSUSED*/
tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
tty_stty(EditLine *el, int argc __attribute__((__unused__)),
const wchar_t **argv)
{
const ttymodes_t *m;
char x;
int aflag = 0;
const Char *s, *d;
const wchar_t *s, *d;
char name[EL_BUFSIZ];
struct termios *tios = &el->el_tty.t_ex;
int z = EX_IO;
@ -1237,7 +1240,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
return 0;
}
while (argv && (s = *argv++)) {
const Char *p;
const wchar_t *p;
switch (*s) {
case '+':
case '-':
@ -1248,7 +1251,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
break;
}
d = s;
p = Strchr(s, '=');
p = wcschr(s, L'=');
for (m = ttymodes; m->m_name; m++)
if ((p ? strncmp(m->m_name, ct_encode_string(d,
&el->el_scratch), (size_t)(p - d)) :
@ -1259,7 +1262,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
if (!m->m_name) {
(void) fprintf(el->el_errfile,
"%s: Invalid argument `" FSTR "'.\n", name, d);
"%s: Invalid argument `%ls'.\n", name, d);
return -1;
}
if (p) {
@ -1308,7 +1311,7 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const Char **argv)
/* tty_printchar():
* DEbugging routine to print the tty characters
*/
private void
static void
tty_printchar(EditLine *el, unsigned char *s)
{
ttyperm_t *m;
@ -1329,7 +1332,7 @@ tty_printchar(EditLine *el, unsigned char *s)
#endif /* notyet */
private void
static void
tty_setup_flags(EditLine *el, struct termios *tios, int mode)
{
int kind;
@ -1338,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;
}
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: tty.h,v 1.19 2016/02/27 18:13:21 christos Exp $ */
/* $NetBSD: tty.h,v 1.23 2018/12/02 16:58:13 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -32,7 +32,6 @@
* SUCH DAMAGE.
*
* @(#)tty.h 8.1 (Berkeley) 6/4/93
* $FreeBSD$
*/
/*
@ -457,14 +456,15 @@ typedef struct {
typedef unsigned char ttychar_t[NN_IO][C_NCC];
protected int tty_init(EditLine *);
protected void tty_end(EditLine *);
protected int tty_stty(EditLine *, int, const Char **);
protected int tty_rawmode(EditLine *);
protected int tty_cookedmode(EditLine *);
protected int tty_quotemode(EditLine *);
protected int tty_noquotemode(EditLine *);
protected void tty_bind_char(EditLine *, int);
libedit_private int tty_init(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;

View file

@ -1,4 +1,4 @@
/* $NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $ */
/* $NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@ -37,11 +37,9 @@
#if 0
static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93";
#else
__RCSID("$NetBSD: vi.c,v 1.55 2016/03/02 19:24:20 christos Exp $");
__RCSID("$NetBSD: vi.c,v 1.63 2019/07/23 10:18:52 christos Exp $");
#endif
#endif /* not lint && not SCCSID */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/*
* vi.c: Vi mode commands.
@ -56,15 +54,16 @@ __FBSDID("$FreeBSD$");
#include "el.h"
#include "common.h"
#include "emacs.h"
#include "fcns.h"
#include "vi.h"
private el_action_t cv_action(EditLine *, wint_t);
private el_action_t cv_paste(EditLine *, wint_t);
static el_action_t cv_action(EditLine *, wint_t);
static el_action_t cv_paste(EditLine *, wint_t);
/* cv_action():
* Handle vi actions.
*/
private el_action_t
static el_action_t
cv_action(EditLine *el, wint_t c)
{
@ -96,7 +95,7 @@ cv_action(EditLine *el, wint_t c)
/* cv_paste():
* Paste previous deletion before or after the cursor
*/
private el_action_t
static el_action_t
cv_paste(EditLine *el, wint_t c)
{
c_kill_t *k = &el->el_chared.c_kill;
@ -105,7 +104,7 @@ cv_paste(EditLine *el, wint_t c)
if (k->buf == NULL || len == 0)
return CC_ERROR;
#ifdef DEBUG_PASTE
(void) fprintf(el->el_errfile, "Paste: \"" FSTARSTR "\"\n", (int)len,
(void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len,
k->buf);
#endif
@ -128,7 +127,7 @@ cv_paste(EditLine *el, wint_t c)
* Vi paste previous deletion to the right of the cursor
* [p]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -141,7 +140,7 @@ vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi paste previous deletion to the left of the cursor
* [P]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -154,7 +153,7 @@ vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the previous space delimited word
* [B]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -179,7 +178,7 @@ vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the previous word
* [b]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -204,7 +203,7 @@ vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the next space delimited word
* [W]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -228,7 +227,7 @@ vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the next word
* [w]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -252,7 +251,7 @@ vi_next_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi change case of character under the cursor and advance one character
* [~]
*/
protected el_action_t
libedit_private el_action_t
vi_change_case(EditLine *el, wint_t c)
{
int i;
@ -263,10 +262,10 @@ vi_change_case(EditLine *el, wint_t c)
for (i = 0; i < el->el_state.argument; i++) {
c = *el->el_line.cursor;
if (Isupper(c))
*el->el_line.cursor = Tolower(c);
else if (Islower(c))
*el->el_line.cursor = Toupper(c);
if (iswupper(c))
*el->el_line.cursor = towlower(c);
else if (iswlower(c))
*el->el_line.cursor = towupper(c);
if (++el->el_line.cursor >= el->el_line.lastchar) {
el->el_line.cursor--;
@ -283,7 +282,7 @@ vi_change_case(EditLine *el, wint_t c)
* Vi change prefix command
* [c]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -300,7 +299,7 @@ vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter insert mode at the beginning of line
* [I]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -316,7 +315,7 @@ vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi replace character under the cursor with the next character typed
* [r]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -335,7 +334,7 @@ vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter replace mode
* [R]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -351,7 +350,7 @@ vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi replace character under the cursor and enter insert mode
* [s]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -366,7 +365,7 @@ vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi substitute entire line
* [S]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -384,7 +383,7 @@ vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi change to end of line
* [C]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -402,7 +401,7 @@ vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter insert mode
* [i]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_insert(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -417,7 +416,7 @@ vi_insert(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter insert mode after the cursor
* [a]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_add(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -442,7 +441,7 @@ vi_add(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter insert mode at end of line
* [A]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -458,7 +457,7 @@ vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi delete prefix command
* [d]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -471,7 +470,7 @@ vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the end of the current space delimited word
* [E]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -495,7 +494,7 @@ vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the end of the current word
* [e]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_end_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -519,7 +518,7 @@ vi_end_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi undo last change
* [u]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_undo(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -546,7 +545,7 @@ vi_undo(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi enter command mode (use alternative key bindings)
* [<ESC>]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -571,7 +570,7 @@ vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the beginning of line
* [0]
*/
protected el_action_t
libedit_private el_action_t
vi_zero(EditLine *el, wint_t c)
{
@ -591,7 +590,7 @@ vi_zero(EditLine *el, wint_t c)
* Vi move to previous character (backspace)
* [^H] in insert mode only
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -609,7 +608,7 @@ vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi list choices for completion or indicate end of file if empty line
* [^D]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_list_or_eof(EditLine *el, wint_t c)
{
@ -646,11 +645,11 @@ vi_list_or_eof(EditLine *el, wint_t c)
* Vi cut from beginning of line to cursor
* [^U]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__)))
{
Char *kp, *cp;
wchar_t *kp, *cp;
cp = el->el_line.buffer;
kp = el->el_chared.c_kill.buf;
@ -667,7 +666,7 @@ vi_kill_line_prev(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi search history previous
* [?]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -680,7 +679,7 @@ vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi search history next
* [/]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -693,7 +692,7 @@ vi_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi repeat current search in the same search direction
* [n]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -710,7 +709,7 @@ vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__)))
* [N]
*/
/*ARGSUSED*/
protected el_action_t
libedit_private el_action_t
vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -727,7 +726,7 @@ vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the character specified next
* [f]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -739,7 +738,7 @@ vi_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move to the character specified previous
* [F]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -751,7 +750,7 @@ vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move up to the character specified next
* [t]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -763,7 +762,7 @@ vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi move up to the character specified previous
* [T]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -775,7 +774,7 @@ vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi repeat current character search in the same search direction
* [;]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -789,7 +788,7 @@ vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi repeat current character search in the opposite search direction
* [,]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -807,22 +806,22 @@ vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi go to matching () {} or []
* [%]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_match(EditLine *el, wint_t c __attribute__((__unused__)))
{
const Char match_chars[] = STR("()[]{}");
Char *cp;
const wchar_t match_chars[] = L"()[]{}";
wchar_t *cp;
size_t delta, i, count;
Char o_ch, c_ch;
wchar_t o_ch, c_ch;
*el->el_line.lastchar = '\0'; /* just in case */
i = Strcspn(el->el_line.cursor, match_chars);
i = wcscspn(el->el_line.cursor, match_chars);
o_ch = el->el_line.cursor[i];
if (o_ch == 0)
return CC_ERROR;
delta = (size_t)(Strchr(match_chars, o_ch) - match_chars);
delta = (size_t)(wcschr(match_chars, o_ch) - match_chars);
c_ch = match_chars[delta ^ 1];
count = 1;
delta = 1 - (delta & 1) * 2;
@ -854,7 +853,7 @@ vi_match(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi undo all changes to line
* [U]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -868,7 +867,7 @@ vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__)))
* [|]
* NB netbsd vi goes to screen column 'n', posix says nth character
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_to_column(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -882,7 +881,7 @@ vi_to_column(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi yank to end of line
* [Y]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -896,7 +895,7 @@ vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi yank
* [y]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_yank(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -908,7 +907,7 @@ vi_yank(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi comment out current command
* [#]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -926,7 +925,7 @@ vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__)))
* NB: posix implies that we should enter insert mode, however
* this is against historical precedent...
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_alias(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -944,7 +943,7 @@ vi_alias(EditLine *el, wint_t c __attribute__((__unused__)))
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));
el_wpush(el, ct_decode_string(alias_text, &el->el_scratch));
return CC_NORM;
}
@ -952,7 +951,7 @@ vi_alias(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi go to specified history file line.
* [G]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -961,7 +960,7 @@ vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__)))
if (el->el_history.eventno == 0) {
(void) Strncpy(el->el_history.buf, el->el_line.buffer,
(void) wcsncpy(el->el_history.buf, el->el_line.buffer,
EL_BUFSIZ);
el->el_history.last = el->el_history.buf +
(el->el_line.lastchar - el->el_line.buffer);
@ -997,7 +996,7 @@ vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi edit history line with vi
* [v]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -1008,7 +1007,7 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
char *cp = NULL;
size_t len;
Char *line = NULL;
wchar_t *line = NULL;
if (el->el_state.doingarg) {
if (vi_to_history_line(el, 0) == CC_ERROR)
@ -1020,15 +1019,15 @@ 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;
Strncpy(line, el->el_line.buffer, len);
wcsncpy(line, el->el_line.buffer, len);
line[len] = '\0';
ct_wcstombs(cp, line, TMP_BUFSIZ - 1);
wcstombs(cp, line, TMP_BUFSIZ - 1);
cp[TMP_BUFSIZ - 1] = '\0';
len = strlen(cp);
write(fd, cp, len);
@ -1050,7 +1049,7 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
if (st > 0) {
cp[st] = '\0';
len = (size_t)(el->el_line.limit - el->el_line.buffer);
len = ct_mbstowcs(el->el_line.buffer, cp, len);
len = mbstowcs(el->el_line.buffer, cp, len);
if (len > 0 && el->el_line.buffer[len - 1] == '\n')
--len;
}
@ -1081,27 +1080,27 @@ vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
* Who knows where this one came from!
* '_' in vi means 'entire current line', so 'cc' is a synonym for 'c_'
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_history_word(EditLine *el, wint_t c __attribute__((__unused__)))
{
const Char *wp = HIST_FIRST(el);
const Char *wep, *wsp;
const wchar_t *wp = HIST_FIRST(el);
const wchar_t *wep, *wsp;
int len;
Char *cp;
const Char *lim;
wchar_t *cp;
const wchar_t *lim;
if (wp == NULL)
return CC_ERROR;
wep = wsp = NULL;
do {
while (Isspace(*wp))
while (iswspace(*wp))
wp++;
if (*wp == 0)
break;
wsp = wp;
while (*wp && !Isspace(*wp))
while (*wp && !iswspace(*wp))
wp++;
wep = wp;
} while ((!el->el_state.doingarg || --el->el_state.argument > 0)
@ -1131,7 +1130,7 @@ vi_history_word(EditLine *el, wint_t c __attribute__((__unused__)))
* Vi redo last non-motion command
* [.]
*/
protected el_action_t
libedit_private el_action_t
/*ARGSUSED*/
vi_redo(EditLine *el, wint_t c __attribute__((__unused__)))
{
@ -1149,7 +1148,7 @@ vi_redo(EditLine *el, wint_t c __attribute__((__unused__)))
/* sanity */
r->pos = r->lim - 1;
r->pos[0] = 0;
FUN(el,push)(el, r->buf);
el_wpush(el, r->buf);
}
el->el_state.thiscmd = r->cmd;

View file

@ -117,7 +117,7 @@ cwalk(FILE *fp)
host[sizeof(host) - 1] = '\0';
if ((user = getlogin()) == NULL) {
struct passwd *pw;
user = (pw = getpwuid(getuid())) == NULL ? pw->pw_name :
user = (pw = getpwuid(getuid())) != NULL ? pw->pw_name :
"<unknown>";
}

View file

@ -1,4 +1,4 @@
/* $NetBSD: only.c,v 1.2 2013/02/05 00:59:03 christos Exp $ */
/* $NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(lint)
__RCSID("$NetBSD: only.c,v 1.2 2013/02/05 00:59:03 christos Exp $");
__RCSID("$NetBSD: only.c,v 1.3 2017/09/07 04:04:13 nakayama Exp $");
#endif
#include <sys/param.h>
@ -89,11 +89,14 @@ static void
hash_insert(char *str, uint32_t h)
{
struct hentry *e;
char *x;
if ((e = malloc(sizeof(*e))) == NULL)
mtree_err("memory allocation error");
if ((x = strdup(str)) == NULL)
mtree_err("memory allocation error");
e->str = str;
e->str = x;
e->hash = h;
e->next = table[h];
table[h] = e;
@ -110,10 +113,7 @@ fill(char *str)
*ptr = '\0';
if (!hash_find(str, &h)) {
char *x = strdup(str);
if (x == NULL)
mtree_err("memory allocation error");
hash_insert(x, h);
hash_insert(str, h);
fill(str);
}
*ptr = '/';
@ -135,6 +135,7 @@ load_only(const char *fname)
err(1, "Duplicate entry %s", line);
hash_insert(line, h);
fill(line);
free(line);
}
fclose(fp);

View file

@ -145,7 +145,7 @@ compare_nodes(NODE *n1, NODE *n2, char const *path)
return (1);
}
if (n1->type != n2->type) {
differs = 0;
differs = F_TYPE;
mismatch(n1, n2, differs, path);
return (1);
}

View file

@ -187,7 +187,8 @@ ATF_TC_BODY(regcomp_too_big, tc)
struct rlimit limit;
#if defined(__i386__)
atf_tc_skip("https://bugs.freebsd.org/237450");
if (atf_tc_get_config_var_as_bool_wd(tc, "ci", false))
atf_tc_skip("https://bugs.freebsd.org/237450");
#endif
limit.rlim_cur = limit.rlim_max = 256 * 1024 * 1024;

View file

@ -411,6 +411,41 @@ netbsd6_nonemptydir_body()
FLAVOR=netbsd6 nonemptydir_body
}
atf_test_case mtree_specspec_type
mtree_specspec_type_head()
{
atf_set "descr" "Test that spec comparisons detect type changes"
}
mtree_specspec_type_body()
{
mkdir testdir
touch testdir/bar
mtree -c -p testdir > mtree1.spec
if [ ! -f mtree1.spec ]; then
atf_fail "mtree failed"
fi
rm -f testdir/bar
ln -s foo testdir/bar
# uid change is expected to be ignored as done in -C
chown -h operator testdir/bar
mtree -c -p testdir > mtree2.spec
if [ ! -f mtree2.spec ]; then
atf_fail "mtree failed"
fi
atf_check -s ignore -o save:output \
-x "mtree -f mtree1.spec -f mtree2.spec"
if ! cut -f 3 output | egrep -q "bar file" || \
! cut -f 3 output | egrep -q "bar link"; then
atf_fail "mtree did not detect type change"
fi
}
atf_init_test_cases()
{
@ -423,6 +458,7 @@ atf_init_test_cases()
atf_add_test_case mtree_ignore
atf_add_test_case mtree_merge
atf_add_test_case mtree_nonemptydir
atf_add_test_case mtree_specspec_type
atf_add_test_case netbsd6_create
atf_add_test_case netbsd6_check

View file

@ -1,5 +1,80 @@
News for the tz database
Release 2019c - 2019-09-11 08:59:48 -0700
Briefly:
Fiji observes DST from 2019-11-10 to 2020-01-12.
Norfolk Island starts observing Australian-style DST.
Changes to future timestamps
Fiji's next DST transitions will be 2019-11-10 and 2020-01-12
instead of 2019-11-03 and 2020-01-19. (Thanks to Raymond Kumar.)
Adjust future guesses accordingly.
Norfolk Island will observe Australian-style DST starting in
spring 2019. The first transition is on 2019-10-06. (Thanks to
Kyle Czech and Michael Deckers.)
Changes to past timestamps
Many corrections to time in Turkey from 1940 through 1985.
(Thanks to Oya Vulaş via Alois Treindl, and to Kıvanç Yazan.)
The Norfolk Island 1975-03-02 transition was at 02:00 standard
time, not 02:00 DST. (Thanks to Michael Deckers.)
South Korea observed DST from 1948 through 1951. Although this
info was supposed to appear in release 2014j, a typo inadvertently
suppressed the change. (Thanks to Alois Treindl.)
Detroit observed DST in 1967 and 1968 following the US DST rules,
except that its 1967 DST began on June 14 at 00:01. (Thanks to
Alois Treindl for pointing out that the old data entries were
probably wrong.)
Fix several errors in pre-1970 transitions in Perry County, IN.
(Thanks to Alois Triendl for pointing out the 1967/9 errors.)
Edmonton did not observe DST in 1967 or 1969. In 1946 Vancouver
ended DST on 09-29 not 10-13, and Vienna ended DST on 10-07 not
10-06. In 1945 Königsberg (now Kaliningrad) switched from +01/+02
to +02/+03 on 04-10 not 01-01, and its +02/+03 is abbreviated
EET/EEST, not CET/CEST. (Thanks to Alois Triendl.) In 1946
Königsberg switched to +03 on 04-07 not 01-01.
In 1946 Louisville switched from CST to CDT on 04-28 at 00:01, not
01-01 at 00:00. (Thanks to Alois Treindl and Michael Deckers.)
Also, it switched from CST to CDT on 1950-04-30, not 1947-04-27.
The 1892-05-01 transition in Brussels was at 00:17:30, not at noon.
(Thanks to Michael Deckers.)
Changes to past time zone abbreviations and DST flags
Hong Kong Winter Time, observed from 1941-10-01 to 1941-12-25,
is now flagged as DST and is abbreviated HKWT not HKT.
Changes to code
leapseconds.awk now relies only on its input data, rather than
also relying on its comments. (Inspired by code from Dennis
Ferguson and Chris Woodbury.)
The code now defends against CRLFs in leap-seconds.list.
(Thanks to Brian Inglis and Chris Woodbury.)
Changes to documentation and commentary
theory.html discusses leap seconds. (Thanks to Steve Summit.)
Nashville's newspapers dueled about the time of day in the 1950s.
(Thanks to John Seigenthaler.)
Liechtenstein observed Swiss DST in 1941/2.
(Thanks to Alois Treindl.)
Release 2019b - 2019-07-01 00:09:53 -0700
Briefly:

View file

@ -8,7 +8,7 @@
# tz@iana.org for general use in the future). For more, please see
# the file CONTRIBUTING in the tz distribution.
# From Paul Eggert (2018-06-19):
# From Paul Eggert (2019-07-11):
#
# Unless otherwise specified, the source for data through 1990 is:
# Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
@ -47,13 +47,13 @@
# 7:00 WIB west Indonesia (Waktu Indonesia Barat)
# 8:00 WITA central Indonesia (Waktu Indonesia Tengah)
# 8:00 CST China
# 8:00 PST PDT* Philippine Standard Time
# 8:00 HKT HKST Hong Kong (HKWT* for Winter Time in late 1941)
# 8:00 PST PDT* Philippines
# 8:30 KST KDT Korea when at +0830
# 9:00 WIT east Indonesia (Waktu Indonesia Timur)
# 9:00 JST JDT Japan
# 9:00 KST KDT Korea when at +09
# 9:30 ACST Australian Central Standard Time
# *I invented the abbreviation PDT; see "Philippines" below.
# *I invented the abbreviations HKWT and PDT; see below.
# Otherwise, these tables typically use numeric abbreviations like +03
# and +0330 for integer hour and minute UT offsets. Although earlier
# editions invented alphabetic time zone abbreviations for every
@ -653,6 +653,15 @@ Zone Asia/Urumqi 5:50:20 - LMT 1928
# * 1941-09-30, Hong Kong Daily Press, Winter Time Warning.
# https://i.imgur.com/dge4kFJ.png
# From Paul Eggert (2019-07-11):
# "Hong Kong winter time" is considered to be daylight saving.
# "Hong Kong had adopted daylight saving on June 15 as a wartime measure,
# clocks moving forward one hour until October 1, when they would be put back
# by just half an hour for 'Hong Kong Winter time', so that daylight saving
# operated year round." -- Low Z. The longest day: when wartime Hong Kong
# introduced daylight saving. South China Morning Post. 2019-06-28.
# https://www.scmp.com/magazines/post-magazine/short-reads/article/3016281/longest-day-when-wartime-hong-kong-introduced
# From P Chan (2018-12-31):
# * According to the Hong Kong Daylight-Saving Regulations, 1941, the
# 1941 spring-forward transition was at 03:00.
@ -754,7 +763,7 @@ Rule HK 1979 only - Oct 21 3:30 0 -
Zone Asia/Hong_Kong 7:36:42 - LMT 1904 Oct 30 0:36:42
8:00 - HKT 1941 Jun 15 3:00
8:00 1:00 HKST 1941 Oct 1 4:00
8:30 - HKT 1941 Dec 25
8:00 0:30 HKWT 1941 Dec 25
9:00 - JST 1945 Nov 18 2:00
8:00 HK HK%sT
@ -2419,7 +2428,7 @@ Rule ROK 1987 1988 - Oct Sun>=8 3:00 0 S
Zone Asia/Seoul 8:27:52 - LMT 1908 Apr 1
8:30 - KST 1912 Jan 1
9:00 - JST 1945 Sep 8
9:00 - KST 1954 Mar 21
9:00 ROK K%sT 1954 Mar 21
8:30 ROK K%sT 1961 Aug 10
9:00 ROK K%sT
Zone Asia/Pyongyang 8:23:00 - LMT 1908 Apr 1
@ -3604,7 +3613,7 @@ Zone Asia/Tashkent 4:37:11 - LMT 1924 May 2
# and in South Vietnam in particular (after 1954):
# To 07:00 on 1911-05-01.
# To 08:00 on 1942-12-31 at 23:00.
# To 09:00 in 1945-03-14 at 23:00.
# To 09:00 on 1945-03-14 at 23:00.
# To 07:00 on 1945-09-02 in Vietnam.
# To 08:00 on 1947-04-01 in French-controlled Indochina.
# To 07:00 on 1955-07-01 in South Vietnam.

View file

@ -367,13 +367,18 @@ Zone Indian/Cocos 6:27:40 - LMT 1900
# From Raymond Kumar (2018-07-13):
# http://www.fijitimes.com/government-approves-2018-daylight-saving/
# ... The daylight saving period will end at 3am on Sunday January 13, 2019.
#
# From Paul Eggert (2018-07-15):
# For now, guess DST from 02:00 the first Sunday in November to 03:00
# the first Sunday on or after January 13. January transitions reportedly
# From Paul Eggert (2019-08-06):
# Today Raymond Kumar reported the Government of Fiji Gazette Supplement No. 27
# (2019-08-02) said that Fiji observes DST "commencing at 2.00 am on
# Sunday, 10 November 2019 and ending at 3.00 am on Sunday, 12 January 2020."
# For now, guess DST from 02:00 the second Sunday in November to 03:00
# the first Sunday on or after January 12. January transitions reportedly
# depend on when school terms start. Although the guess is ad hoc, it matches
# transitions since late 2014 and seems more likely to match future
# practice than guessing no DST.
# transitions planned this year and seems more likely to match future practice
# than guessing no DST.
# From Michael Deckers (2019-08-06):
# https://www.laws.gov.fj/LawsAsMade/downloadfile/848
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Fiji 1998 1999 - Nov Sun>=1 2:00 1:00 -
@ -384,8 +389,9 @@ Rule Fiji 2010 2013 - Oct Sun>=21 2:00 1:00 -
Rule Fiji 2011 only - Mar Sun>=1 3:00 0 -
Rule Fiji 2012 2013 - Jan Sun>=18 3:00 0 -
Rule Fiji 2014 only - Jan Sun>=18 2:00 0 -
Rule Fiji 2014 max - Nov Sun>=1 2:00 1:00 -
Rule Fiji 2015 max - Jan Sun>=13 3:00 0 -
Rule Fiji 2014 2018 - Nov Sun>=1 2:00 1:00 -
Rule Fiji 2015 max - Jan Sun>=12 3:00 0 -
Rule Fiji 2019 max - Nov Sun>=8 2:00 1:00 -
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Fiji 11:55:44 - LMT 1915 Oct 26 # Suva
12:00 Fiji +12/+13
@ -604,10 +610,11 @@ Zone Pacific/Niue -11:19:40 - LMT 1901 # Alofi
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Pacific/Norfolk 11:11:52 - LMT 1901 # Kingston
11:12 - +1112 1951
11:30 - +1130 1974 Oct 27 02:00
11:30 1:00 +1230 1975 Mar 2 02:00
11:30 - +1130 2015 Oct 4 02:00
11:00 - +11
11:30 - +1130 1974 Oct 27 02:00s
11:30 1:00 +1230 1975 Mar 2 02:00s
11:30 - +1130 2015 Oct 4 02:00s
11:00 - +11 2019 Jul
11:00 AN +11/+12
# Palau (Belau)
# Zone NAME STDOFF RULES FORMAT [UNTIL]
@ -1875,12 +1882,21 @@ Zone Pacific/Wallis 12:15:20 - LMT 1901
# ... at 12.30 am (by legal time in New South Wales) on 4 October 2015.
# http://www.norfolkisland.gov.nf/nia/MediaRelease/Media%20Release%20Norfolk%20Island%20Standard%20Time%20Change.pdf
# From Paul Eggert (2015-09-23):
# From Paul Eggert (2019-08-28):
# Transitions before 2015 are from timeanddate.com, which consulted
# the Norfolk Island Museum and the Australian Bureau of Meteorology's
# Norfolk Island station, and found no record of Norfolk observing DST
# other than in 1974/5. See:
# https://www.timeanddate.com/time/australia/norfolk-island.html
# However, disagree with timeanddate about the 1975-03-02 transition;
# timeanddate has 02:00 but 02:00s corresponds to what the NSW law said
# (thanks to Michael Deckers).
# Norfolk started observing Australian DST in spring 2019.
# From Kyle Czech (2019-08-13):
# https://www.legislation.gov.au/Details/F2018L01702
# From Michael Deckers (2019-08-14):
# https://www.legislation.gov.au/Details/F2019C00010
# Palau
# See commentary for Micronesia.

View file

@ -507,19 +507,35 @@ Zone Asia/Muscat 3:54:24 - LMT 1920
#Zone Asia/Panaji [not enough info to complete]
# Cambodia
# From Paul Eggert (2014-10-11):
# See Asia/Ho_Chi_Minh for the source for most of this data. Also, guess
# (1) Cambodia reverted to UT +07 on 1945-09-02, when Vietnam did, and
# (2) they also reverted to +07 on 1953-11-09, the date of independence.
# These guesses are probably wrong but they're better than guessing no
# transitions there.
# From an adoptive daughter of the late Cambodian ruler Prince Sihanouk,
# via Alois Treindl (2019-08-08):
#
# King Sihanouk said that, during the Japanese occupation, starting with
# what historians refer to as "le coup de force du 9 mars 1945", Cambodia,
# like the entire French Indochina, used Tokyo time zone. After Japan
# surrendered, 2 September 1945, Cambodia fell under French rule again and
# adopted Hanoi time zone again.
#
# However, on 7 January 1946, Sihanouk and Tioulong managed to obtain a
# status of "internal autonomy" from the government of Charles de Gaulle.
# Although many fields remained under the administration of the French
# (customs, taxes, justice, defence, foreign affairs, etc.), the Cambodian
# administration was responsible for religious matters and traditional
# celebrations, which included our calendar and time. The time zone was GMT
# + 7 and _no_ DST was applied.
#
# After Sihanouk and Tioulong achieved full independence, on 9 November 1953,
# GMT + 7 was maintained.
# From Paul Eggert (2019-08-26):
# See Asia/Ho_Chi_Minh for the source for most of rest of this data.
Zone Asia/Phnom_Penh 6:59:40 - LMT 1906 Jul 1
7:06:30 - PLMT 1911 May 1
7:00 - +07 1942 Dec 31 23:00
8:00 - +08 1945 Mar 14 23:00
9:00 - +09 1945 Sep 2
7:00 - +07 1947 Apr 1
8:00 - +08 1953 Nov 9
7:00 - +07
# Israel
@ -646,7 +662,7 @@ Zone Europe/Tiraspol 1:58:32 - LMT 1880
# Liechtenstein
Zone Europe/Vaduz 0:38:04 - LMT 1894 Jun
1:00 - CET 1981
1:00 Swiss CE%sT 1981
1:00 EU CE%sT
# Croatia

View file

@ -821,11 +821,16 @@ Zone Europe/Andorra 0:06:04 - LMT 1901
# Shanks & Pottenger give 02:00, the BEV 00:00. Go with the BEV,
# and guess 02:00 for 1945-04-12.
# From Alois Triendl (2019-07-22):
# In 1946 the end of DST was on Monday, 7 October 1946, at 3:00 am.
# Shanks had this right. Source: Die Weltpresse, 5. Oktober 1946, page 5.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Austria 1920 only - Apr 5 2:00s 1:00 S
Rule Austria 1920 only - Sep 13 2:00s 0 -
Rule Austria 1946 only - Apr 14 2:00s 1:00 S
Rule Austria 1946 1948 - Oct Sun>=1 2:00s 0 -
Rule Austria 1946 only - Oct 7 2:00s 0 -
Rule Austria 1947 1948 - Oct Sun>=1 2:00s 0 -
Rule Austria 1947 only - Apr 6 2:00s 1:00 S
Rule Austria 1948 only - Apr 18 2:00s 1:00 S
Rule Austria 1980 only - Apr 6 0:00 1:00 S
@ -875,15 +880,35 @@ Zone Europe/Minsk 1:50:16 - LMT 1880
# Belgium
#
# From Paul Eggert (1997-07-02):
# From Michael Deckers (2019-08-25):
# The exposition in the web page
# https://www.bestor.be/wiki/index.php/Voyager_dans_le_temps._L%E2%80%99introduction_de_la_norme_de_Greenwich_en_Belgique
# gives several contemporary sources from which one can conclude that
# the switch in Europe/Brussels on 1892-05-01 was from 00:17:30 to 00:00:00.
#
# From Paul Eggert (2019-08-28):
# This quote helps explain the late-1914 situation:
# In early November 1914, the Germans imposed the time zone used in central
# Europe and forced the inhabitants to set their watches and public clocks
# sixty minutes ahead. Many were reluctant to accept "German time" and
# continued to use "Belgian time" among themselves. Reflecting the spirit of
# resistance that arose in the population, a song made fun of this change....
# The song ended:
# Putting your clock forward
# Will but hasten the happy hour
# When we kick out the Boches!
# See: Pluvinage G. Brussels on German time. Cahiers Bruxellois -
# Brusselse Cahiers. 2014;XLVI(1E):15-38.
# https://www.cairn.info/revue-cahiers-bruxellois-2014-1E-page-15.htm
#
# Entries from 1914 through 1917 are taken from "De tijd in België"
# <https://www.astro.oma.be/GENERAL/INFO/nli001a.html>.
# Entries from 1918 through 1991 are taken from:
# Annuaire de L'Observatoire Royal de Belgique,
# Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
# (Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
# pp 8-9.
# LMT before 1892 was 0:17:30, according to the official journal of Belgium:
# Moniteur Belge, Samedi 30 Avril 1892, N.121.
# Thanks to Pascal Delmoitie for these references.
# Thanks to Pascal Delmoitie for the 1918/1991 references.
# The 1918 rules are listed for completeness; they apply to unoccupied Belgium.
# Assume Brussels switched to WET in 1918 when the armistice took effect.
#
@ -928,7 +953,7 @@ Rule Belgium 1946 only - May 19 2:00s 1:00 S
Rule Belgium 1946 only - Oct 7 2:00s 0 -
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Brussels 0:17:30 - LMT 1880
0:17:30 - BMT 1892 May 1 12:00 # Brussels MT
0:17:30 - BMT 1892 May 1 00:17:30
0:00 - WET 1914 Nov 8
1:00 - CET 1916 May 1 0:00
1:00 C-Eur CE%sT 1918 Nov 11 11:00u
@ -1627,6 +1652,13 @@ Zone Atlantic/Reykjavik -1:28 - LMT 1908
# advanced to sixty minutes later starting at hour two on 1944-04-02; ...
# Starting at hour three on the date 1944-09-17 standard time will be resumed.
#
# From Alois Triendl (2019-07-02):
# I spent 6 Euros to buy two archive copies of Il Messaggero, a Roman paper,
# for 1 and 2 April 1944. The edition of 2 April has this note: "Tonight at 2
# am, put forward the clock by one hour. Remember that in the night between
# today and Monday the 'ora legale' will come in force again." That makes it
# clear that in Rome the change was on Monday, 3 April 1944 at 2 am.
#
# From Paul Eggert (2016-10-27):
# Go with INRiM for DST rules, except as corrected by Inglis for 1944
# for the Kingdom of Italy. This is consistent with Renzo Baldini.
@ -1774,15 +1806,10 @@ Zone Europe/Riga 1:36:34 - LMT 1880
# From Paul Eggert (2013-09-09):
# Shanks & Pottenger say Vaduz is like Zurich.
# From Alois Treindl (2013-09-18):
# http://www.eliechtensteinensia.li/LIJ/1978/1938-1978/1941.pdf
# ... confirms on p. 6 that Liechtenstein followed Switzerland in 1941 and 1942.
# I ... translate only the last two paragraphs:
# ... during second world war, in the years 1941 and 1942, Liechtenstein
# introduced daylight saving time, adapting to Switzerland. From 1943 on
# central European time was in force throughout the year.
# From a report of the duke's government to the high council,
# regarding the introduction of a time law, of 31 May 1977.
# From Alois Treindl (2019-07-04):
# I was able to access the online archive of the Vaduz paper Vaterland ...
# I could confirm from the paper that Liechtenstein did in fact follow
# the same DST in 1941 and 1942 as Switzerland did.
Link Europe/Zurich Europe/Vaduz
@ -2490,6 +2517,12 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# Europe/Kaliningrad covers...
# 39 RU-KGD Kaliningrad Oblast
# From Paul Eggert (2019-07-25):
# Although Shanks lists 1945-01-01 as the date for transition from
# +01/+02 to +02/+03, more likely this is a placeholder. Guess that
# the transition occurred at 1945-04-10 00:00, which is about when
# Königsberg surrendered to Soviet troops. (Thanks to Alois Triendl.)
# From Paul Eggert (2016-03-18):
# The 1989 transition is from USSR act No. 227 (1989-03-14).
@ -2506,8 +2539,8 @@ Zone Europe/Bucharest 1:44:24 - LMT 1891 Oct
# Moscow on 1991-11-03, switched to Moscow-1 on 1992-01-19.
Zone Europe/Kaliningrad 1:22:00 - LMT 1893 Apr
1:00 C-Eur CE%sT 1945
2:00 Poland CE%sT 1946
1:00 C-Eur CE%sT 1945 Apr 10
2:00 Poland EE%sT 1946 Apr 7
3:00 Russia MSK/MSD 1989 Mar 26 2:00s
2:00 Russia EE%sT 2011 Mar 27 2:00s
3:00 - +03 2014 Oct 26 2:00s
@ -3650,20 +3683,75 @@ Zone Europe/Zurich 0:34:08 - LMT 1853 Jul 16 # See above comment.
# Turkey
# From Alois Treindl (2019-08-12):
# http://www.astrolojidergisi.com/yazsaati.htm has researched the time zone
# history of Turkey, based on newspaper archives and official documents.
# From Paul Eggert (2019-08-28):
# That source (Oya Vulaş, "Türkiye'de Yaz Saati Uygulamaları")
# is used for 1940/1972, where it seems more reliable than our other
# sources.
# From Kıvanç Yazan (2019-08-12):
# http://www.resmigazete.gov.tr/arsiv/14539.pdf#page=24
# 1973-06-03 01:00 -> 02:00, 1973-11-04 02:00 -> 01:00
#
# http://www.resmigazete.gov.tr/arsiv/14829.pdf#page=1
# 1974-03-31 02:00 -> 03:00, 1974-11-03 02:00 -> 01:00
#
# http://www.resmigazete.gov.tr/arsiv/15161.pdf#page=1
# 1975-03-22 02:00 -> 03:00, 1975-11-02 02:00 -> 01:00
#
# http://www.resmigazete.gov.tr/arsiv/15535_1.pdf#page=1
# 1976-03-21 02:00 -> 03:00, 1976-10-31 02:00 -> 01:00
#
# http://www.resmigazete.gov.tr/arsiv/15778.pdf#page=5
# 1977-04-03 02:00 -> 03:00, 1977-10-16 02:00 -> 01:00,
# 1978-04-02 02:00 -> 03:00 (not applied, see below)
# 1978-10-15 02:00 -> 01:00 (not applied, see below)
# 1979-04-01 02:00 -> 03:00 (not applied, see below)
# 1979-10-14 02:00 -> 01:00 (not applied, see below)
#
# http://www.resmigazete.gov.tr/arsiv/16245.pdf#page=17
# This cancels the previous decision, and repeats it only for 1978.
# 1978-04-02 02:00 -> 03:00, 1978-10-15 02:00 -> 01:00
# (not applied due to standard TZ change below)
#
# http://www.resmigazete.gov.tr/arsiv/16331.pdf#page=3
# This decision changes the default longitude for Turkish time zone from 30
# degrees East to 45 degrees East. This means a standard TZ change, from +2
# to +3. This is published & applied on 1978-06-29. At that time, Turkey was
# already on summer time (already on 45E). Hence, this new law just meant an
# "continuous summer time". Note that this was reversed in a few years.
#
# http://www.resmigazete.gov.tr/arsiv/18119_1.pdf#page=1
# 1983-07-31 02:00 -> 03:00 (note that this jumps TZ to +4)
# 1983-10-02 02:00 -> 01:00 (back to +3)
#
# http://www.resmigazete.gov.tr/arsiv/18561.pdf (page 1 and 34)
# At this time, Turkey is still on +3 with no spring-forward on early
# 1984. This decision is published on 10/31/1984. Page 1 declares
# the decision of reverting the "default longitude change". So the
# standard time should go back to +3 (30E). And page 34 explains when
# that will happen: 1984-11-01 02:00 -> 01:00. You can think of this
# as "end of continuous summer time, change of standard time zone".
#
# http://www.resmigazete.gov.tr/arsiv/18713.pdf#page=1
# 1985-04-20 01:00 -> 02:00, 1985-09-28 02:00 -> 01:00
# From Kıvanç Yazan (2016-09-25):
# 1) For 1986-2006, DST started at 01:00 local and ended at 02:00 local, with
# no exceptions.
# 2) 1994's lastSun was overridden with Mar 20 ...
# Here are official papers:
# http://www.resmigazete.gov.tr/arsiv/19032.pdf - page 2 for 1986
# http://www.resmigazete.gov.tr/arsiv/19400.pdf - page 4 for 1987
# http://www.resmigazete.gov.tr/arsiv/19752.pdf - page 15 for 1988
# http://www.resmigazete.gov.tr/arsiv/20102.pdf - page 6 for 1989
# http://www.resmigazete.gov.tr/arsiv/20464.pdf - page 1 for 1990 - 1992
# http://www.resmigazete.gov.tr/arsiv/21531.pdf - page 15 for 1993 - 1995
# http://www.resmigazete.gov.tr/arsiv/21879.pdf - page 1 for overriding 1994
# http://www.resmigazete.gov.tr/arsiv/22588.pdf - page 1 for 1996, 1997
# http://www.resmigazete.gov.tr/arsiv/23286.pdf - page 10 for 1998 - 2000
# http://www.resmigazete.gov.tr/arsiv/19032.pdf#page=2 for 1986
# http://www.resmigazete.gov.tr/arsiv/19400.pdf#page=4 for 1987
# http://www.resmigazete.gov.tr/arsiv/19752.pdf#page=15 for 1988
# http://www.resmigazete.gov.tr/arsiv/20102.pdf#page=6 for 1989
# http://www.resmigazete.gov.tr/arsiv/20464.pdf#page=1 for 1990 - 1992
# http://www.resmigazete.gov.tr/arsiv/21531.pdf#page=15 for 1993 - 1995
# http://www.resmigazete.gov.tr/arsiv/21879.pdf#page=1 for overriding 1994
# http://www.resmigazete.gov.tr/arsiv/22588.pdf#page=1 for 1996, 1997
# http://www.resmigazete.gov.tr/arsiv/23286.pdf#page=10 for 1998 - 2000
# http://www.resmigazete.gov.tr/eskiler/2001/03/20010324.htm#2 - for 2001
# http://www.resmigazete.gov.tr/eskiler/2002/03/20020316.htm#2 - for 2002-2006
# From Paul Eggert (2016-09-25):
@ -3747,46 +3835,36 @@ Rule Turkey 1922 only - Oct 8 0:00 0 -
Rule Turkey 1924 only - May 13 0:00 1:00 S
Rule Turkey 1924 1925 - Oct 1 0:00 0 -
Rule Turkey 1925 only - May 1 0:00 1:00 S
Rule Turkey 1940 only - Jun 30 0:00 1:00 S
Rule Turkey 1940 only - Oct 5 0:00 0 -
Rule Turkey 1940 only - Jul 1 0:00 1:00 S
Rule Turkey 1940 only - Oct 6 0:00 0 -
Rule Turkey 1940 only - Dec 1 0:00 1:00 S
Rule Turkey 1941 only - Sep 21 0:00 0 -
Rule Turkey 1942 only - Apr 1 0:00 1:00 S
# Whitman omits the next two transition and gives 1945 Oct 1;
# go with Shanks & Pottenger.
Rule Turkey 1942 only - Nov 1 0:00 0 -
Rule Turkey 1945 only - Apr 2 0:00 1:00 S
Rule Turkey 1945 only - Oct 8 0:00 0 -
Rule Turkey 1946 only - Jun 1 0:00 1:00 S
Rule Turkey 1946 only - Oct 1 0:00 0 -
Rule Turkey 1947 1948 - Apr Sun>=16 0:00 1:00 S
Rule Turkey 1947 1950 - Oct Sun>=2 0:00 0 -
Rule Turkey 1947 1951 - Oct Sun>=2 0:00 0 -
Rule Turkey 1949 only - Apr 10 0:00 1:00 S
Rule Turkey 1950 only - Apr 19 0:00 1:00 S
Rule Turkey 1950 only - Apr 16 0:00 1:00 S
Rule Turkey 1951 only - Apr 22 0:00 1:00 S
Rule Turkey 1951 only - Oct 8 0:00 0 -
# DST for 15 months; unusual but we'll let it pass.
Rule Turkey 1962 only - Jul 15 0:00 1:00 S
Rule Turkey 1962 only - Oct 8 0:00 0 -
Rule Turkey 1963 only - Oct 30 0:00 0 -
Rule Turkey 1964 only - May 15 0:00 1:00 S
Rule Turkey 1964 only - Oct 1 0:00 0 -
Rule Turkey 1970 1972 - May Sun>=2 0:00 1:00 S
Rule Turkey 1970 1972 - Oct Sun>=2 0:00 0 -
Rule Turkey 1973 only - Jun 3 1:00 1:00 S
Rule Turkey 1973 only - Nov 4 3:00 0 -
Rule Turkey 1973 1976 - Oct Sun>=31 2:00 0 -
Rule Turkey 1974 only - Mar 31 2:00 1:00 S
Rule Turkey 1974 only - Nov 3 5:00 0 -
Rule Turkey 1975 only - Mar 30 0:00 1:00 S
Rule Turkey 1975 1976 - Oct lastSun 0:00 0 -
Rule Turkey 1976 only - Jun 1 0:00 1:00 S
Rule Turkey 1977 1978 - Apr Sun>=1 0:00 1:00 S
Rule Turkey 1977 only - Oct 16 0:00 0 -
Rule Turkey 1979 1980 - Apr Sun>=1 3:00 1:00 S
Rule Turkey 1979 1982 - Oct Mon>=11 0:00 0 -
Rule Turkey 1981 1982 - Mar lastSun 3:00 1:00 S
Rule Turkey 1983 only - Jul 31 0:00 1:00 S
Rule Turkey 1983 only - Oct 2 0:00 0 -
Rule Turkey 1985 only - Apr 20 0:00 1:00 S
Rule Turkey 1985 only - Sep 28 0:00 0 -
Rule Turkey 1975 only - Mar 22 2:00 1:00 S
Rule Turkey 1976 only - Mar 21 2:00 1:00 S
Rule Turkey 1977 1978 - Apr Sun>=1 2:00 1:00 S
Rule Turkey 1977 1978 - Oct Sun>=15 2:00 0 -
Rule Turkey 1978 only - Jun 29 0:00 0 -
Rule Turkey 1983 only - Jul 31 2:00 1:00 S
Rule Turkey 1983 only - Oct 2 2:00 0 -
Rule Turkey 1985 only - Apr 20 1:00s 1:00 S
Rule Turkey 1985 only - Sep 28 1:00s 0 -
Rule Turkey 1986 1993 - Mar lastSun 1:00s 1:00 S
Rule Turkey 1986 1995 - Sep lastSun 1:00s 0 -
Rule Turkey 1994 only - Mar 20 1:00s 1:00 S
@ -3795,8 +3873,8 @@ Rule Turkey 1996 2006 - Oct lastSun 1:00s 0 -
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/Istanbul 1:55:52 - LMT 1880
1:56:56 - IMT 1910 Oct # Istanbul Mean Time?
2:00 Turkey EE%sT 1978 Oct 15
3:00 Turkey +03/+04 1985 Apr 20
2:00 Turkey EE%sT 1978 Jun 29
3:00 Turkey +03/+04 1984 Nov 1 2:00
2:00 Turkey EE%sT 2007
2:00 EU EE%sT 2011 Mar 27 1:00u
2:00 - EET 2011 Mar 28 1:00u

View file

@ -204,10 +204,10 @@
# current -- the update time stamp, the data and the name of the file
# will not change.
#
# Updated through IERS Bulletin C57
# File expires on: 28 December 2019
# Updated through IERS Bulletin C58
# File expires on: 28 June 2020
#
#@ 3786480000
#@ 3802291200
#
2272060800 10 # 1 Jan 1972
2287785600 11 # 1 Jul 1972
@ -252,4 +252,4 @@
# the hash line is also ignored in the
# computation.
#
#h 83c68138 d3650221 07dbbbcd 11fcc859 ced1106a
#h f28827d2 f263b6c3 ec0f19eb a3e0dbf0 97f3fa30

View file

@ -3,36 +3,39 @@
# This file is in the public domain.
# This file is generated automatically from the data in the public-domain
# leap-seconds.list file, which can be copied from
# NIST format leap-seconds.list file, which can be copied from
# <ftp://ftp.nist.gov/pub/time/leap-seconds.list>
# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>
# or <ftp://tycho.usno.navy.mil/pub/ntp/leap-seconds.list>.
# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>.
# For more about leap-seconds.list, please see
# The NTP Timescale and Leap Seconds
# <https://www.eecis.udel.edu/~mills/leap.html>.
# The International Earth Rotation and Reference Systems Service
# The rules for leap seconds are specified in Annex 1 (Time scales) of:
# Standard-frequency and time-signal emissions.
# International Telecommunication Union - Radiocommunication Sector
# (ITU-R) Recommendation TF.460-6 (02/2002)
# <https://www.itu.int/rec/R-REC-TF.460-6-200202-I/>.
# The International Earth Rotation and Reference Systems Service (IERS)
# periodically uses leap seconds to keep UTC to within 0.9 s of UT1
# (which measures the true angular orientation of the earth in space)
# (a proxy for Earth's angle in space as measured by astronomers)
# and publishes leap second data in a copyrighted file
# <https://hpiers.obspm.fr/iers/bul/bulc/Leap_Second.dat>.
# See: Levine J. Coordinated Universal Time and the leap second.
# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995
# <https://ieeexplore.ieee.org/document/7909995>.
# There were no leap seconds before 1972, because the official mechanism
# accounting for the discrepancy between atomic time and the earth's rotation
# did not exist. The first ("1 Jan 1972") data line in leap-seconds.list
# There were no leap seconds before 1972, as no official mechanism
# accounted for the discrepancy between atomic time (TAI) and the earth's
# rotation. The first ("1 Jan 1972") data line in leap-seconds.list
# does not denote a leap second; it denotes the start of the current definition
# of UTC.
# The correction (+ or -) is made at the given time, so lines
# will typically look like:
# Leap YEAR MON DAY 23:59:60 + R/S
# or
# Leap YEAR MON DAY 23:59:59 - R/S
# If the leap second is Rolling (R) the given time is local time (unused here).
# All leap-seconds are Stationary (S) at the given UTC time.
# The correction (+ or -) is made at the given time, so in the unlikely
# event of a negative leap second, a line would look like this:
# Leap YEAR MON DAY 23:59:59 - S
# Typical lines look like this:
# Leap YEAR MON DAY 23:59:60 + S
Leap 1972 Jun 30 23:59:60 + S
Leap 1972 Dec 31 23:59:60 + S
Leap 1973 Dec 31 23:59:60 + S
@ -62,8 +65,8 @@ Leap 2015 Jun 30 23:59:60 + S
Leap 2016 Dec 31 23:59:60 + S
# POSIX timestamps for the data in this file:
#updated 1467936000
#expires 1577491200
#updated 1467936000 (2016-07-08 00:00:00 UTC)
#expires 1593302400 (2020-06-28 00:00:00 UTC)
# Updated through IERS Bulletin C57
# File expires on: 28 December 2019
# Updated through IERS Bulletin C58
# File expires on: 28 June 2020

View file

@ -1,43 +1,59 @@
# Generate the 'leapseconds' file from 'leap-seconds.list'.
# Generate zic format 'leapseconds' from NIST format 'leap-seconds.list'.
# This file is in the public domain.
# This program uses awk arithmetic. POSIX requires awk to support
# exact integer arithmetic only through 10**10, which means for NTP
# timestamps this program works only to the year 2216, which is the
# year 1900 plus 10**10 seconds. However, in practice
# POSIX-conforming awk implementations invariably use IEEE-754 double
# and so support exact integers through 2**53. By the year 2216,
# POSIX will almost surely require at least 2**53 for awk, so for NTP
# timestamps this program should be good until the year 285,428,681
# (the year 1900 plus 2**53 seconds). By then leap seconds will be
# long obsolete, as the Earth will likely slow down so much that
# there will be more than 25 hours per day and so some other scheme
# will be needed.
BEGIN {
print "# Allowance for leap seconds added to each time zone file."
print ""
print "# This file is in the public domain."
print ""
print "# This file is generated automatically from the data in the public-domain"
print "# leap-seconds.list file, which can be copied from"
print "# NIST format leap-seconds.list file, which can be copied from"
print "# <ftp://ftp.nist.gov/pub/time/leap-seconds.list>"
print "# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>"
print "# or <ftp://tycho.usno.navy.mil/pub/ntp/leap-seconds.list>."
print "# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>."
print "# For more about leap-seconds.list, please see"
print "# The NTP Timescale and Leap Seconds"
print "# <https://www.eecis.udel.edu/~mills/leap.html>."
print ""
print "# The International Earth Rotation and Reference Systems Service"
print "# The rules for leap seconds are specified in Annex 1 (Time scales) of:"
print "# Standard-frequency and time-signal emissions."
print "# International Telecommunication Union - Radiocommunication Sector"
print "# (ITU-R) Recommendation TF.460-6 (02/2002)"
print "# <https://www.itu.int/rec/R-REC-TF.460-6-200202-I/>."
print "# The International Earth Rotation and Reference Systems Service (IERS)"
print "# periodically uses leap seconds to keep UTC to within 0.9 s of UT1"
print "# (which measures the true angular orientation of the earth in space)"
print "# (a proxy for Earth's angle in space as measured by astronomers)"
print "# and publishes leap second data in a copyrighted file"
print "# <https://hpiers.obspm.fr/iers/bul/bulc/Leap_Second.dat>."
print "# See: Levine J. Coordinated Universal Time and the leap second."
print "# URSI Radio Sci Bull. 2016;89(4):30-6. doi:10.23919/URSIRSB.2016.7909995"
print "# <https://ieeexplore.ieee.org/document/7909995>."
print ""
print "# There were no leap seconds before 1972, because the official mechanism"
print "# accounting for the discrepancy between atomic time and the earth's rotation"
print "# did not exist. The first (\"1 Jan 1972\") data line in leap-seconds.list"
print "# There were no leap seconds before 1972, as no official mechanism"
print "# accounted for the discrepancy between atomic time (TAI) and the earth's"
print "# rotation. The first (\"1 Jan 1972\") data line in leap-seconds.list"
print "# does not denote a leap second; it denotes the start of the current definition"
print"# of UTC."
print "# of UTC."
print ""
print "# The correction (+ or -) is made at the given time, so lines"
print "# will typically look like:"
print "# Leap YEAR MON DAY 23:59:60 + R/S"
print "# or"
print "# Leap YEAR MON DAY 23:59:59 - R/S"
print ""
print "# If the leap second is Rolling (R) the given time is local time (unused here)."
print "# All leap-seconds are Stationary (S) at the given UTC time."
print "# The correction (+ or -) is made at the given time, so in the unlikely"
print "# event of a negative leap second, a line would look like this:"
print "# Leap YEAR MON DAY 23:59:59 - S"
print "# Typical lines look like this:"
print "# Leap YEAR MON DAY 23:59:60 + S"
monthabbr[ 1] = "Jan"
monthabbr[ 2] = "Feb"
@ -51,45 +67,34 @@ BEGIN {
monthabbr[10] = "Oct"
monthabbr[11] = "Nov"
monthabbr[12] = "Dec"
for (i in monthabbr) {
monthnum[monthabbr[i]] = i
monthlen[i] = 31
}
monthlen[2] = 28
monthlen[4] = monthlen[6] = monthlen[9] = monthlen[11] = 30
# Strip trailing CR, in case the input has CRLF form a la NIST.
RS = "\r?\n"
sstamp_init()
}
/^#\tUpdated through/ || /^#\tFile expires on:/ {
/^#[ \t]*[Uu]pdated through/ || /^#[ \t]*[Ff]ile expires on/ {
last_lines = last_lines $0 "\n"
}
/^#[$][ \t]/ { updated = $2 }
/^#[@][ \t]/ { expires = $2 }
/^#/ { next }
/^[ \t]*#/ { next }
{
NTP_timestamp = $1
TAI_minus_UTC = $2
hash_mark = $3
one = $4
month = $5
year = $6
if (old_TAI_minus_UTC) {
if (old_TAI_minus_UTC < TAI_minus_UTC) {
sign = "23:59:60\t+"
} else {
sign = "23:59:59\t-"
}
m = monthnum[month] - 1
if (m == 0) {
year--;
m = 12
}
month = monthabbr[m]
day = monthlen[m]
day += m == 2 && year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)
printf "Leap\t%s\t%s\t%s\t%s\tS\n", year, month, day, sign
sstamp_to_ymdhMs(NTP_timestamp - 1, ss_NTP)
printf "Leap\t%d\t%s\t%d\t%s\tS\n", \
ss_year, monthabbr[ss_month], ss_mday, sign
}
old_TAI_minus_UTC = TAI_minus_UTC
}
@ -102,7 +107,117 @@ END {
print ""
print "# POSIX timestamps for the data in this file:"
printf "#updated %s\n", updated - epoch_minus_NTP
printf "#expires %s\n", expires - epoch_minus_NTP
sstamp_to_ymdhMs(updated, ss_NTP)
printf "#updated %d (%.4d-%.2d-%.2d %.2d:%.2d:%.2d UTC)\n", \
updated - epoch_minus_NTP, \
ss_year, ss_month, ss_mday, ss_hour, ss_min, ss_sec
sstamp_to_ymdhMs(expires, ss_NTP)
printf "#expires %d (%.4d-%.2d-%.2d %.2d:%.2d:%.2d UTC)\n", \
expires - epoch_minus_NTP, \
ss_year, ss_month, ss_mday, ss_hour, ss_min, ss_sec
printf "\n%s", last_lines
}
# sstamp_to_ymdhMs - convert seconds timestamp to date and time
#
# Call as:
#
# sstamp_to_ymdhMs(sstamp, epoch_days)
#
# where:
#
# sstamp - is the seconds timestamp.
# epoch_days - is the timestamp epoch in Gregorian days since 1600-03-01.
# ss_NTP is appropriate for an NTP sstamp.
#
# Both arguments should be nonnegative integers.
# On return, the following variables are set based on sstamp:
#
# ss_year - Gregorian calendar year
# ss_month - month of the year (1-January to 12-December)
# ss_mday - day of the month (1-31)
# ss_hour - hour (0-23)
# ss_min - minute (0-59)
# ss_sec - second (0-59)
# ss_wday - day of week (0-Sunday to 6-Saturday)
#
# The function sstamp_init should be called prior to using sstamp_to_ymdhMs.
function sstamp_init()
{
# Days in month N, where March is month 0 and January month 10.
ss_mon_days[ 0] = 31
ss_mon_days[ 1] = 30
ss_mon_days[ 2] = 31
ss_mon_days[ 3] = 30
ss_mon_days[ 4] = 31
ss_mon_days[ 5] = 31
ss_mon_days[ 6] = 30
ss_mon_days[ 7] = 31
ss_mon_days[ 8] = 30
ss_mon_days[ 9] = 31
ss_mon_days[10] = 31
# Counts of days in a Gregorian year, quad-year, century, and quad-century.
ss_year_days = 365
ss_quadyear_days = ss_year_days * 4 + 1
ss_century_days = ss_quadyear_days * 25 - 1
ss_quadcentury_days = ss_century_days * 4 + 1
# Standard day epochs, suitable for epoch_days.
# ss_MJD = 94493
# ss_POSIX = 135080
ss_NTP = 109513
}
function sstamp_to_ymdhMs(sstamp, epoch_days, \
quadcentury, century, quadyear, year, month, day)
{
ss_hour = int(sstamp / 3600) % 24
ss_min = int(sstamp / 60) % 60
ss_sec = sstamp % 60
# Start with a count of days since 1600-03-01 Gregorian.
day = epoch_days + int(sstamp / (24 * 60 * 60))
# Compute a year-month-day date with days of the month numbered
# 0-30, months (March-February) numbered 0-11, and years that start
# start March 1 and end after the last day of February. A quad-year
# starts on March 1 of a year evenly divisible by 4 and ends after
# the last day of February 4 years later. A century starts on and
# ends before March 1 in years evenly divisible by 100.
# A quad-century starts on and ends before March 1 in years divisible
# by 400. While the number of days in a quad-century is a constant,
# the number of days in each other time period can vary by 1.
# Any variation is in the last day of the time period (there might
# or might not be a February 29) where it is easy to deal with.
quadcentury = int(day / ss_quadcentury_days)
day -= quadcentury * ss_quadcentury_days
ss_wday = (day + 3) % 7
century = int(day / ss_century_days)
century -= century == 4
day -= century * ss_century_days
quadyear = int(day / ss_quadyear_days)
day -= quadyear * ss_quadyear_days
year = int(day / ss_year_days)
year -= year == 4
day -= year * ss_year_days
for (month = 0; month < 11; month++) {
if (day < ss_mon_days[month])
break
day -= ss_mon_days[month]
}
# Convert the date to a conventional day of month (1-31),
# month (1-12, January-December) and Gregorian year.
ss_mday = day + 1
if (month <= 9) {
ss_month = month + 3
} else {
ss_month = month - 9
year++
}
ss_year = 1600 + quadcentury * 400 + century * 100 + quadyear * 4 + year
}

View file

@ -406,6 +406,31 @@ Zone America/New_York -4:56:02 - LMT 1883 Nov 18 12:03:58
# From Paul Eggert (2015-12-25):
# Assume this practice predates 1970, so Fort Pierre can use America/Chicago.
# From Paul Eggert (2015-04-06):
# In 1950s Nashville a public clock had dueling faces, one for conservatives
# and the other for liberals; the two sides didn't agree about the time of day.
# I haven't found a photo of this clock, nor have I tracked down the TIME
# magazine report cited below, but here's the story as told by the late
# American journalist John Seigenthaler, who was there:
#
# "The two [newspaper] owners held strongly contrasting political and
# ideological views. Evans was a New South liberal, Stahlman an Old South
# conservative, and their two papers frequently clashed editorially, often on
# the same day.... In the 1950s as the state legislature was grappling with
# the question of whether to approve daylight saving time for the entire state,
# TIME magazine reported:
#
# "'The Nashville Banner and The Nashville Tennessean rarely agree on anything
# but the time of day - and last week they couldn't agree on that.'
#
# "It was all too true. The clock on the front of the building had two faces -
# The Tennessean side of the building facing west, the other, east. When it
# was high noon Banner time, it was 11 a.m. Tennessean time."
#
# Seigenthaler J. For 100 years, Tennessean had it covered.
# The Tennessean 2007-05-11, republished 2015-04-06.
# https://www.tennessean.com/story/insider/extras/2015/04/06/archives-seigenthaler-for-100-years-the-tennessean-had-it-covered/25348545/
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Chicago 1920 only - Jun 13 2:00 1:00 D
Rule Chicago 1920 1921 - Oct lastSun 2:00 0 S
@ -945,21 +970,21 @@ Zone America/Indiana/Vincennes -5:50:07 - LMT 1883 Nov 18 12:09:53
-5:00 US E%sT
#
# Perry County, Indiana, switched from eastern to central time in April 2006.
# From Alois Triendl (2019-07-09):
# The Indianapolis News, Friday 27 October 1967 states that Perry County
# returned to CST. It went again to EST on 27 April 1969, as documented by the
# Indianapolis star of Saturday 26 April.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Perry 1946 only - Apr lastSun 2:00 1:00 D
Rule Perry 1946 only - Sep lastSun 2:00 0 S
Rule Perry 1953 1954 - Apr lastSun 2:00 1:00 D
Rule Perry 1953 1959 - Sep lastSun 2:00 0 S
Rule Perry 1955 only - May 1 0:00 1:00 D
Rule Perry 1955 1960 - Sep lastSun 2:00 0 S
Rule Perry 1956 1963 - Apr lastSun 2:00 1:00 D
Rule Perry 1960 only - Oct lastSun 2:00 0 S
Rule Perry 1961 only - Sep lastSun 2:00 0 S
Rule Perry 1962 1963 - Oct lastSun 2:00 0 S
Rule Perry 1961 1963 - Oct lastSun 2:00 0 S
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Indiana/Tell_City -5:47:03 - LMT 1883 Nov 18 12:12:57
-6:00 US C%sT 1946
-6:00 Perry C%sT 1964 Apr 26 2:00
-5:00 - EST 1969
-5:00 - EST 1967 Oct 29 2:00
-6:00 US C%sT 1969 Apr 27 2:00
-5:00 US E%sT 1971
-5:00 - EST 2006 Apr 2 2:00
-6:00 US C%sT
@ -1035,16 +1060,27 @@ Zone America/Indiana/Vevay -5:40:16 - LMT 1883 Nov 18 12:19:44
# clear how this matched civil time in Louisville, so for now continue
# to assume Louisville switched at noon new local time, like New York.
#
# From Michael Deckers (2019-08-06):
# From the contemporary source given by Alois Treindl,
# the switch in Louisville on 1946-04-28 was on 00:01
# From Paul Eggert (2019-08-26):
# That source was the Louisville Courier-Journal, 1946-04-27, p 4.
# Shanks gives 02:00 for all 20th-century transition times in Louisville.
# Evidently this is wrong for spring 1946. Although also likely wrong
# for other dates, we have no data.
#
# Part of Kentucky left its clocks alone in 1974.
# This also includes Clark, Floyd, and Harrison counties in Indiana.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
Rule Louisville 1921 only - May 1 2:00 1:00 D
Rule Louisville 1921 only - Sep 1 2:00 0 S
Rule Louisville 1941 1961 - Apr lastSun 2:00 1:00 D
Rule Louisville 1941 only - Apr lastSun 2:00 1:00 D
Rule Louisville 1941 only - Sep lastSun 2:00 0 S
Rule Louisville 1946 only - Apr lastSun 0:01 1:00 D
Rule Louisville 1946 only - Jun 2 2:00 0 S
Rule Louisville 1950 1961 - Apr lastSun 2:00 1:00 D
Rule Louisville 1950 1955 - Sep lastSun 2:00 0 S
Rule Louisville 1956 1960 - Oct lastSun 2:00 0 S
Rule Louisville 1956 1961 - Oct lastSun 2:00 0 S
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone America/Kentucky/Louisville -5:43:02 - LMT 1883 Nov 18 12:16:58
-6:00 US C%sT 1921
@ -1134,18 +1170,19 @@ Zone America/Kentucky/Monticello -5:39:24 - LMT 1883 Nov 18 12:20:36
# one hour in 1914." This change is not in Shanks. We have no more
# info, so omit this for now.
#
# From Paul Eggert (2017-07-26):
# Although Shanks says Detroit observed DST in 1967 from 06-14 00:01
# until 10-29 00:01, I now see multiple reports that this is incorrect.
# For example, according to a 50-year anniversary report about the 1967
# Detroit riots and a major-league doubleheader on 1967-07-23, "By the time
# the last fly ball of the doubleheader settled into the glove of leftfielder
# Lenny Green, it was after 7 p.m. Detroit did not observe daylight saving
# time, so light was already starting to fail. Twilight was made even deeper
# by billowing columns of smoke that ascended in an unbroken wall north of the
# ballpark." See: Dow B. Detroit '67: As violence unfolded, Tigers played two
# at home vs. Yankees. Detroit Free Press 2017-07-23.
# https://www.freep.com/story/sports/mlb/tigers/2017/07/23/detroit-tigers-1967-riot-new-york-yankees/499951001/
# From Paul Eggert (2019-07-06):
# Due to a complicated set of legal maneuvers, in 1967 Michigan did
# not start daylight saving time when the rest of the US did.
# Instead, it began DST on Jun 14 at 00:01. This was big news:
# the Detroit Free Press reported it at the top of Page 1 on
# 1967-06-14, in an article "State Adjusting to Switch to Fast Time"
# by Gary Blonston, above an article about Thurgood Marshall's
# confirmation to the US Supreme Court. Although Shanks says Detroit
# observed DST until 1967-10-29 00:01, that time of day seems to be
# incorrect, as the Free Press later said DST ended in Michigan at the
# same time as the rest of the US. Also, although Shanks reports no DST in
# Detroit in 1968, it did observe DST that year; in the November 1968
# election Michigan voters narrowly repealed DST, effective 1969.
#
# Most of Michigan observed DST from 1973 on, but was a bit late in 1975.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER
@ -1156,7 +1193,9 @@ Zone America/Detroit -5:32:11 - LMT 1905
-6:00 - CST 1915 May 15 2:00
-5:00 - EST 1942
-5:00 US E%sT 1946
-5:00 Detroit E%sT 1973
-5:00 Detroit E%sT 1967 Jun 14 0:01
-5:00 US E%sT 1969
-5:00 - EST 1973
-5:00 US E%sT 1975
-5:00 - EST 1975 Apr 27 2:00
-5:00 US E%sT
@ -1205,6 +1244,12 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
#
# Other sources occasionally used include:
#
# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
# <https://www.jstor.org/stable/1774359>.
#
# Pearce C. The Great Daylight Saving Time Controversy.
# Australian Ebook Publisher. 2017. ISBN 978-1-925516-96-8.
#
# Edward W. Whitman, World Time Differences,
# Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
# which I found in the UCLA library.
@ -1213,9 +1258,6 @@ Zone America/Menominee -5:50:27 - LMT 1885 Sep 18 12:00
# <http://cs.ucla.edu/~eggert/The-Waste-of-Daylight-19th.pdf>
# [PDF] (1914-03)
#
# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
# <https://www.jstor.org/stable/1774359>.
#
# See the 'europe' file for Greenland.
# Canada
@ -1857,9 +1899,8 @@ Zone America/Winnipeg -6:28:36 - LMT 1887 Jul 16
# Willett (1914-03) notes that DST "has been in operation ... in the
# City of Moose Jaw, Saskatchewan, for one year."
# From Paul Eggert (2019-04-26):
# Chris Pearce's book "The Great Daylight Saving Time Controversy" (2017)
# says that Regina observed DST in 1914-1917. No dates and times,
# From Paul Eggert (2019-07-25):
# Pearce's book says Regina observed DST in 1914-1917. No dates and times,
# unfortunately. It also says that in 1914 Saskatoon observed DST
# from 1 June to 6 July, and that DST was also tried out in Davidson,
# Melfort, and Prince Albert.
@ -1939,6 +1980,19 @@ Zone America/Swift_Current -7:11:20 - LMT 1905 Sep
# Alberta
# From Alois Triendl (2019-07-19):
# There was no DST in Alberta in 1967... Calgary Herald, 29 April 1967.
# 1969, no DST, from Edmonton Journal 18 April 1969
#
# From Paul Eggert (2019-07-25):
# Pearce's book says that Alberta's 1948 Daylight Saving Act required
# Mountain Standard Time without DST, and that "anyone who broke that law
# could be fined up to $25 and costs". There seems to be no record of
# anybody paying the fine. The law was not changed until an August 1971
# plebiscite reinstituted DST in 1972. This story is also mentioned in:
# Boyer JP. Forcing Choice: The Risky Reward of Referendums. Dundum. 2017.
# ISBN 978-1459739123.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Edm 1918 1919 - Apr Sun>=8 2:00 1:00 D
Rule Edm 1918 only - Oct 27 2:00 0 S
@ -1951,10 +2005,6 @@ Rule Edm 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule Edm 1945 only - Sep lastSun 2:00 0 S
Rule Edm 1947 only - Apr lastSun 2:00 1:00 D
Rule Edm 1947 only - Sep lastSun 2:00 0 S
Rule Edm 1967 only - Apr lastSun 2:00 1:00 D
Rule Edm 1967 only - Oct lastSun 2:00 0 S
Rule Edm 1969 only - Apr lastSun 2:00 1:00 D
Rule Edm 1969 only - Oct lastSun 2:00 0 S
Rule Edm 1972 1986 - Apr lastSun 2:00 1:00 D
Rule Edm 1972 2006 - Oct lastSun 2:00 0 S
# Zone NAME STDOFF RULES FORMAT [UNTIL]
@ -2037,8 +2087,20 @@ Zone America/Edmonton -7:33:52 - LMT 1906 Sep
# been on MST (-0700) like Dawson Creek since it advanced its clocks on
# 2015-03-08.
#
# From Paul Eggert (2015-09-23):
# From Paul Eggert (2019-07-25):
# Shanks says Fort Nelson did not observe DST in 1946, unlike Vancouver.
# Alois Triendl confirmed this on 07-22, citing the 1946-04-27 Vancouver Daily
# Province. He also cited the 1946-09-28 Victoria Daily Times, which said
# that Vancouver, Victoria, etc. "change at midnight Saturday"; for now,
# guess they meant 02:00 Sunday since 02:00 was common practice in Vancouver.
#
# Early Vancouver, Volume Four, by Major J.S. Matthews, V.D., 2011 edition
# says that a 1922 plebiscite adopted DST, but a 1923 plebiscite rejected it.
# http://former.vancouver.ca/ctyclerk/archives/digitized/EarlyVan/SearchEarlyVan/Vol4pdf/MatthewsEarlyVancouverVol4_DaylightSavings.pdf
# A catalog entry for a newspaper clipping seems to indicate that Vancouver
# observed DST in 1941 from 07-07 through 09-27; see
# https://searcharchives.vancouver.ca/daylight-saving-1918-starts-again-july-7-1941-start-d-s-sept-27-end-of-d-s-1941
# We have no further details, so omit them for now.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Vanc 1918 only - Apr 14 2:00 1:00 D
@ -2047,7 +2109,7 @@ Rule Vanc 1942 only - Feb 9 2:00 1:00 W # War
Rule Vanc 1945 only - Aug 14 23:00u 1:00 P # Peace
Rule Vanc 1945 only - Sep 30 2:00 0 S
Rule Vanc 1946 1986 - Apr lastSun 2:00 1:00 D
Rule Vanc 1946 only - Oct 13 2:00 0 S
Rule Vanc 1946 only - Sep 29 2:00 0 S
Rule Vanc 1947 1961 - Sep lastSun 2:00 0 S
Rule Vanc 1962 2006 - Oct lastSun 2:00 0 S
# Zone NAME STDOFF RULES FORMAT [UNTIL]

View file

@ -1230,14 +1230,8 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# From Juan Correa (2016-12-04):
# Magallanes region ... will keep DST (UTC -3) all year round....
# http://www.soychile.cl/Santiago/Sociedad/2016/12/04/433428/Bachelet-firmo-el-decreto-para-establecer-un-horario-unico-para-la-Region-de-Magallanes.aspx
#
# From Deborah Goldsmith (2017-01-19):
# http://www.diariooficial.interior.gob.cl/publicaciones/2017/01/17/41660/01/1169626.pdf
# From Paul Eggert (2017-01-19):
# The above says the Magallanes change expires 2019-05-11 at 24:00,
# so in theory, they will revert to -04/-03 after that, which means
# they will switch from -03 to -04 one hour after Santiago does that day.
# For now, assume that they will not revert.
# From Juan Correa (2018-08-13):
# As of moments ago, the Ministry of Energy in Chile has announced the new
@ -1258,6 +1252,11 @@ Zone America/Rio_Branco -4:31:12 - LMT 1914
# So we extend the new rules on Saturdays at 24:00 mainland time indefinitely.
# From Juan Correa (2019-02-04):
# http://www.diariooficial.interior.gob.cl/publicaciones/2018/11/23/42212/01/1498738.pdf
# From Paul Eggert (2019-09-01):
# The above says the Magallanes exception expires 2022-04-02 at 24:00,
# so in theory, they will revert to -04/-03 after that.
# For now, assume that they will not revert,
# since they have extended the expiration date once already.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Chile 1927 1931 - Sep 1 0:00 1:00 -

View file

@ -21,6 +21,7 @@
database</a></li>
<li><a href="#functions">Time and date functions</a></li>
<li><a href="#stability">Interface stability</a></li>
<li><a href="#leapsec">Leap seconds</a></li>
<li><a href="#calendar">Calendrical issues</a></li>
<li><a href="#planets">Time and time zones on other planets</a></li>
</ul>
@ -98,8 +99,9 @@ A <code><abbr>tz</abbr></code> timezone corresponds to a ruleset that can
have more than two changes per year, these changes need not merely
flip back and forth between two alternatives, and the rules themselves
can change at times.
Whether and when a timezone changes its
clock, and even the timezone's notional base offset from UTC, are variable.
Whether and when a timezone changes its clock,
and even the timezone's notional base offset from <abbr>UTC</abbr>,
are variable.
It does not always make sense to talk about a timezone's
"base offset", which is not necessarily a single number.
</p>
@ -428,7 +430,7 @@ in decreasing order of importance:
EET/EEST Eastern European,
GST/GDT Guam,
HST/HDT/HWT/HPT Hawaii,
HKT/HKST Hong Kong,
HKT/HKST/HKWT Hong Kong,
IST India,
IST/GMT Irish,
IST/IDT/IDDT Israel,
@ -972,7 +974,8 @@ an older <code>zic</code>.
that do not fit into the POSIX model.
</li>
<li>
POSIX requires that systems ignore leap seconds.
POSIX requires that <code>time_t</code> clock counts exclude leap
seconds.
</li>
<li>
The <code><abbr>tz</abbr></code> code attempts to support all the
@ -1072,7 +1075,8 @@ an older <code>zic</code>.
where <code>time_t</code> is signed.
</li>
<li>
These functions can account for leap seconds, thanks to Bradley White.
These functions can account for leap seconds;
see <a href="#leapsec">Leap seconds</a> below.
</li>
</ul>
@ -1248,6 +1252,69 @@ between now and the future time.
</p>
</section>
<section>
<h2 id="leapsec">Leap seconds</h2>
<p>
The <code><abbr>tz</abbr></code> code and data can account for leap seconds,
thanks to code contributed by Bradley White.
However, the leap second support of this package is rarely used directly
because POSIX requires leap seconds to be excluded and many
software packages would mishandle leap seconds if they were present.
Instead, leap seconds are more commonly handled by occasionally adjusting
the operating system kernel clock as described in
<a href="tz-link.html#precision">Precision timekeeping</a>,
and this package by default installs a <samp>leapseconds</samp> file
commonly used by
<a href="http://www.ntp.org"><abbr title="Network Time Protocol">NTP</abbr></a>
software that adjusts the kernel clock.
However, kernel-clock twiddling approximates UTC only roughly,
and systems needing more-precise UTC can use this package's leap
second support directly.
</p>
<p>
The directly-supported mechanism assumes that <code>time_t</code>
counts of seconds since the POSIX epoch normally include leap seconds,
as opposed to POSIX <code>time_t</code> counts which exclude leap seconds.
This modified timescale is converted to <abbr>UTC</abbr>
at the same point that time zone and DST adjustments are applied &ndash;
namely, at calls to <code>localtime</code> and analogous functions &ndash;
and the process is driven by leap second information
stored in alternate versions of the <abbr>TZif</abbr> files.
Because a leap second adjustment may be needed even
if no time zone correction is desired,
calls to <code>gmtime</code>-like functions
also need to consult a <abbr>TZif</abbr> file,
conventionally named <samp><abbr>GMT</abbr></samp>,
to see whether leap second corrections are needed.
To convert an application's <code>time_t</code> timestamps to or from
POSIX <code>time_t</code> timestamps (for use when, say,
embedding or interpreting timestamps in portable
<a href="https://en.wikipedia.org/wiki/Tar_(computing)"><code>tar</code></a>
files),
the application can call the utility functions
<code>time2posix</code> and <code>posix2time</code>
included with this package.
</p>
<p>
If the POSIX-compatible <abbr>TZif</abbr> file set is installed
in a directory whose basename is <samp>zoneinfo</samp>, the
leap-second-aware file set is by default installed in a separate
directory <samp>zoneinfo-leaps</samp>.
Although each process can have its own time zone by setting
its <code>TZ</code> environment variable, there is no support for some
processes being leap-second aware while other processes are
POSIX-compatible; the leap-second choice is system-wide.
So if you configure your kernel to count leap seconds, you should also
discard <samp>zoneinfo</samp> and rename <samp>zoneinfo-leaps</samp>
to <samp>zoneinfo</samp>.
Alternatively, you can install just one set of <abbr>TZif</abbr> files
in the first place; see the <code>REDO</code> variable in this package's
<a href="https://en.wikipedia.org/wiki/Makefile">makefile</a>.
</p>
</section>
<section>
<h2 id="calendar">Calendrical issues</h2>
<p>

View file

@ -1 +1 @@
2019b
2019c

View file

@ -7,6 +7,101 @@
https://github.com/openssl/openssl/commits/ and pick the appropriate
release branch.
Changes between 1.1.1c and 1.1.1d [10 Sep 2019]
*) Fixed a fork protection issue. OpenSSL 1.1.1 introduced a rewritten random
number generator (RNG). This was intended to include protection in the
event of a fork() system call in order to ensure that the parent and child
processes did not share the same RNG state. However this protection was not
being used in the default case.
A partial mitigation for this issue is that the output from a high
precision timer is mixed into the RNG state so the likelihood of a parent
and child process sharing state is significantly reduced.
If an application already calls OPENSSL_init_crypto() explicitly using
OPENSSL_INIT_ATFORK then this problem does not occur at all.
(CVE-2019-1549)
[Matthias St. Pierre]
*) For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters, when loading a serialized key
or calling `EC_GROUP_new_from_ecpkparameters()`/
`EC_GROUP_new_from_ecparameters()`.
This prevents bypass of security hardening and performance gains,
especially for curves with specialized EC_METHODs.
By default, if a key encoded with explicit parameters is loaded and later
serialized, the output is still encoded with explicit parameters, even if
internally a "named" EC_GROUP is used for computation.
[Nicola Tuveri]
*) Compute ECC cofactors if not provided during EC_GROUP construction. Before
this change, EC_GROUP_set_generator would accept order and/or cofactor as
NULL. After this change, only the cofactor parameter can be NULL. It also
does some minimal sanity checks on the passed order.
(CVE-2019-1547)
[Billy Bob Brumley]
*) Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey.
An attack is simple, if the first CMS_recipientInfo is valid but the
second CMS_recipientInfo is chosen ciphertext. If the second
recipientInfo decodes to PKCS #1 v1.5 form plaintext, the correct
encryption key will be replaced by garbage, and the message cannot be
decoded, but if the RSA decryption fails, the correct encryption key is
used and the recipient will not notice the attack.
As a work around for this potential attack the length of the decrypted
key must be equal to the cipher default key length, in case the
certifiate is not given and all recipientInfo are tried out.
The old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag.
(CVE-2019-1563)
[Bernd Edlinger]
*) Early start up entropy quality from the DEVRANDOM seed source has been
improved for older Linux systems. The RAND subsystem will wait for
/dev/random to be producing output before seeding from /dev/urandom.
The seeded state is stored for future library initialisations using
a system global shared memory segment. The shared memory identifier
can be configured by defining OPENSSL_RAND_SEED_DEVRANDOM_SHM_ID to
the desired value. The default identifier is 114.
[Paul Dale]
*) Correct the extended master secret constant on EBCDIC systems. Without this
fix TLS connections between an EBCDIC system and a non-EBCDIC system that
negotiate EMS will fail. Unfortunately this also means that TLS connections
between EBCDIC systems with this fix, and EBCDIC systems without this
fix will fail if they negotiate EMS.
[Matt Caswell]
*) Use Windows installation paths in the mingw builds
Mingw isn't a POSIX environment per se, which means that Windows
paths should be used for installation.
(CVE-2019-1552)
[Richard Levitte]
*) Changed DH_check to accept parameters with order q and 2q subgroups.
With order 2q subgroups the bit 0 of the private key is not secret
but DH_generate_key works around that by clearing bit 0 of the
private key for those. This avoids leaking bit 0 of the private key.
[Bernd Edlinger]
*) Significantly reduce secure memory usage by the randomness pools.
[Paul Dale]
*) Revert the DEVRANDOM_WAIT feature for Linux systems
The DEVRANDOM_WAIT feature added a select() call to wait for the
/dev/random device to become readable before reading from the
/dev/urandom device.
It turned out that this change had negative side effects on
performance which were not acceptable. After some discussion it
was decided to revert this feature and leave it up to the OS
resp. the platform maintainer to ensure a proper initialization
during early boot time.
[Matthias St. Pierre]
Changes between 1.1.1b and 1.1.1c [28 May 2019]
*) Add build tests for C++. These are generated files that only do one
@ -75,6 +170,16 @@
(CVE-2019-1543)
[Matt Caswell]
*) Add DEVRANDOM_WAIT feature for Linux systems
On older Linux systems where the getrandom() system call is not available,
OpenSSL normally uses the /dev/urandom device for seeding its CSPRNG.
Contrary to getrandom(), the /dev/urandom device will not block during
early boot when the kernel CSPRNG has not been seeded yet.
To mitigate this known weakness, use select() to wait for /dev/random to
become readable before reading from /dev/urandom.
*) Ensure that SM2 only uses SM3 as digest algorithm
[Paul Yang]
@ -322,7 +427,7 @@
SSL_set_ciphersuites()
[Matt Caswell]
*) Memory allocation failures consistenly add an error to the error
*) Memory allocation failures consistently add an error to the error
stack.
[Rich Salz]
@ -6860,7 +6965,7 @@
reason texts, thereby removing some of the footprint that may not
be interesting if those errors aren't displayed anyway.
NOTE: it's still possible for any application or module to have it's
NOTE: it's still possible for any application or module to have its
own set of error texts inserted. The routines are there, just not
used by default when no-err is given.
[Richard Levitte]
@ -8826,7 +8931,7 @@ des-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k
Changes between 0.9.6g and 0.9.6h [5 Dec 2002]
*) New function OPENSSL_cleanse(), which is used to cleanse a section of
memory from it's contents. This is done with a counter that will
memory from its contents. This is done with a counter that will
place alternating values in each byte. This can be used to solve
two issues: 1) the removal of calls to memset() by highly optimizing
compilers, and 2) cleansing with other values than 0, since those can

View file

@ -87,9 +87,6 @@ my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lx
# linked openssl executable has rather debugging value than
# production quality.
#
# DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items
# provided to stack calls. Generates unique stack functions for
# each possible stack type.
# BN_LLONG use the type 'long long' in crypto/bn/bn.h
# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
# Following are set automatically by this script
@ -145,13 +142,13 @@ my @gcc_devteam_warn = qw(
# -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
# -Wextended-offsetof -- no, needed in CMS ASN1 code
my @clang_devteam_warn = qw(
-Wno-unknown-warning-option
-Wswitch-default
-Wno-parentheses-equality
-Wno-language-extension-token
-Wno-extended-offsetof
-Wconditional-uninitialized
-Wincompatible-pointer-types-discards-qualifiers
-Wno-unknown-warning-option
-Wmissing-variable-declarations
);

View file

@ -98,6 +98,9 @@
$ nmake test
$ nmake install
Note that in order to perform the install step above you need to have
appropriate permissions to write to the installation directory.
If any of these steps fails, see section Installation in Detail below.
This will build and install OpenSSL in the default location, which is:
@ -107,6 +110,12 @@
OpenSSL version number with underscores instead of periods.
Windows: C:\Program Files\OpenSSL or C:\Program Files (x86)\OpenSSL
The installation directory should be appropriately protected to ensure
unprivileged users cannot make changes to OpenSSL binaries or files, or install
engines. If you already have a pre-installed version of OpenSSL as part of
your Operating System it is recommended that you do not overwrite the system
version and instead install to somewhere else.
If you want to install it anywhere else, run config like this:
On Unix:
@ -135,7 +144,10 @@
Don't build with support for deprecated APIs below the
specified version number. For example "--api=1.1.0" will
remove support for all APIS that were deprecated in OpenSSL
version 1.1.0 or below.
version 1.1.0 or below. This is a rather specialized option
for developers. If you just intend to remove all deprecated
APIs entirely (up to the current version), it is easier
to add the 'no-deprecated' option instead (see below).
--cross-compile-prefix=PREFIX
The PREFIX to include in front of commands for your
@ -229,7 +241,7 @@
source exists.
getrandom: Use the L<getrandom(2)> or equivalent system
call.
devrandom: Use the the first device from the DEVRANDOM list
devrandom: Use the first device from the DEVRANDOM list
which can be opened to read random bytes. The
DEVRANDOM preprocessor constant expands to
"/dev/urandom","/dev/random","/dev/srandom" on
@ -908,8 +920,11 @@
$ mms install ! OpenVMS
$ nmake install # Windows
This will install all the software components in this directory
tree under PREFIX (the directory given with --prefix or its
Note that in order to perform the install step above you need to have
appropriate permissions to write to the installation directory.
The above commands will install all the software components in this
directory tree under PREFIX (the directory given with --prefix or its
default):
Unix:
@ -965,6 +980,12 @@
for private key files.
misc Various scripts.
The installation directory should be appropriately protected to ensure
unprivileged users cannot make changes to OpenSSL binaries or files, or
install engines. If you already have a pre-installed version of OpenSSL as
part of your Operating System it is recommended that you do not overwrite
the system version and instead install to somewhere else.
Package builders who want to configure the library for standard
locations, but have the package installed somewhere else so that
it can easily be packaged, can use

View file

@ -5,6 +5,23 @@
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
Major changes between OpenSSL 1.1.1c and OpenSSL 1.1.1d [10 Sep 2019]
o Fixed a fork protection issue (CVE-2019-1549)
o Fixed a padding oracle in PKCS7_dataDecode and CMS_decrypt_set1_pkey
(CVE-2019-1563)
o For built-in EC curves, ensure an EC_GROUP built from the curve name is
used even when parsing explicit parameters
o Compute ECC cofactors if not provided during EC_GROUP construction
(CVE-2019-1547)
o Early start up entropy quality from the DEVRANDOM seed source has been
improved for older Linux systems
o Correct the extended master secret constant on EBCDIC systems
o Use Windows installation paths in the mingw builds (CVE-2019-1552)
o Changed DH_check to accept parameters with order q and 2q subgroups
o Significantly reduce secure memory usage by the randomness pools
o Revert the DEVRANDOM_WAIT feature for Linux systems
Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019]
o Prevent over long nonces in ChaCha20-Poly1305 (CVE-2019-1543)
@ -601,7 +618,7 @@
Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]:
o Give EVP_MAX_MD_SIZE it's old value, except for a FIPS build.
o Give EVP_MAX_MD_SIZE its old value, except for a FIPS build.
Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]:

View file

@ -1,5 +1,5 @@
OpenSSL 1.1.1c 28 May 2019
OpenSSL 1.1.1d 10 Sep 2019
Copyright (c) 1998-2019 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson

View file

@ -40,7 +40,6 @@
#endif
#include <openssl/bn.h>
#include <openssl/ssl.h>
#include "s_apps.h"
#include "apps.h"
#ifdef _WIN32
@ -48,6 +47,14 @@ static int WIN32_rename(const char *from, const char *to);
# define rename(from,to) WIN32_rename((from),(to))
#endif
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
# include <conio.h>
#endif
#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
# define _kbhit kbhit
#endif
typedef struct {
const char *name;
unsigned long flag;

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -444,11 +444,9 @@ void destroy_ui_method(void);
const UI_METHOD *get_ui_method(void);
int chopup_args(ARGS *arg, char *buf);
# ifdef HEADER_X509_H
int dump_cert_text(BIO *out, X509 *x);
void print_name(BIO *out, const char *title, X509_NAME *nm,
unsigned long lflags);
# endif
void print_bignum_var(BIO *, const BIGNUM *, const char*,
int, unsigned char *);
void print_array(BIO *, const char *, int, const unsigned char *);

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -722,7 +722,7 @@ int ca_main(int argc, char **argv)
/*****************************************************************/
if (req || gencrl) {
if (spkac_file != NULL) {
if (spkac_file != NULL && outfile != NULL) {
output_der = 1;
batch = 1;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -421,7 +421,7 @@ int do_fp(BIO *out, unsigned char *buf, BIO *bp, int sep, int binout,
size_t len;
int i;
for (;;) {
while (BIO_pending(bp) || !BIO_eof(bp)) {
i = BIO_read(bp, (char *)buf, BUFSIZE);
if (i < 0) {
BIO_printf(bio_err, "Read Error in %s\n", file);

View file

@ -586,7 +586,7 @@ int enc_main(int argc, char **argv)
if (benc != NULL)
wbio = BIO_push(benc, wbio);
for (;;) {
while (BIO_pending(rbio) || !BIO_eof(rbio)) {
inl = BIO_read(rbio, (char *)buff, bsize);
if (inl <= 0)
break;

View file

@ -1416,9 +1416,11 @@ static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
*q = '\0';
/*
* Skip "GET / HTTP..." requests often used by load-balancers
* Skip "GET / HTTP..." requests often used by load-balancers. Note:
* 'p' was incremented above to point to the first byte *after* the
* leading slash, so with 'GET / ' it is now an empty string.
*/
if (p[1] == '\0')
if (p[0] == '\0')
goto out;
len = urldecode(p);

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -22,7 +22,6 @@
# include <openssl/engine.h>
#endif
#include <openssl/err.h>
#include "s_apps.h"
/* Needed to get the other O_xxx flags. */
#ifdef OPENSSL_SYS_VMS
# include <unixio.h>

View file

@ -838,7 +838,7 @@ static int alg_print(const X509_ALGOR *alg)
goto done;
}
BIO_printf(bio_err, ", Salt length: %d, Cost(N): %ld, "
"Block size(r): %ld, Paralelizm(p): %ld",
"Block size(r): %ld, Parallelism(p): %ld",
ASN1_STRING_length(kdf->salt),
ASN1_INTEGER_get(kdf->costParameter),
ASN1_INTEGER_get(kdf->blockSize),

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -881,9 +881,19 @@ int req_main(int argc, char **argv)
if (text) {
if (x509)
X509_print_ex(out, x509ss, get_nameopt(), reqflag);
ret = X509_print_ex(out, x509ss, get_nameopt(), reqflag);
else
X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
ret = X509_REQ_print_ex(out, req, get_nameopt(), reqflag);
if (ret == 0) {
if (x509)
BIO_printf(bio_err, "Error printing certificate\n");
else
BIO_printf(bio_err, "Error printing certificate request\n");
ERR_print_errors(bio_err);
goto end;
}
}
if (subject) {

View file

@ -1,5 +1,5 @@
/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@ -9,13 +9,7 @@
#include <openssl/opensslconf.h>
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
# include <conio.h>
#endif
#if defined(OPENSSL_SYS_MSDOS) && !defined(_WIN32)
# define _kbhit kbhit
#endif
#include <openssl/ssl.h>
#define PORT "4433"
#define PROTOCOL "tcp"
@ -24,17 +18,15 @@ typedef int (*do_server_cb)(int s, int stype, int prot, unsigned char *context);
int do_server(int *accept_sock, const char *host, const char *port,
int family, int type, int protocol, do_server_cb cb,
unsigned char *context, int naccept, BIO *bio_s_out);
#ifdef HEADER_X509_H
int verify_callback(int ok, X509_STORE_CTX *ctx);
#endif
#ifdef HEADER_SSL_H
int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain, int build_chain);
int ssl_print_sigalgs(BIO *out, SSL *s);
int ssl_print_point_formats(BIO *out, SSL *s);
int ssl_print_groups(BIO *out, SSL *s, int noshared);
#endif
int ssl_print_tmp_key(BIO *out, SSL *s);
int init_client(int *sock, const char *host, const char *port,
const char *bindhost, const char *bindport,
@ -44,13 +36,11 @@ int should_retry(int i);
long bio_dump_callback(BIO *bio, int cmd, const char *argp,
int argi, long argl, long ret);
#ifdef HEADER_SSL_H
void apps_ssl_info_callback(const SSL *s, int where, int ret);
void msg_cb(int write_p, int version, int content_type, const void *buf,
size_t len, SSL *ssl, void *arg);
void tlsext_cb(SSL *s, int client_server, int type, const unsigned char *data,
int len, void *arg);
#endif
int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len);
@ -75,7 +65,6 @@ int args_excert(int option, SSL_EXCERT **pexc);
int load_excert(SSL_EXCERT **pexc);
void print_verify_detail(SSL *s, BIO *bio);
void print_ssl_summary(SSL *s);
#ifdef HEADER_SSL_H
int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str, SSL_CTX *ctx);
int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls,
int crl_download);
@ -86,4 +75,3 @@ int ssl_load_stores(SSL_CTX *ctx, const char *vfyCApath,
void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose);
int set_keylog_file(SSL_CTX *ctx, const char *keylog_file);
void print_ca_names(BIO *bio, SSL *s);
#endif

View file

@ -1525,7 +1525,8 @@ void print_ca_names(BIO *bio, SSL *s)
int i;
if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
if (!SSL_is_server(s))
BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
return;
}

View file

@ -2345,7 +2345,7 @@ int s_client_main(int argc, char **argv)
(void)BIO_flush(fbio);
/*
* The first line is the HTTP response. According to RFC 7230,
* it's formated exactly like this:
* it's formatted exactly like this:
*
* HTTP/d.d ddd Reason text\r\n
*/

Some files were not shown because too many files have changed in this diff Show more