[PATCH] Refactor catv. Move visible from stty to libbb.

Bartosz Golaszewski bartekgola at gmail.com
Tue Jul 9 18:22:02 UTC 2013


Fixes the following TODO:

  stty's visible() function and catv's guts are identical. Merge them into
  an appropriate libbb function.

Also makes catv behave exactly like coreutils' cat -v e.g. it'll print 'M-^I'
instead of 'M-   '.

Signed-off-by: Bartosz Golaszewski <bartekgola at gmail.com>
---
 TODO              |    4 ----
 coreutils/catv.c  |   36 +++++++++++++++---------------------
 coreutils/stty.c  |   38 ++++++--------------------------------
 include/libbb.h   |    4 ++++
 libbb/printable.c |   39 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 64 insertions(+), 57 deletions(-)

diff --git a/TODO b/TODO
index 4436469..100ad93 100644
--- a/TODO
+++ b/TODO
@@ -128,10 +128,6 @@ patch
   And while we're at it, a new patch filename quoting format is apparently
   coming soon:  http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
 ---
-stty / catv
-  stty's visible() function and catv's guts are identical. Merge them into
-  an appropriate libbb function.
----
 struct suffix_mult
   Several duplicate users of: grep -r "1024\*1024" * -B2 -A1
   Merge to a single size_suffixes[] in libbb.
diff --git a/coreutils/catv.c b/coreutils/catv.c
index 214b431..dae7212 100644
--- a/coreutils/catv.c
+++ b/coreutils/catv.c
@@ -25,14 +25,21 @@ int catv_main(int argc UNUSED_PARAM, char **argv)
 {
 	int retval = EXIT_SUCCESS;
 	int fd;
-	unsigned flags;
+	unsigned opts;
+	char buf[10];
+	int flags = 0;
 
-	flags = getopt32(argv, "etv");
+	opts = getopt32(argv, "etv");
 #define CATV_OPT_e (1<<0)
 #define CATV_OPT_t (1<<1)
 #define CATV_OPT_v (1<<2)
-	flags ^= CATV_OPT_v;
 	argv += optind;
+	if (opts & (CATV_OPT_e | CATV_OPT_t))
+		opts &= ~CATV_OPT_v;
+	if (opts & CATV_OPT_e)
+		flags ^= VISIBLE_ENDLINE;
+	if (opts & CATV_OPT_t)
+		flags ^= VISIBLE_SHOW_TABS;
 
 	/* Read from stdin if there's nothing else to do. */
 	if (!argv[0])
@@ -54,25 +61,12 @@ int catv_main(int argc UNUSED_PARAM, char **argv)
 				break;
 			for (i = 0; i < res; i++) {
 				unsigned char c = read_buf[i];
-
-				if (c > 126 && (flags & CATV_OPT_v)) {
-					if (c == 127) {
-						printf("^?");
-						continue;
-					}
-					printf("M-");
-					c -= 128;
-				}
-				if (c < 32) {
-					if (c == 10) {
-						if (flags & CATV_OPT_e)
-							bb_putchar('$');
-					} else if (flags & (c==9 ? CATV_OPT_t : CATV_OPT_v)) {
-						printf("^%c", c+'@');
-						continue;
-					}
+				if (opts & CATV_OPT_v) {
+					bb_putchar(c);
+				} else {
+					visible(c, buf, flags);
+					printf("%s", buf);
 				}
-				bb_putchar(c);
 			}
 		}
 		if (ENABLE_FEATURE_CLEAN_UP && fd)
diff --git a/coreutils/stty.c b/coreutils/stty.c
index d1e74f4..3018fb0 100644
--- a/coreutils/stty.c
+++ b/coreutils/stty.c
@@ -781,36 +781,6 @@ struct globals {
 	G.max_col = 80; \
 } while (0)
 
-
-/* Return a string that is the printable representation of character CH */
-/* Adapted from 'cat' by Torbjorn Granlund */
-static const char *visible(unsigned ch)
-{
-	char *bpout = G.buf;
-
-	if (ch == _POSIX_VDISABLE)
-		return "<undef>";
-
-	if (ch >= 128) {
-		ch -= 128;
-		*bpout++ = 'M';
-		*bpout++ = '-';
-	}
-
-	if (ch < 32) {
-		*bpout++ = '^';
-		*bpout++ = ch + 64;
-	} else if (ch < 127) {
-		*bpout++ = ch;
-	} else {
-		*bpout++ = '^';
-		*bpout++ = '?';
-	}
-
-	*bpout = '\0';
-	return G.buf;
-}
-
 static void set_speed_or_die(enum speed_setting type, const char *arg,
 					struct termios *mode)
 {
@@ -1038,6 +1008,7 @@ static void do_display(const struct termios *mode, int all)
 #endif
 
 	for (i = 0; i != CIDX_min; ++i) {
+	    char ch;
 		/* If swtch is the same as susp, don't print both */
 #if VSWTCH == VSUSP
 		if (i == CIDX_swtch)
@@ -1051,8 +1022,11 @@ static void do_display(const struct termios *mode, int all)
 			continue;
 		}
 #endif
-		wrapf("%s = %s;", nth_string(control_name, i),
-				visible(mode->c_cc[control_info[i].offset]));
+		if ((ch = mode->c_cc[control_info[i].offset]) == _POSIX_VDISABLE)
+		    snprintf(G.buf, sizeof(G.buf), "<undef>");
+		else
+		    visible(ch, G.buf, 0);
+		wrapf("%s = %s;", nth_string(control_name, i), G.buf);
 	}
 #if VEOF == VMIN
 	if ((mode->c_lflag & ICANON) == 0)
diff --git a/include/libbb.h b/include/libbb.h
index b5d1156..57680c7 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -678,6 +678,10 @@ const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str);
  * else it is printed as-is (except for ch = 0x9b) */
 enum { PRINTABLE_META = 0x100 };
 void fputc_printable(int ch, FILE *file) FAST_FUNC;
