diff --git a/CMakeLists.txt b/CMakeLists.txt index 81c404677..de2125e3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ # List of available modules: CURL DBI DBUS DYNLIB GD2 GTK PDF SDL # -cmake_minimum_required(VERSION 2.6.2) +cmake_minimum_required(VERSION 3.16.3) project(Falcon) diff --git a/apps/faldoc/CMakeLists.txt b/apps/faldoc/CMakeLists.txt index 3e0867f63..7ef40d7b3 100644 --- a/apps/faldoc/CMakeLists.txt +++ b/apps/faldoc/CMakeLists.txt @@ -4,7 +4,7 @@ # CMake configuration file for Feather modules #################################################################### -cmake_minimum_required(VERSION 2.6.2) +cmake_minimum_required(VERSION 3.16.3) project(falcon-app-faldoc) set(FALDOC_DIR "${FALCON_APP_DIR}/faldoc" ) diff --git a/clt/falcon/editline/CMakeLists.txt b/clt/falcon/editline/CMakeLists.txt index 8b51862ad..ed10fbebd 100644 --- a/clt/falcon/editline/CMakeLists.txt +++ b/clt/falcon/editline/CMakeLists.txt @@ -1,26 +1,80 @@ -cmake_minimum_required(VERSION 2.6) -project(Editline) - -find_package(Curses REQUIRED) -set(HAVE_CURSES_H ${CURSES_HAVE_CURSES_H}) -set(HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H} ) - -add_subdirectory(src) -#add_subdirectory(examples) - -include(CheckIncludeFile) -include(CheckFunctionExists) -include(CheckTypeSize) -include(CheckSymbolExists) -check_include_file("sys/cdefs.h" HAVE_SYS_CDEFS_H) -check_include_file("term.h" HAVE_TERM_H) -check_function_exists("getpwuid_r" HAVE_GETPW_R_POSIX) -check_type_size("u_int32_t" U_INT32_T) -check_symbol_exists(alloca alloca.h HAVE_ALLOCA) -set(HAVE_ALLOCA_H ${HAVE_ALLOCA}) +#/# Editline for Falcon + +cmake_minimum_required( VERSION 3.16.3 ) +project( Editline ) + +message( STATUS "Configuring Editline ..." ) + +find_package( Curses REQUIRED ) +set( HAVE_CURSES_H ${CURSES_HAVE_CURSES_H} ) +set( HAVE_NCURSES_H ${CURSES_HAVE_NCURSES_H} ) + +include( CheckIncludeFile ) +include( CheckSymbolExists ) +include( CheckTypeSize ) + +set( CMAKE_REQUIRED_DEFINITIONS + -D_GNU_SOURCE # secure_getenv +) + +# includes +check_include_file( stdint.h HAVE_STDINT_H ) +check_include_file( sys/types.h HAVE_SYS_TYPES_H ) +check_include_file( term.h HAVE_TERM_H ) +check_include_file( termcap.h HAVE_TERMCAP_H ) + +# pwd.h +check_include_file( pwd.h HAVE_PWD_H ) +if ( HAVE_PWD_H ) + # assuming posix.1, we're not checking for draft posix.1 version + check_symbol_exists( getpwnam_r pwd.h HAVE_GETPWNAM_R ) + check_symbol_exists( getpwuid_r pwd.h HAVE_GETPWUID_R ) + if ( HAVE_GETPWNAM_R AND HAVE_GETPWUID_R ) + set( HAVE_GETPW_R_POSIX ON ) + endif() +endif() + +# stdlib.h +check_include_file( stdlib.h HAVE_STDLIB_H ) +if ( HAVE_STDLIB_H ) + check_symbol_exists( __secure_getenv stdlib.h HAVE___SECURE_GETENV ) + check_symbol_exists( reallocarr stdlib.h HAVE_REALLOCARR ) + check_symbol_exists( secure_getenv stdlib.h HAVE_SECURE_GETENV ) +endif() + +# string.h +check_include_file( string.h HAVE_STRING_H ) +if ( HAVE_STRING_H ) + check_symbol_exists( strlcat string.h HAVE_STRLCAT ) + check_symbol_exists( strlcpy string.h HAVE_STRLCPY ) +endif() + +# unistd.h +check_include_file( unistd.h HAVE_UNISTD_H ) +if ( HAVE_UNISTD_H ) + check_symbol_exists( issetugid unistd.h HAVE_ISSETUGID ) +endif() + +# vis.h +check_include_file( vis.h HAVE_VIS_H ) +if ( HAVE_VIS_H ) + check_symbol_exists( vis vis.h HAVE_VIS ) +endif() + +# wchar.h +check_include_file( wchar.h HAVE_WCHAR_H ) +if ( HAVE_WCHAR_H ) + check_symbol_exists( wcsdup wchar.h HAVE_WCSDUP ) +endif() + +# type checks +check_type_size( u_int32_t U_INT32_T ) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h ) - \ No newline at end of file + +add_subdirectory( src ) + +# vi: ts=2 sw=2 et diff --git a/clt/falcon/editline/ChangeLog b/clt/falcon/editline/ChangeLog index 3390301d8..d11a9889e 100644 --- a/clt/falcon/editline/ChangeLog +++ b/clt/falcon/editline/ChangeLog @@ -1,9 +1,270 @@ * See also NetBSD changelog: http://cvsweb.netbsd.org/bsdweb.cgi/src/lib/libedit +2022-10-30 Jess Thrysoee + + * src/sys.h, src/reallocarr.c: Remove unused sys/cdefs.h include, to compile against musl libc + Reported by Matt Boehlke + + * version-info: 0:70:0 + +2022-10-09 Jess Thrysoee + + * version-info: 0:69:0 + + * src/sys.h: Add __sun guard around sys/types.h in sys.h + + * all: sync with upstream source + +2021-09-10 Jess Thrysoee + + * all: sync with upstream source + +2021-07-14 Jess Thrysoee + + * all: sync with upstream source + + * src/histedit.h: Add wcsdup declaration when ifndef HAVE_WCSDUP. Patch by Rainer Jung. + + * examples/wtc1.c: Fix warnings and add missing brace. Patch by Rainer Jung. + +2021-05-22 Jess Thrysoee + + * version-info: 0:66:0 + + * all: sync with upstream source + + * src/el.c: editrc not read on systems without issetugid + Patch by Trevor Cordes + +2021-04-19 Jess Thrysoee + + * version-info: 0:65:0 + + * all: sync with upstream source + + * src/getline.c,src/sys.h: Provide getline.c implementation if not available + Patch by Claes Nästén + + * src/makelist: Use Posix locale; mainly to get ASCII character classes in e.g. `tr` + Patch by Claes Nästén + + * examples/test_filecompletion.c, examples/wtc1.c: err.h not supported by + Solaris + +2021-02-16 Jess Thrysoee + + * version-info: 0:64:0 + + * all: sync with upstream source + +2019-12-31 Jess Thrysoee + + * version-info: 0:63:0 + + * configure.ac: Support -ltinfo as split in newer ncurses + The newer versions of ncurses support building terminfo routines as a split -ltinfo library. + Patch by MichaÅ‚ Górny + +2019-12-11 Jess Thrysoee + + * version-info: 0:62:0 + + * all: sync with upstream source + +2019-10-25 Jess Thrysoee + + * version-info: 0:61:0 + + * all: sync with upstream source + +2019-03-24 Jess Thrysoee + + * version-info: 0:60:0 + + * all: sync with upstream source + +2018-12-09 Jess Thrysoee + + * version-info: 0:59:0 + + * all: sync with upstream source + +2018-05-25 Jess Thrysoee + + * version-info: 0:58:0 + + * all: sync with upstream source + +2017-05-22 Jess Thrysoee + + * version-info: 0:57:0 + + * all: sync with upstream source + + * libedit.pc.in: Ncurses should not be a part of public link interface. + Patch by Yegor Timoshenko + +2017-03-29 Jess Thrysoee + + * version-info: 0:56:0 + + * all: sync with upstream source + +2016-09-03 Jess Thrysoee + + * version-info: 0:55:0 + + * all: sync with upstream source + +2016-06-18 Jess Thrysoee + + * version-info: 0:54:0 + + * all: sync with upstream source + + * deprecate option --enable-widec. + Upstream now always build with unicode (wide-char/UTF-8) support. + +2015-03-25 Jess Thrysoee + + * version-info: 0:53:0 + + * all: sync with upstream source + +2014-10-30 Jess Thrysoee + + * version-info: 0:52:0 + + * all: sync with upstream source + + * configura.ac: Fix posix shell portability issue. Patch by Ryo Onodera. + +2014-06-20 Jess Thrysoee + + * version-info: 0:51:0 + + * all: sync with upstream source + +2014-06-18 Jess Thrysoee + + * version-info: 0:50:0 + + * all: sync with upstream source - add weak alias patches + +2014-06-18 Jess Thrysoee + + * version-info: 0:49:0 + + * all: sync with upstream source. + +2014-02-13 Jess Thrysoee + + * version-info: 0:48:0 + + * all: sync with upstream source. + + * examples/fileman.c: Fix typo. Patch by Kamil Dudka. + + * Makefile.am, configure.ac: Add --enable-examples configure parameter. + Make it possible to enable/disable building of the examples programs. + Patch by James Le Cuirot. + +2013-07-12 Jess Thrysoee + + * version-info: 0:47:0 + + * all: sync with upstream source. + + * examples/fileman.c, examples/tc1.c: fix pedantic compiler warnings + +2013-07-10 Jess Thrysoee + + * version-info: 0:46:0 + + * configure.ac, src/el.c: ~/.editrc was never sourced on Linux. + On Linux issetugid is not available. When unable to determine if + the current process is tainted, we did not trust the HOME environment + variable and therefore could not load ~/.editrc. + Now instead use secure_getenv or a issetugid based implementation of secure_getenv. + Patch by Paolo Tosco. + +2013-06-11 Jess Thrysoee + + * version-info: 0:45:0 + + * configure.ac: fix AM_CONDITIONAL regression for strlcpy, strlcat, vis, + unvis checks. + +2013-06-08 Jess Thrysoee + + * version-info: 0:44:0 + + * configure.ac, src/Makefile.am: Prevent 'ranlib: has no symbols' build + warnings for systems that has strlcpy, strlcat, vis, unvis. + +2013-06-01 Jess Thrysoee + + * version-info: 0:43:0 + + * all: sync with upstream source. + +2012-12-13 Jess Thrysoee + + * version-info: 0:42:0 + + * all: sync with upstream source. + +2012-06-01 Jess Thrysoee + + * version-info: 0:41:0 + + * all: sync with upstream source. + +2012-05-22 Jess Thrysoee + + * version-info: 0:40:0 + + * all: sync with upstream source. + +2012-03-11 Jess Thrysoee + + * version-info: 0:39:0 + + * all: sync with upstream source. + +2011-08-02 Jess Thrysoee + + * version-info: 0:38:0 + + * all: sync with upstream source. + +2011-07-09 Jess Thrysoee + + * version-info: 0:37:0 + + * all: sync with upstream source. + +2011-02-27 Jess Thrysoee + + * version-info: 0:36:0 + + * all: sync with upstream source. + +2010-04-24 Jess Thrysoee + + * version-info: 0:35:0 + + * all: sync with upstream source. + Now with UTF-8 support. To enable this run 'configure --enable-widec'. + For now an UTF-32 encoded wchar_t is required. + This requirement is met on NetBSD, Solaris and OS X for any UTF-8 locale, + and any system that define __STDC_ISO_10646__ (e.g. GNU libc on Linux). + 2009-09-23 Jess Thrysoee + * version-info: 0:34:0 - * all: apply Apple patches from: + * all: apply Apple patches from: http://opensource.apple.com/source/libedit/libedit-11/patches 2009-09-05 Jess Thrysoee @@ -58,7 +319,7 @@ information. * examples/fileman.c: cast stat struct members, st_nlink and st_size, - appropriately (see also 'man 2 stat'). Patch by Alex Elder. + appropriately (see also 'man 2 stat'). Patch by Alex Elder. * all: sync with upstream source. MINOR version is now 11. @@ -136,7 +397,7 @@ * patches/cvs_export.sh: strlcat.c and strlcpy.c was moved to src/common/lib/libc/string in the upstream cvs repository. - * all: sync with upstream source. + * all: sync with upstream source. 2005-10-22 Jess Thrysoee @@ -145,7 +406,7 @@ * patches/*.patch, configure.ac: define SCCSID, undef LIBC_SCCS. Remove fourteen cosmetic patches. - * all: sync with upstream source. + * all: sync with upstream source. 2005-09-11 Jess Thrysoee @@ -170,19 +431,19 @@ * acinclude.m4: added EL_GETPW_R_DRAFT test and use AC_TRY_LINK instead of AC_TRY_COMPILE. Suggested by Norihiko Murase. - * all: sync with upstream source. + * all: sync with upstream source. 2005-08-16 Jess Thrysoee * version-info: 0:13:0 - * all: sync with upstream source. + * all: sync with upstream source. 2005-08-05 Jess Thrysoee * version-info: 0:12:0 - * all: sync with upstream source. + * all: sync with upstream source. 2005-07-24 Jess Thrysoee @@ -213,7 +474,7 @@ * version-info: 0:8:0 - * all: sync with upstream source. + * all: sync with upstream source. 2005-06-01 Jess Thrysoee @@ -224,7 +485,7 @@ * src/readline.c, src/filecomplete.c: Solaris use POSIX draft versions of getpwent_r, getpwnam_r and getpwuid_r which return 'struct passwd *'. Define HAVE_GETPW_R_POSIX if these functions are (non draft) POSIX - compatible. Patch by Julien Torrès. + compatible. Patch by Julien Torrès. 2005-05-28 Jess Thrysoee @@ -257,7 +518,7 @@ * all: sync with upstream source. - * doc/Makefile.am: If mdoc2man fails, remove empty file. Patch by + * doc/Makefile.am: If mdoc2man fails, remove empty file. Patch by Darren Tucker. 2004-10-14 Jess Thrysoee diff --git a/clt/falcon/editline/config.h.cmake b/clt/falcon/editline/config.h.cmake index 07d730446..27564cc00 100644 --- a/clt/falcon/editline/config.h.cmake +++ b/clt/falcon/editline/config.h.cmake @@ -1,38 +1,63 @@ -/* Define to 1 if you have `alloca', as a function or macro. */ -#cmakedefine HAVE_ALLOCA +/* config.h.cmake */ -/* Define to 1 if you have and it should be used (not on Ultrix). - */ -#cmakedefine HAVE_ALLOCA_H - -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ #cmakedefine HAVE_CURSES_H -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_NCURSES_H - -/* Define to 1 if you have getpwnam_r and getpwuid_r that are draft POSIX.1 +/* Define if you have getpwnam_r and getpwuid_r that are draft POSIX.1 versions. */ #cmakedefine HAVE_GETPW_R_DRAFT -/* Define to 1 if you have getpwnam_r and getpwuid_r that are POSIX.1 +/* Define if you have getpwnam_r and getpwuid_r that are POSIX.1 compatible. */ #cmakedefine HAVE_GETPW_R_POSIX -/* Define to 1 if you have the `issetugid' function. */ +/* Define if you have the `issetugid' function. */ #cmakedefine HAVE_ISSETUGID +/* Define if you have the header file. */ +#cmakedefine HAVE_NCURSES_H + +/* Define if you have the `reallocarr' function. */ +#cmakedefine HAVE_REALLOCARR + +/* Define if you have the `secure_getenv' function. */ +#cmakedefine HAVE_SECURE_GETENV + +/* Define if you have the header file. */ +#cmakedefine HAVE_STDINT_H + +/* Define if you have the `strlcat' function. */ +#cmakedefine HAVE_STRLCAT -/* Define to 1 if you have the header file. */ -#cmakedefine HAVE_SYS_CDEFS_H +/* Define if you have the `strlcpy' function. */ +#cmakedefine HAVE_STRLCPY -/* Define to 1 if you have the header file. */ +/* Define if you have the header file. */ +#cmakedefine HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#cmakedefine HAVE_TERMCAP_H + +/* Define if you have the header file. */ #cmakedefine HAVE_TERM_H -/* Define to 1 if the system has the type `u_int32_t'. */ +/* Define if the system has the type `u_int32_t'. */ #cmakedefine HAVE_U_INT32_T -#include -#define SCCSID -#undef LIBC_SCCS +/* Define if you have the `vis' function. */ +#cmakedefine HAVE_VIS + +/* Define if you have the `wcsdup' function. */ +#cmakedefine HAVE_WCSDUP +/* Define if you have the `__secure_getenv' function. */ +#cmakedefine HAVE___SECURE_GETENV + +#ifndef _GNU_SOURCE +# define _GNU_SOURCE +#endif + +#include "sys.h" +#undef SCCSID +#undef LIBC_SCCS +#undef lint diff --git a/clt/falcon/editline/examples/CMakeLists.txt b/clt/falcon/editline/examples/CMakeLists.txt deleted file mode 100644 index e7f45ecdb..000000000 --- a/clt/falcon/editline/examples/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -include_directories(${PROJECT_SOURCE_DIR}/src) - -add_executable(fileman fileman.c) -target_link_libraries(fileman edit) - -add_executable(test test.c) -target_link_libraries(test edit) - -add_executable(maik maik.cpp) -target_link_libraries(maik edit) - -add_executable(iohub iohub.cpp) -target_link_libraries(iohub edit) diff --git a/clt/falcon/editline/examples/fileman.c b/clt/falcon/editline/examples/fileman.c deleted file mode 100644 index f1d81af31..000000000 --- a/clt/falcon/editline/examples/fileman.c +++ /dev/null @@ -1,491 +0,0 @@ -/* fileman.c -- A tiny application which demonstrates how to use the - GNU Readline library. This application interactively allows users - to manipulate files and their modes. - - NOTE: this was taken from the GNU Readline documentation and ported - to libedit. A commad to output the history list was added. - - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* GNU readline -#include -#include -*/ -#include - -void * xmalloc (size_t size); -void too_dangerous (char *caller); -void initialize_readline (); -int execute_line (char *line); -int valid_argument (char *caller, char *arg); - -typedef int rl_icpfunc_t (char *); - -/* The names of functions that actually do the manipulation. */ -int com_list (char *); -int com_view (char *); -int com_history (char *); -int com_rename(char *); -int com_stat(char *); -int com_pwd(char *); -int com_delete(char *); -int com_help(char *); -int com_cd(char *); -int com_quit(char *); - -/* A structure which contains information on the commands this program - can understand. */ - -typedef struct { - char *name; /* User printable name of the function. */ - rl_icpfunc_t *func; /* Function to call to do the job. */ - char *doc; /* Documentation for this function. */ -} COMMAND; - -COMMAND commands[] = { - { "cd", com_cd, "Change to directory DIR" }, - { "delete", com_delete, "Delete FILE" }, - { "help", com_help, "Display this text" }, - { "?", com_help, "Synonym for `help'" }, - { "list", com_list, "List files in DIR" }, - { "ls", com_list, "Synonym for `list'" }, - { "pwd", com_pwd, "Print the current working directory" }, - { "quit", com_quit, "Quit using Fileman" }, - { "rename", com_rename, "Rename FILE to NEWNAME" }, - { "stat", com_stat, "Print out statistics on FILE" }, - { "view", com_view, "View the contents of FILE" }, - { "history", com_history, "List editline history" }, - { (char *)NULL, (rl_icpfunc_t *)NULL, (char *)NULL } -}; - -/* Forward declarations. */ -char *stripwhite (); -COMMAND *find_command (); - -/* The name of this program, as taken from argv[0]. */ -char *progname; - -/* When non-zero, this means the user is done using this program. */ -int done; - -char * -dupstr (char* s) -{ - char *r; - - r = xmalloc (strlen (s) + 1); - strcpy (r, s); - return (r); -} - -int -main (int argc, char **argv) -{ - char *line, *s; - - progname = argv[0]; - - initialize_readline(); /* Bind our completer. */ - - stifle_history(7); - - /* Loop reading and executing lines until the user quits. */ - for ( ; done == 0; ) - { - line = readline ("FileMan: "); - - if (!line) - break; - - /* Remove leading and trailing whitespace from the line. - Then, if there is anything left, add it to the history list - and execute it. */ - s = stripwhite(line); - - if (*s) { - - char* expansion; - int result; - - result = history_expand(s, &expansion); - - if (result < 0 || result == 2) { - fprintf(stderr, "%s\n", expansion); - } else { - add_history(expansion); - execute_line(expansion); - } - free(expansion); - } - - free(line); - } - exit (0); - - return 0; -} - -/* Execute a command line. */ -int -execute_line (char *line) -{ - register int i; - COMMAND *command; - char *word; - - /* Isolate the command word. */ - i = 0; - while (line[i] && isspace (line[i])) - i++; - word = line + i; - - while (line[i] && !isspace (line[i])) - i++; - - if (line[i]) - line[i++] = '\0'; - - command = find_command (word); - - if (!command) - { - fprintf (stderr, "%s: No such command for FileMan.\n", word); - return (-1); - } - - /* Get argument to command, if any. */ - while (isspace (line[i])) - i++; - - word = line + i; - - /* Call the function. */ - return ((*(command->func)) (word)); -} - -/* Look up NAME as the name of a command, and return a pointer to that - command. Return a NULL pointer if NAME isn't a command name. */ -COMMAND * -find_command (char *name) -{ - register int i; - - for (i = 0; commands[i].name; i++) - if (strcmp (name, commands[i].name) == 0) - return (&commands[i]); - - return ((COMMAND *)NULL); -} - -/* Strip whitespace from the start and end of STRING. Return a pointer - into STRING. */ -char * -stripwhite (char *string) -{ - register char *s, *t; - - for (s = string; isspace (*s); s++) - ; - - if (*s == 0) - return (s); - - t = s + strlen (s) - 1; - while (t > s && isspace (*t)) - t--; - *++t = '\0'; - - return s; -} - -/* **************************************************************** */ -/* */ -/* Interface to Readline Completion */ -/* */ -/* **************************************************************** */ - -char *command_generator(const char *, int); -char **fileman_completion(const char *, int, int); - -/* Tell the GNU Readline library how to complete. We want to try to - complete on command names if this is the first word in the line, or - on filenames if not. */ -void -initialize_readline () -{ - /* Allow conditional parsing of the ~/.inputrc file. */ - rl_readline_name = "FileMan"; - - /* Tell the completer that we want a crack first. */ - rl_attempted_completion_function = fileman_completion; -} - -/* Attempt to complete on the contents of TEXT. START and END - bound the region of rl_line_buffer that contains the word to - complete. TEXT is the word to complete. We can use the entire - contents of rl_line_buffer in case we want to do some simple - parsing. Returnthe array of matches, or NULL if there aren't any. */ -char ** -fileman_completion (const char* text, int start, int end) -{ - char **matches; - - matches = (char **)NULL; - - /* If this word is at the start of the line, then it is a command - to complete. Otherwise it is the name of a file in the current - directory. */ - if (start == 0) - /* TODO */ - matches = completion_matches (text, command_generator); - /* matches = rl_completion_matches (text, command_generator); */ - - return (matches); -} - -/* Generator function for command completion. STATE lets us - know whether to start from scratch; without any state - (i.e. STATE == 0), then we start at the top of the list. */ -char * -command_generator (text, state) - const char *text; - int state; -{ - static int list_index, len; - char *name; - - /* If this is a new word to complete, initialize now. This - includes saving the length of TEXT for efficiency, and - initializing the index variable to 0. */ - if (!state) - { - list_index = 0; - len = strlen (text); - } - - /* Return the next name which partially matches from the - command list. */ - while (name = commands[list_index].name) - { - list_index++; - - if (strncmp (name, text, len) == 0) - return (dupstr(name)); - } - - /* If no names matched, then return NULL. */ - return ((char *)NULL); -} - -/* **************************************************************** */ -/* */ -/* FileMan Commands */ -/* */ -/* **************************************************************** */ - -/* String to pass to system (). This is for the LIST, VIEW and RENAME - commands. */ -static char syscom[1024]; - -/* List the file(s) named in arg. */ -int -com_list (char *arg) -{ - if (!arg) - arg = ""; - - sprintf (syscom, "ls -FClg %s", arg); - return (system (syscom)); -} - -int -com_view (char *arg) -{ - if (!valid_argument ("view", arg)) - return 1; - - sprintf (syscom, "more %s", arg); - return (system (syscom)); -} - -int -com_history(char* arg) -{ - HIST_ENTRY *he; - - /* rewind history */ - while (next_history()) - ; - - for (he = current_history(); he != NULL; he = previous_history()) { - printf("%5d %s\n", *((int*)he->data), he->line); - } - - return 0; -} - -int -com_rename (char *arg) -{ - too_dangerous ("rename"); - return (1); -} - -int -com_stat (char *arg) -{ - struct stat finfo; - - if (!valid_argument ("stat", arg)) - return (1); - - if (stat (arg, &finfo) == -1) - { - perror (arg); - return (1); - } - - printf ("Statistics for `%s':\n", arg); - - printf ("%s has %ld link%s, and is %lld byte%s in length.\n", arg, - (long) finfo.st_nlink, - (finfo.st_nlink == 1) ? "" : "s", - (long long) finfo.st_size, - (finfo.st_size == 1) ? "" : "s"); - printf ("Inode Last Change at: %s", ctime (&finfo.st_ctime)); - printf (" Last access at: %s", ctime (&finfo.st_atime)); - printf (" Last modified at: %s", ctime (&finfo.st_mtime)); - return (0); -} - -int -com_delete (char *arg) -{ - too_dangerous ("delete"); - return (1); -} - -/* Print out help for ARG, or for all of the commands if ARG is - not present. */ -int -com_help (char *arg) -{ - register int i; - int printed = 0; - - for (i = 0; commands[i].name; i++) - { - if (!*arg || (strcmp (arg, commands[i].name) == 0)) - { - printf ("%s\t\t%s.\n", commands[i].name, commands[i].doc); - printed++; - } - } - - if (!printed) - { - printf ("No commands match `%s'. Possibilties are:\n", arg); - - for (i = 0; commands[i].name; i++) - { - /* Print in six columns. */ - if (printed == 6) - { - printed = 0; - printf ("\n"); - } - - printf ("%s\t", commands[i].name); - printed++; - } - - if (printed) - printf ("\n"); - } - return (0); -} - -/* Change to the directory ARG. */ -int -com_cd (char *arg) -{ - if (chdir (arg) == -1) - { - perror (arg); - return 1; - } - - com_pwd (""); - return (0); -} - -/* Print out the current working directory. */ -int -com_pwd (char* ignore) -{ - char dir[1024], *s; - - s = (char*)getcwd(dir, sizeof(dir) - 1); - if (s == 0) - { - printf ("Error getting pwd: %s\n", dir); - return 1; - } - - printf ("Current directory is %s\n", dir); - return 0; -} - -/* The user wishes to quit using this program. Just set DONE - non-zero. */ -int -com_quit (char *arg) -{ - done = 1; - return (0); -} - -/* Function which tells you that you can't do this. */ -void -too_dangerous (char *caller) -{ - fprintf (stderr, - "%s: Too dangerous for me to distribute.\n", - caller); - fprintf (stderr, "Write it yourself.\n"); -} - -/* Return non-zero if ARG is a valid argument for CALLER, - else print an error message and return zero. */ -int -valid_argument (char *caller, char *arg) -{ - if (!arg || !*arg) - { - fprintf (stderr, "%s: Argument required.\n", caller); - return (0); - } - - return (1); -} - -void * -xmalloc (size_t size) -{ - register void *value = (void*)malloc(size); - if (value == 0) - fprintf(stderr, "virtual memory exhausted"); - return value; -} - - diff --git a/clt/falcon/editline/examples/foo.cpp b/clt/falcon/editline/examples/foo.cpp deleted file mode 100644 index a894a7ac3..000000000 --- a/clt/falcon/editline/examples/foo.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include -#include - -static char** my_completion(const char*, int ,int); -char* my_generator(const char*,int); - -template -struct FreeGuard { - T* p; - explicit FreeGuard(T* p) : p(p) { } - ~FreeGuard() { free(p); } -}; - -using namespace std; - - -vector cmds; - - -int main() -{ - char const* cmd [] = { "hello", "world", "hell" ,"word", "quit", " "}; - cmds.assign(cmd , cmd + sizeof(cmd)/sizeof(cmd[0]) ); - - char *buf; - - rl_attempted_completion_function = my_completion; - - while(buf = readline("\n >> ")) - { - FreeGuard freeGuard(buf); - //enable auto-complete - rl_bind_key('\t',rl_complete); - - printf("cmd [%s]\n",buf); - if (strcmp(buf,"quit")==0) - break; - - if (buf[0]!=0) - add_history(buf); - } - - return 0; -} - -static int abort_rl(int,int) -{ return _rl_abort_internal(); } - -static char** my_completion( const char * text , int start, int end) -{ - char** matches = 0; - - if (start == 0) - matches = rl_completion_matches (text, &my_generator); - else - rl_bind_key('\t',abort_rl); - - return matches; -} - -char* my_generator(const char* text, int state) -{ - static int list_index, len; - char* ret = 0; - - if (!state) - { - list_index = 0; - len = strlen (text); - } - - while(list_index < cmds.size()) - { - string const& cmd = cmds[list_index++]; - if (cmd.compare(0,len,text) == 0) - { - ret = strdup(cmd.c_str()); - break; - } - } - - return ret; -} diff --git a/clt/falcon/editline/examples/iohub.cpp b/clt/falcon/editline/examples/iohub.cpp deleted file mode 100644 index 81bf29531..000000000 --- a/clt/falcon/editline/examples/iohub.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - -template -struct FreeGuard { - T* p; - explicit FreeGuard(T* p) : p(p) { } - ~FreeGuard() { free(p); } -}; - - -//rl_getc_function -static int my_getc(FILE*) -{ - return getchar(); -} - -int main(int argc, char **argv) -{ - rl_getc_function = my_getc; - char *buf; - while(buf = readline("\n >> ")) - { - FreeGuard freeGuard(buf); - //enable auto-complete - rl_bind_key('\t',rl_complete); - - printf("cmd [%s]\n",buf); - if (strcmp(buf,"quit")==0) - break; - - if (buf[0]!=0) - add_history(buf); - } -} diff --git a/clt/falcon/editline/examples/test.c b/clt/falcon/editline/examples/test.c deleted file mode 100644 index 1008d8a2b..000000000 --- a/clt/falcon/editline/examples/test.c +++ /dev/null @@ -1,292 +0,0 @@ -/* $NetBSD: test.c,v 1.18 2005/06/01 11:37:52 lukem 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. - */ - -/* - * test.c: A little test program - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "histedit.h" - -/* from src/sys/sys/cdefs.h */ -#ifndef __UNCONST -# define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) -#endif - -static int continuation = 0; -volatile sig_atomic_t gotsig = 0; - -static unsigned char complete(EditLine *, int); - int main(int, char **); -static char *prompt(EditLine *); -static void sig(int); - -static char * -prompt(EditLine *el) -{ - static char a[] = "Edit$ "; - static char b[] = "Edit> "; - - return (continuation ? b : a); -} - -static void -sig(int i) -{ - gotsig = i; -} - -static unsigned char -complete(EditLine *el, int ch) -{ - DIR *dd = opendir("."); - struct dirent *dp; - const char* ptr; - const LineInfo *lf = el_line(el); - int len; - - /* - * Find the last word - */ - for (ptr = lf->cursor - 1; - !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) - continue; - len = lf->cursor - ++ptr; - - for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { - if (len > strlen(dp->d_name)) - continue; - if (strncmp(dp->d_name, ptr, len) == 0) { - closedir(dd); - if (el_insertstr(el, &dp->d_name[len]) == -1) - return (CC_ERROR); - else - return (CC_REFRESH); - } - } - - closedir(dd); - return (CC_ERROR); -} - -int -main(int argc, char *argv[]) -{ - EditLine *el = NULL; - int num; - const char *buf; - Tokenizer *tok; -#if 0 - int lastevent = 0; -#endif - int ncontinuation; - History *hist; - HistEvent ev; - - (void) signal(SIGINT, sig); - (void) signal(SIGQUIT, sig); - (void) signal(SIGHUP, sig); - (void) signal(SIGTERM, sig); - - hist = history_init(); /* Init the builtin history */ - /* Remember 100 events */ - history(hist, &ev, H_SETSIZE, 100); - - tok = tok_init(NULL); /* Initialize the tokenizer */ - - /* Initialize editline */ - el = el_init(*argv, stdin, stdout, stderr); - - el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ - el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ - el_set(el, EL_PROMPT, prompt); /* Set the prompt function */ - - /* Tell editline to use this history interface */ - el_set(el, EL_HIST, history, hist); - - /* Add a user-defined function */ - el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); - - /* Bind tab to it */ - el_set(el, EL_BIND, "^I", "ed-complete", NULL); - - /* - * Bind j, k in vi command mode to previous and next line, instead - * of previous and next history. - */ - el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); - el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); - - /* - * Source the user's defaults file. - */ - el_source(el, NULL); - - while ((buf = el_gets(el, &num)) != NULL && num != 0) { - int ac, cc, co; -#ifdef DEBUG - int i; -#endif - const char **av; - const LineInfo *li; - li = el_line(el); -#ifdef DEBUG - (void) fprintf(stderr, "==> got %d %s", num, buf); - (void) fprintf(stderr, " > li `%.*s_%.*s'\n", - (li->cursor - li->buffer), li->buffer, - (li->lastchar - 1 - li->cursor), - (li->cursor >= li->lastchar) ? "" : li->cursor); - -#endif - if (gotsig) { - (void) fprintf(stderr, "Got signal %d.\n", gotsig); - gotsig = 0; - el_reset(el); - } - - if (!continuation && num == 1) - continue; - - ac = cc = co = 0; - ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); - if (ncontinuation < 0) { - (void) fprintf(stderr, "Internal error\n"); - continuation = 0; - continue; - } -#ifdef DEBUG - (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", - ncontinuation, ac, cc, co); -#endif -#if 0 - if (continuation) { - /* - * Append to the right event in case the user - * moved around in history. - */ - if (history(hist, &ev, H_SET, lastevent) == -1) - err(1, "%d: %s", lastevent, ev.str); - history(hist, &ev, H_ADD , buf); - } else { - history(hist, &ev, H_ENTER, buf); - lastevent = ev.num; - } -#else - /* Simpler */ - history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); -#endif - - continuation = ncontinuation; - ncontinuation = 0; - if (continuation) - continue; -#ifdef DEBUG - for (i = 0; i < ac; i++) { - (void) fprintf(stderr, " > arg# %2d ", i); - if (i != cc) - (void) fprintf(stderr, "`%s'\n", av[i]); - else - (void) fprintf(stderr, "`%.*s_%s'\n", - co, av[i], av[i] + co); - } -#endif - - if (strcmp(av[0], "history") == 0) { - int rv; - - switch (ac) { - case 1: - for (rv = history(hist, &ev, H_LAST); rv != -1; - rv = history(hist, &ev, H_PREV)) - (void) fprintf(stdout, "%4d %s", - ev.num, ev.str); - break; - - case 2: - if (strcmp(av[1], "clear") == 0) - history(hist, &ev, H_CLEAR); - else - goto badhist; - break; - - case 3: - if (strcmp(av[1], "load") == 0) - history(hist, &ev, H_LOAD, av[2]); - else if (strcmp(av[1], "save") == 0) - history(hist, &ev, H_SAVE, av[2]); - break; - - badhist: - default: - (void) fprintf(stderr, - "Bad history arguments\n"); - break; - } - } else if (el_parse(el, ac, av) == -1) { - switch (fork()) { - case 0: - execvp(av[0], (char *const *)__UNCONST(av)); - perror(av[0]); - _exit(1); - /*NOTREACHED*/ - break; - - case -1: - perror("fork"); - break; - - default: - if (wait(&num) == -1) - perror("wait"); - (void) fprintf(stderr, "Exit %x\n", num); - break; - } - } - - tok_reset(tok); - } - - el_end(el); - tok_end(tok); - history_end(hist); - - return (0); -} diff --git a/clt/falcon/editline/src/CMakeLists.txt b/clt/falcon/editline/src/CMakeLists.txt index 7a700001d..f59a16222 100644 --- a/clt/falcon/editline/src/CMakeLists.txt +++ b/clt/falcon/editline/src/CMakeLists.txt @@ -1,3 +1,7 @@ +#/# editline for falcon + +add_definitions( -D_GNU_SOURCE ) + include_directories( ${PROJECT_BINARY_DIR} # config.h ${CMAKE_CURRENT_SOURCE_DIR} @@ -5,19 +9,18 @@ include_directories( ${CURSES_INCLUDE_DIR} ) -set(AHDR - vi.h - emacs.h +set(AHDR + vi.h + emacs.h common.h -) +) -set(ASRC - ${CMAKE_CURRENT_SOURCE_DIR}/vi.c - ${CMAKE_CURRENT_SOURCE_DIR}/emacs.c +set(ASRC + ${CMAKE_CURRENT_SOURCE_DIR}/vi.c + ${CMAKE_CURRENT_SOURCE_DIR}/emacs.c ${CMAKE_CURRENT_SOURCE_DIR}/common.c ) - add_custom_command( OUTPUT ${AHDR} DEPENDS vi.c emacs.c common.c @@ -25,52 +28,62 @@ add_custom_command( COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -h ${CMAKE_CURRENT_SOURCE_DIR}/emacs.c > emacs.h COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -h ${CMAKE_CURRENT_SOURCE_DIR}/common.c > common.h ) + add_custom_command( - OUTPUT fcns.h fcns.c help.h help.c + OUTPUT fcns.h help.h func.h DEPENDS ${AHDR} COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -fh ${AHDR} > fcns.h COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -bh ${ASRC} > help.h - COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -fc ${AHDR} > fcns.c - COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -bc ${ASRC} > help.c + COMMAND sh ${CMAKE_CURRENT_SOURCE_DIR}/makelist -fc ${AHDR} > func.h ) -add_custom_target(makelist_target DEPENDS - ${AHDR} - help.h +add_custom_target(makelist_target DEPENDS + ${AHDR} + help.h fcns.h + func.h ) -set(libedit_SOURCES - chared.c - el.c - hist.c - key.c + +set(libedit_SOURCES + chared.c + el.c + eln.c + hist.c + keymacro.c map.c - parse.c - prompt.c - read.c - refresh.c + chartype.c + parse.c + prompt.c + read.c + refresh.c search.c - sig.c - term.c - tty.c - fgetln.c + sig.c + terminal.c + tty.c + reallocarr.c + wcsdup.c + tokenizer.c + tokenizern.c + history.c + historyn.c + filecomplete.c + readline.c + literal.c + strlcpy.c strlcat.c - strlcpy.c - unvis.c - vis.c - tokenizer.c - history.c - filecomplete.c - readline.c + vis.c + unvis.c ) -add_library(edit STATIC +add_library(edit STATIC ${libedit_SOURCES} ${ASRC} - fcns.c - help.c ) + add_dependencies(edit makelist_target) -target_link_libraries(edit + +target_link_libraries(edit ${CURSES_LIBRARIES} -) \ No newline at end of file +) + +# vi: ts=2 sw=2 et diff --git a/clt/falcon/editline/src/ChangeLog b/clt/falcon/editline/src/ChangeLog new file mode 100644 index 000000000..35c9205a4 --- /dev/null +++ b/clt/falcon/editline/src/ChangeLog @@ -0,0 +1,6 @@ +2021-08-29 Christos Zoulas + + Change default mappings: + map ^W to ed-delete-prev-word and not kill-region + map ^R to em-inc-search-next and not redisplay + diff --git a/clt/falcon/editline/src/Makefile.am b/clt/falcon/editline/src/Makefile.am index aa73e58f1..9a0b23549 100644 --- a/clt/falcon/editline/src/Makefile.am +++ b/clt/falcon/editline/src/Makefile.am @@ -1,41 +1,55 @@ -BUILT_SOURCES = vi.h emacs.h common.h fcns.h help.h fcns.c help.c +BUILT_SOURCES = vi.h emacs.h common.h fcns.h help.h func.h AHDR= vi.h emacs.h common.h ASRC= $(srcdir)/vi.c $(srcdir)/emacs.c $(srcdir)/common.c vi.h: Makefile $(srcdir)/vi.c - sh $(srcdir)/makelist -h $(srcdir)/vi.c > $@ + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/vi.c > $@ emacs.h: Makefile $(srcdir)/emacs.c - sh $(srcdir)/makelist -h $(srcdir)/emacs.c > $@ + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/emacs.c > $@ common.h: Makefile $(srcdir)/common.c - sh $(srcdir)/makelist -h $(srcdir)/common.c > $@ + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/common.c > $@ fcns.h: Makefile $(AHDR) - sh $(srcdir)/makelist -fh $(AHDR) > $@ + AWK=$(AWK) sh $(srcdir)/makelist -fh $(AHDR) > $@ help.h: Makefile $(ASRC) - sh $(srcdir)/makelist -bh $(ASRC) > $@ - -fcns.c: Makefile $(AHDR) - sh $(srcdir)/makelist -fc $(AHDR) > $@ - -help.c: Makefile $(ASRC) - sh $(srcdir)/makelist -bc $(ASRC) > $@ + AWK=$(AWK) sh $(srcdir)/makelist -bh $(ASRC) > $@ +func.h: Makefile $(AHDR) + AWK=$(AWK) sh $(srcdir)/makelist -fc $(AHDR) > $@ CLEANFILES = $(BUILT_SOURCES) lib_LTLIBRARIES = libedit.la -libedit_la_SOURCES = chared.c common.c el.c emacs.c hist.c key.c map.c parse.c \ - prompt.c read.c refresh.c search.c sig.c term.c tty.c vi.c \ - fgetln.c strlcat.c strlcpy.c unvis.c vis.c tokenizer.c \ - history.c filecomplete.c readline.c chared.h el.h hist.h \ - histedit.h key.h map.h parse.h prompt.h read.h refresh.h \ - search.h sig.h sys.h el_term.h tty.h vis.h filecomplete.h \ - editline/readline.h +libedit_la_SOURCES = chared.c common.c el.c eln.c emacs.c hist.c keymacro.c map.c chartype.c parse.c \ + prompt.c read.c refresh.c search.c sig.c terminal.c tty.c vi.c \ + reallocarr.c wcsdup.c \ + tokenizer.c tokenizern.c \ + history.c historyn.c \ + filecomplete.c readline.c chared.h literal.c el.h hist.h \ + histedit.h keymacro.h map.h chartype.h parse.h prompt.h read.h refresh.h \ + search.h sig.h sys.h terminal.h tty.h vis.h filecomplete.h \ + editline/readline.h literal.h + +if !HAVE_STRLCPY +libedit_la_SOURCES += strlcpy.c +endif +if !HAVE_STRLCAT +libedit_la_SOURCES += strlcat.c +endif +if !HAVE_GETLINE +libedit_la_SOURCES += getline.c +endif +if !HAVE_VIS +libedit_la_SOURCES += vis.c +endif +if !HAVE_UNVIS +libedit_la_SOURCES += unvis.c +endif EXTRA_DIST = makelist shlib_version nobase_include_HEADERS = histedit.h editline/readline.h diff --git a/clt/falcon/editline/src/Makefile.in b/clt/falcon/editline/src/Makefile.in new file mode 100644 index 000000000..c2313a10b --- /dev/null +++ b/clt/falcon/editline/src/Makefile.in @@ -0,0 +1,860 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@HAVE_STRLCPY_FALSE@am__append_1 = strlcpy.c +@HAVE_STRLCAT_FALSE@am__append_2 = strlcat.c +@HAVE_GETLINE_FALSE@am__append_3 = getline.c +@HAVE_VIS_FALSE@am__append_4 = vis.c +@HAVE_UNVIS_FALSE@am__append_5 = unvis.c +subdir = src +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(nobase_include_HEADERS) \ + $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)" +LTLIBRARIES = $(lib_LTLIBRARIES) +libedit_la_LIBADD = +am__libedit_la_SOURCES_DIST = chared.c common.c el.c eln.c emacs.c \ + hist.c keymacro.c map.c chartype.c parse.c prompt.c read.c \ + refresh.c search.c sig.c terminal.c tty.c vi.c reallocarr.c \ + wcsdup.c tokenizer.c tokenizern.c history.c historyn.c \ + filecomplete.c readline.c chared.h literal.c el.h hist.h \ + histedit.h keymacro.h map.h chartype.h parse.h prompt.h read.h \ + refresh.h search.h sig.h sys.h terminal.h tty.h vis.h \ + filecomplete.h editline/readline.h literal.h strlcpy.c \ + strlcat.c getline.c vis.c unvis.c +@HAVE_STRLCPY_FALSE@am__objects_1 = strlcpy.lo +@HAVE_STRLCAT_FALSE@am__objects_2 = strlcat.lo +@HAVE_GETLINE_FALSE@am__objects_3 = getline.lo +@HAVE_VIS_FALSE@am__objects_4 = vis.lo +@HAVE_UNVIS_FALSE@am__objects_5 = unvis.lo +am_libedit_la_OBJECTS = chared.lo common.lo el.lo eln.lo emacs.lo \ + hist.lo keymacro.lo map.lo chartype.lo parse.lo prompt.lo \ + read.lo refresh.lo search.lo sig.lo terminal.lo tty.lo vi.lo \ + reallocarr.lo wcsdup.lo tokenizer.lo tokenizern.lo history.lo \ + historyn.lo filecomplete.lo readline.lo literal.lo \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) $(am__objects_5) +am__objects_6 = +nodist_libedit_la_OBJECTS = $(am__objects_6) +libedit_la_OBJECTS = $(am_libedit_la_OBJECTS) \ + $(nodist_libedit_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libedit_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libedit_la_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/chared.Plo ./$(DEPDIR)/chartype.Plo \ + ./$(DEPDIR)/common.Plo ./$(DEPDIR)/el.Plo ./$(DEPDIR)/eln.Plo \ + ./$(DEPDIR)/emacs.Plo ./$(DEPDIR)/filecomplete.Plo \ + ./$(DEPDIR)/getline.Plo ./$(DEPDIR)/hist.Plo \ + ./$(DEPDIR)/history.Plo ./$(DEPDIR)/historyn.Plo \ + ./$(DEPDIR)/keymacro.Plo ./$(DEPDIR)/literal.Plo \ + ./$(DEPDIR)/map.Plo ./$(DEPDIR)/parse.Plo \ + ./$(DEPDIR)/prompt.Plo ./$(DEPDIR)/read.Plo \ + ./$(DEPDIR)/readline.Plo ./$(DEPDIR)/reallocarr.Plo \ + ./$(DEPDIR)/refresh.Plo ./$(DEPDIR)/search.Plo \ + ./$(DEPDIR)/sig.Plo ./$(DEPDIR)/strlcat.Plo \ + ./$(DEPDIR)/strlcpy.Plo ./$(DEPDIR)/terminal.Plo \ + ./$(DEPDIR)/tokenizer.Plo ./$(DEPDIR)/tokenizern.Plo \ + ./$(DEPDIR)/tty.Plo ./$(DEPDIR)/unvis.Plo ./$(DEPDIR)/vi.Plo \ + ./$(DEPDIR)/vis.Plo ./$(DEPDIR)/wcsdup.Plo +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libedit_la_SOURCES) $(nodist_libedit_la_SOURCES) +DIST_SOURCES = $(am__libedit_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +HEADERS = $(nobase_include_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + ChangeLog +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +LT_VERSION = @LT_VERSION@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MANTYPE = @MANTYPE@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NROFF = @NROFF@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +BUILT_SOURCES = vi.h emacs.h common.h fcns.h help.h func.h +AHDR = vi.h emacs.h common.h +ASRC = $(srcdir)/vi.c $(srcdir)/emacs.c $(srcdir)/common.c +CLEANFILES = $(BUILT_SOURCES) +lib_LTLIBRARIES = libedit.la +libedit_la_SOURCES = chared.c common.c el.c eln.c emacs.c hist.c \ + keymacro.c map.c chartype.c parse.c prompt.c read.c refresh.c \ + search.c sig.c terminal.c tty.c vi.c reallocarr.c wcsdup.c \ + tokenizer.c tokenizern.c history.c historyn.c filecomplete.c \ + readline.c chared.h literal.c el.h hist.h histedit.h \ + keymacro.h map.h chartype.h parse.h prompt.h read.h refresh.h \ + search.h sig.h sys.h terminal.h tty.h vis.h filecomplete.h \ + editline/readline.h literal.h $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) +EXTRA_DIST = makelist shlib_version +nobase_include_HEADERS = histedit.h editline/readline.h +nodist_libedit_la_SOURCES = $(BUILT_SOURCES) +libedit_la_LDFLAGS = -no-undefined -version-info $(LT_VERSION) +all: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ + } + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +libedit.la: $(libedit_la_OBJECTS) $(libedit_la_DEPENDENCIES) $(EXTRA_libedit_la_DEPENDENCIES) + $(AM_V_CCLD)$(libedit_la_LINK) -rpath $(libdir) $(libedit_la_OBJECTS) $(libedit_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chared.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chartype.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/el.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eln.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emacs.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filecomplete.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getline.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hist.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/history.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/historyn.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keymacro.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/literal.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parse.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prompt.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/read.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readline.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reallocarr.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refresh.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/search.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sig.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcat.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strlcpy.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terminal.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokenizer.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tokenizern.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tty.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/unvis.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vi.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vis.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wcsdup.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-nobase_includeHEADERS: $(nobase_include_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \ + fi; \ + $(am__nobase_list) | while read dir files; do \ + xfiles=; for file in $$files; do \ + if test -f "$$file"; then xfiles="$$xfiles $$file"; \ + else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ + test -z "$$xfiles" || { \ + test "x$$dir" = x. || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(includedir)/$$dir'"; \ + $(MKDIR_P) "$(DESTDIR)$(includedir)/$$dir"; }; \ + echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(includedir)/$$dir'"; \ + $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(includedir)/$$dir" || exit $$?; }; \ + done + +uninstall-nobase_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nobase_include_HEADERS)'; test -n "$(includedir)" || list=; \ + $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ + dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am +install-exec: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/chared.Plo + -rm -f ./$(DEPDIR)/chartype.Plo + -rm -f ./$(DEPDIR)/common.Plo + -rm -f ./$(DEPDIR)/el.Plo + -rm -f ./$(DEPDIR)/eln.Plo + -rm -f ./$(DEPDIR)/emacs.Plo + -rm -f ./$(DEPDIR)/filecomplete.Plo + -rm -f ./$(DEPDIR)/getline.Plo + -rm -f ./$(DEPDIR)/hist.Plo + -rm -f ./$(DEPDIR)/history.Plo + -rm -f ./$(DEPDIR)/historyn.Plo + -rm -f ./$(DEPDIR)/keymacro.Plo + -rm -f ./$(DEPDIR)/literal.Plo + -rm -f ./$(DEPDIR)/map.Plo + -rm -f ./$(DEPDIR)/parse.Plo + -rm -f ./$(DEPDIR)/prompt.Plo + -rm -f ./$(DEPDIR)/read.Plo + -rm -f ./$(DEPDIR)/readline.Plo + -rm -f ./$(DEPDIR)/reallocarr.Plo + -rm -f ./$(DEPDIR)/refresh.Plo + -rm -f ./$(DEPDIR)/search.Plo + -rm -f ./$(DEPDIR)/sig.Plo + -rm -f ./$(DEPDIR)/strlcat.Plo + -rm -f ./$(DEPDIR)/strlcpy.Plo + -rm -f ./$(DEPDIR)/terminal.Plo + -rm -f ./$(DEPDIR)/tokenizer.Plo + -rm -f ./$(DEPDIR)/tokenizern.Plo + -rm -f ./$(DEPDIR)/tty.Plo + -rm -f ./$(DEPDIR)/unvis.Plo + -rm -f ./$(DEPDIR)/vi.Plo + -rm -f ./$(DEPDIR)/vis.Plo + -rm -f ./$(DEPDIR)/wcsdup.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-nobase_includeHEADERS + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-libLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/chared.Plo + -rm -f ./$(DEPDIR)/chartype.Plo + -rm -f ./$(DEPDIR)/common.Plo + -rm -f ./$(DEPDIR)/el.Plo + -rm -f ./$(DEPDIR)/eln.Plo + -rm -f ./$(DEPDIR)/emacs.Plo + -rm -f ./$(DEPDIR)/filecomplete.Plo + -rm -f ./$(DEPDIR)/getline.Plo + -rm -f ./$(DEPDIR)/hist.Plo + -rm -f ./$(DEPDIR)/history.Plo + -rm -f ./$(DEPDIR)/historyn.Plo + -rm -f ./$(DEPDIR)/keymacro.Plo + -rm -f ./$(DEPDIR)/literal.Plo + -rm -f ./$(DEPDIR)/map.Plo + -rm -f ./$(DEPDIR)/parse.Plo + -rm -f ./$(DEPDIR)/prompt.Plo + -rm -f ./$(DEPDIR)/read.Plo + -rm -f ./$(DEPDIR)/readline.Plo + -rm -f ./$(DEPDIR)/reallocarr.Plo + -rm -f ./$(DEPDIR)/refresh.Plo + -rm -f ./$(DEPDIR)/search.Plo + -rm -f ./$(DEPDIR)/sig.Plo + -rm -f ./$(DEPDIR)/strlcat.Plo + -rm -f ./$(DEPDIR)/strlcpy.Plo + -rm -f ./$(DEPDIR)/terminal.Plo + -rm -f ./$(DEPDIR)/tokenizer.Plo + -rm -f ./$(DEPDIR)/tokenizern.Plo + -rm -f ./$(DEPDIR)/tty.Plo + -rm -f ./$(DEPDIR)/unvis.Plo + -rm -f ./$(DEPDIR)/vi.Plo + -rm -f ./$(DEPDIR)/vis.Plo + -rm -f ./$(DEPDIR)/wcsdup.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-libLTLIBRARIES uninstall-nobase_includeHEADERS + +.MAKE: all check install install-am install-exec install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libLTLIBRARIES clean-libtool cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-libLTLIBRARIES install-man \ + install-nobase_includeHEADERS install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-libLTLIBRARIES \ + uninstall-nobase_includeHEADERS + +.PRECIOUS: Makefile + + +vi.h: Makefile $(srcdir)/vi.c + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/vi.c > $@ + +emacs.h: Makefile $(srcdir)/emacs.c + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/emacs.c > $@ + +common.h: Makefile $(srcdir)/common.c + AWK=$(AWK) sh $(srcdir)/makelist -h $(srcdir)/common.c > $@ + +fcns.h: Makefile $(AHDR) + AWK=$(AWK) sh $(srcdir)/makelist -fh $(AHDR) > $@ + +help.h: Makefile $(ASRC) + AWK=$(AWK) sh $(srcdir)/makelist -bh $(ASRC) > $@ + +func.h: Makefile $(AHDR) + AWK=$(AWK) sh $(srcdir)/makelist -fc $(AHDR) > $@ + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/clt/falcon/editline/src/chared.c b/clt/falcon/editline/src/chared.c index 0dbaa14c9..ff5545bbe 100644 --- a/clt/falcon/editline/src/chared.c +++ b/clt/falcon/editline/src/chared.c @@ -1,4 +1,4 @@ -/* $NetBSD: chared.c,v 1.27 2009/02/15 21:55:23 christos Exp $ */ +/* $NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,17 +37,20 @@ #if 0 static char sccsid[] = "@(#)chared.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: chared.c,v 1.27 2009/02/15 21:55:23 christos Exp $"); +__RCSID("$NetBSD: chared.c,v 1.62 2022/02/08 21:13:22 rillig Exp $"); #endif #endif /* not lint && not SCCSID */ /* * chared.c: Character editor utilities */ +#include #include -#include "el.h" +#include -private void ch__clearmacro (EditLine *); +#include "el.h" +#include "common.h" +#include "fcns.h" /* value to leave unused in line buffer */ #define EL_LEAVE 2 @@ -55,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; @@ -63,10 +66,10 @@ cv_undo(EditLine *el) size_t size; /* Save entire line for undo */ - size = el->el_line.lastchar - el->el_line.buffer; - vu->len = size; + 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); - memcpy(vu->buf, el->el_line.buffer, size); + (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; @@ -79,12 +82,12 @@ 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; - memcpy(k->buf, ptr, (size_t)size); + (void)memcpy(k->buf, ptr, (size_t)size * sizeof(*k->buf)); k->last = k->buf + size; } @@ -92,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)) @@ -114,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) { @@ -127,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]; @@ -140,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]; @@ -155,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) { @@ -168,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]; @@ -183,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]; @@ -198,22 +201,22 @@ c_delbefore1(EditLine *el) /* ce__isword(): * Return if p is part of a word according to emacs */ -protected int -ce__isword(int p) +libedit_private int +ce__isword(wint_t p) { - return (isalnum(p) || strchr("*?_-.[]~=", p) != NULL); + return iswalnum(p) || wcschr(L"*?_-.[]~=", p) != NULL; } /* cv__isword(): * Return if p is part of a word according to vi */ -protected int -cv__isword(int p) +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; } @@ -222,25 +225,25 @@ cv__isword(int p) /* cv__isWord(): * Return if p is part of a big word according to vi */ -protected int -cv__isWord(int p) +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)(int)) +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)((unsigned char) *p)) + while ((p >= low) && !(*wtest)(*p)) p--; - while ((p >= low) && (*wtest)((unsigned char) *p)) + while ((p >= low) && (*wtest)(*p)) p--; } @@ -249,121 +252,88 @@ c__prev_word(char *p, char *low, int n, int (*wtest)(int)) if (p < low) p = low; /* cp now points where we want it */ - return (p); + return p; } /* c__next_word(): * Find the next word */ -protected char * -c__next_word(char *p, char *high, int n, int (*wtest)(int)) +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)((unsigned char) *p)) + while ((p < high) && !(*wtest)(*p)) p++; - while ((p < high) && (*wtest)((unsigned char) *p)) + while ((p < high) && (*wtest)(*p)) p++; } if (p > high) p = high; /* p now points where we want it */ - return (p); + return p; } /* cv_next_word(): * Find the next word vi style */ -protected char * -cv_next_word(EditLine *el, char *p, char *high, int n, int (*wtest)(int)) +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)((unsigned char) *p); - while ((p < high) && (*wtest)((unsigned char) *p) == test) + test = (*wtest)(*p); + while ((p < high) && (*wtest)(*p) == test) p++; /* * vi historically deletes with cw only the word preserving the * trailing whitespace! This is not what 'w' does.. */ if (n || el->el_chared.c_vcmd.action != (DELETE|INSERT)) - while ((p < high) && isspace((unsigned char) *p)) + while ((p < high) && iswspace(*p)) p++; } /* p now points where we want it */ if (p > high) - return (high); + return high; else - return (p); + return p; } /* cv_prev_word(): * Find the previous word vi style */ -protected char * -cv_prev_word(char *p, char *low, int n, int (*wtest)(int)) +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((unsigned char) *p)) + while ((p > low) && iswspace(*p)) p--; - test = (*wtest)((unsigned char) *p); - while ((p >= low) && (*wtest)((unsigned char) *p) == test) + test = (*wtest)(*p); + while ((p >= low) && (*wtest)(*p) == test) p--; } p++; /* p now points where we want it */ if (p < low) - return (low); + return low; else - return (p); + return p; } -#ifdef notdef -/* c__number(): - * Ignore character p points to, return number appearing after that. - * A '$' by itself means a big number; "$-" is for negative; '^' means 1. - * Return p pointing to last char used. - */ -protected char * -c__number( - char *p, /* character position */ - int *num, /* Return value */ - int dval) /* dval is the number to subtract from like $-3 */ -{ - int i; - int sign = 1; - - if (*++p == '^') { - *num = 1; - return (p); - } - if (*p == '$') { - if (*++p != '-') { - *num = 0x7fffffff; /* Handle $ */ - return (--p); - } - sign = -1; /* Handle $- */ - ++p; - } - for (i = 0; isdigit((unsigned char) *p); i = 10 * i + *p++ - '0') - continue; - *num = (sign < 0 ? dval - i : i); - return (--p); -} -#endif - /* cv_delfini(): * Finish vi delete action */ -protected void +libedit_private void cv_delfini(EditLine *el) { int size; @@ -398,76 +368,53 @@ cv_delfini(EditLine *el) } -#ifdef notdef -/* ce__endword(): - * Go to the end of this word according to emacs - */ -protected char * -ce__endword(char *p, char *high, int n) -{ - p++; - - while (n--) { - while ((p < high) && isspace((unsigned char) *p)) - p++; - while ((p < high) && !isspace((unsigned char) *p)) - p++; - } - - p--; - return (p); -} -#endif - - /* cv__endword(): * Go to the end of this word according to vi */ -protected char * -cv__endword(char *p, char *high, int n, int (*wtest)(int)) +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((unsigned char) *p)) + while ((p < high) && iswspace(*p)) p++; - test = (*wtest)((unsigned char) *p); - while ((p < high) && (*wtest)((unsigned char) *p) == test) + test = (*wtest)(*p); + while ((p < high) && (*wtest)(*p) == test) p++; } p--; - return (p); + return p; } /* 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 = (char *) 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); + return -1; - (void) memset(el->el_line.buffer, 0, EL_BUFSIZ); 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 = (char *) 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); + return -1; el->el_chared.c_undo.len = -1; el->el_chared.c_undo.cursor = 0; - el->el_chared.c_redo.buf = (char *) 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); + 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; @@ -475,12 +422,16 @@ 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 = (char *) 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); + return -1; el->el_chared.c_kill.mark = el->el_line.buffer; el->el_chared.c_kill.last = el->el_chared.c_kill.buf; + el->el_chared.c_resizefun = NULL; + el->el_chared.c_resizearg = NULL; + el->el_chared.c_aliasfun = NULL; + el->el_chared.c_aliasarg = NULL; el->el_map.current = el->el_map.key; @@ -490,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 = (char **) el_malloc(EL_MAXMACRO * sizeof(char *)); - if (ma->macro == NULL) - return (-1); - return (0); + 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; @@ -524,30 +470,19 @@ 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((ptr_t)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 = el->el_line.limit - el->el_line.buffer + EL_LEAVE; + sz = (size_t)(el->el_line.limit - el->el_line.buffer + EL_LEAVE); newsz = sz * 2; /* * If newly required length is longer than current buffer, we need @@ -561,13 +496,13 @@ ch_enlargebufs(EditLine *el, size_t addlen) /* * Reallocate line buffer. */ - newbuffer = el_realloc(el->el_line.buffer, newsz); + newbuffer = el_realloc(el->el_line.buffer, newsz * sizeof(*newbuffer)); if (!newbuffer) return 0; /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, newsz - sz); - + (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); + oldbuf = el->el_line.buffer; el->el_line.buffer = newbuffer; @@ -579,12 +514,13 @@ ch_enlargebufs(EditLine *el, size_t addlen) /* * Reallocate kill buffer. */ - newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz); + newbuffer = el_realloc(el->el_chared.c_kill.buf, newsz * + sizeof(*newbuffer)); if (!newbuffer) return 0; /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, newsz - sz); + (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); oldkbuf = el->el_chared.c_kill.buf; @@ -597,15 +533,17 @@ ch_enlargebufs(EditLine *el, size_t addlen) /* * Reallocate undo buffer. */ - newbuffer = el_realloc(el->el_chared.c_undo.buf, newsz); + newbuffer = el_realloc(el->el_chared.c_undo.buf, + newsz * sizeof(*newbuffer)); if (!newbuffer) return 0; /* zero the newly added memory, leave old data in */ - (void) memset(&newbuffer[sz], 0, newsz - sz); + (void) memset(&newbuffer[sz], 0, (newsz - sz) * sizeof(*newbuffer)); el->el_chared.c_undo.buf = newbuffer; - newbuffer = el_realloc(el->el_chared.c_redo.buf, newsz); + newbuffer = el_realloc(el->el_chared.c_redo.buf, + newsz * sizeof(*newbuffer)); if (!newbuffer) return 0; el->el_chared.c_redo.pos = newbuffer + @@ -613,65 +551,65 @@ ch_enlargebufs(EditLine *el, size_t addlen) el->el_chared.c_redo.lim = newbuffer + (el->el_chared.c_redo.lim - el->el_chared.c_redo.buf); el->el_chared.c_redo.buf = newbuffer; - + if (!hist_enlargebuf(el, sz, newsz)) return 0; /* Safe to set enlarged buffer size */ el->el_line.limit = &el->el_line.buffer[newsz - EL_LEAVE]; + if (el->el_chared.c_resizefun) + (*el->el_chared.c_resizefun)(el, el->el_chared.c_resizearg); return 1; } /* ch_end(): * Free the data structures used by the editor */ -protected void +libedit_private void ch_end(EditLine *el) { - el_free((ptr_t) el->el_line.buffer); + el_free(el->el_line.buffer); el->el_line.buffer = NULL; el->el_line.limit = NULL; - el_free((ptr_t) el->el_chared.c_undo.buf); + el_free(el->el_chared.c_undo.buf); el->el_chared.c_undo.buf = NULL; - el_free((ptr_t) el->el_chared.c_redo.buf); + el_free(el->el_chared.c_redo.buf); el->el_chared.c_redo.buf = NULL; el->el_chared.c_redo.pos = NULL; el->el_chared.c_redo.lim = NULL; el->el_chared.c_redo.cmd = ED_UNASSIGNED; - el_free((ptr_t) el->el_chared.c_kill.buf); + el_free(el->el_chared.c_kill.buf); el->el_chared.c_kill.buf = NULL; - ch_reset(el, 1); - el_free((ptr_t) 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 -el_insertstr(EditLine *el, const char *s) +int +el_winsertstr(EditLine *el, const wchar_t *s) { size_t len; - if ((len = strlen(s)) == 0) - return (-1); + if (s == NULL || (len = wcslen(s)) == 0) + return -1; if (el->el_line.lastchar + len >= el->el_line.limit) { if (!ch_enlargebufs(el, len)) - return (-1); + return -1; } c_insert(el, (int)len); while (*s) *el->el_line.cursor++ = *s++; - return (0); + return 0; } /* el_deletestr(): * Delete num characters before the cursor */ -public void +void el_deletestr(EditLine *el, int n) { if (n <= 0) @@ -686,19 +624,100 @@ el_deletestr(EditLine *el, int n) el->el_line.cursor = el->el_line.buffer; } +/* el_deletestr1(): + * Delete characters between start and end + */ +int +el_deletestr1(EditLine *el, int start, int end) +{ + size_t line_length, len; + wchar_t *p1, *p2; + + if (end <= start) + return 0; + + line_length = (size_t)(el->el_line.lastchar - el->el_line.buffer); + + if (start >= (int)line_length || end >= (int)line_length) + return 0; + + len = (size_t)(end - start); + if (len > line_length - (size_t)end) + len = line_length - (size_t)end; + + p1 = el->el_line.buffer + start; + p2 = el->el_line.buffer + end; + for (size_t i = 0; i < len; i++) { + *p1++ = *p2++; + el->el_line.lastchar--; + } + + if (el->el_line.cursor < el->el_line.buffer) + el->el_line.cursor = el->el_line.buffer; + + return end - start; +} + +/* el_wreplacestr(): + * Replace the contents of the line with the provided string + */ +int +el_wreplacestr(EditLine *el, const wchar_t *s) +{ + size_t len; + wchar_t * p; + + if (s == NULL || (len = wcslen(s)) == 0) + return -1; + + if (el->el_line.buffer + len >= el->el_line.limit) { + if (!ch_enlargebufs(el, len)) + return -1; + } + + p = el->el_line.buffer; + for (size_t i = 0; i < len; i++) + *p++ = *s++; + + el->el_line.buffer[len] = '\0'; + el->el_line.lastchar = el->el_line.buffer + len; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; + + return 0; +} + +/* el_cursor(): + * Move the cursor to the left or the right of the current position + */ +int +el_cursor(EditLine *el, int n) +{ + if (n == 0) + goto out; + + el->el_line.cursor += n; + + if (el->el_line.cursor < el->el_line.buffer) + el->el_line.cursor = el->el_line.buffer; + if (el->el_line.cursor > el->el_line.lastchar) + el->el_line.cursor = el->el_line.lastchar; +out: + return (int)(el->el_line.cursor - el->el_line.buffer); +} + /* c_gets(): * Get a string */ -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) { - char ch; ssize_t len; - char *cp = el->el_line.buffer; + wchar_t *cp = el->el_line.buffer, ch; if (prompt) { - len = strlen(prompt); - memcpy(cp, prompt, (size_t)len); + len = (ssize_t)wcslen(prompt); + (void)memcpy(cp, prompt, (size_t)len * sizeof(*cp)); cp += len; } len = 0; @@ -709,7 +728,7 @@ c_gets(EditLine *el, char *buf, const char *prompt) el->el_line.lastchar = cp + 1; re_refresh(el); - if (el_getc(el, &ch) != 1) { + if (el_wgetc(el, &ch) != 1) { ed_end_of_file(el, 0); len = -1; break; @@ -717,24 +736,25 @@ c_gets(EditLine *el, char *buf, const char *prompt) switch (ch) { - case 0010: /* Delete and backspace */ + case L'\b': /* Delete and backspace */ case 0177: if (len == 0) { len = -1; break; } + len--; cp--; continue; case 0033: /* ESC */ - case '\r': /* Newline */ - case '\n': + case L'\r': /* Newline */ + case L'\n': buf[len] = ch; break; default: - if (len >= EL_BUFSIZ - 16) - term_beep(el); + if (len >= (ssize_t)(EL_BUFSIZ - 16)) + terminal_beep(el); else { buf[len++] = ch; *cp++ = ch; @@ -754,16 +774,16 @@ 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. */ if (el->el_line.cursor == el->el_line.buffer) - return (0); + return 0; else { for (ptr = el->el_line.cursor - 1; ptr >= el->el_line.buffer && *ptr != '\n'; @@ -772,3 +792,19 @@ c_hpos(EditLine *el) return (int)(el->el_line.cursor - ptr - 1); } } + +libedit_private int +ch_resizefun(EditLine *el, el_zfunc_t f, void *a) +{ + el->el_chared.c_resizefun = f; + el->el_chared.c_resizearg = a; + return 0; +} + +libedit_private int +ch_aliasfun(EditLine *el, el_afunc_t f, void *a) +{ + el->el_chared.c_aliasfun = f; + el->el_chared.c_aliasarg = a; + return 0; +} diff --git a/clt/falcon/editline/src/chared.h b/clt/falcon/editline/src/chared.h index 2464f7bb4..39f7d5173 100644 --- a/clt/falcon/editline/src/chared.h +++ b/clt/falcon/editline/src/chared.h @@ -1,4 +1,4 @@ -/* $NetBSD: chared.h,v 1.18 2009/02/15 21:55:23 christos Exp $ */ +/* $NetBSD: chared.h,v 1.30 2016/05/22 19:44:26 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,13 +40,6 @@ #ifndef _h_el_chared #define _h_el_chared -#include -#include - -#include "histedit.h" - -#define EL_MAXMACRO 10 - /* * This is an issue of basic "vi" look-and-feel. Defining VI_MOVE works * like real vi: i.e. the transition from command<->insert modes moves @@ -59,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; @@ -91,18 +77,21 @@ 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 *); +typedef const char *(*el_afunc_t)(void *, const char *); + /* * Note that we use both data structures because the user can bind * commands from both editors! @@ -112,14 +101,16 @@ 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; + void * c_aliasarg; } el_chared_t; #define STRQQ "\"\"" #define isglob(a) (strchr("*[]?", (a)) != NULL) -#define isword(a) (isprint(a)) #define NOP 0x00 #define DELETE 0x01 @@ -133,35 +124,32 @@ typedef struct el_chared_t { #define MODE_REPLACE 1 #define MODE_REPLACE_1 2 -#include "common.h" -#include "vi.h" -#include "emacs.h" -#include "search.h" -#include "fcns.h" - - -protected int cv__isword(int); -protected int cv__isWord(int); -protected void cv_delfini(EditLine *); -protected char *cv__endword(char *, char *, int, int (*)(int)); -protected int ce__isword(int); -protected void cv_undo(EditLine *); -protected void cv_yank(EditLine *, const char *, int); -protected char *cv_next_word(EditLine*, char *, char *, int, int (*)(int)); -protected char *cv_prev_word(char *, char *, int, int (*)(int)); -protected char *c__next_word(char *, char *, int, int (*)(int)); -protected char *c__prev_word(char *, char *, int, int (*)(int)); -protected void c_insert(EditLine *, int); -protected void c_delbefore(EditLine *, int); -protected void c_delbefore1(EditLine *); -protected void c_delafter(EditLine *, int); -protected void c_delafter1(EditLine *); -protected int c_gets(EditLine *, char *, const char *); -protected int c_hpos(EditLine *); - -protected int ch_init(EditLine *); -protected void ch_reset(EditLine *, int); -protected int ch_enlargebufs(EditLine *, size_t); -protected void ch_end(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 *); + +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 */ diff --git a/clt/falcon/editline/src/chartype.c b/clt/falcon/editline/src/chartype.c new file mode 100644 index 000000000..3df4af69b --- /dev/null +++ b/clt/falcon/editline/src/chartype.c @@ -0,0 +1,339 @@ +/* $NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 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. + */ + +/* + * chartype.c: character classification and meta information + */ +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: chartype.c,v 1.35 2019/07/23 10:18:52 christos Exp $"); +#endif /* not lint && not SCCSID */ + +#include +#include +#include +#include + +#include "el.h" + +#define CT_BUFSIZ ((size_t)1024) + +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; + + if (csize <= conv->csize) + return 0; + + conv->csize = csize; + + p = el_realloc(conv->cbuff, conv->csize * sizeof(*conv->cbuff)); + if (p == NULL) { + conv->csize = 0; + el_free(conv->cbuff); + conv->cbuff = NULL; + return -1; + } + conv->cbuff = p; + return 0; +} + +static int +ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize) +{ + void *p; + + if (wsize <= conv->wsize) + return 0; + + conv->wsize = wsize; + + p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff)); + if (p == NULL) { + conv->wsize = 0; + el_free(conv->wbuff); + conv->wbuff = NULL; + return -1; + } + conv->wbuff = p; + return 0; +} + + +char * +ct_encode_string(const wchar_t *s, ct_buffer_t *conv) +{ + char *dst; + ssize_t used; + + if (!s) + return NULL; + + dst = conv->cbuff; + for (;;) { + used = (ssize_t)(dst - conv->cbuff); + if ((conv->csize - (size_t)used) < 5) { + if (ct_conv_cbuff_resize(conv, + conv->csize + CT_BUFSIZ) == -1) + return NULL; + dst = conv->cbuff + used; + } + if (!*s) + break; + used = ct_encode_char(dst, (size_t)5, *s); + if (used == -1) /* failed to encode, need more buffer space */ + abort(); + ++s; + dst += used; + } + *dst = '\0'; + return conv->cbuff; +} + +wchar_t * +ct_decode_string(const char *s, ct_buffer_t *conv) +{ + size_t len; + + if (!s) + return NULL; + + len = mbstowcs(NULL, s, (size_t)0); + if (len == (size_t)-1) + return NULL; + + if (conv->wsize < ++len) + if (ct_conv_wbuff_resize(conv, len + CT_BUFSIZ) == -1) + return NULL; + + mbstowcs(conv->wbuff, s, conv->wsize); + return conv->wbuff; +} + + +libedit_private wchar_t ** +ct_decode_argv(int argc, const char *argv[], ct_buffer_t *conv) +{ + size_t bufspace; + int i; + wchar_t *p; + wchar_t **wargv; + ssize_t bytes; + + /* Make sure we have enough space in the conversion buffer to store all + * the argv strings. */ + for (i = 0, bufspace = 0; i < argc; ++i) + bufspace += argv[i] ? strlen(argv[i]) + 1 : 0; + if (conv->wsize < ++bufspace) + if (ct_conv_wbuff_resize(conv, bufspace + CT_BUFSIZ) == -1) + return NULL; + + 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 */ + wargv[i] = NULL; + continue; + } else { + wargv[i] = p; + bytes = (ssize_t)mbstowcs(p, argv[i], bufspace); + } + if (bytes == -1) { + el_free(wargv); + return NULL; + } else + bytes++; /* include '\0' in the count */ + bufspace -= (size_t)bytes; + p += bytes; + } + wargv[i] = NULL; + + return wargv; +} + + +libedit_private size_t +ct_enc_width(wchar_t c) +{ + mbstate_t mbs; + char buf[MB_LEN_MAX]; + size_t size; + memset(&mbs, 0, sizeof(mbs)); + + if ((size = wcrtomb(buf, c, &mbs)) == (size_t)-1) + return 0; + return size; +} + +libedit_private ssize_t +ct_encode_char(char *dst, size_t len, wchar_t c) +{ + ssize_t l = 0; + if (len < ct_enc_width(c)) + return -1; + l = wctomb(dst, c); + + if (l < 0) { + wctomb(NULL, L'\0'); + l = 0; + } + return l; +} + +libedit_private const wchar_t * +ct_visual_string(const wchar_t *s, ct_buffer_t *conv) +{ + wchar_t *dst; + ssize_t used; + + if (!s) + return NULL; + + if (ct_conv_wbuff_resize(conv, CT_BUFSIZ) == -1) + return NULL; + + used = 0; + dst = conv->wbuff; + while (*s) { + used = ct_visual_char(dst, + conv->wsize - (size_t)(dst - conv->wbuff), *s); + if (used != -1) { + ++s; + dst += used; + continue; + } + + /* 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 >= (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 = L'\0'; + return conv->wbuff; +} + + + +libedit_private int +ct_visual_width(wchar_t c) +{ + int t = ct_chr_class(c); + switch (t) { + case CHTYPE_ASCIICTL: + return 2; /* ^@ ^? etc. */ + case CHTYPE_TAB: + return 1; /* Hmm, this really need to be handled outside! */ + case CHTYPE_NL: + return 0; /* Should this be 1 instead? */ + case CHTYPE_PRINT: + return wcwidth(c); + case CHTYPE_NONPRINT: + if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ + return 8; /* \U+12345 */ + else + return 7; /* \U+1234 */ + default: + return 0; /* should not happen */ + } +} + + +libedit_private ssize_t +ct_visual_char(wchar_t *dst, size_t len, wchar_t c) +{ + int t = ct_chr_class(c); + switch (t) { + case CHTYPE_TAB: + case CHTYPE_NL: + case CHTYPE_ASCIICTL: + if (len < 2) + return -1; /* insufficient space */ + *dst++ = '^'; + if (c == '\177') + *dst = '?'; /* DEL -> ^? */ + else + *dst = c | 0100; /* uncontrolify it */ + return 2; + case CHTYPE_PRINT: + if (len < 1) + return -1; /* insufficient space */ + *dst = c; + return 1; + case CHTYPE_NONPRINT: + /* we only use single-width glyphs for display, + * so this is right */ + if ((ssize_t)len < ct_visual_width(c)) + return -1; /* insufficient space */ + *dst++ = '\\'; + *dst++ = 'U'; + *dst++ = '+'; +#define tohexdigit(v) "0123456789ABCDEF"[v] + if (c > 0xffff) /* prefer standard 4-byte display over 5-byte */ + *dst++ = tohexdigit(((unsigned int) c >> 16) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 12) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 8) & 0xf); + *dst++ = tohexdigit(((unsigned int) c >> 4) & 0xf); + *dst = tohexdigit(((unsigned int) c ) & 0xf); + return c > 0xffff ? 8 : 7; + /*FALLTHROUGH*/ + /* these two should be handled outside this function */ + default: /* we should never hit the default */ + return 0; + } +} + + + + +libedit_private int +ct_chr_class(wchar_t c) +{ + if (c == '\t') + return CHTYPE_TAB; + else if (c == '\n') + return CHTYPE_NL; + else if (c < 0x100 && iswcntrl(c)) + return CHTYPE_ASCIICTL; + else if (iswprint(c)) + return CHTYPE_PRINT; + else + return CHTYPE_NONPRINT; +} diff --git a/clt/falcon/editline/src/chartype.h b/clt/falcon/editline/src/chartype.h new file mode 100644 index 000000000..bcdb293a1 --- /dev/null +++ b/clt/falcon/editline/src/chartype.h @@ -0,0 +1,120 @@ +/* $NetBSD: chartype.h,v 1.37 2022/04/11 19:37:20 tnn 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(__osf__) && \ + !(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 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 ((wint_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 */ diff --git a/clt/falcon/editline/src/common.c b/clt/falcon/editline/src/common.c index 03b09bc3c..f33c29650 100644 --- a/clt/falcon/editline/src/common.c +++ b/clt/falcon/editline/src/common.c @@ -1,4 +1,4 @@ -/* $NetBSD: common.c,v 1.23 2009/02/27 04:18:45 msaitoh Exp $ */ +/* $NetBSD: common.c,v 1.49 2020/03/30 06:54:37 ryo Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,27 +37,34 @@ #if 0 static char sccsid[] = "@(#)common.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: common.c,v 1.23 2009/02/27 04:18:45 msaitoh Exp $"); +__RCSID("$NetBSD: common.c,v 1.49 2020/03/30 06:54:37 ryo Exp $"); #endif #endif /* not lint && not SCCSID */ /* * common.c: Common Editor functions */ +#include +#include + #include "el.h" +#include "common.h" +#include "fcns.h" +#include "parse.h" +#include "vi.h" /* ed_end_of_file(): * Indicate end of file * [^D] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_end_of_file(EditLine *el, int c __attribute__((__unused__))) +ed_end_of_file(EditLine *el, wint_t c __attribute__((__unused__))) { re_goto_bottom(el); *el->el_line.lastchar = '\0'; - return (CC_EOF); + return CC_EOF; } @@ -65,13 +72,13 @@ ed_end_of_file(EditLine *el, int c __attribute__((__unused__))) * Add character to the line * Insert a character [bound to all insert keys] */ -protected el_action_t -ed_insert(EditLine *el, int c) +libedit_private el_action_t +ed_insert(EditLine *el, wint_t c) { int count = el->el_state.argument; if (c == '\0') - return (CC_ERROR); + return CC_ERROR; if (el->el_line.lastchar + el->el_state.argument >= el->el_line.limit) { @@ -99,7 +106,7 @@ ed_insert(EditLine *el, int c) if (el->el_state.inputmode == MODE_REPLACE_1) return vi_command_mode(el, 0); - return (CC_NORM); + return CC_NORM; } @@ -107,14 +114,14 @@ ed_insert(EditLine *el, int 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, int c __attribute__((__unused__))) +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); + return CC_ERROR; cp = c__prev_word(el->el_line.cursor, el->el_line.buffer, el->el_state.argument, ce__isword); @@ -127,7 +134,7 @@ ed_delete_prev_word(EditLine *el, int c __attribute__((__unused__))) el->el_line.cursor = cp; if (el->el_line.cursor < el->el_line.buffer) el->el_line.cursor = el->el_line.buffer; /* bounds check */ - return (CC_REFRESH); + return CC_REFRESH; } @@ -135,14 +142,14 @@ ed_delete_prev_word(EditLine *el, int 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, int c) +ed_delete_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { -#ifdef notdef /* XXX */ +#ifdef DEBUG_EDIT #define EL el->el_line - (void) fprintf(el->el_errlfile, - "\nD(b: %x(%s) c: %x(%s) last: %x(%s) limit: %x(%s)\n", + (void) fprintf(el->el_errfile, + "\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 @@ -152,32 +159,29 @@ ed_delete_next_char(EditLine *el, int c) if (el->el_line.cursor == el->el_line.buffer) { /* if I'm also at the beginning */ #ifdef KSHVI - return (CC_ERROR); + return CC_ERROR; #else /* then do an EOF */ - term_writechar(el, c); - return (CC_EOF); + terminal_writec(el, c); + return CC_EOF; #endif } else { #ifdef KSHVI el->el_line.cursor--; #else - return (CC_ERROR); + return CC_ERROR; #endif } - } else { - if (el->el_line.cursor != el->el_line.buffer) - el->el_line.cursor--; - else - return (CC_ERROR); - } + } else + return CC_ERROR; } c_delafter(el, el->el_state.argument); /* delete after dot */ - if (el->el_line.cursor >= el->el_line.lastchar && + if (el->el_map.type == MAP_VI && + el->el_line.cursor >= el->el_line.lastchar && el->el_line.cursor > el->el_line.buffer) /* bounds check */ el->el_line.cursor = el->el_line.lastchar - 1; - return (CC_REFRESH); + return CC_REFRESH; } @@ -185,11 +189,11 @@ ed_delete_next_char(EditLine *el, int c) * Cut to the end of line * [^K] [^K] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_kill_line(EditLine *el, int c __attribute__((__unused__))) +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; @@ -198,7 +202,7 @@ ed_kill_line(EditLine *el, int c __attribute__((__unused__))) el->el_chared.c_kill.last = kp; /* zap! -- delete to end */ el->el_line.lastchar = el->el_line.cursor; - return (CC_REFRESH); + return CC_REFRESH; } @@ -206,22 +210,22 @@ ed_kill_line(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_move_to_end(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.lastchar; if (el->el_map.type == MAP_VI) { if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } #ifdef VI_MOVE el->el_line.cursor--; #endif } - return (CC_CURSOR); + return CC_CURSOR; } @@ -229,23 +233,23 @@ ed_move_to_end(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_move_to_beg(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.buffer; if (el->el_map.type == MAP_VI) { /* We want FIRST non space character */ - while (isspace((unsigned char) *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); - return (CC_REFRESH); + return CC_REFRESH; } } - return (CC_CURSOR); + return CC_CURSOR; } @@ -253,13 +257,13 @@ ed_move_to_beg(EditLine *el, int c __attribute__((__unused__))) * Exchange the character to the left of the cursor with the one under it * [^T] [^T] */ -protected el_action_t -ed_transpose_chars(EditLine *el, int c) +libedit_private el_action_t +ed_transpose_chars(EditLine *el, wint_t c) { if (el->el_line.cursor < el->el_line.lastchar) { if (el->el_line.lastchar <= &el->el_line.buffer[1]) - return (CC_ERROR); + return CC_ERROR; else el->el_line.cursor++; } @@ -268,9 +272,9 @@ ed_transpose_chars(EditLine *el, int c) c = el->el_line.cursor[-2]; el->el_line.cursor[-2] = el->el_line.cursor[-1]; el->el_line.cursor[-1] = c; - return (CC_REFRESH); + return CC_REFRESH; } else - return (CC_ERROR); + return CC_ERROR; } @@ -278,17 +282,17 @@ ed_transpose_chars(EditLine *el, int c) * Move to the right one character * [^F] [^F] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_next_char(EditLine *el, int c __attribute__((__unused__))) +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 && el->el_map.type == MAP_VI && el->el_chared.c_vcmd.action == NOP)) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor += el->el_state.argument; if (el->el_line.cursor > lim) @@ -297,9 +301,9 @@ ed_next_char(EditLine *el, int c __attribute__((__unused__))) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -307,13 +311,13 @@ ed_next_char(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = c__prev_word(el->el_line.cursor, el->el_line.buffer, @@ -323,9 +327,9 @@ ed_prev_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -333,9 +337,9 @@ ed_prev_word(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor > el->el_line.buffer) { @@ -346,11 +350,11 @@ ed_prev_char(EditLine *el, int c __attribute__((__unused__))) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } else - return (CC_ERROR); + return CC_ERROR; } @@ -358,32 +362,32 @@ ed_prev_char(EditLine *el, int c __attribute__((__unused__))) * Add the next character typed verbatim * [^V] [^V] */ -protected el_action_t -ed_quoted_insert(EditLine *el, int c) +libedit_private el_action_t +/*ARGSUSED*/ +ed_quoted_insert(EditLine *el, wint_t c __attribute__((__unused__))) { int num; - char tc; + wchar_t ch; tty_quotemode(el); - num = el_getc(el, &tc); - c = (unsigned char) tc; + 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)); + return ed_end_of_file(el, 0); } /* ed_digit(): * Adds to argument or enters a digit */ -protected el_action_t -ed_digit(EditLine *el, int c) +libedit_private el_action_t +ed_digit(EditLine *el, wint_t c) { - if (!isdigit((unsigned char)c)) - return (CC_ERROR); + if (!iswdigit(c)) + return CC_ERROR; if (el->el_state.doingarg) { /* if doing an arg, add this in... */ @@ -391,11 +395,11 @@ ed_digit(EditLine *el, int c) el->el_state.argument = c - '0'; else { if (el->el_state.argument > 1000000) - return (CC_ERROR); + return CC_ERROR; el->el_state.argument = (el->el_state.argument * 10) + (c - '0'); } - return (CC_ARGHACK); + return CC_ARGHACK; } return ed_insert(el, c); @@ -406,23 +410,23 @@ ed_digit(EditLine *el, int c) * Digit that starts argument * For ESC-n */ -protected el_action_t -ed_argument_digit(EditLine *el, int c) +libedit_private el_action_t +ed_argument_digit(EditLine *el, wint_t c) { - if (!isdigit((unsigned char)c)) - return (CC_ERROR); + if (!iswdigit(c)) + return CC_ERROR; if (el->el_state.doingarg) { if (el->el_state.argument > 1000000) - return (CC_ERROR); + return CC_ERROR; el->el_state.argument = (el->el_state.argument * 10) + (c - '0'); } else { /* else starting an argument */ el->el_state.argument = c - '0'; el->el_state.doingarg = 1; } - return (CC_ARGHACK); + return CC_ARGHACK; } @@ -430,114 +434,27 @@ ed_argument_digit(EditLine *el, int c) * Indicates unbound character * Bound to keys that are not assigned */ -protected el_action_t -/*ARGSUSED*/ -ed_unassigned(EditLine *el, int c __attribute__((__unused__))) -{ - - return (CC_ERROR); -} - - -/** - ** TTY key handling. - **/ - -/* ed_tty_sigint(): - * Tty interrupt character - * [^C] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_sigint(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) -{ - - return (CC_NORM); -} - - -/* ed_tty_dsusp(): - * Tty delayed suspend character - * [^Y] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_dsusp(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) -{ - - return (CC_NORM); -} - - -/* ed_tty_flush_output(): - * Tty flush output characters - * [^O] - */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_tty_flush_output(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) +ed_unassigned(EditLine *el __attribute__((__unused__)), + wint_t c __attribute__((__unused__))) { - return (CC_NORM); + return CC_ERROR; } -/* ed_tty_sigquit(): - * Tty quit character - * [^\] +/* 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_sigquit(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) +ed_ignore(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__)), - int c __attribute__((__unused__))) -{ - - return (CC_NORM); -} - - -/* ed_tty_stop_output(): - * Tty disallow output characters - * [^S] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_stop_output(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) -{ - - return (CC_NORM); -} - - -/* ed_tty_start_output(): - * Tty allow output characters - * [^Q] - */ -protected el_action_t -/*ARGSUSED*/ -ed_tty_start_output(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) -{ - - return (CC_NORM); + return CC_NORM; } @@ -545,15 +462,15 @@ ed_tty_start_output(EditLine *el __attribute__((__unused__)), * Execute command * [^J] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_newline(EditLine *el, int c __attribute__((__unused__))) +ed_newline(EditLine *el, wint_t c __attribute__((__unused__))) { re_goto_bottom(el); *el->el_line.lastchar++ = '\n'; *el->el_line.lastchar = '\0'; - return (CC_NEWLINE); + return CC_NEWLINE; } @@ -561,19 +478,19 @@ ed_newline(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor <= el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; c_delbefore(el, el->el_state.argument); el->el_line.cursor -= el->el_state.argument; if (el->el_line.cursor < el->el_line.buffer) el->el_line.cursor = el->el_line.buffer; - return (CC_REFRESH); + return CC_REFRESH; } @@ -581,14 +498,14 @@ ed_delete_prev_char(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_clear_screen(EditLine *el, wint_t c __attribute__((__unused__))) { - term_clear_screen(el); /* clear the whole real screen */ + terminal_clear_screen(el); /* clear the whole real screen */ re_clear_display(el); /* reset everything */ - return (CC_REFRESH); + return CC_REFRESH; } @@ -596,13 +513,13 @@ ed_clear_screen(EditLine *el, int c __attribute__((__unused__))) * Redisplay everything * ^R */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_redisplay(EditLine *el __attribute__((__unused__)), - int c __attribute__((__unused__))) +ed_redisplay(EditLine *el __attribute__((__unused__)), + wint_t c __attribute__((__unused__))) { - return (CC_REDISPLAY); + return CC_REDISPLAY; } @@ -610,13 +527,13 @@ 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, int c __attribute__((__unused__))) +ed_start_over(EditLine *el, wint_t c __attribute__((__unused__))) { - ch_reset(el, 0); - return (CC_REFRESH); + ch_reset(el); + return CC_REFRESH; } @@ -624,13 +541,13 @@ ed_start_over(EditLine *el, int 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__)), - int c __attribute__((__unused__))) +ed_sequence_lead_in(EditLine *el __attribute__((__unused__)), + wint_t c __attribute__((__unused__))) { - return (CC_NORM); + return CC_NORM; } @@ -638,9 +555,9 @@ 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, int c __attribute__((__unused__))) +ed_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) { char beep = 0; int sv_event = el->el_history.eventno; @@ -650,7 +567,7 @@ ed_prev_history(EditLine *el, int 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); @@ -660,7 +577,6 @@ ed_prev_history(EditLine *el, int c __attribute__((__unused__))) if (hist_get(el) == CC_ERROR) { if (el->el_map.type == MAP_VI) { el->el_history.eventno = sv_event; - return CC_ERROR; } beep = 1; /* el->el_history.eventno was fixed by first call */ @@ -676,9 +592,9 @@ ed_prev_history(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_next_history(EditLine *el, wint_t c __attribute__((__unused__))) { el_action_t beep = CC_REFRESH, rval; @@ -703,13 +619,13 @@ ed_next_history(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_search_prev_history(EditLine *el, wint_t c __attribute__((__unused__))) { - const char *hp; + const wchar_t *hp; int h; - bool_t found = 0; + int found = 0; el->el_chared.c_vcmd.action = NOP; el->el_chared.c_undo.len = -1; @@ -720,20 +636,20 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__))) "e_prev_search_hist(): eventno < 0;\n"); #endif el->el_history.eventno = 0; - return (CC_ERROR); + 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); } if (el->el_history.ref == NULL) - return (CC_ERROR); + return CC_ERROR; hp = HIST_FIRST(el); if (hp == NULL) - return (CC_ERROR); + return CC_ERROR; c_setpat(el); /* Set search pattern !! */ @@ -742,13 +658,13 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__))) while (hp != NULL) { #ifdef SDEBUG - (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); + (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\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)) { - found++; + found = 1; break; } h++; @@ -759,11 +675,11 @@ ed_search_prev_history(EditLine *el, int c __attribute__((__unused__))) #ifdef SDEBUG (void) fprintf(el->el_errfile, "not found\n"); #endif - return (CC_ERROR); + return CC_ERROR; } el->el_history.eventno = h; - return (hist_get(el)); + return hist_get(el); } @@ -771,35 +687,35 @@ ed_search_prev_history(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_search_next_history(EditLine *el, wint_t c __attribute__((__unused__))) { - const char *hp; + const wchar_t *hp; int h; - bool_t found = 0; + int found = 0; el->el_chared.c_vcmd.action = NOP; el->el_chared.c_undo.len = -1; *el->el_line.lastchar = '\0'; /* just in case */ if (el->el_history.eventno == 0) - return (CC_ERROR); + return CC_ERROR; if (el->el_history.ref == NULL) - return (CC_ERROR); + return CC_ERROR; hp = HIST_FIRST(el); if (hp == NULL) - return (CC_ERROR); + return CC_ERROR; c_setpat(el); /* Set search pattern !! */ for (h = 1; h < el->el_history.eventno && hp; h++) { #ifdef SDEBUG - (void) fprintf(el->el_errfile, "Comparing with \"%s\"\n", hp); + (void) fprintf(el->el_errfile, "Comparing with \"%ls\"\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)) @@ -812,12 +728,12 @@ ed_search_next_history(EditLine *el, int c __attribute__((__unused__))) #ifdef SDEBUG (void) fprintf(el->el_errfile, "not found\n"); #endif - return (CC_ERROR); + return CC_ERROR; } } el->el_history.eventno = found; - return (hist_get(el)); + return hist_get(el); } @@ -825,11 +741,11 @@ ed_search_next_history(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_prev_line(EditLine *el, wint_t c __attribute__((__unused__))) { - char *ptr; + wchar_t *ptr; int nchars = c_hpos(el); /* @@ -843,7 +759,7 @@ ed_prev_line(EditLine *el, int c __attribute__((__unused__))) break; if (el->el_state.argument > 0) - return (CC_ERROR); + return CC_ERROR; /* * Move to the beginning of the line @@ -860,7 +776,7 @@ ed_prev_line(EditLine *el, int c __attribute__((__unused__))) continue; el->el_line.cursor = ptr; - return (CC_CURSOR); + return CC_CURSOR; } @@ -868,11 +784,11 @@ ed_prev_line(EditLine *el, int 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, int c __attribute__((__unused__))) +ed_next_line(EditLine *el, wint_t c __attribute__((__unused__))) { - char *ptr; + wchar_t *ptr; int nchars = c_hpos(el); /* @@ -883,7 +799,7 @@ ed_next_line(EditLine *el, int c __attribute__((__unused__))) break; if (el->el_state.argument > 0) - return (CC_ERROR); + return CC_ERROR; /* * Move to the character requested @@ -894,7 +810,7 @@ ed_next_line(EditLine *el, int c __attribute__((__unused__))) continue; el->el_line.cursor = ptr; - return (CC_CURSOR); + return CC_CURSOR; } @@ -902,18 +818,18 @@ ed_next_line(EditLine *el, int c __attribute__((__unused__))) * Editline extended command * [M-X] [:] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -ed_command(EditLine *el, int c __attribute__((__unused__))) +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, "\n: "); - term__putc(el, '\n'); + tmplen = c_gets(el, tmpbuf, L"\n: "); + terminal__putc(el, '\n'); if (tmplen < 0 || (tmpbuf[tmplen] = 0, parse_line(el, tmpbuf)) == -1) - term_beep(el); + terminal_beep(el); el->el_map.current = el->el_map.key; re_clear_display(el); diff --git a/clt/falcon/editline/src/editline/readline.h b/clt/falcon/editline/src/editline/readline.h index c4a5aa10b..2bd0b7e80 100644 --- a/clt/falcon/editline/src/editline/readline.h +++ b/clt/falcon/editline/src/editline/readline.h @@ -1,4 +1,4 @@ -/* $NetBSD: readline.h,v 1.30 2009/09/07 21:24:34 christos Exp $ */ +/* $NetBSD: readline.h,v 1.53 2022/02/19 17:45:02 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -38,12 +38,14 @@ /* typedefs */ typedef int Function(const char *, int); +typedef char *CPFunction(const char *, int); typedef void VFunction(void); -typedef void VCPFunction(char *); -typedef char *CPFunction(const char *, int); -typedef char **CPPFunction(const char *, int, int); +typedef 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); +typedef int rl_icppfunc_t(char **); /* only supports length */ typedef struct { @@ -54,7 +56,7 @@ typedef void *histdata_t; typedef struct _hist_entry { const char *line; - histdata_t data; + histdata_t data; } HIST_ENTRY; typedef struct _keymap_entry { @@ -88,42 +90,55 @@ typedef KEYMAP_ENTRY *Keymap; #define RUBOUT 0x7f #define ABORT_CHAR CTRL('G') -#define RL_READLINE_VERSION 0x0402 +#define RL_READLINE_VERSION 0x0402 #define RL_PROMPT_START_IGNORE '\1' #define RL_PROMPT_END_IGNORE '\2' +#define RL_STATE_NONE 0x000000 +#define RL_STATE_DONE 0x000001 + +#define RL_SETSTATE(x) (rl_readline_state |= ((unsigned long) x)) +#define RL_UNSETSTATE(x) (rl_readline_state &= ~((unsigned long) x)) +#define RL_ISSTATE(x) (rl_readline_state & ((unsigned long) x)) + /* global variables used by readline enabled applications */ #ifdef __cplusplus extern "C" { #endif extern const char *rl_library_version; -extern int rl_readline_version; -extern char *rl_readline_name; +extern int rl_readline_version; +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_quote_characters; +extern const char *rl_basic_word_break_characters; extern char *rl_completer_word_break_characters; -extern char *rl_completer_quote_characters; -extern Function *rl_completion_entry_function; -extern CPPFunction *rl_attempted_completion_function; +extern 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; -extern Function *rl_startup_hook; +extern rl_hook_func_t *rl_pre_input_hook; +extern rl_hook_func_t *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 */ +extern unsigned long rl_readline_state; +extern int rl_catch_signals; +extern int rl_catch_sigwinch; extern KEYMAP_ENTRY_ARRAY emacs_standard_keymap, emacs_meta_keymap, emacs_ctlx_keymap; @@ -134,8 +149,18 @@ 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; +extern int _rl_complete_mark_directories; +extern rl_icppfunc_t *rl_directory_completion_hook; +extern int rl_completion_suppress_append; +extern int rl_sort_completion_matches; +extern int _rl_completion_prefix_display_length; +extern int _rl_echoing_p; +extern int history_max_entries; +extern char *rl_display_prompt; +extern int rl_erase_empty_line; /* supported functions */ char *readline(const char *); @@ -144,6 +169,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); @@ -151,18 +177,18 @@ int where_history(void); HIST_ENTRY *current_history(void); HIST_ENTRY *history_get(int); HIST_ENTRY *remove_history(int); -/*###152 [lint] syntax error 'histdata_t' [249]%%%*/ HIST_ENTRY *replace_history_entry(int, const char *, histdata_t); int history_total_bytes(void); int history_set_pos(int); HIST_ENTRY *previous_history(void); HIST_ENTRY *next_history(void); +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); int read_history(const char *); int write_history(const char *); -int history_truncate_file (const char *, int); +int history_truncate_file(const char *, int); int history_expand(char *, char **); char **history_tokenize(const char *); const char *get_history_event(const char *, int *, int); @@ -173,16 +199,17 @@ char *filename_completion_function(const char *, int); char *username_completion_function(const char *, int); int rl_complete(int, int); int rl_read_key(void); -char **completion_matches(const char *, CPFunction *); +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); -void rl_callback_handler_install(const char *, VCPFunction *); +void rl_callback_handler_install(const char *, rl_vcpfunc_t *); void rl_callback_handler_remove(void); void rl_redisplay(void); int rl_get_previous_history(int, int); @@ -191,17 +218,29 @@ void rl_deprep_terminal(void); int rl_read_init_file(const char *); int rl_parse_and_bind(const char *); int rl_variable_bind(const char *, const char *); -void rl_stuff_char(int); -int rl_add_defun(const char *, Function *, int); +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 *); void rl_set_screen_size(int, int); -char *rl_filename_completion_function (const char *, int); +char *rl_filename_completion_function(const char *, int); int _rl_abort_internal(void); int _rl_qsort_string_compare(char **, char **); -char **rl_completion_matches(const char *, rl_compentry_func_t *); +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); +int rl_crlf(void); +int rl_ding(void); +char *rl_copy_text(int, int); +void rl_replace_line(const char *, int); +int rl_delete_text(int, int); +void rl_message(const char *format, ...) + __attribute__((__format__(__printf__, 1, 2))); +void rl_save_prompt(void); +void rl_restore_prompt(void); /* * The following are not implemented @@ -212,8 +251,15 @@ void rl_set_keymap(Keymap); Keymap rl_make_bare_keymap(void); int rl_generic_bind(int, const char *, const char *, Keymap); int rl_bind_key_in_map(int, rl_command_func_t *, Keymap); +int rl_set_key(const char *, rl_command_func_t *, Keymap); void rl_cleanup_after_signal(void); void rl_free_line_state(void); +int rl_set_keyboard_input_timeout(int); +int rl_abort(int, int); +int rl_set_keymap_name(const char *, Keymap); +histdata_t free_history_entry(HIST_ENTRY *); +void _rl_erase_entire_line(void); + #ifdef __cplusplus } #endif diff --git a/clt/falcon/editline/src/el.c b/clt/falcon/editline/src/el.c index a92ee1de9..4faf1cfc2 100644 --- a/clt/falcon/editline/src/el.c +++ b/clt/falcon/editline/src/el.c @@ -1,4 +1,4 @@ -/* $NetBSD: el.c,v 1.55 2009/07/25 21:19:23 christos Exp $ */ +/* $NetBSD: el.c,v 1.100 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)el.c 8.2 (Berkeley) 1/3/94"; #else -__RCSID("$NetBSD: el.c,v 1.55 2009/07/25 21:19:23 christos Exp $"); +__RCSID("$NetBSD: el.c,v 1.100 2021/08/15 10:08:41 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -50,33 +50,69 @@ __RCSID("$NetBSD: el.c,v 1.55 2009/07/25 21:19:23 christos Exp $"); */ #include #include -#include -#include -#include #include +#include +#include +#include +#include +#include + #include "el.h" +#include "parse.h" +#include "read.h" + +#ifndef HAVE_SECURE_GETENV +# ifdef HAVE___SECURE_GETENV +# define secure_getenv __secure_getenv +# define HAVE_SECURE_GETENV 1 +# else +# ifdef HAVE_ISSETUGID +# include +# else +# undef issetugid +# define issetugid() 1 +# endif +# endif +#endif + +#ifndef HAVE_SECURE_GETENV +char *secure_getenv(char const *name) +{ + if (issetugid()) + return 0; + return getenv(name); +} +#endif /* el_init(): * Initialize editline and set default parameters. */ -public EditLine * +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)); +} - EditLine *el = (EditLine *) el_malloc(sizeof(EditLine)); +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_calloc(1, sizeof(*el)); if (el == NULL) - return (NULL); - - memset(el, 0, sizeof(EditLine)); + return NULL; el->el_infile = fin; el->el_outfile = fout; el->el_errfile = ferr; - el->el_infd = fileno(fin); + el->el_infd = fdin; + el->el_outfd = fdout; + el->el_errfd = fderr; - if ((el->el_prog = el_strdup(prog)) == NULL) { + el->el_prog = wcsdup(ct_decode_string(prog, &el->el_scratch)); + if (el->el_prog == NULL) { el_free(el); return NULL; } @@ -84,14 +120,14 @@ el_init(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 (term_init(el) == -1) { + if (terminal_init(el) == -1) { el_free(el->el_prog); el_free(el); return NULL; } - (void) key_init(el); + (void) keymacro_init(el); (void) map_init(el); if (tty_init(el) == -1) el->el_flags |= NO_TTY; @@ -100,16 +136,25 @@ el_init(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); - - return (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) { @@ -118,44 +163,53 @@ el_end(EditLine *el) el_reset(el); - term_end(el); - key_end(el); + terminal_end(el); + keymacro_end(el); map_end(el); - tty_end(el); + if (!(el->el_flags & NO_TTY)) + tty_end(el, TCSAFLUSH); ch_end(el); + read_end(el->el_read); search_end(el); hist_end(el); prompt_end(el); sig_end(el); - - el_free((ptr_t) el->el_prog); - el_free((ptr_t) el); + literal_end(el); + + el_free(el->el_prog); + 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); + el_free(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 -el_set(EditLine *el, int op, ...) +int +el_wset(EditLine *el, int op, ...) { va_list ap; int rv = 0; if (el == NULL) - return (-1); + return -1; va_start(ap, op); switch (op) { @@ -163,25 +217,39 @@ el_set(EditLine *el, int op, ...) case EL_RPROMPT: { el_pfunc_t p = va_arg(ap, el_pfunc_t); - rv = prompt_set(el, p, 0, op); + rv = prompt_set(el, p, 0, op, 1); + break; + } + + case EL_RESIZE: { + el_zfunc_t p = va_arg(ap, el_zfunc_t); + void *arg = va_arg(ap, void *); + rv = ch_resizefun(el, p, arg); + break; + } + + case EL_ALIAS_TEXT: { + el_afunc_t p = va_arg(ap, el_afunc_t); + void *arg = va_arg(ap, void *); + rv = ch_aliasfun(el, p, arg); break; } case EL_PROMPT_ESC: case EL_RPROMPT_ESC: { el_pfunc_t p = va_arg(ap, el_pfunc_t); - char c = va_arg(ap, int); + int c = va_arg(ap, int); - rv = prompt_set(el, p, c, op); + rv = prompt_set(el, p, (wchar_t)c, op, 1); break; } case EL_TERMINAL: - rv = term_set(el, va_arg(ap, char *)); + rv = terminal_set(el, va_arg(ap, char *)); 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: @@ -194,40 +262,39 @@ el_set(EditLine *el, int op, ...) case EL_BIND: case EL_TELLTC: case EL_SETTC: - case EL_GETTC: case EL_ECHOTC: case EL_SETTY: { - const char *argv[20]; + const wchar_t *argv[20]; int i; - for (i = 1; i < 20; i++) - if ((argv[i] = va_arg(ap, char *)) == NULL) + for (i = 1; i < (int)__arraycount(argv); i++) + if ((argv[i] = va_arg(ap, wchar_t *)) == NULL) break; switch (op) { case EL_BIND: - argv[0] = "bind"; + argv[0] = L"bind"; rv = map_bind(el, i, argv); break; case EL_TELLTC: - argv[0] = "telltc"; - rv = term_telltc(el, i, argv); + argv[0] = L"telltc"; + rv = terminal_telltc(el, i, argv); break; case EL_SETTC: - argv[0] = "settc"; - rv = term_settc(el, i, argv); + argv[0] = L"settc"; + rv = terminal_settc(el, i, argv); break; case EL_ECHOTC: - argv[0] = "echotc"; - rv = term_echotc(el, i, argv); + argv[0] = L"echotc"; + rv = terminal_echotc(el, i, argv); break; case EL_SETTY: - argv[0] = "setty"; + argv[0] = L"setty"; rv = tty_stty(el, i, argv); break; @@ -241,8 +308,8 @@ 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); @@ -252,12 +319,22 @@ el_set(EditLine *el, int op, ...) case EL_HIST: { hist_fun_t func = va_arg(ap, hist_fun_t); - ptr_t ptr = va_arg(ap, char *); + void *ptr = va_arg(ap, void *); rv = hist_set(el, func, ptr); + if (MB_CUR_MAX == 1) + el->el_flags &= ~NARROW_HISTORY; break; } + case EL_SAFEREAD: + if (va_arg(ap, int)) + el->el_flags |= FIXIO; + else + el->el_flags &= ~FIXIO; + rv = 0; + break; + case EL_EDITMODE: if (va_arg(ap, int)) el->el_flags &= ~EDIT_DISABLED; @@ -269,7 +346,7 @@ 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; } @@ -314,9 +391,11 @@ el_set(EditLine *el, int op, ...) break; case 1: el->el_outfile = fp; + el->el_outfd = fileno(fp); break; case 2: el->el_errfile = fp; + el->el_errfd = fileno(fp); break; default: rv = -1; @@ -328,7 +407,7 @@ el_set(EditLine *el, int op, ...) case EL_REFRESH: re_clear_display(el); re_refresh(el); - term__flush(el); + terminal__flush(el); break; default: @@ -337,15 +416,15 @@ el_set(EditLine *el, int op, ...) } va_end(ap); - return (rv); + return rv; } /* el_get(): * retrieve the editline parameters */ -public int -el_get(EditLine *el, int op, ...) +int +el_wget(EditLine *el, int op, ...) { va_list ap; int rv; @@ -359,14 +438,20 @@ el_get(EditLine *el, int op, ...) case EL_PROMPT: case EL_RPROMPT: { el_pfunc_t *p = va_arg(ap, el_pfunc_t *); - char *c = va_arg(ap, char *); + rv = prompt_get(el, p, 0, op); + break; + } + case EL_PROMPT_ESC: + case EL_RPROMPT_ESC: { + el_pfunc_t *p = va_arg(ap, el_pfunc_t *); + 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: @@ -379,57 +464,29 @@ el_get(EditLine *el, int op, ...) rv = 0; break; + case EL_SAFEREAD: + *va_arg(ap, int *) = (el->el_flags & FIXIO); + rv = 0; + break; + case EL_TERMINAL: - term_get(el, va_arg(ap, const char **)); + terminal_get(el, va_arg(ap, const char **)); rv = 0; break; case EL_GETTC: { static char name[] = "gettc"; - char *argv[20]; - int i; - - for (i = 1; i < (int)(sizeof(argv) / sizeof(argv[0])); i++) - if ((argv[i] = va_arg(ap, char *)) == NULL) - break; - - switch (op) { - case EL_GETTC: - argv[0] = name; - rv = term_gettc(el, i, argv); - break; - - default: - rv = -1; - EL_ABORT((el->el_errfile, "Bad op %d\n", op)); - break; - } - break; - } - -#if 0 /* XXX */ - case EL_ADDFN: - { - char *name = va_arg(ap, char *); - char *help = va_arg(ap, char *); - el_func_t func = va_arg(ap, el_func_t); - - rv = map_addfunc(el, name, help, func); + char *argv[3]; + argv[0] = name; + argv[1] = va_arg(ap, char *); + argv[2] = va_arg(ap, void *); + rv = terminal_gettc(el, 3, argv); break; } - case EL_HIST: - { - hist_fun_t func = va_arg(ap, hist_fun_t); - ptr_t ptr = va_arg(ap, char *); - rv = hist_set(el, func, ptr); - } - break; -#endif /* XXX */ - 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; @@ -439,7 +496,7 @@ el_get(EditLine *el, int op, ...) break; case EL_UNBUFFERED: - *va_arg(ap, int *) = (!(el->el_flags & UNBUFFERED)); + *va_arg(ap, int *) = (el->el_flags & UNBUFFERED) != 0; rv = 0; break; @@ -473,79 +530,97 @@ el_get(EditLine *el, int op, ...) } va_end(ap); - return (rv); + return rv; } /* el_line(): * Return editing info */ -public const LineInfo * -el_line(EditLine *el) +const LineInfoW * +el_wline(EditLine *el) { - return (const 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; size_t len; + ssize_t slen; char *ptr; - char path[MAXPATHLEN]; + char *path = NULL; + const wchar_t *dptr; + int error = 0; fp = NULL; if (fname == NULL) { - static const char elpath[] = "/.editrc"; -#ifdef HAVE_ISSETUGID - if (issetugid()) - return (-1); -#endif - if ((ptr = getenv("HOME")) == NULL) - return (-1); - if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) - return (-1); - if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) - return (-1); - fname = path; + /* secure_getenv is guaranteed to be defined and do the right thing here */ + /* because of the defines above which take into account issetugid, */ + /* secure_getenv and __secure_getenv availability. */ + if ((fname = secure_getenv("EDITRC")) == NULL) { + static const char elpath[] = "/.editrc"; + size_t plen = sizeof(elpath); + + if ((ptr = secure_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; + } + } + if (fname[0] == '\0') + return -1; + if (fp == NULL) fp = fopen(fname, "r"); - if (fp == NULL) - return (-1); - - while ((ptr = fgetln(fp, &len)) != NULL) { - if (len > 0 && ptr[len - 1] == '\n') - --len; - ptr[len] = '\0'; + if (fp == NULL) { + el_free(path); + return -1; + } + ptr = NULL; + len = 0; + while ((slen = getline(&ptr, &len, fp)) != -1) { + if (*ptr == '\n') + continue; /* Empty line. */ + if (slen > 0 && ptr[--slen] == '\n') + ptr[slen] = '\0'; + + dptr = ct_decode_string(ptr, &el->el_scratch); + if (!dptr) + continue; /* loop until first non-space char or EOL */ - while (*ptr != '\0' && isspace((unsigned char)*ptr)) - ptr++; - if (*ptr == '#') + while (*dptr != '\0' && iswspace(*dptr)) + dptr++; + if (*dptr == '#') continue; /* ignore, this is a comment line */ - - if (parse_line(el, ptr) == -1) { - (void) fclose(fp); - return (-1); - } + if ((error = parse_line(el, dptr)) == -1) + break; } + free(ptr); + el_free(path); (void) fclose(fp); - return (0); + return error; } /* el_resize(): * Called from program when terminal is resized */ -public void +void el_resize(EditLine *el) { int lins, cols; @@ -556,8 +631,8 @@ el_resize(EditLine *el) (void) sigprocmask(SIG_BLOCK, &nset, &oset); /* get the correct window size */ - if (term_get_size(el, &lins, &cols)) - term_change_size(el, lins, cols); + if (terminal_get_size(el, &lins, &cols)) + terminal_change_size(el, lins, cols); (void) sigprocmask(SIG_SETMASK, &oset, NULL); } @@ -566,37 +641,38 @@ el_resize(EditLine *el) /* el_beep(): * Called from the program to beep */ -public void +void el_beep(EditLine *el) { - term_beep(el); + terminal_beep(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); + return -1; how = argv[1]; - if (strcmp(how, "on") == 0) { + if (wcscmp(how, L"on") == 0) { el->el_flags &= ~EDIT_DISABLED; tty_rawmode(el); - } else if (strcmp(how, "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 `%s'.\n", how); - return (-1); + (void) fprintf(el->el_errfile, "edit: Bad value `%ls'.\n", + how); + return -1; } - return (0); + return 0; } diff --git a/clt/falcon/editline/src/el.h b/clt/falcon/editline/src/el.h index c2a27d609..757137839 100644 --- a/clt/falcon/editline/src/el.h +++ b/clt/falcon/editline/src/el.h @@ -1,4 +1,4 @@ -/* $NetBSD: el.h,v 1.18 2009/02/15 21:24:13 christos Exp $ */ +/* $NetBSD: el.h,v 1.46 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -46,17 +46,18 @@ #define VIDEFAULT #define ANCHOR -#include -#include +#include "histedit.h" +#include "chartype.h" -#define EL_BUFSIZ 1024 /* Maximum line size */ +#define EL_BUFSIZ ((size_t)1024) /* Maximum line size */ -#define HANDLE_SIGNALS 0x01 -#define NO_TTY 0x02 -#define EDIT_DISABLED 0x04 -#define UNBUFFERED 0x08 - -typedef int bool_t; /* True or not */ +#define HANDLE_SIGNALS 0x001 +#define NO_TTY 0x002 +#define EDIT_DISABLED 0x004 +#define UNBUFFERED 0x008 +#define NARROW_HISTORY 0x040 +#define NO_RESET 0x080 +#define FIXIO 0x100 typedef unsigned char el_action_t; /* Index to command array */ @@ -66,10 +67,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; /* @@ -81,62 +82,69 @@ typedef struct el_state_t { int argument; /* Numeric argument */ int metanext; /* Is the next char a meta char */ el_action_t lastcmd; /* Previous command */ - el_action_t thiscmd; /* this command */ - char thisch; /* char that generated it */ + el_action_t thiscmd; /* this command */ + wchar_t thisch; /* char that generated it */ } el_state_t; /* * Until we come up with something better... */ -#define el_strdup(a) strdup(a) #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 "key.h" -#include "el_term.h" +#include "literal.h" +#include "keymacro.h" +#include "terminal.h" #include "refresh.h" #include "chared.h" -#include "common.h" #include "search.h" #include "hist.h" #include "map.h" -#include "parse.h" #include "sig.h" -#include "help.h" -#include "read.h" + +struct 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 */ int el_infd; /* Input file descriptor */ + int el_outfd; /* Output file descriptor */ + int el_errfd; /* Error file descriptor */ int el_flags; /* Various flags. */ - int el_errno; /* Local copy of errno */ coord_t el_cursor; /* Cursor location */ - char **el_display; /* Real screen image = what is there */ - char **el_vdisplay; /* Virtual screen image = what we see */ + 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 */ - el_term_t el_term; /* Terminal dependent stuff */ + el_terminal_t el_terminal; /* Terminal dependent stuff */ el_tty_t el_tty; /* Tty dependent stuff */ el_refresh_t el_refresh; /* Refresh stuff */ el_prompt_t el_prompt; /* Prompt stuff */ el_prompt_t el_rprompt; /* Prompt stuff */ + el_literal_t el_literal; /* prompt literal bits */ el_chared_t el_chared; /* Characted editor stuff */ el_map_t el_map; /* Key mapping stuff */ - el_key_t el_key; /* Key binding 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 */ + 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 */ }; -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 { \ diff --git a/clt/falcon/editline/src/eln.c b/clt/falcon/editline/src/eln.c new file mode 100644 index 000000000..563ec2a67 --- /dev/null +++ b/clt/falcon/editline/src/eln.c @@ -0,0 +1,394 @@ +/* $NetBSD: eln.c,v 1.37 2022/01/11 18:30:15 christos Exp $ */ + +/*- + * Copyright (c) 2009 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "config.h" +#if !defined(lint) && !defined(SCCSID) +__RCSID("$NetBSD: eln.c,v 1.37 2022/01/11 18:30:15 christos Exp $"); +#endif /* not lint && not SCCSID */ + +#include +#include +#include +#include + +#include "el.h" + +int +el_getc(EditLine *el, char *cp) +{ + int num_read; + wchar_t wc = 0; + + num_read = el_wgetc(el, &wc); + *cp = '\0'; + if (num_read <= 0) + return num_read; + num_read = wctob(wc); + if (num_read == EOF) { + errno = ERANGE; + return -1; + } else { + *cp = (char)num_read; + return 1; + } +} + + +void +el_push(EditLine *el, const char *str) +{ + /* Using multibyte->wide string decoding works fine under single-byte + * character sets too, and Does The Right Thing. */ + el_wpush(el, ct_decode_string(str, &el->el_lgcyconv)); +} + + +const char * +el_gets(EditLine *el, int *nread) +{ + const wchar_t *tmp; + + tmp = el_wgets(el, nread); + if (tmp != NULL) { + int i; + size_t nwread = 0; + + for (i = 0; i < *nread; i++) + nwread += ct_enc_width(tmp[i]); + *nread = (int)nwread; + } + return ct_encode_string(tmp, &el->el_lgcyconv); +} + + +int +el_parse(EditLine *el, int argc, const char *argv[]) +{ + int ret; + const wchar_t **wargv; + + wargv = (void *)ct_decode_argv(argc, argv, &el->el_lgcyconv); + if (!wargv) + return -1; + ret = el_wparse(el, argc, wargv); + el_free(wargv); + + return ret; +} + + +int +el_set(EditLine *el, int op, ...) +{ + va_list ap; + int ret; + + if (!el) + return -1; + va_start(ap, op); + + switch (op) { + case EL_PROMPT: /* el_pfunc_t */ + case EL_RPROMPT: { + el_pfunc_t p = va_arg(ap, el_pfunc_t); + ret = prompt_set(el, p, 0, op, 0); + break; + } + + case EL_RESIZE: { + el_zfunc_t p = va_arg(ap, el_zfunc_t); + void *arg = va_arg(ap, void *); + ret = ch_resizefun(el, p, arg); + break; + } + + case EL_ALIAS_TEXT: { + el_afunc_t p = va_arg(ap, el_afunc_t); + void *arg = va_arg(ap, void *); + ret = ch_aliasfun(el, p, arg); + break; + } + + case EL_PROMPT_ESC: + case EL_RPROMPT_ESC: { + el_pfunc_t p = va_arg(ap, el_pfunc_t); + int c = va_arg(ap, int); + + ret = prompt_set(el, p, c, op, 0); + break; + } + + case EL_TERMINAL: /* const char * */ + ret = el_wset(el, op, va_arg(ap, char *)); + break; + + case EL_EDITOR: /* const wchar_t * */ + ret = el_wset(el, op, ct_decode_string(va_arg(ap, char *), + &el->el_lgcyconv)); + break; + + case EL_SIGNAL: /* int */ + case EL_EDITMODE: + case EL_SAFEREAD: + case EL_UNBUFFERED: + case EL_PREP_TERM: + ret = el_wset(el, op, va_arg(ap, int)); + break; + + case EL_BIND: /* const char * list -> const wchar_t * list */ + case EL_TELLTC: + case EL_SETTC: + case EL_ECHOTC: + case EL_SETTY: { + const char *argv[20]; + int i; + const wchar_t **wargv; + for (i = 1; i < (int)__arraycount(argv) - 1; ++i) + if ((argv[i] = va_arg(ap, const char *)) == NULL) + break; + argv[0] = argv[i] = NULL; + wargv = (void *)ct_decode_argv(i + 1, argv, &el->el_lgcyconv); + if (!wargv) { + ret = -1; + goto out; + } + /* + * AFAIK we can't portably pass through our new wargv to + * el_wset(), so we have to reimplement the body of + * el_wset() for these ops. + */ + switch (op) { + case EL_BIND: + wargv[0] = L"bind"; + ret = map_bind(el, i, wargv); + break; + case EL_TELLTC: + wargv[0] = L"telltc"; + ret = terminal_telltc(el, i, wargv); + break; + case EL_SETTC: + wargv[0] = L"settc"; + ret = terminal_settc(el, i, wargv); + break; + case EL_ECHOTC: + wargv[0] = L"echotc"; + ret = terminal_echotc(el, i, wargv); + break; + case EL_SETTY: + wargv[0] = L"setty"; + ret = tty_stty(el, i, wargv); + break; + default: + ret = -1; + } + el_free(wargv); + break; + } + + /* XXX: do we need to change el_func_t too? */ + case EL_ADDFN: { /* const char *, const char *, el_func_t */ + const char *args[2]; + el_func_t func; + wchar_t **wargv; + + args[0] = va_arg(ap, const char *); + args[1] = va_arg(ap, const char *); + func = va_arg(ap, el_func_t); + + wargv = ct_decode_argv(2, args, &el->el_lgcyconv); + if (!wargv) { + ret = -1; + goto out; + } + /* XXX: The two strdup's leak */ + ret = map_addfunc(el, wcsdup(wargv[0]), wcsdup(wargv[1]), + func); + el_free(wargv); + break; + } + case EL_HIST: { /* hist_fun_t, const char * */ + hist_fun_t fun = va_arg(ap, hist_fun_t); + void *ptr = va_arg(ap, void *); + ret = hist_set(el, fun, ptr); + el->el_flags |= NARROW_HISTORY; + break; + } + + case EL_GETCFN: /* el_rfunc_t */ + ret = el_wset(el, op, va_arg(ap, el_rfunc_t)); + break; + + case EL_CLIENTDATA: /* void * */ + ret = el_wset(el, op, va_arg(ap, void *)); + break; + + case EL_SETFP: { /* int, FILE * */ + int what = va_arg(ap, int); + FILE *fp = va_arg(ap, FILE *); + ret = el_wset(el, op, what, fp); + break; + } + + case EL_REFRESH: + re_clear_display(el); + re_refresh(el); + terminal__flush(el); + ret = 0; + break; + + default: + ret = -1; + break; + } + +out: + va_end(ap); + return ret; +} + + +int +el_get(EditLine *el, int op, ...) +{ + va_list ap; + int ret; + + if (!el) + return -1; + + va_start(ap, op); + + switch (op) { + case EL_PROMPT: /* el_pfunc_t * */ + case EL_RPROMPT: { + el_pfunc_t *p = va_arg(ap, el_pfunc_t *); + ret = prompt_get(el, p, 0, op); + break; + } + + case EL_PROMPT_ESC: /* el_pfunc_t *, char **/ + case EL_RPROMPT_ESC: { + el_pfunc_t *p = va_arg(ap, el_pfunc_t *); + char *c = va_arg(ap, char *); + wchar_t wc = 0; + ret = prompt_get(el, p, &wc, op); + *c = (char)wc; + break; + } + + case EL_EDITOR: { + const char **p = va_arg(ap, const char **); + const wchar_t *pw; + ret = el_wget(el, op, &pw); + *p = ct_encode_string(pw, &el->el_lgcyconv); + if (!el->el_lgcyconv.csize) + ret = -1; + break; + } + + case EL_TERMINAL: /* const char ** */ + ret = el_wget(el, op, va_arg(ap, const char **)); + break; + + case EL_SIGNAL: /* int * */ + case EL_EDITMODE: + case EL_SAFEREAD: + case EL_UNBUFFERED: + case EL_PREP_TERM: + ret = el_wget(el, op, va_arg(ap, int *)); + break; + + case EL_GETTC: { + char *argv[3]; + static char gettc[] = "gettc"; + argv[0] = gettc; + argv[1] = va_arg(ap, char *); + argv[2] = va_arg(ap, void *); + ret = terminal_gettc(el, 3, argv); + break; + } + + case EL_GETCFN: /* el_rfunc_t */ + ret = el_wget(el, op, va_arg(ap, el_rfunc_t *)); + break; + + case EL_CLIENTDATA: /* void ** */ + ret = el_wget(el, op, va_arg(ap, void **)); + break; + + case EL_GETFP: { /* int, FILE ** */ + int what = va_arg(ap, int); + FILE **fpp = va_arg(ap, FILE **); + ret = el_wget(el, op, what, fpp); + break; + } + + default: + ret = -1; + break; + } + + va_end(ap); + return ret; +} + + +const LineInfo * +el_line(EditLine *el) +{ + const LineInfoW *winfo = el_wline(el); + LineInfo *info = &el->el_lgcylinfo; + size_t offset; + const wchar_t *p; + + info->buffer = ct_encode_string(winfo->buffer, &el->el_lgcyconv); + + offset = 0; + for (p = winfo->buffer; p < winfo->cursor; p++) + offset += ct_enc_width(*p); + info->cursor = info->buffer + offset; + + offset = 0; + for (p = winfo->buffer; p < winfo->lastchar; p++) + offset += ct_enc_width(*p); + info->lastchar = info->buffer + offset; + + return info; +} + + +int +el_insertstr(EditLine *el, const char *str) +{ + return el_winsertstr(el, ct_decode_string(str, &el->el_lgcyconv)); +} + +int +el_replacestr(EditLine *el, const char *str) +{ + return el_wreplacestr(el, ct_decode_string(str, &el->el_lgcyconv)); +} diff --git a/clt/falcon/editline/src/emacs.c b/clt/falcon/editline/src/emacs.c index 54e29bc84..0636c28b2 100644 --- a/clt/falcon/editline/src/emacs.c +++ b/clt/falcon/editline/src/emacs.c @@ -1,4 +1,4 @@ -/* $NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $ */ +/* $NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,37 +37,41 @@ #if 0 static char sccsid[] = "@(#)emacs.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: emacs.c,v 1.22 2009/02/15 21:55:23 christos Exp $"); +__RCSID("$NetBSD: emacs.c,v 1.36 2016/05/09 21:46:56 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* * emacs.c: Emacs functions */ +#include + #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, int c) +em_delete_or_list(EditLine *el, wint_t c) { if (el->el_line.cursor == el->el_line.lastchar) { /* if I'm at the end */ if (el->el_line.cursor == el->el_line.buffer) { /* and the beginning */ - term_writec(el, c); /* then do an EOF */ - return (CC_EOF); + terminal_writec(el, c); /* then do an EOF */ + return CC_EOF; } else { /* * Here we could list completions, but it is an * error right now */ - term_beep(el); - return (CC_ERROR); + terminal_beep(el); + return CC_ERROR; } } else { if (el->el_state.doingarg) @@ -77,7 +81,7 @@ em_delete_or_list(EditLine *el, int c) if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; /* bounds check */ - return (CC_REFRESH); + return CC_REFRESH; } } @@ -86,14 +90,14 @@ em_delete_or_list(EditLine *el, int 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, int c __attribute__((__unused__))) +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); + return CC_ERROR; cp = c__next_word(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, ce__isword); @@ -107,7 +111,7 @@ em_delete_next_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; /* bounds check */ - return (CC_REFRESH); + return CC_REFRESH; } @@ -115,19 +119,19 @@ em_delete_next_word(EditLine *el, int c __attribute__((__unused__))) * Paste cut buffer at cursor position * [^Y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_yank(EditLine *el, int c __attribute__((__unused__))) +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); + return CC_NORM; if (el->el_line.lastchar + (el->el_chared.c_kill.last - el->el_chared.c_kill.buf) >= el->el_line.limit) - return (CC_ERROR); + return CC_ERROR; el->el_chared.c_kill.mark = el->el_line.cursor; cp = el->el_line.cursor; @@ -143,7 +147,7 @@ em_yank(EditLine *el, int c __attribute__((__unused__))) if (el->el_state.argument == 1) el->el_line.cursor = cp; - return (CC_REFRESH); + return CC_REFRESH; } @@ -151,11 +155,11 @@ em_yank(EditLine *el, int 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, int c __attribute__((__unused__))) +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; @@ -165,7 +169,7 @@ em_kill_line(EditLine *el, int c __attribute__((__unused__))) /* zap! -- delete all of it */ el->el_line.lastchar = el->el_line.buffer; el->el_line.cursor = el->el_line.buffer; - return (CC_REFRESH); + return CC_REFRESH; } @@ -173,14 +177,14 @@ em_kill_line(EditLine *el, int 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, int c __attribute__((__unused__))) +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); + return CC_ERROR; if (el->el_chared.c_kill.mark > el->el_line.cursor) { cp = el->el_line.cursor; @@ -198,7 +202,7 @@ em_kill_region(EditLine *el, int c __attribute__((__unused__))) c_delbefore(el, (int)(cp - el->el_chared.c_kill.mark)); el->el_line.cursor = el->el_chared.c_kill.mark; } - return (CC_REFRESH); + return CC_REFRESH; } @@ -206,14 +210,14 @@ em_kill_region(EditLine *el, int 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, int c __attribute__((__unused__))) +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); + return CC_ERROR; if (el->el_chared.c_kill.mark > el->el_line.cursor) { cp = el->el_line.cursor; @@ -228,7 +232,7 @@ em_copy_region(EditLine *el, int c __attribute__((__unused__))) *kp++ = *cp++; /* copy it */ el->el_chared.c_kill.last = kp; } - return (CC_NORM); + return CC_NORM; } @@ -236,8 +240,8 @@ em_copy_region(EditLine *el, int c __attribute__((__unused__))) * Exchange the two characters before the cursor * Gosling emacs transpose chars [^T] */ -protected el_action_t -em_gosmacs_transpose(EditLine *el, int c) +libedit_private el_action_t +em_gosmacs_transpose(EditLine *el, wint_t c) { if (el->el_line.cursor > &el->el_line.buffer[1]) { @@ -245,9 +249,9 @@ em_gosmacs_transpose(EditLine *el, int c) c = el->el_line.cursor[-2]; el->el_line.cursor[-2] = el->el_line.cursor[-1]; el->el_line.cursor[-1] = c; - return (CC_REFRESH); + return CC_REFRESH; } else - return (CC_ERROR); + return CC_ERROR; } @@ -255,12 +259,12 @@ em_gosmacs_transpose(EditLine *el, int 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, int c __attribute__((__unused__))) +em_next_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.lastchar) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = c__next_word(el->el_line.cursor, el->el_line.lastchar, @@ -270,9 +274,9 @@ em_next_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -280,23 +284,23 @@ em_next_word(EditLine *el, int 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, int c __attribute__((__unused__))) +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((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); + if (iswlower(*cp)) + *cp = towupper(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; - return (CC_REFRESH); + return CC_REFRESH; } @@ -304,31 +308,31 @@ em_upper_case(EditLine *el, int 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, int c __attribute__((__unused__))) +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((unsigned char)*cp)) { - if (islower((unsigned char)*cp)) - *cp = toupper((unsigned char)*cp); + if (iswalpha(*cp)) { + if (iswlower(*cp)) + *cp = towupper(*cp); cp++; break; } } for (; cp < ep; cp++) - if (isupper((unsigned char)*cp)) - *cp = tolower((unsigned char)*cp); + if (iswupper(*cp)) + *cp = towlower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; - return (CC_REFRESH); + return CC_REFRESH; } @@ -336,23 +340,23 @@ em_capitol_case(EditLine *el, int 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, int c __attribute__((__unused__))) +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((unsigned char)*cp)) - *cp = tolower((unsigned char)*cp); + if (iswupper(*cp)) + *cp = towlower(*cp); el->el_line.cursor = ep; if (el->el_line.cursor > el->el_line.lastchar) el->el_line.cursor = el->el_line.lastchar; - return (CC_REFRESH); + return CC_REFRESH; } @@ -360,13 +364,13 @@ em_lower_case(EditLine *el, int c __attribute__((__unused__))) * Set the mark at cursor * [^@] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_set_mark(EditLine *el, int c __attribute__((__unused__))) +em_set_mark(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_chared.c_kill.mark = el->el_line.cursor; - return (CC_NORM); + return CC_NORM; } @@ -374,16 +378,16 @@ em_set_mark(EditLine *el, int 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, int c __attribute__((__unused__))) +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; el->el_chared.c_kill.mark = cp; - return (CC_CURSOR); + return CC_CURSOR; } @@ -391,16 +395,16 @@ em_exchange_mark(EditLine *el, int c __attribute__((__unused__))) * Universal argument (argument times 4) * [^U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_universal_argument(EditLine *el, int c __attribute__((__unused__))) +em_universal_argument(EditLine *el, wint_t c __attribute__((__unused__))) { /* multiply current argument by 4 */ if (el->el_state.argument > 1000000) - return (CC_ERROR); + return CC_ERROR; el->el_state.doingarg = 1; el->el_state.argument *= 4; - return (CC_ARGHACK); + return CC_ARGHACK; } @@ -408,41 +412,41 @@ em_universal_argument(EditLine *el, int c __attribute__((__unused__))) * Add 8th bit to next character typed * [] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_meta_next(EditLine *el, int c __attribute__((__unused__))) +em_meta_next(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_state.metanext = 1; - return (CC_ARGHACK); + return CC_ARGHACK; } /* 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, int c __attribute__((__unused__))) +em_toggle_overwrite(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_state.inputmode = (el->el_state.inputmode == MODE_INSERT) ? MODE_REPLACE : MODE_INSERT; - return (CC_NORM); + return CC_NORM; } /* 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, int c __attribute__((__unused__))) +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); + return CC_ERROR; oldc = el->el_line.cursor; /* does a bounds check */ @@ -455,33 +459,33 @@ em_copy_prev_word(EditLine *el, int c __attribute__((__unused__))) el->el_line.cursor = dp;/* put cursor at end */ - return (CC_REFRESH); + return CC_REFRESH; } /* em_inc_search_next(): * Emacs incremental next search */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_inc_search_next(EditLine *el, int c __attribute__((__unused__))) +em_inc_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_search.patlen = 0; - return (ce_inc_search(el, ED_SEARCH_NEXT_HISTORY)); + return ce_inc_search(el, ED_SEARCH_NEXT_HISTORY); } /* em_inc_search_prev(): * Emacs incremental reverse search */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -em_inc_search_prev(EditLine *el, int c __attribute__((__unused__))) +em_inc_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_search.patlen = 0; - return (ce_inc_search(el, ED_SEARCH_PREV_HISTORY)); + return ce_inc_search(el, ED_SEARCH_PREV_HISTORY); } @@ -489,13 +493,13 @@ em_inc_search_prev(EditLine *el, int 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, int c __attribute__((__unused__))) +em_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor <= el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; if (el->el_state.doingarg) c_delbefore(el, el->el_state.argument); @@ -504,5 +508,5 @@ em_delete_prev_char(EditLine *el, int c __attribute__((__unused__))) el->el_line.cursor -= el->el_state.argument; if (el->el_line.cursor < el->el_line.buffer) el->el_line.cursor = el->el_line.buffer; - return (CC_REFRESH); + return CC_REFRESH; } diff --git a/clt/falcon/editline/src/filecomplete.c b/clt/falcon/editline/src/filecomplete.c index 289a31183..f3f50c50d 100644 --- a/clt/falcon/editline/src/filecomplete.c +++ b/clt/falcon/editline/src/filecomplete.c @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.c,v 1.15 2009/02/16 00:15:45 christos Exp $ */ +/* $NetBSD: filecomplete.c,v 1.70 2022/03/12 15:29:17 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -28,53 +28,29 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ - -/* AIX requires this to be the first thing in the file. */ -#if defined (_AIX) && !defined (__GNUC__) - #pragma alloca -#endif - -#include -#ifdef __GNUC__ -# undef alloca -# define alloca(n) __builtin_alloca (n) -#else -# ifdef HAVE_ALLOCA_H -# include -# else -# ifndef _AIX -extern char *alloca (); -# endif -# endif -#endif +#include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: filecomplete.c,v 1.15 2009/02/16 00:15:45 christos Exp $"); +__RCSID("$NetBSD: filecomplete.c,v 1.70 2022/03/12 15:29:17 christos Exp $"); #endif /* not lint && not SCCSID */ #include #include -#include #include -#include +#include +#include +#include #include -#include +#include #include +#include #include -#include -#include -#include -#include #include "el.h" -#include "fcns.h" /* for EL_NUM_FCNS */ -#include "histedit.h" #include "filecomplete.h" -static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', - '>', '<', '=', ';', '|', '&', '{', '(', '\0' }; - +static const wchar_t break_chars[] = L" \t\n\"\\'`@$><=;|&{("; /********************************/ /* completion functions */ @@ -84,78 +60,267 @@ static char break_chars[] = { ' ', '\t', '\n', '"', '\\', '\'', '`', '@', '$', * if ``user'' isn't valid user name or ``txt'' doesn't start * w/ '~', returns pointer to strdup()ed copy of ``txt'' * - * it's callers's responsibility to free() returned string + * it's the caller's responsibility to free() the returned string */ char * fn_tilde_expand(const char *txt) { - struct passwd pwres, *pass; +#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT) + struct passwd pwres; + char pwbuf[1024]; +#endif + struct passwd *pass; + const char *pos; char *temp; size_t len = 0; - char pwbuf[1024]; if (txt[0] != '~') - return (strdup(txt)); + return strdup(txt); - temp = strchr(txt + 1, '/'); - if (temp == NULL) { + pos = strchr(txt + 1, '/'); + if (pos == NULL) { temp = strdup(txt + 1); if (temp == NULL) return NULL; } else { - len = temp - txt + 1; /* text until string after slash */ - temp = malloc(len); + /* text until string after slash */ + len = (size_t)(pos - txt + 1); + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; - (void)strncpy(temp, txt + 1, len - 2); - temp[len - 2] = '\0'; + (void)strlcpy(temp, txt + 1, len - 1); } if (temp[0] == 0) { -#if defined(__SUNPRO_C) - pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf)); -#elif defined(HAVE_GETPW_R_POSIX) - if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) +#ifdef HAVE_GETPW_R_POSIX + if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf), + &pass) != 0) pass = NULL; -#elif defined(HAVE_GETPW_R_DRAFT) +#elif HAVE_GETPW_R_DRAFT pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf)); -#else - pass = getpwuid(getuid()); +#else + pass = getpwuid(getuid()); #endif } else { -#if defined(__SUNPRO_C) - pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf)); -#elif defined(HAVE_GETPW_R_POSIX) +#ifdef HAVE_GETPW_R_POSIX if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0) pass = NULL; -#elif defined(HAVE_GETPW_R_DRAFT) +#elif HAVE_GETPW_R_DRAFT pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf)); #else pass = getpwnam(temp); #endif } - free(temp); /* value no more needed */ + el_free(temp); /* value no more needed */ if (pass == NULL) - return (strdup(txt)); + return strdup(txt); /* update pointer txt to point at string immedially following */ /* first slash */ txt += len; - temp = malloc(strlen(pass->pw_dir) + 1 + strlen(txt) + 1); + len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1; + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; - (void)sprintf(temp, "%s/%s", pass->pw_dir, txt); + (void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt); - return (temp); + return temp; } +static int +needs_escaping(wchar_t 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, unless it is already quoted + */ + if (temp[0] == '\'' && !d_quoted && + (temp == el->el_line.buffer || temp[-1] != '\\')) + 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(filename); + /* 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 * such file can be found * value of ``state'' is ignored * - * it's caller's responsibility to free returned string + * it's the caller's responsibility to free the returned string */ char * fn_filename_completion_function(const char *text, int state) @@ -165,30 +330,36 @@ fn_filename_completion_function(const char *text, int state) static size_t filename_len = 0; struct dirent *entry; char *temp; + const char *pos; size_t len; if (state == 0 || dir == NULL) { - temp = strrchr(text, '/'); - if (temp) { + pos = strrchr(text, '/'); + if (pos) { char *nptr; - temp++; - nptr = realloc(filename, strlen(temp) + 1); + pos++; + nptr = el_realloc(filename, (strlen(pos) + 1) * + sizeof(*nptr)); if (nptr == NULL) { - free(filename); + el_free(filename); + filename = NULL; return NULL; } filename = nptr; - (void)strcpy(filename, temp); - len = temp - text; /* including last slash */ - nptr = realloc(dirname, len + 1); + (void)strcpy(filename, pos); + len = (size_t)(pos - text); /* including last slash */ + + nptr = el_realloc(dirname, (len + 1) * + sizeof(*nptr)); if (nptr == NULL) { - free(filename); + el_free(dirname); + dirname = NULL; return NULL; } dirname = nptr; - (void)strncpy(dirname, text, len); - dirname[len] = '\0'; + (void)strlcpy(dirname, text, len + 1); } else { + el_free(filename); if (*text == 0) filename = NULL; else { @@ -196,6 +367,7 @@ fn_filename_completion_function(const char *text, int state) if (filename == NULL) return NULL; } + el_free(dirname); dirname = NULL; } @@ -205,12 +377,14 @@ fn_filename_completion_function(const char *text, int state) } /* support for ``~user'' syntax */ - free(dirpath); - - if (dirname == NULL && (dirname = strdup("./")) == NULL) - return NULL; - if (*dirname == '~') + el_free(dirpath); + dirpath = NULL; + if (dirname == NULL) { + if ((dirname = strdup("")) == NULL) + return NULL; + dirpath = strdup("./"); + } else if (*dirname == '~') dirpath = fn_tilde_expand(dirname); else dirpath = strdup(dirname); @@ -220,7 +394,7 @@ fn_filename_completion_function(const char *text, int state) dir = opendir(dirpath); if (!dir) - return (NULL); /* cannot open the directory */ + return NULL; /* cannot open the directory */ /* will be used in cycle */ filename_len = filename ? strlen(filename) : 0; @@ -249,17 +423,18 @@ fn_filename_completion_function(const char *text, int state) /* Some dirents have d_namlen, but it is not portable. */ len = strlen(entry->d_name); - temp = malloc(strlen(dirname) + len + 1); + len = strlen(dirname) + len + 1; + temp = el_calloc(len, sizeof(*temp)); if (temp == NULL) return NULL; - (void)sprintf(temp, "%s%s", dirname, entry->d_name); + (void)snprintf(temp, len, "%s%s", dirname, entry->d_name); } else { (void)closedir(dir); dir = NULL; temp = NULL; } - return (temp); + return temp; } @@ -276,7 +451,7 @@ append_char_function(const char *name) rs = "/"; out: if (expname) - free(expname); + el_free(expname); return rs; } /* @@ -299,10 +474,10 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int)) char **nmatch_list; while (matches + 3 >= match_list_len) match_list_len <<= 1; - nmatch_list = realloc(match_list, - match_list_len * sizeof(char *)); + nmatch_list = el_realloc(match_list, + match_list_len * sizeof(*nmatch_list)); if (nmatch_list == NULL) { - free(match_list); + el_free(match_list); return NULL; } match_list = nmatch_list; @@ -325,19 +500,18 @@ completion_matches(const char *text, char *(*genfunc)(const char *, int)) max_equal = i; } - retstr = malloc(max_equal + 1); + retstr = el_calloc(max_equal + 1, sizeof(*retstr)); if (retstr == NULL) { - free(match_list); + el_free(match_list); return NULL; } - (void)strncpy(retstr, match_list[1], max_equal); - retstr[max_equal] = '\0'; + (void)strlcpy(retstr, match_list[1], max_equal + 1); match_list[0] = retstr; /* add NULL as last pointer to the array */ - match_list[matches + 1] = (char *) NULL; + match_list[matches + 1] = NULL; - return (match_list); + return match_list; } /* @@ -354,41 +528,115 @@ _fn_qsort_string_compare(const void *i1, const void *i2) /* * 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'. + * 'matches' is list of strings, 'num' is number of strings in 'matches', + * 'width' is maximum length of string in 'matches'. + * + * matches[0] is not one of the match strings, but it is counted in + * num, so the strings are matches[1] *through* matches[num-1]. */ void -fn_display_match_list (EditLine *el, char **matches, size_t len, size_t max) +fn_display_match_list(EditLine * el, char **matches, size_t num, size_t width, + const char *(*app_func) (const char *)) { - size_t i, idx, limit, count; - int screenwidth = el->el_term.t_size.h; + 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++; + num--; /* - * Find out how many entries can be put on one line, count - * with two spaces between strings. + * Find out how many entries can be put on one line; count + * with one space between strings the same way it's printed. */ - limit = screenwidth / (max + 2); - if (limit == 0) - limit = 1; - - /* how many lines of output */ - count = len / limit; - if (count * limit < len) - count++; - - /* Sort the items if they are not already sorted. */ - qsort(&matches[1], (size_t)(len - 1), sizeof(char *), - _fn_qsort_string_compare); - - idx = 1; - for(; count > 0; count--) { - for(i = 0; i < limit && matches[idx]; i++, idx++) - (void)fprintf(el->el_outfile, "%-*s ", (int)max, - matches[idx]); + cols = (size_t)screenwidth / (width + 2); + if (cols == 0) + cols = 1; + + /* how many lines of output, rounded up */ + lines = (num + cols - 1) / cols; + + /* Sort the items. */ + qsort(matches, num, sizeof(char *), _fn_qsort_string_compare); + + /* + * On the ith line print elements i, i+lines, i+lines*2, etc. + */ + for (line = 0; line < lines; line++) { + for (col = 0; col < cols; col++) { + thisguy = line + col * lines; + if (thisguy >= num) + break; + (void)fprintf(el->el_outfile, "%s%s%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, + int do_unescape) +{ + /* We now look backwards for the start of a filename/variable word */ + const wchar_t *ctemp = cursor; + wchar_t *temp; + 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 (ctemp - buffer >= 2 && ctemp[-2] == '\\' && + needs_escaping(ctemp[-1])) { + ctemp -= 2; + continue; + } + if (wcschr(word_break, ctemp[-1])) + 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; + if (do_unescape) { + wchar_t *unescaped_word = unescape_string(ctemp, len); + if (unescaped_word == NULL) + return NULL; + return unescaped_word; + } + temp = el_malloc((len + 1) * sizeof(*temp)); + (void) wcsncpy(temp, ctemp, len); + temp[len] = '\0'; + return temp; +} + /* * Complete the word at or before point, * 'what_to_do' says what to do with the completion. @@ -402,19 +650,22 @@ fn_display_match_list (EditLine *el, char **matches, size_t len, size_t max) * '!' could never be invoked */ int -fn_complete(EditLine *el, - char *(*complet_func)(const char *, int), - char **(*attempted_completion_function)(const char *, int, int), - const char *word_break, const char *special_prefixes, - const char *(*app_func)(const char *), size_t query_items, - int *completion_type, int *over, int *point, int *end) +fn_complete2(EditLine *el, + char *(*complete_func)(const char *, int), + char **(*attempted_completion_function)(const char *, int, int), + 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, + unsigned int flags) { - const LineInfo *li; - char *temp, **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; + int do_unescape = flags & FN_QUOTE_MATCH; if (el->el_state.lastcmd == el->el_state.thiscmd) what_to_do = '?'; @@ -423,133 +674,165 @@ fn_complete(EditLine *el, if (completion_type != NULL) *completion_type = what_to_do; - if (!complet_func) - complet_func = fn_filename_completion_function; + if (!complete_func) + complete_func = fn_filename_completion_function; if (!app_func) app_func = append_char_function; - /* We now look backwards for the start of a filename/variable word */ - li = el_line(el); - ctemp = (const char *) li->cursor; - while (ctemp > li->buffer - && !strchr(word_break, ctemp[-1]) - && (!special_prefixes || !strchr(special_prefixes, ctemp[-1]) ) ) - ctemp--; - - len = li->cursor - ctemp; -#if defined(__SSP__) || defined(__SSP_ALL__) - temp = malloc(len + 1); -#else - temp = alloca(len + 1); -#endif - (void)strncpy(temp, ctemp, len); - temp[len] = '\0'; + li = el_wline(el); + temp = find_word_to_complete(li->cursor, + li->buffer, word_break, special_prefixes, &len, do_unescape); + if (temp == NULL) + goto out; /* these can be used by function called in completion_matches() */ /* or (*attempted_completion_function)() */ - if (point != 0) + if (point != NULL) *point = (int)(li->cursor - li->buffer); if (end != NULL) *end = (int)(li->lastchar - li->buffer); if (attempted_completion_function) { int cur_off = (int)(li->cursor - li->buffer); - matches = (*attempted_completion_function) (temp, - (int)(cur_off - len), cur_off); + matches = (*attempted_completion_function)( + ct_encode_string(temp, &el->el_scratch), + cur_off - (int)len, cur_off); } else - matches = 0; - if (!attempted_completion_function || + matches = NULL; + if (!attempted_completion_function || (over != NULL && !*over && !matches)) - matches = completion_matches(temp, complet_func); + matches = completion_matches( + ct_encode_string(temp, &el->el_scratch), complete_func); if (over != NULL) *over = 0; - if (matches) { - int i; - size_t matches_num, maxlen, match_len, match_display=1; + if (matches == NULL) { + goto out; + } + 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; + + if (matches[0][0] != '\0') { + el_deletestr(el, (int)len); + if (flags & FN_QUOTE_MATCH) + completion = escape_filename(el, matches[0], + single_match, app_func); + else + completion = strdup(matches[0]); + if (completion == NULL) + goto out2; - retval = CC_REFRESH; /* - * Only replace the completed string with common part of - * possible matches if there is possible completion. + * Replace the completed string with the common part of + * all possible matches if there is a possible completion. */ - if (matches[0][0] != '\0') { - el_deletestr(el, (int) len); - el_insertstr(el, matches[0]); - } - - if (what_to_do == '?') - goto display_matches; + el_winsertstr(el, + ct_decode_string(completion, &el->el_scratch)); - if (matches[2] == NULL && strcmp(matches[0], matches[1]) == 0) { + if (single_match && attempted_completion_function && + !(flags & FN_QUOTE_MATCH)) + { /* - * We found exact match. Add a space after + * We found an exact match. Add a space after * it, unless we do filename completion and the - * object is a directory. - */ - el_insertstr(el, (*app_func)(matches[0])); - } else if (what_to_do == '!') { - display_matches: - /* - * More than one match and requested to list possible - * matches. + * object is a directory. Also do necessary + * escape quoting */ + el_winsertstr(el, ct_decode_string( + (*app_func)(completion), &el->el_scratch)); + } + free(completion); + } - for(i=1, maxlen=0; matches[i]; i++) { - match_len = strlen(matches[i]); - if (match_len > maxlen) - maxlen = match_len; - } - matches_num = i - 1; - - /* newline to get on next line from command line */ - (void)fprintf(el->el_outfile, "\n"); - /* - * If there are too many items, ask user for display - * confirmation. - */ - if (matches_num > query_items) { - (void)fprintf(el->el_outfile, - "Display all %zu possibilities? (y or n) ", - matches_num); - (void)fflush(el->el_outfile); - if (getc(stdin) != 'y') - match_display = 0; - (void)fprintf(el->el_outfile, "\n"); - } + if (!single_match && (what_to_do == '!' || what_to_do == '?')) { + /* + * More than one match and requested to list possible + * matches. + */ + + for(i = 1, maxlen = 0; matches[i]; i++) { + match_len = strlen(matches[i]); + if (match_len > maxlen) + maxlen = match_len; + } + /* matches[1] through matches[i-1] are available */ + matches_num = (size_t)(i - 1); + + /* newline to get on next line from command line */ + (void)fprintf(el->el_outfile, "\n"); - if (match_display) - fn_display_match_list(el, matches, matches_num, - maxlen); - retval = CC_REDISPLAY; - } else if (matches[0][0]) { + /* + * If there are too many items, ask user for display + * confirmation. + */ + if (matches_num > query_items) { + (void)fprintf(el->el_outfile, + "Display all %zu possibilities? (y or n) ", + matches_num); + (void)fflush(el->el_outfile); + if (getc(stdin) != 'y') + match_display = 0; + (void)fprintf(el->el_outfile, "\n"); + } + + if (match_display) { /* - * There was some common match, but the name was - * not complete enough. Next tab will print possible - * completions. + * Interface of this function requires the + * strings be matches[1..num-1] for compat. + * We have matches_num strings not counting + * the prefix in matches[0], so we need to + * add 1 to matches_num for the call. */ - el_beep(el); - } else { - /* lcd is not a valid object - further specification */ - /* is needed */ - el_beep(el); - retval = CC_NORM; + fn_display_match_list(el, matches, + matches_num+1, maxlen, app_func); } - - /* free elements of array and the array itself */ - for (i = 0; matches[i]; i++) - free(matches[i]); - free(matches); - matches = NULL; + retval = CC_REDISPLAY; + } else if (matches[0][0]) { + /* + * There was some common match, but the name was + * not complete enough. Next tab will print possible + * completions. + */ + el_beep(el); + } else { + /* lcd is not a valid object - further specification */ + /* is needed */ + el_beep(el); + retval = CC_NORM; } -#if defined(__SSP__) || defined(__SSP_ALL__) - free(temp); -#endif + + /* free elements of array and the array itself */ +out2: + for (i = 0; matches[i]; i++) + el_free(matches[i]); + el_free(matches); + matches = NULL; + +out: + el_free(temp); return retval; } +int +fn_complete(EditLine *el, + char *(*complete_func)(const char *, int), + char **(*attempted_completion_function)(const char *, int, int), + 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) +{ + return fn_complete2(el, complete_func, attempted_completion_function, + word_break, special_prefixes, app_func, query_items, + completion_type, over, point, end, + attempted_completion_function ? 0 : FN_QUOTE_MATCH); +} + /* * el-compatible wrapper around rl_complete; needed for key binding */ @@ -558,6 +841,6 @@ unsigned char _el_fn_complete(EditLine *el, int ch __attribute__((__unused__))) { return (unsigned char)fn_complete(el, NULL, NULL, - break_chars, NULL, NULL, 100, + break_chars, NULL, NULL, (size_t)100, NULL, NULL, NULL, NULL); } diff --git a/clt/falcon/editline/src/filecomplete.h b/clt/falcon/editline/src/filecomplete.h index 0ab43e286..796ae7ab3 100644 --- a/clt/falcon/editline/src/filecomplete.h +++ b/clt/falcon/editline/src/filecomplete.h @@ -1,4 +1,4 @@ -/* $NetBSD: filecomplete.h,v 1.8 2009/02/16 00:15:45 christos Exp $ */ +/* $NetBSD: filecomplete.h,v 1.14 2021/09/26 13:45:54 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -34,10 +34,17 @@ int fn_complete(EditLine *, char *(*)(const char *, int), char **(*)(const char *, int, int), - const char *, const char *, const char *(*)(const char *), size_t, + const wchar_t *, const wchar_t *, const char *(*)(const char *), size_t, int *, int *, int *, int *); +int fn_complete2(EditLine *, + char *(*)(const char *, int), + char **(*)(const char *, int, int), + const wchar_t *, const wchar_t *, const char *(*)(const char *), size_t, + int *, int *, int *, int *, unsigned int); +#define FN_QUOTE_MATCH 1U /* Quote the returned match */ -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); diff --git a/clt/falcon/editline/src/fgetln.c b/clt/falcon/editline/src/getline.c similarity index 61% rename from clt/falcon/editline/src/fgetln.c rename to clt/falcon/editline/src/getline.c index 4098bcd21..1861533df 100644 --- a/clt/falcon/editline/src/fgetln.c +++ b/clt/falcon/editline/src/getline.c @@ -1,7 +1,7 @@ -/* $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $ */ +/* $NetBSD: getline.c,v 1.2 2014/09/16 17:23:50 christos Exp $ */ /*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. + * Copyright (c) 2011 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -33,9 +33,9 @@ #include "nbtool_config.h" #endif -#if !HAVE_FGETLN -#include +#if !HAVE_GETLINE #include + #ifndef HAVE_NBTOOL_CONFIG_H /* These headers are required, but included from nbtool_config.h */ #include @@ -44,49 +44,53 @@ #include #endif -char * -fgetln(FILE *fp, size_t *len) +ssize_t +getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { - static char *buf = NULL; - static size_t bufsiz = 0; - char *ptr; + char *ptr, *eptr; - if (buf == NULL) { - bufsiz = BUFSIZ; - if ((buf = malloc(bufsiz)) == NULL) - return NULL; + if (*buf == NULL || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = malloc(*bufsiz)) == NULL) + return -1; } - if (fgets(buf, bufsiz, fp) == NULL) - return NULL; - - *len = 0; - while ((ptr = strchr(&buf[*len], '\n')) == NULL) { - size_t nbufsiz = bufsiz + BUFSIZ; - char *nbuf = realloc(buf, nbufsiz); - - if (nbuf == NULL) { - int oerrno = errno; - free(buf); - errno = oerrno; - buf = NULL; - return NULL; - } else - buf = nbuf; - - if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) { - buf[bufsiz] = '\0'; - *len = strlen(buf); - return buf; + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) { + ssize_t diff = (ssize_t)(ptr - *buf); + if (diff != 0) { + *ptr = '\0'; + return diff; + } + } + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = realloc(*buf, nbufsiz)) == NULL) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; } - - *len = bufsiz; - bufsiz = nbufsiz; } +} - *len = (ptr - buf) + 1; - return buf; +ssize_t +getline(char **buf, size_t *bufsiz, FILE *fp) +{ + return getdelim(buf, bufsiz, '\n', fp); } #endif @@ -95,13 +99,13 @@ fgetln(FILE *fp, size_t *len) int main(int argc, char *argv[]) { - char *p; - size_t len; + char *p = NULL; + ssize_t len; + size_t n = 0; - while ((p = fgetln(stdin, &len)) != NULL) { - (void)printf("%zu %s", len, p); - free(p); - } + while ((len = getline(&p, &n, stdin)) != -1) + (void)printf("%zd %s", len, p); + free(p); return 0; } #endif diff --git a/clt/falcon/editline/src/hist.c b/clt/falcon/editline/src/hist.c index 282edcaf7..19ce1c161 100644 --- a/clt/falcon/editline/src/hist.c +++ b/clt/falcon/editline/src/hist.c @@ -1,4 +1,4 @@ -/* $NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $ */ +/* $NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)hist.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $"); +__RCSID("$NetBSD: hist.c,v 1.34 2019/07/23 10:19:35 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -45,34 +45,37 @@ __RCSID("$NetBSD: hist.c,v 1.15 2003/11/01 23:36:39 christos Exp $"); * hist.c: History access functions */ #include +#include +#include + #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 = (char *) el_malloc(EL_BUFSIZ); - 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); + return -1; + el->el_history.sz = EL_BUFSIZ; el->el_history.last = el->el_history.buf; - return (0); + return 0; } /* hist_end(): * clean up history; */ -protected void +libedit_private void hist_end(EditLine *el) { - el_free((ptr_t) el->el_history.buf); + el_free(el->el_history.buf); el->el_history.buf = NULL; } @@ -80,13 +83,13 @@ hist_end(EditLine *el) /* hist_set(): * Set new history interface */ -protected int -hist_set(EditLine *el, hist_fun_t fun, ptr_t ptr) +libedit_private int +hist_set(EditLine *el, hist_fun_t fun, void *ptr) { el->el_history.ref = ptr; el->el_history.fun = fun; - return (0); + return 0; } @@ -94,14 +97,15 @@ hist_set(EditLine *el, hist_fun_t fun, ptr_t 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); @@ -113,24 +117,27 @@ hist_get(EditLine *el) #endif /* KSHVI */ el->el_line.cursor = el->el_line.lastchar; - return (CC_REFRESH); + return CC_REFRESH; } if (el->el_history.ref == NULL) - return (CC_ERROR); + return CC_ERROR; hp = HIST_FIRST(el); if (hp == NULL) - return (CC_ERROR); + 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) strlcpy(el->el_line.buffer, hp, - (size_t)(el->el_line.limit - el->el_line.buffer)); - 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') @@ -145,42 +152,67 @@ hist_get(EditLine *el) #endif /* KSHVI */ el->el_line.cursor = el->el_line.lastchar; - return (CC_REFRESH); + 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; - HistEvent ev; + HistEventW ev; if (el->el_history.ref == NULL) - return (-1); + return -1; - if (argc == 1 || strcmp(argv[1], "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, str); - return (0); + 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); + return -1; - num = (int)strtol(argv[2], NULL, 0); + num = (int)wcstol(argv[2], NULL, 0); - if (strcmp(argv[1], "size") == 0) - return 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], "unique") == 0) - return 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; } @@ -189,17 +221,17 @@ 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 = realloc(el->el_history.buf, newsz); + newbuf = el_realloc(el->el_history.buf, newsz * sizeof(*newbuf)); if (!newbuf) return 0; - (void) memset(&newbuf[oldsz], '\0', newsz - oldsz); + (void) memset(&newbuf[oldsz], '\0', (newsz - oldsz) * sizeof(*newbuf)); el->el_history.last = newbuf + (el->el_history.last - el->el_history.buf); @@ -208,3 +240,13 @@ hist_enlargebuf(EditLine *el, size_t oldsz, size_t newsz) return 1; } + +libedit_private wchar_t * +hist_convert(EditLine *el, int fn, void *arg) +{ + HistEventW ev; + if ((*(el)->el_history.fun)((el)->el_history.ref, &ev, fn, arg) == -1) + return NULL; + return ct_decode_string((const char *)(const void *)ev.str, + &el->el_scratch); +} diff --git a/clt/falcon/editline/src/hist.h b/clt/falcon/editline/src/hist.h index 46e14634a..8f5ab0839 100644 --- a/clt/falcon/editline/src/hist.h +++ b/clt/falcon/editline/src/hist.h @@ -1,4 +1,4 @@ -/* $NetBSD: hist.h,v 1.10 2003/08/07 16:44:31 agc Exp $ */ +/* $NetBSD: hist.h,v 1.23 2017/09/01 10:19:10 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,37 +40,41 @@ #ifndef _h_el_hist #define _h_el_hist -#include "histedit.h" - -typedef int (*hist_fun_t)(ptr_t, HistEvent *, int, ...); +typedef int (*hist_fun_t)(void *, HistEventW *, int, ...); typedef struct el_history_t { - char *buf; /* The history buffer */ - size_t sz; /* Size of history buffer */ - char *last; /* The last character */ + wchar_t *buf; /* The history buffer */ + size_t sz; /* Size of history buffer */ + wchar_t *last; /* The last character */ int eventno; /* Event we are looking for */ - ptr_t ref; /* Argument for history fcns */ + void *ref; /* Argument for history fcns */ hist_fun_t fun; /* Event access */ - HistEvent ev; /* Event cookie */ + HistEventW ev; /* Event cookie */ } el_history_t; -#define HIST_FUN(el, fn, arg) \ +#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) +#define HIST_FUN(el, fn, arg) \ + (((el)->el_flags & NARROW_HISTORY) ? hist_convert(el, fn, arg) : \ + HIST_FUN_INTERNAL(el, fn, arg)) -#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_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) -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, ptr_t); -protected int hist_command(EditLine *, int, const char **); -protected int hist_enlargebuf(EditLine *, size_t, size_t); +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 */ diff --git a/clt/falcon/editline/src/histedit.h b/clt/falcon/editline/src/histedit.h index 3445004fe..1e215fc88 100644 --- a/clt/falcon/editline/src/histedit.h +++ b/clt/falcon/editline/src/histedit.h @@ -1,4 +1,4 @@ -/* $NetBSD: histedit.h,v 1.41 2009/09/07 21:24:33 christos Exp $ */ +/* $NetBSD: histedit.h,v 1.61 2022/02/08 21:13:22 rillig Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -84,6 +84,8 @@ typedef struct lineinfo { * Initialization, cleanup, and resetting */ EditLine *el_init(const char *, FILE *, FILE *, FILE *); +EditLine *el_init_fd(const char *, FILE *, FILE *, FILE *, + int, int, int); void el_end(EditLine *); void el_reset(EditLine *); @@ -114,31 +116,48 @@ unsigned char _el_fn_complete(EditLine *, int); /* * el_set/el_get parameters + * + * When using el_wset/el_wget (as opposed to el_set/el_get): + * Char is wchar_t, otherwise it is char. + * prompt_func is el_wpfunc_t, otherwise it is el_pfunc_t . + + * Prompt function prototypes are: + * typedef char *(*el_pfunct_t) (EditLine *); + * typedef wchar_t *(*el_wpfunct_t) (EditLine *); + * + * For operations that support set or set/get, the argument types listed are for + * the "set" operation. For "get", each listed type must be a pointer. + * E.g. EL_EDITMODE takes an int when set, but an int* when get. + * + * Operations that only support "get" have the correct argument types listed. */ -#define EL_PROMPT 0 /* , el_pfunc_t); */ -#define EL_TERMINAL 1 /* , const char *); */ -#define EL_EDITOR 2 /* , const char *); */ -#define EL_SIGNAL 3 /* , int); */ -#define EL_BIND 4 /* , const char *, ..., NULL); */ -#define EL_TELLTC 5 /* , const char *, ..., NULL); */ -#define EL_SETTC 6 /* , const char *, ..., NULL); */ -#define EL_ECHOTC 7 /* , const char *, ..., NULL); */ -#define EL_SETTY 8 /* , const char *, ..., NULL); */ -#define EL_ADDFN 9 /* , const char *, const char * */ - /* , el_func_t); */ -#define EL_HIST 10 /* , hist_fun_t, const char *); */ -#define EL_EDITMODE 11 /* , int); */ -#define EL_RPROMPT 12 /* , el_pfunc_t); */ -#define EL_GETCFN 13 /* , el_rfunc_t); */ -#define EL_CLIENTDATA 14 /* , void *); */ -#define EL_UNBUFFERED 15 /* , int); */ -#define EL_PREP_TERM 16 /* , int); */ -#define EL_GETTC 17 /* , const char *, ..., NULL); */ -#define EL_GETFP 18 /* , int, FILE **); */ -#define EL_SETFP 19 /* , int, FILE *); */ -#define EL_REFRESH 20 /* , void); */ -#define EL_PROMPT_ESC 21 /* , el_pfunc_t, char); */ -#define EL_RPROMPT_ESC 22 /* , el_pfunc_t, char); */ +#define EL_PROMPT 0 /* , prompt_func); set/get */ +#define EL_TERMINAL 1 /* , const char *); set/get */ +#define EL_EDITOR 2 /* , const Char *); set/get */ +#define EL_SIGNAL 3 /* , int); set/get */ +#define EL_BIND 4 /* , const Char *, ..., NULL); set */ +#define EL_TELLTC 5 /* , const Char *, ..., NULL); set */ +#define EL_SETTC 6 /* , const Char *, ..., NULL); set */ +#define EL_ECHOTC 7 /* , const Char *, ..., NULL); set */ +#define EL_SETTY 8 /* , const Char *, ..., NULL); set */ +#define EL_ADDFN 9 /* , const Char *, const Char, set */ + /* el_func_t); */ +#define EL_HIST 10 /* , hist_fun_t, const void *); set */ +#define EL_EDITMODE 11 /* , int); set/get */ +#define EL_RPROMPT 12 /* , prompt_func); set/get */ +#define EL_GETCFN 13 /* , el_rfunc_t); set/get */ +#define EL_CLIENTDATA 14 /* , void *); set/get */ +#define EL_UNBUFFERED 15 /* , int); set/get */ +#define EL_PREP_TERM 16 /* , int); set */ +#define EL_GETTC 17 /* , const Char *, ..., NULL); get */ +#define EL_GETFP 18 /* , int, FILE **); get */ +#define EL_SETFP 19 /* , int, FILE *); set */ +#define EL_REFRESH 20 /* , void); set */ +#define EL_PROMPT_ESC 21 /* , prompt_func, Char); set/get */ +#define EL_RPROMPT_ESC 22 /* , prompt_func, Char); set/get */ +#define EL_RESIZE 23 /* , el_zfunc_t, void *); set */ +#define EL_ALIAS_TEXT 24 /* , el_afunc_t, void *); set */ +#define EL_SAFEREAD 25 /* , int); set/get */ #define EL_BUILTIN_GETCFN (NULL) @@ -160,7 +179,8 @@ void el_resize(EditLine *); const LineInfo *el_line(EditLine *); int el_insertstr(EditLine *, const char *); void el_deletestr(EditLine *, int); - +int el_replacestr(EditLine *, const char *); +int el_deletestr1(EditLine *, int, int); /* * ==== History ==== @@ -190,12 +210,12 @@ int history(History *, HistEvent *, int, ...); #define H_NEXT 6 /* , void); */ #define H_CURR 8 /* , const int); */ #define H_SET 7 /* , int); */ -#define H_ADD 9 /* , const char *); */ -#define H_ENTER 10 /* , const char *); */ -#define H_APPEND 11 /* , const char *); */ +#define H_ADD 9 /* , const wchar_t *); */ +#define H_ENTER 10 /* , const wchar_t *); */ +#define H_APPEND 11 /* , const wchar_t *); */ #define H_END 12 /* , void); */ -#define H_NEXT_STR 13 /* , const char *); */ -#define H_PREV_STR 14 /* , const char *); */ +#define H_NEXT_STR 13 /* , const wchar_t *); */ +#define H_PREV_STR 14 /* , const wchar_t *); */ #define H_NEXT_EVENT 15 /* , const int); */ #define H_PREV_EVENT 16 /* , const int); */ #define H_LOAD 17 /* , const char *); */ @@ -207,6 +227,8 @@ int history(History *, HistEvent *, int, ...); #define H_NEXT_EVDATA 23 /* , const int, histdata_t *); */ #define H_DELDATA 24 /* , int, histdata_t *);*/ #define H_REPLACE 25 /* , const char *, histdata_t); */ +#define H_SAVE_FP 26 /* , FILE *); */ +#define H_NSAVE_FP 27 /* , size_t, FILE *); */ @@ -227,6 +249,71 @@ int tok_line(Tokenizer *, const LineInfo *, int tok_str(Tokenizer *, const char *, int *, const char ***); +/* + * Begin Wide Character Support + */ +#include +#include + +#ifndef HAVE_WCSDUP +wchar_t * wcsdup(const wchar_t *str); +#endif + +/* + * ==== Editing ==== + */ +typedef struct lineinfow { + const wchar_t *buffer; + const wchar_t *cursor; + 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 *); + +int el_wparse(EditLine *, int, const wchar_t **); + +int el_wset(EditLine *, int, ...); +int el_wget(EditLine *, int, ...); + +int el_cursor(EditLine *, int); +const LineInfoW *el_wline(EditLine *); +int el_winsertstr(EditLine *, const wchar_t *); +#define el_wdeletestr el_deletestr +int el_wreplacestr(EditLine *, const wchar_t *); + +/* + * ==== History ==== + */ +typedef struct histeventW { + int num; + const wchar_t *str; +} HistEventW; + +typedef struct historyW HistoryW; + +HistoryW * history_winit(void); +void history_wend(HistoryW *); + +int history_w(HistoryW *, HistEventW *, int, ...); + +/* + * ==== Tokenization ==== + */ +typedef struct tokenizerW TokenizerW; + +/* Wide character tokenizer support */ +TokenizerW *tok_winit(const wchar_t *); +void tok_wend(TokenizerW *); +void tok_wreset(TokenizerW *); +int tok_wline(TokenizerW *, const LineInfoW *, + int *, const wchar_t ***, int *, int *); +int tok_wstr(TokenizerW *, const wchar_t *, + int *, const wchar_t ***); + #ifdef __cplusplus } #endif diff --git a/clt/falcon/editline/src/history.c b/clt/falcon/editline/src/history.c index a692cf769..2a8ca1aa2 100644 --- a/clt/falcon/editline/src/history.c +++ b/clt/falcon/editline/src/history.c @@ -1,4 +1,4 @@ -/* $NetBSD: history.c,v 1.34 2009/09/07 21:24:33 christos Exp $ */ +/* $NetBSD: history.c,v 1.63 2019/10/08 19:17:57 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,35 +32,75 @@ * SUCH DAMAGE. */ +#ifndef NARROWCHAR #include "config.h" +#endif + #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)history.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: history.c,v 1.34 2009/09/07 21:24:33 christos Exp $"); +__RCSID("$NetBSD: history.c,v 1.63 2019/10/08 19:17:57 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* - * hist.c: History access functions + * hist.c: TYPE(History) access functions */ -#include -#include +#include #include +#include +#include #include -#include static const char hist_cookie[] = "_HiStOrY_V2_\n"; #include "histedit.h" -typedef int (*history_gfun_t)(ptr_t, HistEvent *); -typedef int (*history_efun_t)(ptr_t, HistEvent *, const char *); -typedef void (*history_vfun_t)(ptr_t, HistEvent *); -typedef int (*history_sfun_t)(ptr_t, HistEvent *, const int); -struct history { - ptr_t h_ref; /* Argument for history fcns */ +#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) *); +typedef int (*history_sfun_t)(void *, TYPE(HistEvent) *, const int); + +struct TYPE(history) { + void *h_ref; /* Argument for history fcns */ int h_ent; /* Last entry point for history */ history_gfun_t h_first; /* Get the first element */ history_gfun_t h_next; /* Get the next element */ @@ -85,29 +125,31 @@ struct history { #define HADD(h, ev, str) (*(h)->h_add)((h)->h_ref, ev, str) #define HDEL(h, ev, n) (*(h)->h_del)((h)->h_ref, ev, n) -#define h_strdup(a) strdup(a) +#define h_strdup(a) Strdup(a) #define h_malloc(a) malloc(a) #define h_realloc(a, b) realloc((a), (b)) #define h_free(a) free(a) typedef struct { int num; - char *str; + Char *str; } HistEventPrivate; - -private int history_setsize(History *, HistEvent *, int); -private int history_getsize(History *, HistEvent *); -private int history_setunique(History *, HistEvent *, int); -private int history_getunique(History *, HistEvent *); -private int history_set_fun(History *, History *); -private int history_load(History *, const char *); -private int history_save(History *, const char *); -private int history_prev_event(History *, HistEvent *, int); -private int history_next_event(History *, HistEvent *, int); -private int history_next_string(History *, HistEvent *, const char *); -private int history_prev_string(History *, 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 *); /***********************************************************************/ @@ -116,7 +158,7 @@ private int history_prev_string(History *, HistEvent *, const char *); * Builtin- history implementation */ typedef struct hentry_t { - HistEvent ev; /* What we return */ + TYPE(HistEvent) ev; /* What we return */ void *data; /* data */ struct hentry_t *next; /* Next entry */ struct hentry_t *prev; /* Previous entry */ @@ -128,27 +170,27 @@ typedef struct history_t { int max; /* Maximum number of events */ int cur; /* Current number of events */ int eventid; /* For generation of unique event id */ - int flags; /* History flags */ + int flags; /* TYPE(History) flags */ #define H_UNIQUE 1 /* Store only unique elements */ } history_t; -private int history_def_next(ptr_t, HistEvent *); -private int history_def_first(ptr_t, HistEvent *); -private int history_def_prev(ptr_t, HistEvent *); -private int history_def_last(ptr_t, HistEvent *); -private int history_def_curr(ptr_t, HistEvent *); -private int history_def_set(ptr_t, HistEvent *, const int); -private void history_def_clear(ptr_t, HistEvent *); -private int history_def_enter(ptr_t, HistEvent *, const char *); -private int history_def_add(ptr_t, HistEvent *, const char *); -private int history_def_del(ptr_t, 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(ptr_t *, HistEvent *, int); -private int history_def_insert(history_t *, HistEvent *, const char *); -private void history_def_delete(history_t *, 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 *, HistEvent *, int, void **); -private int history_set_nth(ptr_t, 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) @@ -166,23 +208,23 @@ private int history_set_nth(ptr_t, HistEvent *, int); } /* error messages */ -static const char *const he_errlist[] = { - "OK", - "unknown error", - "malloc() failed", - "first event not found", - "last event not found", - "empty list", - "no next event", - "no previous event", - "current event is invalid", - "event not found", - "can't read history from file", - "can't write history", - "required parameter(s) not supplied", - "history size negative", - "function not allowed with other history-functions-set the default", - "bad parameters" +static const Char *const he_errlist[] = { + STR("OK"), + STR("unknown error"), + STR("malloc() failed"), + STR("first event not found"), + STR("last event not found"), + STR("empty list"), + STR("no next event"), + STR("no previous event"), + STR("current event is invalid"), + STR("event not found"), + STR("can't read history from file"), + STR("can't write history"), + STR("required parameter(s) not supplied"), + STR("history size negative"), + STR("function not allowed with other history-functions-set the default"), + STR("bad parameters") }; /* error codes */ #define _HE_OK 0 @@ -205,8 +247,8 @@ static const char *const he_errlist[] = { /* history_def_first(): * Default function to return the first event in the history. */ -private int -history_def_first(ptr_t p, HistEvent *ev) +static int +history_def_first(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -215,18 +257,18 @@ history_def_first(ptr_t p, HistEvent *ev) *ev = h->cursor->ev; else { he_seterrev(ev, _HE_FIRST_NOTFOUND); - return (-1); + return -1; } - return (0); + return 0; } /* history_def_last(): * Default function to return the last event in the history. */ -private int -history_def_last(ptr_t p, HistEvent *ev) +static int +history_def_last(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -235,69 +277,69 @@ history_def_last(ptr_t p, HistEvent *ev) *ev = h->cursor->ev; else { he_seterrev(ev, _HE_LAST_NOTFOUND); - return (-1); + return -1; } - return (0); + return 0; } /* history_def_next(): * Default function to return the next event in the history. */ -private int -history_def_next(ptr_t p, HistEvent *ev) +static int +history_def_next(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; if (h->cursor == &h->list) { he_seterrev(ev, _HE_EMPTY_LIST); - return (-1); + return -1; } if (h->cursor->next == &h->list) { he_seterrev(ev, _HE_END_REACHED); - return (-1); + return -1; } h->cursor = h->cursor->next; *ev = h->cursor->ev; - return (0); + return 0; } /* history_def_prev(): * Default function to return the previous event in the history. */ -private int -history_def_prev(ptr_t p, HistEvent *ev) +static int +history_def_prev(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; if (h->cursor == &h->list) { he_seterrev(ev, (h->cur > 0) ? _HE_END_REACHED : _HE_EMPTY_LIST); - return (-1); + return -1; } if (h->cursor->prev == &h->list) { he_seterrev(ev, _HE_START_REACHED); - return (-1); + return -1; } h->cursor = h->cursor->prev; *ev = h->cursor->ev; - return (0); + return 0; } /* history_def_curr(): * Default function to return the current event in the history. */ -private int -history_def_curr(ptr_t p, HistEvent *ev) +static int +history_def_curr(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; @@ -306,10 +348,10 @@ history_def_curr(ptr_t p, HistEvent *ev) else { he_seterrev(ev, (h->cur > 0) ? _HE_CURR_INVALID : _HE_EMPTY_LIST); - return (-1); + return -1; } - return (0); + return 0; } @@ -317,14 +359,14 @@ history_def_curr(ptr_t p, HistEvent *ev) * Default function to set the current event in the history to the * given one. */ -private int -history_def_set(ptr_t p, HistEvent *ev, const int n) +static int +history_def_set(void *p, TYPE(HistEvent) *ev, const int n) { history_t *h = (history_t *) p; if (h->cur == 0) { he_seterrev(ev, _HE_EMPTY_LIST); - return (-1); + return -1; } if (h->cursor == &h->list || h->cursor->ev.num != n) { for (h->cursor = h->list.next; h->cursor != &h->list; @@ -334,9 +376,9 @@ history_def_set(ptr_t p, HistEvent *ev, const int n) } if (h->cursor == &h->list) { he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } - return (0); + return 0; } @@ -344,14 +386,14 @@ history_def_set(ptr_t p, HistEvent *ev, const int n) * Default function to set the current event in the history to the * n-th one. */ -private int -history_set_nth(ptr_t p, HistEvent *ev, int n) +static int +history_set_nth(void *p, TYPE(HistEvent) *ev, int n) { history_t *h = (history_t *) p; if (h->cur == 0) { he_seterrev(ev, _HE_EMPTY_LIST); - return (-1); + return -1; } for (h->cursor = h->list.prev; h->cursor != &h->list; h->cursor = h->cursor->prev) @@ -359,55 +401,58 @@ history_set_nth(ptr_t p, HistEvent *ev, int n) break; if (h->cursor == &h->list) { he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } - return (0); + return 0; } /* history_def_add(): * Append string to element */ -private int -history_def_add(ptr_t p, HistEvent *ev, const char *str) +static int +history_def_add(void *p, TYPE(HistEvent) *ev, const Char *str) { history_t *h = (history_t *) p; - size_t len; - char *s; + size_t len, elen, slen; + Char *s; HistEventPrivate *evp = (void *)&h->cursor->ev; if (h->cursor == &h->list) - return (history_def_enter(p, ev, str)); - len = strlen(evp->str) + strlen(str) + 1; - s = (char *) h_malloc(len); + return history_def_enter(p, ev, str); + elen = Strlen(evp->str); + slen = Strlen(str); + len = elen + slen + 1; + s = h_malloc(len * sizeof(*s)); if (s == NULL) { he_seterrev(ev, _HE_MALLOC_FAILED); - return (-1); + return -1; } - (void) strlcpy(s, h->cursor->ev.str, len); - (void) strlcat(s, str, len); - h_free((ptr_t)evp->str); + memcpy(s, evp->str, elen * sizeof(*s)); + memcpy(s + elen, str, slen * sizeof(*s)); + s[len - 1] = '\0'; + h_free(evp->str); evp->str = s; *ev = h->cursor->ev; - return (0); + return 0; } -private int -history_deldata_nth(history_t *h, HistEvent *ev, +static int +history_deldata_nth(history_t *h, TYPE(HistEvent) *ev, int num, void **data) { if (history_set_nth(h, ev, num) != 0) - return (-1); + return -1; /* magic value to skip delete (just set to n-th history) */ if (data == (void **)-1) - return (0); - ev->str = strdup(h->cursor->ev.str); + return 0; + ev->str = Strdup(h->cursor->ev.str); ev->num = h->cursor->ev.num; if (data) *data = h->cursor->data; history_def_delete(h, ev, h->cursor); - return (0); + return 0; } @@ -415,17 +460,17 @@ history_deldata_nth(history_t *h, HistEvent *ev, * Delete element hp of the h list */ /* ARGSUSED */ -private int -history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)), +static int +history_def_del(void *p, TYPE(HistEvent) *ev __attribute__((__unused__)), const int num) { history_t *h = (history_t *) p; if (history_def_set(h, ev, num) != 0) - return (-1); - ev->str = strdup(h->cursor->ev.str); + return -1; + ev->str = Strdup(h->cursor->ev.str); ev->num = h->cursor->ev.num; history_def_delete(h, ev, h->cursor); - return (0); + return 0; } @@ -433,9 +478,9 @@ history_def_del(ptr_t p, HistEvent *ev __attribute__((__unused__)), * Delete element hp of the h list */ /* ARGSUSED */ -private void -history_def_delete(history_t *h, - HistEvent *ev __attribute__((__unused__)), hentry_t *hp) +static void +history_def_delete(history_t *h, + TYPE(HistEvent) *ev __attribute__((__unused__)), hentry_t *hp) { HistEventPrivate *evp = (void *)&hp->ev; if (hp == &h->list) @@ -447,7 +492,7 @@ history_def_delete(history_t *h, } hp->prev->next = hp->next; hp->next->prev = hp->prev; - h_free((ptr_t) evp->str); + h_free(evp->str); h_free(hp); h->cur--; } @@ -456,47 +501,49 @@ history_def_delete(history_t *h, /* history_def_insert(): * Insert element with string str in the h list */ -private int -history_def_insert(history_t *h, HistEvent *ev, const char *str) +static int +history_def_insert(history_t *h, TYPE(HistEvent) *ev, const Char *str) { + hentry_t *c; - h->cursor = (hentry_t *) h_malloc(sizeof(hentry_t)); - if (h->cursor == NULL) + c = h_malloc(sizeof(*c)); + if (c == NULL) goto oomem; - if ((h->cursor->ev.str = h_strdup(str)) == NULL) { - h_free((ptr_t)h->cursor); + if ((c->ev.str = h_strdup(str)) == NULL) { + h_free(c); goto oomem; } - h->cursor->data = NULL; - h->cursor->ev.num = ++h->eventid; - h->cursor->next = h->list.next; - h->cursor->prev = &h->list; - h->list.next->prev = h->cursor; - h->list.next = h->cursor; + c->data = NULL; + c->ev.num = ++h->eventid; + c->next = h->list.next; + c->prev = &h->list; + h->list.next->prev = c; + h->list.next = c; h->cur++; + h->cursor = c; - *ev = h->cursor->ev; - return (0); + *ev = c->ev; + return 0; oomem: he_seterrev(ev, _HE_MALLOC_FAILED); - return (-1); + return -1; } /* history_def_enter(): * Default function to enter an item in the history */ -private int -history_def_enter(ptr_t p, HistEvent *ev, const char *str) +static int +history_def_enter(void *p, TYPE(HistEvent) *ev, const Char *str) { history_t *h = (history_t *) p; if ((h->flags & H_UNIQUE) != 0 && h->list.next != &h->list && - strcmp(h->list.next->ev.str, str) == 0) - return (0); + Strcmp(h->list.next->ev.str, str) == 0) + return 0; if (history_def_insert(h, ev, str) == -1) - return (-1); /* error, keep error message */ + return -1; /* error, keep error message */ /* * Always keep at least one entry. @@ -505,7 +552,7 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str) while (h->cur > h->max && h->cur > 0) history_def_delete(h, ev, h->list.prev); - return (1); + return 1; } @@ -513,10 +560,10 @@ history_def_enter(ptr_t p, HistEvent *ev, const char *str) * Default history initialization function */ /* ARGSUSED */ -private int -history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n) +static int +history_def_init(void **p, TYPE(HistEvent) *ev __attribute__((__unused__)), int n) { - history_t *h = (history_t *) h_malloc(sizeof(history_t)); + history_t *h = (history_t *) h_malloc(sizeof(*h)); if (h == NULL) return -1; @@ -530,7 +577,7 @@ history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n) h->list.ev.num = 0; h->cursor = &h->list; h->flags = 0; - *p = (ptr_t) h; + *p = h; return 0; } @@ -538,13 +585,14 @@ history_def_init(ptr_t *p, HistEvent *ev __attribute__((__unused__)), int n) /* history_def_clear(): * Default history cleanup function */ -private void -history_def_clear(ptr_t p, HistEvent *ev) +static void +history_def_clear(void *p, TYPE(HistEvent) *ev) { history_t *h = (history_t *) p; while (h->list.prev != &h->list) history_def_delete(h, ev, h->list.prev); + h->cursor = &h->list; h->eventid = 0; h->cur = 0; } @@ -557,16 +605,16 @@ history_def_clear(ptr_t p, HistEvent *ev) /* history_init(): * Initialization function. */ -public History * -history_init(void) +TYPE(History) * +FUN(history,init)(void) { - HistEvent ev; - History *h = (History *) h_malloc(sizeof(History)); + TYPE(HistEvent) ev; + TYPE(History) *h = (TYPE(History) *) h_malloc(sizeof(*h)); if (h == NULL) return NULL; if (history_def_init(&h->h_ref, &ev, 0) == -1) { - h_free((ptr_t)h); + h_free(h); return NULL; } h->h_ent = -1; @@ -581,17 +629,17 @@ history_init(void) h->h_add = history_def_add; h->h_del = history_def_del; - return (h); + return h; } /* history_end(): * clean up history; */ -public void -history_end(History *h) +void +FUN(history,end)(TYPE(History) *h) { - HistEvent ev; + TYPE(HistEvent) ev; if (h->h_next == history_def_next) history_def_clear(h->h_ref, &ev); @@ -604,87 +652,88 @@ history_end(History *h) /* history_setsize(): * Set history number of events */ -private int -history_setsize(History *h, HistEvent *ev, int num) +static int +history_setsize(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { if (h->h_next != history_def_next) { he_seterrev(ev, _HE_NOT_ALLOWED); - return (-1); + return -1; } if (num < 0) { he_seterrev(ev, _HE_BAD_PARAM); - return (-1); + return -1; } history_def_setsize(h->h_ref, num); - return (0); + return 0; } /* history_getsize(): * Get number of events currently in history */ -private int -history_getsize(History *h, HistEvent *ev) +static int +history_getsize(TYPE(History) *h, TYPE(HistEvent) *ev) { if (h->h_next != history_def_next) { he_seterrev(ev, _HE_NOT_ALLOWED); - return (-1); + return -1; } ev->num = history_def_getsize(h->h_ref); if (ev->num < -1) { he_seterrev(ev, _HE_SIZE_NEGATIVE); - return (-1); + return -1; } - return (0); + return 0; } /* history_setunique(): * Set if adjacent equal events should not be entered in history. */ -private int -history_setunique(History *h, HistEvent *ev, int uni) +static int +history_setunique(TYPE(History) *h, TYPE(HistEvent) *ev, int uni) { if (h->h_next != history_def_next) { he_seterrev(ev, _HE_NOT_ALLOWED); - return (-1); + return -1; } history_def_setunique(h->h_ref, uni); - return (0); + return 0; } /* history_getunique(): * Get if adjacent equal events should not be entered in history. */ -private int -history_getunique(History *h, HistEvent *ev) +static int +history_getunique(TYPE(History) *h, TYPE(HistEvent) *ev) { if (h->h_next != history_def_next) { he_seterrev(ev, _HE_NOT_ALLOWED); - return (-1); + return -1; } ev->num = history_def_getunique(h->h_ref); - return (0); + return 0; } /* history_set_fun(): * Set history functions */ -private int -history_set_fun(History *h, History *nh) +static int +history_set_fun(TYPE(History) *h, TYPE(History) *nh) { - HistEvent ev; + TYPE(HistEvent) ev; if (nh->h_first == NULL || nh->h_next == NULL || nh->h_last == NULL || nh->h_prev == NULL || nh->h_curr == NULL || nh->h_set == NULL || nh->h_enter == NULL || nh->h_add == NULL || nh->h_clear == NULL || nh->h_del == NULL || nh->h_ref == NULL) { if (h->h_next != history_def_next) { - history_def_init(&h->h_ref, &ev, 0); + if (history_def_init(&h->h_ref, &ev, 0) == -1) + return -1; h->h_first = history_def_first; h->h_next = history_def_next; h->h_last = history_def_last; @@ -696,7 +745,7 @@ history_set_fun(History *h, History *nh) h->h_add = history_def_add; h->h_del = history_def_del; } - return (-1); + return -1; } if (h->h_next == history_def_next) history_def_clear(h->h_ref, &ev); @@ -713,47 +762,50 @@ history_set_fun(History *h, History *nh) h->h_add = nh->h_add; h->h_del = nh->h_del; - return (0); + return 0; } /* history_load(): - * History load function + * TYPE(History) load function */ -private int -history_load(History *h, const char *fname) +static int +history_load(TYPE(History) *h, const char *fname) { FILE *fp; char *line; - size_t sz, max_size; + size_t llen; + ssize_t sz; + size_t max_size; char *ptr; int i = -1; - HistEvent ev; + TYPE(HistEvent) ev; + Char *decode_result; +#ifndef NARROWCHAR + static ct_buffer_t conv; +#endif if ((fp = fopen(fname, "r")) == NULL) - return (i); + return i; - if ((line = fgetln(fp, &sz)) == NULL) + line = NULL; + llen = 0; + if ((sz = getline(&line, &llen, fp)) == -1) goto done; - if (strncmp(line, hist_cookie, sz) != 0) + if (strncmp(line, hist_cookie, (size_t)sz) != 0) goto done; - ptr = h_malloc(max_size = 1024); + ptr = h_malloc((max_size = 1024) * sizeof(*ptr)); if (ptr == NULL) goto done; - for (i = 0; (line = fgetln(fp, &sz)) != NULL; i++) { - char c = line[sz]; - - if (sz != 0 && line[sz - 1] == '\n') + for (i = 0; (sz = getline(&line, &llen, fp)) != -1; i++) { + if (sz > 0 && line[sz - 1] == '\n') line[--sz] = '\0'; - else - line[sz] = '\0'; - - if (max_size < sz) { + if (max_size < (size_t)sz) { char *nptr; - max_size = (sz + 1024) & ~1023; - nptr = h_realloc(ptr, max_size); + max_size = ((size_t)sz + 1024) & (size_t)~1023; + nptr = h_realloc(ptr, max_size * sizeof(*ptr)); if (nptr == NULL) { i = -1; goto oomem; @@ -761,151 +813,181 @@ history_load(History *h, const char *fname) ptr = nptr; } (void) strunvis(ptr, line); - line[sz] = c; - if (HENTER(h, &ev, ptr) == -1) { + decode_result = ct_decode_string(ptr, &conv); + if (decode_result == NULL) + continue; + if (HENTER(h, &ev, decode_result) == -1) { i = -1; goto oomem; } } oomem: - h_free((ptr_t)ptr); + h_free(ptr); done: + free(line); (void) fclose(fp); - return (i); + return i; } -/* history_save(): - * History save function +/* history_save_fp(): + * TYPE(History) save function */ -private int -history_save(History *h, const char *fname) +static int +history_save_fp(TYPE(History) *h, size_t nelem, FILE *fp) { - FILE *fp; - HistEvent ev; + TYPE(HistEvent) ev; int i = -1, retval; size_t len, max_size; char *ptr; - - if ((fp = fopen(fname, "w")) == NULL) - return (-1); + const char *str; +#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); + 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++) { - len = strlen(ev.str) * 4; - if (len >= max_size) { + 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) { char *nptr; - max_size = (len + 1024) & ~1023; - nptr = h_realloc(ptr, max_size); + max_size = (len + 1024) & (size_t)~1023; + nptr = h_realloc(ptr, max_size * sizeof(*ptr)); if (nptr == NULL) { i = -1; goto oomem; } ptr = nptr; } - (void) strvis(ptr, ev.str, VIS_WHITE); + (void) strvis(ptr, str, VIS_WHITE); (void) fprintf(fp, "%s\n", ptr); } oomem: - h_free((ptr_t)ptr); + h_free(ptr); done: - (void) fclose(fp); - return (i); + return i; +} + + +/* history_save(): + * History save function + */ +static int +history_save(TYPE(History) *h, const char *fname) +{ + FILE *fp; + int i; + + if ((fp = fopen(fname, "w")) == NULL) + return -1; + + i = history_save_fp(h, (size_t)-1, fp); + + (void) fclose(fp); + return i; } /* history_prev_event(): * Find the previous event, with number given */ -private int -history_prev_event(History *h, HistEvent *ev, int num) +static int +history_prev_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { int retval; for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) if (ev->num == num) - return (0); + return 0; he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } -private int -history_next_evdata(History *h, HistEvent *ev, int num, void **d) +static int +history_next_evdata(TYPE(History) *h, TYPE(HistEvent) *ev, int num, void **d) { int retval; for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) - if (num-- <= 0) { + if (ev->num == num) { if (d) *d = ((history_t *)h->h_ref)->cursor->data; - return (0); + return 0; } he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } /* history_next_event(): * Find the next event, with number given */ -private int -history_next_event(History *h, HistEvent *ev, int num) +static int +history_next_event(TYPE(History) *h, TYPE(HistEvent) *ev, int num) { int retval; for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) if (ev->num == num) - return (0); + return 0; he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } /* history_prev_string(): * Find the previous event beginning with string */ -private int -history_prev_string(History *h, HistEvent *ev, const char *str) +static int +history_prev_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) { - size_t len = strlen(str); + size_t len = Strlen(str); int retval; for (retval = HCURR(h, ev); retval != -1; retval = HNEXT(h, ev)) - if (strncmp(str, ev->str, len) == 0) - return (0); + if (Strncmp(str, ev->str, len) == 0) + return 0; he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } /* history_next_string(): * Find the next event beginning with string */ -private int -history_next_string(History *h, HistEvent *ev, const char *str) +static int +history_next_string(TYPE(History) *h, TYPE(HistEvent) *ev, const Char *str) { - size_t len = strlen(str); + size_t len = Strlen(str); int retval; for (retval = HCURR(h, ev); retval != -1; retval = HPREV(h, ev)) - if (strncmp(str, ev->str, len) == 0) - return (0); + if (Strncmp(str, ev->str, len) == 0) + return 0; he_seterrev(ev, _HE_NOT_FOUND); - return (-1); + return -1; } @@ -913,10 +995,10 @@ history_next_string(History *h, HistEvent *ev, const char *str) * User interface to history functions. */ int -history(History *h, HistEvent *ev, int fun, ...) +FUNW(history)(TYPE(History) *h, TYPE(HistEvent) *ev, int fun, ...) { va_list va; - const char *str; + const Char *str; int retval; va_start(va, fun); @@ -941,7 +1023,7 @@ history(History *h, HistEvent *ev, int fun, ...) break; case H_ADD: - str = va_arg(va, const char *); + str = va_arg(va, const Char *); retval = HADD(h, ev, str); break; @@ -950,13 +1032,13 @@ history(History *h, HistEvent *ev, int fun, ...) break; case H_ENTER: - str = va_arg(va, const char *); + str = va_arg(va, const Char *); if ((retval = HENTER(h, ev, str)) != -1) h->h_ent = ev->num; break; case H_APPEND: - str = va_arg(va, const char *); + str = va_arg(va, const Char *); if ((retval = HSET(h, ev, h->h_ent)) != -1) retval = HADD(h, ev, str); break; @@ -1002,6 +1084,21 @@ history(History *h, HistEvent *ev, int fun, ...) he_seterrev(ev, _HE_HIST_WRITE); break; + case H_SAVE_FP: + 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; @@ -1011,18 +1108,18 @@ history(History *h, HistEvent *ev, int fun, ...) break; case H_PREV_STR: - retval = history_prev_string(h, ev, va_arg(va, const char *)); + retval = history_prev_string(h, ev, va_arg(va, const Char *)); break; case H_NEXT_STR: - retval = history_next_string(h, ev, va_arg(va, const char *)); + retval = history_next_string(h, ev, va_arg(va, const Char *)); break; case H_FUNC: { - History hf; + TYPE(History) hf; - hf.h_ref = va_arg(va, ptr_t); + hf.h_ref = va_arg(va, void *); h->h_ent = -1; hf.h_first = va_arg(va, history_gfun_t); hf.h_next = va_arg(va, history_gfun_t); @@ -1041,7 +1138,7 @@ history(History *h, HistEvent *ev, int fun, ...) } case H_END: - history_end(h); + FUN(history,end)(h); retval = 0; break; @@ -1063,10 +1160,10 @@ history(History *h, HistEvent *ev, int fun, ...) case H_REPLACE: /* only use after H_NEXT_EVDATA */ { - const char *line = va_arg(va, const char *); + const Char *line = va_arg(va, const Char *); void *d = va_arg(va, void *); - const char *s; - if(!line || !(s = strdup(line))) { + const Char *s; + if(!line || !(s = Strdup(line))) { retval = -1; break; } diff --git a/clt/falcon/editline/src/historyn.c b/clt/falcon/editline/src/historyn.c new file mode 100644 index 000000000..59130dea3 --- /dev/null +++ b/clt/falcon/editline/src/historyn.c @@ -0,0 +1,3 @@ +#include "config.h" +#define NARROWCHAR +#include "history.c" diff --git a/clt/falcon/editline/src/key.c b/clt/falcon/editline/src/keymacro.c similarity index 52% rename from clt/falcon/editline/src/key.c rename to clt/falcon/editline/src/keymacro.c index 61603ee6f..cef24a175 100644 --- a/clt/falcon/editline/src/key.c +++ b/clt/falcon/editline/src/keymacro.c @@ -1,4 +1,4 @@ -/* $NetBSD: key.c,v 1.22 2009/02/21 23:31:56 christos Exp $ */ +/* $NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,283 +37,289 @@ #if 0 static char sccsid[] = "@(#)key.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: key.c,v 1.22 2009/02/21 23:31:56 christos Exp $"); +__RCSID("$NetBSD: keymacro.c,v 1.24 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* - * key.c: This module contains the procedures for maintaining - * the extended-key map. + * keymacro.c: This module contains the procedures for maintaining + * the extended-key map. * * An extended-key (key) is a sequence of keystrokes introduced * with a sequence introducer and consisting of an arbitrary - * number of characters. This module maintains a map (the el->el_key.map) + * 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 * keys are lost!! That is, if the keys "abcd" and "abcef" - * are in el->el_key.map, adding the key "abc" will cause the first two - * definitions to be lost. + * are in el->el_keymacro.map, adding the key "abc" will cause + * the first two definitions to be lost. * * Restrictions: * ------------- * 1) It is not possible to have one key that is a * substr of another. */ -#include #include +#include #include "el.h" +#include "fcns.h" /* - * The Nodes of the el->el_key.map. The el->el_key.map is a linked list - * of these node elements + * The Nodes of the el->el_keymacro.map. The el->el_keymacro.map is a + * linked list of these node elements */ -struct key_node_t { - char ch; /* single character of key */ - int type; /* node type */ - key_value_t val; /* command code or pointer to str, */ - /* if this is a leaf */ - struct key_node_t *next; /* ptr to next char of this key */ - struct key_node_t *sibling; /* ptr to another key with same prefix*/ +struct keymacro_node_t { + 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 */ + struct keymacro_node_t *next; /* ptr to next char of this key */ + struct keymacro_node_t *sibling;/* ptr to another key with same prefix*/ }; -private int node_trav(EditLine *, key_node_t *, char *, - key_value_t *); -private int node__try(EditLine *, key_node_t *, const char *, - key_value_t *, int); -private key_node_t *node__get(int); -private void node__free(key_node_t *); -private void node__put(EditLine *, key_node_t *); -private int node__delete(EditLine *, key_node_t **, const char *); -private int node_lookup(EditLine *, const char *, key_node_t *, - size_t); -private int node_enum(EditLine *, key_node_t *, size_t); +static int node_trav(EditLine *, keymacro_node_t *, wchar_t *, + keymacro_value_t *); +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); +static int node_enum(EditLine *, keymacro_node_t *, size_t); #define KEY_BUFSIZ EL_BUFSIZ -/* key_init(): +/* keymacro_init(): * Initialize the key maps */ -protected int -key_init(EditLine *el) +libedit_private int +keymacro_init(EditLine *el) { - el->el_key.buf = (char *) el_malloc(KEY_BUFSIZ); - if (el->el_key.buf == NULL) - return (-1); - el->el_key.map = NULL; - key_reset(el); - return (0); + el->el_keymacro.buf = el_calloc(KEY_BUFSIZ, + sizeof(*el->el_keymacro.buf)); + if (el->el_keymacro.buf == NULL) + return -1; + el->el_keymacro.map = NULL; + keymacro_reset(el); + return 0; } -/* key_end(): +/* keymacro_end(): * Free the key maps */ -protected void -key_end(EditLine *el) +libedit_private void +keymacro_end(EditLine *el) { - el_free((ptr_t) el->el_key.buf); - el->el_key.buf = NULL; - node__free(el->el_key.map); + el_free(el->el_keymacro.buf); + el->el_keymacro.buf = NULL; + node__free(el->el_keymacro.map); } -/* key_map_cmd(): +/* keymacro_map_cmd(): * Associate cmd with a key value */ -protected key_value_t * -key_map_cmd(EditLine *el, int cmd) +libedit_private keymacro_value_t * +keymacro_map_cmd(EditLine *el, int cmd) { - el->el_key.val.cmd = (el_action_t) cmd; - return (&el->el_key.val); + el->el_keymacro.val.cmd = (el_action_t) cmd; + return &el->el_keymacro.val; } -/* key_map_str(): +/* keymacro_map_str(): * Associate str with a key value */ -protected key_value_t * -key_map_str(EditLine *el, char *str) +libedit_private keymacro_value_t * +keymacro_map_str(EditLine *el, wchar_t *str) { - el->el_key.val.str = str; - return (&el->el_key.val); + el->el_keymacro.val.str = str; + return &el->el_keymacro.val; } -/* key_reset(): - * Takes all nodes on el->el_key.map and puts them on free list. Then - * initializes el->el_key.map with arrow keys +/* keymacro_reset(): + * Takes all nodes on el->el_keymacro.map and puts them on free list. + * Then initializes el->el_keymacro.map with arrow keys * [Always bind the ansi arrow keys?] */ -protected void -key_reset(EditLine *el) +libedit_private void +keymacro_reset(EditLine *el) { - node__put(el, el->el_key.map); - el->el_key.map = NULL; + node__put(el, el->el_keymacro.map); + el->el_keymacro.map = NULL; return; } -/* key_get(): - * Calls the recursive function with entry point el->el_key.map +/* keymacro_get(): + * Calls the recursive function with entry point el->el_keymacro.map * Looks up *ch in map and then reads characters until a * complete match is found or a mismatch occurs. Returns the - * type of the match found (XK_STR, XK_CMD, or XK_EXE). + * 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 -key_get(EditLine *el, char *ch, key_value_t *val) +libedit_private int +keymacro_get(EditLine *el, wchar_t *ch, keymacro_value_t *val) { - return (node_trav(el, el->el_key.map, ch, val)); + return node_trav(el, el->el_keymacro.map, ch, val); } -/* key_add(): - * Adds key to the el->el_key.map and associates the value in val with it. - * If key is already is in el->el_key.map, the new code is applied to the - * existing key. Ntype specifies if code is a command, an - * out str or a unix command. +/* keymacro_add(): + * Adds key to the el->el_keymacro.map and associates the value in + * val with it. If key is already is in el->el_keymacro.map, the new + * code is applied to the existing key. Ntype specifies if code is a + * command, an out str or a unix command. */ -protected void -key_add(EditLine *el, const char *key, key_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') { (void) fprintf(el->el_errfile, - "key_add: Null extended-key not allowed.\n"); + "keymacro_add: Null extended-key not allowed.\n"); return; } if (ntype == XK_CMD && val->cmd == ED_SEQUENCE_LEAD_IN) { (void) fprintf(el->el_errfile, - "key_add: sequence-lead-in command not allowed\n"); + "keymacro_add: sequence-lead-in command not allowed\n"); return; } - if (el->el_key.map == NULL) + if (el->el_keymacro.map == NULL) /* tree is initially empty. Set up new node to match key[0] */ - el->el_key.map = node__get(key[0]); + el->el_keymacro.map = node__get(key[0]); /* it is properly initialized */ - /* Now recurse through el->el_key.map */ - (void) node__try(el, el->el_key.map, key, val, ntype); + /* Now recurse through el->el_keymacro.map */ + (void) node__try(el, el->el_keymacro.map, key, val, ntype); return; } -/* key_clear(): +/* keymacro_clear(): * */ -protected void -key_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) { - + if (*in > N_KEYS) /* can't be in the map */ + return; if ((map[(unsigned char)*in] == ED_SEQUENCE_LEAD_IN) && ((map == el->el_map.key && el->el_map.alt[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN) || (map == el->el_map.alt && el->el_map.key[(unsigned char)*in] != ED_SEQUENCE_LEAD_IN))) - (void) key_delete(el, in); + (void) keymacro_delete(el, in); } -/* key_delete(): +/* keymacro_delete(): * Delete the key and all longer keys staring with key, if * they exists. */ -protected int -key_delete(EditLine *el, const char *key) +libedit_private int +keymacro_delete(EditLine *el, const wchar_t *key) { if (key[0] == '\0') { (void) fprintf(el->el_errfile, - "key_delete: Null extended-key not allowed.\n"); - return (-1); + "keymacro_delete: Null extended-key not allowed.\n"); + return -1; } - if (el->el_key.map == NULL) - return (0); + if (el->el_keymacro.map == NULL) + return 0; - (void) node__delete(el, &el->el_key.map, key); - return (0); + (void) node__delete(el, &el->el_keymacro.map, key); + return 0; } -/* key_print(): +/* keymacro_print(): * Print the binding associated with key key. - * Print entire el->el_key.map if null + * Print entire el->el_keymacro.map if null */ -protected void -key_print(EditLine *el, const char *key) +libedit_private void +keymacro_print(EditLine *el, const wchar_t *key) { - /* do nothing if el->el_key.map is empty and null key specified */ - if (el->el_key.map == NULL && *key == 0) + /* do nothing if el->el_keymacro.map is empty and null key specified */ + if (el->el_keymacro.map == NULL && *key == 0) return; - el->el_key.buf[0] = '"'; - if (node_lookup(el, key, el->el_key.map, 1) <= -1) + 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 \"%s\"\n", - key); + (void) fprintf(el->el_errfile, "Unbound extended key \"%ls" + "\"\n", key); return; } /* node_trav(): * recursively traverses node in tree until match or mismatch is - * found. May read in more characters. + * found. May read in more characters. */ -private int -node_trav(EditLine *el, key_node_t *ptr, char *ch, key_value_t *val) +static int +node_trav(EditLine *el, keymacro_node_t *ptr, wchar_t *ch, + keymacro_value_t *val) { if (ptr->ch == *ch) { /* match found */ if (ptr->next) { /* key not complete so get next char */ - if (el_getc(el, ch) != 1) { /* if EOF or error */ - val->cmd = ED_END_OF_FILE; - return (XK_CMD); - /* PWP: Pretend we just read an end-of-file */ - } - return (node_trav(el, ptr->next, ch, val)); + if (el_wgetc(el, ch) != 1) + return XK_NOD; + return node_trav(el, ptr->next, ch, val); } else { *val = ptr->val; if (ptr->type != XK_CMD) *ch = '\0'; - return (ptr->type); + return ptr->type; } } else { /* no match found here */ if (ptr->sibling) { /* try next sibling */ - return (node_trav(el, ptr->sibling, ch, val)); + return node_trav(el, ptr->sibling, ch, val); } else { /* no next sibling -- mismatch */ val->str = NULL; - return (XK_STR); + return XK_STR; } } } /* node__try(): - * Find a node that matches *str or allocate a new one + * Find a node that matches *str or allocate a new one */ -private int -node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ntype) +static int +node__try(EditLine *el, keymacro_node_t *ptr, const wchar_t *str, + keymacro_value_t *val, int ntype) { if (ptr->ch != *str) { - key_node_t *xm; + keymacro_node_t *xm; for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) if (xm->sibling->ch == *str) @@ -334,9 +340,8 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int case XK_NOD: break; case XK_STR: - case XK_EXE: if (ptr->val.str) - el_free((ptr_t) ptr->val.str); + el_free(ptr->val.str); break; default: EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", @@ -349,8 +354,7 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ptr->val = *val; break; case XK_STR: - case XK_EXE: - if ((ptr->val.str = el_strdup(val->str)) == NULL) + if ((ptr->val.str = wcsdup(val->str)) == NULL) return -1; break; default: @@ -363,29 +367,29 @@ node__try(EditLine *el, key_node_t *ptr, const char *str, key_value_t *val, int ptr->next = node__get(*str); /* setup new node */ (void) node__try(el, ptr->next, str, val, ntype); } - return (0); + return 0; } /* node__delete(): * Delete node that matches str */ -private int -node__delete(EditLine *el, key_node_t **inptr, const char *str) +static int +node__delete(EditLine *el, keymacro_node_t **inptr, const wchar_t *str) { - key_node_t *ptr; - key_node_t *prev_ptr = NULL; + keymacro_node_t *ptr; + keymacro_node_t *prev_ptr = NULL; ptr = *inptr; if (ptr->ch != *str) { - key_node_t *xm; + keymacro_node_t *xm; for (xm = ptr; xm->sibling != NULL; xm = xm->sibling) if (xm->sibling->ch == *str) break; if (xm->sibling == NULL) - return (0); + return 0; prev_ptr = xm; ptr = xm->sibling; } @@ -397,20 +401,20 @@ node__delete(EditLine *el, key_node_t **inptr, const char *str) prev_ptr->sibling = ptr->sibling; ptr->sibling = NULL; node__put(el, ptr); - return (1); + return 1; } else if (ptr->next != NULL && node__delete(el, &ptr->next, str) == 1) { if (ptr->next != NULL) - return (0); + return 0; if (prev_ptr == NULL) *inptr = ptr->sibling; else prev_ptr->sibling = ptr->sibling; ptr->sibling = NULL; node__put(el, ptr); - return (1); + return 1; } else { - return (0); + return 0; } } @@ -418,8 +422,8 @@ node__delete(EditLine *el, key_node_t **inptr, const char *str) /* node__put(): * Puts a tree of nodes onto free list using free(3). */ -private void -node__put(EditLine *el, key_node_t *ptr) +static void +node__put(EditLine *el, keymacro_node_t *ptr) { if (ptr == NULL) return; @@ -434,28 +438,27 @@ node__put(EditLine *el, key_node_t *ptr) case XK_CMD: case XK_NOD: break; - case XK_EXE: case XK_STR: if (ptr->val.str != NULL) - el_free((ptr_t) ptr->val.str); + el_free(ptr->val.str); break; default: EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ptr->type)); break; } - el_free((ptr_t) ptr); + el_free(ptr); } /* node__get(): - * Returns pointer to a key_node_t for ch. + * Returns pointer to a keymacro_node_t for ch. */ -private key_node_t * -node__get(int ch) +static keymacro_node_t * +node__get(wint_t ch) { - key_node_t *ptr; + keymacro_node_t *ptr; - ptr = (key_node_t *) el_malloc((size_t) sizeof(key_node_t)); + ptr = el_malloc(sizeof(*ptr)); if (ptr == NULL) return NULL; ptr->ch = ch; @@ -463,56 +466,59 @@ node__get(int ch) ptr->val.str = NULL; ptr->next = NULL; ptr->sibling = NULL; - return (ptr); + return ptr; } -private void -node__free(key_node_t *k) +static void +node__free(keymacro_node_t *k) { if (k == NULL) return; node__free(k->sibling); node__free(k->next); - el_free((ptr_t) k); + el_free(k); } /* node_lookup(): * look for the str starting at node ptr. * Print if last node */ -private int -node_lookup(EditLine *el, const char *str, key_node_t *ptr, size_t cnt) +static int +node_lookup(EditLine *el, const wchar_t *str, keymacro_node_t *ptr, + size_t cnt) { - size_t ncnt; + ssize_t used; if (ptr == NULL) - return (-1); /* cannot have null ptr */ + return -1; /* cannot have null ptr */ - if (*str == 0) { + if (!str || *str == 0) { /* no more chars in str. node_enum from here. */ (void) node_enum(el, ptr, cnt); - return (0); + return 0; } else { - /* If match put this char into el->el_key.buf. Recurse */ + /* If match put this char into el->el_keymacro.buf. Recurse */ if (ptr->ch == *str) { /* match found */ - ncnt = key__decode_char(el->el_key.buf, - (size_t)KEY_BUFSIZ, cnt, - (unsigned char) ptr->ch); + used = ct_visual_char(el->el_keymacro.buf + cnt, + KEY_BUFSIZ - cnt, ptr->ch); + if (used == -1) + return -1; /* ran out of buffer space */ if (ptr->next != NULL) /* not yet at leaf */ return (node_lookup(el, str + 1, ptr->next, - ncnt + 1)); + (size_t)used + cnt)); else { /* next node is null so key should be complete */ if (str[1] == 0) { - el->el_key.buf[ncnt + 1] = '"'; - el->el_key.buf[ncnt + 2] = '\0'; - key_kprint(el, el->el_key.buf, + size_t px = cnt + (size_t)used; + el->el_keymacro.buf[px] = '"'; + el->el_keymacro.buf[px + 1] = '\0'; + keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type); - return (0); + return 0; } else - return (-1); + return -1; /* mismatch -- str still has chars */ } } else { @@ -521,7 +527,7 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, size_t cnt) return (node_lookup(el, str, ptr->sibling, cnt)); else - return (-1); + return -1; } } } @@ -530,50 +536,52 @@ node_lookup(EditLine *el, const char *str, key_node_t *ptr, size_t cnt) /* node_enum(): * Traverse the node printing the characters it is bound in buffer */ -private int -node_enum(EditLine *el, key_node_t *ptr, size_t cnt) +static int +node_enum(EditLine *el, keymacro_node_t *ptr, size_t cnt) { - size_t ncnt; + ssize_t used; if (cnt >= KEY_BUFSIZ - 5) { /* buffer too small */ - el->el_key.buf[++cnt] = '"'; - el->el_key.buf[++cnt] = '\0'; + el->el_keymacro.buf[++cnt] = '"'; + el->el_keymacro.buf[++cnt] = '\0'; (void) fprintf(el->el_errfile, "Some extended keys too long for internal print buffer"); - (void) fprintf(el->el_errfile, " \"%s...\"\n", el->el_key.buf); - return (0); + (void) fprintf(el->el_errfile, " \"%ls...\"\n", + el->el_keymacro.buf); + return 0; } if (ptr == NULL) { #ifdef DEBUG_EDIT (void) fprintf(el->el_errfile, "node_enum: BUG!! Null ptr passed\n!"); #endif - return (-1); + return -1; } /* put this char at end of str */ - ncnt = key__decode_char(el->el_key.buf, (size_t)KEY_BUFSIZ, cnt, - (unsigned char)ptr->ch); + used = ct_visual_char(el->el_keymacro.buf + cnt, KEY_BUFSIZ - cnt, + ptr->ch); if (ptr->next == NULL) { /* print this key and function */ - el->el_key.buf[ncnt + 1] = '"'; - el->el_key.buf[ncnt + 2] = '\0'; - key_kprint(el, el->el_key.buf, &ptr->val, ptr->type); + el->el_keymacro.buf[cnt + (size_t)used ] = '"'; + el->el_keymacro.buf[cnt + (size_t)used + 1] = '\0'; + keymacro_kprint(el, el->el_keymacro.buf, &ptr->val, ptr->type); } else - (void) node_enum(el, ptr->next, ncnt + 1); + (void) node_enum(el, ptr->next, cnt + (size_t)used); /* go to sibling if there is one */ if (ptr->sibling) (void) node_enum(el, ptr->sibling, cnt); - return (0); + return 0; } -/* key_kprint(): +/* keymacro_kprint(): * Print the specified key and its associated * function specified by val */ -protected void -key_kprint(EditLine *el, const char *key, key_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]; @@ -582,17 +590,19 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) if (val != NULL) switch (ntype) { case XK_STR: - case XK_EXE: - (void) key__decode_str(val->str, unparsbuf, - sizeof(unparsbuf), + (void) keymacro__decode_str(val->str, unparsbuf, + sizeof(unparsbuf), ntype == XK_STR ? "\"\"" : "[]"); - (void) fprintf(el->el_outfile, fmt, key, unparsbuf); + (void) fprintf(el->el_outfile, fmt, + ct_encode_string(key, &el->el_scratch), unparsbuf); break; case XK_CMD: for (fp = el->el_map.help; fp->name; fp++) if (val->cmd == fp->func) { + wcstombs(unparsbuf, fp->name, sizeof(unparsbuf)); + unparsbuf[sizeof(unparsbuf) -1] = '\0'; (void) fprintf(el->el_outfile, fmt, - key, fp->name); + ct_encode_string(key, &el->el_scratch), unparsbuf); break; } #ifdef DEBUG_KEY @@ -607,7 +617,8 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) break; } else - (void) fprintf(el->el_outfile, fmt, key, "no input"); + (void) fprintf(el->el_outfile, fmt, ct_encode_string(key, + &el->el_scratch), "no input"); } @@ -616,52 +627,15 @@ key_kprint(EditLine *el, const char *key, key_value_t *val, int ntype) *b++ = c; \ else \ b++ -/* key__decode_char(): - * Put a printable form of char in buf. - */ -protected size_t -key__decode_char(char *buf, size_t cnt, size_t off, int ch) -{ - char *sb = buf + off; - char *eb = buf + cnt; - char *b = sb; - if (ch == 0) { - ADDC('^'); - ADDC('@'); - return (int)(b - sb); - } - if (iscntrl(ch)) { - ADDC('^'); - if (ch == '\177') - ADDC('?'); - else - ADDC(ch | 0100); - } else if (ch == '^') { - ADDC('\\'); - ADDC('^'); - } else if (ch == '\\') { - ADDC('\\'); - ADDC('\\'); - } else if (ch == ' ' || (isprint(ch) && !isspace(ch))) { - ADDC(ch); - } else { - ADDC('\\'); - ADDC((((unsigned int) ch >> 6) & 7) + '0'); - ADDC((((unsigned int) ch >> 3) & 7) + '0'); - ADDC((ch & 7) + '0'); - } - return (size_t)(b - sb); -} - - -/* key__decode_str(): +/* keymacro__decode_str(): * Make a printable version of the ey */ -protected size_t -key__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') { @@ -670,36 +644,24 @@ key__decode_str(const char *str, char *buf, size_t len, const char *sep) if (*str == '\0') { ADDC('^'); ADDC('@'); - if (sep[0] != '\0' && sep[1] != '\0') { - ADDC(sep[1]); - } - goto done; + goto add_endsep; } for (p = str; *p != 0; p++) { - if (iscntrl((unsigned char) *p)) { - ADDC('^'); - if (*p == '\177') { - ADDC('?'); - } else { - ADDC(*p | 0100); - } - } else if (*p == '^' || *p == '\\') { - ADDC('\\'); - ADDC(*p); - } else if (*p == ' ' || (isprint((unsigned char) *p) && - !isspace((unsigned char) *p))) { - ADDC(*p); - } else { - ADDC('\\'); - ADDC((((unsigned int) *p >> 6) & 7) + '0'); - ADDC((((unsigned int) *p >> 3) & 7) + '0'); - ADDC((*p & 7) + '0'); + 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++); + if (n == -1) /* ran out of space */ + goto add_endsep; + else + b += n; } } +add_endsep: if (sep[0] != '\0' && sep[1] != '\0') { ADDC(sep[1]); } -done: ADDC('\0'); if ((size_t)(b - buf) >= len) buf[len - 1] = '\0'; diff --git a/clt/falcon/editline/src/key.h b/clt/falcon/editline/src/keymacro.h similarity index 58% rename from clt/falcon/editline/src/key.h rename to clt/falcon/editline/src/keymacro.h index d09ad36e0..0653bbe3f 100644 --- a/clt/falcon/editline/src/key.h +++ b/clt/falcon/editline/src/keymacro.h @@ -1,4 +1,4 @@ -/* $NetBSD: key.h,v 1.12 2009/02/21 23:31:56 christos Exp $ */ +/* $NetBSD: keymacro.h,v 1.6 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -35,47 +35,42 @@ */ /* - * el.key.h: Key macro header + * el.keymacro.h: Key macro header */ -#ifndef _h_el_key -#define _h_el_key +#ifndef _h_el_keymacro +#define _h_el_keymacro -typedef union key_value_t { +typedef union keymacro_value_t { el_action_t cmd; /* If it is a command the # */ - char *str; /* If it is a string... */ -} key_value_t; + wchar_t *str; /* If it is a string... */ +} keymacro_value_t; -typedef struct key_node_t key_node_t; +typedef struct keymacro_node_t keymacro_node_t; -typedef struct el_key_t { - char *buf; /* Key print buffer */ - key_node_t *map; /* Key map */ - key_value_t val; /* Local conversion buffer */ -} el_key_t; +typedef struct el_keymacro_t { + wchar_t *buf; /* Key print buffer */ + keymacro_node_t *map; /* Key map */ + keymacro_value_t val; /* Local conversion buffer */ +} el_keymacro_t; #define XK_CMD 0 #define XK_STR 1 #define XK_NOD 2 -#define XK_EXE 3 -#undef key_end -#undef key_clear -#undef key_print - -protected int key_init(EditLine *); -protected void key_end(EditLine *); -protected key_value_t *key_map_cmd(EditLine *, int); -protected key_value_t *key_map_str(EditLine *, char *); -protected void key_reset(EditLine *); -protected int key_get(EditLine *, char *, key_value_t *); -protected void key_add(EditLine *, const char *, key_value_t *, int); -protected void key_clear(EditLine *, el_action_t *, const char *); -protected int key_delete(EditLine *, const char *); -protected void key_print(EditLine *, const char *); -protected void key_kprint(EditLine *, const char *, key_value_t *, - int); -protected size_t key__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 *); -protected size_t key__decode_char(char *, size_t, size_t, int); -#endif /* _h_el_key */ +#endif /* _h_el_keymacro */ diff --git a/clt/falcon/editline/src/literal.c b/clt/falcon/editline/src/literal.c new file mode 100644 index 000000000..3c5681648 --- /dev/null +++ b/clt/falcon/editline/src/literal.c @@ -0,0 +1,138 @@ +/* $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) +#if 0 +__RCSID("$NetBSD: literal.c,v 1.5 2019/07/23 13:10:11 christos Exp $"); +#endif +#endif /* not lint && not SCCSID */ + +/* + * literal.c: Literal sequences handling. + */ +#include +#include +#include +#include +#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]; +} diff --git a/clt/falcon/editline/src/literal.h b/clt/falcon/editline/src/literal.h new file mode 100644 index 000000000..a8e0a4168 --- /dev/null +++ b/clt/falcon/editline/src/literal.h @@ -0,0 +1,53 @@ +/* $NetBSD: literal.h,v 1.2 2017/06/30 20:26:52 kre 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. + */ + +/* + * el.literal.h: Literal character + */ +#ifndef _h_el_literal +#define _h_el_literal + +#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 */ diff --git a/clt/falcon/editline/src/makelist b/clt/falcon/editline/src/makelist index 06ae91b54..01104524f 100644 --- a/clt/falcon/editline/src/makelist +++ b/clt/falcon/editline/src/makelist @@ -1,5 +1,5 @@ #!/bin/sh - -# $NetBSD: makelist,v 1.12 2009/02/12 13:39:49 sketch 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. @@ -35,8 +35,16 @@ # makelist.sh: Automatically generate header files... -AWK=awk -USAGE="Usage: $0 -h|-e|-fc|-fh|-bc|-bh|-m " +LC_ALL=C +LANG=C +export LC_ALL LANG + +if [ "x$AWK" = "x" ] +then + AWK=awk +fi + +USAGE="Usage: $0 -h|-fc|-fh|-bh " if [ "x$1" = "x" ] then @@ -51,8 +59,6 @@ FILES="$@" case $FLAG in -# generate foo.h file from foo.c -# -h) set - `echo $FILES | sed -e 's/\\./_/g'` hdr="_h_`basename $1`" @@ -69,7 +75,8 @@ case $FLAG in # XXX: need a space between name and prototype so that -fc and -fh # parsing is much easier # - printf("protected el_action_t\t%s (EditLine *, int);\n", name); + printf("libedit_private el_action_t\t%s (EditLine *, wint_t);\n", + name); } } END { @@ -77,14 +84,13 @@ case $FLAG in }' ;; -# 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("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++) @@ -104,13 +110,13 @@ case $FLAG in fname = fname s; } - printf(" { %-30.30s %-30.30s\n","\"" fname "\",", uname ","); + printf(" { %-30.30s %-30.30s\n","L\"" fname "\",", uname ","); ok = 1; } } /^ \*/ { if (ok) { - printf(" \""); + printf(" L\""); for (i = 2; i < NF; i++) printf("%s ", $i); printf("%s\" },\n", $i); @@ -119,23 +125,9 @@ case $FLAG in } END { printf("};\n"); - printf("\nprotected const el_bindings_t* help__get()"); - printf("{ return el_func_help; }\n"); }' ;; -# generate help.h from various .c files -# --bh) - $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("#ifndef _h_help_c\n#define _h_help_c\n"); - printf("protected const el_bindings_t *help__get(void);\n"); - printf("#endif /* _h_help_c */\n"); - }' /dev/null - ;; - # generate fcns.h from various .h files # -fh) @@ -143,7 +135,6 @@ case $FLAG in 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; } { @@ -151,21 +142,16 @@ case $FLAG in } END { printf("#define\t%-30.30s\t%3d\n", "EL_NUM_FCNS", count); - - printf("typedef el_action_t (*el_func_t)(EditLine *, int);"); - printf("\nprotected const el_func_t* func__get(void);\n"); - printf("#endif /* _h_fcns_c */\n"); }' ;; -# generate fcns.c from various .h files +# 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("private const el_func_t el_func[] = {"); + printf("static const el_func_t el_func[] = {"); maxlen = 80; needn = 1; len = 0; @@ -185,59 +171,6 @@ case $FLAG in } END { printf("\n};\n"); - printf("\nprotected const el_func_t* func__get() { return el_func; }\n"); - }' - ;; - -# generate editline.c from various .c files -# --e) - echo "$FILES" | tr ' ' '\012' | $AWK ' - BEGIN { - printf("/* Automatically generated file, do not edit */\n"); - printf("#define protected static\n"); - printf("#define SCCSID\n"); - } - { - printf("#include \"%s\"\n", $1); - }' - ;; - -# generate man page fragment from various .c files -# --m) - cat $FILES | $AWK ' - BEGIN { - printf(".\\\" Section automatically generated with makelist\n"); - printf(".Bl -tag -width 4n\n"); - } - /\(\):/ { - pr = substr($2, 1, 2); - if (pr == "vi" || pr == "em" || pr == "ed") { - name = substr($2, 1, length($2) - 3); - fname = ""; - for (i = 1; i <= length(name); i++) { - s = substr(name, i, 1); - if (s == "_") - s = "-"; - fname = fname s; - } - - printf(".It Ic %s\n", fname); - ok = 1; - } - } - /^ \*/ { - if (ok) { - for (i = 2; i < NF; i++) - printf("%s ", $i); - printf("%s.\n", $i); - ok = 0; - } - } - END { - printf(".El\n"); - printf(".\\\" End of section automatically generated with makelist\n"); }' ;; diff --git a/clt/falcon/editline/src/map.c b/clt/falcon/editline/src/map.c index 322c1f1e6..321bb3539 100644 --- a/clt/falcon/editline/src/map.c +++ b/clt/falcon/editline/src/map.c @@ -1,4 +1,4 @@ -/* $NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $ */ +/* $NetBSD: map.c,v 1.54 2021/08/29 09:41:59 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,32 +37,40 @@ #if 0 static char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: map.c,v 1.24 2006/04/09 01:36:51 christos Exp $"); +__RCSID("$NetBSD: map.c,v 1.54 2021/08/29 09:41:59 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* * map.c: Editor function definitions */ +#include #include -#include "el.h" - -#define N_KEYS 256 +#include -private void map_print_key(EditLine *, el_action_t *, const char *); -private void map_print_some_keys(EditLine *, el_action_t *, int, int); -private void map_print_all_keys(EditLine *); -private void map_init_nls(EditLine *); -private void map_init_meta(EditLine *); +#include "el.h" +#include "common.h" +#include "emacs.h" +#include "vi.h" +#include "fcns.h" +#include "func.h" +#include "help.h" +#include "parse.h" + +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 */ @@ -74,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 */ - /* 18 */ ED_REDISPLAY, /* ^R */ - /* 19 */ ED_TTY_STOP_OUTPUT, /* ^S */ + /* 17 */ ED_IGNORE, /* ^Q */ + /* 18 */ EM_INC_SEARCH_PREV, /* ^R */ + /* 19 */ ED_IGNORE, /* ^S */ /* 20 */ ED_TRANSPOSE_CHARS, /* ^T */ /* 21 */ EM_KILL_LINE, /* ^U */ /* 22 */ ED_QUOTED_INSERT, /* ^V */ - /* 23 */ EM_KILL_REGION, /* ^W */ + /* 23 */ ED_DELETE_PREV_WORD, /* ^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 */ @@ -325,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 */ @@ -344,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 */ @@ -356,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,7 +378,7 @@ private const el_action_t el_map_vi_insert[] = { /* 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 */ @@ -382,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, /* ^_ */ @@ -626,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 */ @@ -642,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 */ @@ -655,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, /* ^_ */ @@ -889,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) { @@ -898,33 +906,32 @@ map_init(EditLine *el) */ #ifdef MAP_DEBUG if (sizeof(el_map_emacs) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Emacs map incorrect\n")); + EL_ABORT((el->el_errfile, "Emacs map incorrect\n")); if (sizeof(el_map_vi_command) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Vi command map incorrect\n")); + EL_ABORT((el->el_errfile, "Vi command map incorrect\n")); if (sizeof(el_map_vi_insert) != N_KEYS * sizeof(el_action_t)) - EL_ABORT((el->errfile, "Vi insert map incorrect\n")); + EL_ABORT((el->el_errfile, "Vi insert map incorrect\n")); #endif - el->el_map.alt = (el_action_t *)el_malloc(sizeof(el_action_t) * 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_action_t *)el_malloc(sizeof(el_action_t) * N_KEYS); + return -1; + el->el_map.key = el_calloc(N_KEYS, sizeof(*el->el_map.key)); if (el->el_map.key == NULL) - return (-1); + 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_bindings_t *) el_malloc(sizeof(el_bindings_t) * - 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(), - sizeof(el_bindings_t) * EL_NUM_FCNS); - el->el_map.func = (el_func_t *)el_malloc(sizeof(el_func_t) * - EL_NUM_FCNS); + return -1; + (void) memcpy(el->el_map.help, el_func_help, + sizeof(*el->el_map.help) * 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_func_t) * EL_NUM_FCNS); + return -1; + memcpy(el->el_map.func, el_func, sizeof(*el->el_map.func) + * EL_NUM_FCNS); el->el_map.nfunc = EL_NUM_FCNS; #ifdef VIDEFAULT @@ -932,27 +939,27 @@ map_init(EditLine *el) #else map_init_emacs(el); #endif /* VIDEFAULT */ - return (0); + return 0; } /* map_end(): * Free the space taken by the editor maps */ -protected void +libedit_private void map_end(EditLine *el) { - el_free((ptr_t) el->el_map.alt); + el_free(el->el_map.alt); el->el_map.alt = NULL; - el_free((ptr_t) el->el_map.key); + el_free(el->el_map.key); el->el_map.key = NULL; el->el_map.emacs = NULL; el->el_map.vic = NULL; el->el_map.vii = NULL; - el_free((ptr_t) el->el_map.help); + el_free(el->el_map.help); el->el_map.help = NULL; - el_free((ptr_t) el->el_map.func); + el_free(el->el_map.func); el->el_map.func = NULL; } @@ -960,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; @@ -968,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; } @@ -976,10 +983,10 @@ map_init_nls(EditLine *el) /* map_init_meta(): * Bind all the meta keys to the appropriate ESC- 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; @@ -997,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]) { @@ -1007,7 +1014,7 @@ map_init_meta(EditLine *el) break; default: buf[1] = i & 0177; - key_add(el, buf, key_map_cmd(el, (int) map[i]), XK_CMD); + keymacro_add(el, buf, keymacro_map_cmd(el, (int) map[i]), XK_CMD); break; } map[(int) buf[0]] = ED_SEQUENCE_LEAD_IN; @@ -1017,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; @@ -1029,7 +1036,7 @@ map_init_vi(EditLine *el) el->el_map.type = MAP_VI; el->el_map.current = el->el_map.key; - key_reset(el); + keymacro_reset(el); for (i = 0; i < N_KEYS; i++) { key[i] = vii[i]; @@ -1040,25 +1047,25 @@ map_init_vi(EditLine *el) map_init_nls(el); tty_bind_char(el, 1); - term_bind_arrow(el); + terminal_bind_arrow(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; el->el_map.type = MAP_EMACS; el->el_map.current = el->el_map.key; - key_reset(el); + keymacro_reset(el); for (i = 0; i < N_KEYS; i++) { key[i] = emacs[i]; @@ -1071,84 +1078,84 @@ map_init_emacs(EditLine *el) buf[0] = CONTROL('X'); buf[1] = CONTROL('X'); buf[2] = 0; - key_add(el, buf, key_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); + keymacro_add(el, buf, keymacro_map_cmd(el, EM_EXCHANGE_MARK), XK_CMD); tty_bind_char(el, 1); - term_bind_arrow(el); + terminal_bind_arrow(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, "emacs") == 0) { + if (wcscmp(editor, L"emacs") == 0) { map_init_emacs(el); - return (0); + return 0; } - if (strcmp(editor, "vi") == 0) { + if (wcscmp(editor, L"vi") == 0) { map_init_vi(el); - return (0); + return 0; } - return (-1); + return -1; } /* 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); + return -1; switch (el->el_map.type) { case MAP_EMACS: - *editor = "emacs"; - return (0); + *editor = L"emacs"; + return 0; case MAP_VI: - *editor = "vi"; - return (0); + *editor = L"vi"; + return 0; } - return (-1); + return -1; } /* 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; if (in[0] == '\0' || in[1] == '\0') { - (void) key__decode_str(in, outbuf, sizeof(outbuf), ""); + (void) keymacro__decode_str(in, outbuf, sizeof(outbuf), ""); ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) if (bp->func == map[(unsigned char) *in]) { (void) fprintf(el->el_outfile, - "%s\t->\t%s\n", outbuf, bp->name); + "%s\t->\t%ls\n", outbuf, bp->name); return; } } else - key_print(el, in); + keymacro_print(el, in); } /* map_print_some_keys(): * Print keys from first to last */ -private void -map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) +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] = first; @@ -1157,7 +1164,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) lastbuf[1] = 0; if (map[first] == ED_UNASSIGNED) { if (first == last) { - (void) key__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "%-15s-> is undefined\n", unparsbuf); @@ -1168,17 +1175,17 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) for (bp = el->el_map.help; bp < ep; bp++) { if (bp->func == map[first]) { if (first == last) { - (void) key__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); - (void) fprintf(el->el_outfile, "%-15s-> %s\n", + (void) fprintf(el->el_outfile, "%-15s-> %ls\n", unparsbuf, bp->name); } else { - (void) key__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); - (void) key__decode_str(lastbuf, extrabuf, + (void) keymacro__decode_str(lastbuf, extrabuf, sizeof(extrabuf), STRQQ); (void) fprintf(el->el_outfile, - "%-4s to %-7s-> %s\n", + "%-4s to %-7s-> %ls\n", unparsbuf, extrabuf, bp->name); } return; @@ -1186,14 +1193,14 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int last) } #ifdef MAP_DEBUG if (map == el->el_map.key) { - (void) key__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", unparsbuf); (void) fprintf(el->el_outfile, "el->el_map.key[%d] == %d\n", first, el->el_map.key[first]); } else { - (void) key__decode_str(firstbuf, unparsbuf, + (void) keymacro__decode_str(firstbuf, unparsbuf, sizeof(unparsbuf), STRQQ); (void) fprintf(el->el_outfile, "BUG!!! %s isn't bound to anything.\n", unparsbuf); @@ -1208,7 +1215,7 @@ map_print_some_keys(EditLine *el, el_action_t *map, int first, int 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; @@ -1234,31 +1241,31 @@ 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"); - key_print(el, ""); + keymacro_print(el, L""); (void) fprintf(el->el_outfile, "Arrow key bindings\n"); - term_print_arrow(el, ""); + 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 = NULL; + 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; if (argv == NULL) - return (-1); + return -1; map = el->el_map.key; ntype = XK_CMD; @@ -1273,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; @@ -1288,135 +1290,138 @@ map_bind(EditLine *el, int argc, const char **argv) case 'v': map_init_vi(el); - return (0); + return 0; case 'e': map_init_emacs(el); - return (0); + return 0; case 'l': ep = &el->el_map.help[el->el_map.nfunc]; for (bp = el->el_map.help; bp < ep; bp++) (void) fprintf(el->el_outfile, - "%s\n\t%s\n", + "%ls\n\t%ls\n", bp->name, bp->description); - return (0); + return 0; default: (void) fprintf(el->el_errfile, - "%s: Invalid switch `%c'.\n", - argv[0], p[1]); + "%ls: Invalid switch `%lc'.\n", + argv[0], (wint_t)p[1]); } else break; if (argv[argc] == NULL) { map_print_all_keys(el); - return (0); + return 0; } if (key) in = argv[argc++]; else if ((in = parse__string(inbuf, argv[argc++])) == NULL) { (void) fprintf(el->el_errfile, - "%s: Invalid \\ or ^ in instring.\n", + "%ls: Invalid \\ or ^ in instring.\n", argv[0]); - return (-1); + return -1; } if (rem) { if (key) { - (void) term_clear_arrow(el, in); - return (-1); + (void) terminal_clear_arrow(el, in); + return -1; } if (in[1]) - (void) key_delete(el, in); + (void) keymacro_delete(el, in); else if (map[(unsigned char) *in] == ED_SEQUENCE_LEAD_IN) - (void) key_delete(el, in); + (void) keymacro_delete(el, in); else map[(unsigned char) *in] = ED_UNASSIGNED; - return (0); + return 0; } if (argv[argc] == NULL) { if (key) - term_print_arrow(el, in); + terminal_print_arrow(el, in); else map_print_key(el, map, in); - return (0); + return 0; } #ifdef notyet if (argv[argc + 1] != NULL) { - bindkey_usage(); - return (-1); + bindkeymacro_usage(); + return -1; } #endif switch (ntype) { case XK_STR: - case XK_EXE: if ((out = parse__string(outbuf, argv[argc])) == NULL) { (void) fprintf(el->el_errfile, - "%s: Invalid \\ or ^ in outstring.\n", argv[0]); - return (-1); + "%ls: Invalid \\ or ^ in outstring.\n", argv[0]); + return -1; } if (key) - term_set_arrow(el, in, key_map_str(el, out), ntype); + terminal_set_arrow(el, in, keymacro_map_str(el, out), ntype); else - key_add(el, in, key_map_str(el, out), ntype); + keymacro_add(el, in, keymacro_map_str(el, out), ntype); map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; break; case XK_CMD: if ((cmd = parse_cmd(el, argv[argc])) == -1) { (void) fprintf(el->el_errfile, - "%s: Invalid command `%s'.\n", argv[0], argv[argc]); - return (-1); + "%ls: Invalid command `%ls'.\n", + argv[0], argv[argc]); + return -1; } if (key) - term_set_arrow(el, in, key_map_str(el, out), ntype); + terminal_set_arrow(el, in, keymacro_map_cmd(el, cmd), ntype); else { if (in[1]) { - key_add(el, in, key_map_cmd(el, cmd), ntype); + keymacro_add(el, in, keymacro_map_cmd(el, cmd), ntype); map[(unsigned char) *in] = ED_SEQUENCE_LEAD_IN; } else { - key_clear(el, map, in); - map[(unsigned char) *in] = cmd; + keymacro_clear(el, map, in); + map[(unsigned char) *in] = (el_action_t)cmd; } } break; + /* coverity[dead_error_begin] */ default: EL_ABORT((el->el_errfile, "Bad XK_ type %d\n", ntype)); break; } - return (0); + return 0; } /* 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; - int nf = el->el_map.nfunc + 1; + size_t nf = el->el_map.nfunc + 1; if (name == NULL || help == NULL || func == NULL) - return (-1); + return -1; - if ((p = el_realloc(el->el_map.func, nf * sizeof(el_func_t))) == NULL) - return (-1); - el->el_map.func = (el_func_t *) p; - if ((p = el_realloc(el->el_map.help, nf * sizeof(el_bindings_t))) + if ((p = el_realloc(el->el_map.func, nf * + sizeof(*el->el_map.func))) == NULL) + return -1; + el->el_map.func = p; + if ((p = el_realloc(el->el_map.help, nf * sizeof(*el->el_map.help))) == NULL) - return (-1); - el->el_map.help = (el_bindings_t *) p; + return -1; + el->el_map.help = p; - nf = el->el_map.nfunc; + nf = (size_t)el->el_map.nfunc; el->el_map.func[nf] = func; el->el_map.help[nf].name = name; - el->el_map.help[nf].func = nf; + el->el_map.help[nf].func = (int)nf; el->el_map.help[nf].description = help; el->el_map.nfunc++; - return (0); + return 0; } diff --git a/clt/falcon/editline/src/map.h b/clt/falcon/editline/src/map.h index 3b08f48be..b4e4e2899 100644 --- a/clt/falcon/editline/src/map.h +++ b/clt/falcon/editline/src/map.h @@ -1,4 +1,4 @@ -/* $NetBSD: map.h,v 1.8 2003/08/07 16:44:32 agc Exp $ */ +/* $NetBSD: map.h,v 1.13 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,13 +40,14 @@ #ifndef _h_el_map #define _h_el_map +typedef el_action_t (*el_func_t)(EditLine *, wint_t); + typedef struct el_bindings_t { /* for the "bind" shell command */ - const char *name; /* function name for bind command */ + const wchar_t *name; /* function name for bind command */ int func; /* function numeric value */ - const char *description; /* description of function */ + const wchar_t *description; /* description of function */ } el_bindings_t; - typedef struct el_map_t { el_action_t *alt; /* The current alternate key map */ el_action_t *key; /* The current normal key map */ @@ -57,19 +58,22 @@ typedef struct el_map_t { int type; /* Emacs or vi */ el_bindings_t *help; /* The help for the editor functions */ el_func_t *func; /* List of available functions */ - int nfunc; /* The number of functions/help items */ + size_t nfunc; /* The number of functions/help items */ } el_map_t; #define MAP_EMACS 0 #define MAP_VI 1 -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); +#define N_KEYS 256 + +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 */ diff --git a/clt/falcon/editline/src/parse.c b/clt/falcon/editline/src/parse.c index 5552308ba..2620f41eb 100644 --- a/clt/falcon/editline/src/parse.c +++ b/clt/falcon/editline/src/parse.c @@ -1,4 +1,4 @@ -/* $NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $ */ +/* $NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $"); +__RCSID("$NetBSD: parse.c,v 1.42 2019/07/23 10:18:52 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -54,97 +54,100 @@ __RCSID("$NetBSD: parse.c,v 1.22 2005/05/29 04:58:15 lukem Exp $"); * settc * setty */ -#include "el.h" #include +#include + +#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[] = { - { "bind", map_bind }, - { "echotc", term_echotc }, - { "edit", el_editmode }, - { "history", hist_command }, - { "telltc", term_telltc }, - { "settc", term_settc }, - { "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; - Tokenizer *tok; + TokenizerW *tok; - tok = tok_init(NULL); - tok_str(tok, line, &argc, &argv); - argc = el_parse(el, argc, argv); - tok_end(tok); - return (argc); + tok = tok_winit(NULL); + tok_wstr(tok, line, &argc, &argv); + argc = el_wparse(el, argc, argv); + tok_wend(tok); + return argc; } /* el_parse(): * Command dispatcher */ -public int -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], ':'); + return -1; + ptr = wcschr(argv[0], L':'); if (ptr != NULL) { - char *tprog; + wchar_t *tprog; size_t l; if (ptr == argv[0]) - return (0); - l = ptr - argv[0] - 1; - tprog = (char *) el_malloc(l + 1); + return 0; + l = (size_t)(ptr - argv[0]); + tprog = el_calloc(l + 1, sizeof(*tprog)); if (tprog == NULL) - return (0); - (void) strncpy(tprog, argv[0], l); + return 0; + (void) wcsncpy(tprog, argv[0], l); tprog[l] = '\0'; ptr++; - l = el_match(el->el_prog, tprog); + l = (size_t)el_match(el->el_prog, tprog); el_free(tprog); if (!l) - return (0); + return 0; } else 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); + return -i; } - return (-1); + return -1; } /* parse__escape(): - * Parse a string of the form ^ \ \ and return + * Parse a string of the form ^ \ \ \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; - int c; + const wchar_t *p; + wint_t c; p = *ptr; if (p[1] == 0) - return (-1); + return -1; if (*p == '\\') { p++; @@ -173,6 +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 wchar_t hex[] = L"0123456789ABCDEF"; + const wchar_t *h; + ++p; + if (*p++ != '+') + return -1; + c = 0; + 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': @@ -192,8 +217,8 @@ parse__escape(const char **ptr) } c = (c << 3) | (ch - '0'); } - if ((c & 0xffffff00) != 0) - return (-1); + if ((c & (wint_t)0xffffff00) != (wint_t)0) + return -1; --p; break; } @@ -207,29 +232,29 @@ parse__escape(const char **ptr) } else c = *p; *ptr = ++p; - return (c); + return c; } /* 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 (;;) switch (*in) { case '\0': *out = '\0'; - return (rv); + return rv; case '\\': case '^': if ((n = parse__escape(&in)) == -1) - return (NULL); - *out++ = n; + return NULL; + *out++ = (wchar_t)n; break; case 'M': @@ -251,13 +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_bindings_t *b = el->el_map.help; + size_t i; - for (b = el->el_map.help; b->name != NULL; b++) - if (strcmp(b->name, cmd) == 0) - return (b->func); - return (-1); + for (i = 0; i < el->el_map.nfunc; i++) + if (wcscmp(b[i].name, cmd) == 0) + return b[i].func; + return -1; } diff --git a/clt/falcon/editline/src/parse.h b/clt/falcon/editline/src/parse.h index 58dced1ae..fe8eb4733 100644 --- a/clt/falcon/editline/src/parse.h +++ b/clt/falcon/editline/src/parse.h @@ -1,4 +1,4 @@ -/* $NetBSD: parse.h,v 1.6 2005/05/29 04:58:15 lukem Exp $ */ +/* $NetBSD: parse.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,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 */ diff --git a/clt/falcon/editline/src/prompt.c b/clt/falcon/editline/src/prompt.c index fe027a37d..026a746af 100644 --- a/clt/falcon/editline/src/prompt.c +++ b/clt/falcon/editline/src/prompt.c @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.c,v 1.16 2009/07/17 12:26:26 christos Exp $ */ +/* $NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)prompt.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: prompt.c,v 1.16 2009/07/17 12:26:26 christos Exp $"); +__RCSID("$NetBSD: prompt.c,v 1.27 2017/06/27 23:25:13 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -47,62 +47,68 @@ __RCSID("$NetBSD: prompt.c,v 1.16 2009/07/17 12:26:26 christos Exp $"); #include #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); + return a; } /* 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); + return a; } /* prompt_print(): * Print the prompt and update the prompt position. - * We use an array of integers in case we want to pass - * literal escape sequences in the prompt and we want a - * bit to flag them */ -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; else elp = &el->el_rprompt; - for (p = (*elp->p_func)(el); *p; p++) { + if (elp->p_wide) + p = (*elp->p_func)(el); + else + p = ct_decode_string((char *)(void *)(*elp->p_func)(el), + &el->el_scratch); + + 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) - term__putc(el, *p); - else - re_putc(el, *p, 1); + re_putc(el, *p, 1); } elp->p_pos.v = el->el_refresh.r_cursor.v; @@ -113,7 +119,7 @@ prompt_print(EditLine *el, int op) /* prompt_init(): * Initialize the prompt stuff */ -protected int +libedit_private int prompt_init(EditLine *el) { @@ -132,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__))) { @@ -142,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) +libedit_private int +prompt_set(EditLine *el, el_pfunc_t prf, wchar_t c, int op, int wide) { el_prompt_t *p; @@ -157,13 +163,15 @@ prompt_set(EditLine *el, el_pfunc_t prf, char c, int op) p->p_func = prompt_default; else p->p_func = prompt_default_r; - } else + } else { p->p_func = prf; + } p->p_ignore = c; p->p_pos.v = 0; p->p_pos.h = 0; + p->p_wide = wide; return 0; } @@ -172,8 +180,8 @@ prompt_set(EditLine *el, el_pfunc_t prf, char c, int op) /* 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; @@ -185,8 +193,8 @@ prompt_get(EditLine *el, el_pfunc_t *prf, char *c, int op) else p = &el->el_rprompt; - *prf = el->el_rprompt.p_func; - + if (prf) + *prf = p->p_func; if (c) *c = p->p_ignore; diff --git a/clt/falcon/editline/src/prompt.h b/clt/falcon/editline/src/prompt.h index a70401c29..2931428db 100644 --- a/clt/falcon/editline/src/prompt.h +++ b/clt/falcon/editline/src/prompt.h @@ -1,4 +1,4 @@ -/* $NetBSD: prompt.h,v 1.9 2009/03/31 17:38:27 christos Exp $ */ +/* $NetBSD: prompt.h,v 1.15 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,20 +40,19 @@ #ifndef _h_el_prompt #define _h_el_prompt -#include "histedit.h" - -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); -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 */ diff --git a/clt/falcon/editline/src/read.c b/clt/falcon/editline/src/read.c index 9de03f3a4..a49a304de 100644 --- a/clt/falcon/editline/src/read.c +++ b/clt/falcon/editline/src/read.c @@ -1,4 +1,4 @@ -/* $NetBSD: read.c,v 1.52 2009/07/22 15:57:00 christos Exp $ */ +/* $NetBSD: read.c,v 1.107 2021/08/15 10:08:41 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,48 +37,90 @@ #if 0 static char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: read.c,v 1.52 2009/07/22 15:57:00 christos Exp $"); +__RCSID("$NetBSD: read.c,v 1.107 2021/08/15 10:08:41 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* - * read.c: Clean this junk up! This is horrible code. - * Terminal read functions + * read.c: Terminal read functions */ +#include #include #include -#include +#include #include -#include "el.h" - -#define OKCMD -1 /* must be -1! */ +#include +#include -private int read__fixio(int, int); -private int read_preread(EditLine *); -private int read_char(EditLine *, char *); -private int read_getcmd(EditLine *, el_action_t *, char *); -private void read_pop(c_macro_t *); +#include "el.h" +#include "fcns.h" +#include "read.h" + +#define EL_MAXMACRO 10 + +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; } @@ -87,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) { @@ -132,7 +151,7 @@ read__fixio(int fd __attribute__((__unused__)), int e) #ifdef EWOULDBLOCK case EWOULDBLOCK: #ifndef TRY_AGAIN -#define TRY_AGAIN +#define TRY_AGAIN #endif #endif /* EWOULDBLOCK */ @@ -140,7 +159,7 @@ read__fixio(int fd __attribute__((__unused__)), int e) #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EAGAIN: #ifndef TRY_AGAIN -#define TRY_AGAIN +#define TRY_AGAIN #endif #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */ #endif /* POSIX && EAGAIN */ @@ -149,10 +168,10 @@ read__fixio(int fd __attribute__((__unused__)), int e) #ifdef TRY_AGAIN #if defined(F_SETFL) && defined(O_NDELAY) if ((e = fcntl(fd, F_GETFL, 0)) == -1) - return (-1); + return -1; if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1) - return (-1); + return -1; else e = 1; #endif /* F_SETFL && O_NDELAY */ @@ -161,91 +180,61 @@ read__fixio(int fd __attribute__((__unused__)), int e) { int zero = 0; - if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1) - return (-1); + if (ioctl(fd, FIONBIO, &zero) == -1) + return -1; else e = 1; } #endif /* FIONBIO */ #endif /* TRY_AGAIN */ - return (e ? 0 : -1); + return e ? 0 : -1; case EINTR: - return (-1); + return 0; default: - return (-1); + return -1; } } -/* 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); - -#ifdef FIONREAD - (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & 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 */ - - return (chrs > 0); -} - - /* el_push(): * Push a macro */ -public void -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] = el_strdup(str)) != NULL) + if ((ma->macro[ma->level] = wcsdup(str)) != NULL) return; ma->level--; } - term_beep(el); - term__flush(el); + terminal_beep(el); + terminal__flush(el); } /* read_getcmd(): - * Return next command from the input stream. + * 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 wchar_t meta = (wchar_t)0x80; el_action_t cmd; - int num; - el->el_errno = 0; do { - if ((num = el_getc(el, ch)) != 1) { /* if EOF or error */ - el->el_errno = num == 0 ? 0 : errno; - return (num); - } + if (el_wgetc(el, ch) != 1) + return -1; #ifdef KANJI - if ((*ch & 0200)) { + if ((*ch & meta)) { el->el_state.metanext = 0; cmd = CcViMap[' ']; break; @@ -254,69 +243,116 @@ read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch) if (el->el_state.metanext) { el->el_state.metanext = 0; - *ch |= 0200; + *ch |= meta; } - cmd = el->el_map.current[(unsigned char) *ch]; + if (*ch >= N_KEYS) + cmd = ED_INSERT; + else + cmd = el->el_map.current[(unsigned char) *ch]; if (cmd == ED_SEQUENCE_LEAD_IN) { - key_value_t val; - switch (key_get(el, ch, &val)) { + keymacro_value_t val; + switch (keymacro_get(el, ch, &val)) { case XK_CMD: cmd = val.cmd; break; case XK_STR: - 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 -read_char(EditLine *el, char *cp) +static int +read_char(EditLine *el, wchar_t *cp) { ssize_t num_read; - int tried = 0; + int tried = (el->el_flags & FIXIO) == 0; + char cbuf[MB_LEN_MAX]; + size_t cbp = 0; + int save_errno = errno; again: el->el_signal->sig_no = 0; - while ((num_read = read(el->el_infd, cp, 1)) == -1) { - if (el->el_signal->sig_no == SIGCONT) { + while ((num_read = read(el->el_infd, cbuf + cbp, (size_t)1)) == -1) { + int e = errno; + switch (el->el_signal->sig_no) { + case SIGCONT: + el_wset(el, EL_REFRESH); + /*FALLTHROUGH*/ + case SIGWINCH: sig_set(el); - el_set(el, EL_REFRESH); goto again; + default: + break; } - if (!tried && read__fixio(el->el_infd, errno) == 0) + if (!tried && read__fixio(el->el_infd, e) == 0) { + errno = save_errno; tried = 1; - else { - *cp = '\0'; - return (-1); + } else { + errno = e; + *cp = L'\0'; + return -1; + } + } + + /* Test for EOF */ + if (num_read == 0) { + *cp = L'\0'; + return 0; + } + + for (;;) { + mbstate_t mbs; + + ++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) { + /* + * Invalid sequence, discard all bytes + * except the last one. + */ + cbuf[0] = cbuf[cbp - 1]; + cbp = 0; + break; + } else { + /* Invalid byte, discard it. */ + cbp = 0; + goto again; + } + case (size_t)-2: + if (cbp >= MB_LEN_MAX) { + errno = EILSEQ; + *cp = L'\0'; + return -1; + } + /* Incomplete sequence, read another byte. */ + goto again; + default: + /* Valid character, process it. */ + return 1; } } - return (int)num_read; } /* 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; @@ -327,22 +363,25 @@ read_pop(c_macro_t *ma) ma->offset = 0; } -/* el_getc(): - * Read a character +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 -el_getc(EditLine *el, char *cp) +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; - term__flush(el); + terminal__flush(el); for (;;) { - if (ma->level < 0) { - if (!read_preread(el)) - break; - } - if (ma->level < 0) break; @@ -351,33 +390,33 @@ el_getc(EditLine *el, char *cp) continue; } - *cp = ma->macro[0][ma->offset++] & 0377; + *cp = ma->macro[0][ma->offset++]; if (ma->macro[0][ma->offset] == '\0') { /* Needed for QuoteMode On */ read_pop(ma); } - return (1); + 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); -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, "Got it %c\n", *cp); -#endif /* DEBUG_READ */ - return (num_read); + return 0; + + 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_read->read_errno = errno; + + return num_read; } -protected void +libedit_private void read_prepare(EditLine *el) { if (el->el_flags & HANDLE_SIGNALS) @@ -391,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) - term__flush(el); + terminal__flush(el); } -protected void +libedit_private void read_finish(EditLine *el) { if ((el->el_flags & UNBUFFERED) == 0) @@ -407,64 +446,59 @@ read_finish(EditLine *el) sig_clr(el); } -public const char * -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 */ - char ch; - 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) { - char *cp = el->el_line.buffer; - size_t idx; - - while ((num = (*el->el_read.read_char)(el, cp)) == 1) { - /* make sure there is space for next character */ - if (cp + 1 >= el->el_line.limit) { - idx = (cp - el->el_line.buffer); - if (!ch_enlargebufs(el, 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; - } - - el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; - *nread = (int)(el->el_line.cursor - el->el_line.buffer); - goto done; + 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, (ioctl_t) & chrs); + (void) ioctl(el->el_infd, FIONREAD, &chrs); if (chrs == 0) { if (tty_rawmode(el) < 0) { errno = 0; *nread = 0; - return (NULL); + return NULL; } } } @@ -474,84 +508,19 @@ el_gets(EditLine *el, int *nread) read_prepare(el); if (el->el_flags & EDIT_DISABLED) { - char *cp; - size_t idx; - if ((el->el_flags & UNBUFFERED) == 0) - cp = el->el_line.buffer; - else - cp = el->el_line.lastchar; - - term__flush(el); - - while ((num = (*el->el_read.read_char)(el, cp)) == 1) { - /* make sure there is space next character */ - if (cp + 1 >= el->el_line.limit) { - idx = (cp - el->el_line.buffer); - if (!ch_enlargebufs(el, 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; - } - - el->el_line.cursor = el->el_line.lastchar = cp; - *cp = '\0'; - goto done; + el->el_line.lastchar = el->el_line.buffer; + terminal__flush(el); + 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) { -#ifdef DEBUG_READ - (void) fprintf(el->el_errfile, - "Returning from el_gets %d\n", num); -#endif /* DEBUG_READ */ - break; - } - if (el->el_errno == EINTR) { - el->el_line.buffer[0] = '\0'; - el->el_line.lastchar = - el->el_line.cursor = el->el_line.buffer; + if (read_getcmd(el, &cmdnum, &ch) == -1) break; - } - if ((unsigned int)cmdnum >= (unsigned int)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 %s\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; @@ -560,16 +529,12 @@ 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((unsigned char)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; @@ -591,7 +556,7 @@ el_gets(EditLine *el, int *nread) case CC_REFRESH_BEEP: re_refresh(el); - term_beep(el); + terminal_beep(el); break; case CC_NORM: /* normal char */ @@ -616,24 +581,17 @@ 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 */ - re_refresh(el); /* print the prompt again */ + 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 */ - term_beep(el); - term__flush(el); + terminal_beep(el); + terminal__flush(el); break; } el->el_state.argument = 1; @@ -643,19 +601,19 @@ el_gets(EditLine *el, int *nread) break; } - term__flush(el); /* flush any buffered output */ + terminal__flush(el); /* flush any buffered output */ /* make sure the tty is set up correctly */ 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); - } -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 diff --git a/clt/falcon/editline/src/read.h b/clt/falcon/editline/src/read.h index bd8d4c1f5..1acf5d676 100644 --- a/clt/falcon/editline/src/read.h +++ b/clt/falcon/editline/src/read.h @@ -1,4 +1,4 @@ -/* $NetBSD: read.h,v 1.6 2008/04/29 06:53:01 martin Exp $ */ +/* $NetBSD: read.h,v 1.12 2016/05/22 19:44:26 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -35,16 +35,11 @@ #ifndef _h_el_read #define _h_el_read -typedef int (*el_rfunc_t)(EditLine *, char *); - -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 */ diff --git a/clt/falcon/editline/src/readline.c b/clt/falcon/editline/src/readline.c index 842ab44ce..8fdd13c5f 100644 --- a/clt/falcon/editline/src/readline.c +++ b/clt/falcon/editline/src/readline.c @@ -1,4 +1,4 @@ -/* $NetBSD: readline.c,v 1.85 2009/09/07 21:24:33 christos Exp $ */ +/* $NetBSD: readline.c,v 1.176 2022/09/21 01:33:53 christos Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -29,34 +29,35 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include - +#include "config.h" #if !defined(lint) && !defined(SCCSID) -__RCSID("$NetBSD: readline.c,v 1.85 2009/09/07 21:24:33 christos Exp $"); +__RCSID("$NetBSD: readline.c,v 1.176 2022/09/21 01:33:53 christos Exp $"); #endif /* not lint && not SCCSID */ #include #include -#include -#include -#include -#include #include -#include -#include -#include +#include #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include #include + #include "editline/readline.h" #include "el.h" -#include "fcns.h" /* for EL_NUM_FCNS */ -#include "histedit.h" +#include "fcns.h" #include "filecomplete.h" #if !defined(SIZE_T_MAX) -# define SIZE_T_MAX (size_t)(-1) +# define SIZE_T_MAX (size_t)(-1) #endif void rl_prep_terminal(int); @@ -76,21 +77,30 @@ 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; int rl_end = 0; char *rl_line_buffer = NULL; -VCPFunction *rl_linefunc = 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; +/* + * The following is not implemented; we always catch signals in the + * libedit fashion: set handlers on entry to el_gets() and clear them + * on the way out. This simplistic approach works for most cases; if + * it does not work for your application, please let us know. + */ +int rl_catch_signals = 1; +int rl_catch_sigwinch = 1; int history_base = 1; /* probably never subject to change */ int history_length = 0; +int history_offset = 0; int max_input_history = 0; char history_expansion_char = '!'; char history_subst_char = '^'; @@ -100,32 +110,44 @@ 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; -Function *rl_completion_entry_function = NULL; -CPPFunction *rl_attempted_completion_function = NULL; -Function *rl_pre_input_hook = NULL; -Function *rl_startup1_hook = NULL; +const char *rl_completer_quote_characters = NULL; +const char *rl_basic_quote_characters = "\"'"; +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; +rl_hook_func_t *rl_pre_input_hook = NULL; +rl_hook_func_t *rl_startup1_hook = NULL; int (*rl_getc_function)(FILE *) = NULL; char *rl_terminal_name = NULL; int rl_already_prompted = 0; int rl_filename_completion_desired = 0; int rl_ignore_completion_duplicates = 0; -int rl_catch_signals = 1; int readline_echoing_p = 1; int _rl_print_completions_horizontally = 0; VFunction *rl_redisplay_function = NULL; -Function *rl_startup_hook = NULL; +rl_hook_func_t *rl_startup_hook = NULL; 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; KEYMAP_ENTRY_ARRAY emacs_meta_keymap; +unsigned long rl_readline_state = RL_STATE_NONE; +int _rl_complete_mark_directories; +rl_icppfunc_t *rl_directory_completion_hook; +int rl_completion_suppress_append; +int rl_sort_completion_matches; +int _rl_completion_prefix_display_length; +int _rl_echoing_p; +int history_max_entries; +char *rl_display_prompt; +int rl_erase_empty_line; /* * The current prompt string. */ char *rl_prompt = NULL; +char *rl_prompt_saved = NULL; /* * This is set to character indicating type of completion being done by * rl_complete_internal(); this is available for application completion @@ -144,7 +166,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 @@ -156,48 +178,29 @@ int rl_completion_append_character = ' '; static History *h = NULL; static EditLine *e = NULL; -static Function *map[256]; +static rl_command_func_t *map[256]; static jmp_buf topbuf; /* internal functions */ 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 *, char *); -static HIST_ENTRY *_move_history(int); +static int _getc_function(EditLine *, wchar_t *); static int _history_expand_command(const char *, size_t, size_t, char **); static char *_rl_compat_sub(const char *, const char *, const char *, int); -static int _rl_event_read_char(EditLine *, char *); +static int _rl_event_read_char(EditLine *, wchar_t *); static void _rl_update_pos(void); +static HIST_ENTRY rl_he; /* ARGSUSED */ static char * _get_prompt(EditLine *el __attribute__((__unused__))) { rl_already_prompted = 1; - return (rl_prompt); -} - - -/* - * 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 (HIST_ENTRY *) NULL; - - rl_he.line = ev.str; - rl_he.data = (histdata_t) &(ev.num); - - return (&rl_he); + return rl_prompt; } @@ -206,31 +209,45 @@ _move_history(int op) */ static int /*ARGSUSED*/ -_getc_function(EditLine *el, char *c) +_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 = i; + *c = (wchar_t)i; return 1; } -static const char _dothistory[] = "/.history"; +static void +_resize_fun(EditLine *el, void *a) +{ + const LineInfo *li; + const char **ap = a; + + li = el_line(el); + *ap = li->buffer; +} static const char * _default_history_file(void) { struct passwd *p; - static char path[PATH_MAX]; + static char *path; + size_t len; - if (*path) + if (path) return path; + if ((p = getpwuid(getuid())) == NULL) return NULL; - strlcpy(path, p->pw_dir, PATH_MAX); - strlcat(path, _dothistory, PATH_MAX); + + len = strlen(p->pw_dir) + sizeof("/.history"); + if ((path = malloc(len)) == NULL) + return NULL; + + (void)snprintf(path, len, "%s/.history", p->pw_dir); return path; } @@ -248,20 +265,41 @@ rl_set_prompt(const char *prompt) if (!prompt) prompt = ""; - if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) + if (rl_prompt != NULL && strcmp(rl_prompt, prompt) == 0) return 0; if (rl_prompt) - free(rl_prompt); + el_free(rl_prompt); rl_prompt = strdup(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; } +void +rl_save_prompt(void) +{ + rl_prompt_saved = strdup(rl_prompt); +} + +void +rl_restore_prompt(void) +{ + if (!rl_prompt_saved) + return; + rl_prompt = rl_prompt_saved; + rl_prompt_saved = NULL; +} + /* * initialize rl compat stuff */ @@ -269,7 +307,6 @@ int rl_initialize(void) { HistEvent ev; - const LineInfo *li; int editmode = 1; struct termios t; @@ -278,6 +315,8 @@ rl_initialize(void) if (h != NULL) history_end(h); + RL_UNSETSTATE(RL_STATE_DONE); + if (!rl_instream) rl_instream = stdin; if (!rl_outstream) @@ -289,20 +328,25 @@ 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); h = history_init(); if (!e || !h) - return (-1); + return -1; history(h, &ev, H_SETSIZE, INT_MAX); /* unlimited */ history_length = 0; max_input_history = INT_MAX; el_set(e, EL_HIST, history, h); + /* Setup resize function */ + el_set(e, EL_RESIZE, _resize_fun, &rl_line_buffer); + /* setup getc function if valid */ if (rl_getc_function) el_set(e, EL_GETCFN, _getc_function); @@ -313,11 +357,11 @@ 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 */ - /* so this can be overriden */ + /* so this can be overridden */ el_set(e, EL_EDITOR, "emacs"); if (rl_terminal_name != NULL) el_set(e, EL_TERMINAL, rl_terminal_name); @@ -340,7 +384,38 @@ rl_initialize(void) "ReadLine compatible suspend function", _el_rl_tstp); el_set(e, EL_BIND, "^Z", "rl_tstp", NULL); - + + /* + * Set some readline compatible key-bindings. + */ + el_set(e, EL_BIND, "^R", "em-inc-search-prev", NULL); + + /* + * Allow the use of Home/End keys. + */ + el_set(e, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL); + el_set(e, EL_BIND, "\\e[4~", "ed-move-to-end", NULL); + el_set(e, EL_BIND, "\\e[7~", "ed-move-to-beg", NULL); + el_set(e, EL_BIND, "\\e[8~", "ed-move-to-end", NULL); + el_set(e, EL_BIND, "\\e[H", "ed-move-to-beg", NULL); + el_set(e, EL_BIND, "\\e[F", "ed-move-to-end", NULL); + + /* + * Allow the use of the Delete/Insert keys. + */ + el_set(e, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL); + el_set(e, EL_BIND, "\\e[2~", "ed-quoted-insert", NULL); + + /* + * Ctrl-left-arrow and Ctrl-right-arrow for word moving. + */ + el_set(e, EL_BIND, "\\e[1;5C", "em-next-word", NULL); + el_set(e, EL_BIND, "\\e[1;5D", "ed-prev-word", NULL); + el_set(e, EL_BIND, "\\e[5C", "em-next-word", NULL); + el_set(e, EL_BIND, "\\e[5D", "ed-prev-word", NULL); + el_set(e, EL_BIND, "\\e\\e[C", "em-next-word", NULL); + el_set(e, EL_BIND, "\\e\\e[D", "ed-prev-word", NULL); + /* read settings from configuration file */ el_source(e, NULL); @@ -348,15 +423,12 @@ rl_initialize(void) * Unfortunately, some applications really do use rl_point * and rl_line_buffer directly. */ - li = el_line(e); - /* a cheesy way to get rid of const cast. */ - rl_line_buffer = memchr(li->buffer, *li->buffer, 1); + _resize_fun(e, &rl_line_buffer); _rl_update_pos(); - if (rl_startup_hook) - (*rl_startup_hook)(NULL, 0); + tty_end(e, TCSADRAIN); - return (0); + return 0; } @@ -376,19 +448,25 @@ readline(const char *p) if (e == NULL || h == NULL) rl_initialize(); + if (rl_startup_hook) { + (*rl_startup_hook)(); + } + 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); + (*rl_pre_input_hook)(); - 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; } @@ -408,7 +486,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'; @@ -418,6 +496,8 @@ readline(const char *p) history(h, &ev, H_GETSIZE); history_length = ev.num; +out: + tty_end(e, TCSADRAIN); return buf; } @@ -434,6 +514,7 @@ using_history(void) { if (h == NULL || e == NULL) rl_initialize(); + history_offset = history_length; } @@ -465,24 +546,24 @@ _rl_compat_sub(const char *str, const char *what, const char *with, } else s++; } - r = result = malloc(len + 1); + r = result = el_calloc(len + 1, sizeof(*r)); if (result == NULL) return NULL; s = str; while (*s) { if (*s == *what && !strncmp(s, what, what_len)) { - (void)strncpy(r, with, with_len); + memcpy(r, with, with_len); r += with_len; s += what_len; if (!globally) { (void)strcpy(r, s); - return(result); + return result; } } else *r++ = *s++; } *r = '\0'; - return(result); + return result; } static char *last_search_pat; /* last !?pat[?] search pattern */ @@ -499,14 +580,14 @@ get_history_event(const char *cmd, int *cindex, int qchar) idx = *cindex; if (cmd[idx++] != history_expansion_char) - return(NULL); + return NULL; /* find out which event to take */ if (cmd[idx] == history_expansion_char || cmd[idx] == '\0') { if (history(h, &ev, H_FIRST) != 0) - return(NULL); + return NULL; *cindex = cmd[idx]? (idx + 1):idx; - return(ev.str); + return ev.str; } sign = 0; if (cmd[idx] == '-') { @@ -515,7 +596,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') { @@ -523,13 +604,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))) - return(NULL); + if (!(he = history_get(num))) + return NULL; *cindex = idx; - return(rl_he->line); + return he->line; } sub = 0; if (cmd[idx] == '?') { @@ -543,35 +624,33 @@ get_history_event(const char *cmd, int *cindex, int qchar) if (sub && cmd[idx] == '?') break; if (!sub && (cmd[idx] == ':' || cmd[idx] == ' ' - || cmd[idx] == '\t' || cmd[idx] == qchar)) + || cmd[idx] == '\t' || cmd[idx] == qchar)) break; idx++; } - len = idx - begin; + len = (size_t)idx - (size_t)begin; if (sub && cmd[idx] == '?') idx++; if (sub && len == 0 && last_search_pat && *last_search_pat) pat = last_search_pat; else if (len == 0) - return(NULL); + return NULL; else { - if ((pat = malloc(len + 1)) == NULL) + if ((pat = el_calloc(len + 1, sizeof(*pat))) == NULL) return NULL; - (void)strncpy(pat, cmd + begin, len); - pat[len] = '\0'; + (void)strlcpy(pat, cmd + begin, len + 1); } if (history(h, &ev, H_CURR) != 0) { if (pat != last_search_pat) - free(pat); - return (NULL); + el_free(pat); + return NULL; } num = ev.num; if (sub) { if (pat != last_search_pat) { - if (last_search_pat) - free(last_search_pat); + el_free(last_search_pat); last_search_pat = pat; } ret = history_search(pat, -1); @@ -583,21 +662,20 @@ get_history_event(const char *cmd, int *cindex, int qchar) history(h, &ev, H_FIRST); (void)fprintf(rl_outstream, "%s: Event not found\n", pat); if (pat != last_search_pat) - free(pat); - return(NULL); + el_free(pat); + return NULL; } if (sub && len) { - if (last_search_match && last_search_match != pat) - free(last_search_match); - last_search_match = pat; + el_free(last_search_match); + last_search_match = strdup(pat); } if (pat != last_search_pat) - free(pat); + el_free(pat); if (history(h, &ev, H_CURR) != 0) - return(NULL); + return NULL; *cindex = idx; rptr = ev.str; @@ -607,6 +685,123 @@ get_history_event(const char *cmd, int *cindex, int qchar) return rptr; } +static int +getfrom(const char **cmdp, char **fromp, const char *search, int delim) +{ + size_t size = 16; + size_t len = 0; + const char *cmd = *cmdp; + char *what = el_realloc(*fromp, size * sizeof(*what)); + if (what == NULL){ + el_free(*fromp); + *fromp = NULL; + return 0; + } + for (; *cmd && *cmd != delim; cmd++) { + if (*cmd == '\\' && cmd[1] == delim) + cmd++; + if (len - 1 >= size) { + char *nwhat; + nwhat = el_realloc(what, (size <<= 1) * sizeof(*nwhat)); + if (nwhat == NULL) { + el_free(what); + el_free(*fromp); + *cmdp = cmd; + *fromp = NULL; + return 0; + } + what = nwhat; + } + what[len++] = *cmd; + } + what[len] = '\0'; + *fromp = what; + *cmdp = cmd; + if (*what == '\0') { + el_free(what); + if (search) { + *fromp = strdup(search); + if (*fromp == NULL) { + return 0; + } + } else { + *fromp = NULL; + return -1; + } + } + if (!*cmd) { + el_free(what); + *fromp = NULL; + return -1; + } + + cmd++; /* shift after delim */ + *cmdp = cmd; + + if (!*cmd) { + el_free(what); + *fromp = NULL; + return -1; + } + return 1; +} + +static int +getto(const char **cmdp, char **top, const char *from, int delim) +{ + size_t size = 16; + size_t len = 0; + size_t from_len = strlen(from); + const char *cmd = *cmdp; + char *with = el_realloc(*top, size * sizeof(*with)); + *top = NULL; + if (with == NULL) + goto out; + + for (; *cmd && *cmd != delim; cmd++) { + if (len + from_len + 1 >= size) { + char *nwith; + size += from_len + 1; + nwith = el_realloc(with, size * sizeof(*nwith)); + if (nwith == NULL) + goto out; + with = nwith; + } + if (*cmd == '&') { + /* safe */ + strcpy(&with[len], from); + len += from_len; + continue; + } + if (*cmd == '\\' && (*(cmd + 1) == delim || *(cmd + 1) == '&')) + cmd++; + with[len++] = *cmd; + } + if (!*cmd) + goto out; + with[len] = '\0'; + *top = with; + *cmdp = cmd; + return 1; +out: + el_free(with); + el_free(*top); + *top = NULL; + *cmdp = cmd; + return -1; +} + +static void +replace(char **tmp, int c) +{ + char *aptr; + if ((aptr = strrchr(*tmp, c)) == NULL) + return; + aptr = strdup(aptr + 1); // XXX: check + el_free(*tmp); + *tmp = aptr; +} + /* * the real function doing history expansion - takes as argument command * to do and data upon which the command should be executed @@ -615,17 +810,17 @@ get_history_event(const char *cmd, int *cindex, int qchar) * returns 0 if data was not modified, 1 if it was and 2 if the string * should be only printed and not executed; in case of error, * returns -1 and *result points to NULL - * it's callers responsibility to free() string returned in *result + * it's the caller's responsibility to free() the string returned in *result */ static int _history_expand_command(const char *command, size_t offs, size_t cmdlen, char **result) { - char *tmp, *search = NULL, *aptr; + char *tmp, *search = NULL, *aptr, delim; const char *ptr, *cmd; static char *from = NULL, *to = NULL; int start, end, idx, has_mods = 0; - int p_on = 0, g_on = 0; + int p_on = 0, g_on = 0, ev; *result = NULL; aptr = NULL; @@ -649,30 +844,31 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, } else { if (command[offs + 1] == '#') { /* use command so far */ - if ((aptr = malloc(offs + 1)) == NULL) + if ((aptr = el_calloc(offs + 1, sizeof(*aptr))) + == NULL) return -1; - (void)strncpy(aptr, command, offs); - aptr[offs] = '\0'; + (void)strlcpy(aptr, command, offs + 1); idx = 1; } else { int qchar; - qchar = (offs > 0 && command[offs - 1] == '"')? '"':0; + qchar = (offs > 0 && command[offs - 1] == '"') + ? '"' : '\0'; ptr = get_history_event(command + offs, &idx, qchar); } - has_mods = command[offs + idx] == ':'; + has_mods = command[offs + (size_t)idx] == ':'; } if (ptr == NULL && aptr == NULL) - return(-1); + return -1; if (!has_mods) { *result = strdup(aptr ? aptr : ptr); if (aptr) - free(aptr); + el_free(aptr); if (*result == NULL) return -1; - return(1); + return 1; } cmd = command + offs + idx + 1; @@ -680,7 +876,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, /* Now parse any word designators */ if (*cmd == '%') /* last word matched by ?pat? */ - tmp = strdup(last_search_match? last_search_match:""); + tmp = strdup(last_search_match ? last_search_match : ""); else if (strchr("^*$-0123456789", *cmd)) { start = end = -1; if (*cmd == '^') @@ -689,7 +885,7 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, start = -1, cmd++; else if (*cmd == '*') start = 1, cmd++; - else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { + else if (*cmd == '-' || isdigit((unsigned char) *cmd)) { start = 0; while (*cmd && '0' <= *cmd && *cmd <= '9') start = start * 10 + *cmd++ - '0'; @@ -717,145 +913,73 @@ _history_expand_command(const char *command, size_t offs, size_t cmdlen, (void)fprintf(rl_outstream, "%s: Bad word specifier", command + offs + idx); if (aptr) - free(aptr); - return(-1); + el_free(aptr); + return -1; } } else tmp = strdup(aptr? aptr:ptr); if (aptr) - free(aptr); + el_free(aptr); if (*cmd == '\0' || ((size_t)(cmd - (command + offs)) >= cmdlen)) { *result = tmp; - return(1); + return 1; } for (; *cmd; cmd++) { - if (*cmd == ':') + switch (*cmd) { + case ':': continue; - else if (*cmd == 'h') { /* remove trailing path */ + case 'h': /* remove trailing path */ if ((aptr = strrchr(tmp, '/')) != NULL) *aptr = '\0'; - } else if (*cmd == 't') { /* remove leading path */ - if ((aptr = strrchr(tmp, '/')) != NULL) { - aptr = strdup(aptr + 1); - free(tmp); - tmp = aptr; - } - } else if (*cmd == 'r') { /* remove trailing suffix */ + continue; + case 't': /* remove leading path */ + replace(&tmp, '/'); + continue; + case 'r': /* remove trailing suffix */ if ((aptr = strrchr(tmp, '.')) != NULL) *aptr = '\0'; - } else if (*cmd == 'e') { /* remove all but suffix */ - if ((aptr = strrchr(tmp, '.')) != NULL) { - aptr = strdup(aptr); - free(tmp); - tmp = aptr; - } - } else if (*cmd == 'p') /* print only */ + continue; + case 'e': /* remove all but suffix */ + replace(&tmp, '.'); + continue; + case 'p': /* print only */ p_on = 1; - else if (*cmd == 'g') + continue; + case 'g': g_on = 2; - else if (*cmd == 's' || *cmd == '&') { - char *what, *with, delim; - size_t len, from_len; - size_t size; - - if (*cmd == '&' && (from == NULL || to == NULL)) + continue; + case '&': + if (from == NULL || to == NULL) continue; - else if (*cmd == 's') { - delim = *(++cmd), cmd++; - size = 16; - what = realloc(from, size); - if (what == NULL) { - free(from); - free(tmp); - return 0; - } - len = 0; - for (; *cmd && *cmd != delim; cmd++) { - if (*cmd == '\\' && cmd[1] == delim) - cmd++; - if (len >= size) { - char *nwhat; - nwhat = realloc(what, - (size <<= 1)); - if (nwhat == NULL) { - free(what); - free(tmp); - return 0; - } - what = nwhat; - } - what[len++] = *cmd; - } - what[len] = '\0'; - from = what; - if (*what == '\0') { - free(what); - if (search) { - from = strdup(search); - if (from == NULL) { - free(tmp); - return 0; - } - } else { - from = NULL; - free(tmp); - return (-1); - } - } - cmd++; /* shift after delim */ - if (!*cmd) - continue; - - size = 16; - with = realloc(to, size); - if (with == NULL) { - free(to); - free(tmp); - return -1; - } - len = 0; - from_len = strlen(from); - for (; *cmd && *cmd != delim; cmd++) { - if (len + from_len + 1 >= size) { - char *nwith; - size += from_len + 1; - nwith = realloc(with, size); - if (nwith == NULL) { - free(with); - free(tmp); - return -1; - } - with = nwith; - } - if (*cmd == '&') { - /* safe */ - (void)strcpy(&with[len], from); - len += from_len; - continue; - } - if (*cmd == '\\' - && (*(cmd + 1) == delim - || *(cmd + 1) == '&')) - cmd++; - with[len++] = *cmd; - } - with[len] = '\0'; - to = with; - } - + /*FALLTHROUGH*/ + case 's': + ev = -1; + delim = *++cmd; + if (delim == '\0' || *++cmd == '\0') + goto out; + if ((ev = getfrom(&cmd, &from, search, delim)) != 1) + goto out; + if ((ev = getto(&cmd, &to, from, delim)) != 1) + goto out; aptr = _rl_compat_sub(tmp, from, to, g_on); if (aptr) { - free(tmp); + el_free(tmp); tmp = aptr; } g_on = 0; + cmd--; + continue; } } *result = tmp; - return (p_on? 2:1); + return p_on ? 2 : 1; +out: + el_free(tmp); + return ev; + } @@ -874,13 +998,13 @@ history_expand(char *str, char **output) if (history_expansion_char == 0) { *output = strdup(str); - return(0); + return 0; } *output = NULL; if (str[0] == history_subst_char) { /* ^foo^foo2^ is equivalent to !!:s^foo^foo2^ */ - *output = malloc(strlen(str) + 4 + 1); + *output = el_calloc(strlen(str) + 4 + 1, sizeof(**output)); if (*output == NULL) return 0; (*output)[0] = (*output)[1] = history_expansion_char; @@ -897,18 +1021,17 @@ history_expand(char *str, char **output) #define ADD_STRING(what, len, fr) \ { \ if (idx + len + 1 > size) { \ - char *nresult = realloc(result, (size += len + 1));\ + char *nresult = el_realloc(result, \ + (size += len + 1) * sizeof(*nresult)); \ if (nresult == NULL) { \ - free(*output); \ - if (/*CONSTCOND*/fr) \ - free(tmp); \ + el_free(*output); \ + el_free(fr); \ return 0; \ } \ result = nresult; \ } \ - (void)strncpy(&result[idx], what, len); \ + (void)strlcpy(&result[idx], what, len + 1); \ idx += len; \ - result[idx] = '\0'; \ } result = NULL; @@ -925,7 +1048,8 @@ history_expand(char *str, char **output) for (; str[j]; j++) { if (str[j] == '\\' && str[j + 1] == history_expansion_char) { - (void)strcpy(&str[j], &str[j + 1]); + len = strlen(&str[j + 1]) + 1; + memmove(&str[j], &str[j + 1], len); continue; } if (!loop_again) { @@ -951,11 +1075,11 @@ history_expand(char *str, char **output) goto loop; } len = i - start; - ADD_STRING(&str[start], len, 0); + ADD_STRING(&str[start], len, NULL); if (str[i] == '\0' || str[i] != history_expansion_char) { len = j - i; - ADD_STRING(&str[i], len, 0); + ADD_STRING(&str[i], len, NULL); if (start == 0) ret = 0; else @@ -965,10 +1089,10 @@ history_expand(char *str, char **output) ret = _history_expand_command (str, i, (j - i), &tmp); if (ret > 0 && tmp) { len = strlen(tmp); - ADD_STRING(tmp, len, 1); + ADD_STRING(tmp, len, tmp); } if (tmp) { - free(tmp); + el_free(tmp); tmp = NULL; } i = j; @@ -985,10 +1109,10 @@ history_expand(char *str, char **output) ret = -1; #endif } - free(*output); + el_free(*output); *output = result; - return (ret); + return ret; } /* @@ -1023,14 +1147,14 @@ history_arg_extract(int start, int end, const char *str) (size_t)end > max || start > end) goto out; - for (i = start, len = 0; i <= (size_t)end; i++) + for (i = (size_t)start, len = 0; i <= (size_t)end; i++) len += strlen(arr[i]) + 1; len++; - result = malloc(len); + result = el_calloc(len, sizeof(*result)); if (result == NULL) goto out; - for (i = start, len = 0; i <= (size_t)end; i++) { + for (i = (size_t)start, len = 0; i <= (size_t)end; i++) { (void)strcpy(result + len, arr[i]); len += strlen(arr[i]); if (i < (size_t)end) @@ -1040,8 +1164,8 @@ history_arg_extract(int start, int end, const char *str) out: for (i = 0; arr[i]; i++) - free(arr[i]); - free(arr); + el_free(arr[i]); + el_free(arr); return result; } @@ -1080,29 +1204,28 @@ history_tokenize(const char *str) if (idx + 2 >= size) { char **nresult; size <<= 1; - nresult = realloc(result, size * sizeof(char *)); + nresult = el_realloc(result, (size_t)size * sizeof(*nresult)); if (nresult == NULL) { - free(result); + el_free(result); return NULL; } result = nresult; } - len = i - start; - temp = malloc(len + 1); + len = (size_t)i - (size_t)start; + temp = el_calloc(len + 1, sizeof(*temp)); if (temp == NULL) { for (i = 0; i < idx; i++) - free(result[i]); - free(result); + el_free(result[i]); + el_free(result); return NULL; } - (void)strncpy(temp, &str[start], len); - temp[len] = '\0'; + (void)strlcpy(temp, &str[start], len + 1); result[idx++] = temp; result[idx] = NULL; if (str[i]) i++; } - return (result); + return result; } @@ -1113,12 +1236,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); + } + } } @@ -1134,7 +1267,7 @@ unstifle_history(void) history(h, &ev, H_SETSIZE, INT_MAX); omax = max_input_history; max_input_history = INT_MAX; - return (omax); /* some value _must_ be returned */ + return omax; /* some value _must_ be returned */ } @@ -1143,7 +1276,7 @@ history_is_stifled(void) { /* cannot return true answer */ - return (max_input_history != INT_MAX); + return max_input_history != INT_MAX; } static const char _history_tmp_template[] = "/tmp/.historyXXXXXX"; @@ -1178,7 +1311,7 @@ history_truncate_file (const char *filename, int nlines) } for(;;) { - if (fread(buf, sizeof(buf), 1, fp) != 1) { + if (fread(buf, sizeof(buf), (size_t)1, fp) != 1) { if (ferror(fp)) { ret = errno; break; @@ -1188,7 +1321,7 @@ history_truncate_file (const char *filename, int nlines) ret = errno; break; } - left = fread(buf, 1, sizeof(buf), fp); + left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), fp); if (ferror(fp)) { ret = errno; break; @@ -1196,14 +1329,15 @@ history_truncate_file (const char *filename, int nlines) if (left == 0) { count--; left = sizeof(buf); - } else if (fwrite(buf, (size_t)left, 1, tp) != 1) { + } else if (fwrite(buf, (size_t)left, (size_t)1, tp) + != 1) { ret = errno; break; } fflush(tp); break; } - if (fwrite(buf, sizeof(buf), 1, tp) != 1) { + if (fwrite(buf, sizeof(buf), (size_t)1, tp) != 1) { ret = errno; break; } @@ -1233,7 +1367,7 @@ history_truncate_file (const char *filename, int nlines) ret = errno; break; } - if (fread(buf, sizeof(buf), 1, tp) != 1) { + if (fread(buf, sizeof(buf), (size_t)1, tp) != 1) { if (ferror(tp)) { ret = errno; break; @@ -1247,7 +1381,7 @@ history_truncate_file (const char *filename, int nlines) if (ret || nlines > 0) goto out3; - if (fseeko(fp, 0, SEEK_SET) == (off_t)-1) { + if (fseeko(fp, (off_t)0, SEEK_SET) == (off_t)-1) { ret = errno; goto out3; } @@ -1259,12 +1393,12 @@ history_truncate_file (const char *filename, int nlines) } for(;;) { - if ((left = fread(buf, 1, sizeof(buf), tp)) == 0) { + if ((left = (ssize_t)fread(buf, (size_t)1, sizeof(buf), tp)) == 0) { if (ferror(fp)) ret = errno; break; } - if (fwrite(buf, (size_t)left, 1, fp) != 1) { + if (fwrite(buf, (size_t)left, (size_t)1, fp) != 1) { ret = errno; break; } @@ -1295,7 +1429,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; } @@ -1311,9 +1452,32 @@ write_history(const char *filename) rl_initialize(); if (filename == NULL && (filename = _default_history_file()) == NULL) return errno; - return (history(h, &ev, H_SAVE, filename) == -1 ? (errno ? errno : EINVAL) : 0); + return history(h, &ev, H_SAVE, filename) == -1 ? + (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 @@ -1330,25 +1494,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); + 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); + return &she; + +out: + /* restore pointer to where it was */ + (void)history(h, &ev, H_SET, curr_num); + return NULL; } @@ -1363,11 +1539,17 @@ add_history(const char *line) 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; } @@ -1383,11 +1565,11 @@ remove_history(int num) if (h == NULL || e == NULL) rl_initialize(); - if ((he = malloc(sizeof(*he))) == NULL) + if ((he = el_malloc(sizeof(*he))) == NULL) return NULL; if (history(h, &ev, H_DELDATA, num, &he->data) != 0) { - free(he); + el_free(he); return NULL; } @@ -1421,7 +1603,7 @@ replace_history_entry(int num, const char *line, histdata_t data) if (history(h, &ev, H_LAST) != 0) return NULL; /* error */ - if ((he = malloc(sizeof(*he))) == NULL) + if ((he = el_malloc(sizeof(*he))) == NULL) return NULL; /* look forwards for event matching specified offset */ @@ -1441,7 +1623,7 @@ replace_history_entry(int num, const char *line, histdata_t data) return he; out: - free(he); + el_free(he); return NULL; } @@ -1453,8 +1635,11 @@ clear_history(void) { HistEvent ev; - history(h, &ev, H_CLEAR); - history_length = 0; + if (h == NULL || e == NULL) + rl_initialize(); + + (void)history(h, &ev, H_CLEAR); + history_offset = history_length = 0; } @@ -1463,22 +1648,44 @@ clear_history(void) */ int where_history(void) +{ + return history_offset; +} + +static HIST_ENTRY **_history_listp; +static HIST_ENTRY *_history_list; + +HIST_ENTRY ** +history_list(void) { HistEvent ev; - int curr_num, off; + HIST_ENTRY **nlp, *nl; + int i; - if (history(h, &ev, H_CURR) != 0) - return (0); - curr_num = ev.num; + if (history(h, &ev, H_LAST) != 0) + return NULL; - history(h, &ev, H_FIRST); - off = 1; - while (ev.num != curr_num && history(h, &ev, H_NEXT) == 0) - off++; + if ((nlp = el_realloc(_history_listp, + ((size_t)history_length + 1) * sizeof(*nlp))) == NULL) + return NULL; + _history_listp = nlp; - return (off); -} + 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 @@ -1486,8 +1693,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; } @@ -1502,19 +1715,19 @@ history_total_bytes(void) size_t size; if (history(h, &ev, H_CURR) != 0) - return (-1); + return -1; curr_num = ev.num; - history(h, &ev, H_FIRST); + (void)history(h, &ev, H_FIRST); size = 0; do - size += strlen(ev.str); + size += strlen(ev.str) * sizeof(*ev.str); while (history(h, &ev, H_NEXT) == 0); /* get to the same position as before */ history(h, &ev, H_PREV_EVENT, curr_num); - return (int)(size); + return (int)size; } @@ -1524,35 +1737,31 @@ history_total_bytes(void) int history_set_pos(int pos) { - HistEvent ev; - int curr_num; - if (pos >= history_length || pos < 0) - return (-1); - - history(h, &ev, H_CURR); - curr_num = ev.num; + return 0; - /* - * use H_DELDATA to set to nth history (without delete) by passing - * (void **)-1 - */ - if (history(h, &ev, H_DELDATA, pos, (void **)-1)) { - 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(); } @@ -1562,8 +1771,16 @@ previous_history(void) HIST_ENTRY * next_history(void) { + HistEvent ev; + + if (history_offset >= history_length) + return NULL; + + if (history(h, &ev, H_LAST) != 0) + return NULL; - return (_move_history(H_NEXT)); + history_offset++; + return current_history(); } @@ -1578,17 +1795,17 @@ history_search(const char *str, int direction) int curr_num; if (history(h, &ev, H_CURR) != 0) - return (-1); + return -1; curr_num = ev.num; for (;;) { if ((strp = strstr(ev.str, str)) != NULL) - return (int) (strp - ev.str); + return (int)(strp - ev.str); if (history(h, &ev, direction < 0 ? H_NEXT:H_PREV) != 0) break; } - history(h, &ev, H_SET, curr_num); - return (-1); + (void)history(h, &ev, H_SET, curr_num); + return -1; } @@ -1600,7 +1817,8 @@ history_search_prefix(const char *str, int direction) { HistEvent ev; - return (history(h, &ev, direction < 0? H_PREV_STR:H_NEXT_STR, str)); + return (history(h, &ev, direction < 0 ? + H_PREV_STR : H_NEXT_STR, str)); } @@ -1620,24 +1838,24 @@ history_search_pos(const char *str, pos = (pos > 0) ? 1 : -1; if (history(h, &ev, H_CURR) != 0) - return (-1); + return -1; curr_num = ev.num; - if (history_set_pos(off) != 0 || history(h, &ev, H_CURR) != 0) - return (-1); - + if (!history_set_pos(off) || history(h, &ev, H_CURR) != 0) + return -1; for (;;) { if (strstr(ev.str, str)) - return (off); + return off; if (history(h, &ev, (pos < 0) ? H_PREV : H_NEXT) != 0) break; } /* set "current" pointer back to previous state */ - history(h, &ev, (pos < 0) ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); + (void)history(h, &ev, + pos < 0 ? H_NEXT_EVENT : H_PREV_EVENT, curr_num); - return (-1); + return -1; } @@ -1660,16 +1878,16 @@ filename_completion_function(const char *name, int state) * a completion generator for usernames; returns _first_ username * which starts with supplied text * text contains a partial username preceded by random character - * (usually '~'); state is ignored - * it's callers responsibility to free returned value + * (usually '~'); state resets search from start (??? should we do that anyway) + * it's the caller's responsibility to free the returned value */ char * username_completion_function(const char *text, int state) { - struct passwd *pwd; + struct passwd *pass = NULL; if (text[0] == '\0') - return (NULL); + return NULL; if (*text == '~') text++; @@ -1677,15 +1895,17 @@ username_completion_function(const char *text, int state) if (state == 0) setpwent(); - while ((pwd = getpwent()) - && pwd != NULL && text[0] == pwd->pw_name[0] - && strcmp(text, pwd->pw_name) == 0); + while ( + (pass = getpwent()) != NULL + && text[0] == pass->pw_name[0] + && strcmp(text, pass->pw_name) == 0) + continue; - if (pwd == NULL) { + if (pass == NULL) { endpwent(); return NULL; } - return strdup(pwd->pw_name); + return strdup(pass->pw_name); } @@ -1700,30 +1920,31 @@ _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 __attribute__((__unused__))) { static char buf[2]; - buf[0] = rl_completion_append_character; + buf[0] = (char)rl_completion_append_character; buf[1] = '\0'; return buf; } +/* + * 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 */ @@ -1731,6 +1952,9 @@ _rl_completion_append_character_function(const char *dummy int rl_complete(int ignore __attribute__((__unused__)), int invoking_key) { + static ct_buffer_t wbreak_conv, sprefix_conv; + const char *breakchars; + if (h == NULL || e == NULL) rl_initialize(); @@ -1739,18 +1963,28 @@ rl_complete(int ignore __attribute__((__unused__)), int invoking_key) arr[0] = (char)invoking_key; arr[1] = '\0'; el_insertstr(e, arr); - return (CC_REFRESH); + return CC_REFRESH; } + if (rl_completion_word_break_hook != NULL) + breakchars = (*rl_completion_word_break_hook)(); + else + breakchars = rl_basic_word_break_characters; + + _rl_update_pos(); + /* Just look at how many global variables modify this operation! */ return fn_complete(e, - (CPFunction *)rl_completion_entry_function, + (rl_compentry_func_t *)rl_completion_entry_function, rl_attempted_completion_function, - rl_basic_word_break_characters, rl_special_prefixes, + ct_decode_string(rl_basic_word_break_characters, &wbreak_conv), + ct_decode_string(breakchars, &sprefix_conv), _rl_completion_append_character_function, (size_t)rl_completion_query_items, &rl_completion_type, &rl_attempted_completion_over, &rl_point, &rl_end); + + } @@ -1781,7 +2015,7 @@ rl_bind_key(int c, rl_command_func_t *func) e->el_map.key[c] = ED_INSERT; retval = 0; } - return (retval); + return retval; } @@ -1797,7 +2031,7 @@ rl_read_key(void) if (e == NULL || h == NULL) rl_initialize(); - return (el_getc(e, fooarr)); + return el_getc(e, fooarr); } @@ -1805,13 +2039,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; } @@ -1827,32 +2062,33 @@ rl_insert(int count, int c) rl_initialize(); /* XXX - int -> char conversion can lose on multichars */ - arr[0] = c; + arr[0] = (char)c; arr[1] = '\0'; for (; count > 0; count--) el_push(e, arr); - return (0); + return 0; } int rl_insert_text(const char *text) { if (!text || *text == 0) - return (0); + return 0; if (h == NULL || e == NULL) rl_initialize(); if (el_insertstr(e, text) < 0) - return (0); + return 0; return (int)strlen(text); } /*ARGSUSED*/ int -rl_newline(int count, int c) +rl_newline(int count __attribute__((__unused__)), + int c __attribute__((__unused__))) { /* * Readline-4.0 appears to ignore the args. @@ -1862,14 +2098,14 @@ rl_newline(int count, int c) /*ARGSUSED*/ static unsigned char -rl_bind_wrapper(EditLine *el, unsigned char c) +rl_bind_wrapper(EditLine *el __attribute__((__unused__)), unsigned char c) { if (map[c] == NULL) - return CC_ERROR; + return CC_ERROR; _rl_update_pos(); - (*map[c])(NULL, c); + (*map[c])(1, c); /* If rl_done was set by the above call, deal with it here */ if (rl_done) @@ -1879,7 +2115,7 @@ rl_bind_wrapper(EditLine *el, unsigned char c) } int -rl_add_defun(const char *name, Function *fun, int c) +rl_add_defun(const char *name, rl_command_func_t *fun, int c) { char dest[8]; if ((size_t)c >= sizeof(map) / sizeof(map[0]) || c < 0) @@ -1887,17 +2123,18 @@ rl_add_defun(const char *name, Function *fun, int c) map[(unsigned char)c] = fun; el_set(e, EL_ADDFN, name, name, rl_bind_wrapper); vis(dest, c, VIS_WHITE|VIS_NOSLASH, 0); - el_set(e, EL_BIND, dest, name); + el_set(e, EL_BIND, dest, name, NULL); return 0; } void -rl_callback_read_char() +rl_callback_read_char(void) { int count = 0, done = 0; const char *buf = el_gets(e, &count); char *wbuf; + el_set(e, EL_UNBUFFERED, 1); if (buf == NULL || count-- <= 0) return; if (count == 0 && buf[0] == e->el_tty.t_c[TS_IO][C_EOF]) @@ -1908,17 +2145,18 @@ rl_callback_read_char() 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'; + RL_SETSTATE(RL_STATE_DONE); } else wbuf = NULL; (*(void (*)(const char *))rl_linefunc)(wbuf); - //el_set(e, EL_UNBUFFERED, 1); } + _rl_update_pos(); } -void -rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) +void +rl_callback_handler_install(const char *prompt, rl_vcpfunc_t *linefunc) { if (e == NULL) { rl_initialize(); @@ -1926,9 +2164,9 @@ rl_callback_handler_install(const char *prompt, VCPFunction *linefunc) (void)rl_set_prompt(prompt); rl_linefunc = linefunc; el_set(e, EL_UNBUFFERED, 1); -} +} -void +void rl_callback_handler_remove(void) { el_set(e, EL_UNBUFFERED, 0); @@ -1939,16 +2177,17 @@ void rl_redisplay(void) { char a[2]; - a[0] = e->el_tty.t_c[TS_IO][C_REPRINT]; + a[0] = (char)e->el_tty.t_c[TS_IO][C_REPRINT]; a[1] = '\0'; el_push(e, a); + rl_forced_update_display(); } int rl_get_previous_history(int count, int key) { char a[2]; - a[0] = key; + a[0] = (char)key; a[1] = '\0'; while (count--) el_push(e, a); @@ -1957,7 +2196,7 @@ rl_get_previous_history(int count, int key) void /*ARGSUSED*/ -rl_prep_terminal(int meta_flag) +rl_prep_terminal(int meta_flag __attribute__((__unused__))) { el_set(e, EL_PREP_TERM, 1); } @@ -1971,7 +2210,7 @@ rl_deprep_terminal(void) int rl_read_init_file(const char *s) { - return(el_source(e, s)); + return el_source(e, s); } int @@ -1985,7 +2224,7 @@ rl_parse_and_bind(const char *line) tok_str(tok, line, &argc, &argv); argc = el_parse(e, argc, argv); tok_end(tok); - return (argc ? 1 : 0); + return argc ? 1 : 0; } int @@ -1995,49 +2234,52 @@ rl_variable_bind(const char *var, const char *value) * The proper return value is undocument, but this is what the * readline source seems to do. */ - return ((el_set(e, EL_BIND, "", var, value) == -1) ? 1 : 0); + return el_set(e, EL_BIND, "", var, value, NULL) == -1 ? 1 : 0; } -void +int rl_stuff_char(int c) { char buf[2]; - buf[0] = c; + buf[0] = (char)c; buf[1] = '\0'; el_insertstr(e, buf); + return 1; } static int -_rl_event_read_char(EditLine *el, char *cp) +_rl_event_read_char(EditLine *el, wchar_t *wc) { + char ch; int n; ssize_t num_read = 0; - *cp = '\0'; + ch = '\0'; + *wc = L'\0'; while (rl_event_hook) { (*rl_event_hook)(); #if defined(FIONREAD) if (ioctl(el->el_infd, FIONREAD, &n) < 0) - return(-1); + return -1; if (n) - num_read = read(el->el_infd, cp, 1); + num_read = read(el->el_infd, &ch, (size_t)1); else num_read = 0; #elif defined(F_SETFL) && defined(O_NDELAY) if ((n = fcntl(el->el_infd, F_GETFL, 0)) < 0) - return(-1); + return -1; if (fcntl(el->el_infd, F_SETFL, n|O_NDELAY) < 0) - return(-1); - num_read = read(el->el_infd, cp, 1); + return -1; + num_read = read(el->el_infd, &ch, 1); if (fcntl(el->el_infd, F_SETFL, n)) - return(-1); + return -1; #else /* not non-blocking, but what you gonna do? */ - num_read = read(el->el_infd, cp, 1); - return(-1); + num_read = read(el->el_infd, &ch, 1); + return -1; #endif if (num_read < 0 && errno == EAGAIN) @@ -2048,6 +2290,7 @@ _rl_event_read_char(EditLine *el, char *cp) } if (!rl_event_hook) el_set(el, EL_GETCFN, EL_BUILTIN_GETCFN); + *wc = (wchar_t)ch; return (int)num_read; } @@ -2058,6 +2301,57 @@ _rl_update_pos(void) rl_point = (int)(li->cursor - li->buffer); rl_end = (int)(li->lastchar - li->buffer); + rl_line_buffer[rl_end] = '\0'; +} + +char * +rl_copy_text(int from, int to) +{ + const LineInfo *li; + size_t len; + char * out; + + if (h == NULL || e == NULL) + rl_initialize(); + + li = el_line(e); + + if (from > to) + return NULL; + + if (li->buffer + from > li->lastchar) + from = (int)(li->lastchar - li->buffer); + + if (li->buffer + to > li->lastchar) + to = (int)(li->lastchar - li->buffer); + + len = (size_t)(to - from); + out = el_malloc((size_t)len + 1); + (void)strlcpy(out, li->buffer + from , len); + + return out; +} + +void +rl_replace_line(const char * text, int clear_undo __attribute__((__unused__))) +{ + if (!text || *text == 0) + return; + + if (h == NULL || e == NULL) + rl_initialize(); + + el_replacestr(e, text); +} + +int +rl_delete_text(int start, int end) +{ + + if (h == NULL || e == NULL) + rl_initialize(); + + return el_deletestr1(e, start, end); } void @@ -2069,14 +2363,29 @@ rl_get_screen_size(int *rows, int *cols) el_get(e, EL_GETTC, "co", cols); } +#define MAX_MESSAGE 160 +void +rl_message(const char *format, ...) +{ + char msg[MAX_MESSAGE]; + va_list args; + + va_start(args, format); + vsnprintf(msg, sizeof(msg), format, args); + va_end(args); + + rl_set_prompt(msg); + rl_forced_update_display(); +} + void rl_set_screen_size(int rows, int cols) { char buf[64]; (void)snprintf(buf, sizeof(buf), "%d", rows); - el_set(e, EL_SETTC, "li", buf); + el_set(e, EL_SETTC, "li", buf, NULL); (void)snprintf(buf, sizeof(buf), "%d", cols); - el_set(e, EL_SETTC, "co", buf); + el_set(e, EL_SETTC, "co", buf, NULL); } char ** @@ -2087,7 +2396,7 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun) len = 1; max = 10; - if ((list = malloc(max * sizeof(*list))) == NULL) + if ((list = el_calloc(max, sizeof(*list))) == NULL) return NULL; while ((match = (*fun)(str, (int)(len - 1))) != NULL) { @@ -2095,7 +2404,7 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun) if (len == max) { char **nl; max += 10; - if ((nl = realloc(list, max * sizeof(*nl))) == NULL) + if ((nl = el_realloc(list, max * sizeof(*nl))) == NULL) goto out; list = nl; } @@ -2110,7 +2419,7 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun) } qsort(&list[1], len - 1, sizeof(*list), (int (*)(const void *, const void *)) strcmp); - min = SIZE_T_MAX; + min = SIZE_MAX; for (i = 1, a = list[i]; i < len - 1; i++, a = b) { b = list[i + 1]; for (j = 0; a[j] && a[j] == b[j]; j++) @@ -2122,15 +2431,15 @@ rl_completion_matches(const char *str, rl_compentry_func_t *fun) if ((list[0] = strdup(str)) == NULL) goto out; } else { - if ((list[0] = malloc(min + 1)) == 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'; } return list; - + out: - free(list); + el_free(list); return NULL; } @@ -2165,15 +2474,16 @@ history_get_history_state(void) { HISTORY_STATE *hs; - if ((hs = malloc(sizeof(HISTORY_STATE))) == NULL) - return (NULL); + if ((hs = el_malloc(sizeof(*hs))) == NULL) + return NULL; hs->length = history_length; - return (hs); + return hs; } int /*ARGSUSED*/ -rl_kill_text(int from, int to) +rl_kill_text(int from __attribute__((__unused__)), + int to __attribute__((__unused__))) { return 0; } @@ -2192,20 +2502,33 @@ rl_get_keymap(void) void /*ARGSUSED*/ -rl_set_keymap(Keymap k) +rl_set_keymap(Keymap k __attribute__((__unused__))) { } int /*ARGSUSED*/ -rl_generic_bind(int type, const char * keyseq, const char * data, Keymap k) +rl_generic_bind(int type __attribute__((__unused__)), + const char * keyseq __attribute__((__unused__)), + const char * data __attribute__((__unused__)), + Keymap k __attribute__((__unused__))) { return 0; } int /*ARGSUSED*/ -rl_bind_key_in_map(int key, rl_command_func_t *fun, Keymap k) +rl_bind_key_in_map(int key __attribute__((__unused__)), + rl_command_func_t *fun __attribute__((__unused__)), + Keymap k __attribute__((__unused__))) +{ + return 0; +} + +int +rl_set_key(const char *keyseq __attribute__((__unused__)), + rl_command_func_t *function __attribute__((__unused__)), + Keymap k __attribute__((__unused__))) { return 0; } @@ -2215,3 +2538,80 @@ void rl_cleanup_after_signal(void) { } + +int +rl_on_new_line(void) +{ + return 0; +} + +void +rl_free_line_state(void) +{ +} + +int +/*ARGSUSED*/ +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); +} + +int +rl_crlf(void) +{ + re_putc(e, '\n', 0); + return 0; +} + +int +rl_ding(void) +{ + re_putc(e, '\a', 0); + return 0; +} + +int +rl_abort(int count, int key) +{ + return count && key ? 0 : 0; +} + +int +rl_set_keymap_name(const char *name, Keymap k) +{ + return name && k ? 0 : 0; +} + +histdata_t +free_history_entry(HIST_ENTRY *he) +{ + return he ? NULL : NULL; +} + +void +_rl_erase_entire_line(void) +{ +} diff --git a/clt/falcon/editline/src/reallocarr.c b/clt/falcon/editline/src/reallocarr.c new file mode 100644 index 000000000..0f0926573 --- /dev/null +++ b/clt/falcon/editline/src/reallocarr.c @@ -0,0 +1,96 @@ +/* $NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $ */ + +/*- + * Copyright (c) 2015 Joerg Sonnenberger . + * 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. + */ + +#ifndef HAVE_REALLOCARR + +#include "config.h" + +#if HAVE_NBTOOL_CONFIG_H +#include "nbtool_config.h" +#endif + +__RCSID("$NetBSD: reallocarr.c,v 1.5 2015/08/20 22:27:49 kamil Exp $"); + +#include +/* Old POSIX has SIZE_MAX in limits.h */ +#include +#include +#include +#include + +#ifdef _LIBC +#ifdef __weak_alias +__weak_alias(reallocarr, _reallocarr) +#endif +#endif + +#define SQRT_SIZE_MAX (((size_t)1) << (sizeof(size_t) * CHAR_BIT / 2)) + +int +reallocarr(void *ptr, size_t number, size_t size) +{ + int saved_errno, result; + void *optr; + void *nptr; + + saved_errno = errno; + memcpy(&optr, ptr, sizeof(ptr)); + if (number == 0 || size == 0) { + free(optr); + nptr = NULL; + memcpy(ptr, &nptr, sizeof(ptr)); + errno = saved_errno; + return 0; + } + + /* + * Try to avoid division here. + * + * It isn't possible to overflow during multiplication if neither + * operand uses any of the most significant half of the bits. + */ + if ((number|size) >= SQRT_SIZE_MAX && + number > SIZE_MAX / size) { + errno = saved_errno; + return EOVERFLOW; + } + + nptr = realloc(optr, number * size); + if (nptr == NULL) { + result = errno; + } else { + result = 0; + memcpy(ptr, &nptr, sizeof(ptr)); + } + errno = saved_errno; + return result; +} +#endif diff --git a/clt/falcon/editline/src/refresh.c b/clt/falcon/editline/src/refresh.c index baf587a33..26a49fe75 100644 --- a/clt/falcon/editline/src/refresh.c +++ b/clt/falcon/editline/src/refresh.c @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.c,v 1.32 2009/07/17 12:28:27 christos Exp $ */ +/* $NetBSD: refresh.c,v 1.58 2021/09/09 20:24:07 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)refresh.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: refresh.c,v 1.32 2009/07/17 12:28:27 christos Exp $"); +__RCSID("$NetBSD: refresh.c,v 1.58 2021/09/09 20:24:07 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -45,26 +45,26 @@ __RCSID("$NetBSD: refresh.c,v 1.32 2009/07/17 12:28:27 christos Exp $"); * refresh.c: Lower level screen refreshing functions */ #include -#include -#include +#include #include +#include #include "el.h" -private void re_nextline(EditLine *); -private void re_addc(EditLine *, int); -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 *, int); -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 \ +#define ELRE_ASSERT(a, b, c) do \ if (/*CONSTCOND*/ a) { \ (void) fprintf b; \ c; \ @@ -75,8 +75,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)); @@ -92,7 +92,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. */ @@ -103,111 +103,150 @@ re_nextline(EditLine *el) * We do this via pointer shuffling - it's safe in this case * and we avoid memcpy(). */ - if (el->el_refresh.r_cursor.v + 1 >= el->el_term.t_size.v) { - int i, lins = el->el_term.t_size.v; - char *firstline = el->el_vdisplay[0]; + if (el->el_refresh.r_cursor.v + 1 >= el->el_terminal.t_size.v) { + int i, lins = el->el_terminal.t_size.v; + wint_t *firstline = el->el_vdisplay[0]; for(i = 1; i < lins; i++) el->el_vdisplay[i - 1] = el->el_vdisplay[i]; - firstline[0] = '\0'; /* empty the string */ + firstline[0] = '\0'; /* empty the string */ el->el_vdisplay[i - 1] = firstline; } else el->el_refresh.r_cursor.v++; - ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_term.t_size.v, + ELRE_ASSERT(el->el_refresh.r_cursor.v >= el->el_terminal.t_size.v, (__F, "\r\nre_putc: overflow! r_cursor.v == %d > %d\r\n", - el->el_refresh.r_cursor.v, el->el_term.t_size.v), + el->el_refresh.r_cursor.v, el->el_terminal.t_size.v), abort()); } /* re_addc(): * Draw c, expanding tabs, control chars etc. */ -private void -re_addc(EditLine *el, int c) +static void +re_addc(EditLine *el, wint_t c) { - - if (isprint(c)) { - re_putc(el, c, 1); - return; - } - if (c == '\n') { /* expand the newline */ - int oldv = el->el_refresh.r_cursor.v; - re_putc(el, '\0', 0); /* assure end of line */ - if (oldv == el->el_refresh.r_cursor.v) /* XXX */ - re_nextline(el); - return; - } - if (c == '\t') { /* expand the tab */ + switch (ct_chr_class(c)) { + case CHTYPE_TAB: /* expand the tab */ for (;;) { re_putc(el, ' ', 1); if ((el->el_refresh.r_cursor.h & 07) == 0) break; /* go until tab stop */ } - } else if (iscntrl(c)) { - re_putc(el, '^', 1); - if (c == '\177') - re_putc(el, '?', 1); - else - /* uncontrolify it; works only for iso8859-1 like sets */ - re_putc(el, (c | 0100), 1); - } else { - re_putc(el, '\\', 1); - re_putc(el, (int) ((((unsigned int) c >> 6) & 07) + '0'), 1); - re_putc(el, (int) ((((unsigned int) c >> 3) & 07) + '0'), 1); - re_putc(el, (c & 07) + '0', 1); + break; + case CHTYPE_NL: { + int oldv = el->el_refresh.r_cursor.v; + re_putc(el, '\0', 0); /* assure end of line */ + if (oldv == el->el_refresh.r_cursor.v) /* XXX */ + re_nextline(el); + break; + } + case CHTYPE_PRINT: + re_putc(el, c, 1); + break; + default: { + wchar_t visbuf[VISUAL_WIDTH_MAX]; + ssize_t i, n = + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); + for (i = 0; n-- > 0; ++i) + re_putc(el, visbuf[i], 1); + break; + } } } +/* 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 -re_putc(EditLine *el, int c, int shift) +libedit_private void +re_putc(EditLine *el, wint_t c, int shift) { + coord_t *cur = &el->el_refresh.r_cursor; + int i, w = wcwidth(c); + int sizeh = el->el_terminal.t_size.h; - ELRE_DEBUG(1, (__F, "printing %3.3o '%c'\r\n", c, c)); + 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[cur->v][cur->h] = c; + /* assumes !shift is only used for single-column chars */ + i = w; + while (--i > 0) + el->el_vdisplay[cur->v][cur->h + i] = MB_FILL_CHAR; - el->el_vdisplay[el->el_refresh.r_cursor.v][el->el_refresh.r_cursor.h] = c; if (!shift) return; - el->el_refresh.r_cursor.h++; /* advance to next place */ - if (el->el_refresh.r_cursor.h >= el->el_term.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_term.t_size.h] - = '\0'; + el->el_vdisplay[cur->v][sizeh] = '\0'; re_nextline(el); } - } /* re_refresh(): * draws the new virtual screen image from the current input - * line, then goes line-by-line changing the real image to the new + * line, then goes line-by-line changing the real image to the new * 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 = :%s:\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); @@ -230,7 +269,7 @@ re_refresh(EditLine *el) /* draw the current input buffer */ #if notyet - termsz = el->el_term.t_size.h * el->el_term.t_size.v; + termsz = el->el_terminal.t_size.h * el->el_terminal.t_size.v; if (el->el_line.lastchar - el->el_line.buffer > termsz) { /* * If line is longer than terminal, process only part @@ -239,26 +278,33 @@ re_refresh(EditLine *el) size_t rem = (el->el_line.lastchar-el->el_line.buffer)%termsz; st = el->el_line.lastchar - rem - - (termsz - (((rem / el->el_term.t_size.v) - 1) - * el->el_term.t_size.v)); + - (termsz - (((rem / el->el_terminal.t_size.v) - 1) + * el->el_terminal.t_size.v)); } else #endif st = el->el_line.buffer; for (cp = st; cp < el->el_line.lastchar; cp++) { if (cp == el->el_line.cursor) { + int w = wcwidth(*cp); /* save for later */ cur.h = el->el_refresh.r_cursor.h; cur.v = el->el_refresh.r_cursor.v; + /* handle being at a linebroken doublewidth char */ + if (w > 1 && el->el_refresh.r_cursor.h + w > + el->el_terminal.t_size.h) { + cur.h = 0; + cur.v++; + } } - re_addc(el, (unsigned char) *cp); + re_addc(el, *cp); } if (cur.h == -1) { /* if I haven't been set yet, I'm at the end */ cur.h = el->el_refresh.r_cursor.h; cur.v = el->el_refresh.r_cursor.v; } - rhdiff = el->el_term.t_size.h - el->el_refresh.r_cursor.h - + rhdiff = el->el_terminal.t_size.h - el->el_refresh.r_cursor.h - el->el_rprompt.p_pos.h; if (el->el_rprompt.p_pos.h && !el->el_rprompt.p_pos.v && !el->el_refresh.r_cursor.v && rhdiff > 1) { @@ -281,13 +327,15 @@ re_refresh(EditLine *el) ELRE_DEBUG(1, (__F, "term.h=%d vcur.h=%d vcur.v=%d vdisplay[0]=\r\n:%80.80s:\r\n", - el->el_term.t_size.h, el->el_refresh.r_cursor.h, - el->el_refresh.r_cursor.v, el->el_vdisplay[0])); + el->el_terminal.t_size.h, el->el_refresh.r_cursor.h, + el->el_refresh.r_cursor.v, ct_encode_string(el->el_vdisplay[0], + &el->el_scratch))); ELRE_DEBUG(1, (__F, "updating %d lines.\r\n", el->el_refresh.r_newcv)); for (i = 0; i <= el->el_refresh.r_newcv; i++) { /* NOTE THAT re_update_line MAY CHANGE el_display[i] */ - re_update_line(el, el->el_display[i], el->el_vdisplay[i], i); + re_update_line(el, (wchar_t *)el->el_display[i], + (wchar_t *)el->el_vdisplay[i], i); /* * Copy the new line to be the current one, and pad out with @@ -296,8 +344,9 @@ re_refresh(EditLine *el) * end of the screen line, it won't be a NUL or some old * leftover stuff. */ - re__copy_and_pad(el->el_display[i], el->el_vdisplay[i], - (size_t) el->el_term.t_size.h); + re__copy_and_pad((wchar_t *)el->el_display[i], + (wchar_t *)el->el_vdisplay[i], + (size_t) el->el_terminal.t_size.h); } ELRE_DEBUG(1, (__F, "\r\nel->el_refresh.r_cursor.v=%d,el->el_refresh.r_oldcv=%d i=%d\r\n", @@ -305,11 +354,13 @@ re_refresh(EditLine *el) if (el->el_refresh.r_oldcv > el->el_refresh.r_newcv) for (; i <= el->el_refresh.r_oldcv; i++) { - term_move_to_line(el, i); - term_move_to_char(el, 0); - term_clear_EOL(el, (int) strlen(el->el_display[i])); + terminal_move_to_line(el, i); + terminal_move_to_char(el, 0); + /* This wcslen should be safe even with MB_FILL_CHARs */ + terminal_clear_EOL(el, + (int) wcslen((const wchar_t *)el->el_display[i])); #ifdef DEBUG_REFRESH - term_overwrite(el, "C\b", (size_t)2); + terminal_overwrite(el, L"C\b", 2); #endif /* DEBUG_REFRESH */ el->el_display[i][0] = '\0'; } @@ -319,22 +370,22 @@ re_refresh(EditLine *el) "\r\ncursor.h = %d, cursor.v = %d, cur.h = %d, cur.v = %d\r\n", el->el_refresh.r_cursor.h, el->el_refresh.r_cursor.v, cur.h, cur.v)); - term_move_to_line(el, cur.v); /* go to where the cursor is */ - term_move_to_char(el, cur.h); + terminal_move_to_line(el, cur.v); /* go to where the cursor is */ + terminal_move_to_char(el, cur.h); } /* re_goto_bottom(): * used to go to last used screen line */ -protected void +libedit_private void re_goto_bottom(EditLine *el) { - term_move_to_line(el, el->el_refresh.r_oldcv); - term__putc(el, '\n'); + terminal_move_to_line(el, el->el_refresh.r_oldcv); + terminal__putc(el, '\n'); re_clear_display(el); - term__flush(el); + terminal__flush(el); } @@ -342,12 +393,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; @@ -356,8 +407,9 @@ re_insert(EditLine *el __attribute__((__unused__)), ELRE_DEBUG(1, (__F, "re_insert() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); + num, dat, dlen, ct_encode_string(d, &el->el_scratch))); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s, + &el->el_scratch))); /* open up the space for num chars */ if (num > 0) { @@ -367,31 +419,37 @@ re_insert(EditLine *el __attribute__((__unused__)), *b-- = *a--; d[dlen] = '\0'; /* just in case */ } + ELRE_DEBUG(1, (__F, "re_insert() after insert: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); - ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); + num, dat, dlen, ct_encode_string(d, &el->el_scratch))); + ELRE_DEBUG(1, (__F, "s == \"%s\"\n", ct_encode_string(s, + &el->el_scratch))); /* copy the characters */ for (a = d + dat; (a < d + dlen) && (num > 0); num--) *a++ = *s++; +#ifdef notyet + /* ct_encode_string() uses a static buffer, so we can't conveniently + * encode both d & s here */ ELRE_DEBUG(1, (__F, "re_insert() after copy: %d at %d max %d, %s == \"%s\"\n", num, dat, dlen, d, s)); ELRE_DEBUG(1, (__F, "s == \"%s\"\n", s)); +#endif } /* 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; @@ -401,7 +459,7 @@ re_delete(EditLine *el __attribute__((__unused__)), } ELRE_DEBUG(1, (__F, "re_delete() starting: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); + num, dat, dlen, ct_encode_string(d, &el->el_scratch))); /* open up the space for num chars */ if (num > 0) { @@ -413,15 +471,15 @@ re_delete(EditLine *el __attribute__((__unused__)), } ELRE_DEBUG(1, (__F, "re_delete() after delete: %d at %d max %d, d == \"%s\"\n", - num, dat, dlen, d)); + num, dat, dlen, ct_encode_string(d, &el->el_scratch))); } /* 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) @@ -432,10 +490,10 @@ re__strncopy(char *a, char *b, size_t n) * Find the number of characters we need to clear till the end of line * in order to make sure that we have cleared the previous contents of * the line. fx and sx is the number of characters inserted or deleted - * int the first or second diff, diff is the difference between the - * number of characters between the new and old line. + * 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) { @@ -452,7 +510,7 @@ re_clear_eol(EditLine *el, int fx, int sx, int diff) diff = sx; ELRE_DEBUG(1, (__F, "re_clear_eol %d\n", diff)); - term_clear_EOL(el, diff); + terminal_clear_EOL(el, diff); } /***************************************************************** @@ -479,12 +537,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; @@ -541,7 +599,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) nls = ++n; /* - * find same begining and same end + * find same beginning and same end */ osb = ols; nsb = nls; @@ -671,9 +729,9 @@ re_update_line(EditLine *el, char *old, char *new, int i) sx = (int)((nls - nse) - (ols - ose)); ELRE_DEBUG(1, (__F, "fx %d, sx %d\n", fx, sx)); - ELRE_DEBUG(1, (__F, "ofd %d, osb %d, ose %d, ols %d, oe %d\n", + ELRE_DEBUG(1, (__F, "ofd %td, osb %td, ose %td, ols %td, oe %td\n", ofd - old, osb - old, ose - old, ols - old, oe - old)); - ELRE_DEBUG(1, (__F, "nfd %d, nsb %d, nse %d, nls %d, ne %d\n", + ELRE_DEBUG(1, (__F, "nfd %td, nsb %td, nse %td, nls %td, ne %td\n", nfd - new, nsb - new, nse - new, nls - new, ne - new)); ELRE_DEBUG(1, (__F, "xxx-xxx:\"00000000001111111111222222222233333333334\"\r\n")); @@ -699,7 +757,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) * don't have to change the line, we don't move to it. el_cursor.h to * first diff char */ - term_move_to_line(el, i); + terminal_move_to_line(el, i); /* * at this point we have something like this: @@ -723,7 +781,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) * if we have a net insert on the first difference, AND inserting the * net amount ((nsb-nfd) - (osb-ofd)) won't push the last useful * character (which is ne if nls != ne, otherwise is nse) off the edge - * of the screen (el->el_term.t_size.h) else we do the deletes first + * of the screen (el->el_terminal.t_size.h) else we do the deletes first * so that we keep everything we need to. */ @@ -745,13 +803,13 @@ re_update_line(EditLine *el, char *old, char *new, int i) * No insert or delete */ if ((nsb != nfd) && fx > 0 && - ((p - old) + fx <= el->el_term.t_size.h)) { + ((p - old) + fx <= el->el_terminal.t_size.h)) { ELRE_DEBUG(1, - (__F, "first diff insert at %d...\r\n", nfd - new)); + (__F, "first diff insert at %td...\r\n", nfd - new)); /* * Move to the first char to insert, where the first diff is. */ - term_move_to_char(el, (int)(nfd - new)); + terminal_move_to_char(el, (int)(nfd - new)); /* * Check if we have stuff to keep at end */ @@ -763,21 +821,21 @@ re_update_line(EditLine *el, char *old, char *new, int i) if (fx > 0) { ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in early first diff\n")); - term_insertwrite(el, nfd, fx); + terminal_insertwrite(el, nfd, fx); re_insert(el, old, (int)(ofd - old), - el->el_term.t_size.h, nfd, fx); + el->el_terminal.t_size.h, nfd, fx); } /* * write (nsb-nfd) - fx chars of new starting at * (nfd + fx) */ len = (size_t) ((nsb - nfd) - fx); - term_overwrite(el, (nfd + fx), len); + terminal_overwrite(el, (nfd + fx), len); re__strncopy(ofd + fx, nfd + fx, len); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); len = (size_t)(nsb - nfd); - term_overwrite(el, nfd, len); + terminal_overwrite(el, nfd, len); re__strncopy(ofd, nfd, len); /* * Done @@ -786,11 +844,11 @@ re_update_line(EditLine *el, char *old, char *new, int i) } } else if (fx < 0) { ELRE_DEBUG(1, - (__F, "first diff delete at %d...\r\n", ofd - old)); + (__F, "first diff delete at %td...\r\n", ofd - old)); /* * move to the first char to delete where the first diff is */ - term_move_to_char(el, (int)(ofd - old)); + terminal_move_to_char(el, (int)(ofd - old)); /* * Check if we have stuff to save */ @@ -803,15 +861,15 @@ re_update_line(EditLine *el, char *old, char *new, int i) if (fx < 0) { ELRE_DEBUG(!EL_CAN_DELETE, (__F, "ERROR: cannot delete in first diff\n")); - term_deletechars(el, -fx); + terminal_deletechars(el, -fx); re_delete(el, old, (int)(ofd - old), - el->el_term.t_size.h, -fx); + el->el_terminal.t_size.h, -fx); } /* * write (nsb-nfd) chars of new starting at nfd */ len = (size_t) (nsb - nfd); - term_overwrite(el, nfd, len); + terminal_overwrite(el, nfd, len); re__strncopy(ofd, nfd, len); } else { @@ -820,7 +878,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) /* * write (nsb-nfd) chars of new starting at nfd */ - term_overwrite(el, nfd, (size_t)(nsb - nfd)); + terminal_overwrite(el, nfd, (size_t)(nsb - nfd)); re_clear_eol(el, fx, sx, (int)((oe - old) - (ne - new))); /* @@ -831,9 +889,9 @@ re_update_line(EditLine *el, char *old, char *new, int i) } else fx = 0; - if (sx < 0 && (ose - old) + fx < el->el_term.t_size.h) { + if (sx < 0 && (ose - old) + fx < el->el_terminal.t_size.h) { ELRE_DEBUG(1, (__F, - "second diff delete at %d...\r\n", (ose - old) + fx)); + "second diff delete at %td...\r\n", (ose - old) + fx)); /* * Check if we have stuff to delete */ @@ -841,7 +899,7 @@ re_update_line(EditLine *el, char *old, char *new, int i) * fx is the number of characters inserted (+) or deleted (-) */ - term_move_to_char(el, (int)((ose - old) + fx)); + terminal_move_to_char(el, (int)((ose - old) + fx)); /* * Check if we have stuff to save */ @@ -853,16 +911,16 @@ re_update_line(EditLine *el, char *old, char *new, int i) if (sx < 0) { ELRE_DEBUG(!EL_CAN_DELETE, (__F, "ERROR: cannot delete in second diff\n")); - term_deletechars(el, -sx); + terminal_deletechars(el, -sx); } /* * write (nls-nse) chars of new starting at nse */ - term_overwrite(el, nse, (size_t)(nls - nse)); + terminal_overwrite(el, nse, (size_t)(nls - nse)); } else { ELRE_DEBUG(1, (__F, "but with nothing left to save\r\n")); - term_overwrite(el, nse, (size_t)(nls - nse)); + terminal_overwrite(el, nse, (size_t)(nls - nse)); re_clear_eol(el, fx, sx, (int)((oe - old) - (ne - new))); } @@ -871,10 +929,10 @@ re_update_line(EditLine *el, char *old, char *new, int i) * if we have a first insert AND WE HAVEN'T ALREADY DONE IT... */ if ((nsb != nfd) && (osb - ofd) <= (nsb - nfd) && (fx == 0)) { - ELRE_DEBUG(1, (__F, "late first diff insert at %d...\r\n", + ELRE_DEBUG(1, (__F, "late first diff insert at %td...\r\n", nfd - new)); - term_move_to_char(el, (int)(nfd - new)); + terminal_move_to_char(el, (int)(nfd - new)); /* * Check if we have stuff to keep at the end */ @@ -892,21 +950,21 @@ re_update_line(EditLine *el, char *old, char *new, int i) */ ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in late first diff\n")); - term_insertwrite(el, nfd, fx); + terminal_insertwrite(el, nfd, fx); re_insert(el, old, (int)(ofd - old), - el->el_term.t_size.h, nfd, fx); + el->el_terminal.t_size.h, nfd, fx); } /* * write (nsb-nfd) - fx chars of new starting at * (nfd + fx) */ len = (size_t) ((nsb - nfd) - fx); - term_overwrite(el, (nfd + fx), len); + terminal_overwrite(el, (nfd + fx), len); re__strncopy(ofd + fx, nfd + fx, len); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); len = (size_t) (nsb - nfd); - term_overwrite(el, nfd, len); + terminal_overwrite(el, nfd, len); re__strncopy(ofd, nfd, len); } } @@ -916,24 +974,24 @@ re_update_line(EditLine *el, char *old, char *new, int i) if (sx >= 0) { ELRE_DEBUG(1, (__F, "second diff insert at %d...\r\n", (int)(nse - new))); - term_move_to_char(el, (int)(nse - new)); + terminal_move_to_char(el, (int)(nse - new)); if (ols != oe) { ELRE_DEBUG(1, (__F, "with stuff to keep at end\r\n")); if (sx > 0) { /* insert sx chars of new starting at nse */ ELRE_DEBUG(!EL_CAN_INSERT, (__F, "ERROR: cannot insert in second diff\n")); - term_insertwrite(el, nse, sx); + terminal_insertwrite(el, nse, sx); } /* * write (nls-nse) - sx chars of new starting at * (nse + sx) */ - term_overwrite(el, (nse + sx), + terminal_overwrite(el, (nse + sx), (size_t)((nls - nse) - sx)); } else { ELRE_DEBUG(1, (__F, "without anything to save\r\n")); - term_overwrite(el, nse, (size_t)(nls - nse)); + terminal_overwrite(el, nse, (size_t)(nls - nse)); /* * No need to do a clear-to-end here because we were @@ -949,8 +1007,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; @@ -970,11 +1028,11 @@ 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, c; - int h, v, th; + wchar_t *cp; + int h, v, th, w; if (el->el_line.cursor >= el->el_line.lastchar) { if (el->el_map.current == el->el_map.alt @@ -987,54 +1045,69 @@ re_refresh_cursor(EditLine *el) /* first we must find where the cursor is... */ h = el->el_prompt.p_pos.h; v = el->el_prompt.p_pos.v; - th = el->el_term.t_size.h; /* optimize for speed */ + th = el->el_terminal.t_size.h; /* optimize for speed */ /* do input buffer to el->el_line.cursor */ for (cp = el->el_line.buffer; cp < el->el_line.cursor; cp++) { - c = *cp; - - switch (c) { - case '\n': /* handle newline in data part too */ + switch (ct_chr_class(*cp)) { + case CHTYPE_NL: /* handle newline in data part too */ h = 0; v++; break; - case '\t': /* if a tab, to next tab stop */ + case CHTYPE_TAB: /* if a tab, to next tab stop */ while (++h & 07) continue; break; default: - if (iscntrl((unsigned char) c)) - h += 2; /* ^x */ - else if (!isprint((unsigned char) c)) - h += 4; /* octal \xxx */ - else - h++; + w = wcwidth(*cp); + if (w > 1 && h + w > th) { /* won't fit on line */ + h = 0; + v++; + } + h += ct_visual_width(*cp); break; - } + } if (h >= th) { /* check, extra long tabs picked up here also */ h -= th; v++; } } + /* 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 = wcwidth(*cp)) > 1) + if (h + w > th) { + h = 0; + v++; + } /* now go there */ - term_move_to_line(el, v); - term_move_to_char(el, h); - term__flush(el); + terminal_move_to_line(el, v); + terminal_move_to_char(el, h); + terminal__flush(el); } /* re_fastputc(): * Add a character fast. */ -private void -re_fastputc(EditLine *el, int c) +static void +re_fastputc(EditLine *el, wint_t c) { + wint_t *lastline; + int w; - term__putc(el, c); + 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++] = c; - if (el->el_cursor.h >= el->el_term.t_size.h) { + while (--w > 0) + el->el_display[el->el_cursor.v][el->el_cursor.h++] + = MB_FILL_CHAR; + + if (el->el_cursor.h >= el->el_terminal.t_size.h) { /* if we must overflow */ el->el_cursor.h = 0; @@ -1044,27 +1117,29 @@ re_fastputc(EditLine *el, int c) * We do this via pointer shuffling - it's safe in this case * and we avoid memcpy(). */ - if (el->el_cursor.v + 1 >= el->el_term.t_size.v) { - int i, lins = el->el_term.t_size.v; - char *firstline = el->el_display[0]; - + if (el->el_cursor.v + 1 >= el->el_terminal.t_size.v) { + int i, lins = el->el_terminal.t_size.v; + + 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, "", 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((wchar_t *)lastline, L"", + (size_t)el->el_terminal.t_size.h); + if (EL_HAS_AUTO_MARGINS) { if (EL_HAS_MAGIC_MARGINS) { - term__putc(el, ' '); - term__putc(el, '\b'); + terminal__putc(el, ' '); + terminal__putc(el, '\b'); } } else { - term__putc(el, '\r'); - term__putc(el, '\n'); + terminal__putc(el, '\r'); + terminal__putc(el, '\n'); } } } @@ -1074,10 +1149,10 @@ re_fastputc(EditLine *el, int 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]; @@ -1086,39 +1161,44 @@ re_fastaddc(EditLine *el) re_refresh(el); /* too hard to handle */ return; } - rhdiff = el->el_term.t_size.h - el->el_cursor.h - + rhdiff = el->el_terminal.t_size.h - el->el_cursor.h - el->el_rprompt.p_pos.h; if (el->el_rprompt.p_pos.h && rhdiff < 3) { re_refresh(el); /* clear out rprompt if less than 1 char gap */ return; } /* else (only do at end of line, no TAB) */ - if (iscntrl((unsigned char) c)) { /* if control char, do caret */ - char mc = (c == '\177') ? '?' : (c | 0100); - re_fastputc(el, '^'); - re_fastputc(el, mc); - } else if (isprint((unsigned char) c)) { /* normal char */ + switch (ct_chr_class(c)) { + case CHTYPE_TAB: /* already handled, should never happen here */ + break; + case CHTYPE_NL: + case CHTYPE_PRINT: re_fastputc(el, c); - } else { - re_fastputc(el, '\\'); - re_fastputc(el, (int)(((((unsigned int)c) >> 6) & 3) + '0')); - re_fastputc(el, (int)(((((unsigned int)c) >> 3) & 7) + '0')); - re_fastputc(el, (c & 7) + '0'); + break; + case CHTYPE_ASCIICTL: + case CHTYPE_NONPRINT: { + wchar_t visbuf[VISUAL_WIDTH_MAX]; + ssize_t i, n = + ct_visual_char(visbuf, VISUAL_WIDTH_MAX, c); + for (i = 0; n-- > 0; ++i) + re_fastputc(el, visbuf[i]); + break; + } } - term__flush(el); + terminal__flush(el); } /* re_clear_display(): * clear the screen buffers so that new new prompt starts fresh. */ -protected void +libedit_private void re_clear_display(EditLine *el) { int i; el->el_cursor.v = 0; el->el_cursor.h = 0; - for (i = 0; i < el->el_term.t_size.v; i++) + for (i = 0; i < el->el_terminal.t_size.v; i++) el->el_display[i][0] = '\0'; el->el_refresh.r_oldcv = 0; } @@ -1127,23 +1207,22 @@ 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) { if (EL_CAN_CEOL) { int i; - term_move_to_char(el, 0); - for (i = 0; i <= el->el_refresh.r_oldcv; i++) { + for (i = el->el_refresh.r_oldcv; i >= 0; i--) { /* for each line on the screen */ - term_move_to_line(el, i); - term_clear_EOL(el, el->el_term.t_size.h); + terminal_move_to_line(el, i); + terminal_move_to_char(el, 0); + terminal_clear_EOL(el, el->el_terminal.t_size.h); } - term_move_to_line(el, 0); } else { - term_move_to_line(el, el->el_refresh.r_oldcv); + terminal_move_to_line(el, el->el_refresh.r_oldcv); /* go to last line */ - term__putc(el, '\r'); /* go to BOL */ - term__putc(el, '\n'); /* go to new line */ + terminal__putc(el, '\r'); /* go to BOL */ + terminal__putc(el, '\n'); /* go to new line */ } } diff --git a/clt/falcon/editline/src/refresh.h b/clt/falcon/editline/src/refresh.h index dd2bd0209..22e4ccb9d 100644 --- a/clt/falcon/editline/src/refresh.h +++ b/clt/falcon/editline/src/refresh.h @@ -1,4 +1,4 @@ -/* $NetBSD: refresh.h,v 1.5 2003/08/07 16:44:33 agc Exp $ */ +/* $NetBSD: refresh.h,v 1.11 2017/06/27 23:23:48 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,20 +40,20 @@ #ifndef _h_el_refresh #define _h_el_refresh -#include "histedit.h" - typedef struct { coord_t r_cursor; /* Refresh cursor position */ int r_oldcv; /* Vertical locations */ int r_newcv; } el_refresh_t; -protected void re_putc(EditLine *, int, 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 */ diff --git a/clt/falcon/editline/src/search.c b/clt/falcon/editline/src/search.c index 80ea415d4..b8b70b6f0 100644 --- a/clt/falcon/editline/src/search.c +++ b/clt/falcon/editline/src/search.c @@ -1,4 +1,4 @@ -/* $NetBSD: search.c,v 1.21 2009/02/15 21:55:23 christos Exp $ */ +/* $NetBSD: search.c,v 1.51 2020/03/30 06:56:38 ryo Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)search.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: search.c,v 1.21 2009/02/15 21:55:23 christos Exp $"); +__RCSID("$NetBSD: search.c,v 1.51 2020/03/30 06:56:38 ryo Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -46,12 +46,16 @@ __RCSID("$NetBSD: search.c,v 1.21 2009/02/15 21:55:23 christos Exp $"); */ #include #include +#include #if defined(REGEX) #include #elif defined(REGEXP) #include #endif + #include "el.h" +#include "common.h" +#include "fcns.h" /* * Adjust cursor in vi mode to include the character under it @@ -63,30 +67,32 @@ __RCSID("$NetBSD: search.c,v 1.21 2009/02/15 21:55:23 christos Exp $"); /* search_init(): * Initialize the search stuff */ -protected int +libedit_private int search_init(EditLine *el) { - el->el_search.patbuf = (char *) 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); + 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); + return 0; } /* search_end(): * Initialize the search stuff */ -protected void +libedit_private void search_end(EditLine *el) { - el_free((ptr_t) el->el_search.patbuf); + el_free(el->el_search.patbuf); el->el_search.patbuf = NULL; } @@ -95,7 +101,7 @@ search_end(EditLine *el) /* regerror(): * Handle regular expression errors */ -public void +void /*ARGSUSED*/ regerror(const char *msg) { @@ -106,9 +112,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) { + static ct_buffer_t conv; #if defined (REGEX) regex_t re; int rv; @@ -120,30 +127,31 @@ el_match(const char *str, const char *pat) extern int re_exec(const char *); #endif - if (strstr(str, pat) != NULL) - return (1); + if (wcsstr(str, pat) != 0) + return 1; #if defined(REGEX) - if (regcomp(&re, pat, 0) == 0) { - rv = regexec(&re, str, 0, NULL, 0) == 0; + if (regcomp(&re, ct_encode_string(pat, &conv), 0) == 0) { + rv = regexec(&re, ct_encode_string(str, &conv), (size_t)0, NULL, + 0) == 0; regfree(&re); } else { rv = 0; } - return (rv); + return rv; #elif defined(REGEXP) - if ((re = regcomp(pat)) != NULL) { - rv = regexec(re, str); - free((ptr_t) re); + if ((re = regcomp(ct_encode_string(pat, &conv))) != NULL) { + rv = regexec(re, ct_encode_string(str, &conv)); + el_free(re); } else { rv = 0; } - return (rv); + return rv; #else - if (re_comp(pat) != NULL) - return (0); + if (re_comp(ct_encode_string(pat, &conv)) != NULL) + return 0; else - return (re_exec(str) == 1); + return re_exec(ct_encode_string(str, &conv)) == 1; #endif } @@ -151,43 +159,41 @@ 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", + (void) fprintf(el->el_errfile, "match `%ls' with `%ls'\n", el->el_search.patbuf, str); #endif /* SDEBUG */ - return (el_match(str, el->el_search.patbuf)); + return el_match(str, el->el_search.patbuf); } /* 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 && el->el_state.lastcmd != ED_SEARCH_NEXT_HISTORY) { - el->el_search.patlen = EL_CURSOR(el) - el->el_line.buffer; + el->el_search.patlen = + (size_t)(EL_CURSOR(el) - el->el_line.buffer); 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, - el->el_search.patlen); - el->el_search.patbuf[el->el_search.patlen] = '\0'; - } else - el->el_search.patlen = strlen(el->el_search.patbuf); + (void) wcsncpy(el->el_search.patbuf, el->el_line.buffer, + el->el_search.patlen); + el->el_search.patbuf[el->el_search.patlen] = '\0'; } #ifdef SDEBUG (void) fprintf(el->el_errfile, "\neventno = %d\n", el->el_history.eventno); - (void) fprintf(el->el_errfile, "patlen = %d\n", el->el_search.patlen); - (void) fprintf(el->el_errfile, "patbuf = \"%s\"\n", + (void) fprintf(el->el_errfile, "patlen = %ld\n", el->el_search.patlen); + (void) fprintf(el->el_errfile, "patbuf = \"%ls\"\n", el->el_search.patbuf); - (void) fprintf(el->el_errfile, "cursor %d lastchar %d\n", + (void) fprintf(el->el_errfile, "cursor %ld lastchar %ld\n", EL_CURSOR(el) - el->el_line.buffer, el->el_line.lastchar - el->el_line.buffer); #endif @@ -197,15 +203,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 ch, *ocursor = el->el_line.cursor, oldpchar = pchar; - const char *cp; + 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; @@ -214,9 +219,10 @@ ce_inc_search(EditLine *el, int dir) int newdir = dir; int done, redo; - if (el->el_line.lastchar + sizeof(STRfwd) / sizeof(char) + 2 + + if (el->el_line.lastchar + sizeof(STRfwd) / + sizeof(*el->el_line.lastchar) + 2 + el->el_search.patlen >= el->el_line.limit) - return (CC_ERROR); + return CC_ERROR; for (;;) { @@ -243,14 +249,14 @@ ce_inc_search(EditLine *el, int dir) *el->el_line.lastchar = '\0'; re_refresh(el); - if (el_getc(el, &ch) != 1) - return (ed_end_of_file(el, 0)); + if (el_wgetc(el, &ch) != 1) + return ed_end_of_file(el, 0); switch (el->el_map.current[(unsigned char) ch]) { case ED_INSERT: case ED_DIGIT: if (el->el_search.patlen >= EL_BUFSIZ - LEN) - term_beep(el); + terminal_beep(el); else { el->el_search.patbuf[el->el_search.patlen++] = ch; @@ -275,7 +281,7 @@ ce_inc_search(EditLine *el, int dir) if (el->el_search.patlen > LEN) done++; else - term_beep(el); + terminal_beep(el); break; default: @@ -299,7 +305,7 @@ ce_inc_search(EditLine *el, int dir) *el->el_line.cursor != '\n') { if (el->el_search.patlen >= EL_BUFSIZ - LEN) { - term_beep(el); + terminal_beep(el); break; } el->el_search.patbuf[el->el_search.patlen++] = @@ -312,14 +318,14 @@ ce_inc_search(EditLine *el, int dir) re_refresh(el); break; } else if (isglob(*cp)) { - term_beep(el); + terminal_beep(el); break; } break; default: /* Terminate and execute cmd */ endcmd[0] = ch; - el_push(el, endcmd); + el_wpush(el, endcmd); /* FALLTHROUGH */ case 0033: /* ESC: Terminate */ @@ -339,14 +345,14 @@ ce_inc_search(EditLine *el, int dir) /* Can't search if unmatched '[' */ for (cp = &el->el_search.patbuf[el->el_search.patlen-1], - ch = ']'; + ch = L']'; cp >= &el->el_search.patbuf[LEN]; cp--) if (*cp == '[' || *cp == ']') { ch = *cp; break; } - if (el->el_search.patlen > LEN && ch != '[') { + if (el->el_search.patlen > LEN && ch != L'[') { if (redo && newdir == dir) { if (pchar == '?') { /* wrap around */ el->el_history.eventno = @@ -381,9 +387,10 @@ ce_inc_search(EditLine *el, int dir) /* avoid c_setpat */ el->el_state.lastcmd = (el_action_t) newdir; - ret = newdir == ED_SEARCH_PREV_HISTORY ? + ret = (el_action_t) + (newdir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : - ed_search_next_history(el, 0); + ed_search_next_history(el, 0)); if (ret != CC_ERROR) { el->el_line.cursor = newdir == ED_SEARCH_PREV_HISTORY ? @@ -397,13 +404,13 @@ ce_inc_search(EditLine *el, int dir) el->el_search.patbuf[el->el_search.patlen] = '\0'; if (ret == CC_ERROR) { - term_beep(el); + terminal_beep(el); if (el->el_history.eventno != ohisteventno) { el->el_history.eventno = ohisteventno; if (hist_get(el) == CC_ERROR) - return (CC_ERROR); + return CC_ERROR; } el->el_line.cursor = ocursor; pchar = '?'; @@ -428,14 +435,14 @@ ce_inc_search(EditLine *el, int dir) if (el->el_history.eventno != ohisteventno) { el->el_history.eventno = ohisteventno; if (hist_get(el) == CC_ERROR) - return (CC_ERROR); + return CC_ERROR; } el->el_line.cursor = ocursor; if (ret == CC_ERROR) re_refresh(el); } if (done || ret != CC_NORM) - return (ret); + return ret; } } @@ -443,12 +450,12 @@ 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]; - int tmplen; + wchar_t ch; + wchar_t tmpbuf[EL_BUFSIZ]; + ssize_t tmplen; #ifdef ANCHOR tmpbuf[0] = '.'; @@ -459,7 +466,7 @@ cv_search(EditLine *el, int dir) el->el_search.patdir = dir; tmplen = c_gets(el, &tmpbuf[LEN], - dir == ED_SEARCH_PREV_HISTORY ? "\n/" : "\n?" ); + dir == ED_SEARCH_PREV_HISTORY ? L"\n/" : L"\n?" ); if (tmplen == -1) return CC_REFRESH; @@ -473,16 +480,16 @@ cv_search(EditLine *el, int dir) */ if (el->el_search.patlen == 0) { re_refresh(el); - return (CC_ERROR); + return CC_ERROR; } #ifdef ANCHOR if (el->el_search.patbuf[0] != '.' && el->el_search.patbuf[0] != '*') { - (void) strncpy(tmpbuf, el->el_search.patbuf, - sizeof(tmpbuf) - 1); + (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++] = '.'; @@ -496,33 +503,33 @@ cv_search(EditLine *el, int dir) tmpbuf[tmplen++] = '*'; #endif tmpbuf[tmplen] = '\0'; - (void) strncpy(el->el_search.patbuf, tmpbuf, EL_BUFSIZ - 1); - el->el_search.patlen = tmplen; + (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 */ el->el_line.cursor = el->el_line.lastchar = el->el_line.buffer; if ((dir == ED_SEARCH_PREV_HISTORY ? ed_search_prev_history(el, 0) : ed_search_next_history(el, 0)) == CC_ERROR) { re_refresh(el); - return (CC_ERROR); + return CC_ERROR; } if (ch == 0033) { re_refresh(el); return ed_newline(el, 0); } - return (CC_REFRESH); + return CC_REFRESH; } /* 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; @@ -537,21 +544,21 @@ ce_search_line(EditLine *el, int dir) if (el_match(cp, ocp)) { *ocp = oc; el->el_line.cursor = cp; - return (CC_NORM); + return CC_NORM; } } *ocp = oc; - return (CC_ERROR); + return CC_ERROR; } else { for (; *cp != '\0' && cp < el->el_line.limit; cp++) { if (el_match(cp, ocp)) { *ocp = oc; el->el_line.cursor = cp; - return (CC_NORM); + return CC_NORM; } } *ocp = oc; - return (CC_ERROR); + return CC_ERROR; } } @@ -559,13 +566,14 @@ ce_search_line(EditLine *el, int dir) /* cv_repeat_srch(): * Vi repeat search */ -protected el_action_t -cv_repeat_srch(EditLine *el, int c) +libedit_private el_action_t +cv_repeat_srch(EditLine *el, wint_t c) { #ifdef SDEBUG - (void) fprintf(el->el_errfile, "dir %d patlen %d patbuf %s\n", - c, el->el_search.patlen, el->el_search.patbuf); + static ct_buffer_t conv; + (void) fprintf(el->el_errfile, "dir %d patlen %ld patbuf %s\n", + c, el->el_search.patlen, ct_encode_string(el->el_search.patbuf, &conv)); #endif el->el_state.lastcmd = (el_action_t) c; /* Hack to stop c_setpat */ @@ -573,11 +581,11 @@ cv_repeat_srch(EditLine *el, int c) switch (c) { case ED_SEARCH_NEXT_HISTORY: - return (ed_search_next_history(el, 0)); + return ed_search_next_history(el, 0); case ED_SEARCH_PREV_HISTORY: - return (ed_search_prev_history(el, 0)); + return ed_search_prev_history(el, 0); default: - return (CC_ERROR); + return CC_ERROR; } } @@ -585,17 +593,17 @@ cv_repeat_srch(EditLine *el, int c) /* cv_csearch(): * Vi character search */ -protected el_action_t -cv_csearch(EditLine *el, int direction, int ch, int count, int tflag) +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 == -1) { - char c; - if (el_getc(el, &c) != 1) + if (ch == (wint_t)-1) { + wchar_t c; + if (el_wgetc(el, &c) != 1) return ed_end_of_file(el, 0); ch = c; } @@ -603,18 +611,18 @@ cv_csearch(EditLine *el, int direction, int ch, int count, int tflag) /* Save for ';' and ',' commands */ el->el_search.chacha = ch; el->el_search.chadir = direction; - el->el_search.chatflg = tflag; + el->el_search.chatflg = (char)tflag; cp = el->el_line.cursor; while (count--) { - if (*cp == ch) + if ((wint_t)*cp == ch) cp += direction; for (;;cp += direction) { if (cp >= el->el_line.lastchar) return CC_ERROR; if (cp < el->el_line.buffer) return CC_ERROR; - if (*cp == ch) + if ((wint_t)*cp == ch) break; } } diff --git a/clt/falcon/editline/src/search.h b/clt/falcon/editline/src/search.h index 2aa8f9850..4ca39c4c0 100644 --- a/clt/falcon/editline/src/search.h +++ b/clt/falcon/editline/src/search.h @@ -1,4 +1,4 @@ -/* $NetBSD: search.h,v 1.8 2003/10/18 23:27:36 christos Exp $ */ +/* $NetBSD: search.h,v 1.14 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,27 +40,25 @@ #ifndef _h_el_search #define _h_el_search -#include "histedit.h" - 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 *, int); -protected el_action_t cv_csearch(EditLine *, int, int, 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 */ diff --git a/clt/falcon/editline/src/shlib_version b/clt/falcon/editline/src/shlib_version new file mode 100644 index 000000000..303609d26 --- /dev/null +++ b/clt/falcon/editline/src/shlib_version @@ -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 diff --git a/clt/falcon/editline/src/sig.c b/clt/falcon/editline/src/sig.c index 1ea319faa..83742a3d6 100644 --- a/clt/falcon/editline/src/sig.c +++ b/clt/falcon/editline/src/sig.c @@ -1,4 +1,4 @@ -/* $NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $ */ +/* $NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)sig.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $"); +__RCSID("$NetBSD: sig.c,v 1.26 2016/05/09 21:46:56 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -46,31 +46,35 @@ __RCSID("$NetBSD: sig.c,v 1.15 2009/02/19 15:20:22 christos Exp $"); * our policy is to trap all signals, set a good state * and pass the ball to our caller. */ -#include "el.h" +#include #include -private EditLine *sel = NULL; +#include "el.h" +#include "common.h" + +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; + int i, save_errno; sigset_t nset, oset; + save_errno = errno; (void) sigemptyset(&nset); (void) sigaddset(&nset, signo); (void) sigprocmask(SIG_BLOCK, &nset, &oset); @@ -82,7 +86,7 @@ sig_handler(int signo) tty_rawmode(sel); if (ed_redisplay(sel, 0) == CC_REFRESH) re_refresh(sel); - term__flush(sel); + terminal__flush(sel); break; case SIGWINCH: @@ -104,13 +108,14 @@ sig_handler(int signo) sigemptyset(&sel->el_signal->sig_action[i].sa_mask); (void) sigprocmask(SIG_SETMASK, &oset, NULL); (void) kill(0, signo); + errno = save_errno; } /* sig_init(): * Initialize all signal stuff */ -protected int +libedit_private int sig_init(EditLine *el) { size_t i; @@ -142,11 +147,11 @@ sig_init(EditLine *el) /* sig_end(): * Clear all signal stuff */ -protected void +libedit_private void sig_end(EditLine *el) { - el_free((ptr_t) el->el_signal); + el_free(el->el_signal); el->el_signal = NULL; } @@ -154,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; @@ -181,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; diff --git a/clt/falcon/editline/src/sig.h b/clt/falcon/editline/src/sig.h index c957cfdf5..5ee453fb6 100644 --- a/clt/falcon/editline/src/sig.h +++ b/clt/falcon/editline/src/sig.h @@ -1,4 +1,4 @@ -/* $NetBSD: sig.h,v 1.8 2009/02/19 15:20:22 christos Exp $ */ +/* $NetBSD: sig.h,v 1.11 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -42,8 +42,6 @@ #include -#include "histedit.h" - /* * Define here all the signals we are going to handle * The _DO macro is used to iterate in the source code @@ -64,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 */ diff --git a/clt/falcon/editline/src/strlcat.c b/clt/falcon/editline/src/strlcat.c index bfacbd34d..2b8098fc0 100644 --- a/clt/falcon/editline/src/strlcat.c +++ b/clt/falcon/editline/src/strlcat.c @@ -1,4 +1,4 @@ -/* $NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $ */ +/* $NetBSD: strlcat.c,v 1.4 2013/01/23 07:57:27 matt Exp $ */ /* $OpenBSD: strlcat.c,v 1.10 2003/04/12 21:56:39 millert Exp $ */ /* @@ -17,10 +17,10 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "config.h" #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: strlcat.c,v 1.3 2007/06/04 18:19:27 christos Exp $"); +__RCSID("$NetBSD: strlcat.c,v 1.4 2013/01/23 07:57:27 matt Exp $"); #endif /* LIBC_SCCS and not lint */ #include @@ -33,7 +33,7 @@ __weak_alias(strlcat, _strlcat) # endif #endif -#if !HAVE_STRLCAT +#ifndef HAVE_STRLCAT /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters @@ -44,6 +44,7 @@ __weak_alias(strlcat, _strlcat) size_t strlcat(char *dst, const char *src, size_t siz) { +#if 1 char *d = dst; const char *s = src; size_t n = siz; @@ -70,5 +71,20 @@ strlcat(char *dst, const char *src, size_t siz) *d = '\0'; return(dlen + (s - src)); /* count does not include NUL */ +#else + _DIAGASSERT(dst != NULL); + _DIAGASSERT(src != NULL); + + /* + * Find length of string in dst (maxing out at siz). + */ + size_t dlen = strnlen(dst, siz); + + /* + * Copy src into any remaining space in dst (truncating if needed). + * Note strlcpy(dst, src, 0) returns strlen(src). + */ + return dlen + strlcpy(dst + dlen, src, siz - dlen); +#endif } #endif diff --git a/clt/falcon/editline/src/strlcpy.c b/clt/falcon/editline/src/strlcpy.c index 154d820eb..c03cad6bb 100644 --- a/clt/falcon/editline/src/strlcpy.c +++ b/clt/falcon/editline/src/strlcpy.c @@ -17,7 +17,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include +#include "config.h" #if defined(LIBC_SCCS) && !defined(lint) __RCSID("$NetBSD: strlcpy.c,v 1.3 2007/06/04 18:19:27 christos Exp $"); @@ -33,7 +33,7 @@ __weak_alias(strlcpy, _strlcpy) # endif #endif -#if !HAVE_STRLCPY +#ifndef HAVE_STRLCPY /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). diff --git a/clt/falcon/editline/src/sys.h b/clt/falcon/editline/src/sys.h index b57b3a952..4dff2fd5d 100644 --- a/clt/falcon/editline/src/sys.h +++ b/clt/falcon/editline/src/sys.h @@ -1,4 +1,4 @@ -/* $NetBSD: sys.h,v 1.12 2009/08/31 00:05:43 christos Exp $ */ +/* $NetBSD: sys.h,v 1.27 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,20 +40,14 @@ #ifndef _h_sys #define _h_sys -#include - -#ifdef HAVE_SYS_CDEFS_H -#include +#if defined(HAVE_SYS_TYPES_H) && defined(__sun) +#include #endif #if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) # define __attribute__(A) #endif -#ifndef __P -# define __P(x) x -#endif - #ifndef _DIAGASSERT # define _DIAGASSERT(x) #endif @@ -67,22 +61,12 @@ # define __END_DECLS # 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 HAVE_U_INT32_T -typedef unsigned int u_int32_t; +#ifndef __arraycount +# define __arraycount(a) (sizeof(a) / sizeof(*(a))) #endif #ifndef _PTR_T @@ -98,18 +82,42 @@ typedef void *ioctl_t; #include #ifndef HAVE_STRLCAT -#define strlcat libedit_strlcat +//#define strlcat libedit_strlcat size_t strlcat(char *dst, const char *src, size_t size); #endif #ifndef HAVE_STRLCPY -#define strlcpy libedit_strlcpy +//#define strlcpy libedit_strlcpy size_t strlcpy(char *dst, const char *src, size_t size); #endif -#ifndef HAVE_FGETLN -#define fgetln libedit_fgetln -char *fgetln(FILE *fp, size_t *len); +#ifndef HAVE_GETLINE +//#define getline libedit_getline +ssize_t getline(char **line, size_t *len, FILE *fp); +#endif + +#ifndef HAVE_REALLOCARR +int reallocarr(void *ptr, size_t number, size_t size); +#endif + +#ifndef HAVE_WCSDUP +wchar_t * wcsdup(const wchar_t *str); +#endif + +#ifndef _DIAGASSERT +#define _DIAGASSERT(x) +#endif + +#ifndef __RCSID +#define __RCSID(x) +#endif + +#ifndef HAVE_U_INT32_T +typedef unsigned int u_int32_t; +#endif + +#ifndef HAVE_SIZE_MAX +#define SIZE_MAX ((size_t)-1) #endif #define REGEX /* Use POSIX.2 regular expression functions */ @@ -124,40 +132,4 @@ extern char* tgoto(const char*, int, int); extern char* tgetstr(char*, char**); #endif -#ifdef notdef -# undef REGEX -# undef REGEXP -# include -# ifdef __GNUC__ -/* - * Broken hdrs. - */ -extern int tgetent(const char *bp, char *name); -extern int tgetflag(const char *id); -extern int tgetnum(const char *id); -extern char *tgetstr(const char *id, char **area); -extern char *tgoto(const char *cap, int col, int row); -extern int tputs(const char *str, int affcnt, int (*putc)(int)); -extern char *getenv(const char *); -extern int fprintf(FILE *, const char *, ...); -extern int sigsetmask(int); -extern int sigblock(int); -extern int fputc(int, FILE *); -extern int fgetc(FILE *); -extern int fflush(FILE *); -extern int tolower(int); -extern int toupper(int); -extern int errno, sys_nerr; -extern char *sys_errlist[]; -extern void perror(const char *); -# include -# define strerror(e) sys_errlist[e] -# endif -# ifdef SABER -extern ptr_t memcpy(ptr_t, const ptr_t, size_t); -extern ptr_t memset(ptr_t, int, size_t); -# endif -extern char *fgetline(FILE *, int *); -#endif - #endif /* _h_sys */ diff --git a/clt/falcon/editline/src/term.c b/clt/falcon/editline/src/terminal.c similarity index 53% rename from clt/falcon/editline/src/term.c rename to clt/falcon/editline/src/terminal.c index 8858d28cf..3bea1fc27 100644 --- a/clt/falcon/editline/src/term.c +++ b/clt/falcon/editline/src/terminal.c @@ -1,4 +1,4 @@ -/* $NetBSD: term.c,v 1.55 2009/08/31 00:05:43 christos Exp $ */ +/* $NetBSD: terminal.c,v 1.44 2021/09/09 20:24:07 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,19 +37,22 @@ #if 0 static char sccsid[] = "@(#)term.c 8.2 (Berkeley) 4/30/95"; #else -__RCSID("$NetBSD: term.c,v 1.55 2009/08/31 00:05:43 christos Exp $"); +__RCSID("$NetBSD: terminal.c,v 1.44 2021/09/09 20:24:07 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* - * term.c: Editor/termcap-curses interface - * We have to declare a static variable here, since the - * termcap putchar routine does not take an argument! + * terminal.c: Editor/termcap-curses interface + * We have to declare a static variable here, since the + * termcap putchar routine does not take an argument! */ -#include +#include +#include +#include #include -#include +#include #include +#include #include #ifdef HAVE_TERMCAP_H #include @@ -59,107 +62,34 @@ __RCSID("$NetBSD: term.c,v 1.55 2009/08/31 00:05:43 christos Exp $"); #elif HAVE_NCURSES_H #include #endif -/* Solaris's term.h does horrid things. */ -#if defined(HAVE_TERM_H) && !defined(__sun) +/* Solaris's term.h does horrid things. */ +#if defined(HAVE_TERM_H) && !defined(__sun) && !defined(HAVE_TERMCAP_H) #include #endif -#include -#include #ifdef _REENTRANT #include #endif #include "el.h" +#include "fcns.h" /* * IMPORTANT NOTE: these routines are allowed to look at the current screen - * and the current possition assuming that it is correct. If this is not + * and the current position assuming that it is correct. If this is not * true, then the update will be WRONG! This is (should be) a valid * assumption... */ -#define TC_BUFSIZE 2048 - -#define GoodStr(a) (el->el_term.t_str[a] != NULL && \ - el->el_term.t_str[a][0] != '\0') -#define Str(a) el->el_term.t_str[a] -#define Val(a) el->el_term.t_val[a] +#define TC_BUFSIZE ((size_t)2048) -#ifdef notdef -private const struct { - const char *b_name; - int b_rate; -} baud_rate[] = { -#ifdef B0 - { "0", B0 }, -#endif -#ifdef B50 - { "50", B50 }, -#endif -#ifdef B75 - { "75", B75 }, -#endif -#ifdef B110 - { "110", B110 }, -#endif -#ifdef B134 - { "134", B134 }, -#endif -#ifdef B150 - { "150", B150 }, -#endif -#ifdef B200 - { "200", B200 }, -#endif -#ifdef B300 - { "300", B300 }, -#endif -#ifdef B600 - { "600", B600 }, -#endif -#ifdef B900 - { "900", B900 }, -#endif -#ifdef B1200 - { "1200", B1200 }, -#endif -#ifdef B1800 - { "1800", B1800 }, -#endif -#ifdef B2400 - { "2400", B2400 }, -#endif -#ifdef B3600 - { "3600", B3600 }, -#endif -#ifdef B4800 - { "4800", B4800 }, -#endif -#ifdef B7200 - { "7200", B7200 }, -#endif -#ifdef B9600 - { "9600", B9600 }, -#endif -#ifdef EXTA - { "19200", EXTA }, -#endif -#ifdef B19200 - { "19200", B19200 }, -#endif -#ifdef EXTB - { "38400", EXTB }, -#endif -#ifdef B38400 - { "38400", B38400 }, -#endif - { NULL, 0 } -}; -#endif +#define GoodStr(a) (el->el_terminal.t_str[a] != NULL && \ + el->el_terminal.t_str[a][0] != '\0') +#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[] = { @@ -239,11 +169,13 @@ private const struct termcapstr { { "kh", "send cursor home" }, #define T_at7 37 { "@7", "send cursor end" }, -#define T_str 38 +#define T_kD 38 + { "kD", "send cursor delete" }, +#define T_str 39 { NULL, NULL } }; -private const struct termcapval { +static const struct termcapval { const char *name; const char *long_name; } tval[] = { @@ -268,27 +200,28 @@ private const struct termcapval { }; /* do two or more of the attributes use me */ -private void term_setflags(EditLine *); -private int term_rebuffer_display(EditLine *); -private void term_free_display(EditLine *); -private int term_alloc_display(EditLine *); -private void term_alloc(EditLine *, const struct termcapstr *, const char *); -private void term_init_arrow(EditLine *); -private void term_reset_arrow(EditLine *); -private int term_putc(int); -private void term_tputs(EditLine *, const char *, int); +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 *); +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 term_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t terminal_mutex = PTHREAD_MUTEX_INITIALIZER; #endif -private FILE *term_outfile = NULL; +static FILE *terminal_outfile = NULL; -/* term_setflags(): +/* terminal_setflags(): * Set the terminal capability flags */ -private void -term_setflags(EditLine *el) +static void +terminal_setflags(EditLine *el) { EL_FLAGS = 0; if (el->el_tty.t_tabs) @@ -329,69 +262,87 @@ term_setflags(EditLine *el) #endif /* DEBUG_SCREEN */ } -/* term_init(): +/* terminal_init(): * Initialize the terminal stuff */ -protected int -term_init(EditLine *el) +libedit_private int +terminal_init(EditLine *el) { - el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE); - if (el->el_term.t_buf == NULL) - return (-1); - el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE); - if (el->el_term.t_cap == NULL) - return (-1); - el->el_term.t_fkey = (fkey_t *) el_malloc(A_K_NKEYS * sizeof(fkey_t)); - if (el->el_term.t_fkey == NULL) - return (-1); - el->el_term.t_loc = 0; - el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char *)); - if (el->el_term.t_str == NULL) - return (-1); - (void) memset(el->el_term.t_str, 0, T_str * sizeof(char *)); - el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int)); - if (el->el_term.t_val == NULL) - return (-1); - (void) memset(el->el_term.t_val, 0, T_val * sizeof(int)); - (void) term_set(el, NULL); - term_init_arrow(el); - return (0); + 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_calloc(TC_BUFSIZE, + sizeof(*el->el_terminal.t_cap)); + if (el->el_terminal.t_cap == NULL) + goto fail2; + 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_calloc(T_str, + sizeof(*el->el_terminal.t_str)); + if (el->el_terminal.t_str == NULL) + goto fail4; + 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) terminal_set(el, NULL); + terminal_init_arrow(el); + return 0; +fail5: + free(el->el_terminal.t_str); + el->el_terminal.t_str = NULL; +fail4: + free(el->el_terminal.t_fkey); + el->el_terminal.t_fkey = NULL; +fail3: + free(el->el_terminal.t_cap); + el->el_terminal.t_cap = NULL; +fail2: + free(el->el_terminal.t_buf); + el->el_terminal.t_buf = NULL; +fail1: + return -1; } -/* term_end(): +/* terminal_end(): * Clean up the terminal stuff */ -protected void -term_end(EditLine *el) +libedit_private void +terminal_end(EditLine *el) { - el_free((ptr_t) el->el_term.t_buf); - el->el_term.t_buf = NULL; - el_free((ptr_t) el->el_term.t_cap); - el->el_term.t_cap = NULL; - el->el_term.t_loc = 0; - el_free((ptr_t) el->el_term.t_str); - el->el_term.t_str = NULL; - el_free((ptr_t) el->el_term.t_val); - el->el_term.t_val = NULL; - el_free((ptr_t) el->el_term.t_fkey); - el->el_term.t_fkey = NULL; - term_free_display(el); + el_free(el->el_terminal.t_buf); + el->el_terminal.t_buf = NULL; + el_free(el->el_terminal.t_cap); + el->el_terminal.t_cap = NULL; + el->el_terminal.t_loc = 0; + el_free(el->el_terminal.t_str); + el->el_terminal.t_str = NULL; + el_free(el->el_terminal.t_val); + el->el_terminal.t_val = NULL; + el_free(el->el_terminal.t_fkey); + el->el_terminal.t_fkey = NULL; + terminal_free_display(el); } -/* term_alloc(): +/* terminal_alloc(): * Maintain a string pool for termcap strings */ -private void -term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) +static void +terminal_alloc(EditLine *el, const struct termcapstr *t, const char *cap) { char termbuf[TC_BUFSIZE]; size_t tlen, clen; - char **tlist = el->el_term.t_str; + char **tlist = el->el_terminal.t_str; char **tmp, **str = &tlist[t - tstr]; + (void) memset(termbuf, 0, sizeof(termbuf)); if (cap == NULL || *cap == '\0') { *str = NULL; return; @@ -411,11 +362,11 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) /* * New string is longer; see if we have enough space to append */ - if (el->el_term.t_loc + 3 < TC_BUFSIZE) { + if (el->el_terminal.t_loc + 3 < TC_BUFSIZE) { /* XXX strcpy is safe */ - (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], - cap); - el->el_term.t_loc += (int)clen + 1; /* one for \0 */ + (void) strcpy(*str = &el->el_terminal.t_buf[ + el->el_terminal.t_loc], cap); + el->el_terminal.t_loc += clen + 1; /* one for \0 */ return; } /* @@ -424,177 +375,162 @@ term_alloc(EditLine *el, const struct termcapstr *t, const char *cap) */ tlen = 0; for (tmp = tlist; tmp < &tlist[T_str]; tmp++) - if (*tmp != NULL && *tmp != '\0' && *tmp != *str) { + if (*tmp != NULL && **tmp != '\0' && *tmp != *str) { char *ptr; for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) continue; termbuf[tlen++] = '\0'; } - memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE); - el->el_term.t_loc = (int)tlen; - if (el->el_term.t_loc + 3 >= TC_BUFSIZE) { + memcpy(el->el_terminal.t_buf, termbuf, TC_BUFSIZE); + el->el_terminal.t_loc = tlen; + if (el->el_terminal.t_loc + 3 >= TC_BUFSIZE) { (void) fprintf(el->el_errfile, "Out of termcap string space.\n"); return; } /* XXX strcpy is safe */ - (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); - el->el_term.t_loc += (int)clen + 1; /* one for \0 */ + (void) strcpy(*str = &el->el_terminal.t_buf[el->el_terminal.t_loc], + cap); + el->el_terminal.t_loc += (size_t)clen + 1; /* one for \0 */ return; } -/* term_rebuffer_display(): +/* terminal_rebuffer_display(): * Rebuffer the display after the screen changed size */ -private int -term_rebuffer_display(EditLine *el) +static int +terminal_rebuffer_display(EditLine *el) { - coord_t *c = &el->el_term.t_size; + coord_t *c = &el->el_terminal.t_size; - term_free_display(el); + terminal_free_display(el); c->h = Val(T_co); c->v = Val(T_li); - if (term_alloc_display(el) == -1) - return (-1); - return (0); + if (terminal_alloc_display(el) == -1) + return -1; + return 0; } - -/* term_alloc_display(): - * Allocate a new display. - */ -private int -term_alloc_display(EditLine *el) +static wint_t ** +terminal_alloc_buffer(EditLine *el) { + wint_t **b; + coord_t *c = &el->el_terminal.t_size; int i; - char **b; - coord_t *c = &el->el_term.t_size; - b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); + b = el_calloc((size_t)(c->v + 1), sizeof(*b)); if (b == NULL) - return (-1); + return NULL; for (i = 0; i < c->v; i++) { - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); + b[i] = el_calloc((size_t)(c->h + 1), sizeof(**b)); if (b[i] == NULL) { while (--i >= 0) - el_free((ptr_t) b[i]); - el_free((ptr_t) b); - return (-1); + el_free(b[i]); + el_free(b); + return NULL; } } b[c->v] = NULL; - el->el_display = b; + return b; +} - b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); - if (b == NULL) - return (-1); - for (i = 0; i < c->v; i++) { - b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); - if (b[i] == NULL) { - while (--i >= 0) - el_free((ptr_t) b[i]); - el_free((ptr_t) b); - return (-1); - } - } - b[c->v] = NULL; - el->el_vdisplay = b; - return (0); +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. + */ +static int +terminal_alloc_display(EditLine *el) +{ + el->el_display = terminal_alloc_buffer(el); + if (el->el_display == NULL) + goto done; + el->el_vdisplay = terminal_alloc_buffer(el); + if (el->el_vdisplay == NULL) + goto done; + return 0; +done: + terminal_free_display(el); + return -1; +} -/* term_free_display(): + +/* terminal_free_display(): * Free the display buffers */ -private void -term_free_display(EditLine *el) +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((ptr_t) * bufp); - el_free((ptr_t) b); - } - b = el->el_vdisplay; - el->el_vdisplay = NULL; - if (b != NULL) { - for (bufp = b; *bufp != NULL; bufp++) - el_free((ptr_t) * bufp); - el_free((ptr_t) b); - } + terminal_free_buffer(&el->el_display); + terminal_free_buffer(&el->el_vdisplay); } -/* term_move_to_line(): +/* terminal_move_to_line(): * move to line (first line == 0) - * as efficiently as possible + * as efficiently as possible */ -protected void -term_move_to_line(EditLine *el, int where) +libedit_private void +terminal_move_to_line(EditLine *el, int where) { int del; if (where == el->el_cursor.v) return; - if (where > el->el_term.t_size.v) { + if (where >= el->el_terminal.t_size.v) { #ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, - "term_move_to_line: where is ridiculous: %d\r\n", where); + "%s: where is ridiculous: %d\r\n", __func__, where); #endif /* DEBUG_SCREEN */ 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') { - /* move without newline */ - term_move_to_char(el, el->el_term.t_size.h - 1); - term_overwrite(el, &el->el_display - [el->el_cursor.v][el->el_cursor.h], - (size_t)(el->el_term.t_size.h - - el->el_cursor.h)); - /* updates Cursor */ - del--; - } else { - if ((del > 1) && GoodStr(T_DO)) { - term_tputs(el, tgoto(Str(T_DO), del, - del), del); - del = 0; - } else { - for (; del > 0; del--) - term__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))) - term_tputs(el, tgoto(Str(T_UP), -del, -del), -del); + terminal_tputs(el, tgoto(Str(T_UP), -del, -del), -del); else { if (GoodStr(T_up)) for (; del < 0; del++) - term_tputs(el, Str(T_up), 1); + terminal_tputs(el, Str(T_up), 1); } } el->el_cursor.v = where;/* now where is here */ } -/* term_move_to_char(): +/* terminal_move_to_char(): * Move to the character position specified */ -protected void -term_move_to_char(EditLine *el, int where) +libedit_private void +terminal_move_to_char(EditLine *el, int where) { int del, i; @@ -602,15 +538,15 @@ term_move_to_char(EditLine *el, int where) if (where == el->el_cursor.h) return; - if (where > el->el_term.t_size.h) { + if (where > el->el_terminal.t_size.h) { #ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, - "term_move_to_char: where is riduculous: %d\r\n", where); + "%s: where is ridiculous: %d\r\n", __func__, where); #endif /* DEBUG_SCREEN */ return; } if (!where) { /* if where is first column */ - term__putc(el, '\r'); /* do a CR */ + terminal__putc(el, '\r'); /* do a CR */ el->el_cursor.h = 0; return; } @@ -618,24 +554,30 @@ term_move_to_char(EditLine *el, int where) if ((del < -4 || del > 4) && GoodStr(T_ch)) /* go there directly */ - term_tputs(el, tgoto(Str(T_ch), where, where), where); + terminal_tputs(el, tgoto(Str(T_ch), where, where), where); else { if (del > 0) { /* moving forward */ if ((del > 4) && GoodStr(T_RI)) - term_tputs(el, tgoto(Str(T_RI), del, del), del); + terminal_tputs(el, tgoto(Str(T_RI), del, del), + del); else { /* if I can do tabs, use them */ if (EL_CAN_TAB) { if ((el->el_cursor.h & 0370) != - (where & 0370)) { + (where & ~0x7) + && (el->el_display[ + el->el_cursor.v][where & 0370] != + MB_FILL_CHAR) + ) { /* if not within tab stop */ for (i = (el->el_cursor.h & 0370); - i < (where & 0370); + i < (where & ~0x7); i += 8) - term__putc(el, '\t'); + terminal__putc(el, + '\t'); /* then tab over */ - el->el_cursor.h = where & 0370; + el->el_cursor.h = where & ~0x7; } } /* @@ -643,17 +585,18 @@ term_move_to_char(EditLine *el, int where) * chars, so we do. */ /* - * NOTE THAT term_overwrite() WILL CHANGE + * NOTE THAT terminal_overwrite() WILL CHANGE * el->el_cursor.h!!! */ - term_overwrite(el, - &el->el_display[el->el_cursor.v][el->el_cursor.h], + terminal_overwrite(el, + (wchar_t *)&el->el_display[ + el->el_cursor.v][el->el_cursor.h], (size_t)(where - el->el_cursor.h)); } } else { /* del < 0 := moving backward */ if ((-del > 4) && GoodStr(T_LE)) - term_tputs(el, tgoto(Str(T_LE), -del, -del), + terminal_tputs(el, tgoto(Str(T_LE), -del, -del), -del); else { /* can't go directly there */ /* @@ -665,12 +608,12 @@ term_move_to_char(EditLine *el, int where) (((unsigned int) where >> 3) + (where & 07))) : (-del > where)) { - term__putc(el, '\r'); /* do a CR */ + terminal__putc(el, '\r');/* do a CR */ el->el_cursor.h = 0; goto mc_again; /* and try again */ } for (i = 0; i < -del; i++) - term__putc(el, '\b'); + terminal__putc(el, '\b'); } } } @@ -678,54 +621,61 @@ term_move_to_char(EditLine *el, int where) } -/* term_overwrite(): +/* terminal_overwrite(): * Overstrike num characters + * Assumes MB_FILL_CHARs are present to keep the column count correct */ -protected void -term_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; - if (n > (size_t)el->el_term.t_size.h) { + if (n > (size_t)el->el_terminal.t_size.h) { #ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, - "term_overwrite: n is riduculous: %d\r\n", n); + "%s: n is ridiculous: %zu\r\n", __func__, n); #endif /* DEBUG_SCREEN */ return; } - do { - term__putc(el, *cp++); - el->el_cursor.h++; - } while (--n); + do { + /* terminal__putc() ignores any MB_FILL_CHARs */ + terminal__putc(el, *cp++); + el->el_cursor.h++; + } while (--n); - if (el->el_cursor.h >= el->el_term.t_size.h) { /* wrap? */ + if (el->el_cursor.h >= el->el_terminal.t_size.h) { /* wrap? */ if (EL_HAS_AUTO_MARGINS) { /* yes */ el->el_cursor.h = 0; - el->el_cursor.v++; + if (el->el_cursor.v + 1 < el->el_terminal.t_size.v) + el->el_cursor.v++; if (EL_HAS_MAGIC_MARGINS) { /* force the wrap to avoid the "magic" * situation */ - char c; - if ((c = el->el_display[el->el_cursor.v][el->el_cursor.h]) - != '\0') - term_overwrite(el, &c, 1); - else - term__putc(el, ' '); - el->el_cursor.h = 1; + wchar_t c; + if ((c = el->el_display[el->el_cursor.v] + [el->el_cursor.h]) != '\0') { + terminal_overwrite(el, &c, (size_t)1); + while (el->el_display[el->el_cursor.v] + [el->el_cursor.h] == MB_FILL_CHAR) + el->el_cursor.h++; + } else { + terminal__putc(el, ' '); + el->el_cursor.h = 1; + } } } else /* no wrap, but cursor stays on screen */ - el->el_cursor.h = el->el_term.t_size.h - 1; + el->el_cursor.h = el->el_terminal.t_size.h - 1; } } -/* term_deletechars(): +/* terminal_deletechars(): * Delete num characters */ -protected void -term_deletechars(EditLine *el, int num) +libedit_private void +terminal_deletechars(EditLine *el, int num) { if (num <= 0) return; @@ -736,37 +686,38 @@ term_deletechars(EditLine *el, int num) #endif /* DEBUG_EDIT */ return; } - if (num > el->el_term.t_size.h) { + if (num > el->el_terminal.t_size.h) { #ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, - "term_deletechars: num is riduculous: %d\r\n", num); + "%s: num is ridiculous: %d\r\n", __func__, num); #endif /* DEBUG_SCREEN */ return; } if (GoodStr(T_DC)) /* if I have multiple delete */ if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more * expen. */ - term_tputs(el, tgoto(Str(T_DC), num, num), num); + terminal_tputs(el, tgoto(Str(T_DC), num, num), num); return; } if (GoodStr(T_dm)) /* if I have delete mode */ - term_tputs(el, Str(T_dm), 1); + terminal_tputs(el, Str(T_dm), 1); if (GoodStr(T_dc)) /* else do one at a time */ while (num--) - term_tputs(el, Str(T_dc), 1); + terminal_tputs(el, Str(T_dc), 1); if (GoodStr(T_ed)) /* if I have delete mode */ - term_tputs(el, Str(T_ed), 1); + terminal_tputs(el, Str(T_ed), 1); } -/* term_insertwrite(): +/* terminal_insertwrite(): * Puts terminal in insert character mode or inserts num * characters in the line + * Assumes MB_FILL_CHARs are present to keep column count correct */ -protected void -term_insertwrite(EditLine *el, char *cp, int num) +libedit_private void +terminal_insertwrite(EditLine *el, wchar_t *cp, int num) { if (num <= 0) return; @@ -776,130 +727,116 @@ term_insertwrite(EditLine *el, char *cp, int num) #endif /* DEBUG_EDIT */ return; } - if (num > el->el_term.t_size.h) { + if (num > el->el_terminal.t_size.h) { #ifdef DEBUG_SCREEN (void) fprintf(el->el_errfile, - "StartInsert: num is riduculous: %d\r\n", num); + "%s: num is ridiculous: %d\r\n", __func__, num); #endif /* DEBUG_SCREEN */ return; } if (GoodStr(T_IC)) /* if I have multiple insert */ if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expensive */ - term_tputs(el, tgoto(Str(T_IC), num, num), num); - term_overwrite(el, cp, (size_t)num); + terminal_tputs(el, tgoto(Str(T_IC), num, num), num); + terminal_overwrite(el, cp, (size_t)num); /* this updates el_cursor.h */ return; } if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ - term_tputs(el, Str(T_im), 1); + terminal_tputs(el, Str(T_im), 1); el->el_cursor.h += num; do - term__putc(el, *cp++); + terminal__putc(el, *cp++); while (--num); if (GoodStr(T_ip)) /* have to make num chars insert */ - term_tputs(el, Str(T_ip), 1); + terminal_tputs(el, Str(T_ip), 1); - term_tputs(el, Str(T_ei), 1); + terminal_tputs(el, Str(T_ei), 1); return; } do { if (GoodStr(T_ic)) /* have to make num chars insert */ - term_tputs(el, Str(T_ic), 1); + terminal_tputs(el, Str(T_ic), 1); - term__putc(el, *cp++); + terminal__putc(el, *cp++); el->el_cursor.h++; if (GoodStr(T_ip)) /* have to make num chars insert */ - term_tputs(el, Str(T_ip), 1); + terminal_tputs(el, Str(T_ip), 1); /* pad the inserted char */ } while (--num); } -/* term_clear_EOL(): +/* terminal_clear_EOL(): * clear to end of line. There are num characters to clear */ -protected void -term_clear_EOL(EditLine *el, int num) +libedit_private void +terminal_clear_EOL(EditLine *el, int num) { int i; if (EL_CAN_CEOL && GoodStr(T_ce)) - term_tputs(el, Str(T_ce), 1); + terminal_tputs(el, Str(T_ce), 1); else { for (i = 0; i < num; i++) - term__putc(el, ' '); + terminal__putc(el, ' '); el->el_cursor.h += num; /* have written num spaces */ } } -/* term_clear_screen(): +/* terminal_clear_screen(): * Clear the screen */ -protected void -term_clear_screen(EditLine *el) +libedit_private void +terminal_clear_screen(EditLine *el) { /* clear the whole screen and home */ if (GoodStr(T_cl)) /* send the clear screen code */ - term_tputs(el, Str(T_cl), Val(T_li)); + terminal_tputs(el, Str(T_cl), Val(T_li)); else if (GoodStr(T_ho) && GoodStr(T_cd)) { - term_tputs(el, Str(T_ho), Val(T_li)); /* home */ + terminal_tputs(el, Str(T_ho), Val(T_li)); /* home */ /* clear to bottom of screen */ - term_tputs(el, Str(T_cd), Val(T_li)); + terminal_tputs(el, Str(T_cd), Val(T_li)); } else { - term__putc(el, '\r'); - term__putc(el, '\n'); + terminal__putc(el, '\r'); + terminal__putc(el, '\n'); } } -/* term_beep(): +/* terminal_beep(): * Beep the way the terminal wants us */ -protected void -term_beep(EditLine *el) +libedit_private void +terminal_beep(EditLine *el) { if (GoodStr(T_bl)) /* what termcap says we should use */ - term_tputs(el, Str(T_bl), 1); + terminal_tputs(el, Str(T_bl), 1); else - term__putc(el, '\007'); /* an ASCII bell; ^G */ + terminal__putc(el, '\007'); /* an ASCII bell; ^G */ } -#ifdef notdef -/* term_clear_to_bottom(): - * Clear to the bottom of the screen - */ -protected void -term_clear_to_bottom(EditLine *el) +libedit_private void +terminal_get(EditLine *el, const char **term) { - if (GoodStr(T_cd)) - term_tputs(el, Str(T_cd), Val(T_li)); - else if (GoodStr(T_ce)) - term_tputs(el, Str(T_ce), Val(T_li)); -} -#endif - -protected void -term_get(EditLine *el, const char **term) -{ - *term = el->el_term.t_name; + *term = el->el_terminal.t_name; } -/* term_set(): +/* terminal_set(): * Read in the terminal capabilities from the requested terminal */ -protected int -term_set(EditLine *el, const char *term) +libedit_private int +terminal_set(EditLine *el, const char *term) { int i; char buf[TC_BUFSIZE]; @@ -924,9 +861,9 @@ term_set(EditLine *el, const char *term) if (strcmp(term, "emacs") == 0) el->el_flags |= EDIT_DISABLED; - memset(el->el_term.t_cap, 0, TC_BUFSIZE); + (void) memset(el->el_terminal.t_cap, 0, TC_BUFSIZE); - i = tgetent(el->el_term.t_cap, term); + i = tgetent(el->el_terminal.t_cap, term); if (i <= 0) { if (i == -1) @@ -941,7 +878,7 @@ term_set(EditLine *el, const char *term) Val(T_pt) = Val(T_km) = Val(T_li) = 0; Val(T_xt) = Val(T_MT); for (t = tstr; t->name != NULL; t++) - term_alloc(el, t, NULL); + terminal_alloc(el, t, NULL); } else { /* auto/magic margins */ Val(T_am) = tgetflag("am"); @@ -957,7 +894,7 @@ term_set(EditLine *el, const char *term) Val(T_li) = tgetnum("li"); for (t = tstr; t->name != NULL; t++) { /* XXX: some systems' tgetstr needs non const */ - term_alloc(el, t, tgetstr(strchr(t->name, *t->name), + terminal_alloc(el, t, tgetstr(strchr(t->name, *t->name), &area)); } } @@ -967,28 +904,28 @@ term_set(EditLine *el, const char *term) if (Val(T_li) < 1) Val(T_li) = 24; - el->el_term.t_size.v = Val(T_co); - el->el_term.t_size.h = Val(T_li); + el->el_terminal.t_size.v = Val(T_co); + el->el_terminal.t_size.h = Val(T_li); - term_setflags(el); + terminal_setflags(el); /* get the correct window size */ - (void) term_get_size(el, &lins, &cols); - if (term_change_size(el, lins, cols) == -1) - return (-1); + (void) terminal_get_size(el, &lins, &cols); + if (terminal_change_size(el, lins, cols) == -1) + return -1; (void) sigprocmask(SIG_SETMASK, &oset, NULL); - term_bind_arrow(el); - el->el_term.t_name = term; - return (i <= 0 ? -1 : 0); + terminal_bind_arrow(el); + el->el_terminal.t_name = term; + return i <= 0 ? -1 : 0; } -/* term_get_size(): +/* terminal_get_size(): * Return the new window size in lines and cols, and * true if the size was changed. */ -protected int -term_get_size(EditLine *el, int *lins, int *cols) +libedit_private int +terminal_get_size(EditLine *el, int *lins, int *cols) { *cols = Val(T_co); @@ -997,7 +934,7 @@ term_get_size(EditLine *el, int *lins, int *cols) #ifdef TIOCGWINSZ { struct winsize ws; - if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) & ws) != -1) { + if (ioctl(el->el_infd, TIOCGWINSZ, &ws) != -1) { if (ws.ws_col) *cols = ws.ws_col; if (ws.ws_row) @@ -1008,7 +945,7 @@ term_get_size(EditLine *el, int *lins, int *cols) #ifdef TIOCGSIZE { struct ttysize ts; - if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) & ts) != -1) { + if (ioctl(el->el_infd, TIOCGSIZE, &ts) != -1) { if (ts.ts_cols) *cols = ts.ts_cols; if (ts.ts_lines) @@ -1016,300 +953,326 @@ term_get_size(EditLine *el, int *lins, int *cols) } } #endif - return (Val(T_co) != *cols || Val(T_li) != *lins); + return Val(T_co) != *cols || Val(T_li) != *lins; } -/* term_change_size(): +/* terminal_change_size(): * Change the size of the terminal */ -protected int -term_change_size(EditLine *el, int lins, int cols) +libedit_private int +terminal_change_size(EditLine *el, int lins, int cols) { + coord_t cur = el->el_cursor; /* - * Just in case - */ + * Just in case + */ Val(T_co) = (cols < 2) ? 80 : cols; Val(T_li) = (lins < 1) ? 24 : lins; /* re-make display buffers */ - if (term_rebuffer_display(el) == -1) - return (-1); + if (terminal_rebuffer_display(el) == -1) + return -1; re_clear_display(el); - return (0); + el->el_cursor = cur; + return 0; } -/* term_init_arrow(): +/* terminal_init_arrow(): * Initialize the arrow key bindings from termcap */ -private void -term_init_arrow(EditLine *el) +static void +terminal_init_arrow(EditLine *el) { - fkey_t *arrow = el->el_term.t_fkey; + funckey_t *arrow = el->el_terminal.t_fkey; - arrow[A_K_DN].name = "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 = "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 = "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 = "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 = "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 = "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 = 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; } -/* term_reset_arrow(): +/* terminal_reset_arrow(): * Reset arrow key bindings */ -private void -term_reset_arrow(EditLine *el) +static void +terminal_reset_arrow(EditLine *el) { - fkey_t *arrow = el->el_term.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'}; - - key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); - key_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); - key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); - key_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); - - if (el->el_map.type == MAP_VI) { - key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); - key_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); - key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); - key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); - key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); - key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); - key_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); - key_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); - } + funckey_t *arrow = el->el_terminal.t_fkey; + 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); + keymacro_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); + keymacro_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); + keymacro_add(el, strH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); + keymacro_add(el, strF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); + keymacro_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); + keymacro_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); + keymacro_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); + keymacro_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); + keymacro_add(el, stOH, &arrow[A_K_HO].fun, arrow[A_K_HO].type); + keymacro_add(el, stOF, &arrow[A_K_EN].fun, arrow[A_K_EN].type); + + if (el->el_map.type != MAP_VI) + return; + keymacro_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); + keymacro_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); + keymacro_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); + keymacro_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); + keymacro_add(el, &strH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); + keymacro_add(el, &strF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); + keymacro_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); + keymacro_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); + keymacro_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); + keymacro_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); + keymacro_add(el, &stOH[1], &arrow[A_K_HO].fun, arrow[A_K_HO].type); + keymacro_add(el, &stOF[1], &arrow[A_K_EN].fun, arrow[A_K_EN].type); } -/* term_set_arrow(): +/* terminal_set_arrow(): * Set an arrow key binding */ -protected int -term_set_arrow(EditLine *el, const char *name, key_value_t *fun, int type) +libedit_private int +terminal_set_arrow(EditLine *el, const wchar_t *name, keymacro_value_t *fun, + int type) { - fkey_t *arrow = el->el_term.t_fkey; + 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); + return 0; } - return (-1); + return -1; } -/* term_clear_arrow(): +/* terminal_clear_arrow(): * Clear an arrow key binding */ -protected int -term_clear_arrow(EditLine *el, const char *name) +libedit_private int +terminal_clear_arrow(EditLine *el, const wchar_t *name) { - fkey_t *arrow = el->el_term.t_fkey; + 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); + return 0; } - return (-1); + return -1; } -/* term_print_arrow(): +/* terminal_print_arrow(): * Print the arrow key bindings */ -protected void -term_print_arrow(EditLine *el, const char *name) +libedit_private void +terminal_print_arrow(EditLine *el, const wchar_t *name) { int i; - fkey_t *arrow = el->el_term.t_fkey; + 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) - key_kprint(el, arrow[i].name, &arrow[i].fun, - arrow[i].type); + keymacro_kprint(el, arrow[i].name, + &arrow[i].fun, arrow[i].type); } -/* term_bind_arrow(): +/* terminal_bind_arrow(): * Bind the arrow keys */ -protected void -term_bind_arrow(EditLine *el) +libedit_private void +terminal_bind_arrow(EditLine *el) { el_action_t *map; const el_action_t *dmap; int i, j; char *p; - fkey_t *arrow = el->el_term.t_fkey; + funckey_t *arrow = el->el_terminal.t_fkey; /* Check if the components needed are initialized */ - if (el->el_term.t_buf == NULL || el->el_map.key == NULL) + if (el->el_terminal.t_buf == NULL || el->el_map.key == NULL) return; map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key; dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs; - term_reset_arrow(el); + terminal_reset_arrow(el); for (i = 0; i < A_K_NKEYS; i++) { - p = el->el_term.t_str[arrow[i].key]; - if (p && *p) { - j = (unsigned char) *p; - /* - * Assign the arrow keys only if: - * - * 1. They are multi-character arrow keys and the user - * has not re-assigned the leading character, or - * has re-assigned the leading character to be - * ED_SEQUENCE_LEAD_IN - * 2. They are single arrow keys pointing to an - * unassigned key. - */ - if (arrow[i].type == XK_NOD) - key_clear(el, map, p); - else { - if (p[1] && (dmap[j] == map[j] || - map[j] == ED_SEQUENCE_LEAD_IN)) { - key_add(el, p, &arrow[i].fun, + wchar_t wt_str[VISUAL_WIDTH_MAX]; + wchar_t *px; + size_t n; + + p = el->el_terminal.t_str[arrow[i].key]; + if (!p || !*p) + continue; + for (n = 0; n < VISUAL_WIDTH_MAX && p[n]; ++n) + wt_str[n] = p[n]; + while (n < VISUAL_WIDTH_MAX) + wt_str[n++] = '\0'; + px = wt_str; + j = (unsigned char) *p; + /* + * Assign the arrow keys only if: + * + * 1. They are multi-character arrow keys and the user + * has not re-assigned the leading character, or + * has re-assigned the leading character to be + * ED_SEQUENCE_LEAD_IN + * 2. They are single arrow keys pointing to an + * unassigned key. + */ + if (arrow[i].type == XK_NOD) + keymacro_clear(el, map, px); + else { + if (p[1] && (dmap[j] == map[j] || + map[j] == ED_SEQUENCE_LEAD_IN)) { + keymacro_add(el, px, &arrow[i].fun, + arrow[i].type); + map[j] = ED_SEQUENCE_LEAD_IN; + } else if (map[j] == ED_UNASSIGNED) { + keymacro_clear(el, map, px); + if (arrow[i].type == XK_CMD) + map[j] = arrow[i].fun.cmd; + else + keymacro_add(el, px, &arrow[i].fun, arrow[i].type); - map[j] = ED_SEQUENCE_LEAD_IN; - } else if (map[j] == ED_UNASSIGNED) { - key_clear(el, map, p); - if (arrow[i].type == XK_CMD) - map[j] = arrow[i].fun.cmd; - else - key_add(el, p, &arrow[i].fun, - arrow[i].type); - } } } } } -/* term_putc(): +/* terminal_putc(): * Add a character */ -private int -term_putc(int c) +static int +terminal_putc(int c) { - - if (term_outfile == NULL) + if (terminal_outfile == NULL) return -1; - return fputc(c, term_outfile); + return fputc(c, terminal_outfile); } -private void -term_tputs(EditLine *el, const char *cap, int affcnt) +static void +terminal_tputs(EditLine *el, const char *cap, int affcnt) { #ifdef _REENTRANT - pthread_mutex_lock(&term_mutex); + pthread_mutex_lock(&terminal_mutex); #endif - term_outfile = el->el_outfile; - (void)tputs(cap, affcnt, term_putc); + terminal_outfile = el->el_outfile; + (void)tputs(cap, affcnt, terminal_putc); #ifdef _REENTRANT - pthread_mutex_unlock(&term_mutex); + pthread_mutex_unlock(&terminal_mutex); #endif } -/* term__putc(): +/* terminal__putc(): * Add a character */ -protected int -term__putc(EditLine *el, int c) +libedit_private int +terminal__putc(EditLine *el, wint_t c) { - - return fputc(c, el->el_outfile); + char buf[MB_LEN_MAX +1]; + ssize_t i; + if (c == MB_FILL_CHAR) + return 0; + 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'; + return fputs(buf, el->el_outfile); } -/* term__flush(): +/* terminal__flush(): * Flush output */ -protected void -term__flush(EditLine *el) +libedit_private void +terminal__flush(EditLine *el) { (void) fflush(el->el_outfile); } -/* term_writec(): +/* terminal_writec(): * Write the given character out, in a human readable form */ -protected void -term_writec(EditLine *el, int c) +libedit_private void +terminal_writec(EditLine *el, wint_t c) { - char buf[8]; - size_t cnt = key__decode_char(buf, sizeof(buf), 0, c); - buf[cnt] = '\0'; - term_overwrite(el, buf, (size_t)cnt); - term__flush(el); + 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'; + terminal_overwrite(el, visbuf, (size_t)vcnt); + terminal__flush(el); } -/* term_telltc(): +/* terminal_telltc(): * Print the current termcap characteristics */ -protected int +libedit_private int /*ARGSUSED*/ -term_telltc(EditLine *el, int argc __attribute__((__unused__)), - const char **argv __attribute__((__unused__))) +terminal_telltc(EditLine *el, int argc __attribute__((__unused__)), + const wchar_t **argv __attribute__((__unused__))) { const struct termcapstr *t; char **ts; - char upbuf[EL_BUFSIZ]; (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n"); (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n"); @@ -1325,39 +1288,42 @@ term_telltc(EditLine *el, int argc __attribute__((__unused__)), (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", EL_HAS_MAGIC_MARGINS ? "has" : "does not have"); - for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) { + for (t = tstr, ts = el->el_terminal.t_str; t->name != NULL; t++, ts++) { const char *ub; if (*ts && **ts) { - (void) key__decode_str(*ts, upbuf, sizeof(upbuf), ""); - ub = upbuf; + ub = ct_encode_string(ct_visual_string( + ct_decode_string(*ts, &el->el_scratch), + &el->el_visual), &el->el_scratch); } else { - ub = "(empty)"; + ub = "(empty)"; } (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name, t->name, ub); } (void) fputc('\n', el->el_outfile); - return (0); + return 0; } -/* term_settc(): +/* terminal_settc(): * Change the current terminal characteristics */ -protected int +libedit_private int /*ARGSUSED*/ -term_settc(EditLine *el, int argc __attribute__((__unused__)), - const char **argv) +terminal_settc(EditLine *el, int argc __attribute__((__unused__)), + const wchar_t **argv) { const struct termcapstr *ts; const struct termcapval *tv; - const char *what, *how; + char what[8], how[8]; + long i; + char *ep; if (argv == NULL || argv[1] == NULL || argv[2] == NULL) return -1; - what = argv[1]; - how = argv[2]; + strlcpy(what, ct_encode_string(argv[1], &el->el_scratch), sizeof(what)); + strlcpy(how, ct_encode_string(argv[2], &el->el_scratch), sizeof(how)); /* * Do the strings first @@ -1367,8 +1333,8 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), break; if (ts->name != NULL) { - term_alloc(el, ts, how); - term_setflags(el); + terminal_alloc(el, ts, how); + terminal_setflags(el); return 0; } /* @@ -1378,52 +1344,60 @@ term_settc(EditLine *el, int argc __attribute__((__unused__)), if (strcmp(tv->name, what) == 0) break; - if (tv->name != NULL) + if (tv->name == NULL) { + (void) fprintf(el->el_errfile, + "%ls: Bad capability `%s'.\n", argv[0], what); return -1; + } if (tv == &tval[T_pt] || tv == &tval[T_km] || tv == &tval[T_am] || tv == &tval[T_xn]) { + /* + * Booleans + */ if (strcmp(how, "yes") == 0) - el->el_term.t_val[tv - tval] = 1; + el->el_terminal.t_val[tv - tval] = 1; else if (strcmp(how, "no") == 0) - el->el_term.t_val[tv - tval] = 0; + el->el_terminal.t_val[tv - tval] = 0; else { (void) fprintf(el->el_errfile, - "%s: Bad value `%s'.\n", argv[0], how); + "%ls: Bad value `%s'.\n", argv[0], how); return -1; } - term_setflags(el); - if (term_change_size(el, Val(T_li), Val(T_co)) == -1) - return -1; + terminal_setflags(el); return 0; - } else { - long i; - char *ep; + } - i = strtol(how, &ep, 10); - if (*ep != '\0') { - (void) fprintf(el->el_errfile, - "%s: Bad value `%s'.\n", argv[0], how); - return -1; - } - el->el_term.t_val[tv - tval] = (int) i; - el->el_term.t_size.v = Val(T_co); - el->el_term.t_size.h = Val(T_li); - if (tv == &tval[T_co] || tv == &tval[T_li]) - if (term_change_size(el, Val(T_li), Val(T_co)) - == -1) - return -1; - return 0; + /* + * Numerics + */ + i = strtol(how, &ep, 10); + if (*ep != '\0') { + (void) fprintf(el->el_errfile, + "%ls: Bad value `%s'.\n", argv[0], how); + return -1; } + el->el_terminal.t_val[tv - tval] = (int) i; + i = 0; + if (tv == &tval[T_co]) { + el->el_terminal.t_size.v = Val(T_co); + i++; + } else if (tv == &tval[T_li]) { + el->el_terminal.t_size.h = Val(T_li); + i++; + } + if (i && terminal_change_size(el, Val(T_li), Val(T_co)) == -1) + return -1; + return 0; } -/* term_gettc(): +/* terminal_gettc(): * Get the current terminal characteristics */ -protected int +libedit_private int /*ARGSUSED*/ -term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) +terminal_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) { const struct termcapstr *ts; const struct termcapval *tv; @@ -1431,7 +1405,7 @@ term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) void *how; if (argv == NULL || argv[1] == NULL || argv[2] == NULL) - return (-1); + return -1; what = argv[1]; how = argv[2]; @@ -1444,7 +1418,7 @@ term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) break; if (ts->name != NULL) { - *(char **)how = el->el_term.t_str[ts - tstr]; + *(char **)how = el->el_terminal.t_str[ts - tstr]; return 0; } /* @@ -1461,26 +1435,27 @@ term_gettc(EditLine *el, int argc __attribute__((__unused__)), char **argv) tv == &tval[T_am] || tv == &tval[T_xn]) { static char yes[] = "yes"; static char no[] = "no"; - if (el->el_term.t_val[tv - tval]) + if (el->el_terminal.t_val[tv - tval]) *(char **)how = yes; else *(char **)how = no; return 0; } else { - *(int *)how = el->el_term.t_val[tv - tval]; + *(int *)how = el->el_terminal.t_val[tv - tval]; return 0; } } -/* term_echotc(): +/* terminal_echotc(): * Print the termcap string out with variable substitution */ -protected int +libedit_private int /*ARGSUSED*/ -term_echotc(EditLine *el, int argc __attribute__((__unused__)), - const char **argv) +terminal_echotc(EditLine *el, int argc __attribute__((__unused__)), + const wchar_t **argv) { - char *cap, *scap, *ep; + char *cap, *scap; + wchar_t *ep; int arg_need, arg_cols, arg_rows; int verbose = 0, silent = 0; char *area; @@ -1492,7 +1467,7 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), area = buf; if (argv == NULL || argv[1] == NULL) - return (-1); + return -1; argv++; if (argv[0][0] == '-') { @@ -1510,62 +1485,52 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), argv++; } if (!*argv || *argv[0] == '\0') - return (0); - if (strcmp(*argv, "tabs") == 0) { + return 0; + if (wcscmp(*argv, L"tabs") == 0) { (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); - return (0); - } else if (strcmp(*argv, "meta") == 0) { + return 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, "xn") == 0) { + return 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, "am") == 0) { + return 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, "baud") == 0) { -#ifdef notdef - int i; - - for (i = 0; baud_rate[i].b_name != NULL; i++) - if (el->el_tty.t_speed == baud_rate[i].b_rate) { - (void) fprintf(el->el_outfile, fmts, - baud_rate[i].b_name); - return (0); - } - (void) fprintf(el->el_outfile, fmtd, 0); -#else + return 0; + } else if (wcscmp(*argv, L"baud") == 0) { (void) fprintf(el->el_outfile, fmtd, (int)el->el_tty.t_speed); -#endif - return (0); - } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { + return 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, "cols") == 0) { + return 0; + } else if (wcscmp(*argv, L"cols") == 0) { (void) fprintf(el->el_outfile, fmtd, Val(T_co)); - return (0); + return 0; } /* * Try to use our local definition first */ scap = NULL; for (t = tstr; t->name != NULL; t++) - if (strcmp(t->name, *argv) == 0) { - scap = el->el_term.t_str[t - tstr]; + if (strcmp(t->name, + ct_encode_string(*argv, &el->el_scratch)) == 0) { + scap = el->el_terminal.t_str[t - tstr]; break; } if (t->name == NULL) { /* XXX: some systems' tgetstr needs non const */ - scap = tgetstr(strchr(*argv, **argv), &area); + scap = tgetstr(ct_encode_string(*argv, &el->el_scratch), &area); } if (!scap || scap[0] == '\0') { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Termcap parameter `%s' not found.\n", + "echotc: Termcap parameter `%ls' not found.\n", *argv); - return (-1); + return -1; } /* * Count home many values we need for this capability. @@ -1606,11 +1571,11 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", + "echotc: Warning: Extra argument `%ls'.\n", *argv); - return (-1); + return -1; } - term_tputs(el, scap, 1); + terminal_tputs(el, scap, 1); break; case 1: argv++; @@ -1618,27 +1583,27 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), if (!silent) (void) fprintf(el->el_errfile, "echotc: Warning: Missing argument.\n"); - return (-1); + 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 `%s' for rows.\n", + "echotc: Bad value `%ls' for rows.\n", *argv); - return (-1); + return -1; } arg_rows = (int) i; argv++; if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", - *argv); - return (-1); + "echotc: Warning: Extra argument `%ls" + "'.\n", *argv); + return -1; } - term_tputs(el, tgoto(scap, arg_cols, arg_rows), 1); + terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), 1); break; default: /* This is wrong, but I will ignore it... */ @@ -1653,15 +1618,15 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), if (!silent) (void) fprintf(el->el_errfile, "echotc: Warning: Missing argument.\n"); - return (-1); + 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 `%s' for cols.\n", + "echotc: Bad value `%ls' for cols.\n", *argv); - return (-1); + return -1; } arg_cols = (int) i; argv++; @@ -1669,33 +1634,33 @@ term_echotc(EditLine *el, int argc __attribute__((__unused__)), if (!silent) (void) fprintf(el->el_errfile, "echotc: Warning: Missing argument.\n"); - return (-1); + 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 `%s' for rows.\n", + "echotc: Bad value `%ls' for rows.\n", *argv); - return (-1); + return -1; } arg_rows = (int) i; if (*ep != '\0') { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Bad value `%s'.\n", *argv); - return (-1); + "echotc: Bad value `%ls'.\n", *argv); + return -1; } argv++; if (*argv && *argv[0]) { if (!silent) (void) fprintf(el->el_errfile, - "echotc: Warning: Extra argument `%s'.\n", - *argv); - return (-1); + "echotc: Warning: Extra argument `%ls" + "'.\n", *argv); + return -1; } - term_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows); + terminal_tputs(el, tgoto(scap, arg_cols, arg_rows), arg_rows); break; } - return (0); + return 0; } diff --git a/clt/falcon/editline/src/el_term.h b/clt/falcon/editline/src/terminal.h similarity index 63% rename from clt/falcon/editline/src/el_term.h rename to clt/falcon/editline/src/terminal.h index 105d8e76a..e45836954 100644 --- a/clt/falcon/editline/src/el_term.h +++ b/clt/falcon/editline/src/terminal.h @@ -1,4 +1,4 @@ -/* $NetBSD: term.h,v 1.20 2009/03/31 17:38:27 christos Exp $ */ +/* $NetBSD: terminal.h,v 1.9 2016/05/09 21:46:56 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,17 +37,15 @@ /* * el.term.h: Termcap header */ -#ifndef _h_el_term -#define _h_el_term - -#include "histedit.h" +#ifndef _h_el_terminal +#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 */ - key_value_t fun; /* Function bound to it */ + keymacro_value_t fun; /* Function bound to it */ int type; /* Type of function */ -} fkey_t; +} funckey_t; typedef struct { const char *t_name; /* the terminal name */ @@ -63,12 +61,12 @@ typedef struct { #define TERM_HAS_AUTO_MARGINS 0x080 /* Has auto margins */ #define TERM_HAS_MAGIC_MARGINS 0x100 /* Has magic margins */ char *t_buf; /* Termcap buffer */ - int t_loc; /* location used */ + size_t t_loc; /* location used */ char **t_str; /* termcap strings */ int *t_val; /* termcap values */ char *t_cap; /* Termcap buffer */ - fkey_t *t_fkey; /* Array of keys */ -} el_term_t; + funckey_t *t_fkey; /* Array of keys */ +} el_terminal_t; /* * fKey indexes @@ -79,7 +77,8 @@ typedef struct { #define A_K_RT 3 #define A_K_HO 4 #define A_K_EN 5 -#define A_K_NKEYS 6 +#define A_K_DE 6 +#define A_K_NKEYS 7 #ifdef __sun extern int tgetent(char *, const char *); @@ -90,36 +89,37 @@ extern char* tgoto(const char*, int, int); extern char* tgetstr(char*, char**); #endif -protected void term_move_to_line(EditLine *, int); -protected void term_move_to_char(EditLine *, int); -protected void term_clear_EOL(EditLine *, int); -protected void term_overwrite(EditLine *, const char *, size_t); -protected void term_insertwrite(EditLine *, char *, int); -protected void term_deletechars(EditLine *, int); -protected void term_clear_screen(EditLine *); -protected void term_beep(EditLine *); -protected int term_change_size(EditLine *, int, int); -protected int term_get_size(EditLine *, int *, int *); -protected int term_init(EditLine *); -protected void term_bind_arrow(EditLine *); -protected void term_print_arrow(EditLine *, const char *); -protected int term_clear_arrow(EditLine *, const char *); -protected int term_set_arrow(EditLine *, const char *, key_value_t *, int); -protected void term_end(EditLine *); -protected void term_get(EditLine *, const char **); -protected int term_set(EditLine *, const char *); -protected int term_settc(EditLine *, int, const char **); -protected int term_gettc(EditLine *, int, char **); -protected int term_telltc(EditLine *, int, const char **); -protected int term_echotc(EditLine *, int, const char **); -protected void term_writec(EditLine *, int); -protected int term__putc(EditLine *, int); -protected void term__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 */ -#define EL_FLAGS (el)->el_term.t_flags +#define EL_FLAGS (el)->el_terminal.t_flags #define EL_CAN_INSERT (EL_FLAGS & TERM_CAN_INSERT) #define EL_CAN_DELETE (EL_FLAGS & TERM_CAN_DELETE) @@ -131,4 +131,4 @@ protected void term__flush(EditLine *); #define EL_HAS_AUTO_MARGINS (EL_FLAGS & TERM_HAS_AUTO_MARGINS) #define EL_HAS_MAGIC_MARGINS (EL_FLAGS & TERM_HAS_MAGIC_MARGINS) -#endif /* _h_el_term */ +#endif /* _h_el_terminal */ diff --git a/clt/falcon/editline/src/tokenizer.c b/clt/falcon/editline/src/tokenizer.c index d98bd7f42..5efb43275 100644 --- a/clt/falcon/editline/src/tokenizer.c +++ b/clt/falcon/editline/src/tokenizer.c @@ -1,4 +1,4 @@ -/* $NetBSD: tokenizer.c,v 1.15 2009/02/15 21:55:23 christos Exp $ */ +/* $NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -32,60 +32,79 @@ * SUCH DAMAGE. */ +#ifndef NARROWCHAR #include "config.h" +#endif + #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)tokenizer.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tokenizer.c,v 1.15 2009/02/15 21:55:23 christos Exp $"); +__RCSID("$NetBSD: tokenizer.c,v 1.28 2016/04/11 18:56:31 christos Exp $"); #endif #endif /* not lint && not SCCSID */ +/* We build this file twice, once as NARROW, once as WIDE. */ /* * tokenize.c: Bourne shell like tokenizer */ -#include #include +#include + #include "histedit.h" typedef enum { Q_none, Q_single, Q_double, Q_one, Q_doubleone } quote_t; -#define IFS "\t \n" - #define TOK_KEEP 1 #define TOK_EAT 2 #define WINCR 20 #define AINCR 10 -#define tok_strdup(a) strdup(a) +#define IFS STR("\t \n") + #define tok_malloc(a) malloc(a) #define tok_free(a) free(a) #define tok_realloc(a, b) realloc(a, b) +#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 tokenizer { - char *ifs; /* In field separator */ - int argc, amax; /* Current and maximum number of args */ - char **argv; /* Argument list */ - char *wptr, *wmax; /* Space and limit on the word buffer */ - char *wstart; /* Beginning of next word */ - char *wspace; /* Space of word buffer */ +struct TYPE(tokenizer) { + Char *ifs; /* In field separator */ + size_t argc, amax; /* Current and maximum number of args */ + Char **argv; /* Argument list */ + Char *wptr, *wmax; /* Space and limit on the word buffer */ + Char *wstart; /* Beginning of next word */ + Char *wspace; /* Space of word buffer */ quote_t quote; /* Quoting state */ int flags; /* flags; */ }; -private void tok_finish(Tokenizer *); +static void FUN(tok,finish)(TYPE(Tokenizer) *); -/* tok_finish(): +/* FUN(tok,finish)(): * Finish a word in the tokenizer. */ -private void -tok_finish(Tokenizer *tok) +static void +FUN(tok,finish)(TYPE(Tokenizer) *tok) { *tok->wptr = '\0'; @@ -98,35 +117,35 @@ tok_finish(Tokenizer *tok) } -/* tok_init(): +/* FUN(tok,init)(): * Initialize the tokenizer */ -public Tokenizer * -tok_init(const char *ifs) +TYPE(Tokenizer) * +FUN(tok,init)(const Char *ifs) { - Tokenizer *tok = (Tokenizer *) tok_malloc(sizeof(Tokenizer)); + TYPE(Tokenizer) *tok = tok_malloc(sizeof(*tok)); if (tok == NULL) return NULL; tok->ifs = tok_strdup(ifs ? ifs : IFS); if (tok->ifs == NULL) { - tok_free((ptr_t)tok); + tok_free(tok); return NULL; } tok->argc = 0; tok->amax = AINCR; - tok->argv = (char **) tok_malloc(sizeof(char *) * tok->amax); + tok->argv = tok_malloc(sizeof(*tok->argv) * tok->amax); if (tok->argv == NULL) { - tok_free((ptr_t)tok->ifs); - tok_free((ptr_t)tok); + tok_free(tok->ifs); + tok_free(tok); return NULL; } tok->argv[0] = NULL; - tok->wspace = (char *) tok_malloc(WINCR); + tok->wspace = tok_malloc(WINCR * sizeof(*tok->wspace)); if (tok->wspace == NULL) { - tok_free((ptr_t)tok->argv); - tok_free((ptr_t)tok->ifs); - tok_free((ptr_t)tok); + tok_free(tok->argv); + tok_free(tok->ifs); + tok_free(tok); return NULL; } tok->wmax = tok->wspace + WINCR; @@ -135,15 +154,15 @@ tok_init(const char *ifs) tok->flags = 0; tok->quote = Q_none; - return (tok); + return tok; } -/* tok_reset(): +/* FUN(tok,reset)(): * Reset the tokenizer */ -public void -tok_reset(Tokenizer *tok) +void +FUN(tok,reset)(TYPE(Tokenizer) *tok) { tok->argc = 0; @@ -154,25 +173,25 @@ tok_reset(Tokenizer *tok) } -/* tok_end(): +/* FUN(tok,end)(): * Clean up */ -public void -tok_end(Tokenizer *tok) +void +FUN(tok,end)(TYPE(Tokenizer) *tok) { - tok_free((ptr_t) tok->ifs); - tok_free((ptr_t) tok->wspace); - tok_free((ptr_t) tok->argv); - tok_free((ptr_t) tok); + tok_free(tok->ifs); + tok_free(tok->wspace); + tok_free(tok->argv); + tok_free(tok); } -/* tok_line(): +/* FUN(tok,line)(): * Bourne shell (sh(1)) like tokenizing * Arguments: - * tok current tokenizer state (setup with tok_init()) + * tok current tokenizer state (setup with FUN(tok,init)()) * line line to parse * Returns: * -1 Internal error @@ -186,20 +205,20 @@ tok_end(Tokenizer *tok) * cursorc if !NULL, argv element containing cursor * cursorv if !NULL, offset in argv[cursorc] of cursor */ -public int -tok_line(Tokenizer *tok, const LineInfo *line, - int *argc, const char ***argv, int *cursorc, int *cursoro) +int +FUN(tok,line)(TYPE(Tokenizer) *tok, const TYPE(LineInfo) *line, + int *argc, const Char ***argv, int *cursorc, int *cursoro) { - const char *ptr; + const Char *ptr; int cc, co; cc = co = -1; ptr = line->buffer; for (ptr = line->buffer; ;ptr++) { if (ptr >= line->lastchar) - ptr = ""; + ptr = STR(""); if (ptr == line->cursor) { - cc = tok->argc; + cc = (int)tok->argc; co = (int)(tok->wptr - tok->wstart); } switch (*ptr) { @@ -231,7 +250,7 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (-1); + return -1; } break; @@ -262,7 +281,7 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (-1); + return -1; } break; @@ -293,7 +312,7 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (-1); + return -1; } break; @@ -319,7 +338,7 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (0); + return 0; } break; @@ -329,15 +348,15 @@ tok_line(Tokenizer *tok, const LineInfo *line, /* Finish word and return */ if (tok->flags & TOK_EAT) { tok->flags &= ~TOK_EAT; - return (3); + return 3; } goto tok_line_outok; case Q_single: - return (1); + return 1; case Q_double: - return (2); + return 2; case Q_doubleone: tok->quote = Q_double; @@ -350,7 +369,7 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (-1); + return -1; } break; @@ -358,8 +377,8 @@ tok_line(Tokenizer *tok, const LineInfo *line, tok->flags &= ~TOK_EAT; switch (tok->quote) { case Q_none: - if (strchr(tok->ifs, *ptr) != NULL) - tok_finish(tok); + if (Strchr(tok->ifs, *ptr) != NULL) + FUN(tok,finish)(tok); else *tok->wptr++ = *ptr; break; @@ -382,20 +401,21 @@ tok_line(Tokenizer *tok, const LineInfo *line, break; default: - return (-1); + return -1; } break; } if (tok->wptr >= tok->wmax - 4) { - size_t size = tok->wmax - tok->wspace + WINCR; - char *s = (char *) tok_realloc(tok->wspace, size); + size_t size = (size_t)(tok->wmax - tok->wspace + WINCR); + Char *s = tok_realloc(tok->wspace, + size * sizeof(*s)); if (s == NULL) - return (-1); + return -1; if (s != tok->wspace) { - int i; + size_t i; for (i = 0; i < tok->argc; i++) { tok->argv[i] = (tok->argv[i] - tok->wspace) + s; @@ -407,41 +427,43 @@ tok_line(Tokenizer *tok, const LineInfo *line, tok->wmax = s + size; } if (tok->argc >= tok->amax - 4) { - char **p; + Char **p; tok->amax += AINCR; - p = (char **) tok_realloc(tok->argv, - tok->amax * sizeof(char *)); - if (p == NULL) - return (-1); + p = tok_realloc(tok->argv, tok->amax * sizeof(*p)); + if (p == NULL) { + tok->amax -= AINCR; + return -1; + } tok->argv = p; } } tok_line_outok: if (cc == -1 && co == -1) { - cc = tok->argc; + cc = (int)tok->argc; co = (int)(tok->wptr - tok->wstart); } if (cursorc != NULL) *cursorc = cc; if (cursoro != NULL) *cursoro = co; - tok_finish(tok); - *argv = (const char **)tok->argv; - *argc = tok->argc; - return (0); + FUN(tok,finish)(tok); + *argv = (const Char **)tok->argv; + *argc = (int)tok->argc; + return 0; } -/* tok_str(): +/* FUN(tok,str)(): * Simpler version of tok_line, taking a NUL terminated line * and splitting into words, ignoring cursor state. */ -public int -tok_str(Tokenizer *tok, const char *line, int *argc, const char ***argv) +int +FUN(tok,str)(TYPE(Tokenizer) *tok, const Char *line, int *argc, + const Char ***argv) { - LineInfo li; + TYPE(LineInfo) li; memset(&li, 0, sizeof(li)); li.buffer = line; - li.cursor = li.lastchar = strchr(line, '\0'); - return (tok_line(tok, &li, argc, argv, NULL, NULL)); + li.cursor = li.lastchar = Strchr(line, '\0'); + return FUN(tok,line)(tok, &li, argc, argv, NULL, NULL); } diff --git a/clt/falcon/editline/src/tokenizern.c b/clt/falcon/editline/src/tokenizern.c new file mode 100644 index 000000000..5846b6064 --- /dev/null +++ b/clt/falcon/editline/src/tokenizern.c @@ -0,0 +1,3 @@ +#include "config.h" +#define NARROWCHAR +#include "tokenizer.c" diff --git a/clt/falcon/editline/src/tty.c b/clt/falcon/editline/src/tty.c index 976f2e466..b96c9a53c 100644 --- a/clt/falcon/editline/src/tty.c +++ b/clt/falcon/editline/src/tty.c @@ -1,4 +1,4 @@ -/* $NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $ */ +/* $NetBSD: tty.c,v 1.70 2021/07/14 07:47:23 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -37,7 +37,7 @@ #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $"); +__RCSID("$NetBSD: tty.c,v 1.70 2021/07/14 07:47:23 christos Exp $"); #endif #endif /* not lint && not SCCSID */ @@ -46,8 +46,14 @@ __RCSID("$NetBSD: tty.c,v 1.31 2009/07/22 15:58:09 christos Exp $"); */ #include #include -#include "tty.h" +#include /* for abort */ +#include +#include /* for ffs */ +#include /* for isatty */ + #include "el.h" +#include "fcns.h" +#include "parse.h" typedef struct ttymodes_t { const char *m_name; @@ -56,12 +62,12 @@ typedef struct ttymodes_t { } ttymodes_t; typedef struct ttymap_t { - int nch, och; /* Internal and termio rep of chars */ + wint_t nch, och; /* Internal and termio rep of chars */ el_action_t bind[3]; /* emacs, vi, and vi-cmd */ } ttymap_t; -private const ttyperm_t ttyperm = { +static const ttyperm_t ttyperm = { { {"iflag:", ICRNL, (INLCR | IGNCR)}, {"oflag:", (OPOST | ONLCR), ONLRET}, @@ -89,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, @@ -119,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}}, @@ -152,11 +158,11 @@ private const ttymap_t tty_map[] = { {C_LNEXT, VLNEXT, {ED_QUOTED_INSERT, ED_QUOTED_INSERT, ED_UNASSIGNED}}, #endif /* VLNEXT */ - {-1, -1, + {(wint_t)-1, (wint_t)-1, {ED_UNASSIGNED, ED_UNASSIGNED, ED_UNASSIGNED}} }; -private const ttymodes_t ttymodes[] = { +static const ttymodes_t ttymodes[] = { #ifdef IGNBRK {"ignbrk", IGNBRK, MD_INP}, #endif /* IGNBRK */ @@ -450,20 +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 *); +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; @@ -475,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; @@ -487,38 +494,38 @@ 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); + return 0; + + if (el->el_tty.t_initialized) + return -1; - if (tty_getty(el, &el->el_tty.t_ed) == -1) { + if (!isatty(el->el_outfd)) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, - "tty_setup: tty_getty: %s\n", strerror(errno)); + (void) fprintf(el->el_errfile, "%s: isatty: %s\n", __func__, + strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; + } + if (tty_getty(el, &el->el_tty.t_or) == -1) { +#ifdef DEBUG_TTY + (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, + strerror(errno)); +#endif /* DEBUG_TTY */ + return -1; } - el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed; + el->el_tty.t_ts = el->el_tty.t_ex = el->el_tty.t_ed = el->el_tty.t_or; el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ex); el->el_tty.t_tabs = tty__gettabs(&el->el_tty.t_ex); el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ex); - el->el_tty.t_ex.c_iflag &= ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; - el->el_tty.t_ex.c_iflag |= el->el_tty.t_t[EX_IO][MD_INP].t_setmask; - - el->el_tty.t_ex.c_oflag &= ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; - el->el_tty.t_ex.c_oflag |= el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; - - el->el_tty.t_ex.c_cflag &= ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; - el->el_tty.t_ex.c_cflag |= el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; - - el->el_tty.t_ex.c_lflag &= ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; - el->el_tty.t_ex.c_lflag |= el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; + tty_setup_flags(el, &el->el_tty.t_ex, EX_IO); /* * Reset the tty chars to reasonable defaults @@ -546,76 +553,74 @@ tty_setup(EditLine *el) tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, - "tty_setup: tty_setty: %s\n", - strerror(errno)); + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", + __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } } -#ifdef notdef - else - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); -#endif - el->el_tty.t_ed.c_iflag &= ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; - el->el_tty.t_ed.c_iflag |= el->el_tty.t_t[ED_IO][MD_INP].t_setmask; - - el->el_tty.t_ed.c_oflag &= ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; - el->el_tty.t_ed.c_oflag |= el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; - - el->el_tty.t_ed.c_cflag &= ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; - el->el_tty.t_ed.c_cflag |= el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; - - el->el_tty.t_ed.c_lflag &= ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; - el->el_tty.t_ed.c_lflag |= el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; + tty_setup_flags(el, &el->el_tty.t_ed, ED_IO); tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); tty_bind_char(el, 1); - return (0); + el->el_tty.t_initialized = 1; + return 0; } -protected int +libedit_private int tty_init(EditLine *el) { el->el_tty.t_mode = EX_IO; el->el_tty.t_vdisable = _POSIX_VDISABLE; + el->el_tty.t_initialized = 0; (void) memcpy(el->el_tty.t_t, ttyperm, sizeof(ttyperm_t)); (void) memcpy(el->el_tty.t_c, ttychar, sizeof(ttychar_t)); - return (tty_setup(el)); + return tty_setup(el); } /* tty_end(): * Restore the tty to its original settings */ -protected void +libedit_private void /*ARGSUSED*/ -tty_end(EditLine *el __attribute__((__unused__))) +tty_end(EditLine *el, int how) { + if (el->el_flags & EDIT_DISABLED) + return; + + if (!el->el_tty.t_initialized) + return; - /* XXX: Maybe reset to an initial state? */ + 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)); +#endif /* DEBUG_TTY */ + } } /* tty__getspeed(): * Get the tty speed */ -private speed_t +static speed_t tty__getspeed(struct termios *td) { speed_t spd; if ((spd = cfgetispeed(td)) == 0) spd = cfgetospeed(td); - return (spd); + return spd; } /* tty__getspeed(): * Return the index of the asked char in the c_cc array */ -private int +static int tty__getcharindex(int i) { switch (i) { @@ -723,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) { @@ -805,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) { @@ -887,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; - unsigned 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; @@ -909,50 +914,104 @@ tty_bind_char(EditLine *el, int force) dalt = NULL; } - for (tp = tty_map; tp->nch != -1; tp++) { - new[0] = t_n[tp->nch]; - old[0] = t_o[tp->och]; + for (tp = tty_map; tp->nch != (wint_t)-1; tp++) { + 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 */ - key_clear(el, map, (char *)old); - map[old[0]] = dmap[old[0]]; - key_clear(el, map, (char *)new); + keymacro_clear(el, map, old); + map[(unsigned char)old[0]] = dmap[(unsigned char)old[0]]; + keymacro_clear(el, map, new); /* MAP_VI == 1, MAP_EMACS == 0... */ - map[new[0]] = tp->bind[el->el_map.type]; + map[(unsigned char)new[0]] = tp->bind[el->el_map.type]; if (dalt) { - key_clear(el, alt, (char *)old); - alt[old[0]] = dalt[old[0]]; - key_clear(el, alt, (char *)new); - alt[new[0]] = tp->bind[el->el_map.type + 1]; + keymacro_clear(el, alt, old); + alt[(unsigned char)old[0]] = + dalt[(unsigned char)old[0]]; + keymacro_clear(el, alt, new); + alt[(unsigned char)new[0]] = + tp->bind[el->el_map.type + 1]; } } } +static tcflag_t * +tty__get_flag(struct termios *t, int kind) { + switch (kind) { + case MD_INP: + return &t->c_iflag; + case MD_OUT: + return &t->c_oflag; + case MD_CTL: + return &t->c_cflag; + case MD_LIN: + return &t->c_lflag; + default: + abort(); + /*NOTREACHED*/ + } +} + + +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; + f |= el->el_tty.t_t[mode][kind].t_setmask; + return f; +} + + +static void +tty_update_flags(EditLine *el, int kind) +{ + tcflag_t *tt, *ed, *ex; + tt = tty__get_flag(&el->el_tty.t_ts, kind); + ed = tty__get_flag(&el->el_tty.t_ed, kind); + ex = tty__get_flag(&el->el_tty.t_ex, kind); + + if (*tt != *ex && (kind != MD_CTL || *tt != *ed)) { + *ed = tty_update_flag(el, *tt, ED_IO, kind); + *ex = tty_update_flag(el, *tt, EX_IO, kind); + } +} + + +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])) + el->el_tty.t_c[mode][c] = el->el_tty.t_c[TS_IO][c]; + if (el->el_tty.t_t[mode][MD_CHAR].t_clrmask & C_SH(c)) + el->el_tty.t_c[mode][c] = el->el_tty.t_vdisable; +} + + /* tty_rawmode(): - * Set terminal into 1 character at a time mode. + * Set terminal into 1 character at a time mode. */ -protected int +libedit_private int tty_rawmode(EditLine *el) { if (el->el_tty.t_mode == ED_IO || el->el_tty.t_mode == QU_IO) - return (0); + return 0; if (el->el_flags & EDIT_DISABLED) - return (0); + return 0; if (tty_getty(el, &el->el_tty.t_ts) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "tty_rawmode: tty_getty: %s\n", + (void) fprintf(el->el_errfile, "%s: tty_getty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } /* * We always keep up with the eight bit setting and the speed of the - * tty. But only we only believe changes that are made to cooked mode! + * tty. But we only believe changes that are made to cooked mode! */ el->el_tty.t_eight = tty__geteightbit(&el->el_tty.t_ts); el->el_tty.t_speed = tty__getspeed(&el->el_tty.t_ts); @@ -965,226 +1024,146 @@ tty_rawmode(EditLine *el) (void) cfsetospeed(&el->el_tty.t_ed, el->el_tty.t_speed); } if (tty__cooked_mode(&el->el_tty.t_ts)) { - if (el->el_tty.t_ts.c_cflag != el->el_tty.t_ex.c_cflag) { - el->el_tty.t_ex.c_cflag = - el->el_tty.t_ts.c_cflag; - el->el_tty.t_ex.c_cflag &= - ~el->el_tty.t_t[EX_IO][MD_CTL].t_clrmask; - el->el_tty.t_ex.c_cflag |= - el->el_tty.t_t[EX_IO][MD_CTL].t_setmask; - - el->el_tty.t_ed.c_cflag = - el->el_tty.t_ts.c_cflag; - el->el_tty.t_ed.c_cflag &= - ~el->el_tty.t_t[ED_IO][MD_CTL].t_clrmask; - el->el_tty.t_ed.c_cflag |= - el->el_tty.t_t[ED_IO][MD_CTL].t_setmask; - } - if ((el->el_tty.t_ts.c_lflag != el->el_tty.t_ex.c_lflag) && - (el->el_tty.t_ts.c_lflag != el->el_tty.t_ed.c_lflag)) { - el->el_tty.t_ex.c_lflag = - el->el_tty.t_ts.c_lflag; - el->el_tty.t_ex.c_lflag &= - ~el->el_tty.t_t[EX_IO][MD_LIN].t_clrmask; - el->el_tty.t_ex.c_lflag |= - el->el_tty.t_t[EX_IO][MD_LIN].t_setmask; - - el->el_tty.t_ed.c_lflag = - el->el_tty.t_ts.c_lflag; - el->el_tty.t_ed.c_lflag &= - ~el->el_tty.t_t[ED_IO][MD_LIN].t_clrmask; - el->el_tty.t_ed.c_lflag |= - el->el_tty.t_t[ED_IO][MD_LIN].t_setmask; - } - if ((el->el_tty.t_ts.c_iflag != el->el_tty.t_ex.c_iflag) && - (el->el_tty.t_ts.c_iflag != el->el_tty.t_ed.c_iflag)) { - el->el_tty.t_ex.c_iflag = - el->el_tty.t_ts.c_iflag; - el->el_tty.t_ex.c_iflag &= - ~el->el_tty.t_t[EX_IO][MD_INP].t_clrmask; - el->el_tty.t_ex.c_iflag |= - el->el_tty.t_t[EX_IO][MD_INP].t_setmask; - - el->el_tty.t_ed.c_iflag = - el->el_tty.t_ts.c_iflag; - el->el_tty.t_ed.c_iflag &= - ~el->el_tty.t_t[ED_IO][MD_INP].t_clrmask; - el->el_tty.t_ed.c_iflag |= - el->el_tty.t_t[ED_IO][MD_INP].t_setmask; - } - if ((el->el_tty.t_ts.c_oflag != el->el_tty.t_ex.c_oflag) && - (el->el_tty.t_ts.c_oflag != el->el_tty.t_ed.c_oflag)) { - el->el_tty.t_ex.c_oflag = - el->el_tty.t_ts.c_oflag; - el->el_tty.t_ex.c_oflag &= - ~el->el_tty.t_t[EX_IO][MD_OUT].t_clrmask; - el->el_tty.t_ex.c_oflag |= - el->el_tty.t_t[EX_IO][MD_OUT].t_setmask; - - el->el_tty.t_ed.c_oflag = - el->el_tty.t_ts.c_oflag; - el->el_tty.t_ed.c_oflag &= - ~el->el_tty.t_t[ED_IO][MD_OUT].t_clrmask; - el->el_tty.t_ed.c_oflag |= - el->el_tty.t_t[ED_IO][MD_OUT].t_setmask; - } + int i; + + for (i = MD_INP; i <= MD_LIN; i++) + tty_update_flags(el, i); + if (tty__gettabs(&el->el_tty.t_ex) == 0) el->el_tty.t_tabs = 0; else el->el_tty.t_tabs = EL_CAN_TAB ? 1 : 0; - { - int i; + tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); + /* + * Check if the user made any changes. + * If he did, then propagate the changes to the + * edit and execute data structures. + */ + for (i = 0; i < C_NCC; i++) + if (el->el_tty.t_c[TS_IO][i] != + el->el_tty.t_c[EX_IO][i]) + break; - tty__getchar(&el->el_tty.t_ts, el->el_tty.t_c[TS_IO]); + if (i != C_NCC) { /* - * Check if the user made any changes. - * If he did, then propagate the changes to the - * edit and execute data structures. - */ + * Propagate changes only to the unlibedit_private + * chars that have been modified just now. + */ for (i = 0; i < C_NCC; i++) - if (el->el_tty.t_c[TS_IO][i] != - el->el_tty.t_c[EX_IO][i]) - break; - - if (i != C_NCC) { - /* - * Propagate changes only to the unprotected - * chars that have been modified just now. - */ - for (i = 0; i < C_NCC; i++) { - if (!((el->el_tty.t_t[ED_IO][MD_CHAR].t_setmask & C_SH(i))) - && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) - el->el_tty.t_c[ED_IO][i] = el->el_tty.t_c[TS_IO][i]; - if (el->el_tty.t_t[ED_IO][MD_CHAR].t_clrmask & C_SH(i)) - el->el_tty.t_c[ED_IO][i] = el->el_tty.t_vdisable; - } - tty_bind_char(el, 0); - tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); - - for (i = 0; i < C_NCC; i++) { - if (!((el->el_tty.t_t[EX_IO][MD_CHAR].t_setmask & C_SH(i))) - && (el->el_tty.t_c[TS_IO][i] != el->el_tty.t_c[EX_IO][i])) - el->el_tty.t_c[EX_IO][i] = el->el_tty.t_c[TS_IO][i]; - if (el->el_tty.t_t[EX_IO][MD_CHAR].t_clrmask & C_SH(i)) - el->el_tty.t_c[EX_IO][i] = el->el_tty.t_vdisable; - } - tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); - } + tty_update_char(el, ED_IO, i); + + tty_bind_char(el, 0); + tty__setchar(&el->el_tty.t_ed, el->el_tty.t_c[ED_IO]); + + for (i = 0; i < C_NCC; i++) + tty_update_char(el, EX_IO, i); + + tty__setchar(&el->el_tty.t_ex, el->el_tty.t_c[EX_IO]); } } if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "tty_rawmode: tty_setty: %s\n", + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } el->el_tty.t_mode = ED_IO; - return (0); + return 0; } /* tty_cookedmode(): * Set the tty back to normal mode */ -protected int +libedit_private int tty_cookedmode(EditLine *el) { /* set tty in normal setup */ if (el->el_tty.t_mode == EX_IO) - return (0); + return 0; if (el->el_flags & EDIT_DISABLED) - return (0); + return 0; if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ex) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, - "tty_cookedmode: tty_setty: %s\n", + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } el->el_tty.t_mode = EX_IO; - return (0); + return 0; } /* tty_quotemode(): * Turn on quote mode */ -protected int +libedit_private int tty_quotemode(EditLine *el) { if (el->el_tty.t_mode == QU_IO) - return (0); + return 0; el->el_tty.t_qu = el->el_tty.t_ed; - el->el_tty.t_qu.c_iflag &= ~el->el_tty.t_t[QU_IO][MD_INP].t_clrmask; - el->el_tty.t_qu.c_iflag |= el->el_tty.t_t[QU_IO][MD_INP].t_setmask; - - el->el_tty.t_qu.c_oflag &= ~el->el_tty.t_t[QU_IO][MD_OUT].t_clrmask; - el->el_tty.t_qu.c_oflag |= el->el_tty.t_t[QU_IO][MD_OUT].t_setmask; - - el->el_tty.t_qu.c_cflag &= ~el->el_tty.t_t[QU_IO][MD_CTL].t_clrmask; - el->el_tty.t_qu.c_cflag |= el->el_tty.t_t[QU_IO][MD_CTL].t_setmask; - - el->el_tty.t_qu.c_lflag &= ~el->el_tty.t_t[QU_IO][MD_LIN].t_clrmask; - el->el_tty.t_qu.c_lflag |= el->el_tty.t_t[QU_IO][MD_LIN].t_setmask; + tty_setup_flags(el, &el->el_tty.t_qu, QU_IO); if (tty_setty(el, TCSADRAIN, &el->el_tty.t_qu) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "QuoteModeOn: tty_setty: %s\n", + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } el->el_tty.t_mode = QU_IO; - return (0); + return 0; } /* tty_noquotemode(): * Turn off quote mode */ -protected int +libedit_private int tty_noquotemode(EditLine *el) { if (el->el_tty.t_mode != QU_IO) - return (0); + return 0; if (tty_setty(el, TCSADRAIN, &el->el_tty.t_ed) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, "QuoteModeOff: tty_setty: %s\n", + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } el->el_tty.t_mode = ED_IO; - return (0); + return 0; } /* 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 char *name; + const wchar_t *s, *d; + char name[EL_BUFSIZ]; struct termios *tios = &el->el_tty.t_ex; int z = EX_IO; if (argv == NULL) - return (-1); - name = *argv++; + return -1; + strlcpy(name, ct_encode_string(*argv++, &el->el_scratch), sizeof(name)); while (argv && *argv && argv[0][0] == '-' && argv[0][2] == '\0') switch (argv[0][1]) { @@ -1209,9 +1188,9 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) break; default: (void) fprintf(el->el_errfile, - "%s: Unknown switch `%c'.\n", - name, argv[0][1]); - return (-1); + "%s: Unknown switch `%lc'.\n", + name, (wint_t)argv[0][1]); + return -1; } if (!argv || !*argv) { @@ -1229,8 +1208,9 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) if (i != -1) { x = (el->el_tty.t_t[z][i].t_setmask & m->m_value) ? '+' : '\0'; - x = (el->el_tty.t_t[z][i].t_clrmask & m->m_value) - ? '-' : x; + + if (el->el_tty.t_t[z][i].t_clrmask & m->m_value) + x = '-'; } else { x = '\0'; } @@ -1239,7 +1219,8 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) cu = strlen(m->m_name) + (x != '\0') + 1; - if (len + cu >= (size_t)el->el_term.t_size.h) { + if (len + cu >= + (size_t)el->el_terminal.t_size.h) { (void) fprintf(el->el_outfile, "\n%*s", (int)st, ""); len = st + cu; @@ -1255,41 +1236,43 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) } } (void) fprintf(el->el_outfile, "\n"); - return (0); + return 0; } while (argv && (s = *argv++)) { - const char *p; + const wchar_t *p; switch (*s) { case '+': case '-': - x = *s++; + x = (char)*s++; break; default: x = '\0'; break; } d = s; - p = strchr(s, '='); + p = wcschr(s, L'='); for (m = ttymodes; m->m_name; m++) - if ((p ? strncmp(m->m_name, d, (size_t)(p - d)) : - strcmp(m->m_name, d)) == 0 && + if ((p ? strncmp(m->m_name, ct_encode_string(d, + &el->el_scratch), (size_t)(p - d)) : + strcmp(m->m_name, ct_encode_string(d, + &el->el_scratch))) == 0 && (p == NULL || m->m_type == MD_CHAR)) break; if (!m->m_name) { (void) fprintf(el->el_errfile, - "%s: Invalid argument `%s'.\n", name, d); - return (-1); + "%s: Invalid argument `%ls'.\n", name, d); + return -1; } if (p) { int c = ffs((int)m->m_value); - int v = *++p ? parse__escape((const char **) &p) : + int v = *++p ? parse__escape(&p) : el->el_tty.t_vdisable; assert(c != 0); c--; c = tty__getcharindex(c); assert(c != -1); - tios->c_cc[c] = v; + tios->c_cc[c] = (cc_t)v; continue; } switch (x) { @@ -1308,17 +1291,18 @@ tty_stty(EditLine *el, int argc __attribute__((__unused__)), const char **argv) } } + tty_setup_flags(el, tios, z); if (el->el_tty.t_mode == z) { if (tty_setty(el, TCSADRAIN, tios) == -1) { #ifdef DEBUG_TTY - (void) fprintf(el->el_errfile, - "tty_stty: tty_setty: %s\n", strerror(errno)); + (void) fprintf(el->el_errfile, "%s: tty_setty: %s\n", + __func__, strerror(errno)); #endif /* DEBUG_TTY */ - return (-1); + return -1; } } - return (0); + return 0; } @@ -1326,7 +1310,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; @@ -1345,3 +1329,44 @@ tty_printchar(EditLine *el, unsigned char *s) (void) fprintf(el->el_errfile, "\n"); } #endif /* notyet */ + + +static void +tty_setup_flags(EditLine *el, struct termios *tios, int mode) +{ + int kind; + for (kind = MD_INP; kind <= MD_LIN; kind++) { + tcflag_t *f = tty__get_flag(tios, kind); + *f = tty_update_flag(el, *f, mode, kind); + } +} + +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) { +#if defined(SIGINT) && defined(VINTR) + case SIGINT: + return el->el_tty.t_c[ED_IO][VINTR]; +#endif +#if defined(SIGQUIT) && defined(VQUIT) + case SIGQUIT: + return el->el_tty.t_c[ED_IO][VQUIT]; +#endif +#if defined(SIGINFO) && defined(VSTATUS) + case SIGINFO: + return el->el_tty.t_c[ED_IO][VSTATUS]; +#endif +#if defined(SIGTSTP) && defined(VSUSP) + case SIGTSTP: + return el->el_tty.t_c[ED_IO][VSUSP]; +#endif + default: + return -1; + } +} diff --git a/clt/falcon/editline/src/tty.h b/clt/falcon/editline/src/tty.h index 10e9b98c9..ac817c8ad 100644 --- a/clt/falcon/editline/src/tty.h +++ b/clt/falcon/editline/src/tty.h @@ -1,4 +1,4 @@ -/* $NetBSD: tty.h,v 1.11 2005/06/01 11:37:52 lukem Exp $ */ +/* $NetBSD: tty.h,v 1.24 2021/07/31 20:51:32 andvar Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -40,7 +40,6 @@ #ifndef _h_el_tty #define _h_el_tty -#include "histedit.h" #include #include @@ -430,10 +429,10 @@ #define C_MIN 23 #define C_TIME 24 #define C_NCC 25 -#define C_SH(A) (1 << (A)) +#define C_SH(A) ((unsigned int)(1 << (A))) /* - * Terminal dependend data structures + * Terminal dependent data structures */ #define EX_IO 0 /* while we are executing */ #define ED_IO 1 /* while we are editing */ @@ -441,6 +440,7 @@ #define QU_IO 2 /* used only for quoted chars */ #define NN_IO 3 /* The number of entries */ +/* Don't re-order */ #define MD_INP 0 #define MD_OUT 1 #define MD_CTL 2 @@ -456,24 +456,26 @@ 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; ttychar_t t_c; - struct termios t_ex, t_ed, t_ts; + struct termios t_or, t_ex, t_ed, t_ts; int t_tabs; int t_eight; speed_t t_speed; - int t_mode; + unsigned char t_mode; unsigned char t_vdisable; + unsigned char t_initialized; } el_tty_t; diff --git a/clt/falcon/editline/src/unvis.c b/clt/falcon/editline/src/unvis.c index 124e28e14..d129577e5 100644 --- a/clt/falcon/editline/src/unvis.c +++ b/clt/falcon/editline/src/unvis.c @@ -1,4 +1,4 @@ -/* $NetBSD: unvis.c,v 1.30 2009/02/11 13:51:59 christos Exp $ */ +/* $NetBSD: unvis.c,v 1.45 2022/04/19 20:32:15 rillig Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -29,12 +29,12 @@ * SUCH DAMAGE. */ -#include +#include "config.h" #if defined(LIBC_SCCS) && !defined(lint) #if 0 static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: unvis.c,v 1.30 2009/02/11 13:51:59 christos Exp $"); +__RCSID("$NetBSD: unvis.c,v 1.45 2022/04/19 20:32:15 rillig Exp $"); #endif #endif /* LIBC_SCCS and not lint */ @@ -42,14 +42,18 @@ __RCSID("$NetBSD: unvis.c,v 1.30 2009/02/11 13:51:59 christos Exp $"); #include #include +#ifdef HAVE_STDINT_H +#include +#endif #include +#include #include #ifdef __weak_alias -__weak_alias(strunvis,_strunvis) +__weak_alias(strnunvisx,_strnunvisx) #endif -#if !HAVE_VIS +#ifndef HAVE_VIS /* * decode driven by state machine */ @@ -60,15 +64,128 @@ __weak_alias(strunvis,_strunvis) #define S_CTRL 4 /* control char started (^) */ #define S_OCTAL2 5 /* octal digit 2 */ #define S_OCTAL3 6 /* octal digit 3 */ -#define S_HEX1 7 /* http hex digit */ -#define S_HEX2 8 /* http hex digit 2 */ -#define S_MIME1 9 /* mime hex digit 1 */ -#define S_MIME2 10 /* mime hex digit 2 */ -#define S_EATCRNL 11 /* mime eating CRNL */ +#define S_HEX 7 /* mandatory hex digit */ +#define S_HEX1 8 /* http hex digit */ +#define S_HEX2 9 /* http hex digit 2 */ +#define S_MIME1 10 /* mime hex digit 1 */ +#define S_MIME2 11 /* mime hex digit 2 */ +#define S_EATCRNL 12 /* mime eating CRNL */ +#define S_AMP 13 /* seen & */ +#define S_NUMBER 14 /* collecting number */ +#define S_STRING 15 /* collecting string */ #define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) -#define XTOD(c) (isdigit(c) ? (c - '0') : ((c - 'A') + 10)) +#define xtod(c) (isdigit(c) ? (c - '0') : ((tolower(c) - 'a') + 10)) +#define XTOD(c) (isdigit(c) ? (c - '0') : ((c - 'A') + 10)) + +/* + * RFC 1866 + */ +static const struct nv { + char name[7]; + uint8_t value; +} nv[] = { + { "AElig", 198 }, /* capital AE diphthong (ligature) */ + { "Aacute", 193 }, /* capital A, acute accent */ + { "Acirc", 194 }, /* capital A, circumflex accent */ + { "Agrave", 192 }, /* capital A, grave accent */ + { "Aring", 197 }, /* capital A, ring */ + { "Atilde", 195 }, /* capital A, tilde */ + { "Auml", 196 }, /* capital A, dieresis or umlaut mark */ + { "Ccedil", 199 }, /* capital C, cedilla */ + { "ETH", 208 }, /* capital Eth, Icelandic */ + { "Eacute", 201 }, /* capital E, acute accent */ + { "Ecirc", 202 }, /* capital E, circumflex accent */ + { "Egrave", 200 }, /* capital E, grave accent */ + { "Euml", 203 }, /* capital E, dieresis or umlaut mark */ + { "Iacute", 205 }, /* capital I, acute accent */ + { "Icirc", 206 }, /* capital I, circumflex accent */ + { "Igrave", 204 }, /* capital I, grave accent */ + { "Iuml", 207 }, /* capital I, dieresis or umlaut mark */ + { "Ntilde", 209 }, /* capital N, tilde */ + { "Oacute", 211 }, /* capital O, acute accent */ + { "Ocirc", 212 }, /* capital O, circumflex accent */ + { "Ograve", 210 }, /* capital O, grave accent */ + { "Oslash", 216 }, /* capital O, slash */ + { "Otilde", 213 }, /* capital O, tilde */ + { "Ouml", 214 }, /* capital O, dieresis or umlaut mark */ + { "THORN", 222 }, /* capital THORN, Icelandic */ + { "Uacute", 218 }, /* capital U, acute accent */ + { "Ucirc", 219 }, /* capital U, circumflex accent */ + { "Ugrave", 217 }, /* capital U, grave accent */ + { "Uuml", 220 }, /* capital U, dieresis or umlaut mark */ + { "Yacute", 221 }, /* capital Y, acute accent */ + { "aacute", 225 }, /* small a, acute accent */ + { "acirc", 226 }, /* small a, circumflex accent */ + { "acute", 180 }, /* acute accent */ + { "aelig", 230 }, /* small ae diphthong (ligature) */ + { "agrave", 224 }, /* small a, grave accent */ + { "amp", 38 }, /* ampersand */ + { "aring", 229 }, /* small a, ring */ + { "atilde", 227 }, /* small a, tilde */ + { "auml", 228 }, /* small a, dieresis or umlaut mark */ + { "brvbar", 166 }, /* broken (vertical) bar */ + { "ccedil", 231 }, /* small c, cedilla */ + { "cedil", 184 }, /* cedilla */ + { "cent", 162 }, /* cent sign */ + { "copy", 169 }, /* copyright sign */ + { "curren", 164 }, /* general currency sign */ + { "deg", 176 }, /* degree sign */ + { "divide", 247 }, /* divide sign */ + { "eacute", 233 }, /* small e, acute accent */ + { "ecirc", 234 }, /* small e, circumflex accent */ + { "egrave", 232 }, /* small e, grave accent */ + { "eth", 240 }, /* small eth, Icelandic */ + { "euml", 235 }, /* small e, dieresis or umlaut mark */ + { "frac12", 189 }, /* fraction one-half */ + { "frac14", 188 }, /* fraction one-quarter */ + { "frac34", 190 }, /* fraction three-quarters */ + { "gt", 62 }, /* greater than */ + { "iacute", 237 }, /* small i, acute accent */ + { "icirc", 238 }, /* small i, circumflex accent */ + { "iexcl", 161 }, /* inverted exclamation mark */ + { "igrave", 236 }, /* small i, grave accent */ + { "iquest", 191 }, /* inverted question mark */ + { "iuml", 239 }, /* small i, dieresis or umlaut mark */ + { "laquo", 171 }, /* angle quotation mark, left */ + { "lt", 60 }, /* less than */ + { "macr", 175 }, /* macron */ + { "micro", 181 }, /* micro sign */ + { "middot", 183 }, /* middle dot */ + { "nbsp", 160 }, /* no-break space */ + { "not", 172 }, /* not sign */ + { "ntilde", 241 }, /* small n, tilde */ + { "oacute", 243 }, /* small o, acute accent */ + { "ocirc", 244 }, /* small o, circumflex accent */ + { "ograve", 242 }, /* small o, grave accent */ + { "ordf", 170 }, /* ordinal indicator, feminine */ + { "ordm", 186 }, /* ordinal indicator, masculine */ + { "oslash", 248 }, /* small o, slash */ + { "otilde", 245 }, /* small o, tilde */ + { "ouml", 246 }, /* small o, dieresis or umlaut mark */ + { "para", 182 }, /* pilcrow (paragraph sign) */ + { "plusmn", 177 }, /* plus-or-minus sign */ + { "pound", 163 }, /* pound sterling sign */ + { "quot", 34 }, /* double quote */ + { "raquo", 187 }, /* angle quotation mark, right */ + { "reg", 174 }, /* registered sign */ + { "sect", 167 }, /* section sign */ + { "shy", 173 }, /* soft hyphen */ + { "sup1", 185 }, /* superscript one */ + { "sup2", 178 }, /* superscript two */ + { "sup3", 179 }, /* superscript three */ + { "szlig", 223 }, /* small sharp s, German (sz ligature) */ + { "thorn", 254 }, /* small thorn, Icelandic */ + { "times", 215 }, /* multiply sign */ + { "uacute", 250 }, /* small u, acute accent */ + { "ucirc", 251 }, /* small u, circumflex accent */ + { "ugrave", 249 }, /* small u, grave accent */ + { "uml", 168 }, /* umlaut (dieresis) */ + { "uuml", 252 }, /* small u, dieresis or umlaut mark */ + { "yacute", 253 }, /* small y, acute accent */ + { "yen", 165 }, /* yen sign */ + { "yuml", 255 }, /* small y, dieresis or umlaut mark */ +}; /* * unvis - decode characters previously encoded by vis @@ -77,33 +194,52 @@ int unvis(char *cp, int c, int *astate, int flag) { unsigned char uc = (unsigned char)c; + unsigned char st, ia, is, lc; + +/* + * Bottom 8 bits of astate hold the state machine state. + * Top 8 bits hold the current character in the http 1866 nv string decoding + */ +#define GS(a) ((a) & 0xff) +#define SS(a, b) (((uint32_t)(a) << 24) | (b)) +#define GI(a) ((uint32_t)(a) >> 24) _DIAGASSERT(cp != NULL); _DIAGASSERT(astate != NULL); + st = GS(*astate); if (flag & UNVIS_END) { - if (*astate == S_OCTAL2 || *astate == S_OCTAL3 - || *astate == S_HEX2) { - *astate = S_GROUND; + switch (st) { + case S_OCTAL2: + case S_OCTAL3: + case S_HEX2: + *astate = SS(0, S_GROUND); return UNVIS_VALID; + case S_GROUND: + return UNVIS_NOCHAR; + default: + return UNVIS_SYNBAD; } - return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD); } - switch (*astate) { + switch (st) { case S_GROUND: *cp = 0; - if (c == '\\') { - *astate = S_START; + if ((flag & VIS_NOESCAPE) == 0 && c == '\\') { + *astate = SS(0, S_START); + return UNVIS_NOCHAR; + } + if ((flag & VIS_HTTP1808) && c == '%') { + *astate = SS(0, S_HEX1); return UNVIS_NOCHAR; } - if ((flag & VIS_HTTPSTYLE) && c == '%') { - *astate = S_HEX1; + if ((flag & VIS_HTTP1866) && c == '&') { + *astate = SS(0, S_AMP); return UNVIS_NOCHAR; } if ((flag & VIS_MIMESTYLE) && c == '=') { - *astate = S_MIME1; + *astate = SS(0, S_MIME1); return UNVIS_NOCHAR; } *cp = c; @@ -113,85 +249,91 @@ unvis(char *cp, int c, int *astate, int flag) switch(c) { case '\\': *cp = c; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *cp = (c - '0'); - *astate = S_OCTAL2; + *astate = SS(0, S_OCTAL2); return UNVIS_NOCHAR; case 'M': *cp = (char)0200; - *astate = S_META; + *astate = SS(0, S_META); return UNVIS_NOCHAR; case '^': - *astate = S_CTRL; + *astate = SS(0, S_CTRL); return UNVIS_NOCHAR; case 'n': *cp = '\n'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'r': *cp = '\r'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'b': *cp = '\b'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'a': *cp = '\007'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'v': *cp = '\v'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 't': *cp = '\t'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'f': *cp = '\f'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 's': *cp = ' '; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case 'E': *cp = '\033'; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; + case 'x': + *astate = SS(0, S_HEX); + return UNVIS_NOCHAR; case '\n': /* * hidden newline */ - *astate = S_GROUND; - return (UNVIS_NOCHAR); + *astate = SS(0, S_GROUND); + return UNVIS_NOCHAR; case '$': /* * hidden marker */ - *astate = S_GROUND; - return (UNVIS_NOCHAR); + *astate = SS(0, S_GROUND); + return UNVIS_NOCHAR; + default: + if (isgraph(c)) { + *cp = c; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + } } - *astate = S_GROUND; - return (UNVIS_SYNBAD); + goto bad; case S_META: if (c == '-') - *astate = S_META1; + *astate = SS(0, S_META1); else if (c == '^') - *astate = S_CTRL; - else { - *astate = S_GROUND; - return (UNVIS_SYNBAD); - } + *astate = SS(0, S_CTRL); + else + goto bad; return UNVIS_NOCHAR; case S_META1: - *astate = S_GROUND; + *astate = SS(0, S_GROUND); *cp |= c; return UNVIS_VALID; @@ -200,7 +342,7 @@ unvis(char *cp, int c, int *astate, int flag) *cp |= 0177; else *cp |= c & 037; - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALID; case S_OCTAL2: /* second possible octal digit */ @@ -209,17 +351,17 @@ unvis(char *cp, int c, int *astate, int flag) * yes - and maybe a third */ *cp = (*cp << 3) + (c - '0'); - *astate = S_OCTAL3; + *astate = SS(0, S_OCTAL3); return UNVIS_NOCHAR; } /* * no - done with current sequence, push back passed char */ - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALIDPUSH; case S_OCTAL3: /* third possible octal digit */ - *astate = S_GROUND; + *astate = SS(0, S_GROUND); if (isoctal(uc)) { *cp = (*cp << 3) + (c - '0'); return UNVIS_VALID; @@ -229,16 +371,20 @@ unvis(char *cp, int c, int *astate, int flag) */ return UNVIS_VALIDPUSH; + case S_HEX: + if (!isxdigit(uc)) + goto bad; + /*FALLTHROUGH*/ case S_HEX1: if (isxdigit(uc)) { *cp = xtod(uc); - *astate = S_HEX2; + *astate = SS(0, S_HEX2); return UNVIS_NOCHAR; } /* * no - done with current sequence, push back passed char */ - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_VALIDPUSH; case S_HEX2: @@ -251,25 +397,23 @@ unvis(char *cp, int c, int *astate, int flag) case S_MIME1: if (uc == '\n' || uc == '\r') { - *astate = S_EATCRNL; + *astate = SS(0, S_EATCRNL); return UNVIS_NOCHAR; } if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { *cp = XTOD(uc); - *astate = S_MIME2; + *astate = SS(0, S_MIME2); return UNVIS_NOCHAR; } - *astate = S_GROUND; - return UNVIS_SYNBAD; + goto bad; case S_MIME2: if (isxdigit(uc) && (isdigit(uc) || isupper(uc))) { - *astate = S_GROUND; + *astate = SS(0, S_GROUND); *cp = XTOD(uc) | (*cp << 4); return UNVIS_VALID; } - *astate = S_GROUND; - return UNVIS_SYNBAD; + goto bad; case S_EATCRNL: switch (uc) { @@ -277,69 +421,140 @@ unvis(char *cp, int c, int *astate, int flag) case '\n': return UNVIS_NOCHAR; case '=': - *astate = S_MIME1; + *astate = SS(0, S_MIME1); return UNVIS_NOCHAR; default: *cp = uc; + *astate = SS(0, S_GROUND); return UNVIS_VALID; } + case S_AMP: + *cp = 0; + if (uc == '#') { + *astate = SS(0, S_NUMBER); + return UNVIS_NOCHAR; + } + *astate = SS(0, S_STRING); + /*FALLTHROUGH*/ + + case S_STRING: + ia = *cp; /* index in the array */ + is = GI(*astate); /* index in the string */ + lc = is == 0 ? 0 : nv[ia].name[is - 1]; /* last character */ + + if (uc == ';') + uc = '\0'; + + for (; ia < __arraycount(nv); ia++) { + if (is != 0 && nv[ia].name[is - 1] != lc) + goto bad; + if (nv[ia].name[is] == uc) + break; + } + + if (ia == __arraycount(nv)) + goto bad; + + if (uc != 0) { + *cp = ia; + *astate = SS(is + 1, S_STRING); + return UNVIS_NOCHAR; + } + + *cp = nv[ia].value; + *astate = SS(0, S_GROUND); + return UNVIS_VALID; + + case S_NUMBER: + if (uc == ';') + return UNVIS_VALID; + if (!isdigit(uc)) + goto bad; + *cp += (*cp * 10) + uc - '0'; + return UNVIS_NOCHAR; + default: + bad: /* * decoder in unknown state - (probably uninitialized) */ - *astate = S_GROUND; + *astate = SS(0, S_GROUND); return UNVIS_SYNBAD; } } /* - * strunvis - decode src into dst + * strnunvisx - decode src into dst * * Number of chars decoded into dst is returned, -1 on error. * Dst is null terminated. */ int -strunvisx(dst, src, flag) - char *dst; - const char *src; - int flag; +strnunvisx(char *dst, size_t dlen, const char *src, int flag) { char c; - char *start = dst; + char t = '\0', *start = dst; int state = 0; _DIAGASSERT(src != NULL); _DIAGASSERT(dst != NULL); +#define CHECKSPACE() \ + do { \ + if (dlen-- == 0) { \ + errno = ENOSPC; \ + return -1; \ + } \ + } while (0) while ((c = *src++) != '\0') { again: - switch (unvis(dst, c, &state, flag)) { + switch (unvis(&t, c, &state, flag)) { case UNVIS_VALID: - dst++; + CHECKSPACE(); + *dst++ = t; break; case UNVIS_VALIDPUSH: - dst++; + CHECKSPACE(); + *dst++ = t; goto again; case 0: case UNVIS_NOCHAR: break; + case UNVIS_SYNBAD: + errno = EINVAL; + return -1; default: - return (-1); + _DIAGASSERT(/*CONSTCOND*/0); + errno = EINVAL; + return -1; } } - if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID) - dst++; + if (unvis(&t, c, &state, UNVIS_END) == UNVIS_VALID) { + CHECKSPACE(); + *dst++ = t; + } + CHECKSPACE(); *dst = '\0'; return (int)(dst - start); } int -strunvis(dst, src) - char *dst; - const char *src; +strunvisx(char *dst, const char *src, int flag) +{ + return strnunvisx(dst, (size_t)~0, src, flag); +} + +int +strunvis(char *dst, const char *src) +{ + return strnunvisx(dst, (size_t)~0, src, 0); +} + +int +strnunvis(char *dst, size_t dlen, const char *src) { - return strunvisx(dst, src, 0); + return strnunvisx(dst, dlen, src, 0); } #endif diff --git a/clt/falcon/editline/src/vi.c b/clt/falcon/editline/src/vi.c index 438aad486..e7f78494f 100644 --- a/clt/falcon/editline/src/vi.c +++ b/clt/falcon/editline/src/vi.c @@ -1,4 +1,4 @@ -/* $NetBSD: vi.c,v 1.30 2009/02/21 23:31:56 christos Exp $ */ +/* $NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 christos Exp $ */ /*- * Copyright (c) 1992, 1993 @@ -33,36 +33,43 @@ */ #include "config.h" -#include -#include -#include - #if !defined(lint) && !defined(SCCSID) #if 0 static char sccsid[] = "@(#)vi.c 8.1 (Berkeley) 6/4/93"; #else -__RCSID("$NetBSD: vi.c,v 1.30 2009/02/21 23:31:56 christos Exp $"); +__RCSID("$NetBSD: vi.c,v 1.64 2021/08/28 17:17:47 christos Exp $"); #endif #endif /* not lint && not SCCSID */ /* * vi.c: Vi mode commands. */ +#include +#include +#include +#include +#include +#include + #include "el.h" +#include "common.h" +#include "emacs.h" +#include "fcns.h" +#include "vi.h" -private el_action_t cv_action(EditLine *, int); -private el_action_t cv_paste(EditLine *, int); +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 -cv_action(EditLine *el, int c) +static el_action_t +cv_action(EditLine *el, wint_t c) { if (el->el_chared.c_vcmd.action != NOP) { /* 'cc', 'dd' and (possibly) friends */ - if (c != el->el_chared.c_vcmd.action) + if (c != (wint_t)el->el_chared.c_vcmd.action) return CC_ERROR; if (!(c & YANK)) @@ -78,26 +85,27 @@ cv_action(EditLine *el, int c) if (c & INSERT) el->el_map.current = el->el_map.key; - return (CC_REFRESH); + return CC_REFRESH; } el->el_chared.c_vcmd.pos = el->el_line.cursor; el->el_chared.c_vcmd.action = c; - return (CC_ARGHACK); + return CC_ARGHACK; } /* cv_paste(): * Paste previous deletion before or after the cursor */ -private el_action_t -cv_paste(EditLine *el, int c) +static el_action_t +cv_paste(EditLine *el, wint_t c) { c_kill_t *k = &el->el_chared.c_kill; size_t len = (size_t)(k->last - k->buf); if (k->buf == NULL || len == 0) - return (CC_ERROR); + return CC_ERROR; #ifdef DEBUG_PASTE - (void) fprintf(el->el_errfile, "Paste: \"%.*s\"\n", (int)len, k->buf); + (void) fprintf(el->el_errfile, "Paste: \"%.*ls\"\n", (int)len, + k->buf); #endif cv_undo(el); @@ -107,10 +115,11 @@ cv_paste(EditLine *el, int c) c_insert(el, (int)len); if (el->el_line.cursor + len > el->el_line.lastchar) - return (CC_ERROR); - (void) memcpy(el->el_line.cursor, k->buf, len); + return CC_ERROR; + (void) memcpy(el->el_line.cursor, k->buf, len * + sizeof(*el->el_line.cursor)); - return (CC_REFRESH); + return CC_REFRESH; } @@ -118,12 +127,12 @@ cv_paste(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_paste_next(EditLine *el, wint_t c __attribute__((__unused__))) { - return (cv_paste(el, 0)); + return cv_paste(el, 0); } @@ -131,12 +140,12 @@ vi_paste_next(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_paste_prev(EditLine *el, wint_t c __attribute__((__unused__))) { - return (cv_paste(el, 1)); + return cv_paste(el, 1); } @@ -144,13 +153,13 @@ vi_paste_prev(EditLine *el, int 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, int c) +vi_prev_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, @@ -159,9 +168,9 @@ vi_prev_big_word(EditLine *el, int c) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -169,13 +178,13 @@ vi_prev_big_word(EditLine *el, int c) * Vi move to the previous word * [b] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_prev_word(EditLine *el, int c __attribute__((__unused__))) +vi_prev_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv_prev_word(el->el_line.cursor, el->el_line.buffer, @@ -184,9 +193,9 @@ vi_prev_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -194,13 +203,13 @@ vi_prev_word(EditLine *el, int 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, int c) +vi_next_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor >= el->el_line.lastchar - 1) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv_next_word(el, el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, cv__isWord); @@ -208,9 +217,9 @@ vi_next_big_word(EditLine *el, int c) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -218,13 +227,13 @@ vi_next_big_word(EditLine *el, int c) * Vi move to the next word * [w] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_next_word(EditLine *el, int c __attribute__((__unused__))) +vi_next_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor >= el->el_line.lastchar - 1) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv_next_word(el, el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, cv__isword); @@ -232,9 +241,9 @@ vi_next_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_map.type == MAP_VI) if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -242,21 +251,21 @@ vi_next_word(EditLine *el, int c __attribute__((__unused__))) * Vi change case of character under the cursor and advance one character * [~] */ -protected el_action_t -vi_change_case(EditLine *el, int c) +libedit_private el_action_t +vi_change_case(EditLine *el, wint_t c) { int i; if (el->el_line.cursor >= el->el_line.lastchar) - return (CC_ERROR); + return CC_ERROR; cv_undo(el); for (i = 0; i < el->el_state.argument; i++) { - c = *(unsigned char *)el->el_line.cursor; - if (isupper(c)) - *el->el_line.cursor = tolower(c); - else if (islower(c)) - *el->el_line.cursor = toupper(c); + c = *el->el_line.cursor; + 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--; @@ -273,16 +282,16 @@ vi_change_case(EditLine *el, int c) * Vi change prefix command * [c] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_change_meta(EditLine *el, int c __attribute__((__unused__))) +vi_change_meta(EditLine *el, wint_t c __attribute__((__unused__))) { /* * Delete with insert == change: first we delete and then we leave in * insert mode. */ - return (cv_action(el, DELETE | INSERT)); + return cv_action(el, DELETE | INSERT); } @@ -290,15 +299,15 @@ vi_change_meta(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_insert_at_bol(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.buffer; cv_undo(el); el->el_map.current = el->el_map.key; - return (CC_CURSOR); + return CC_CURSOR; } @@ -306,9 +315,9 @@ vi_insert_at_bol(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_replace_char(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor >= el->el_line.lastchar) @@ -317,7 +326,7 @@ vi_replace_char(EditLine *el, int c __attribute__((__unused__))) el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE_1; cv_undo(el); - return (CC_ARGHACK); + return CC_ARGHACK; } @@ -325,15 +334,15 @@ vi_replace_char(EditLine *el, int c __attribute__((__unused__))) * Vi enter replace mode * [R] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_replace_mode(EditLine *el, int c __attribute__((__unused__))) +vi_replace_mode(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; el->el_state.inputmode = MODE_REPLACE; cv_undo(el); - return (CC_NORM); + return CC_NORM; } @@ -341,14 +350,14 @@ vi_replace_mode(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_substitute_char(EditLine *el, wint_t c __attribute__((__unused__))) { c_delafter(el, el->el_state.argument); el->el_map.current = el->el_map.key; - return (CC_REFRESH); + return CC_REFRESH; } @@ -356,9 +365,9 @@ vi_substitute_char(EditLine *el, int c __attribute__((__unused__))) * Vi substitute entire line * [S] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_substitute_line(EditLine *el, int c __attribute__((__unused__))) +vi_substitute_line(EditLine *el, wint_t c __attribute__((__unused__))) { cv_undo(el); @@ -366,7 +375,7 @@ vi_substitute_line(EditLine *el, int c __attribute__((__unused__))) (int)(el->el_line.lastchar - el->el_line.buffer)); (void) em_kill_line(el, 0); el->el_map.current = el->el_map.key; - return (CC_REFRESH); + return CC_REFRESH; } @@ -374,9 +383,9 @@ vi_substitute_line(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_change_to_eol(EditLine *el, wint_t c __attribute__((__unused__))) { cv_undo(el); @@ -384,7 +393,7 @@ vi_change_to_eol(EditLine *el, int c __attribute__((__unused__))) (int)(el->el_line.lastchar - el->el_line.cursor)); (void) ed_kill_line(el, 0); el->el_map.current = el->el_map.key; - return (CC_REFRESH); + return CC_REFRESH; } @@ -392,14 +401,14 @@ vi_change_to_eol(EditLine *el, int c __attribute__((__unused__))) * Vi enter insert mode * [i] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_insert(EditLine *el, int c __attribute__((__unused__))) +vi_insert(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; cv_undo(el); - return (CC_NORM); + return CC_NORM; } @@ -407,9 +416,9 @@ vi_insert(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_add(EditLine *el, wint_t c __attribute__((__unused__))) { int ret; @@ -424,7 +433,7 @@ vi_add(EditLine *el, int c __attribute__((__unused__))) cv_undo(el); - return (ret); + return (el_action_t)ret; } @@ -432,15 +441,15 @@ vi_add(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_add_at_eol(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_map.current = el->el_map.key; el->el_line.cursor = el->el_line.lastchar; cv_undo(el); - return (CC_CURSOR); + return CC_CURSOR; } @@ -448,12 +457,12 @@ vi_add_at_eol(EditLine *el, int c __attribute__((__unused__))) * Vi delete prefix command * [d] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_delete_meta(EditLine *el, int c __attribute__((__unused__))) +vi_delete_meta(EditLine *el, wint_t c __attribute__((__unused__))) { - return (cv_action(el, DELETE)); + return cv_action(el, DELETE); } @@ -461,13 +470,13 @@ vi_delete_meta(EditLine *el, int 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, int c) +vi_end_big_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.lastchar) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, cv__isWord); @@ -475,9 +484,9 @@ vi_end_big_word(EditLine *el, int c) if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -485,13 +494,13 @@ vi_end_big_word(EditLine *el, int c) * 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, int c __attribute__((__unused__))) +vi_end_word(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor == el->el_line.lastchar) - return (CC_ERROR); + return CC_ERROR; el->el_line.cursor = cv__endword(el->el_line.cursor, el->el_line.lastchar, el->el_state.argument, cv__isword); @@ -499,9 +508,9 @@ vi_end_word(EditLine *el, int c __attribute__((__unused__))) if (el->el_chared.c_vcmd.action != NOP) { el->el_line.cursor++; cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } @@ -509,9 +518,9 @@ vi_end_word(EditLine *el, int c __attribute__((__unused__))) * Vi undo last change * [u] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_undo(EditLine *el, int c __attribute__((__unused__))) +vi_undo(EditLine *el, wint_t c __attribute__((__unused__))) { c_undo_t un = el->el_chared.c_undo; @@ -528,7 +537,7 @@ vi_undo(EditLine *el, int c __attribute__((__unused__))) el->el_line.cursor = un.buf + un.cursor; el->el_line.lastchar = un.buf + un.len; - return (CC_REFRESH); + return CC_REFRESH; } @@ -536,9 +545,9 @@ vi_undo(EditLine *el, int c __attribute__((__unused__))) * Vi enter command mode (use alternative key bindings) * [] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_command_mode(EditLine *el, int c __attribute__((__unused__))) +vi_command_mode(EditLine *el, wint_t c __attribute__((__unused__))) { /* [Esc] cancels pending action */ @@ -553,7 +562,7 @@ vi_command_mode(EditLine *el, int c __attribute__((__unused__))) if (el->el_line.cursor > el->el_line.buffer) el->el_line.cursor--; #endif - return (CC_CURSOR); + return CC_CURSOR; } @@ -561,8 +570,8 @@ vi_command_mode(EditLine *el, int c __attribute__((__unused__))) * Vi move to the beginning of line * [0] */ -protected el_action_t -vi_zero(EditLine *el, int c) +libedit_private el_action_t +vi_zero(EditLine *el, wint_t c) { if (el->el_state.doingarg) @@ -571,27 +580,27 @@ vi_zero(EditLine *el, int c) el->el_line.cursor = el->el_line.buffer; if (el->el_chared.c_vcmd.action != NOP) { cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } /* vi_delete_prev_char(): - * Vi move to previous character (backspace) + * 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, int c __attribute__((__unused__))) +vi_delete_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_line.cursor <= el->el_line.buffer) - return (CC_ERROR); + return CC_ERROR; c_delbefore1(el); el->el_line.cursor--; - return (CC_REFRESH); + return CC_REFRESH; } @@ -599,34 +608,34 @@ vi_delete_prev_char(EditLine *el, int 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, int c) +vi_list_or_eof(EditLine *el, wint_t c) { if (el->el_line.cursor == el->el_line.lastchar) { if (el->el_line.cursor == el->el_line.buffer) { - term_writec(el, c); /* then do a EOF */ - return (CC_EOF); + terminal_writec(el, c); /* then do a EOF */ + return CC_EOF; } else { /* * Here we could list completions, but it is an * error right now */ - term_beep(el); - return (CC_ERROR); + terminal_beep(el); + return CC_ERROR; } } else { #ifdef notyet re_goto_bottom(el); *el->el_line.lastchar = '\0'; /* just in case */ - return (CC_LIST_CHOICES); + return CC_LIST_CHOICES; #else /* * Just complain for now. */ - term_beep(el); - return (CC_ERROR); + terminal_beep(el); + return CC_ERROR; #endif } } @@ -636,11 +645,11 @@ vi_list_or_eof(EditLine *el, int 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, int c __attribute__((__unused__))) +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; @@ -649,7 +658,7 @@ vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__))) el->el_chared.c_kill.last = kp; c_delbefore(el, (int)(el->el_line.cursor - el->el_line.buffer)); el->el_line.cursor = el->el_line.buffer; /* zap! */ - return (CC_REFRESH); + return CC_REFRESH; } @@ -657,12 +666,12 @@ vi_kill_line_prev(EditLine *el, int c __attribute__((__unused__))) * Vi search history previous * [?] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_search_prev(EditLine *el, int c __attribute__((__unused__))) +vi_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { - return (cv_search(el, ED_SEARCH_PREV_HISTORY)); + return cv_search(el, ED_SEARCH_PREV_HISTORY); } @@ -670,12 +679,12 @@ vi_search_prev(EditLine *el, int c __attribute__((__unused__))) * Vi search history next * [/] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_search_next(EditLine *el, int c __attribute__((__unused__))) +vi_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { - return (cv_search(el, ED_SEARCH_NEXT_HISTORY)); + return cv_search(el, ED_SEARCH_NEXT_HISTORY); } @@ -683,15 +692,15 @@ vi_search_next(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_repeat_search_next(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_search.patlen == 0) - return (CC_ERROR); + return CC_ERROR; else - return (cv_repeat_srch(el, el->el_search.patdir)); + return cv_repeat_srch(el, el->el_search.patdir); } @@ -700,12 +709,12 @@ vi_repeat_search_next(EditLine *el, int c __attribute__((__unused__))) * [N] */ /*ARGSUSED*/ -protected el_action_t -vi_repeat_search_prev(EditLine *el, int c __attribute__((__unused__))) +libedit_private el_action_t +vi_repeat_search_prev(EditLine *el, wint_t c __attribute__((__unused__))) { if (el->el_search.patlen == 0) - return (CC_ERROR); + return CC_ERROR; else return (cv_repeat_srch(el, el->el_search.patdir == ED_SEARCH_PREV_HISTORY ? @@ -717,9 +726,9 @@ vi_repeat_search_prev(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 0); } @@ -729,9 +738,9 @@ vi_next_char(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 0); } @@ -741,9 +750,9 @@ vi_prev_char(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_to_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_csearch(el, CHAR_FWD, -1, el->el_state.argument, 1); } @@ -753,9 +762,9 @@ vi_to_next_char(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_to_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_csearch(el, CHAR_BACK, -1, el->el_state.argument, 1); } @@ -765,9 +774,9 @@ vi_to_prev_char(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_repeat_next_char(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_csearch(el, el->el_search.chadir, el->el_search.chacha, @@ -779,9 +788,9 @@ vi_repeat_next_char(EditLine *el, int 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, int c __attribute__((__unused__))) +vi_repeat_prev_char(EditLine *el, wint_t c __attribute__((__unused__))) { el_action_t r; int dir = el->el_search.chadir; @@ -797,22 +806,22 @@ vi_repeat_prev_char(EditLine *el, int c __attribute__((__unused__))) * Vi go to matching () {} or [] * [%] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_match(EditLine *el, int c) +vi_match(EditLine *el, wint_t c __attribute__((__unused__))) { - const char match_chars[] = "()[]{}"; - 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 = 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; @@ -835,18 +844,18 @@ vi_match(EditLine *el, int c) if (delta > 0) el->el_line.cursor++; cv_delfini(el); - return (CC_REFRESH); + return CC_REFRESH; } - return (CC_CURSOR); + return CC_CURSOR; } /* vi_undo_line(): * Vi undo all changes to line * [U] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_undo_line(EditLine *el, int c) +vi_undo_line(EditLine *el, wint_t c __attribute__((__unused__))) { cv_undo(el); @@ -858,9 +867,9 @@ vi_undo_line(EditLine *el, int c) * [|] * 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, int c) +vi_to_column(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.buffer; @@ -872,9 +881,9 @@ vi_to_column(EditLine *el, int c) * Vi yank to end of line * [Y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_yank_end(EditLine *el, int c) +vi_yank_end(EditLine *el, wint_t c __attribute__((__unused__))) { cv_yank(el, el->el_line.cursor, @@ -886,9 +895,9 @@ vi_yank_end(EditLine *el, int c) * Vi yank * [y] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_yank(EditLine *el, int c) +vi_yank(EditLine *el, wint_t c __attribute__((__unused__))) { return cv_action(el, YANK); @@ -898,9 +907,9 @@ vi_yank(EditLine *el, int c) * Vi comment out current command * [#] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_comment_out(EditLine *el, int c) +vi_comment_out(EditLine *el, wint_t c __attribute__((__unused__))) { el->el_line.cursor = el->el_line.buffer; @@ -916,49 +925,42 @@ vi_comment_out(EditLine *el, int c) * NB: posix implies that we should enter insert mode, however * this is against historical precedent... */ -#ifdef __weak_reference -extern char *get_alias_text(const char *) __weak_reference(get_alias_text); -#endif -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_alias(EditLine *el, int c) +vi_alias(EditLine *el, wint_t c __attribute__((__unused__))) { -#ifdef __weak_reference char alias_name[3]; - char *alias_text; + const char *alias_text; - if (get_alias_text == 0) { + if (el->el_chared.c_aliasfun == NULL) return CC_ERROR; - } alias_name[0] = '_'; alias_name[2] = 0; if (el_getc(el, &alias_name[1]) != 1) return CC_ERROR; - alias_text = get_alias_text(alias_name); + alias_text = (*el->el_chared.c_aliasfun)(el->el_chared.c_aliasarg, + alias_name); if (alias_text != NULL) - el_push(el, alias_text); + el_wpush(el, ct_decode_string(alias_text, &el->el_scratch)); return CC_NORM; -#else - return CC_ERROR; -#endif } /* vi_to_history_line(): * Vi go to specified history file line. * [G] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_to_history_line(EditLine *el, int c) +vi_to_history_line(EditLine *el, wint_t c __attribute__((__unused__))) { int sv_event_no = el->el_history.eventno; el_action_t rval; 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); @@ -977,7 +979,7 @@ vi_to_history_line(EditLine *el, int c) el->el_history.eventno = 1; if (hist_get(el) == CC_ERROR) return CC_ERROR; - el->el_history.eventno = 1 + el->el_history.ev.num + el->el_history.eventno = 1 + el->el_history.ev.num - el->el_state.argument; if (el->el_history.eventno < 0) { el->el_history.eventno = sv_event_no; @@ -994,48 +996,72 @@ vi_to_history_line(EditLine *el, int c) * Vi edit history line with vi * [v] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_histedit(EditLine *el, int c) +vi_histedit(EditLine *el, wint_t c __attribute__((__unused__))) { int fd; pid_t pid; ssize_t st; int status; char tempfile[] = "/tmp/histedit.XXXXXXXXXX"; - char *cp; + char *cp = NULL; + size_t len; + wchar_t *line = NULL; + const char *editor; if (el->el_state.doingarg) { if (vi_to_history_line(el, 0) == CC_ERROR) return CC_ERROR; } + if ((editor = getenv("EDITOR")) == NULL) + editor = "vi"; fd = mkstemp(tempfile); if (fd < 0) return CC_ERROR; - cp = el->el_line.buffer; - write(fd, cp, (size_t)(el->el_line.lastchar - cp)); - write(fd, "\n", 1); + len = (size_t)(el->el_line.lastchar - el->el_line.buffer); +#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX) + cp = el_calloc(TMP_BUFSIZ, sizeof(*cp)); + if (cp == NULL) + goto error; + line = el_calloc(len + 1, sizeof(*line)); + if (line == NULL) + goto error; + wcsncpy(line, el->el_line.buffer, len); + line[len] = '\0'; + wcstombs(cp, line, TMP_BUFSIZ - 1); + cp[TMP_BUFSIZ - 1] = '\0'; + len = strlen(cp); + write(fd, cp, len); + write(fd, "\n", (size_t)1); pid = fork(); switch (pid) { case -1: - close(fd); - unlink(tempfile); - return CC_ERROR; + goto error; case 0: close(fd); - execlp("vi", "vi", tempfile, (char *)NULL); + execlp(editor, editor, tempfile, (char *)NULL); exit(0); /*NOTREACHED*/ default: while (waitpid(pid, &status, 0) != pid) continue; lseek(fd, (off_t)0, SEEK_SET); - st = read(fd, cp, (size_t)(el->el_line.limit - cp)); - if (st > 0 && cp[st - 1] == '\n') - st--; - el->el_line.cursor = cp; - el->el_line.lastchar = cp + st; + st = read(fd, cp, TMP_BUFSIZ - 1); + if (st > 0) { + cp[st] = '\0'; + len = (size_t)(el->el_line.limit - el->el_line.buffer); + len = mbstowcs(el->el_line.buffer, cp, len); + if (len > 0 && el->el_line.buffer[len - 1] == '\n') + --len; + } + else + len = 0; + el->el_line.cursor = el->el_line.buffer; + el->el_line.lastchar = el->el_line.buffer + len; + el_free(cp); + el_free(line); break; } @@ -1043,6 +1069,12 @@ vi_histedit(EditLine *el, int c) unlink(tempfile); /* return CC_REFRESH; */ return ed_newline(el, 0); +error: + el_free(line); + el_free(cp); + close(fd); + unlink(tempfile); + return CC_ERROR; } /* vi_history_word(): @@ -1051,32 +1083,33 @@ vi_histedit(EditLine *el, int c) * 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, int c) +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 = 0; + wep = wsp = NULL; do { - while (isspace((unsigned char)*wp)) + while (iswspace(*wp)) wp++; if (*wp == 0) break; wsp = wp; - while (*wp && !isspace((unsigned char)*wp)) + while (*wp && !iswspace(*wp)) wp++; wep = wp; - } while ((!el->el_state.doingarg || --el->el_state.argument > 0) && *wp != 0); + } while ((!el->el_state.doingarg || --el->el_state.argument > 0) + && *wp != 0); - if (wsp == 0 || (el->el_state.doingarg && el->el_state.argument != 0)) + if (wsp == NULL || (el->el_state.doingarg && el->el_state.argument != 0)) return CC_ERROR; cv_undo(el); @@ -1100,9 +1133,9 @@ vi_history_word(EditLine *el, int c) * Vi redo last non-motion command * [.] */ -protected el_action_t +libedit_private el_action_t /*ARGSUSED*/ -vi_redo(EditLine *el, int c) +vi_redo(EditLine *el, wint_t c __attribute__((__unused__))) { c_redo_t *r = &el->el_chared.c_redo; @@ -1118,10 +1151,10 @@ vi_redo(EditLine *el, int c) /* sanity */ r->pos = r->lim - 1; r->pos[0] = 0; - el_push(el, r->buf); + el_wpush(el, r->buf); } el->el_state.thiscmd = r->cmd; el->el_state.thisch = r->ch; - return (*el->el_map.func[r->cmd])(el, r->ch); + return (*el->el_map.func[r->cmd])(el, r->ch); } diff --git a/clt/falcon/editline/src/vis.c b/clt/falcon/editline/src/vis.c index b3c790c77..bfe223395 100644 --- a/clt/falcon/editline/src/vis.c +++ b/clt/falcon/editline/src/vis.c @@ -1,4 +1,4 @@ -/* $NetBSD: vis.c,v 1.40 2009/02/11 13:52:28 christos Exp $ */ +/* $NetBSD: vis.c,v 1.75 2021/06/18 10:57:14 christos Exp $ */ /*- * Copyright (c) 1989, 1993 @@ -55,76 +55,129 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" + #if defined(LIBC_SCCS) && !defined(lint) -__RCSID("$NetBSD: vis.c,v 1.40 2009/02/11 13:52:28 christos Exp $"); +__RCSID("$NetBSD: vis.c,v 1.75 2021/06/18 10:57:14 christos Exp $"); #endif /* LIBC_SCCS and not lint */ +#ifdef __FBSDID +__FBSDID("$FreeBSD$"); +#endif #include +#include +#include #include #include +#include #include +#include +#include #ifdef __weak_alias -__weak_alias(strsvis,_strsvis) -__weak_alias(strsvisx,_strsvisx) -__weak_alias(strvis,_strvis) __weak_alias(strvisx,_strvisx) -__weak_alias(svis,_svis) -__weak_alias(vis,_vis) #endif -#if !HAVE_VIS || !HAVE_SVIS +#if !defined(HAVE_VIS) || !defined(HAVE_SVIS) #include #include #include #include -static char *do_svis(char *, int, int, int, const char *); +/* + * The reason for going through the trouble to deal with character encodings + * in vis(3), is that we use this to safe encode output of commands. This + * safe encoding varies depending on the character set. For example if we + * display ps output in French, we don't want to display French characters + * as M-foo. + */ + +static wchar_t *do_svis(wchar_t *, wint_t, int, wint_t, const wchar_t *); #undef BELL -#define BELL '\a' - -#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7') -#define iswhite(c) (c == ' ' || c == '\t' || c == '\n') -#define issafe(c) (c == '\b' || c == BELL || c == '\r') -#define xtoa(c) "0123456789abcdef"[c] -#define XTOA(c) "0123456789ABCDEF"[c] - -#define MAXEXTRAS 5 - -#define MAKEEXTRALIST(flag, extra, orig_str) \ -do { \ - const char *orig = orig_str; \ - const char *o = orig; \ - char *e; \ - while (*o++) \ - continue; \ - extra = malloc((size_t)((o - orig) + MAXEXTRAS)); \ - if (!extra) break; \ - for (o = orig, e = extra; (*e++ = *o++) != '\0';) \ - continue; \ - e--; \ - if (flag & VIS_SP) *e++ = ' '; \ - if (flag & VIS_TAB) *e++ = '\t'; \ - if (flag & VIS_NL) *e++ = '\n'; \ - if ((flag & VIS_NOSLASH) == 0) *e++ = '\\'; \ - *e = '\0'; \ -} while (/*CONSTCOND*/0) +#define BELL L'\a' + +#if defined(LC_C_LOCALE) +#define iscgraph(c) isgraph_l(c, LC_C_LOCALE) +#else +/* Keep it simple for now, no locale stuff */ +#define iscgraph(c) isgraph(c) +#ifdef notyet +#include +static int +iscgraph(int c) { + int rv; + char *ol; + + ol = setlocale(LC_CTYPE, "C"); + rv = isgraph(c); + if (ol) + setlocale(LC_CTYPE, ol); + return rv; +} +#endif +#endif + +#define ISGRAPH(flags, c) \ + (((flags) & VIS_NOLOCALE) ? iscgraph(c) : iswgraph(c)) + +#define iswoctal(c) (((u_char)(c)) >= L'0' && ((u_char)(c)) <= L'7') +#define iswwhite(c) (c == L' ' || c == L'\t' || c == L'\n') +#define iswsafe(c) (c == L'\b' || c == BELL || c == L'\r') +#define xtoa(c) L"0123456789abcdef"[c] +#define XTOA(c) L"0123456789ABCDEF"[c] + +#define MAXEXTRAS 30 + +static const wchar_t char_shell[] = L"'`\";&<>()|{}]\\$!^~"; +static const wchar_t char_glob[] = L"*?[#"; + +#if !HAVE_NBTOOL_CONFIG_H +#ifndef __NetBSD__ +/* + * On NetBSD MB_LEN_MAX is currently 32 which does not fit on any integer + * integral type and it is probably wrong, since currently the maximum + * number of bytes and character needs is 6. Until this is fixed, the + * loops below are using sizeof(uint64_t) - 1 instead of MB_LEN_MAX, and + * the assertion is commented out. + */ +#ifdef __FreeBSD__ +/* + * On FreeBSD including for CTASSERT only works in kernel + * mode. + */ +#ifndef CTASSERT +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] +#endif +#endif /* __FreeBSD__ */ +/* +CTASSERT(MB_LEN_MAX <= sizeof(uint64_t)); +*/ +#endif /* !__NetBSD__ */ +#endif /* * This is do_hvis, for HTTP style (RFC 1808) */ -static char * -do_hvis(char *dst, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_hvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - if (!isascii(c) || !isalnum(c) || strchr("$-_.+!*'(),", c) != NULL) { - *dst++ = '%'; + if (iswalnum(c) + /* safe */ + || c == L'$' || c == L'-' || c == L'_' || c == L'.' || c == L'+' + /* extra */ + || c == L'!' || c == L'*' || c == L'\'' || c == L'(' || c == L')' + || c == L',') + dst = do_svis(dst, c, flags, nextc, extra); + else { + *dst++ = L'%'; *dst++ = xtoa(((unsigned int)c >> 4) & 0xf); *dst++ = xtoa((unsigned int)c & 0xf); - } else { - dst = do_svis(dst, c, flag, nextc, extra); } + return dst; } @@ -132,283 +185,590 @@ do_hvis(char *dst, int c, int flag, int nextc, const char *extra) * This is do_mvis, for Quoted-Printable MIME (RFC 2045) * NB: No handling of long lines or CRLF. */ -static char * -do_mvis(char *dst, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_mvis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) { - if ((c != '\n') && + if ((c != L'\n') && /* Space at the end of the line */ - ((isspace(c) && (nextc == '\r' || nextc == '\n')) || + ((iswspace(c) && (nextc == L'\r' || nextc == L'\n')) || /* Out of range */ - (!isspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || - /* Specific char to be escaped */ - strchr("#$@[\\]^`{|}~", c) != NULL)) { - *dst++ = '='; + (!iswspace(c) && (c < 33 || (c > 60 && c < 62) || c > 126)) || + /* Specific char to be escaped */ + wcschr(L"#$@[\\]^`{|}~", c) != NULL)) { + *dst++ = L'='; *dst++ = XTOA(((unsigned int)c >> 4) & 0xf); *dst++ = XTOA((unsigned int)c & 0xf); - } else { - dst = do_svis(dst, c, flag, nextc, extra); - } + } else + dst = do_svis(dst, c, flags, nextc, extra); return dst; } /* - * This is do_vis, the central code of vis. - * dst: Pointer to the destination buffer - * c: Character to encode - * flag: Flag word - * nextc: The character following 'c' - * extra: Pointer to the list of extra characters to be - * backslash-protected. + * Output single byte of multibyte character. */ -static char * -do_svis(char *dst, int c, int flag, int nextc, const char *extra) +static wchar_t * +do_mbyte(wchar_t *dst, wint_t c, int flags, wint_t nextc, int iswextra) { - int isextra; - isextra = strchr(extra, c) != NULL; - if (!isextra && isascii(c) && (isgraph(c) || iswhite(c) || - ((flag & VIS_SAFE) && issafe(c)))) { - *dst++ = c; - return dst; - } - if (flag & VIS_CSTYLE) { + if (flags & VIS_CSTYLE) { switch (c) { - case '\n': - *dst++ = '\\'; *dst++ = 'n'; + case L'\n': + *dst++ = L'\\'; *dst++ = L'n'; return dst; - case '\r': - *dst++ = '\\'; *dst++ = 'r'; + case L'\r': + *dst++ = L'\\'; *dst++ = L'r'; return dst; - case '\b': - *dst++ = '\\'; *dst++ = 'b'; + case L'\b': + *dst++ = L'\\'; *dst++ = L'b'; return dst; case BELL: - *dst++ = '\\'; *dst++ = 'a'; + *dst++ = L'\\'; *dst++ = L'a'; return dst; - case '\v': - *dst++ = '\\'; *dst++ = 'v'; + case L'\v': + *dst++ = L'\\'; *dst++ = L'v'; return dst; - case '\t': - *dst++ = '\\'; *dst++ = 't'; + case L'\t': + *dst++ = L'\\'; *dst++ = L't'; return dst; - case '\f': - *dst++ = '\\'; *dst++ = 'f'; + case L'\f': + *dst++ = L'\\'; *dst++ = L'f'; return dst; - case ' ': - *dst++ = '\\'; *dst++ = 's'; + case L' ': + *dst++ = L'\\'; *dst++ = L's'; return dst; - case '\0': - *dst++ = '\\'; *dst++ = '0'; - if (isoctal(nextc)) { - *dst++ = '0'; - *dst++ = '0'; + case L'\0': + *dst++ = L'\\'; *dst++ = L'0'; + if (iswoctal(nextc)) { + *dst++ = L'0'; + *dst++ = L'0'; } return dst; + /* We cannot encode these characters in VIS_CSTYLE + * because they special meaning */ + case L'n': + case L'r': + case L'b': + case L'a': + case L'v': + case L't': + case L'f': + case L's': + case L'0': + case L'M': + case L'^': + case L'$': /* vis(1) -l */ + break; default: - if (isgraph(c)) { - *dst++ = '\\'; *dst++ = c; + if (ISGRAPH(flags, c) && !iswoctal(c)) { + *dst++ = L'\\'; + *dst++ = c; return dst; } } } - if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) { - *dst++ = '\\'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + '0'; - *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + '0'; - *dst++ = (c & 07) + '0'; + if (iswextra || ((c & 0177) == L' ') || (flags & VIS_OCTAL)) { + *dst++ = L'\\'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 6) & 03) + L'0'; + *dst++ = (u_char)(((u_int32_t)(u_char)c >> 3) & 07) + L'0'; + *dst++ = (c & 07) + L'0'; } else { - if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\'; + if ((flags & VIS_NOSLASH) == 0) + *dst++ = L'\\'; + if (c & 0200) { - c &= 0177; *dst++ = 'M'; + c &= 0177; + *dst++ = L'M'; } - if (iscntrl(c)) { - *dst++ = '^'; + + if (iswcntrl(c)) { + *dst++ = L'^'; if (c == 0177) - *dst++ = '?'; + *dst++ = L'?'; else - *dst++ = c + '@'; + *dst++ = c + L'@'; } else { - *dst++ = '-'; *dst++ = c; + *dst++ = L'-'; + *dst++ = c; } } + return dst; } -typedef char *(*visfun_t)(char *, int, int, int, const char *); +/* + * This is do_vis, the central code of vis. + * dst: Pointer to the destination buffer + * c: Character to encode + * flags: Flags word + * nextc: The character following 'c' + * extra: Pointer to the list of extra characters to be + * backslash-protected. + */ +static wchar_t * +do_svis(wchar_t *dst, wint_t c, int flags, wint_t nextc, const wchar_t *extra) +{ + int iswextra, i, shft; + uint64_t bmsk, wmsk; + + iswextra = wcschr(extra, c) != NULL; + if (!iswextra && (ISGRAPH(flags, c) || iswwhite(c) || + ((flags & VIS_SAFE) && iswsafe(c)))) { + *dst++ = c; + return dst; + } + + /* See comment in istrsenvisx() output loop, below. */ + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((c & wmsk) || i == 0) + dst = do_mbyte(dst, (wint_t)( + (uint64_t)(c & bmsk) >> shft), + flags, nextc, iswextra); + } + + return dst; +} + +typedef wchar_t *(*visfun_t)(wchar_t *, wint_t, int, wint_t, const wchar_t *); /* * Return the appropriate encoding function depending on the flags given. */ static visfun_t -getvisfun(int flag) +getvisfun(int flags) { - if (flag & VIS_HTTPSTYLE) + if (flags & VIS_HTTPSTYLE) return do_hvis; - if (flag & VIS_MIMESTYLE) + if (flags & VIS_MIMESTYLE) return do_mvis; return do_svis; } /* - * svis - visually encode characters, also encoding the characters - * pointed to by `extra' + * Expand list of extra characters to not visually encode. */ -char * -svis(char *dst, int c, int flag, int nextc, const char *extra) +static wchar_t * +makeextralist(int flags, const char *src) { - char *nextra = NULL; - visfun_t f; + wchar_t *dst, *d; + size_t len; + const wchar_t *s; + mbstate_t mbstate; + + len = strlen(src); + if ((dst = calloc(len + MAXEXTRAS, sizeof(*dst))) == NULL) + return NULL; + + memset(&mbstate, 0, sizeof(mbstate)); + if ((flags & VIS_NOLOCALE) + || mbsrtowcs(dst, &src, len, &mbstate) == (size_t)-1) { + size_t i; + for (i = 0; i < len; i++) + dst[i] = (wchar_t)(u_char)src[i]; + d = dst + len; + } else + d = dst + wcslen(dst); + + if (flags & VIS_GLOB) + for (s = char_glob; *s; *d++ = *s++) + continue; + + if (flags & VIS_SHELL) + for (s = char_shell; *s; *d++ = *s++) + continue; + + if (flags & VIS_SP) *d++ = L' '; + if (flags & VIS_TAB) *d++ = L'\t'; + if (flags & VIS_NL) *d++ = L'\n'; + if (flags & VIS_DQ) *d++ = L'"'; + if ((flags & VIS_NOSLASH) == 0) *d++ = L'\\'; + *d = L'\0'; - _DIAGASSERT(dst != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - *dst = '\0'; /* can't create nextra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, c, flag, nextc, nextra); - free(nextra); - *dst = '\0'; return dst; } - /* - * strsvis, strsvisx - visually encode characters from src into dst - * - * Extra is a pointer to a \0-terminated list of characters to - * be encoded, too. These functions are useful e. g. to - * encode strings in such a way so that they are not interpreted - * by a shell. - * - * Dst must be 4 times the size of src to account for possible - * expansion. The length of dst, not including the trailing NULL, - * is returned. - * - * Strsvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. + * istrsenvisx() + * The main internal function. + * All user-visible functions call this one. */ -int -strsvis(char *dst, const char *csrc, int flag, const char *extra) +static int +istrsenvisx(char **mbdstp, size_t *dlen, const char *mbsrc, size_t mblength, + int flags, const char *mbextra, int *cerr_ptr) { - int c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; + wchar_t *dst, *src, *pdst, *psrc, *start, *extra; + size_t len, olen; + uint64_t bmsk, wmsk; + wint_t c; visfun_t f; - - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (!nextra) { - *dst = '\0'; /* can't create nextra, return "" */ - return 0; + int clen = 0, cerr, error = -1, i, shft; + char *mbdst, *mdst; + ssize_t mbslength, maxolen; + mbstate_t mbstate; + + _DIAGASSERT(mbdstp != NULL); + _DIAGASSERT(mbsrc != NULL || mblength == 0); + _DIAGASSERT(mbextra != NULL); + + mbslength = (ssize_t)mblength; + /* + * When inputing a single character, must also read in the + * next character for nextc, the look-ahead character. + */ + if (mbslength == 1) + mbslength++; + + /* + * Input (mbsrc) is a char string considered to be multibyte + * characters. The input loop will read this string pulling + * one character, possibly multiple bytes, from mbsrc and + * converting each to wchar_t in src. + * + * The vis conversion will be done using the wide char + * wchar_t string. + * + * This will then be converted back to a multibyte string to + * return to the caller. + */ + + /* Allocate space for the wide char strings */ + psrc = pdst = extra = NULL; + mdst = NULL; + if ((psrc = calloc(mbslength + 1, sizeof(*psrc))) == NULL) + return -1; + if ((pdst = calloc((16 * mbslength) + 1, sizeof(*pdst))) == NULL) + goto out; + if (*mbdstp == NULL) { + if ((mdst = calloc((16 * mbslength) + 1, sizeof(*mdst))) == NULL) + goto out; + *mbdstp = mdst; } - f = getvisfun(flag); - for (start = dst; (c = *src++) != '\0'; /* empty */) - dst = (*f)(dst, c, flag, *src, nextra); - free(nextra); - *dst = '\0'; - return (int)(dst - start); -} + mbdst = *mbdstp; + dst = pdst; + src = psrc; -int -strsvisx(char *dst, const char *csrc, size_t len, int flag, const char *extra) -{ - unsigned char c; - char *start; - char *nextra = NULL; - const unsigned char *src = (const unsigned char *)csrc; - visfun_t f; + if (flags & VIS_NOLOCALE) { + /* Do one byte at a time conversion */ + cerr = 1; + } else { + /* Use caller's multibyte conversion error flag. */ + cerr = cerr_ptr ? *cerr_ptr : 0; + } - _DIAGASSERT(dst != NULL); - _DIAGASSERT(src != NULL); - _DIAGASSERT(extra != NULL); - MAKEEXTRALIST(flag, nextra, extra); - if (! nextra) { - *dst = '\0'; /* can't create nextra, return "" */ - return 0; + /* + * Input loop. + * Handle up to mblength characters (not bytes). We do not + * stop at NULs because we may be processing a block of data + * that includes NULs. + */ + memset(&mbstate, 0, sizeof(mbstate)); + while (mbslength > 0) { + /* Convert one multibyte character to wchar_t. */ + if (!cerr) + clen = mbrtowc(src, mbsrc, MIN(mbslength, MB_LEN_MAX), + &mbstate); + if (cerr || clen < 0) { + /* Conversion error, process as a byte instead. */ + *src = (wint_t)(u_char)*mbsrc; + clen = 1; + cerr = 1; + } + if (clen == 0) { + /* + * NUL in input gives 0 return value. process + * as single NUL byte and keep going. + */ + clen = 1; + } + /* Advance buffer character pointer. */ + src++; + /* Advance input pointer by number of bytes read. */ + mbsrc += clen; + /* Decrement input byte count. */ + mbslength -= clen; + } + len = src - psrc; + src = psrc; + + /* + * In the single character input case, we will have actually + * processed two characters, c and nextc. Reset len back to + * just a single character. + */ + if (mblength < len) + len = mblength; + + /* Convert extra argument to list of characters for this mode. */ + extra = makeextralist(flags, mbextra); + if (!extra) { + if (dlen && *dlen == 0) { + errno = ENOSPC; + goto out; + } + *mbdst = '\0'; /* can't create extra, return "" */ + error = 0; + goto out; } - f = getvisfun(flag); + /* Look up which processing function to call. */ + f = getvisfun(flags); + + /* + * Main processing loop. + * Call do_Xvis processing function one character at a time + * with next character available for look-ahead. + */ for (start = dst; len > 0; len--) { c = *src++; - dst = (*f)(dst, c, flag, len > 1 ? *src : '\0', nextra); + dst = (*f)(dst, c, flags, len >= 1 ? *src : L'\0', extra); + if (dst == NULL) { + errno = ENOSPC; + goto out; + } } - free(nextra); - *dst = '\0'; - return (int)(dst - start); + + /* Terminate the string in the buffer. */ + *dst = L'\0'; + + /* + * Output loop. + * Convert wchar_t string back to multibyte output string. + * If we have hit a multi-byte conversion error on input, + * output byte-by-byte here. Else use wctomb(). + */ + len = wcslen(start); + maxolen = dlen ? *dlen : (wcslen(start) * MB_LEN_MAX + 1); + olen = 0; + memset(&mbstate, 0, sizeof(mbstate)); + for (dst = start; len > 0; len--) { + if (!cerr) + clen = wcrtomb(mbdst, *dst, &mbstate); + if (cerr || clen < 0) { + /* + * Conversion error, process as a byte(s) instead. + * Examine each byte and higher-order bytes for + * data. E.g., + * 0x000000000000a264 -> a2 64 + * 0x000000001f00a264 -> 1f 00 a2 64 + */ + clen = 0; + wmsk = 0; + for (i = sizeof(wmsk) - 1; i >= 0; i--) { + shft = i * NBBY; + bmsk = (uint64_t)0xffLL << shft; + wmsk |= bmsk; + if ((*dst & wmsk) || i == 0) + mbdst[clen++] = (char)( + (uint64_t)(*dst & bmsk) >> + shft); + } + cerr = 1; + } + /* If this character would exceed our output limit, stop. */ + if (olen + clen > (size_t)maxolen) + break; + /* Advance output pointer by number of bytes written. */ + mbdst += clen; + /* Advance buffer character pointer. */ + dst++; + /* Incrment output character count. */ + olen += clen; + } + + /* Terminate the output string. */ + *mbdst = '\0'; + + if (flags & VIS_NOLOCALE) { + /* Pass conversion error flag out. */ + if (cerr_ptr) + *cerr_ptr = cerr; + } + + free(extra); + free(pdst); + free(psrc); + + return (int)olen; +out: + free(extra); + free(pdst); + free(psrc); + free(mdst); + return error; +} + +static int +istrsenvisxl(char **mbdstp, size_t *dlen, const char *mbsrc, + int flags, const char *mbextra, int *cerr_ptr) +{ + return istrsenvisx(mbdstp, dlen, mbsrc, + mbsrc != NULL ? strlen(mbsrc) : 0, flags, mbextra, cerr_ptr); +} + +#endif + +#if !HAVE_SVIS +/* + * The "svis" variants all take an "extra" arg that is a pointer + * to a NUL-terminated list of characters to be encoded, too. + * These functions are useful e. g. to encode strings in such a + * way so that they are not interpreted by a shell. + */ + +char * +svis(char *mbdst, int c, int flags, int nextc, const char *mbextra) +{ + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(&mbdst, NULL, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} + +char * +snvis(char *mbdst, size_t dlen, int c, int flags, int nextc, const char *mbextra) +{ + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(&mbdst, &dlen, cc, 1, flags, mbextra, NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} + +int +strsvis(char *mbdst, const char *mbsrc, int flags, const char *mbextra) +{ + return istrsenvisxl(&mbdst, NULL, mbsrc, flags, mbextra, NULL); +} + +int +strsnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags, const char *mbextra) +{ + return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, mbextra, NULL); +} + +int +strsvisx(char *mbdst, const char *mbsrc, size_t len, int flags, const char *mbextra) +{ + return istrsenvisx(&mbdst, NULL, mbsrc, len, flags, mbextra, NULL); +} + +int +strsnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra) +{ + return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, mbextra, NULL); +} + +int +strsenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + const char *mbextra, int *cerr_ptr) +{ + return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, mbextra, cerr_ptr); } #endif -#if !HAVE_VIS +#ifndef HAVE_VIS /* * vis - visually encode characters */ char * -vis(char *dst, int c, int flag, int nextc) +vis(char *mbdst, int c, int flags, int nextc) { - char *extra = NULL; - unsigned char uc = (unsigned char)c; - visfun_t f; + char cc[2]; + int ret; - _DIAGASSERT(dst != NULL); + cc[0] = c; + cc[1] = nextc; - MAKEEXTRALIST(flag, extra, ""); - if (! extra) { - *dst = '\0'; /* can't create extra, return "" */ - return dst; - } - f = getvisfun(flag); - dst = (*f)(dst, uc, flag, nextc, extra); - free(extra); - *dst = '\0'; - return dst; + ret = istrsenvisx(&mbdst, NULL, cc, 1, flags, "", NULL); + if (ret < 0) + return NULL; + return mbdst + ret; } +char * +nvis(char *mbdst, size_t dlen, int c, int flags, int nextc) +{ + char cc[2]; + int ret; + + cc[0] = c; + cc[1] = nextc; + + ret = istrsenvisx(&mbdst, &dlen, cc, 1, flags, "", NULL); + if (ret < 0) + return NULL; + return mbdst + ret; +} /* - * strvis, strvisx - visually encode characters from src into dst + * strvis - visually encode characters from src into dst * * Dst must be 4 times the size of src to account for possible * expansion. The length of dst, not including the trailing NULL, * is returned. - * - * Strvisx encodes exactly len bytes from src into dst. - * This is useful for encoding a block of data. */ + int -strvis(char *dst, const char *src, int flag) +strvis(char *mbdst, const char *mbsrc, int flags) { - char *extra = NULL; - int rv; + return istrsenvisxl(&mbdst, NULL, mbsrc, flags, "", NULL); +} - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = strsvis(dst, src, flag, extra); - free(extra); - return rv; +int +strnvis(char *mbdst, size_t dlen, const char *mbsrc, int flags) +{ + return istrsenvisxl(&mbdst, &dlen, mbsrc, flags, "", NULL); } +int +stravis(char **mbdstp, const char *mbsrc, int flags) +{ + *mbdstp = NULL; + return istrsenvisxl(mbdstp, NULL, mbsrc, flags, "", NULL); +} + +/* + * strvisx - visually encode characters from src into dst + * + * Dst must be 4 times the size of src to account for possible + * expansion. The length of dst, not including the trailing NULL, + * is returned. + * + * Strvisx encodes exactly len characters from src into dst. + * This is useful for encoding a block of data. + */ int -strvisx(char *dst, const char *src, size_t len, int flag) +strvisx(char *mbdst, const char *mbsrc, size_t len, int flags) { - char *extra = NULL; - int rv; + return istrsenvisx(&mbdst, NULL, mbsrc, len, flags, "", NULL); +} - MAKEEXTRALIST(flag, extra, ""); - if (!extra) { - *dst = '\0'; /* can't create extra, return "" */ - return 0; - } - rv = strsvisx(dst, src, len, flag, extra); - free(extra); - return rv; +int +strnvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags) +{ + return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, "", NULL); +} + +int +strenvisx(char *mbdst, size_t dlen, const char *mbsrc, size_t len, int flags, + int *cerr_ptr) +{ + return istrsenvisx(&mbdst, &dlen, mbsrc, len, flags, "", cerr_ptr); } #endif diff --git a/clt/falcon/editline/src/vis.h b/clt/falcon/editline/src/vis.h index f262f2644..65ee43300 100644 --- a/clt/falcon/editline/src/vis.h +++ b/clt/falcon/editline/src/vis.h @@ -1,4 +1,4 @@ -/* $NetBSD: vis.h,v 1.17 2009/02/10 23:06:31 christos Exp $ */ +/* $NetBSD: vis.h,v 1.26 2022/05/20 21:31:24 andvar Exp $ */ /*- * Copyright (c) 1990, 1993 @@ -34,30 +34,37 @@ #ifndef _VIS_H_ #define _VIS_H_ -#include - /* * to select alternate encoding format */ -#define VIS_OCTAL 0x001 /* use octal \ddd format */ -#define VIS_CSTYLE 0x002 /* use \[nrft0..] where appropiate */ +#define VIS_OCTAL 0x0001 /* use octal \ddd format */ +#define VIS_CSTYLE 0x0002 /* use \[nrft0..] where appropriate */ /* * to alter set of characters encoded (default is to encode all * non-graphic except space, tab, and newline). */ -#define VIS_SP 0x004 /* also encode space */ -#define VIS_TAB 0x008 /* also encode tab */ -#define VIS_NL 0x010 /* also encode newline */ +#define VIS_SP 0x0004 /* also encode space */ +#define VIS_TAB 0x0008 /* also encode tab */ +#define VIS_NL 0x0010 /* also encode newline */ #define VIS_WHITE (VIS_SP | VIS_TAB | VIS_NL) -#define VIS_SAFE 0x020 /* only encode "unsafe" characters */ +#define VIS_SAFE 0x0020 /* only encode "unsafe" characters */ +#define VIS_DQ 0x8000 /* also encode double quotes */ /* * other */ -#define VIS_NOSLASH 0x040 /* inhibit printing '\' */ -#define VIS_HTTPSTYLE 0x080 /* http-style escape % hex hex */ -#define VIS_MIMESTYLE 0x100 /* mime-style escape = HEX HEX */ +#define VIS_NOSLASH 0x0040 /* inhibit printing '\' */ +#define VIS_HTTP1808 0x0080 /* http-style escape % hex hex */ +#define VIS_HTTPSTYLE 0x0080 /* http-style escape % hex hex */ +#define VIS_MIMESTYLE 0x0100 /* mime-style escape = HEX HEX */ +#define VIS_HTTP1866 0x0200 /* http-style &#num; or &string; */ +#define VIS_NOESCAPE 0x0400 /* don't decode `\' */ +#define _VIS_END 0x0800 /* for unvis */ +#define VIS_GLOB 0x1000 /* encode glob(3) magic characters */ +#define VIS_SHELL 0x2000 /* encode shell special characters [not glob] */ +#define VIS_META (VIS_WHITE | VIS_GLOB | VIS_SHELL) +#define VIS_NOLOCALE 0x4000 /* encode using the C locale */ /* * unvis return codes @@ -71,17 +78,37 @@ /* * unvis flags */ -#define UNVIS_END 1 /* no more characters */ +#define UNVIS_END _VIS_END /* no more characters */ __BEGIN_DECLS char *vis(char *, int, int, int); +char *nvis(char *, size_t, int, int, int); + char *svis(char *, int, int, int, const char *); +char *snvis(char *, size_t, int, int, int, const char *); + int strvis(char *, const char *, int); +int stravis(char **, const char *, int); +int strnvis(char *, size_t, const char *, int); + int strsvis(char *, const char *, int, const char *); +int strsnvis(char *, size_t, const char *, int, const char *); + int strvisx(char *, const char *, size_t, int); +int strnvisx(char *, size_t, const char *, size_t, int); +int strenvisx(char *, size_t, const char *, size_t, int, int *); + int strsvisx(char *, const char *, size_t, int, const char *); +int strsnvisx(char *, size_t, const char *, size_t, int, const char *); +int strsenvisx(char *, size_t, const char *, size_t , int, const char *, + int *); + int strunvis(char *, const char *); +int strnunvis(char *, size_t, const char *); + int strunvisx(char *, const char *, int); +int strnunvisx(char *, size_t, const char *, int); + #ifndef __LIBC12_SOURCE__ int unvis(char *, int, int *, int); #endif diff --git a/clt/falcon/editline/src/wcsdup.c b/clt/falcon/editline/src/wcsdup.c new file mode 100644 index 000000000..2405e0d7e --- /dev/null +++ b/clt/falcon/editline/src/wcsdup.c @@ -0,0 +1,45 @@ +/* $NetBSD: wcsdup.c,v 1.6 2022/03/12 17:31:40 christos Exp $ */ + +/* + * Copyright (C) 2006 Aleksey Cheusov + * + * This material is provided "as is", with absolutely no warranty expressed + * or implied. Any use is at your own risk. + * + * Permission to use or copy this software for any purpose is hereby granted + * without fee. Permission to modify the code and to distribute modified + * code is also granted without any restrictions. + */ + +#ifndef HAVE_WCSDUP + +#include "config.h" + +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: wcsdup.c,v 1.6 2022/03/12 17:31:40 christos Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include + +wchar_t * +wcsdup(const wchar_t *str) +{ + wchar_t *copy; + size_t len; + + _DIAGASSERT(str != NULL); + + len = wcslen(str) + 1; + + copy = NULL; + errno = reallocarr(©, len, sizeof(*copy)); + if (errno) + return NULL; + + return wmemcpy(copy, str, len); +} + +#endif diff --git a/cmake/modules/FindEditline.cmake b/cmake/modules/FindEditline.cmake index 29a81aa76..a0396a5e6 100644 --- a/cmake/modules/FindEditline.cmake +++ b/cmake/modules/FindEditline.cmake @@ -1,24 +1,32 @@ -option(FALCON_WITH_GPL_READLINE "" off) -if(FALCON_WITH_GPL_READLINE) - set(_header readline/readline.h) - set(_libname readline) +### FindEditLine.cmake module for Falcon + +option( FALCON_WITH_GPL_READLINE "Insist on using GNU readline" OFF ) + +# unset these so that we can actually find GNU readline +unset( Editline_INCLUE_DIR CACHE ) +unset( Editline_LIBRARY CACHE ) + +if( FALCON_WITH_GPL_READLINE ) + set( _header readline/readline.h ) + set( _libname readline ) else() - set(_header editline/readline.h) - set(_libname edit) + set( _header editline/readline.h ) + set( _libname edit ) endif() -find_path(Editline_INCLUE_DIR ${_header}) -find_library(Editline_LIBRARY ${_libname}) +find_path( Editline_INCLUE_DIR ${_header} ) +find_library( Editline_LIBRARY ${_libname} ) + +include( CheckSymbolExists ) +set( CMAKE_REQUIRED_INCLUDES ${Editline_INCLUE_DIR} ) +set( CMAKE_REQUIRED_LIBRARIES ${Editline_LIBRARY} ) +check_symbol_exists( rl_getc_function "${_header}" HAVE_RL_GETC_FUNCTION ) -include(CheckSymbolExists) -set(CMAKE_REQUIRED_INCLUDES ${Editline_INCLUE_DIR}) -set(CMAKE_REQUIRED_LIBRARIES ${Editline_LIBRARY}) -check_symbol_exists(rl_getc_function "stdio.h;${_header}" - HAVE_RL_GETC_FUNCTION -) +include( FindPackageHandleStandardArgs ) +find_package_handle_standard_args( Editline DEFAULT_MSG + Editline_LIBRARY Editline_INCLUE_DIR HAVE_RL_GETC_FUNCTION ) -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(Editline DEFAULT_MSG Editline_LIBRARY Editline_INCLUE_DIR HAVE_RL_GETC_FUNCTION) +set( Editline_INCLUDE_DIRS ${Editline_INCLUE_DIR} ) +set( Editline_LIBRARIES ${Editline_LIBRARY} ) -set(Editline_INCLUDE_DIRS ${Editline_INCLUE_DIR}) -set(Editline_LIBRARIES ${Editline_LIBRARY}) \ No newline at end of file +# vi: ts=2 sw=2 et diff --git a/dist/nsis/CMakeLists.txt b/dist/nsis/CMakeLists.txt index c6e0110bb..996ce5436 100644 --- a/dist/nsis/CMakeLists.txt +++ b/dist/nsis/CMakeLists.txt @@ -1,7 +1,7 @@ # # Configurator for NSIS installer # -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) # # Files to be configured diff --git a/modules/native/MP/CMakeLists.txt b/modules/native/MP/CMakeLists.txt index 2b86107e0..f8eba5c40 100644 --- a/modules/native/MP/CMakeLists.txt +++ b/modules/native/MP/CMakeLists.txt @@ -5,7 +5,7 @@ #################################################################### PROJECT(MP) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) # Set here project-wide options # OPTION( WITH_OPT "An poption" OFF) diff --git a/modules/native/conio/CMakeLists.txt b/modules/native/conio/CMakeLists.txt index 104c9bcec..d828d7e09 100644 --- a/modules/native/conio/CMakeLists.txt +++ b/modules/native/conio/CMakeLists.txt @@ -4,7 +4,7 @@ # CMake configuration file for @PROJECT_NAME@ #################################################################### -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) project(conio) # find the falcon installation. Set CMAKE_INSTALL_PREFIX to the falcon root diff --git a/modules/native/curl/CMakeLists.txt b/modules/native/curl/CMakeLists.txt index 2f1e908e7..7d7a2377c 100644 --- a/modules/native/curl/CMakeLists.txt +++ b/modules/native/curl/CMakeLists.txt @@ -4,7 +4,7 @@ # CMake configuration file for curl #################################################################### -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) project(Falcon_curl) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/modules/native/dbi/CMakeLists.txt b/modules/native/dbi/CMakeLists.txt index 3a3f72c5f..20dbee902 100644 --- a/modules/native/dbi/CMakeLists.txt +++ b/modules/native/dbi/CMakeLists.txt @@ -3,7 +3,7 @@ # # CMake configuration file for DBI #################################################################### -cmake_minimum_required(VERSION 2.6.2) +cmake_minimum_required(VERSION 3.16.3) project(Falcon_DBI) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) diff --git a/modules/native/dbus/CMakeLists.txt b/modules/native/dbus/CMakeLists.txt index 4bd76ce38..09f575fa7 100644 --- a/modules/native/dbus/CMakeLists.txt +++ b/modules/native/dbus/CMakeLists.txt @@ -5,7 +5,7 @@ #################################################################### PROJECT(dbus) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) INCLUDE( ${CMAKE_ROOT}/Modules/FindPkgConfig.cmake) diff --git a/modules/native/dynlib/CMakeLists.txt b/modules/native/dynlib/CMakeLists.txt index 92bc09e59..6e1f31ec9 100644 --- a/modules/native/dynlib/CMakeLists.txt +++ b/modules/native/dynlib/CMakeLists.txt @@ -4,7 +4,7 @@ # CMake configuration file for dynlib #################################################################### -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) project(Falcon_dynlib) find_package(Falcon REQUIRED) diff --git a/modules/native/feathers/CMakeLists.txt b/modules/native/feathers/CMakeLists.txt index 7be6dca12..3591a4b9a 100644 --- a/modules/native/feathers/CMakeLists.txt +++ b/modules/native/feathers/CMakeLists.txt @@ -3,7 +3,7 @@ # # CMake configuration file for Feather modules #################################################################### -cmake_minimum_required(VERSION 2.6.2) +cmake_minimum_required(VERSION 3.16.3) PROJECT(Falcon_Feathers) # Find our Find*.cmake files diff --git a/modules/native/gd2/CMakeLists.txt b/modules/native/gd2/CMakeLists.txt index 7d775d1e7..73692d4fd 100644 --- a/modules/native/gd2/CMakeLists.txt +++ b/modules/native/gd2/CMakeLists.txt @@ -5,7 +5,7 @@ #################################################################### PROJECT(gd2) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) MESSAGE(STATUS "Building GD2 module" ) diff --git a/modules/native/gtk/CMakeLists.txt b/modules/native/gtk/CMakeLists.txt index 0f08e4bb3..f1bc647e9 100644 --- a/modules/native/gtk/CMakeLists.txt +++ b/modules/native/gtk/CMakeLists.txt @@ -3,7 +3,7 @@ # project( gtk ) -cmake_minimum_required( VERSION 2.6.3 ) +cmake_minimum_required( VERSION 3.16.3 ) list( APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ) diff --git a/modules/native/hpdf/CMakeLists.txt b/modules/native/hpdf/CMakeLists.txt index 679444146..cf86e9392 100644 --- a/modules/native/hpdf/CMakeLists.txt +++ b/modules/native/hpdf/CMakeLists.txt @@ -4,7 +4,7 @@ # CMake configuration file for Feather modules #################################################################### -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) project(falcon-module-hpdf) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") diff --git a/modules/native/sdl/CMakeLists.txt b/modules/native/sdl/CMakeLists.txt index 32a07dfd5..7d46ae513 100644 --- a/modules/native/sdl/CMakeLists.txt +++ b/modules/native/sdl/CMakeLists.txt @@ -6,7 +6,7 @@ if(COMMAND cmake_policy) cmake_policy(SET CMP0003 OLD) endif(COMMAND cmake_policy) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) PROJECT(Falcon_SDL) diff --git a/modules/native/wopi/CMakeLists.txt b/modules/native/wopi/CMakeLists.txt index 3f711cd6d..56e6c539b 100644 --- a/modules/native/wopi/CMakeLists.txt +++ b/modules/native/wopi/CMakeLists.txt @@ -3,7 +3,7 @@ # Falcon Web Oriented Programming Interface # -cmake_minimum_required(VERSION 2.6.2) +cmake_minimum_required(VERSION 3.16.3) project( falcon_wopi ) ###################################################################### diff --git a/tests/native/dynlib/CMakeLists.txt b/tests/native/dynlib/CMakeLists.txt index 1781380d9..ed3f1e99f 100644 --- a/tests/native/dynlib/CMakeLists.txt +++ b/tests/native/dynlib/CMakeLists.txt @@ -3,7 +3,7 @@ # # CMake configuration file for dynlib - TESTS #################################################################### -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.16.3) include_directories( ${CMAKE_CURRENT_SOURCE_DIR}