From: Keith Bostic Date: Thu, 14 Sep 1989 05:00:08 +0000 (-0800) Subject: add table formatting code X-Git-Tag: BSD-4_3_Reno-Snapshot-Development~5341 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/ff1bcce4ae6bfef07581e0aa7f5d30ede9ee2027 add table formatting code SCCS-vsn: usr.bin/column/column.1 5.2 SCCS-vsn: usr.bin/column/column.c 5.3 --- diff --git a/usr/src/usr.bin/column/column.1 b/usr/src/usr.bin/column/column.1 index 3a570665a3..aa507d59d1 100644 --- a/usr/src/usr.bin/column/column.1 +++ b/usr/src/usr.bin/column/column.1 @@ -13,7 +13,7 @@ .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. .\" -.\" @(#)column.1 5.1 (Berkeley) %G% +.\" @(#)column.1 5.2 (Berkeley) %G% .\" .UC 7 .TH COLUMN 1 "" @@ -21,7 +21,7 @@ .SH NAME column \- columnate lists .SH SYNOPSIS -\fBcolumn [ \fI-x\fB ] [\fI-c columns\fB ] [ \fIfile ...\fB ] +\fBcolumn [ \fI-tx\fB ] [\fI-c columns\fB ] [ \fIfile ...\fB ] .ft R .SH DESCRIPTION The @@ -35,12 +35,21 @@ Empty lines are ignored. .PP The options are as follows: .TP -.I -c +.I \-c Output is formatted for a display .I columns wide. .TP -.I -x +.I \-t +Use the whitespace in each line to determine the number of columns +it contains and create a table. +Useful for pretty-printing displays, for example: +.sp +(printf "PERM LINKS OWNER SIZE MONTH DAY HH:MM/YEAR NAME\en"; +.br +ls -l | sed 1d) | column -t +.TP +.I \-x Fill columns before filling rows. .PP .I Column @@ -51,4 +60,4 @@ exits 0 on success, >0 if an error occurred. The environmental variable COLUMNS is used to determine the size of the screen if no other information is available. .SH "SEE ALSO" -ls(1), paste(1), sort(1) +colrm(1), ls(1), paste(1), sort(1) diff --git a/usr/src/usr.bin/column/column.c b/usr/src/usr.bin/column/column.c index f603e8321a..7888ec0e5e 100644 --- a/usr/src/usr.bin/column/column.c +++ b/usr/src/usr.bin/column/column.c @@ -22,18 +22,20 @@ char copyright[] = #endif /* not lint */ #ifndef lint -static char sccsid[] = "@(#)column.c 5.2 (Berkeley) %G%"; +static char sccsid[] = "@(#)column.c 5.3 (Berkeley) %G%"; #endif /* not lint */ #include #include #include #include +#include int termwidth = 80; /* default terminal width */ char **list; /* array of pointers to records */ int entries; /* number of records */ +int eval; /* exit value */ int maxlength; /* longest record */ main(argc, argv) @@ -44,7 +46,7 @@ main(argc, argv) extern int errno, optind; struct winsize win; FILE *fp; - int ch, eval, xflag; + int ch, tflag, xflag; char *p, *getenv(); if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) { @@ -54,11 +56,14 @@ main(argc, argv) termwidth = win.ws_col; xflag = 0; - while ((ch = getopt(argc, argv, "c:x")) != EOF) + while ((ch = getopt(argc, argv, "c:tx")) != EOF) switch(ch) { case 'c': termwidth = atoi(optarg); break; + case 't': + tflag = 1; + break; case 'x': xflag = 1; break; @@ -69,7 +74,6 @@ main(argc, argv) argc -= optind; argv += optind; - eval = 0; if (!*argv) input(stdin); else for (; *argv; ++argv) @@ -85,12 +89,16 @@ main(argc, argv) if (!entries) exit(eval); - if (maxlength >= termwidth) - print(); - else if (xflag) - c_columnate(); - else - r_columnate(); + if (tflag) + maketbl(); + else { + if (maxlength >= termwidth) + print(); + if (xflag) + c_columnate(); + else + r_columnate(); + } exit(eval); } @@ -157,7 +165,55 @@ print() register char **lp; for (cnt = entries, lp = list; cnt--; ++lp) - printf("%s\n", *lp); + (void)printf("%s\n", *lp); +} + +typedef struct _tbl { + char **list; + int cols, *len; +} TBL; +#define DEFCOLS 25 + +maketbl() +{ + register TBL *t; + register int coloff, cnt; + register char *p, **lp; + int *lens, maxcols; + TBL *tbl; + char **cols, *emalloc(), *realloc(); + + t = tbl = (TBL *)emalloc(entries * sizeof(TBL)); + cols = (char **)emalloc((maxcols = DEFCOLS) * sizeof(char *)); + lens = (int *)emalloc(maxcols * sizeof(int)); + for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) { + for (coloff = 0, p = *lp; cols[coloff] = strtok(p, "\t "); + p = NULL) + if (++coloff == maxcols) { + if (!(cols = (char **)realloc((char *)cols, + (u_int)maxcols + DEFCOLS * sizeof(char *))) || + !(lens = (int *)realloc((char *)lens, + (u_int)maxcols + DEFCOLS * sizeof(int)))) + nomem(); + bzero((char *)lens + maxcols * sizeof(int), + DEFCOLS * sizeof(int)); + maxcols += DEFCOLS; + } + t->list = (char **)emalloc(coloff * sizeof(char *)); + t->len = (int *)emalloc(coloff * sizeof(int)); + for (t->cols = coloff; --coloff >= 0;) { + t->list[coloff] = cols[coloff]; + t->len[coloff] = strlen(cols[coloff]); + if (t->len[coloff] > lens[coloff]) + lens[coloff] = t->len[coloff]; + } + } + for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) { + for (coloff = 0; coloff < t->cols - 1; ++coloff) + (void)printf("%s%*s", t->list[coloff], + lens[coloff] - t->len[coloff] + 2, " "); + (void)printf("%s\n", t->list[coloff]); + } } #define DEFNUM 1000 @@ -166,35 +222,50 @@ print() input(fp) register FILE *fp; { - static u_int maxentry; + static int maxentry; register int len; register char *p; - char buf[MAXLINELEN], *malloc(), *realloc(); + char buf[MAXLINELEN], *emalloc(), *realloc(); - if (!list && - !(list = (char **)malloc((maxentry = DEFNUM) * sizeof(char *)))) - nomem(); + if (!list) + list = (char **)emalloc((maxentry = DEFNUM) * sizeof(char *)); while (fgets(buf, MAXLINELEN, fp)) { - if (buf[0] == '\n') + for (p = buf; *p && isspace(*p); ++p); + if (!*p) continue; + if (!(p = index(p, '\n'))) { + (void)fprintf(stderr, "column: line too long.\n"); + eval = 1; + continue; + } + *p = '\0'; + len = p - buf; + if (maxlength < len) + maxlength = len; if (entries == maxentry) { maxentry += DEFNUM; if (!(list = - (char **)realloc(list, maxentry * sizeof(char *)))) + (char **)realloc((char *)list, + (u_int)maxentry * sizeof(char *)))) nomem(); } - if (p = index(buf, '\n')) { - *p = '\0'; - len = p - buf; - } - else - len = strlen(buf); - if (maxlength < len) - maxlength = len; list[entries++] = strdup(buf); } } +char * +emalloc(size) + int size; +{ + char *p, *malloc(); + + /* NOSTRICT */ + if (!(p = malloc((u_int)size))) + nomem(); + bzero(p, size); + return(p); +} + nomem() { (void)fprintf(stderr, "column: out of memory.\n"); @@ -204,6 +275,6 @@ nomem() usage() { (void)fprintf(stderr, - "usage: column [-x] [-c columns] [file ...]\n"); + "usage: column [-tx] [-c columns] [file ...]\n"); exit(1); }