From owner-svn-src-all@freebsd.org Tue Sep 10 13:56:37 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id DD6D3D71C8; Tue, 10 Sep 2019 13:56:37 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 46SRQs6HjMz4Sy7; Tue, 10 Sep 2019 13:56:37 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id A1B9327140; Tue, 10 Sep 2019 13:56:37 +0000 (UTC) (envelope-from bapt@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x8ADubER017467; Tue, 10 Sep 2019 13:56:37 GMT (envelope-from bapt@FreeBSD.org) Received: (from bapt@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x8ADubYs017463; Tue, 10 Sep 2019 13:56:37 GMT (envelope-from bapt@FreeBSD.org) Message-Id: <201909101356.x8ADubYs017463@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: bapt set sender to bapt@FreeBSD.org using -f From: Baptiste Daroussin Date: Tue, 10 Sep 2019 13:56:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-vendor@freebsd.org Subject: svn commit: r352135 - in vendor/NetBSD/libedit/2019-09-10: . TEST readline X-SVN-Group: vendor X-SVN-Commit-Author: bapt X-SVN-Commit-Paths: in vendor/NetBSD/libedit/2019-09-10: . TEST readline X-SVN-Commit-Revision: 352135 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Sep 2019 13:56:37 -0000 Author: bapt Date: Tue Sep 10 13:56:36 2019 New Revision: 352135 URL: https://svnweb.freebsd.org/changeset/base/352135 Log: Tag import of libedit snapshot 2019-09-10 Added: vendor/NetBSD/libedit/2019-09-10/ - copied from r338453, vendor/NetBSD/libedit/dist/ vendor/NetBSD/libedit/2019-09-10/TEST/test_filecompletion.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/TEST/test_filecompletion.c Replaced: vendor/NetBSD/libedit/2019-09-10/TEST/Makefile - copied unchanged from r352134, vendor/NetBSD/libedit/dist/TEST/Makefile vendor/NetBSD/libedit/2019-09-10/chared.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/chared.c vendor/NetBSD/libedit/2019-09-10/chartype.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/chartype.c vendor/NetBSD/libedit/2019-09-10/common.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/common.c vendor/NetBSD/libedit/2019-09-10/editline.3 - copied unchanged from r352134, vendor/NetBSD/libedit/dist/editline.3 vendor/NetBSD/libedit/2019-09-10/el.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/el.c vendor/NetBSD/libedit/2019-09-10/el.h - copied unchanged from r352134, vendor/NetBSD/libedit/dist/el.h vendor/NetBSD/libedit/2019-09-10/eln.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/eln.c vendor/NetBSD/libedit/2019-09-10/filecomplete.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/filecomplete.c vendor/NetBSD/libedit/2019-09-10/hist.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/hist.c vendor/NetBSD/libedit/2019-09-10/history.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/history.c vendor/NetBSD/libedit/2019-09-10/keymacro.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/keymacro.c vendor/NetBSD/libedit/2019-09-10/literal.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/literal.c vendor/NetBSD/libedit/2019-09-10/map.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/map.c vendor/NetBSD/libedit/2019-09-10/parse.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/parse.c vendor/NetBSD/libedit/2019-09-10/read.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/read.c vendor/NetBSD/libedit/2019-09-10/readline.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/readline.c vendor/NetBSD/libedit/2019-09-10/readline/readline.h - copied unchanged from r352134, vendor/NetBSD/libedit/dist/readline/readline.h vendor/NetBSD/libedit/2019-09-10/refresh.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/refresh.c vendor/NetBSD/libedit/2019-09-10/search.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/search.c vendor/NetBSD/libedit/2019-09-10/shlib_version - copied unchanged from r286801, vendor/NetBSD/libedit/dist/shlib_version vendor/NetBSD/libedit/2019-09-10/terminal.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/terminal.c vendor/NetBSD/libedit/2019-09-10/tty.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/tty.c vendor/NetBSD/libedit/2019-09-10/tty.h - copied unchanged from r352134, vendor/NetBSD/libedit/dist/tty.h vendor/NetBSD/libedit/2019-09-10/vi.c - copied unchanged from r352134, vendor/NetBSD/libedit/dist/vi.c Copied: vendor/NetBSD/libedit/2019-09-10/TEST/Makefile (from r352134, vendor/NetBSD/libedit/dist/TEST/Makefile) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/NetBSD/libedit/2019-09-10/TEST/Makefile Tue Sep 10 13:56:36 2019 (r352135, copy of r352134, vendor/NetBSD/libedit/dist/TEST/Makefile) @@ -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 Copied: vendor/NetBSD/libedit/2019-09-10/TEST/test_filecompletion.c (from r352134, vendor/NetBSD/libedit/dist/TEST/test_filecompletion.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/NetBSD/libedit/2019-09-10/TEST/test_filecompletion.c Tue Sep 10 13:56:36 2019 (r352135, copy of r352134, vendor/NetBSD/libedit/dist/TEST/test_filecompletion.c) @@ -0,0 +1,553 @@ +/* $NetBSD: test_filecompletion.c,v 1.5 2019/09/08 05:50:58 abhinav Exp $ */ + +/*- + * Copyright (c) 2017 Abhinav Upadhyay + * 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 +#include +#include +#include +#include +#include +#include + +#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", + {"angtest", NULL}, + L"ls ang\\test " + }, + { + /* test angular bracket inside double quotes: ls "dq_ang */ + L"ls \"dq_ang", + "dq_ang", + {"dq_angtest", NULL}, + L"ls \"dq_angtest\"" + }, + { + /* test angular bracket inside singlq quotes: ls "sq_ang */ + L"ls 'sq_ang", + "sq_ang", + {"sq_angtest", NULL}, + L"ls 'sq_angtest'" + }, + { + /* 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 "}, + L"ls bar\\ \\<=;|&{("; + +/* + * 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; + +} Copied: vendor/NetBSD/libedit/2019-09-10/chared.c (from r352134, vendor/NetBSD/libedit/dist/chared.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ vendor/NetBSD/libedit/2019-09-10/chared.c Tue Sep 10 13:56:36 2019 (r352135, copy of r352134, vendor/NetBSD/libedit/dist/chared.c) @@ -0,0 +1,747 @@ +/* $NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $ */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Christos Zoulas of Cornell University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +#if 0 +static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; +#else +__RCSID("$NetBSD: chared.c,v 1.59 2019/07/23 10:18:52 christos Exp $"); +#endif +#endif /* not lint && not SCCSID */ + +/* + * chared.c: Character editor utilities + */ +#include +#include +#include + +#include "el.h" +#include "common.h" +#include "fcns.h" + +/* value to leave unused in line buffer */ +#define EL_LEAVE 2 + +/* cv_undo(): + * Handle state for the vi undo command + */ +libedit_private void +cv_undo(EditLine *el) +{ + c_undo_t *vu = &el->el_chared.c_undo; + c_redo_t *r = &el->el_chared.c_redo; + size_t size; + + /* Save entire line for undo */ + size = (size_t)(el->el_line.lastchar - el->el_line.buffer); + vu->len = (ssize_t)size; + vu->cursor = (int)(el->el_line.cursor - el->el_line.buffer); + (void)memcpy(vu->buf, el->el_line.buffer, size * sizeof(*vu->buf)); + + /* save command info for redo */ + r->count = el->el_state.doingarg ? el->el_state.argument : 0; + r->action = el->el_chared.c_vcmd.action; + r->pos = r->buf; + r->cmd = el->el_state.thiscmd; + r->ch = el->el_state.thisch; +} + +/* cv_yank(): + * Save yank/delete data for paste + */ +libedit_private void +cv_yank(EditLine *el, const wchar_t *ptr, int size) +{ + c_kill_t *k = &el->el_chared.c_kill; + + (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); + k->last = k->buf + size; +} + + +/* c_insert(): + * Insert num characters + */ +libedit_private void +c_insert(EditLine *el, int num) +{ + wchar_t *cp; + + if (el->el_line.lastchar + num >= el->el_line.limit) { + if (!ch_enlargebufs(el, (size_t)num)) + return; /* can't go past end of buffer */ + } + + if (el->el_line.cursor < el->el_line.lastchar) { + /* if I must move chars */ + for (cp = el->el_line.lastchar; cp >= el->el_line.cursor; cp--) + cp[num] = *cp; + } + el->el_line.lastchar += num; +} + + +/* c_delafter(): + * Delete num characters after the cursor + */ +libedit_private void +c_delafter(EditLine *el, int num) +{ + + if (el->el_line.cursor + num > el->el_line.lastchar) + num = (int)(el->el_line.lastchar - el->el_line.cursor); + + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor, num); + } + + if (num > 0) { + wchar_t *cp; + + for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) + *cp = cp[num]; + + el->el_line.lastchar -= num; + } +} + + +/* c_delafter1(): + * Delete the character after the cursor, do not yank + */ +libedit_private void +c_delafter1(EditLine *el) +{ + wchar_t *cp; + + for (cp = el->el_line.cursor; cp <= el->el_line.lastchar; cp++) + *cp = cp[1]; + + el->el_line.lastchar--; +} + + +/* c_delbefore(): + * Delete num characters before the cursor + */ +libedit_private void +c_delbefore(EditLine *el, int num) +{ + + if (el->el_line.cursor - num < el->el_line.buffer) + num = (int)(el->el_line.cursor - el->el_line.buffer); + + if (el->el_map.current != el->el_map.emacs) { + cv_undo(el); + cv_yank(el, el->el_line.cursor - num, num); + } + + if (num > 0) { + wchar_t *cp; + + for (cp = el->el_line.cursor - num; + &cp[num] <= el->el_line.lastchar; + cp++) + *cp = cp[num]; + + el->el_line.lastchar -= num; + } +} + + +/* c_delbefore1(): + * Delete the character before the cursor, do not yank + */ +libedit_private void +c_delbefore1(EditLine *el) +{ + wchar_t *cp; + + for (cp = el->el_line.cursor - 1; cp <= el->el_line.lastchar; cp++) + *cp = cp[1]; + + el->el_line.lastchar--; +} + + +/* ce__isword(): + * Return if p is part of a word according to emacs + */ +libedit_private int +ce__isword(wint_t p) +{ + return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; +} + + +/* cv__isword(): + * Return if p is part of a word according to vi + */ +libedit_private int +cv__isword(wint_t p) +{ + if (iswalnum(p) || p == L'_') + return 1; + if (iswgraph(p)) + return 2; + return 0; +} + + +/* cv__isWord(): + * Return if p is part of a big word according to vi + */ +libedit_private int +cv__isWord(wint_t p) +{ + return !iswspace(p); +} + + +/* c__prev_word(): + * Find the previous word + */ +libedit_private wchar_t * +c__prev_word(wchar_t *p, wchar_t *low, int n, int (*wtest)(wint_t)) +{ + p--; + + while (n--) { + while ((p >= low) && !(*wtest)(*p)) + p--; + while ((p >= low) && (*wtest)(*p)) + p--; + } + + /* cp now points to one character before the word */ + p++; + if (p < low) + p = low; + /* cp now points where we want it */ + return p; +} + + +/* c__next_word(): + * Find the next word + */ +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)) + p++; + while ((p < high) && (*wtest)(*p)) + p++; + } + if (p > high) + p = high; + /* p now points where we want it */ + return p; +} + +/* cv_next_word(): + * Find the next word vi style + */ +libedit_private wchar_t * +cv_next_word(EditLine *el, wchar_t *p, wchar_t *high, int n, + int (*wtest)(wint_t)) +{ + int test; + + while (n--) { + test = (*wtest)(*p); + while ((p < high) && (*wtest)(*p) == test) + p++; + /* + * vi historically deletes with cw only the word preserving the + * trailing whitespace! This is not what 'w' does.. + */ + if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) + while ((p < high) && iswspace(*p)) + p++; + } + + /* p now points where we want it */ + if (p > high) + return high; + else + return p; +} + + +/* cv_prev_word(): + * Find the previous word vi style + */ +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) && iswspace(*p)) + p--; + test = (*wtest)(*p); + while ((p >= low) && (*wtest)(*p) == test) + p--; + } + p++; + + /* p now points where we want it */ + if (p < low) + return low; + else + return p; +} + + +/* cv_delfini(): + * Finish vi delete action + */ +libedit_private void +cv_delfini(EditLine *el) +{ + int size; + int action = el->el_chared.c_vcmd.action; + + if (action & INSERT) + el->el_map.current = el->el_map.key; + + if (el->el_chared.c_vcmd.pos == 0) + /* sanity */ + return; + + size = (int)(el->el_line.cursor - el->el_chared.c_vcmd.pos); + if (size == 0) + size = 1; + el->el_line.cursor = el->el_chared.c_vcmd.pos; + if (action & YANK) { + if (size > 0) + cv_yank(el, el->el_line.cursor, size); + else + cv_yank(el, el->el_line.cursor + size, -size); + } else { + if (size > 0) { + c_delafter(el, size); + re_refresh_cursor(el); + } else { + c_delbefore(el, -size); + el->el_line.cursor += size; + } + } + el->el_chared.c_vcmd.action = NOP; +} + + +/* cv__endword(): + * Go to the end of this word according to vi + */ +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) && iswspace(*p)) + p++; + + test = (*wtest)(*p); + while ((p < high) && (*wtest)(*p) == test) + p++; + } + p--; + return p; +} + +/* ch_init(): + * Initialize the character editor + */ +libedit_private int +ch_init(EditLine *el) +{ + el->el_line.buffer = el_calloc(EL_BUFSIZ, + sizeof(*el->el_line.buffer)); + if (el->el_line.buffer == NULL) + return -1; + + 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_calloc(EL_BUFSIZ, + sizeof(*el->el_chared.c_undo.buf)); + if (el->el_chared.c_undo.buf == NULL) + return -1; + el->el_chared.c_undo.len = -1; + el->el_chared.c_undo.cursor = 0; + 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; + el->el_chared.c_redo.pos = el->el_chared.c_redo.buf; + el->el_chared.c_redo.lim = el->el_chared.c_redo.buf + EL_BUFSIZ; + el->el_chared.c_redo.cmd = ED_UNASSIGNED; + + el->el_chared.c_vcmd.action = NOP; + el->el_chared.c_vcmd.pos = el->el_line.buffer; + + el->el_chared.c_kill.buf = el_calloc(EL_BUFSIZ, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***