+/* Return a string that is the printable representation of character ch.
+ * Buffer must hold at least four characters. */
+enum { VISIBLE_SHOW_TABS = 1, VISIBLE_ENDLINE = 2 };
+void visible(unsigned ch, char *buf, int flags) FAST_FUNC;
 
 /* dmalloc will redefine these to it's own implementation. It is safe
  * to have the prototypes here unconditionally.  */
diff --git a/libbb/printable.c b/libbb/printable.c
index f6ada49..52ac855 100644
--- a/libbb/printable.c
+++ b/libbb/printable.c
@@ -32,3 +32,42 @@ void FAST_FUNC fputc_printable(int ch, FILE *file)
 	}
 	fputc(ch, file);
 }
+
+void FAST_FUNC visible(unsigned ch, char *buf, int flags)
+{
+	if (ch == 9) {
+		if (flags & VISIBLE_SHOW_TABS) {
+			*buf++ = '^';
+			*buf++ = 'I';
+		} else {
+			*buf++ = ch;
+		}
+	} else
+	if (ch == 10) {
+		if (flags & VISIBLE_ENDLINE) {
+			*buf++ = '$';
+			*buf++ = '\n';
+		} else {
+			*buf++ = ch;
+		}
+	} else {
+		if (ch >= 128) {
+			ch -= 128;
+			*buf++ = 'M';
+			*buf++ = '-';
+		}
+
+		if (ch < 32) {
+			*buf++ = '^';
+			*buf++ = ch + 64;
+		} else
+		if (ch < 127) {
+			*buf++ = ch;
+		} else {
+			*buf++ = '^';
+			*buf++ = '?';
+		}
+	}
+
+	*buf = '\0';
+}
-- 
1.7.10.4



More information about the busybox mailing list