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>
This commit is contained in:
Bartosz Golaszewski 2013-07-30 06:29:42 +02:00 committed by Denys Vlasenko
parent d0bc708cb5
commit 79c618c411
5 changed files with 51 additions and 58 deletions

4
TODO
View File

@ -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

View File

@ -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;
if (opts & CATV_OPT_v) {
putchar(c);
} else {
char buf[sizeof("M-^c")];
visible(c, buf, flags);
fputs(buf, stdout);
}
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;
}
}
bb_putchar(c);
}
}
if (ENABLE_FEATURE_CLEAN_UP && fd)

View File

@ -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)

View File

@ -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. */

View File

@ -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';
}