summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBartosz Golaszewski <bartekgola@gmail.com>2013-07-30 06:29:42 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2013-07-30 06:29:42 +0200
commit79c618c41193eaaa092cb977f06fc112155ba92b (patch)
tree369938db46d4691ebbcc476386c7dafdac827887
parentd0bc708cb52693b9ed1dab495e5f99fb8e1122f7 (diff)
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 <bartekgola@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--TODO4
-rw-r--r--coreutils/catv.c38
-rw-r--r--coreutils/stty.c39
-rw-r--r--include/libbb.h4
-rw-r--r--libbb/printable.c24
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 "<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,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, "<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 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';
+}