[git commit master 1/1] conspy: code shrink

Denys Vlasenko vda.linux at googlemail.com
Wed Jun 30 05:05:31 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=fa5ea17b5f6457d888a30afeff87420b7fe0348a
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
screen_read_close                                    114     187     +73
set_cursor                                             -      53     +53
cleanup                                               93      91      -2
screen_dump                                          202     197      -5
curon                                                 34       -     -34
screen_char                                          351     308     -43
conspy_main                                         1444    1264    -180
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 1/4 up/down: 126/-264)         Total: -138 bytes

Signed-off-by: Pascal Bellard <pascal.bellard at ads-lu.com>
Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 miscutils/conspy.c |  211 +++++++++++++++++++++++++---------------------------
 1 files changed, 101 insertions(+), 110 deletions(-)

diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index 6f2f025..565922c 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -46,9 +46,9 @@ struct screen_info {
 	unsigned char lines, cols, cursor_x, cursor_y;
 };
 
-#define CHAR(x) ((uint8_t)((x)[0]))
-#define ATTR(x) ((uint8_t)((x)[1]))
-#define NEXT(x) ((x)+=2)
+#define CHAR(x) (*(uint8_t*)(x))
+#define ATTR(x) (((uint8_t*)(x))[1])
+#define NEXT(x) ((x) += 2)
 #define DATA(x) (*(uint16_t*)(x))
 
 struct globals {
@@ -56,25 +56,25 @@ struct globals {
 	int size;
 	int x, y;
 	int kbd_fd;
-	int vcsa_fd;
 	int ioerror_count;
 	int key_count;
 	int escape_count;
 	int nokeys;
 	int current;
+	int first_line_offset;
+	int last_attr;
 	// cached local tty parameters
 	unsigned width;
 	unsigned height;
 	unsigned col;
 	unsigned line;
-	smallint curoff;
-	uint8_t last_attr;
-	uint8_t force_attr_change;
+	smallint curoff; // unknown:0 cursor on:-1 cursor off:1
 	char attrbuf[sizeof("\033[0;1;5;30;40m")];
 	// remote console
 	struct screen_info remote;
 	// saved local tty terminfo
 	struct termios term_orig;
+	char vcsa_name[sizeof("/dev/vcsaNN")];
 };
 
 #define G (*ptr_to_globals)
@@ -82,7 +82,8 @@ struct globals {
 	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
 	G.attrbuf[0] = '\033'; \
 	G.attrbuf[1] = '['; \
-	G.force_attr_change = 0xff; \
+	G.width = G.height = UINT_MAX; \
+	G.last_attr--; \
 } while (0)
 
 enum {
@@ -96,24 +97,80 @@ enum {
 #define FLAG(x) (1 << FLAG_##x)
 #define BW (option_mask32 & FLAG(n))
 
+static void clrscr(void)
+{
+	// Home, clear till end of screen
+	fputs("\033[1;1H" "\033[J", stdout);
+	G.col = G.line = 0;
+}
+
+static void set_cursor(int state)
+{
+	if (G.curoff != state) {
+		G.curoff = state;
+		fputs("\033[?25", stdout);
+		bb_putchar("h?l"[1 + state]);
+	}
+}
+
+static void gotoxy(int col, int line)
+{
+	if (G.col != col || G.line != line) {
+		G.col = col;
+		G.line = line;
+		printf("\033[%u;%uH", line + 1, col + 1);
+	}
+}
+
+static void cleanup(int code)
+{
+	set_cursor(-1); // cursor on
+	tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig);
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		close(G.kbd_fd);
+	}
+	// Reset attributes
+	if (!BW)
+		fputs("\033[0m", stdout);
+	bb_putchar('\n');
+	if (code > 1)
+		kill_myself_with_sig(code);
+	exit(code);
+}
+
 static void screen_read_close(void)
 {
 	unsigned i, j;
-	char *data = G.data + G.current;
-
-	xread(G.vcsa_fd, data, G.size);
+	int vcsa_fd;
+	char *data;
+
+	// Close & re-open vcsa in case they have swapped virtual consoles
+	vcsa_fd = xopen(G.vcsa_name, O_RDONLY);
+	xread(vcsa_fd, &G.remote, 4);
+	i = G.remote.cols * 2;
+	G.first_line_offset = G.y * i;
+	i *= G.remote.lines;
+	if (G.data == NULL) {
+		G.size = i;
+		G.data = xzalloc(2 * i);
+	}
+	else if (G.size != i) {
+		cleanup(1);
+	}
+	data = G.data + G.current;
+	xread(vcsa_fd, data, G.size);
+	close(vcsa_fd);
 	for (i = 0; i < G.remote.lines; i++) {
 		for (j = 0; j < G.remote.cols; j++, NEXT(data)) {
 			unsigned x = j - G.x; // if will catch j < G.x too
 			unsigned y = i - G.y; // if will catch i < G.y too
 
 			if (CHAR(data) < ' ')
-				*data = ' '; // CHAR(data) = ' ';
+				CHAR(data) = ' ';
 			if (y >= G.height || x >= G.width)
 				DATA(data) = 0;
 		}
 	}
-	close(G.vcsa_fd);
 }
 
 static void screen_char(char *data)
@@ -121,7 +178,7 @@ static void screen_char(char *data)
 	if (!BW) {
 		uint8_t attr = ATTR(data);
 		//uint8_t attr = ATTR(data) >> 1; // for framebuffer console
-		uint8_t attr_diff = (G.last_attr ^ attr) | G.force_attr_change;
+		uint8_t attr_diff = G.last_attr ^ attr;
 
 		if (attr_diff) {
 // Attribute layout for VGA compatible text videobuffer:
@@ -153,19 +210,20 @@ static void screen_char(char *data)
 			const uint8_t bg_mask = 0x70, blink_mask = 0x80;
 			char *ptr;
 
-			ptr = G.attrbuf + 2; /* skip "ESC [" */
+			ptr = G.attrbuf + 2; // skip "ESC ["
 
 			// (G.last_attr & ~attr) has 1 only where
 			// G.last_attr has 1 but attr has 0.
 			// Here we check whether we have transition
 			// bold->non-bold or blink->non-blink:
-			if ((G.last_attr & ~attr) & (bold_mask | blink_mask)) {
+			if (G.last_attr < 0  // initial value
+			 || ((G.last_attr & ~attr) & (bold_mask | blink_mask)) != 0
+			) {
 				*ptr++ = '0'; // "reset all attrs"
 				*ptr++ = ';';
 				// must set fg & bg, maybe need to set bold or blink:
 				attr_diff = attr | ~(bold_mask | blink_mask);
 			}
-			G.force_attr_change = 0;
 			G.last_attr = attr;
 			if (attr_diff & bold_mask) {
 				*ptr++ = '1';
@@ -196,44 +254,12 @@ static void screen_char(char *data)
 	G.col++;
 }
 
-static void clrscr(void)
-{
-	// Home, clear till end of src, cursor on
-	fputs("\033[1;1H" "\033[J" "\033[?25h", stdout);
-	G.curoff = G.col = G.line = 0;
-}
-
-static void curoff(void)
-{
-	if (!G.curoff) {
-		G.curoff = 1;
-		fputs("\033[?25l", stdout);
-	}
-}
-
-static void curon(void)
-{
-	if (G.curoff) {
-		G.curoff = 0;
-		fputs("\033[?25h", stdout);
-	}
-}
-
-static void gotoxy(int col, int line)
-{
-	if (G.col != col || G.line != line) {
-		G.col = col;
-		G.line = line;
-		printf("\033[%u;%uH", line + 1, col + 1);
-	}
-}
-
 static void screen_dump(void)
 {
 	int linefeed_cnt;
 	int line, col;
 	int linecnt = G.remote.lines - G.y;
-	char *data = G.data + G.current + (2 * G.y * G.remote.cols);
+	char *data = G.data + G.current + G.first_line_offset;
 
 	linefeed_cnt = 0;
 	for (line = 0; line < linecnt && line < G.height; line++) {
@@ -263,41 +289,13 @@ static void curmove(void)
 {
 	unsigned cx = G.remote.cursor_x - G.x;
 	unsigned cy = G.remote.cursor_y - G.y;
+	int cursor = 1;
 
-	if (cx >= G.width || cy >= G.height) {
-		curoff();
-	} else {
-		curon();
+	if (cx < G.width && cy < G.height) {
 		gotoxy(cx, cy);
+		cursor = -1;
 	}
-	fflush_all();
-}
-
-static void cleanup(int code)
-{
-	curon();
-	fflush_all();
-	tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig);
-	if (ENABLE_FEATURE_CLEAN_UP) {
-		close(G.kbd_fd);
-	}
-	// Reset attributes
-	if (!BW)
-		fputs("\033[0m", stdout);
-	bb_putchar('\n');
-	if (code > 1)
-		kill_myself_with_sig(code); // does not return
-	exit(code);
-}
-
-static void get_initial_data(const char* vcsa_name)
-{
-	G.vcsa_fd = xopen(vcsa_name, O_RDONLY);
-	xread(G.vcsa_fd, &G.remote, 4);
-	G.size = G.remote.cols * G.remote.lines * 2;
-	G.width = G.height = UINT_MAX;
-	G.data = xzalloc(2 * G.size);
-	screen_read_close();
+	set_cursor(cursor);
 }
 
 static void create_cdev_if_doesnt_exist(const char* name, dev_t dev)
@@ -345,7 +343,6 @@ static NOINLINE void start_shell_in_child(const char* tty_name)
 int conspy_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int conspy_main(int argc UNUSED_PARAM, char **argv)
 {
-	char vcsa_name[sizeof("/dev/vcsaNN")];
 	char tty_name[sizeof("/dev/ttyNN")];
 #define keybuf bb_common_bufsiz1
 	struct termios termbuf;
@@ -365,7 +362,7 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 	applet_long_options = getopt_longopts;
 #endif
 	INIT_G();
-	strcpy(vcsa_name, "/dev/vcsa");
+	strcpy(G.vcsa_name, "/dev/vcsa");
 
 	opt_complementary = "x+:y+"; // numeric params
 	opts = getopt32(argv, "vcsndfx:y:", &G.x, &G.y);
@@ -373,19 +370,19 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 	ttynum = 0;
 	if (argv[0]) {
 		ttynum = xatou_range(argv[0], 0, 63);
-		sprintf(vcsa_name + sizeof("/dev/vcsa")-1, "%u", ttynum);
+		sprintf(G.vcsa_name + sizeof("/dev/vcsa")-1, "%u", ttynum);
 	}
 	sprintf(tty_name, "%s%u", "/dev/tty", ttynum);
 	if (opts & FLAG(c)) {
 		if ((opts & (FLAG(s)|FLAG(v))) != FLAG(v))
 			create_cdev_if_doesnt_exist(tty_name, makedev(4, ttynum));
-		create_cdev_if_doesnt_exist(vcsa_name, makedev(7, 128 + ttynum));
+		create_cdev_if_doesnt_exist(G.vcsa_name, makedev(7, 128 + ttynum));
 	}
 	if ((opts & FLAG(s)) && ttynum) {
 		start_shell_in_child(tty_name);
 	}
 
-	get_initial_data(vcsa_name);
+	screen_read_close();
 	if (opts & FLAG(d)) {
 		screen_dump();
 		bb_putchar('\n');
@@ -412,17 +409,11 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 		int i, j;
 		char *data, *old;
 
-		// Close & re-open vcsa in case they have
-		// swapped virtual consoles
-		G.vcsa_fd = xopen(vcsa_name, O_RDONLY);
-		xread(G.vcsa_fd, &G.remote, 4);
-		if (G.size != (G.remote.cols * G.remote.lines * 2)) {
-			cleanup(1);
-		}
+		// in the first loop G.width = G.height = 0: refresh
 		i = G.width;
 		j = G.height;
 		get_terminal_width_height(G.kbd_fd, &G.width, &G.height);
-		if ((option_mask32 & FLAG(f))) {
+		if (option_mask32 & FLAG(f)) {
 			int nx = G.remote.cursor_x - G.width + 1;
 			int ny = G.remote.cursor_y - G.height + 1;
 
@@ -454,8 +445,8 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 			screen_dump();
 		} else {
 			// For each remote line
-			old += G.y * G.remote.cols * 2;
-			data += G.y * G.remote.cols * 2;
+			old += G.first_line_offset;
+			data += G.first_line_offset;
 			for (i = G.y; i < G.remote.lines; i++) {
 				char *first = NULL; // first char which needs updating
 				char *last = last;  // last char which needs updating
@@ -463,10 +454,8 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 
 				if (iy >= G.height)
 					break;
-				old += G.x * 2;
-				data += G.x * 2;
-				for (j = G.x; j < G.remote.cols; j++, NEXT(old), NEXT(data)) {
-					unsigned jx = j - G.x;
+				for (j = 0; j < G.remote.cols; j++, NEXT(old), NEXT(data)) {
+					unsigned jx = j - G.x; // if will catch j >= G.x too
 
 					if (jx < G.width && DATA(data) != DATA(old)) {
 						last = data;
@@ -486,6 +475,7 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 		curmove();
 
 		// Wait for local user keypresses
+		fflush_all();
 		pfd.fd = G.kbd_fd;
 		pfd.events = POLLIN;
 		bytes_read = 0;
@@ -532,15 +522,16 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 			else if (kbd_mode != K_XLATE && kbd_mode != K_UNICODE)
 				G.key_count = 0; // scan code mode
 			else {
-				for (i = 0; i < G.key_count && result != -1; i++)
-					result = ioctl(handle, TIOCSTI, keybuf + i);
-				G.key_count -= i;
+				char *p = keybuf;
+				for (; G.key_count != 0 && result != -1; p++, G.key_count--) {
+					result = ioctl(handle, TIOCSTI, p);
+					// If there is an application on console which reacts
+					// to keypresses, we need to make our first sleep
+					// shorter to quickly redraw whatever it printed there.
+					poll_timeout_ms = 20;
+				}
 				if (G.key_count)
-					memmove(keybuf, keybuf + i, G.key_count);
-				// If there is an application on console which reacts
-				// to keypresses, we need to make our first sleep
-				// shorter to quickly redraw whatever it printed there.
-				poll_timeout_ms = 20;
+					memmove(keybuf, p, G.key_count);
 			}
 			// Close & re-open tty in case they have
 			// swapped virtual consoles
@@ -553,5 +544,5 @@ int conspy_main(int argc UNUSED_PARAM, char **argv)
 			else if (errno != EIO || ++G.ioerror_count > 4)
 				cleanup(1);
 		}
-	}
+	} /* while (1) */
 }
-- 
1.7.1



More information about the busybox-cvs mailing list