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
|
=*| chroot non-posix none
|
||||||
=* cksum yes none
|
=* cksum yes none
|
||||||
=* cmp yes none
|
=* cmp yes none
|
||||||
#* cols non-posix none
|
#*| cols non-posix none
|
||||||
col yes none
|
col yes none
|
||||||
=* comm yes none
|
=* comm yes none
|
||||||
=*| cp yes none (-i)
|
=*| 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
|
.Dt COLS 1
|
||||||
.Os sbase
|
.Os sbase
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -15,7 +15,8 @@ reads each
|
||||||
in sequence and writes them to stdout, in as many vertical
|
in sequence and writes them to stdout, in as many vertical
|
||||||
columns as will fit in
|
columns as will fit in
|
||||||
.Ar num
|
.Ar num
|
||||||
character columns. If no
|
character columns.
|
||||||
|
If no
|
||||||
.Ar file
|
.Ar file
|
||||||
is given,
|
is given,
|
||||||
.Nm
|
.Nm
|
||||||
|
@ -27,17 +28,15 @@ tries to figure out the width of the output
|
||||||
device. If that fails, it defaults to 65 chars.
|
device. If that fails, it defaults to 65 chars.
|
||||||
.Sh OPTIONS
|
.Sh OPTIONS
|
||||||
.Bl -tag -width Ds
|
.Bl -tag -width Ds
|
||||||
.It Fl c Ar chars
|
.It Fl c Ar num
|
||||||
Set the maximum number of character columns to use
|
Set maximum number of character columns to
|
||||||
(unless the input contains lines longer than
|
.Ar num ,
|
||||||
.Ar num
|
unless input lines exceed this limit.
|
||||||
characters).
|
|
||||||
.El
|
.El
|
||||||
.Sh ENVIRONMENT
|
.Sh ENVIRONMENT
|
||||||
.Bl -tag -width COLUMNS
|
.Bl -tag -width Ds
|
||||||
.It COLUMNS
|
.It COLUMNS
|
||||||
If this variable is set, the value is used as the
|
The width of the output device.
|
||||||
width of the output device.
|
|
||||||
.El
|
.El
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
.Nm
|
.Nm
|
||||||
|
|
70
cols.c
70
cols.c
|
@ -12,82 +12,74 @@
|
||||||
#include "utf.h"
|
#include "utf.h"
|
||||||
#include "util.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
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
eprintf("usage: %s [-c chars] [file ...]\n", argv0);
|
eprintf("usage: %s [-c num] [file ...]\n", argv0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
size_t i, l, col, len, bytes, maxlen = 0;
|
|
||||||
struct winsize w;
|
|
||||||
FILE *fp;
|
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;
|
char *p;
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'c':
|
case 'c':
|
||||||
cflag = 1;
|
cflag = 1;
|
||||||
chars = estrtonum(EARGF(usage()), 3, MIN(LLONG_MAX, SIZE_MAX));
|
chars = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
} ARGEND;
|
} ARGEND;
|
||||||
|
|
||||||
if (cflag == 0) {
|
if (!cflag) {
|
||||||
if ((p = getenv("COLUMNS")))
|
if ((p = getenv("COLUMNS")))
|
||||||
chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
|
chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX));
|
||||||
else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0)
|
else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0)
|
||||||
chars = w.ws_col;
|
chars = w.ws_col;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 0) {
|
if (!argc) {
|
||||||
getlines(stdin, &b);
|
getlines(stdin, &b);
|
||||||
} else for (; argc > 0; argc--, argv++) {
|
} else {
|
||||||
if (!(fp = fopen(argv[0], "r")))
|
for (; *argv; argc--, argv++) {
|
||||||
eprintf("fopen %s:", argv[0]);
|
if (!(fp = fopen(*argv, "r"))) {
|
||||||
|
weprintf("fopen %s:", *argv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
getlines(fp, &b);
|
getlines(fp, &b);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (l = 0; l < b.nlines; ++l) {
|
for (i = 0; i < b.nlines; i++) {
|
||||||
len = utflen(b.lines[l]);
|
len = utflen(b.lines[i]);
|
||||||
bytes = strlen(b.lines[l]);
|
bytes = strlen(b.lines[i]);
|
||||||
if (len > 0 && b.lines[l][bytes - 1] == '\n') {
|
if (len && bytes && b.lines[i][bytes - 1] == '\n') {
|
||||||
b.lines[l][bytes - 1] = '\0';
|
b.lines[i][bytes - 1] = '\0';
|
||||||
--len;
|
len--;
|
||||||
}
|
}
|
||||||
if (len > maxlen)
|
if (len > maxlen)
|
||||||
maxlen = len;
|
maxlen = len;
|
||||||
if (maxlen > (chars - 1) / 2)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
n_columns = (chars + 1) / (maxlen + 1);
|
for (cols = 1; (cols + 1) * maxlen + cols <= chars; cols++);
|
||||||
if (n_columns <= 1) {
|
rows = b.nlines / cols + (b.nlines % cols > 0);
|
||||||
for (l = 0; l < b.nlines; ++l) {
|
|
||||||
fputs(b.lines[l], stdout);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
n_rows = (b.nlines + (n_columns - 1)) / n_columns;
|
for (i = 0; i < rows; i++) {
|
||||||
for (i = 0; i < n_rows; ++i) {
|
for (j = 0; j < cols && i + j * rows < b.nlines; j++) {
|
||||||
for (l = i, col = 1; l < b.nlines; l += n_rows, ++col) {
|
len = utflen(b.lines[i + j * rows]);
|
||||||
len = utflen(b.lines[l]);
|
fputs(b.lines[i + j * rows], stdout);
|
||||||
fputs(b.lines[l], stdout);
|
if (j < cols - 1)
|
||||||
if (col < n_columns)
|
for (k = len; k < maxlen + 1; k++)
|
||||||
printf("%*s", (int)(maxlen + 1 - len), "");
|
putchar(' ');
|
||||||
}
|
}
|
||||||
fputs("\n", stdout);
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user