add table formatting code
authorKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Thu, 14 Sep 1989 05:00:08 +0000 (21:00 -0800)
committerKeith Bostic <bostic@ucbvax.Berkeley.EDU>
Thu, 14 Sep 1989 05:00:08 +0000 (21:00 -0800)
SCCS-vsn: usr.bin/column/column.1 5.2
SCCS-vsn: usr.bin/column/column.c 5.3

usr/src/usr.bin/column/column.1
usr/src/usr.bin/column/column.c

index 3a57066..aa507d5 100644 (file)
@@ -13,7 +13,7 @@
 .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 .\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 .\"
 .\" 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 ""
 .\"
 .UC 7
 .TH COLUMN 1 ""
@@ -21,7 +21,7 @@
 .SH NAME
 column \- columnate lists
 .SH SYNOPSIS
 .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
 .ft R
 .SH DESCRIPTION
 The
@@ -35,12 +35,21 @@ Empty lines are ignored.
 .PP
 The options are as follows:
 .TP
 .PP
 The options are as follows:
 .TP
-.I -c
+.I \-c
 Output is formatted for a display
 .I columns
 wide.
 .TP
 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
 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"
 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)
index f603e83..7888ec0 100644 (file)
@@ -22,18 +22,20 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #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 <sys/types.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
 #include <strings.h>
 #endif /* not lint */
 
 #include <sys/types.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
 #include <strings.h>
+#include <ctype.h>
 
 int termwidth = 80;            /* default terminal width */
 
 char **list;                   /* array of pointers to records */
 int entries;                   /* number of records */
 
 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)
 int maxlength;                 /* longest record */
 
 main(argc, argv)
@@ -44,7 +46,7 @@ main(argc, argv)
        extern int errno, optind;
        struct winsize win;
        FILE *fp;
        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) {
        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;
                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;
                switch(ch) {
                case 'c':
                        termwidth = atoi(optarg);
                        break;
+               case 't':
+                       tflag = 1;
+                       break;
                case 'x':
                        xflag = 1;
                        break;
                case 'x':
                        xflag = 1;
                        break;
@@ -69,7 +74,6 @@ main(argc, argv)
        argc -= optind;
        argv += optind;
 
        argc -= optind;
        argv += optind;
 
-       eval = 0;
        if (!*argv)
                input(stdin);
        else for (; *argv; ++argv)
        if (!*argv)
                input(stdin);
        else for (; *argv; ++argv)
@@ -85,12 +89,16 @@ main(argc, argv)
        if (!entries)
                exit(eval);
 
        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);
 }
 
        exit(eval);
 }
 
@@ -157,7 +165,55 @@ print()
        register char **lp;
 
        for (cnt = entries, lp = list; cnt--; ++lp)
        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
 }
 
 #define        DEFNUM          1000
@@ -166,35 +222,50 @@ print()
 input(fp)
        register FILE *fp;
 {
 input(fp)
        register FILE *fp;
 {
-       static u_int maxentry;
+       static int maxentry;
        register int len;
        register char *p;
        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)) {
        while (fgets(buf, MAXLINELEN, fp)) {
-               if (buf[0] == '\n')
+               for (p = buf; *p && isspace(*p); ++p);
+               if (!*p)
                        continue;
                        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 =
                if (entries == maxentry) {
                        maxentry += DEFNUM;
                        if (!(list =
-                           (char **)realloc(list, maxentry * sizeof(char *))))
+                           (char **)realloc((char *)list,
+                           (u_int)maxentry * sizeof(char *))))
                                nomem();
                }
                                nomem();
                }
-               if (p = index(buf, '\n')) {
-                       *p = '\0';
-                       len = p - buf;
-               }
-               else
-                       len = strlen(buf);
-               if (maxlength < len)
-                       maxlength = len;
                list[entries++] = strdup(buf);
        }
 }
 
                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");
 nomem()
 {
        (void)fprintf(stderr, "column: out of memory.\n");
@@ -204,6 +275,6 @@ nomem()
 usage()
 {
        (void)fprintf(stderr,
 usage()
 {
        (void)fprintf(stderr,
-           "usage: column [-x] [-c columns] [file ...]\n");
+           "usage: column [-tx] [-c columns] [file ...]\n");
        exit(1);
 }
        exit(1);
 }