From 79c618c41193eaaa092cb977f06fc112155ba92b Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 30 Jul 2013 06:29:42 +0200 Subject: Refactor catv. Move visible() from stty to libbb. 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- '. function old new delta visible - 70 +70 do_display 431 379 -52 catv_main 306 250 -56 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/2 up/down: 70/-108) Total: -38 bytes Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- TODO | 4 ---- coreutils/catv.c | 38 ++++++++++++++++---------------------- coreutils/stty.c | 39 +++++++-------------------------------- include/libbb.h | 4 ++++ libbb/printable.c | 24 ++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 58 deletions(-) diff --git a/TODO b/TODO index 8d0850cd7..d2a085ede 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. ---- tail ./busybox tail -f foo.c~ TODO should not print fmt=header_fmt for subsequent date >> TODO; i.e. only diff --git a/coreutils/catv.c b/coreutils/catv.c index 214b4311a..18b18104e 100644 --- a/coreutils/catv.c +++ b/coreutils/catv.c @@ -25,14 +25,20 @@ int catv_main(int argc UNUSED_PARAM, char **argv) { int retval = EXIT_SUCCESS; int fd; - unsigned flags; + unsigned opts; + 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]) @@ -50,29 +56,17 @@ int catv_main(int argc UNUSED_PARAM, char **argv) res = read(fd, read_buf, COMMON_BUFSIZE); if (res < 0) retval = EXIT_FAILURE; - if (res < 1) + if (res <= 0) 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) { + putchar(c); + } else { + char buf[sizeof("M-^c")]; + visible(c, buf, flags); + fputs(buf, stdout); } - bb_putchar(c); } } if (ENABLE_FEATURE_CLEAN_UP && fd) diff --git a/coreutils/stty.c b/coreutils/stty.c index d1e74f437..378a848e7 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 ""; - - 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,12 @@ 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])); + ch = mode->c_cc[control_info[i].offset]; + if (ch == _POSIX_VDISABLE) + strcpy(G.buf, ""); + 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 83e9b5fb9..0c3734cdb 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 f6ada4904..9a423431e 100644 --- a/libbb/printable.c +++ b/libbb/printable.c @@ -32,3 +32,27 @@ void FAST_FUNC fputc_printable(int ch, FILE *file) } fputc(ch, file); } + +void FAST_FUNC visible(unsigned ch, char *buf, int flags) +{ + if (ch == '\t' && !(flags & VISIBLE_SHOW_TABS)) { + goto raw; + } + if (ch == '\n') { + if (flags & VISIBLE_ENDLINE) + *buf++ = '$'; + } else { + if (ch >= 128) { + ch -= 128; + *buf++ = 'M'; + *buf++ = '-'; + } + if (ch < 32 || ch == 127) { + *buf++ = '^'; + ch ^= 0x40; + } + } + raw: + *buf++ = ch; + *buf = '\0'; +} -- cgit v1.2.3