The '%' character in a format specification may be followed by
one or more flags from the list "+- #0". BusyBox printf didn't
support the '0' flag or allow multiple flags to be provided.
As a result the formats '%0*d' and '%0 d' were considered to be
invalid.
The lack of support for '0' was pointed out by Andrew Snyder on the
musl mailing list:
https://www.openwall.com/lists/musl/2021/12/14/2
function old new delta
printf_main 860 891 +31
.rodata 99281 99282 +1
------------------------------------------------------------------------------
(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>
Add some tests which coreutils realpath pass but BusyBox realpath
fails (bar one). Adjust xmalloc_realpath_coreutils() so the tests
pass:
- Expand symbolic links before testing whether the last path component
exists.
- When the link target is a relative path canonicalize it by passing
it through xmalloc_realpath_coreutils() as already happens for
absolute paths.
- Ignore trailing slashes when finding the last path component and
correctly handle the case where the only slash is at the start of
the path. This requires ignoring superfluous leading slashes.
- Undo all changes to the path so error messages from the caller show
the original filename.
function old new delta
xmalloc_realpath_coreutils 214 313 +99
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Add the --post-file option to send form data from a file. As with
--post-data it's up to the user to ensure that the data is encoded
as appropriate: all wget does is stuff the provided data into
the request.
The --post-data and --post-file options are mutually exclusive and
only one instance of either may be given.
Additionally:
- update the usage message to include missing details of the --post-data
and --header options;
- free POST data if FEATURE_CLEAN_UP is enabled.
function old new delta
packed_usage 34158 34214 +56
wget_main 2762 2805 +43
.rodata 99225 99240 +15
static.wget_longopts 266 278 +12
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 126/0) Total: 126 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Some people prefer the week to start on Monday. Add the '-m'
option to support this.
function old new delta
cal_main 926 966 +40
day_array 316 337 +21
packed_usage 34151 34158 +7
.rodata 99224 99225 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 69/0) Total: 69 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 9fe1548bb (date,touch: allow timezone offsets in dates)
mentioned the similarity between '@' format dates and those with
timezone offsets. It didn't notice that as a result there's
common code which can be shared.
function old new delta
parse_datestr 730 687 -43
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-43) Total: -43 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
If the mode_string array is no longer static we can't rely on
it being NUL terminated.
function old new delta
bb_mode_string 115 118 +3
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Allow ISO 8601 style dates to include a timezone offset. Like
the '@' format these dates aren't relative to the user's current
timezone and shouldn't be subject to DST adjustment.
- The implementation uses the strptime() '%z' format specifier.
This an extension which may not be available so the use of
timezones is a configuration option.
- The 'touch' applet has been updated to respect whether DST
adjustment is required, matching 'date'.
function old new delta
parse_datestr 624 730 +106
static.fmt_str 106 136 +30
touch_main 388 392 +4
date_main 818 819 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 4/0 up/down: 141/0) Total: 141 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The default build uses strptime() in parse_datestr() to support the
'month_name d HH:MM:SS YYYY' format of GNU date. If we've linked
with strptime() there's an advantage is using it for other formats
too.
There's no change to the non-default, non-DESKTOP build.
function old new delta
fmt_str - 106 +106
.rodata 99216 99145 -71
parse_datestr 948 624 -324
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/2 up/down: 106/-395) Total: -289 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit fb7d6c89 from Harald van Dijk's gwsh variant of ash
(https://github.com/hvdijk/gwsh):
ignoreeof is documented as only having an effect for interactive shells,
but is implemented as having mostly the same effect for interactive
shells as for non-interactive shells. Change the implementation to match
the documentation.
Test case:
$SHELL -o ignoreeof /dev/null
function old new delta
cmdloop 359 361 +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 2/0) Total: 2 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When the user tries to exit an interactive shell with stopped jobs
present the shell issues a warning and only exits if the user
insists by trying to exit again.
This shouldn't apply to non-interactive shells.
Reported-by: Roberto A. Foglietta <roberto.foglietta@gmail.com>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The ignoreeof option should prevent an interactive shell from
exiting on EOF. This hasn't worked in BusyBox ash since commit
727752d2d (ash: better fix for ash -c 'echo 5&' and ash -c 'sleep 5&'
with testcase).
Commit 3b4d04b77e (ash: input: Allow two consecutive calls to pungetc)
pulled in improved support for multiple calls to pungetc from dash,
thus rendering much of commit 727752d2d obsolete. Removing this old
code fixes the problem with ignoreeof.
function old new delta
__pgetc 605 587 -18
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-18) Total: -18 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 7d06d6e18 (awk: fix printf %%) can cause awk printf to read
beyond the end of a strduped buffer:
2349 while (*f && *f != '%')
2350 f++;
2351 c = *++f;
If the loop terminates because a NUL character is detected the
character after the NUL is read. This can result in failures
depending on the value of that character.
function old new delta
awk_printf 672 665 -7
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Stacy Harper reports that this script:
test() { . /tmp/bb_test; }
echo "export TEST=foo" >/tmp/bb_test
test 2>/dev/null
echo "$TEST"
correctly prints 'foo' in BusyBox 1.33 but hangs in 1.34.
Bisection suggested the problem was caused by commit a1b0d3856 (ash: add
process substitution in bash-compatibility mode). Removing the call to
unwindredir() in cmdloop() introduced in that commit makes the script
work again.
Additionally, these examples of process substitution:
while true; do cat <(echo hi); done
f() { while true; do cat <(echo hi); done }
f
result in running out of file descriptors. This is a regression from
v5 of the process substitution patch caused by changes to evalcommand()
not being transferred to v6.
function old new delta
static.pushredir - 99 +99
evalcommand 1729 1750 +21
exitreset 69 86 +17
cmdloop 372 365 -7
unwindredir 28 - -28
pushredir 112 - -112
------------------------------------------------------------------------------
(add/remove: 1/2 grow/shrink: 2/1 up/down: 137/-147) Total: -10 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Improved error messages:
- specify when a search fails or a mark isn't set;
- warn when line addresses are out of range or when a range of
lines is reversed.
Addresses are limited to the number of lines in the file so a
command like ':2000000000' (go to the two billionth line) no
longer causes a long pause.
Improved vi compatibility of '+' and '-' operators that aren't
followed immediately by a number:
:4+++= 7
:3-2= 1
:3 - 2= 4 (yes, really!)
In a command like ':,$' the empty address before the separator now
correctly refers to the current line. (The similar case ':1,' was
already being handled.)
And all with a tidy reduction in bloat (32-bit build):
function old new delta
colon 4029 4069 +40
.rodata 99348 99253 -95
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 40/-95) Total: -55 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
gcc 11.2.1 complains that the tar header checksum might overflow
the checksum field. It won't and using an unsigned int for the
calculation seems to convince the compiler too.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
A user noted that the following command was slower than they
expected:
busybox shuf -i "1500000000-$(date +%s)" -n 5
At time of writing the range contains 128 million values. On my
system this takes 7.7s whereas 'shuf' from coreutils takes a
handful of milliseconds.
Optimise BusyBox 'shuf' for cases where -n is specified by stopping
shuffling once the required number of lines have been processed.
On my system the time for the example is reduced to 0.4s.
function old new delta
shuf_main 520 540 +20
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 20/0) Total: 20 bytes
v2: Code shrink. Since outlines <= numlines:
- the loop in shuffle_lines() only needs to test the value of
outlines;
- shuffle_lines() can be called unconditionally.
Update timing to allow for the 13 million seconds elapsed since v1.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Simplify the function print_literal() which is used to format a
string that may contain unprintable characters or control
characters.
- Unprintable characters were being displayed in normal text rather
than the bold used for the rest of the message. This doesn't seem
particularly helpful and it upsets the calculation of the width
of the message in show_status_line(). Use '?' rather than '.' for
unprintable characters.
- Newlines in the string were displayed as both '^J' and '$', which
is somewhat redundant.
function old new delta
not_implemented 199 108 -91
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-91) Total: -91 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The '/' and '?' search commands wrap to the other end of the buffer
if the search target isn't found. When searches are used to specify
addresses in colon commands they should do the same.
(In traditional vi and vim this behaviour is controlled by the
'wrapscan' option. BusyBox vi doesn't have this option and always
uses the default behaviour.)
function old new delta
colon 4033 4077 +44
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 44/0) Total: 44 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The input buffer is initialised to a reasonable size and extended
if necessary. When this happened the offset into the buffer wasn't
reset to zero so subsequent lines were appended to the long line.
Fix this and add some tests.
function old new delta
rev_main 377 368 -9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Run initialisation commands from ~/.exrc. As with EXINIT these
commands are processed before the first file is loaded.
Commands starting with double quotes are ignored. This is how
comments are often included in .exrc.
function old new delta
vi_main 268 406 +138
colon 4033 4071 +38
.rodata 108411 108442 +31
packed_usage 34128 34118 -10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/1 up/down: 207/-10) Total: 197 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Rewrite handling of command line arguments so any number of -c
commands will be processed. Previously only two -c commands
were allowed (or one if EXINIT was set).
Process commands from EXINIT before the first file is read into
memory, as specified by POSIX.
function old new delta
run_cmds - 77 +77
.rodata 108410 108411 +1
vi_main 305 268 -37
edit_file 816 764 -52
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/2 up/down: 78/-89) Total: -11 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When long options were disabled cp failed to compile with:
coreutils/cp.c:130:9: error: empty enum is invalid
130 | };
| ^
Rearrange the conditional compilation to suit.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Building with FEATURE_VI_REGEX_SEARCH enabled fails.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
When regular expressions are allowed in search commands it becomes
possible to escape the delimiter in search/replace commands. For
example, this command will replace '/abc' with '/abc/':
:s/\/abc/\/abc\//g
The code to split the command into 'find' and 'replace' strings
should allow for this possibility.
VI_REGEX_SEARCH isn't enabled by default. When it is:
function old new delta
strchr_backslash - 38 +38
colon 4378 4373 -5
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/1 up/down: 38/-5) Total: 33 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Suppose we search for a git conflict marker '<<<<<<< HEAD' using
the command '/^<<<'. Using 'n' to go to the next match finds
'<<<' on the current line, apparently ignoring the '^' anchor.
Set a flag in the compiled regular expression to indicate that the
start of the string should not be considered a beginning-of-line
anchor. An exception has to be made when the search starts from
the beginning of the file. Make a similar change for end-of-line
anchors.
This doesn't affect a default build with VI_REGEX_SEARCH disabled.
When it's enabled:
function old new delta
char_search 247 285 +38
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Both traditional vi and vim use basic regular expressions for
search. Also, they don't allow matches to extend across line
endings. Thus with the file:
123
234
the search '/2.*4$' should find the second '2', not the first.
Make BusyBox vi do the same.
Whether or not VI_REGEX_SEARCH is enabled:
function old new delta
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0) Total: 0 bytes
Signed-off-by: Andrey Dobrovolsky <andrey.dobrovolsky.odessa@gmail.com>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 7b93e317c (vi: enable 'dG' command. Closes 11801) allowed
'G' to be used as a range specifier for change/yank/delete
operations.
Add similar support for 'gg'. This requires setting the 'cmd_error'
flag if 'g' is followed by any character other than another 'g'.
function old new delta
do_cmd 4852 4860 +8
.rodata 108179 108180 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 9/0) Total: 9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The same stored search pattern applies to both search ('/') and
search/replace (':s') operations.
A search/replace operation with an empty "find" string (':s//abc/')
should use the last stored search pattern, if available, and issue an
error message if there is none.
If the "find" string is not empty it should replace the stored search
pattern.
function old new delta
colon 3952 4024 +72
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 72/0) Total: 72 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When the '-t DIR' option is used the loop over the remaining
arguments should terminate when a NULL pointer is reached.
function old new delta
mv_main 585 590 +5
cp_main 492 496 +4
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 9/0) Total: 9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
With FEATURE_VI_REGEX_SEARCH enabled backward searches don't work.
This is problematic on distros that enable regexes, such as Tiny
Core Linux and Fedora.
When calling GNU re_search() with a negative range parameter
(indicating a backward search) the start offset must be set to
the end of the area being searched.
The return value of re_search() is the offset of the matched pattern
from the start of the area being searched. For a successful search
(positive return value) char_search() can return the pointer to
the start of the area plus the offset.
FEATURE_VI_REGEX_SEARCH isn't enabled by default but when it is:
function old new delta
char_search 256 247 -9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-9) Total: -9 bytes
Signed-off-by: Andrey Dobrovolsky <andrey.dobrovolsky.odessa@gmail.com>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
If the motion command used to define the range of a change, yank or
delete fails the whole command should be rejected. BusyBox vi already
handled failed searches in these circumstances. Add some more cases:
- non-existent mark: d'x
- movement beyond end of file: c99999+ or 99999<<
This is implemented using a global variable which is set when a command
error is detected. Unlike the case of motion within a line it's
insufficient to check that the motion command doesn't move the cursor:
this fails to process 'LyL' correctly, for example, as the second 'L'
doesn't move the cursor.
function old new delta
indicate_error 75 82 +7
find_range 686 692 +6
do_cmd 4851 4852 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 14/0) Total: 14 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
In traditional vi and vim line motion commands ('+'/'-'/'j'/'k')
fail if the movement would exceed the bounds of the file. BusyBox vi
allowed such commands to succeed, leaving the cursor on the first or
last character of the file.
Make BusyBox vi work like vi/vim.
For the 'G'/'H'/'L' commands traditional vi treats an out of bounds
result as an error, vim doesn't. BusyBox vi behaves like vim, both
before and after this patch.
function old new delta
do_cmd 4785 4851 +66
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 66/0) Total: 66 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When ESC is entered to leave insert mode any autoindent should only
be removed if there's no content beyond the indent. This may be the
case if a line has been split by entering insert mode and then
entering a CR.
Add a check to ensure there's only a newline after the indent.
function old new delta
char_insert 912 929 +17
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 17/0) Total: 17 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The default tabstop value should be set during early start up,
not reset for each new file.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When no line number is specified ':read' should place the inserted
text after the current line, not before.
This used to be correct but was broken when commit 0c42a6b07
(vi: fix empty line range regression) revealed a bug in commit
7a8ceb4eb (vi: changes to line addresses for colon commands).
function old new delta
colon 3960 3952 -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8) Total: -8 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Process substitution is a Korn shell feature that's also available
in bash and some other shells. This patch implements process
substitution in ash when ASH_BASH_COMPAT is enabled.
function old new delta
argstr 1386 1522 +136
strtodest - 52 +52
readtoken1 3346 3392 +46
.rodata 183206 183250 +44
unwindredir - 28 +28
cmdloop 365 372 +7
static.spclchars 10 12 +2
cmdputs 380 367 -13
exitreset 86 69 -17
evalcommand 1754 1737 -17
varvalue 675 634 -41
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 5/4 up/down: 315/-88) Total: 227 bytes
text data bss dec hex filename
953967 4219 1904 960090 ea65a busybox_old
954192 4219 1904 960315 ea73b busybox_unstripped
v2: Replace array of file descriptors with a linked list.
Include tests that were unaccountably omitted from v1.
v3: Update linked list code to the intended version.
v4: Change order of conditional code in cmdputs().
v5: Use existing popredir() mechanism to manage file descriptors.
v6: Rebase to latest version of BusyBox ash. Reduce code churn.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Lines that have no content apart from automatic indentation should
be treated as empty when the user hits return or ESC.
The implementation uses the global variable 'indentcol'. Usually
this is zero. It can also be -1 to indicate an 'O' (open above)
command, replacing the overloading of the tabstop option bit.
A value greater than zero indicates that the current line has
been autoindented to the given column (or that the autoindent has
been adjusted with ctrl-D). Any other change to the line resets
'indentcol' to zero.
Replace strspn() with ident_len(). The latter handles the unlikely
case that it's called on the last line of a file which doesn't have
a terminating newline.
function old new delta
char_insert 741 912 +171
indent_len - 42 +42
do_cmd 4781 4785 +4
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 2/0 up/down: 217/0) Total: 217 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Autoindent took a copy of the indent from a neighbouring line, which
may not have respected the expandtab setting.
Determine the target column and construct a suitable indent. This
will consist entirely of spaces if expandtab is enabled or an
efficient combination of tabs and spaces otherwise.
function old new delta
char_insert 719 741 +22
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 22/0) Total: 22 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 24effc7a3 (vi: cursor positioning after whole-line 'y')
tried to save a few bytes by treating whole-line deletion the
same as whole-line yank. If the deletion removed the last lines
of the file the cursor was left beyond the end of the file.
Revert the part of the commit related to whole-line deletion.
Position the cursor on the first non-whitespace character of the
line when whole lines are 'put'.
function old new delta
do_cmd 4759 4781 +22
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 22/0) Total: 22 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
':wq' or ':x' should issue a warning if there are more files to edit,
unless they're followed by '!'.
function old new delta
colon 3911 3960 +49
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 49/0) Total: 49 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The 'y' command to yank text should leave the cursor at the start
of the range. This mostly works correctly in BusyBox vi but not
for whole-line yanks with backward motion, e.g. '2yk' to yank two
lines backwards. In this case the cursor is left at the end of the
range.
Fix this by returning the actual range from find_range(). Cursor
positioning following whole-line deletion is inconsistent between
vim and traditional vi. For BusyBox vi chose the option that uses
least code without being exactly compatible with either.
Also, find_range() preserved the value of 'dot', the current cursor
position. Since this isn't used by either caller of find_range()
we can save a few bytes by not bothering.
function old new delta
do_cmd 4730 4759 +29
find_range 749 686 -63
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 29/-63) Total: -34 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 7a8ceb4eb (vi: changes to line addresses for colon commands)
was supposed to address the issue:
When the last address is empty it should refer to the current line.
This was intended to allow ranges of the form '1,' with an empty
last address. It should have been expressed as:
When the last address is empty *and the second last isn't* it
should refer to the current line.
Otherwise a command like ':w' only writes the current line resulting
in serious loss of data.
function old new delta
colon 3906 3911 +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>
Track the current and alternate filenames. The placeholders '%'
and '#' can be used in arguments to colon commands to represent
the current and alternate filenames respectively. Backslash can
be used to allow literal '%' and '#' characters to be entered.
This feature is controlled by the configuration option
FEATURE_VI_COLON_EXPAND.
function old new delta
expand_args - 198 +198
colon 3751 3927 +176
update_filename - 70 +70
init_filename - 48 +48
.rodata 105218 105239 +21
get_one_char 115 124 +9
edit_file 835 838 +3
do_cmd 4724 4727 +3
init_text_buffer 190 172 -18
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 5/1 up/down: 528/-18) Total: 510 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
It was possible for get_input_line() to store its NUL terminator
one character beyond the end of its buffer.
Code shrink in colon():
- Certain colon commands can be matched exactly, as any shorter
string would be matched earlier, e.g. ':wq' versus ':write'.
- Command matching is now case sensitive so there's no need to
check for 'N' or 'Q' suffixes.
- Rewrite how commands and arguments are split.
function old new delta
colon 3848 3751 -97
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-97) Total: -97 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Improvements to ':read':
- When a file is read into the current buffer the cursor should be
placed on the first line read.
- If invoked without supplying a filename the current filename should
be used. This is similar to how ':edit' works.
- The code for ':edit' included an explicit check that the current
filename was non-empty. Both vim and traditional vi accept non-empty
filenames, only issuing an error message when an attempt to use such
a name fails.
- Allow undo of a file read.
function old new delta
file_insert 367 382 +15
colon 3841 3848 +7
.rodata 105236 105218 -18
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 22/-18) Total: 4 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When a new file is opened from an existing editing session the
following details should be preserved:
- the last command used;
- the last character searched for on a line.
function old new delta
edit_file 849 835 -14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-14) Total: -14 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When 'ZZ' was used to save the current file and more files were
available to edit BusyBox vi immediately moved on to the next file.
The correct behaviour is to issue a warning.
function old new delta
do_cmd 4673 4724 +51
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 51/0) Total: 51 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Suppose vi is started with the command 'vi -R', that is, in readonly
mode with no filename. Attempting to save the file with 'ZZ' or ':w'
results in the message:
'(null)' is read only
Skip the code which prints this if no filename was provided, thus
falling through to file_write() which gives the more helpful message
'No current filename'.
function old new delta
colon 3867 3874 +7
do_cmd 4668 4673 +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 12/0) Total: 12 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Since commit 74d565ff1 (vi: make context marks more like vi) the
list of commands that modify the text is no longer required when
FEATURE_VI_YANKMARK is enabled, only FEATURE_VI_DOT_CMD.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Make line addresses behave more like vi:
- Vi allows the user to enter an arbitrary number of addresses,
though only the last two are used. This simplifies get_address()
by reducing the amount of state that needs to be carried.
- When a command requires a single address the last one entered is
used.
- If addresses are separated by a ';' instead of a ',' the current
line is updated to the left address. This may be useful when a
search is used to specify a range, e.g. ':/first/;/last/d'.
- When the last address is empty it should refer to the current line.
function old new delta
colon 3855 3834 -21
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-21) Total: -21 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit ac6495f6f (vi: allow ctrl-D to reduce indentation) treated
ctrl-D during autoindent as a backspace. This was adequate for
indentation using tabs but doesn't work well with the expandtab
option. In the latter case it's necessary to backspace over all
the spaces.
Make ctrl-D work correctly when spaces are present in the indent.
Also, make it behave more like vim:
- ctrl-D is independent of autoindent;
- indentation is reduced even when the cursor isn't positioned at
the end of the indent.
function old new delta
char_insert 679 717 +38
get_column - 37 +37
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 75/0) Total: 75 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This implements the vim option expandtab in BusyBox vi. From
vim help:
In Insert mode: Use the appropriate number of spaces to insert a
<Tab>. Spaces are used in indents with the '>' and '<' commands and
when 'autoindent' is on. To insert a real tab when 'expandtab' is
on, use CTRL-V<Tab>.
This implementation doesn't change how BusyBox vi handles autoindent:
it continues to copy the indentation from a neighbouring line. If
that line has tabs in its indentation so too will the new line.
function old new delta
char_insert 563 679 +116
next_column - 48 +48
.rodata 105211 105236 +25
colon 3844 3855 +11
refresh 1000 982 -18
move_to_col 83 59 -24
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 3/2 up/down: 200/-42) Total: 158 bytes
Signed-off-by: Peter D <urmum69@snopyta.org>
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Line addresses in colon commands can be defined using an expression
that includes '+' or '-' operators. The implementation follows
traditional vi:
- The first term in the expression defines an address. It can be
an absolute line number, '.', '$', a search or a marker.
- The second and subsequent terms must be non-negative integers.
- If the first term is missing '.' is assumed. If the operator is
missing addition is assumed. If the final term in missing an
offset of 1 is assumed.
Thus the following are valid addresses:
.+1 .+ + .1
.-1 .- -
The following are not valid (though they are in vim):
.+$ .$ 2+.
function old new delta
colon 3701 3844 +143
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 143/0) Total: 143 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
It should be possible to use a backward search as a line address
in colon commands.
function old new delta
colon 3661 3701 +40
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 40/0) Total: 40 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
BusyBox vi didn't have proper handling for invalid markers or
unsuccessful searches in colon line addresses. This could result
in the wrong lines being affected by a change.
Detect when an invalid address is specified, propagate an error
indicator up the call chain and issue a warning.
function old new delta
colon 3604 3661 +57
.rodata 105195 105211 +16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 73/0) Total: 73 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The context marks that are automatically updated and can be used
with the "''" command didn't behave the same as in vi. Marks
were only being set for certain editing commands when they should
have been set on successful movement commands.
Make BusyBox vi behave more like vi.
function old new delta
.rodata 105179 105194 +15
do_cmd 4723 4668 -55
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 15/-55) Total: -40 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Opening a line above the current line with the 'O' command should
use the current, not previous, line to determine how much to
autoindent.
function old new delta
char_insert 531 563 +32
do_cmd 4746 4723 -23
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 32/-23) Total: 9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When whitespace has been automatically added to a new line due to
autoindent entering ctrl-D should reduce the level of indentation.
Implement an approximation of this by treating ctrl-D as backspace.
For the common case of indentation using tabs this is good enough.
My attempt at a full implementation was three times bigger.
function old new delta
char_insert 476 531 +55
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 55/0) Total: 55 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When whole lines are yanked using 'yy' or 'Y' vi doesn't change the
cursor position. Make BusyBox vi do the same.
function old new delta
do_cmd 4776 4786 +10
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 10/0) Total: 10 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Since commit a54450248 (vi: allow the '.' command to have a
repetition count) using '0' to specify a range doesn't work with
a non-zero repeat count, e.g. '1d0'. Users wouldn't normally try
to do that but the '.' command does.
Add a special case in get_motion_char() to handle this.
function old new delta
find_range 737 746 +9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 9/0) Total: 9 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Use a hand-coded loop to search for paragraph boundaries instead
of calling char_search(). We were using a loop anyway to skip
consecutive newlines.
function old new delta
do_cmd 4792 4752 -40
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-40) Total: -40 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Vi places the cursor on the last column of a tab character whereas
BusyBox vi puts it on the first. This is disconcerting for
experienced vi users and makes it impossible to distinguish
visually between an empty line and one containing just a tab.
It wasn't always this way. Prior to commit e3cbfb91d (vi: introduce
FEATURE_VI_8BIT) BusyBox vi also put the cursor on the last column.
However there were problems with cursor positioning when text was
inserted before a tab. Commit eaabf0675 (vi: multiple fixes by
Natanael Copa) includes a partial attempt to fix this. (The code is
still present but it's never executed. Clever compilers optimise it
away.)
Revert the changes of commit e3cbfb91d and fix the insert problem
for all tabs, not just the first.
To quote Natanael: "Costs a few bytes but its worth it imho".
function old new delta
refresh 974 1000 +26
move_to_col 81 83 +2
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 28/0) Total: 28 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The undo queue didn't record deleted characters properly. For
example, insert some text, backspace over a couple of characters
then exit insert mode. At this point undo will restore two nulls
instead of the deleted characters.
The fix is in undo_push(): record the state of the UNDO_USE_SPOS
flag and clear it before using 'u_type'.
Also, update the comments to reflect the fact that UNDO_QUEUED_FLAG
isn't actually used.
function old new delta
undo_push 443 435 -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-8) Total: -8 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Commit 4bdc914ff (build system: fix compiler warnings) added a
test on the return value of fgets() in split-include.c.
During bisection it's possible to go back to a state where a
configuration value didn't exist. This results in an empty
include file corresponding to the missing feature. If a
subsequent bisection returns to a state where the feature exists
split-include treats the empty file as an error and the build
fails.
Add a call to ferror() to distinguish between fgets() failing
due to an error and due to there being no data to read.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Traditional vi is mostly silent about the results of yank, delete,
change, undo or substitution commands. Vim reports some details
about undo and substitution. BusyBox vi is positively verbose in
comparison.
Make some improvements to BusyBox vi:
- Add vim-like reporting of changes caused by substitutions, of
the form '64 substitutions on 53 lines'. This replaces a fairly
useless report of the result of the last change made.
- Ensure that the report about put operations correctly reflects the
newly introduced repetition count.
- Commit 25d2592640 tried to limit status updates for delete and
yank operations by detecting whether the register had changed.
This didn't always work because the previously allocated memory
could be reused for the new register contents. Fix this by
delaying freeing the old register until after the new one has
been allocated.
- Add a configuration option to control verbose status reporting.
This is on by default. Turning it off make BusyBox vi as taciturn
as traditional vi and saves 435 bytes.
function old new delta
colon 3212 3292 +80
yank_status - 74 +74
static.text_yank 99 86 -13
string_insert 130 76 -54
do_cmd 4842 4776 -66
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/3 up/down: 154/-133) Total: 21 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When a search for a character within a line fails issue a warning.
function old new delta
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0) Total: 0 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Make the ':s/find/replace/g' command behave more like vi:
- the final delimiter is optional if no flag is specified;
- the cursor is moved to the first visible character of the last
line where a substitution was made;
- a warning is displayed if no substitution was made.
function old new delta
colon 3156 3212 +56
.rodata 105133 105142 +9
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 65/0) Total: 65 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Make the put commands 'p' and 'P' behave more like vi:
- allow a repetition count to be specified;
- when the text being inserted doesn't include a newline the cursor
should be positioned at the end of the inserted text.
function old new delta
do_cmd 4765 4842 +77
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 77/0) Total: 77 bytes
v2: Don't break build when FEATURE_VI_UNDO is disabled.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The '.' command repeats the last text change. When it has a
repetition count replay the change the number of times requested.
Update the stored count if it changes. For example,
3dw deletes 3 words
. deletes another 3 words
2. deletes 2 words and changes the stored count
. deletes 2 words
function old new delta
do_cmd 4746 4781 +35
.rodata 105133 105138 +5
edit_file 887 849 -38
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/1 up/down: 40/-38) Total: 2 bytes
v2: Change implementation to include repetition count in string.
Otherwise repeating 'r' doesn't work properly.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Make the 'r' command behave more like vi:
- abort the command if ESC is entered after the 'r';
- allow a repeat count to be entered before the 'r';
- if the repeat count exceeds the space available on the line don't
change any characters and issue an alert.
function old new delta
do_cmd 4679 4746 +67
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 67/0) Total: 67 bytes
v2: Don't break build when FEATURE_VI_UNDO is disabled.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The left shift operator ('<') didn't support undo at all; right
shift ('>') required changes to be undone separately for each line.
Allow both types of shift to be undone as a single operation.
Also, neither traditional vi nor vim yank the lines being shifted by
the '<' and '>' commands, so remove that call to yank_delete();
When a repetition count was specified for the '~', 'x', 'X' or 's'
commands the changes had to be undone one character at a time.
Allow undo as a single operation (though the delete and change
parts of the 's' command still have to be undone separately).
function old new delta
undo_push_insert 37 40 +3
do_cmd 4695 4663 -32
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 3/-32) Total: -29 bytes
v2: Don't break build when FEATURE_VI_UNDO is disabled. Don't reset
'undo_del' too early in '~' handling code. Code shrink '~'.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
An example in my vi book presents different ways to fix the spelling
of the last word in a line:
... anyweigh.
With the cursor on the 'e' the command 'cway' should do the job.
Since commit 776b56d77, though, 'cw' incorrectly includes the full
stop in the range if we're on the last line of the file.
(Prior to commit 776b56d77 BusyBox vi got 'cw' right in this case but
'cW' wrong: it *didn't* delete the full stop.)
Reinstate some of the bloat removed by the earlier commit to fix this.
Also, commit 7b4c2276a (vi: fix word operations across line boundaries)
incorrectly ignores whitespace after a single character word. Adjust
the condition to avoid this.
function old new delta
find_range 707 737 +30
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 30/0) Total: 30 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Rewrite find_range(), pushing quite a bit of code from do_cmd()
down into it.
- The commands 'y', 'd', 'c', '<' and '>' can be given twice to
specify a whole-line range. BusyBox vi actually accepted any
second character from that group, e.g. 'dc' or '<y', with the
latter being accepted even if yank was disabled. Require the
two characters to match.
- '<' and '>' commands followed by ESC incorrectly issued an alert.
- Allow search commands and a marker (specified as "y'a", for example)
to define a range for those operators that support it.
function old new delta
find_range 518 707 +189
.rodata 105119 105133 +14
get_motion_char 68 - -68
do_cmd 4860 4695 -165
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 2/1 up/down: 203/-233) Total: -30 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Changes to search commands ('/', '?', 'n' and 'N'):
- Rewrite to be smaller and (possibly) clearer.
- Issue a warning when a repeat search is requested without a
previous search having been made.
Vim and BusyBox vi support a repetition count for searches though
the original vi doesn't. If the count exceeds the number of
occurrences of the search string the search may loop through the
file multiple times.
function old new delta
.rodata 105135 105119 -16
do_cmd 4898 4860 -38
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-54) Total: -54 bytes
Signed-off-by; Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Since commit 70ee23399 (vi: code shrink) the ':set' command is
unable to process multiple options on a line. Fix this by
temporarily null-terminating each option.
Change the default setting for all options to off to match vim.
Actually, 'flash' isn't an option in vim, only traditional vi,
where it's on by default. In vim the corresponding option is
'visualbell' which defaults to off. POSIX doesn't have either
of these.
Allow the abbreviation 'ts' for the 'tabstop' option.
Issue an error message if:
- an option is not implemented
- an option that takes a value has no '=' or has a 'no' prefix
- a boolean option has a '='
function old new delta
colon 2944 3003 +59
.rodata 103171 103189 +18
vi_main 274 270 -4
setops 73 - -73
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 2/1 up/down: 77/-77) Total: 0 bytes
v2: Try harder to detect invalid options. Thanks to Peter D for pointing
this out.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Since commit 25d259264 (vi: make buffer handling more vi-like)
find_range() can return early when an invalid movement is
specified.
The call to find_range() in the code that handles shift commands
('<' and '>') doesn't check for this condition. Previously this
only resulted in the current line being shifted but it can now
result in a segfault.
Check for an invalid movement and notify the user without taking
any further action.
function old new delta
do_cmd 4890 4898 +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>
- In the '+' and '-' commands the call to dot_skip_over_ws() is
only needed for the final line processed so it can be moved out
of the while loop.
- Marking sync_cursor() NOINLINE doesn't seem to offer the same
advantages it did in 2009 (commit adf922ec2).
function old new delta
refresh 694 974 +280
do_cmd 4900 4887 -13
sync_cursor 336 - -336
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/1 up/down: 280/-349) Total: -69 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Movement by paragraph doesn't always involve whole lines. If the
cursor is positioned in the middle of a line deleting to either end
of the paragraph will result in one partial line and zero or more
full lines.
Adjust the end of ranges delimited by paragraph movement to more
closely match what vi does.
function old new delta
find_range 467 518 +51
at_eof - 49 +49
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/0 up/down: 100/0) Total: 100 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When moving by paragraph ('{' and '}'):
- Treat multiple empty lines as a single paragraph separator.
- When no paragraph separator is found move to the start or end of
the file depending on the direction of motion.
function old new delta
do_cmd 4821 4900 +79
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 79/0) Total: 79 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The paragraph motion commands '{' and '}' should accept a count.
function old new delta
do_cmd 5054 5071 +17
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 17/0) Total: 17 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The motion that determines the range of a change, delete, yank
or shift operation can have its own count. Thus the commands
'5dd' and 'd5d' are equivalent: both delete 5 lines.
When the command itself also has a count the two values are
multiplied. Thus the command '2d3w' deletes 6 words and '2D3G'
deletes from the current line to line 6.
(When dealing with structured data it might make sense to think in
units of 3 words so '2d3w' is deleting 2 such units. It doesn't
seem quite as sensible to express 'delete from current line to line 6'
as '2D3G' but vi permits it.)
function old new delta
get_motion_char - 68 +68
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/0 up/down: 68/0) Total: 68 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Add 'F', 'T' and '|' as commands that can be used to specify a
range for change/delete/yank operations.
function old new delta
.rodata 105129 105135 +6
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 6/0) Total: 6 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
- Use a common routine to handle all commands to search for a
character in a line.
- When searching for the nth occurrence of a character don't move
the cursor if fewer than n occurrences are present.
- Add support for the 'T' command, search backwards for character
after next occurrence of given character.
function old new delta
do_cmd 4861 4805 -56
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-56) Total: -56 bytes
v2: Add parentheses to avoid searches continuing past end of line.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
When the 'j'/'k' commands or up/down arrow keys are used to move
the cursor vertically 'vi' remembers the original cursor column
and positions the cursor there if possible. Also, if the '$'
command has been used to position the cursor at the end of a line
vertical movements keep the cursor at the end of the line.
Make BusyBox 'vi' do the same.
function old new delta
refresh 674 694 +20
do_cmd 4853 4861 +8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 28/0) Total: 28 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The 'G' command with no target (meaning 'go to last line') should
position the cursor on the first visible character of the line, as
it already does in other cases.
The 'M' command should position the cursor on the first visible
character (as 'H' and 'L' already do).
function old new delta
do_cmd 4842 4853 +11
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 11/0) Total: 11 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
If the name of the file being written doesn't match the current
filename and the output file already exists vi should issue a
warning and not overwrite the file.
Because the test only compares the file names it's somewhat over-
protective. If the current file name is 'my_text' and the user tries
to save to './my_text' they'll be prevented from doing so.
function old new delta
colon 3092 3151 +59
.rodata 105118 105146 +28
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 87/0) Total: 87 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
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>
Disable 'echo' in the default config, run 'make baseline', then
re-enable 'echo' and run 'make bloatcheck':
function old new delta
.rodata 182521 182622 +101
packed_usage 33714 33792 +78
applet_main 3168 3176 +8
applet_names 2730 2735 +5
applet_suid 99 100 +1
applet_install_loc 198 199 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 194/0) Total: 194 bytes
text data bss dec hex filename
955052 4195 1808 961055 eaa1f busybox_old
955153 4195 1808 961156 eaa84 busybox_unstripped
The Total bytes value doesn't equal the change in the size of the
binary. The packed_usage and applet_* items are in .rodata and
are counted twice. With this modified bloat-o-meter the size of
named items is deducted from .rodata:
function old new delta
packed_usage 33714 33792 +78
applet_main 3168 3176 +8
.rodata 105105 105113 +8
applet_names 2730 2735 +5
applet_suid 99 100 +1
applet_install_loc 198 199 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 6/0 up/down: 101/0) Total: 101 bytes
text data bss dec hex filename
955052 4195 1808 961055 eaa1f busybox_old
955153 4195 1808 961156 eaa84 busybox_unstripped
v2: Sections numbered less than 10 were always being omitted from
consideration because splitting "[ 1] .interp" leaves "1]" in
x[1] where the section name is expected. This wasn't a problem
for .rodata (numbered 15 in my testing) but let's fix it anyway.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Zero-length path prefixes can be specified in PATH as a leading or
trailing colon or two adjacent colons. POSIX says that the use of
zero-length prefixes to refer to the current directory is a legacy
feature. Nonetheless the shells in BusyBox respect this feature,
as does 'which'.
Tab-completion of executables using PATH should support this too.
function old new delta
complete_cmd_dir_file 934 931 -3
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-3) Total: -3 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Use a NULL value of maxsz_p to indicate to xmalloc_fgets_internal()
that the caller doesn't care about the maximum size of the buffer.
This allows the default maximum size to be set once in
xmalloc_fgets_internal() instead of separately in each caller.
function old new delta
xmalloc_fgets_internal 273 287 +14
xmalloc_fgets_str 30 9 -21
xmalloc_fgetline_str 33 12 -21
xmalloc_fgets_str_len 38 10 -28
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 14/-70) Total: -56 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
The command 'nl -b n' should output no line numbers, just some
spaces as a placeholder followed by the actual file content.
Add tests for line numbering by cat and nl. The correct results
were obtained from coreutils.
function old new delta
print_numbered_lines 152 157 +5
.rodata 182456 182453 -3
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/1 up/down: 5/-3) Total: 2 bytes
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
'[-p N]' should be '[-P N]' in the trivial usage message.
Signed-off-by: Ron Yorston <rmy@pobox.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>