[git commit] vi: code shrink, optimize: do not call count_lines() unless needed
Denys Vlasenko
vda.linux at googlemail.com
Fri Feb 6 19:50:47 UTC 2026
commit: https://git.busybox.net/busybox/commit/?id=80ce9e3998dc07d8c4653daa7265df09145b9c13
branch: https://git.busybox.net/busybox/log/?h=master
function old new delta
colon 4010 3980 -30
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
editors/vi.c | 134 +++++++++++++++++++++++++++--------------------------------
1 file changed, 61 insertions(+), 73 deletions(-)
diff --git a/editors/vi.c b/editors/vi.c
index 5d736a3a5..5bc180b5d 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2601,7 +2601,7 @@ static char *get_one_address(char *p, int *result, int *valid)
// Read line addresses for a colon command. The user can enter as
// many as they like but only the last two will be used.
-static char *get_address(char *p, int *b, int *e, unsigned int *got)
+static char *get_address(char *p, int *b, int *e, unsigned *got)
{
int state = GET_ADDRESS;
int valid;
@@ -2849,16 +2849,16 @@ static void colon(char *buf)
}
not_implemented(p);
#else
-
+ char c, *q, *r;
+ char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args;
+ char *exp = NULL;
+ char *useforce;
+ int cmdlen;
+ int b, e;
// check how many addresses we got
# define GOT_ADDRESS (got & 1)
-# define GOT_RANGE ((got & 3) == 3)
-
- char c, *buf1, *q, *r;
- char *fn, cmd[MAX_INPUT_LEN], *cmdend, *args, *exp = NULL;
- int i, l, li, b, e;
- unsigned int got;
- int useforce;
+# define GOT_RANGE ((got & 3) == 3)
+ unsigned got;
// :3154 // if (-e line 3154) goto it else stay put
// :4,33w! foo // write a portion of buffer to file "foo"
@@ -2873,44 +2873,33 @@ static void colon(char *buf)
// :/xyz/ // goto the "xyz" line
// :s/find/replace/ // substitute pattern "find" with "replace"
// :!<cmd> // run <cmd> then return
- //
while (*buf == ':')
buf++; // move past leading colons
- while (isblank(*buf))
- buf++; // move past leading blanks
- if (!buf[0] || buf[0] == '"')
+ buf = skip_whitespace(buf); // move past leading blanks
+ if (!*buf || *buf == '"')
goto ret; // ignore empty lines or those starting with '"'
- li = i = 0;
- b = e = -1;
- got = 0;
- li = count_lines(text, end - 1);
fn = current_filename;
- // look for optional address(es) :. :1 :1,9 :'q,'a :%
+ // look for optional address(es) ":." ":1" ":1,9" ":'q,'a" ":%"
+ b = e = -1;
+ got = 0;
buf = get_address(buf, &b, &e, &got);
- if (buf == NULL) {
+ if (buf == NULL)
goto ret;
- }
// get the COMMAND into cmd[]
strcpy(cmd, buf);
- buf1 = cmd;
- while (!isspace(*buf1) && *buf1 != '\0') {
- buf1++;
- }
- cmdend = buf1;
+ cmdend = skip_non_whitespace(cmd);
// get any ARGuments
- while (isblank(*buf1))
- buf1++;
- args = buf1;
+ args = skip_whitespace(cmdend);
+//NB: arguments can be accessed in buf[] as well, there is no need to copy them into cmd[]?
*cmdend = '\0';
- useforce = FALSE;
- if (cmdend > cmd && cmdend[-1] == '!') {
- useforce = TRUE;
- cmdend[-1] = '\0'; // get rid of !
- }
+ useforce = last_char_is(cmd, '!');
+ if (useforce && useforce > cmd)
+ *useforce = '\0'; // "CMD!" -> "CMD" (unless single "!")
+
// assume the command will want a range, certain commands
// (read, substitute) need to adjust these assumptions
if (!GOT_ADDRESS) {
@@ -2918,7 +2907,10 @@ static void colon(char *buf)
r = end - 1;
} else {
// at least one addr was given, get its details
- if (e < 0 || e > li) {
+ int lines;
+ if (e < 0
+ || e > (lines = count_lines(text, end - 1))
+ ) {
status_line_bold("Invalid range");
goto ret;
}
@@ -2928,31 +2920,28 @@ static void colon(char *buf)
// number of the single line the user wants.
// Reset the end pointer to the end of that line.
r = end_line(q);
- li = 1;
} else {
// we were given two addrs. change the
// start pointer to the addr given by user.
- if (b < 0 || b > li || b > e) {
+ if (b < 0 || b > lines || b > e) {
status_line_bold("Invalid range");
goto ret;
}
q = find_line(b); // what line is #b
r = end_line(r);
- li = e - b + 1;
}
}
// ------------ now look for the command ------------
- i = strlen(cmd);
- if (i == 0) { // :123CR goto line #123
+ cmdlen = strlen(cmd);
+ if (cmdlen == 0) { // ":123<enter>" - goto line #123
if (e >= 0) {
dot = find_line(e); // what line is #e
dot_skip_over_ws();
}
}
# if ENABLE_FEATURE_ALLOW_EXEC
- else if (cmd[0] == '!') { // run a cmd
+ else if (cmd[0] == '!') { // ":!CMD" - run shell CMD
int retcode;
- // :!ls run the <cmd>
if (GOT_ADDRESS) {
status_line_bold("Range not allowed");
goto ret;
@@ -2974,14 +2963,14 @@ static void colon(char *buf)
e = count_lines(text, dot);
}
status_line("%d", e);
- } else if (strncmp(cmd, "delete", i) == 0) { // delete lines
+ } else if (strncmp(cmd, "delete", cmdlen) == 0) { // delete lines
if (!GOT_ADDRESS) { // no addr given- use defaults
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
}
dot = yank_delete(q, r, WHOLE, YANKDEL, ALLOW_UNDO); // save, then delete lines
dot_skip_over_ws();
- } else if (strncmp(cmd, "edit", i) == 0) { // Edit a file
+ } else if (strncmp(cmd, "edit", cmdlen) == 0) { // Edit a file
int size;
// don't edit, if the current file has been modified
@@ -3012,8 +3001,6 @@ static void colon(char *buf)
reg[YDreg] = NULL;
}
# endif
- // how many lines in text[]?
- li = count_lines(text, end - 1);
status_line("'%s'%s"
IF_FEATURE_VI_READONLY("%s")
" %uL, %uC",
@@ -3022,9 +3009,10 @@ static void colon(char *buf)
IF_FEATURE_VI_READONLY(
((readonly_mode) ? " [Readonly]" : ""),
)
- li, (int)(end - text)
+ count_lines(text, end - 1),
+ (int)(end - text)
);
- } else if (strncmp(cmd, "file", i) == 0) { // what File is this
+ } else if (strncmp(cmd, "file", cmdlen) == 0) { // what File is this
if (e >= 0) {
status_line_bold("No address allowed on this command");
goto ret;
@@ -3039,14 +3027,14 @@ static void colon(char *buf)
// user wants file status info
last_status_cksum = 0; // force status update
}
- } else if (strncmp(cmd, "features", i) == 0) { // what features are available
+ } else if (strncmp(cmd, "features", cmdlen) == 0) { // what features are available
// print out values of all features
go_bottom_and_clear_to_eol();
cookmode();
show_help();
rawmode();
Hit_Return();
- } else if (strncmp(cmd, "list", i) == 0) { // literal print line
+ } else if (strncmp(cmd, "list", cmdlen) == 0) { // literal print line
if (!GOT_ADDRESS) { // no addr given- use defaults
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
@@ -3076,9 +3064,9 @@ static void colon(char *buf)
standout_end();
}
Hit_Return();
- } else if (strncmp(cmd, "quit", i) == 0 // quit
- || strncmp(cmd, "next", i) == 0 // edit next file
- || strncmp(cmd, "prev", i) == 0 // edit previous file
+ } else if (strncmp(cmd, "quit", cmdlen) == 0 // quit
+ || strncmp(cmd, "next", cmdlen) == 0 // edit next file
+ || strncmp(cmd, "prev", cmdlen) == 0 // edit previous file
) {
int n;
if (useforce) {
@@ -3113,7 +3101,7 @@ static void colon(char *buf)
optind -= 2;
}
editing = 0;
- } else if (strncmp(cmd, "read", i) == 0) { // read file into text[]
+ } else if (strncmp(cmd, "read", cmdlen) == 0) { // read file into text[]
int size, num;
if (args[0]) {
@@ -3145,17 +3133,16 @@ static void colon(char *buf)
}
if (size < 0)
goto ret; // nothing was inserted
- // how many lines in text[]?
- li = count_lines(q, q + size - 1);
status_line("'%s'"
IF_FEATURE_VI_READONLY("%s")
" %uL, %uC",
fn,
IF_FEATURE_VI_READONLY((readonly_mode ? " [Readonly]" : ""),)
- li, size
+ count_lines(q, q + size - 1),
+ size
);
dot = find_line(num);
- } else if (strncmp(cmd, "rewind", i) == 0) { // rewind cmd line args
+ } else if (strncmp(cmd, "rewind", cmdlen) == 0) { // rewind cmd line args
if (modified_count && !useforce) {
status_line_bold("No write since last change (:%s! overrides)", cmd);
} else {
@@ -3164,7 +3151,7 @@ static void colon(char *buf)
editing = 0;
}
# if ENABLE_FEATURE_VI_SET
- } else if (strncmp(cmd, "set", i) == 0) { // set or clear features
+ } else if (strncmp(cmd, "set", cmdlen) == 0) { // set or clear features
# if ENABLE_FEATURE_VI_SETOPTS
char *argp, *argn, oldch;
# endif
@@ -3192,7 +3179,7 @@ static void colon(char *buf)
# if ENABLE_FEATURE_VI_SETOPTS
argp = args;
while (*argp) {
- i = 0;
+ int i = 0;
if (argp[0] == 'n' && argp[1] == 'o') // "noXXX"
i = 2;
argn = skip_non_whitespace(argp);
@@ -3209,6 +3196,7 @@ static void colon(char *buf)
} else if (cmd[0] == 's') { // substitute a pattern with a replacement pattern
char *F, *R, *flags;
size_t len_F, len_R;
+ int i;
int gflag = 0; // global replace flag
int subs = 0; // number of substitutions
# if ENABLE_FEATURE_VI_VERBOSE_STATUS
@@ -3272,7 +3260,6 @@ static void colon(char *buf)
# else
len_R = strlen(R);
# endif
-
for (i = b; i <= e; i++) { // so, :20,23 s \0 find \0 replace \0
char *ls = q; // orig line start
char *found;
@@ -3344,14 +3331,14 @@ static void colon(char *buf)
regfree(&preg);
# endif
# endif /* FEATURE_VI_SEARCH */
- } else if (strncmp(cmd, "version", i) == 0) { // show software version
+ } else if (strncmp(cmd, "version", cmdlen) == 0) { // show software version
status_line(BB_VER);
- } else if (strncmp(cmd, "write", i) == 0 // write text to file
+ } else if (strncmp(cmd, "write", cmdlen) == 0 // write text to file
|| strcmp(cmd, "wq") == 0
|| strcmp(cmd, "wn") == 0
|| (cmd[0] == 'x' && !cmd[1])
) {
- int size;
+ int size, l;
//int forced = FALSE;
// is there a file name to write to?
@@ -3361,8 +3348,10 @@ static void colon(char *buf)
exp = expand_args(args);
if (exp == NULL)
goto ret;
- if (!useforce && (fn == NULL || strcmp(fn, exp) != 0) &&
- stat(exp, &statbuf) == 0) {
+ if (!useforce
+ && (fn == NULL || strcmp(fn, exp) != 0)
+ && stat(exp, &statbuf) == 0
+ ) {
status_line_bold("File exists (:w! overrides)");
goto ret;
}
@@ -3381,12 +3370,10 @@ static void colon(char *buf)
// system(syscmd);
// forced = TRUE;
//}
+ size = l = 0;
if (modified_count != 0 || cmd[0] != 'x') {
size = r - q + 1;
l = file_write(fn, q, r);
- } else {
- size = 0;
- l = 0;
}
//if (useforce && forced) {
// chmod u-w
@@ -3399,8 +3386,8 @@ static void colon(char *buf)
status_line_bold_errno(fn);
} else {
// how many lines written
- li = count_lines(q, q + l - 1);
- status_line("'%s' %uL, %uC", fn, li, l);
+ int lines = count_lines(q, q + l - 1);
+ status_line("'%s' %uL, %uC", fn, lines, l);
if (l == size) {
if (q == text && q + l == end) {
modified_count = 0;
@@ -3425,15 +3412,16 @@ static void colon(char *buf)
}
}
# if ENABLE_FEATURE_VI_YANKMARK
- } else if (strncmp(cmd, "yank", i) == 0) { // yank lines
+ } else if (strncmp(cmd, "yank", cmdlen) == 0) { // yank lines
+ int lines;
if (!GOT_ADDRESS) { // no addr given- use defaults
q = begin_line(dot); // assume .,. for the range
r = end_line(dot);
}
text_yank(q, r, YDreg, WHOLE);
- li = count_lines(q, r);
+ lines = count_lines(q, r);
status_line("Yank %d lines (%d chars) into [%c]",
- li, strlen(reg[YDreg]), what_reg());
+ lines, strlen(reg[YDreg]), what_reg());
# endif
} else {
// cmd unknown
More information about the busybox-cvs
mailing list