diff options
author | Baptiste Daroussin <bapt@FreeBSD.org> | 2023-09-26 07:08:15 +0000 |
---|---|---|
committer | Baptiste Daroussin <bapt@FreeBSD.org> | 2023-09-26 07:08:15 +0000 |
commit | 16c0a3151e5fa4958711f64bbc2f172cfe781743 (patch) | |
tree | c5d9c0587848d7f5e5393f8d5c70e22763b619b8 | |
parent | 8e6e1224184eb6cd3dfa05b2ecd9515c59f4f425 (diff) |
-rw-r--r-- | CMakeLists.txt | 4 | ||||
-rw-r--r-- | INSTALL.md | 47 | ||||
-rw-r--r-- | README | 26 | ||||
-rw-r--r-- | common/key.c | 95 | ||||
-rw-r--r-- | common/main.c | 3 | ||||
-rw-r--r-- | common/options.c | 2 | ||||
-rw-r--r-- | common/options_f.c | 2 | ||||
-rw-r--r-- | common/search.c | 11 | ||||
-rw-r--r-- | ex/ex.c | 13 | ||||
-rw-r--r-- | ex/ex_argv.c | 6 | ||||
-rw-r--r-- | ex/ex_subst.c | 7 | ||||
-rw-r--r-- | man/vi.1 | 4 | ||||
-rw-r--r-- | regex/regex.h | 10 | ||||
-rw-r--r-- | vi/v_paragraph.c | 11 | ||||
-rw-r--r-- | vi/v_redraw.c | 1 |
15 files changed, 222 insertions, 20 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 66d3ca2aafb0..0c935b3c2a19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ if (NOT APPLE) endif() add_compile_options($<$<CONFIG:Release>:-Wuninitialized>) add_compile_options($<$<CONFIG:Release>:-Wno-dangling-else>) +add_compile_options(-Wno-string-compare) add_compile_options(-Wstack-protector -fstack-protector) add_compile_options(-Wstrict-aliasing -fstrict-aliasing) @@ -148,6 +149,9 @@ if(USE_WIDECHAR) target_sources(regex PRIVATE ${REGEX_SRCS}) target_include_directories(regex PUBLIC regex) target_compile_definitions(regex PUBLIC __REGEX_PRIVATE) + # The macro _XOPEN_SOURCE_EXTENDED is needed to get the waddnwstr() + # definition on at least FreeBSD and recent macOS. + target_compile_definitions(nvi PRIVATE _XOPEN_SOURCE_EXTENDED) target_link_libraries(nvi PRIVATE regex) else() find_library(CURSES_LIBRARY NAMES ncurses curses HINTS /usr/lib) diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 000000000000..7b2fd35b7c60 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,47 @@ +# Install from source + +For instructions to bring nvi2 as a part of your operating system's base system, see [Porting](https://github.com/lichray/nvi2/wiki/Porting) in the Wiki. This document is an overview of the build process that allows you to give nvi2 a try. + +## Prerequisites + +- CMake >= 3.17; +- Ninja build system; +- libiconv (for `USE_ICONV`); +- libncursesw (for `USE_WIDECHAR`); + +Anything required by a minimal nvi, notably: + +- Berkeley DB1 in libc; +- /var/tmp/vi.recover/ with mode 41777. + +## Building + +Nvi2 uses CMake build system generator. By specifying "Ninja Multi-Config" as the build system to generate, you can compile the project in both Debug and Release modes without re-running CMake. Under the project root directory, run + +```sh +cmake -G "Ninja Multi-Config" -B build +``` + +Now `build` becomes your build directory to hold the artifacts. To build nvi2 in Debug mode, run + +```sh +ninja -C build +``` + +Upon finishing, the nvi2 executable will be available as `build/Debug/nvi`. To launch it in `ex` mode, you can create a symlink + +```sh +ln -s nvi build/Debug/ex +``` + +and run `./build/Debug/ex` rather than `./build/Debug/nvi`. + +To build nvi2 in Release mode, use the following command instead: + +```sh +ninja -C build -f build-Release.ninja +``` + +Upon finishing, you will be able to edit files with `./build/Release/nvi`. + +To change configure-time options, such as disabling wide character support, use `ccmake build`. @@ -1,4 +1,4 @@ -This is version 2.2.0 (2020-08-01) of nex/nvi, a reimplementation of the ex/vi +This is version 2.2.1 (2023-09-25) of nex/nvi, a reimplementation of the ex/vi text editors originally distributed as part of the Fourth Berkeley Software Distribution (4BSD), by the University of California, Berkeley. @@ -24,6 +24,30 @@ o Nvi was written by Keith Bostic, and the last version is 1.79. After that, Jun-ichiro itojun Hagino developed the file encoding detection techniques in his nvi-m17n. +o In nvi2, Zhihao Yuan incorporated the multibyte encoding support onto DB1. + + It was not possible without great support from Alexander Leidinger, + Peter Wemm, and the FreeBSD community. + + Last but not least, money from Google Summer of Code. + +o Since then, + + Todd C. Miller and Craig Leres adopted and refined the NetBSD-style + expandtab option. + + Yamamoto Takashi, Matija Skala, and Jessica Clarke ported the + software to macOS and Linux. + + Anthony J. Bentley made heroic efforts to modernize the code base + and documentation, leveraging experience from OpenBSD to improve the + quality of the project. + + ...and many others, including Michael McConville, Marc Simpson, + Jeffrey H. Johnson, Bosco GarcĂa, Anton Konyahin, Walter Alejandro + Iglesias, and those who tried hard to keep anonymous on GitHub :) + Their insights render the software usable, secure, and sustainable. + The following acknowledgments were written by Keith Bostic: =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/common/key.c b/common/key.c index e71396893fd4..1ccfb61ee0a1 100644 --- a/common/key.c +++ b/common/key.c @@ -31,6 +31,7 @@ static int v_event_grow(SCR *, int); static int v_key_cmp(const void *, const void *); static void v_keyval(SCR *, int, scr_keyval_t); static void v_sync(SCR *, int); +static const char *alt_key_notation(int ch); /* * !!! @@ -252,6 +253,10 @@ v_key_name(SCR *sp, ARG_CHAR_T ach) * followed by the character offset from the '@' character in the ASCII * character set. Del (0x7f) is represented as '^' followed by '?'. * + * If set O_ALTNOTATION, control characters less than 0x20 are + * represented in <C-char> notations. Carriage feed, escape, and + * delete are marked as <Enter>, <Esc>, and <Del>, respectively. + * * XXX * The following code depends on the current locale being identical to * the ASCII map from 0x40 to 0x5f (since 0x1f + 0x40 == 0x5f). I'm @@ -264,9 +269,14 @@ v_key_name(SCR *sp, ARG_CHAR_T ach) if (CAN_PRINT(sp, ach)) goto done; nopr: if (iscntrl(ch) && (ch < 0x20 || ch == 0x7f)) { - sp->cname[0] = '^'; - sp->cname[1] = ch == 0x7f ? '?' : '@' + ch; - len = 2; + if (O_ISSET(sp, O_ALTNOTATION)) { + const char *notation = alt_key_notation(ch); + len = strlcpy(sp->cname, notation, sizeof(sp->cname)); + } else { + sp->cname[0] = '^'; + sp->cname[1] = ch == 0x7f ? '?' : '@' + ch; + len = 2; + } goto done; } #ifdef USE_WIDECHAR @@ -746,6 +756,85 @@ v_sync(SCR *sp, int flags) } /* + * alt_key_notation -- + * Lookup for alternative notations of control characters. + */ +static const char* +alt_key_notation(int ch) +{ + switch (ch) { + case 0x00: + return "<C-@>"; + case 0x01: + return "<C-a>"; + case 0x02: + return "<C-b>"; + case 0x03: + return "<C-c>"; + case 0x04: + return "<C-d>"; + case 0x05: + return "<C-e>"; + case 0x06: + return "<C-f>"; + case 0x07: + return "<C-g>"; + case 0x08: + return "<C-h>"; + case 0x09: + return "<Tab>"; + case 0x0A: + return "<NL>"; + case 0x0B: + return "<C-k>"; + case 0x0C: + return "<C-l>"; + case 0x0D: + return "<Enter>"; + case 0x0E: + return "<C-n>"; + case 0x0F: + return "<C-o>"; + case 0x10: + return "<C-p>"; + case 0x11: + return "<C-q>"; + case 0x12: + return "<C-r>"; + case 0x13: + return "<C-s>"; + case 0x14: + return "<C-t>"; + case 0x15: + return "<C-u>"; + case 0x16: + return "<C-v>"; + case 0x17: + return "<C-w>"; + case 0x18: + return "<C-x>"; + case 0x19: + return "<C-y>"; + case 0x1A: + return "<C-z>"; + case 0x1B: + return "<Esc>"; + case 0x1C: + return "<C-\\>"; + case 0x1D: + return "<C-]>"; + case 0x1E: + return "<C-^>"; + case 0x1F: + return "<C-_>"; + case 0x7f: + return "<Del>"; + default: + __builtin_unreachable(); + } +} + +/* * v_event_err -- * Unexpected event. * diff --git a/common/main.c b/common/main.c index a7e60f1af806..807dbde3895c 100644 --- a/common/main.c +++ b/common/main.c @@ -419,8 +419,7 @@ err: rval = 1; * PUBLIC: void v_end(GS *); */ void -v_end(gp) - GS *gp; +v_end(GS *gp) { MSGS *mp; SCR *sp; diff --git a/common/options.c b/common/options.c index d5c039f97228..c3d1f7343f9a 100644 --- a/common/options.c +++ b/common/options.c @@ -46,6 +46,8 @@ static int opts_print(SCR *, OPTLIST const *); * VI and EX Text Editors", 1990. */ OPTLIST const optlist[] = { +/* O_ALTNOTATION */ + {L("altnotation"), f_print, OPT_0BOOL, 0}, /* O_ALTWERASE 4.4BSD */ {L("altwerase"), f_altwerase, OPT_0BOOL, 0}, /* O_AUTOINDENT 4BSD */ diff --git a/common/options_f.c b/common/options_f.c index 45ab913c55ab..fe07e4989f05 100644 --- a/common/options_f.c +++ b/common/options_f.c @@ -147,7 +147,7 @@ f_print(SCR *sp, OPTION *op, char *str, u_long *valp) int offset = op - sp->opts; /* Preset the value, needed for reinitialization of lookup table. */ - if (offset == O_OCTAL) { + if (offset == O_OCTAL || offset == O_ALTNOTATION) { if (*valp) O_SET(sp, offset); else diff --git a/common/search.c b/common/search.c index e8dcac431f51..c3f7291437ff 100644 --- a/common/search.c +++ b/common/search.c @@ -103,9 +103,14 @@ prev: if (sp->re == NULL) { ++p; break; } - if (plen > 1 && p[0] == '\\' && p[1] == delim) { - ++p; - --plen; + if (plen > 1 && p[0] == '\\') { + if (p[1] == delim) { + ++p; + --plen; + } else if ( p[1] == '\\') { + *t++ = *p++; + --plen; + } } } if (epp != NULL) @@ -154,6 +154,10 @@ ex(SCR **spp) if (file_end(sp, NULL, F_ISSET(sp, SC_EXIT_FORCE))) return (1); *spp = screen_next(sp); + if (*spp) { + F_CLR(*spp, SC_SCR_VI); + F_SET(*spp, SC_SCR_EX); + } return (screen_end(sp)); } } @@ -1463,8 +1467,13 @@ addr_verify: LF_INIT(FL_ISSET(ecp->iflags, E_C_HASH | E_C_LIST | E_C_PRINT)); if (!LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT | E_NOAUTO) && !F_ISSET(sp, SC_EX_GLOBAL) && - O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT)) - LF_INIT(E_C_PRINT); + O_ISSET(sp, O_AUTOPRINT) && F_ISSET(ecp, E_AUTOPRINT)) { + /* Honor the number option if autoprint is set. */ + if (F_ISSET(ecp, E_OPTNUM)) + LF_INIT(E_C_HASH); + else + LF_INIT(E_C_PRINT); + } if (LF_ISSET(E_C_HASH | E_C_LIST | E_C_PRINT)) { cur.lno = sp->lno; diff --git a/ex/ex_argv.c b/ex/ex_argv.c index 8b1fd7858fb1..dd37fe1f69e2 100644 --- a/ex/ex_argv.c +++ b/ex/ex_argv.c @@ -764,11 +764,11 @@ err: if (ifp != NULL) * shell that does that is broken. */ for (p = bp, len = 0, ch = EOF; - (ch = GETC(ifp)) != EOF; *p++ = ch, blen-=sizeof(CHAR_T), ++len) + (ch = GETC(ifp)) != EOF; *p++ = ch, blen -= sizeof(CHAR_T), ++len) if (blen < 5) { - ADD_SPACE_GOTOW(sp, bp, *blenp, *blenp * 2); + ADD_SPACE_GOTO(sp, CHAR_T, bp, *blenp, *blenp * 2); p = bp + len; - blen = *blenp - len; + blen = *blenp - len * sizeof(CHAR_T); } /* Delete the final newline, nul terminate the string. */ diff --git a/ex/ex_subst.c b/ex/ex_subst.c index bf03e4417e91..3113ac5ca360 100644 --- a/ex/ex_subst.c +++ b/ex/ex_subst.c @@ -643,7 +643,9 @@ nextmatch: match[0].rm_so = 0; goto lquit; } } else { - if (ex_print(sp, cmdp, &from, &to, 0) || + const int flags = + O_ISSET(sp, O_NUMBER) ? E_C_HASH : 0; + if (ex_print(sp, cmdp, &from, &to, flags) || ex_scprint(sp, &from, &to)) goto lquit; if (ex_txt(sp, tiq, 0, TXT_CR)) @@ -1195,7 +1197,8 @@ re_tag_conv(SCR *sp, CHAR_T **ptrnp, size_t *plenp, int *replacedp) for (; len > 0; --len) { if (p[0] == '\\' && (p[1] == '/' || p[1] == '?')) { ++p; - --len; + if (len > 1) + --len; } else if (STRCHR(L("^.[]$*"), p[0])) *t++ = '\\'; *t++ = *p++; @@ -2282,6 +2282,10 @@ and .Nm vi modes, unless otherwise specified. .Bl -tag -width Ds +.It Cm altnotation Bq off +Display control characters less than 0x20 in <C-char> notations. +Carriage feed, escape, and delete are marked as <Enter>, <Esc>, and <Del>, +respectively. .It Cm altwerase Bq off .Nm vi only. diff --git a/regex/regex.h b/regex/regex.h index 20ea7865c0a0..7d788514a54c 100644 --- a/regex/regex.h +++ b/regex/regex.h @@ -96,6 +96,16 @@ typedef struct { #define REG_LARGE 01000 /* force large representation */ #define REG_BACKR 02000 /* force use of backref code */ +#ifdef USE_WIDECHAR +/* + * Avoid function name conflicts with the system regex functions. + * This is needed e.g. to build with AddressSanitizer. + */ +#define regcomp nvi_regcomp +#define regerror nvi_regerror +#define regexec nvi_regexec +#define regfree nvi_regfree +#endif int regcomp(regex_t *, const RCHAR_T *, int); size_t regerror(int, const regex_t *, char *, size_t); int regexec(const regex_t *, diff --git a/vi/v_paragraph.c b/vi/v_paragraph.c index abe8d9cf50e0..2d7f07569b79 100644 --- a/vi/v_paragraph.c +++ b/vi/v_paragraph.c @@ -39,15 +39,20 @@ if (p[0] == '\014') { \ if (!--cnt) \ goto found; \ + if (pstate == P_INTEXT && !--cnt) \ + goto found; \ continue; \ } \ if (p[0] != '.' || len < 2) \ continue; \ for (lp = VIP(sp)->ps; *lp != '\0'; lp += 2) \ if (lp[0] == p[1] && \ - (lp[1] == ' ' && len == 2 || lp[1] == p[2]) && \ - !--cnt) \ - goto found; \ + (lp[1] == ' ' && len == 2 || lp[1] == p[2])) { \ + if (!--cnt) \ + goto found; \ + if (pstate == P_INTEXT && !--cnt) \ + goto found; \ + } \ } while (0) /* diff --git a/vi/v_redraw.c b/vi/v_redraw.c index de6ed0079701..046fcf15c1b4 100644 --- a/vi/v_redraw.c +++ b/vi/v_redraw.c @@ -29,5 +29,6 @@ int v_redraw(SCR *sp, VICMD *vp) { + F_SET(sp, SC_SCR_REFORMAT); return (sp->gp->scr_refresh(sp, 1)); } |