[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