sbase

suckless unix tools
git clone git://git.2f30.org/sbase
Log | Files | Refs | README | LICENSE

commit f140403fcafaee00623e8310ffa1bb5311619447
parent 78187474cf6a45eeee8a5500eff665e473bc75c6
Author: FRIGN <dev@frign.de>
Date:   Sun,  8 Mar 2015 19:33:46 +0100

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.

Diffstat:
MREADME | 2+-
Mcols.1 | 19+++++++++----------
Mcols.c | 74+++++++++++++++++++++++++++++++++-----------------------------------------
3 files changed, 43 insertions(+), 52 deletions(-)

diff --git a/README b/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) diff --git a/cols.1 b/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 diff --git a/cols.c b/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]); - getlines(fp, &b); - fclose(fp); + } 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;