git: c7bcccbb669e - stable/14 - MFC: MFV: less v710.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 26 Sep 2026 01:49:24 UTC
The branch stable/14 has been updated by delphij:
URL: https://cgit.FreeBSD.org/src/commit/?id=c7bcccbb669ee9900bf13c6ecbf42daa9d5d1f82
commit c7bcccbb669ee9900bf13c6ecbf42daa9d5d1f82
Author: Xin LI <delphij@FreeBSD.org>
AuthorDate: 2026-09-19 18:20:29 +0000
Commit: Xin LI <delphij@FreeBSD.org>
CommitDate: 2026-09-26 01:48:17 +0000
MFC: MFV: less v710.
(cherry picked from commit 4523eebc6c1828d4fd41d7f1ab943cf079043bc8)
---
ObsoleteFiles.inc | 4 +
UPDATING | 21 ++
contrib/less/NEWS | 81 +++++
contrib/less/brac.c | 17 +-
contrib/less/ch.c | 46 ++-
contrib/less/charset.c | 47 +--
contrib/less/cmd.h | 13 +-
contrib/less/cmdbuf.c | 33 +-
contrib/less/command.c | 228 ++++++++----
contrib/less/decode.c | 371 ++++++++++++-------
contrib/less/edit.c | 48 +--
contrib/less/filename.c | 133 +++++--
contrib/less/forwback.c | 11 +-
contrib/less/funcs.h | 43 +--
contrib/less/help.c | 6 +-
contrib/less/ifile.c | 9 +-
contrib/less/input.c | 14 +-
contrib/less/jump.c | 23 +-
contrib/less/less.h | 16 +-
contrib/less/less.hlp | 4 +
contrib/less/less.nro | 238 ++++++++----
contrib/less/lessecho.nro | 67 +++-
contrib/less/lesskey.c | 364 -------------------
contrib/less/lesskey.h | 22 --
contrib/less/lesskey.nro | 120 +++---
contrib/less/lesskey_parse.c | 83 +++--
contrib/less/lessmsg | 372 +++++++++++++++++++
contrib/less/lessmsg.inc | 331 +++++++++++++++++
contrib/less/lessmsg_int | 5 +
contrib/less/line.c | 106 ++++--
contrib/less/linenum.c | 6 +-
contrib/less/lmsg.c | 218 +++++++++++
contrib/less/lmsg.h | 24 ++
contrib/less/lsystem.c | 124 ++++---
contrib/less/main.c | 66 ++--
contrib/less/mark.c | 40 +-
contrib/less/optfunc.c | 157 ++++----
contrib/less/option.c | 59 +--
contrib/less/option.h | 1 +
contrib/less/opttbl.c | 622 ++++++++++++++++++--------------
contrib/less/os.c | 2 +-
contrib/less/output.c | 67 ++--
contrib/less/pattern.c | 41 ++-
contrib/less/pattern.h | 15 +-
contrib/less/pckeys.h | 11 +-
contrib/less/prompt.c | 39 +-
contrib/less/screen.c | 510 ++++++++++++++------------
contrib/less/search.c | 104 +++---
contrib/less/signal.c | 10 +-
contrib/less/tags.c | 20 +-
contrib/less/ttyin.c | 8 +
contrib/less/version.c | 20 +-
targets/pseudo/userland/Makefile.depend | 1 -
usr.bin/Makefile | 1 -
usr.bin/less/Makefile | 5 +-
usr.bin/less/Makefile.common | 5 +-
usr.bin/lesskey/Makefile | 7 -
usr.bin/lesskey/Makefile.depend | 15 -
58 files changed, 3274 insertions(+), 1800 deletions(-)
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index d4c05005f5a2..5b7648b78e6d 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -51,6 +51,10 @@
# xargs -n1 | sort | uniq -d;
# done
+# 20260925: lesskey(1) removed, lesskey(5) man page added
+OLD_FILES+=usr/bin/lesskey
+OLD_FILES+=usr/share/man/man1/lesskey.1.gz
+
# 20260602: Removed by 0a36787e4c1f on 20210723
OLD_FILES+=usr/share/locale/hr_HR.ISO8859-2/LC_MESSAGES
OLD_FILES+=usr/share/locale/nl_BE.ISO8859-1/LC_MESSAGES
diff --git a/UPDATING b/UPDATING
index 0e3fd5317bb0..443af136201c 100644
--- a/UPDATING
+++ b/UPDATING
@@ -12,6 +12,27 @@ Items affecting the ports and packages system can be found in
/usr/ports/UPDATING. Please read that file before updating system packages
and/or ports.
+20260925:
+ less(1) has been updated to version 710, which removes the obsolete
+ lesskey(1) utility. It is no longer built or installed, and the
+ manual page describing the lesskey file format has moved from
+ lesskey(1) to lesskey(5).
+
+ No separate compilation step is needed any more: less(1) has been
+ able to read plain-text lesskey files directly since version 590,
+ imported into FreeBSD in 2021. Keep your key bindings in the
+ plain-text ~/.lesskey (or the file named by $LESSKEYIN) rather than
+ compiling them into the binary ~/.less; system-wide bindings belong
+ in /etc/syslesskey (or $LESSKEYIN_SYSTEM) rather than /etc/sysless.
+ If both forms are present, the plain-text one is used and the binary
+ one is ignored.
+
+ Existing binary lesskey files are still read, so nothing stops
+ working immediately, but they can no longer be generated or
+ regenerated. Binary files produced by lesskey from less 240 or
+ older are no longer supported at all and must be rewritten in the
+ plain-text format.
+
20260727:
The wait_for_pids() function in rc.subr, used by rc scripts
when stopping or restarting a service, has been modified to
diff --git a/contrib/less/NEWS b/contrib/less/NEWS
index a031353acf46..49c4a5c0f317 100644
--- a/contrib/less/NEWS
+++ b/contrib/less/NEWS
@@ -9,6 +9,87 @@
Report bugs, suggestions or comments at
https://github.com/gwsw/less/issues.
+======================================================================
+
+ Major changes between "less" versions 704 and 710
+
+* Add || command.
+
+* In | and || commands, ^N allows entering line number instead of mark letter.
+
+* Add "ESC-]" / "ESC-RIGHTARROW" (right-limit-scroll) command (github #783).
+
+* In lesskey files, add \k^x syntax for control chars and \k+x syntax
+ for shifted chars.
+
+* Underline OSC 8 links in text.
+
+* Add -DO for custom coloring of OSC 8 links.
+
+* Add LESSMSG, which allows translation of messages into other languages.
+
+* Add LESSSECURE_DISALLOW.
+
+* Add LESS_SHELL_COPTION.
+
+* Add %G, %y, and %% in prompt strings.
+
+* Add lesskey support for shift-uparrow, shift-downarrow, shift-pageup,
+ shift-pagedown, ctl-uparrow, ctl-downarrow, ctl-pageup, ctl-pagedown,
+ shift-delete.
+
+* Change "make check" to use nonstandard object and binary file names,
+ to avoid accidentally installing test binaries (github #791).
+
+* Fix issues on systems with volatile getenv return values.
+
+* Improve error handling for malformed binary lesskey file.
+
+* Improve messaging when using __mouse after --emouse (github #808).
+
+* Remove support for obsolete pre-241 lesskey binary format.
+
+* Remove obsolete lesskey program.
+
+* Move lesskey man page to section 5.
+
+* Update display when resize window while in F mode on Windows.
+
+* Fix missing "END" message at end of &-filtered output (github #774).
+
+* Fix missing bell with G command at end of &-filtered output (github #774).
+
+* Don't reset signal handlers in a subprocess on Windows.
+
+* Fix ' command to not modify the mark when given a numeric argument
+ (github #799).
+
+* Fix erroneous message from --rscroll command when rscroll char is non-ASCII.
+
+* Fix unexpected exit when TERM is invalid (github #809).
+
+* Fix possible crash when use ":e #" after ":d" (github #810).
+
+* Fix infinite loop if invalid option letter in LESS_UNSUPPORT.
+
+* Fix crash if run !! command with no previous ! command (github #812).
+
+* Fix inability to run a shell command starting with "!" character.
+
+* Fix bugs using ^S search modifier (github #814).
+
+* Fix display bugs when a status message contains non-ASCII chars
+ or is displayed on a very narrow screen (github #816).
+
+* Fix bug defining command which has a built-in command as a prefix
+ (github #795).
+
+* Fix string overrrun if input contains "\e\0".
+
+* Fix memory leak when using ${...} in lesskey file.
+
+* Fix status column display when long line is marked (github #820).
+
======================================================================
Major changes between "less" versions 702 and 704
diff --git a/contrib/less/brac.c b/contrib/less/brac.c
index b3b74e07d18a..deaedb187b3c 100644
--- a/contrib/less/brac.c
+++ b/contrib/less/brac.c
@@ -23,12 +23,12 @@
* The characters which serve as "open bracket" and
* "close bracket" are given.
*/
-public void match_brac(char obrac, char cbrac, int forwdir, int n)
+public void match_brac(char obrac, char cbrac, lbool forwdir, int n)
{
int c;
int nest;
POSITION pos;
- int (*chget)();
+ int (*chget)(void);
extern int ch_forw_get(), ch_back_get();
@@ -41,9 +41,9 @@ public void match_brac(char obrac, char cbrac, int forwdir, int n)
if (pos == NULL_POSITION || ch_seek(pos))
{
if (forwdir)
- error("Nothing in top line", NULL_PARG);
+ error(LM(Nothing_in_top_line), NULL_PARG);
else
- error("Nothing in bottom line", NULL_PARG);
+ error(LM(Nothing_in_bottom_line), NULL_PARG);
return;
}
@@ -55,9 +55,9 @@ public void match_brac(char obrac, char cbrac, int forwdir, int n)
if ((c = ch_forw_get()) == '\n' || c == EOI)
{
if (forwdir)
- error("No bracket in top line", NULL_PARG);
+ error(LM(No_bracket_in_top_line), NULL_PARG);
else
- error("No bracket in bottom line", NULL_PARG);
+ error(LM(No_bracket_in_bottom_line), NULL_PARG);
return;
}
} while (c != obrac || --n > 0);
@@ -83,8 +83,7 @@ public void match_brac(char obrac, char cbrac, int forwdir, int n)
if (nest == INT_MAX)
break;
nest++;
- }
- else if (c == cbrac && --nest < 0)
+ } else if (c == cbrac && --nest < 0)
{
/*
* Found the matching bracket.
@@ -95,5 +94,5 @@ public void match_brac(char obrac, char cbrac, int forwdir, int n)
return;
}
}
- error("No matching bracket", NULL_PARG);
+ error(LM(No_matching_bracket), NULL_PARG);
}
diff --git a/contrib/less/ch.c b/contrib/less/ch.c
index dfe1e7169f72..beda45895c52 100644
--- a/contrib/less/ch.c
+++ b/contrib/less/ch.c
@@ -124,8 +124,8 @@ extern int autobuf;
extern int sigs;
extern int follow_mode;
extern lbool waiting_for_data;
-extern constant char helpdata[];
-extern constant int size_helpdata;
+extern constant char *help_data;
+extern constant int size_help_data;
extern IFILE curr_ifile;
#if LOGFILE
extern int logfile;
@@ -256,7 +256,7 @@ static int ch_get(void)
return ('?');
if (less_lseek(ch_file, (less_off_t)pos, SEEK_SET) == BAD_LSEEK)
{
- error("seek error", NULL_PARG);
+ error(LM(seek_error), NULL_PARG);
clear_eol();
return (EOI);
}
@@ -275,10 +275,12 @@ static int ch_get(void)
ch_have_ungotchar = FALSE;
} else if (ch_flags & CH_HELPFILE)
{
- bp->data[bp->datasize] = (unsigned char) helpdata[ch_fpos];
+ bp->data[bp->datasize] = (unsigned char) help_data[ch_fpos];
n = 1;
} else
{
+ if (ch_file < 0)
+ return (EOI);
n = iread(ch_file, &bp->data[bp->datasize], LBUFSIZE - bp->datasize);
}
@@ -324,7 +326,22 @@ static int ch_get(void)
/* Either end of file or no data available.
* read_again indicates the latter. */
if (!read_again)
+ {
ch_fsize = pos;
+ if (ch_flags & CH_POPENED)
+ {
+ /*
+ * ch_file is a pipe from a LESSOPEN child program.
+ * Since we've read to EOF, the child should have exited.
+ * Close the pipe now so the child does not remain a
+ * zombie. This also reports any error status from the
+ * child if -show-preproc-errors is enabled.
+ */
+ close_pipe(get_altpipe(curr_ifile));
+ set_altpipe(curr_ifile, NULL);
+ ch_file = -1;
+ }
+ }
if (ignore_eoi || read_again)
{
/* Wait a while, then try again. */
@@ -388,7 +405,7 @@ public void ch_ungetchar(int c)
else
{
if (ch_have_ungotchar)
- error("ch_ungetchar overrun", NULL_PARG);
+ error(LM(ch_ungetchar_overrun), NULL_PARG);
ch_ungotchar = (unsigned char) c;
ch_have_ungotchar = TRUE;
}
@@ -408,7 +425,7 @@ public void end_logfile(void)
if (!tried && ch_fsize == NULL_POSITION)
{
tried = TRUE;
- ierror("Finishing logfile", NULL_PARG);
+ ierror(LM(Finishing_logfile), NULL_PARG);
while (ch_forw_get() != EOI)
if (ABORT_SIGS())
break;
@@ -454,8 +471,7 @@ public void sync_logfile(void)
}
if (!wrote && !warned)
{
- error("Warning: log file is incomplete",
- NULL_PARG);
+ error(LM(log_file_is_incomplete), NULL_PARG);
warned = TRUE;
}
}
@@ -614,7 +630,7 @@ public POSITION ch_length(void)
if (ignore_eoi)
return (NULL_POSITION);
if (ch_flags & CH_HELPFILE)
- return (size_helpdata);
+ return (size_help_data);
if (ch_flags & CH_NODATA)
return (0);
return (ch_fsize);
@@ -745,7 +761,7 @@ public void ch_flush(void)
ch_flags &= ~CH_CANSEEK;
} else
{
- ch_fsize = (ch_flags & CH_HELPFILE) ? size_helpdata : filesize(ch_file);
+ ch_fsize = (ch_flags & CH_HELPFILE) ? size_help_data : filesize(ch_file);
}
if (less_lseek(ch_file, (less_off_t)0, SEEK_SET) == BAD_LSEEK)
@@ -755,7 +771,7 @@ public void ch_flush(void)
* there's a good chance we're at the beginning anyway.
* {{ I think this is bogus reasoning. }}
*/
- error("seek error to 0", NULL_PARG);
+ error(LM(seek_error_to_0), NULL_PARG);
}
}
@@ -818,7 +834,7 @@ static void ch_delbufs(void)
/*
* Is it possible to seek on a file descriptor?
*/
-public int seekable(int f)
+public lbool seekable(int f)
{
#if MSDOS_COMPILER
extern int fd0;
@@ -828,7 +844,7 @@ public int seekable(int f)
* In MS-DOS, pipes are seekable. Check for
* standard input, and pretend it is not seekable.
*/
- return (0);
+ return (FALSE);
}
#endif
return (less_lseek(f, (less_off_t)1, SEEK_SET) != BAD_LSEEK);
@@ -883,7 +899,7 @@ public void ch_init(int f, int flags, ssize_t nread)
/*
* Figure out the size of the file, if we can.
*/
- ch_fsize = (flags & CH_HELPFILE) ? size_helpdata : filesize(ch_file);
+ ch_fsize = (flags & CH_HELPFILE) ? size_help_data : filesize(ch_file);
if (ch_fsize == 0 && nread > 0)
{
@@ -924,7 +940,7 @@ public void ch_close(void)
* But don't really close it if it was opened via popen(),
* because pclose() wants to close it.
*/
- if (!(ch_flags & (CH_POPENED|CH_HELPFILE)))
+ if (ch_file >= 0 && !(ch_flags & (CH_POPENED|CH_HELPFILE)))
close(ch_file);
ch_file = -1;
} else
diff --git a/contrib/less/charset.c b/contrib/less/charset.c
index f2020e4ef5c5..9447a8dcff24 100644
--- a/contrib/less/charset.c
+++ b/contrib/less/charset.c
@@ -191,12 +191,12 @@ static void ichardef_utf(constant char *s)
wchar_range_get(&s, &range);
if (range.last == 0)
{
- error("invalid hex number(s) in LESSUTFCHARDEF", NULL_PARG);
+ error(LM(invalid_hex_number_in_LESSUTFCHARDEF), NULL_PARG);
quit(QUIT_ERROR);
}
if (*s++ != ':')
{
- error("missing colon in LESSUTFCHARDEF", NULL_PARG);
+ error(LM(missing_colon_in_LESSUTFCHARDEF), NULL_PARG);
quit(QUIT_ERROR);
}
switch (*s++)
@@ -279,7 +279,7 @@ static void ichardef(constant char *s)
default:
invalid_chardef:
- error("invalid chardef", NULL_PARG);
+ error(LM(invalid_chardef), NULL_PARG);
quit(QUIT_ERROR);
/*NOTREACHED*/
}
@@ -288,7 +288,7 @@ static void ichardef(constant char *s)
{
if (cp >= chardef + sizeof(chardef))
{
- error("chardef longer than 256", NULL_PARG);
+ error(LM(chardef_longer_than_256), NULL_PARG);
quit(QUIT_ERROR);
/*NOTREACHED*/
}
@@ -305,7 +305,7 @@ static void ichardef(constant char *s)
* Define a charset, given a charset name.
* The valid charset names are listed in the "charsets" array.
*/
-static int icharset(constant char *name, int no_error)
+static int icharset(constant char *name, lbool no_error)
{
struct charset *p;
struct cs_alias *a;
@@ -341,7 +341,7 @@ static int icharset(constant char *name, int no_error)
}
if (!no_error) {
- error("invalid charset name", NULL_PARG);
+ error(LM(invalid_charset_name), NULL_PARG);
quit(QUIT_ERROR);
}
return (0);
@@ -353,9 +353,9 @@ static int icharset(constant char *name, int no_error)
*/
static void ilocale(void)
{
- int c;
+ size_t c;
- for (c = 0; c < (int) sizeof(chardef); c++)
+ for (c = 0; c < sizeof(chardef); c++)
{
if (isprint(c))
chardef[c] = 0;
@@ -411,7 +411,7 @@ static void set_charset(void)
* See if environment variable LESSCHARSET is defined.
*/
s = lgetenv("LESSCHARSET");
- if (icharset(s, 0))
+ if (icharset(s, FALSE))
return;
/*
@@ -438,7 +438,7 @@ static void set_charset(void)
#endif
{
s = nl_langinfo(CODESET);
- if (icharset(s, 1))
+ if (icharset(s, TRUE))
return;
}
#endif
@@ -453,7 +453,7 @@ static void set_charset(void)
{
if ( strstr(s, "UTF-8") != NULL || strstr(s, "utf-8") != NULL
|| strstr(s, "UTF8") != NULL || strstr(s, "utf8") != NULL)
- if (icharset("utf-8", 1))
+ if (icharset("utf-8", TRUE))
return;
}
@@ -466,12 +466,12 @@ static void set_charset(void)
#else
#if MSDOS_COMPILER
#if MSDOS_COMPILER==WIN32C
- (void) icharset("utf-8", 1);
+ (void) icharset("utf-8", TRUE);
#else
- (void) icharset("dos", 1);
+ (void) icharset("dos", TRUE);
#endif
#else
- (void) icharset("utf-8", 1);
+ (void) icharset("utf-8", TRUE);
#endif
#endif
}
@@ -527,7 +527,7 @@ public constant char * prchar(LWCHAR c)
/* {{ Fixed buffer size means LESSBINFMT etc can be truncated. }} */
static char buf[MAX_PRCHAR_LEN+1];
- c &= 0377; /*{{type-issue}}*/
+ c = (unsigned char) c; /* {{ parameter is interpreted as a byte }} */
if ((c < 128 || !utf_mode) && !control_char(c))
SNPRINTF1(buf, sizeof(buf), "%c", (int) c);
else if (c == ESC)
@@ -617,27 +617,28 @@ public lbool is_utf8_well_formed(constant char *ssa, int slen)
unsigned char s0 = ss[0];
if (IS_UTF8_LEAD5(s0) || IS_UTF8_LEAD6(s0) || IS_UTF8_INVALID(s0))
- return (FALSE);
+ return (FALSE); /* invalid lead byte */
len = utf_len(s0);
if (len > slen)
- return (FALSE);
+ return (FALSE); /* UTF-8 sequence doesn't fit in buffer */
if (len == 1)
return (TRUE);
if (len == 2)
{
if (s0 < 0xC2)
- return (FALSE);
+ return (FALSE); /* overlong (fits in 1 byte) */
} else
{
+ /* mask = byte with len high-order bits set to 1, others 0 */
unsigned char mask = (unsigned char) (~((1 << (8-len)) - 1));
if (s0 == mask && (ss[1] & mask) == 0x80)
- return (FALSE);
+ return (FALSE); /* overlong (fits in fewer bytes) */
}
for (i = 1; i < len; i++)
if (!IS_UTF8_TRAIL(ss[i]))
- return (FALSE);
+ return (FALSE); /* not a continuation byte */
return (TRUE);
}
@@ -651,7 +652,6 @@ public void utf_skip_to_lead(constant char **pp, constant char *limit)
} while (*pp < limit && !IS_UTF8_LEAD((*pp)[0] & 0377) && !IS_ASCII_OCTET((*pp)[0]));
}
-
/*
* Get the value of a UTF-8 character.
*/
@@ -755,7 +755,8 @@ public void put_wchar(mutable char **pp, LWCHAR ch)
}
/*
- * Step forward or backward one character in a string.
+ * Step forward (dir > 0) or backward (dir < 0) one character in a string.
+ * If dir > 0, limit is end of string; if dir < 0, limit is start of string.
*/
public LWCHAR step_charc(constant char **pp, signed int dir, constant char *limit)
{
@@ -779,6 +780,7 @@ public LWCHAR step_charc(constant char **pp, signed int dir, constant char *limi
len = utf_len(*p);
if (p + len > limit || !is_utf8_well_formed(p, len))
{
+ /* Invalid UTF-8 sequence; just take the next byte as a character. */
ch = (LWCHAR) (unsigned char) *p++;
} else
{
@@ -797,6 +799,7 @@ public LWCHAR step_charc(constant char **pp, signed int dir, constant char *limi
len = utf_len(*--p);
if (p + len != *pp || !is_utf8_well_formed(p, len))
{
+ /* Invalid UTF-8 sequence; just take the next byte as a character. */
p = *pp - 1;
ch = (LWCHAR) (unsigned char) *p;
} else
diff --git a/contrib/less/cmd.h b/contrib/less/cmd.h
index fb66a6adb99d..97d51ab9b7f9 100644
--- a/contrib/less/cmd.h
+++ b/contrib/less/cmd.h
@@ -89,6 +89,7 @@
#define A_F_FOREVER_BELL 77
#define A_L_MOUSE 78
#define A_R_MOUSE 79
+#define A_RSHIFT_LIMIT 80
/* These values must not conflict with any A_* or EC_* value. */
#define A_INVALID 100
@@ -180,6 +181,14 @@
#define SK_CTL_END 37
#define SK_SHIFT_LEFT_ARROW 38
#define SK_SHIFT_RIGHT_ARROW 39
-#define SK_PAD_ENTER 41
-
#define SK_CONTROL_K 40
+#define SK_PAD_ENTER 41
+#define SK_SHIFT_UP_ARROW 42
+#define SK_SHIFT_DOWN_ARROW 43
+#define SK_CTL_UP_ARROW 44
+#define SK_CTL_DOWN_ARROW 45
+#define SK_SHIFT_DELETE 46
+#define SK_SHIFT_PAGE_UP 47
+#define SK_SHIFT_PAGE_DOWN 48
+#define SK_CTL_PAGE_UP 49
+#define SK_CTL_PAGE_DOWN 50
diff --git a/contrib/less/cmdbuf.c b/contrib/less/cmdbuf.c
index 9f13473eba03..5c6600f9c49c 100644
--- a/contrib/less/cmdbuf.c
+++ b/contrib/less/cmdbuf.c
@@ -358,7 +358,7 @@ static void cmd_lshift(void)
s = ns;
}
- cmd_offset = (int) (s - cmdbuf);
+ cmd_offset = (int) ptr_diff(s, cmdbuf);
save_cp = cp;
cmd_home();
cmd_repaint(save_cp);
@@ -387,7 +387,7 @@ static void cmd_rshift(void)
cols += width;
}
- cmd_offset = (int) (s - cmdbuf);
+ cmd_offset = (int) ptr_diff(s, cmdbuf);
save_cp = cp;
cmd_home();
cmd_repaint(save_cp);
@@ -479,7 +479,7 @@ static int cmd_erase(void)
*/
s = cp;
cmd_left();
- clen = (int) (s - cp);
+ clen = (int) ptr_diff(s, cp);
/*
* Remove the char from the buffer (shift the buffer left).
@@ -993,10 +993,12 @@ static int cmd_istr(constant char *str)
*/
static void set_tk_original(constant char *word)
{
+ size_t len = ptr_diff(cp, word);
if (tk_original != NULL)
free(tk_original);
- tk_original = (char *) ecalloc(ptr_diff(cp,word)+1, sizeof(char));
- strncpy(tk_original, word, ptr_diff(cp,word));
+ tk_original = (char *) ecalloc(len+1, sizeof(char));
+ strncpy(tk_original, word, len);
+ tk_original[len] = '\0';
}
#if TAB_COMPLETE_FILENAME
@@ -1418,15 +1420,18 @@ public LINENUM cmd_int(mutable long *frac)
{
if (ckd_mul(&n, n, 10) || ckd_add(&n, n, *p - '0'))
{
- error("Integer is too big", NULL_PARG);
+ error(LM(Integer_is_too_big), NULL_PARG);
return (0);
}
}
- *frac = 0;
- if (*p++ == '.')
+ if (frac != NULL)
{
- /* {{ Just ignore error in fractional part. }} */
- (void) getfraction(&p, frac);
+ *frac = 0;
+ if (*p++ == '.')
+ {
+ /* {{ Just ignore error in fractional part. }} */
+ (void) getfraction(&p, frac);
+ }
}
return (n);
}
@@ -1481,7 +1486,7 @@ static char * histfile_find(lbool must_exist)
name = dirfile(lgetenv("XDG_STATE_HOME"), &LESSHISTFILE[1], must_exist);
if (name == NULL)
{
- char *dir = dirfile(home, ".local/state", 1);
+ char *dir = dirfile(home, ".local/state", TRUE);
if (dir != NULL)
{
name = dirfile(dir, &LESSHISTFILE[1], must_exist);
@@ -1606,7 +1611,7 @@ static void addhist_init(void *uparam, struct mlist *ml, constant char *string)
{
(void) uparam;
if (ml != NULL)
- cmd_addhist(ml, string, 0);
+ cmd_addhist(ml, string, FALSE);
else if (string != NULL)
restore_mark(string);
}
@@ -1721,8 +1726,8 @@ static void make_file_private(FILE *f)
#if HAVE_FCHMOD
lbool do_chmod = TRUE;
#if HAVE_STAT
- struct stat statbuf;
- int r = fstat(fileno(f), &statbuf);
+ less_stat_t statbuf;
+ int r = less_fstat(fileno(f), &statbuf);
if (r < 0 || !S_ISREG(statbuf.st_mode))
/* Don't chmod if not a regular file. */
do_chmod = FALSE;
diff --git a/contrib/less/command.c b/contrib/less/command.c
index 09eb1614c76d..cba6117c4f6f 100644
--- a/contrib/less/command.c
+++ b/contrib/less/command.c
@@ -38,7 +38,7 @@ extern int hshift;
extern int bs_mode;
extern int proc_backspace;
extern int show_attn;
-extern int less_is_more;
+extern lbool less_is_more;
extern int chopline;
extern POSITION highest_hilite;
extern char *every_first_cmd;
@@ -103,7 +103,8 @@ static int search_incr_hshift;
static time_type ignoring_input_time;
#endif
#if PIPEC
-static char pipec;
+static POSITION pipe_pos1;
+static POSITION pipe_pos2;
#endif
/* Stack of ungotten chars (via ungetcc) */
@@ -181,28 +182,34 @@ static void mca_search1(void)
set_mca(A_B_SEARCH);
if (search_type & SRCH_NO_MATCH)
- cmd_putstr("Non-match ");
+ cmd_putstr(LM(Non_match));
if (search_type & SRCH_FIRST_FILE)
- cmd_putstr("First-file ");
+ cmd_putstr(LM(First_file));
if (search_type & SRCH_PAST_EOF)
- cmd_putstr("EOF-ignore ");
+ cmd_putstr(LM(EOF_ignore));
if (search_type & SRCH_NO_MOVE)
- cmd_putstr("Keep-pos ");
+ cmd_putstr(LM(Keep_pos));
if (search_type & SRCH_NO_REGEX)
- cmd_putstr("Regex-off ");
+ cmd_putstr(LM(Regex_off));
if (search_type & SRCH_WRAP)
- cmd_putstr("Wrap ");
+ cmd_putstr(LM(Wrap));
for (i = 1; i <= NUM_SEARCH_COLORS; i++)
{
if (search_type & SRCH_SUBSEARCH(i))
{
- char buf[INT_STRLEN_BOUND(int)+8];
- SNPRINTF1(buf, sizeof(buf), "Sub-%d ", i);
+ static char *buf = NULL;
+ static size_t buflen;
+ if (buf == NULL)
+ {
+ buflen = INT_STRLEN_BOUND(int)+strlen(LM(Sub_X)+1);
+ buf = ecalloc(buflen, sizeof(char));
+ }
+ SNPRINTF1(buf, buflen, LM(Sub_X), i);
cmd_putstr(buf);
}
}
if (literal_char)
- cmd_putstr("Lit ");
+ cmd_putstr(LM(Lit));
#if HILITE_SEARCH
if (search_type & SRCH_FILTER)
@@ -300,10 +307,10 @@ static void exec_mca(void)
curropt = NULL;
break;
case A_F_BRACKET:
- match_brac(cbuf[0], cbuf[1], 1, (int) number);
+ match_brac(cbuf[0], cbuf[1], TRUE, (int) number);
break;
case A_B_BRACKET:
- match_brac(cbuf[1], cbuf[0], 0, (int) number);
+ match_brac(cbuf[1], cbuf[0], FALSE, (int) number);
break;
#if EXAMINE
case A_EXAMINE: {
@@ -329,7 +336,7 @@ static void exec_mca(void)
constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "!done";
if (done_msg == NULL)
++cbuf;
- if (*cbuf != '!')
+ if (strcmp(cbuf, "!") != 0)
{
if (shellcmd != NULL)
free(shellcmd);
@@ -337,9 +344,7 @@ static void exec_mca(void)
}
if (!secure_allow(SF_SHELL))
break;
- if (shellcmd == NULL)
- shellcmd = "";
- lsystem(shellcmd, done_msg);
+ lsystem(shellcmd == NULL ? "" : shellcmd, done_msg);
break; }
case A_PSHELL: {
constant char *done_msg = (*cbuf == CONTROL('P')) ? NULL : "#done";
@@ -357,7 +362,7 @@ static void exec_mca(void)
++cbuf;
if (!secure_allow(SF_PIPE))
break;
- (void) pipe_mark(pipec, cbuf);
+ (void) pipe_pos(cbuf, pipe_pos1, pipe_pos2);
if (done_msg != NULL)
error(done_msg, NULL_PARG);
break; }
@@ -513,7 +518,7 @@ static int mca_opt_char(char c)
parg.p_string = get_cmdbuf();
if (parg.p_string == NULL)
return (MCA_MORE);
- error("There is no --%s option", &parg);
+ error(LM(There_is_no__X_option), &parg);
return (MCA_DONE);
}
optgetname = FALSE;
@@ -529,7 +534,7 @@ static int mca_opt_char(char c)
if (curropt == NULL)
{
parg.p_string = propt(c);
- error("There is no %s option", &parg);
+ error(LM(There_is_no_X_option), &parg);
return (MCA_DONE);
}
opt_lower = ASCII_IS_LOWER(c);
@@ -608,8 +613,14 @@ static int mca_search_char(char c)
flag = SRCH_NO_MOVE;
break;
case CONTROL('S'): { /* SUBSEARCH */
- char buf[INT_STRLEN_BOUND(int)+24];
- SNPRINTF1(buf, sizeof(buf), "Sub-pattern (1-%d):", NUM_SEARCH_COLORS);
+ static char *buf = NULL;
+ static size_t buflen;
+ if (buf == NULL)
+ {
+ buflen = INT_STRLEN_BOUND(int)+strlen(LM(Sub_pattern_1_X))+1;
+ buf = ecalloc(buflen, sizeof(char));
+ }
+ SNPRINTF1(buf, buflen, LM(Sub_pattern_1_X), NUM_SEARCH_COLORS);
clear_bot();
cmd_putstr(buf);
flush();
@@ -890,15 +901,15 @@ static void prompt_message(void)
{
if (read_error)
{
- error("read error", NULL_PARG);
+ error(LM(read_error), NULL_PARG);
read_error = FALSE;
}
if (search_wrapped)
{
if (search_type & SRCH_BACK)
- error("Search hit top; continuing at bottom", NULL_PARG);
+ error(LM(Search_hit_top), NULL_PARG);
else
- error("Search hit bottom; continuing at top", NULL_PARG);
+ error(LM(Search_hit_bottom), NULL_PARG);
search_wrapped = FALSE;
}
#if OSC8_LINK
@@ -906,7 +917,7 @@ static void prompt_message(void)
{
PARG parg;
parg.p_string = osc8_uri;
- error("Link: %s", &parg);
+ error(LM(Link_X), &parg);
free(osc8_uri);
osc8_uri = NULL;
}
@@ -1328,9 +1339,9 @@ static void multi_search(constant char *pattern, int n, int silent)
PARG parg;
parg.p_string = prev_pattern_text();
if (parg.p_string == NULL) /* {{ can this happen? }} */
- error("Pattern not found", NULL_PARG);
+ error(LM(Pattern_not_found), NULL_PARG);
else
- error("Pattern not found: %s", &parg);
+ error(LM(Pattern_not_found_X), &parg);
}
if (changed_file)
@@ -1425,6 +1436,72 @@ public lbool is_ignoring_input(int action)
return (action != A_PREFIX);
}
+#if PIPEC
+/*
+ * Read a mark char or line number from the user for use by the pipe command.
+ * If mark_char != NULL, accept *mark_char as well as the normal mark chars.
+ * Also return the entered mark char in *mark_char.
+ */
+static POSITION get_pipe_pos(constant char *mark_msg, constant char *line_msg, mutable char *mark_char)
+{
+ lbool get_line = FALSE;
+ char spec_char = '\0';
+ char c;
+
+ start_mca(A_PIPE, mark_msg, NULL, 0);
+ if (mark_char != NULL)
+ {
+ spec_char = *mark_char;
+ *mark_char = '\0';
+ }
+ for (;;)
+ {
+ c = getcc();
+ if (spec_char != '\0' && c == spec_char)
+ {
+ *mark_char = c;
+ return NULL_POSITION;
+ }
+ if (c == CONTROL('N')) /* toggle between reading mark and line number */
+ {
+ get_line = !get_line;
+ cmd_reset();
+ start_mca(A_PIPE, get_line ? line_msg : mark_msg, NULL, 0);
+ } else if (get_line) /* reading line number */
+ {
+ if ((c >= '0' && c <= '9') || is_erase_char(c))
+ {
+ if (cmd_char(c) == CC_QUIT)
+ return NULL_POSITION;
+ } else if (is_newline_char(c))
+ {
+ POSITION pos;
+ LINENUM lnum = cmd_int(NULL);
+ cmd_reset();
+ if (lnum == 0 || (pos = find_pos(lnum)) == NULL_POSITION)
+ {
+ error(LM(Invalid_line_number), NULL_PARG);
+ return NULL_POSITION;
+ }
+ return pos;
+ } else
+ lbell();
+ } else /* reading mark char */
+ {
+ if (is_erase_char(c))
+ return NULL_POSITION;
+ if (is_newline_char(c))
+ c = '.';
+ if (badmark(c))
+ return NULL_POSITION;
+ if (mark_char != NULL)
*** 8772 LINES SKIPPED ***