Vi places text affected by change/delete/yank operations into a
buffer. The contents of such buffers can be restored with the put
commands, 'p' or 'P'. These behave differently depending on whether
the buffer contains whole lines or partial lines. For whole lines
the text is copied into the file on the line before (P) or after
(p) the current line. For partial lines the text is copied before
or after the current cursor position.
Whether an operation results in whole or partial lines depends on
the command used.
BusyBox vi treats any buffer with a newline as though it contained
whole lines. This is incorrect. Deleting multiple words across
a line boundary results in a buffer with a newline but not having
whole lines.
Rework how buffers are handled to behave more like vi.
function old new delta
static.text_yank 79 99 +20
colon 3092 3097 +5
edit_file 885 887 +2
yank_delete 127 112 -15
.rodata 105139 105101 -38
find_range 514 467 -47
do_cmd 5088 4842 -246
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/4 up/down: 27/-346) Total: -319 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
I was puzzled by code in find_range() which handles forward word
movement. It included a test to see if we're at the start of a
word. Since these are forward word movements surely we'd expect to
be at the start of a word? In fact, the test was intended to fix a
problem with changes to the last word in a file, as discussed in the
thread starting here:
http://lists.busybox.net/pipermail/busybox/2004-January/044552.html
The code can be simplified by testing directly for end of file instead
of indirectly for not being at the start of a word. Since trailing
whitespace is now handled in do_cmd() the code to back up off a newline
is no longer required.
function old new delta
find_range 619 514 -105
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-105) Total: -105 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 4b49422a0 (vi: fix changes to word at end of line. Closes
11796) fixed a problem where an operation on a word at the end of
a line followed by a line starting with whitespace incorrectly
joined the lines. However it also broke the case where operating
on multiple words across a line boundary *should* join the lines.
Fix this by detecting when trailing whitepace in a word operation
includes a newline. Whitespace beyond the newline is excluded
from consideration.
function old new delta
do_cmd 5083 5088 +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 5/0) Total: 5 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Fixes bug where commands after the first noXXX command are ignored.
e.g. :set noic tabstop=4
While at it, stop recognizing "notabstop=NNN".
function old new delta
colon 2990 2965 -25
Signed-off-by: Alison Winters <alisonatwork@outlook.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Selection of ranges for change/delete/yank by forward character
motion commands (SPACE or 'l') was incorrect. The range was
always one character whereas vi allows the size of the range to
be specified.
Fix this by executing the motion command the required number of times.
There is a complication when the range is at the end of a line. We need
to distinguish between a range which excludes the last character and
one which includes it. This requires comparing the actual range with
that expected from the command count. (With the additional quirk that
a command count of zero is equivalent to a command count of one.)
function old new delta
find_range 587 619 +32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 32/0) Total: 32 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Treat the output of printf as binary rather than a null-terminated
string so that NUL characters can be output.
This is considered to be a GNU extension, though it's also available
in mawk and FreeBSD's awk.
function old new delta
evaluate 3487 3504 +17
awk_printf 504 519 +15
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 32/0) Total: 32 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Handling of string searches in colon commands (e.g ':/pat1/,/pat2/cmd')
differ from standard vi:
- As reported in bug 10321 such searches can't be repeated using the
'n' command. This is because the last search pattern isn't updated.
- The search also can't be repeated using the command '://' because
an empty search pattern doesn't imply the use of the last search
pattern.
- Such searches should start on the line after the current line,
otherwise '://' never moves to the next occurrence of the pattern.
This can also affect other cases where line ranges are specified
using search patterns.
Fix these various issues.
function old new delta
get_one_address 325 342 +17
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Back in 2007, commit 0c97c9d437 ("'simple' error message functions by
Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower
overhead call to bb_perror_msg() when only a string was being printed
with no parameters. This saves space for some CPU architectures because
it avoids the overhead of a call to a variadic function. However there
has never been a simple version of bb_error_msg(), and since 2007 many
new calls to bb_perror_msg() have been added that only take a single
parameter and so could have been using bb_simple_perror_message().
This changeset introduces 'simple' versions of bb_info_msg(),
bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and
bb_herror_msg_and_die(), and replaces all calls that only take a
single parameter, or use something like ("%s", arg), with calls to the
corresponding 'simple' version.
Since it is likely that single parameter calls to the variadic functions
may be accidentally reintroduced in the future a new debugging config
option WARN_SIMPLE_MSG has been introduced. This uses some macro magic
which will cause any such calls to generate a warning, but this is
turned off by default to avoid use of the unpleasant macros in normal
circumstances.
This is a large changeset due to the number of calls that have been
replaced. The only files that contain changes other than simple
substitution of function calls are libbb.h, libbb/herror_msg.c,
libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c,
networking/udhcp/common.h and util-linux/mdev.c additonal macros have
been added for logging so that single parameter and multiple parameter
logging variants exist.
The amount of space saved varies considerably by architecture, and was
found to be as follows (for 'defconfig' using GCC 7.4):
Arm: -92 bytes
MIPS: -52 bytes
PPC: -1836 bytes
x86_64: -938 bytes
Note that for the MIPS architecture only an exception had to be made
disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h)
because it made these files larger on MIPS.
Signed-off-by: James Byrne <james.byrne@origamienergy.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The 'G' command was omitted from the list of commands that change or
delete whole lines. Add it in the appropriate places so the 'dG',
'cG' and 'yG' commands work, including in cases where an explicit
line number has been supplied.
function old new delta
find_range 534 596 +62
.rodata 175166 175167 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 63/0) Total: 63 bytes
Reported-by: David Kelly <david.kelly@liberica.ch>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
As reported in bug 11796 BusyBox vi incorrectly handles changes
to a word at the end of a line. If the following line starts
with whitespace changing or deleting the last word of a line
with the 'cw' or 'dw' commands causes the lines to be joined.
This happens because the range for the change returned by
find_range() covers all whitespace after the word, including
newlines. The problem can be fixed by setting 'ml' to zero
to indicate to yank_delete() that processing should stop at
the end of the current line.
However, this results in a new problem. 'dw' correctly deletes
all whitespace following the word but so does 'cw', which should
preserve the trailing whitespace. To fix this the code to omit
whitespace from the change is modified to include all whitespace
not just blanks.
function old new delta
do_cmd 5034 5069 +35
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 35/0) Total: 35 bytes
Reported-by: David Kelly <david.kelly@liberica.ch>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
If vi is built with FEATURE_VI_USE_SIGNALS disabled and
FEATURE_VI_WIN_RESIZE enabled new_screen() is used without a
declaration. Move the function to avoid this.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This is the last use of "vsprintf" in busybox:
function old new delta
status_line_bold 72 77 +5
status_line 40 45 +5
vsprintf 23 - -23
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 2/0 up/down: 10/-23) Total: -13 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
On platforms that don't support SIGWINCH vi can be configured
with FEATURE_VI_USE_SIGNALS disabled and FEATURE_VI_WIN_RESIZE
enabled. This allows the user to force an update with ^L when
the screen is resized.
However, because the SIGWINCH handler hasn't run the virtual
screen buffer won't have been updated and the display becomes
corrupted. Fix this by calling new_screen() if necessary.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit bb983f30e (vi: fix faulty undo after autoinsert) has a
number of problems:
- The commit message refers to 'autoinsert' when it really means
'autoindent'.
- The indentation of undo_push_insert() was incorrect.
- Most seriously the commit only fixed the problem for cases where
the indentation was exactly one character. This is because undo_push()
only allows single characters to be queued for UNDO_INS_QUEUED.
Lifting this restriction allows the example given in the previous
commit message (with a three character indent) to work.
function old new delta
undo_push 406 435 +29
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 29/0) Total: 29 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Currently if the 'r' command is followed by a carriage return a
literal CR replaces the current character.
Fix this so that:
- a new line is inserted
- the autoindent setting is respected
- the cursor is placed at the start of the new line
function old new delta
do_cmd 5052 5060 +8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 8/0) Total: 8 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Enable autoinsert and enter the following with an indent of three
spaces:
line 1
line 2
Using 'u' to undo the last insert results in:
line1e 2
The insertion of the indent hasn't been properly recorded.
Since recording insertions is a common operation add a convenience
function, undo_push_insert(), to handle this and use it to record
the autoindent correctly.
function old new delta
undo_push_insert - 36 +36
string_insert 133 129 -4
char_insert 518 473 -45
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/2 up/down: 36/-49) Total: -13 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
If there's any whitespace between w and the filename, parse_file_cmd
writes to the wrong offset when trying to fix up backslashes.
This can be seen in the asan build with busybox sed -e 'w 0\\'
Signed-off-by: Brian Foley <bpfoley@google.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Unlike exit and return, delete strictly requires an arg, and derefs a
null pointer if executed without one.
Signed-off-by: Brian Foley <bpfoley@google.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Avoids an uninit pointer deref for some malformed ternary exprs.
Add a test that would crash in busybox before this fix.
Signed-off-by: Brian Foley <bpfoley@google.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>