Audit cols(1)
1) Refactor manpage. 2) De-globalize local values. 3) update usage(). 4) sort local variable declarations. 5) fix wrong argument in strtonum (3 -> 1). 6) argc-argv style, boolean style. 7) check bytes > 0 before accessing b.lines[i][bytes - 1] relying on len only makes sense but let's not push it. 7) don't break on maxlen > (chars - 1) / 2. This didn't even make sense. 8) _correctly_ calculate cols and rows in a readable way. 9) Rewrite loop over rows and cols in a readable way and using putchar in a loop instead of printf-magic or fputs where not necessary.
This commit is contained in:
parent
78187474cf
commit
f140403fca
2
README
2
README
|
@ -18,7 +18,7 @@ The following tools are implemented ('*' == finished, '#' == UTF-8 support,
|
|||
=*| chroot non-posix none
|
||||
=* cksum yes none
|
||||
=* cmp yes none
|
||||
#* cols non-posix none
|
||||
#*| cols non-posix none
|
||||
col yes none
|
||||
=* comm yes none
|
||||
=*| cp yes none (-i)
|
||||
|
|
19
cols.1
19
cols.1
|
@ -1,4 +1,4 @@
|
|||
.Dd February 19, 2015
|
||||
.Dd March 8, 2015
|
||||
.Dt COLS 1
|
||||
.Os sbase
|
||||
.Sh NAME
|
||||
|
@ -15,7 +15,8 @@ reads each
|
|||
in sequence and writes them to stdout, in as many vertical
|
||||
columns as will fit in
|
||||
.Ar num
|
||||
character columns. If no
|
||||
character columns.
|
||||
If no
|
||||
.Ar file
|
||||
is given,
|
||||
.Nm
|
||||
|
@ -27,17 +28,15 @@ tries to figure out the width of the output
|
|||
device. If that fails, it defaults to 65 chars.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width Ds
|
||||
.It Fl c Ar chars
|
||||
Set the maximum number of character columns to use
|
||||
(unless the input contains lines longer than
|
||||
.Ar num
|
||||
characters).
|
||||
.It Fl c Ar num
|
||||
Set maximum number of character columns to
|
||||
.Ar num ,
|
||||
unless input lines exceed this limit.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width COLUMNS
|
||||
.Bl -tag -width Ds
|
||||
.It COLUMNS
|
||||
If this variable is set, the value is used as the
|
||||
width of the output device.
|
||||
The width of the output device.
|
||||
.El
|
||||
.Sh HISTORY
|
||||
.Nm
|
||||
|
|
70
cols.c
70
cols.c
|
@ -12,82 +12,74 @@
|
|||
#include "utf.h"
|
||||
#include "util.h"
|
||||
|
||||
static size_t chars = 65;
|
||||
static int cflag;
|
||||
static struct linebuf b = EMPTY_LINEBUF;
|
||||
|
||||
static size_t n_columns;
|
||||
static size_t n_rows;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
eprintf("usage: %s [-c chars] [file ...]\n", argv0);
|
||||
eprintf("usage: %s [-c num] [file ...]\n", argv0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
size_t i, l, col, len, bytes, maxlen = 0;
|
||||
struct winsize w;
|
||||
FILE *fp;
|
||||
struct winsize w;
|
||||
struct linebuf b = EMPTY_LINEBUF;
|
||||
size_t chars = 65, maxlen = 0, i, j, k, len, bytes, cols, rows;
|
||||
int cflag = 0;
|
||||
char *p;
|
||||
|
||||
ARGBEGIN {
|
||||
case 'c':
|
||||
cflag = 1;
|
||||
chars = estrtonum(EARGF(usage()), 3, MIN(LLONG_MAX, SIZE_MAX));
|
||||
chars = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX));
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
} ARGEND;
|
||||
|
||||
if (cflag == 0) {
|
||||
if (!cflag) {
|
||||
if ((p = getenv("COLUMNS")))
|
||||
chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
|
||||
else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0)
|
||||
chars = w.ws_col;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
if (!argc) {
|
||||
getlines(stdin, &b);
|
||||
} else for (; argc > 0; argc--, argv++) {
|
||||
if (!(fp = fopen(argv[0], "r")))
|
||||
eprintf("fopen %s:", argv[0]);
|
||||
} else {
|
||||
for (; *argv; argc--, argv++) {
|
||||
if (!(fp = fopen(*argv, "r"))) {
|
||||
weprintf("fopen %s:", *argv);
|
||||
continue;
|
||||
}
|
||||
getlines(fp, &b);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
for (l = 0; l < b.nlines; ++l) {
|
||||
len = utflen(b.lines[l]);
|
||||
bytes = strlen(b.lines[l]);
|
||||
if (len > 0 && b.lines[l][bytes - 1] == '\n') {
|
||||
b.lines[l][bytes - 1] = '\0';
|
||||
--len;
|
||||
for (i = 0; i < b.nlines; i++) {
|
||||
len = utflen(b.lines[i]);
|
||||
bytes = strlen(b.lines[i]);
|
||||
if (len && bytes && b.lines[i][bytes - 1] == '\n') {
|
||||
b.lines[i][bytes - 1] = '\0';
|
||||
len--;
|
||||
}
|
||||
if (len > maxlen)
|
||||
maxlen = len;
|
||||
if (maxlen > (chars - 1) / 2)
|
||||
break;
|
||||
}
|
||||
|
||||
n_columns = (chars + 1) / (maxlen + 1);
|
||||
if (n_columns <= 1) {
|
||||
for (l = 0; l < b.nlines; ++l) {
|
||||
fputs(b.lines[l], stdout);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
for (cols = 1; (cols + 1) * maxlen + cols <= chars; cols++);
|
||||
rows = b.nlines / cols + (b.nlines % cols > 0);
|
||||
|
||||
n_rows = (b.nlines + (n_columns - 1)) / n_columns;
|
||||
for (i = 0; i < n_rows; ++i) {
|
||||
for (l = i, col = 1; l < b.nlines; l += n_rows, ++col) {
|
||||
len = utflen(b.lines[l]);
|
||||
fputs(b.lines[l], stdout);
|
||||
if (col < n_columns)
|
||||
printf("%*s", (int)(maxlen + 1 - len), "");
|
||||
for (i = 0; i < rows; i++) {
|
||||
for (j = 0; j < cols && i + j * rows < b.nlines; j++) {
|
||||
len = utflen(b.lines[i + j * rows]);
|
||||
fputs(b.lines[i + j * rows], stdout);
|
||||
if (j < cols - 1)
|
||||
for (k = len; k < maxlen + 1; k++)
|
||||
putchar(' ');
|
||||
}
|
||||
fputs("\n", stdout);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user