home *** CD-ROM | disk | FTP | other *** search
/ Chip 1995 March / CHIP3.mdf / slackwar / a / util / util-lin.2 / util-lin / util-linux-2.2 / text-utils / column.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-22  |  7.1 KB  |  312 lines

  1. /*
  2.  * Copyright (c) 1989, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char copyright[] =
  36. "@(#) Copyright (c) 1989, 1993, 1994\n\
  37.     The Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. static char sccsid[] = "@(#)column.c    8.3 (Berkeley) 4/2/94";
  42. #endif /* not lint */
  43.  
  44. #include <sys/types.h>
  45. #include <sys/ioctl.h>
  46.  
  47. #include <ctype.h>
  48. #include <err.h>
  49. #include <limits.h>
  50. #include <stdio.h>
  51. #include <stdlib.h>
  52. #include <string.h>
  53.  
  54. void  c_columnate __P((void));
  55. void *emalloc __P((int));
  56. void  input __P((FILE *));
  57. void  maketbl __P((void));
  58. void  print __P((void));
  59. void  r_columnate __P((void));
  60. void  usage __P((void));
  61.  
  62. int termwidth = 80;        /* default terminal width */
  63.  
  64. int entries;            /* number of records */
  65. int eval;            /* exit value */
  66. int maxlength;            /* longest record */
  67. char **list;            /* array of pointers to records */
  68. char *separator = "\t ";    /* field separator for table option */
  69.  
  70. int
  71. main(argc, argv)
  72.     int argc;
  73.     char **argv;
  74. {
  75.     struct winsize win;
  76.     FILE *fp;
  77.     int ch, tflag, xflag;
  78.     char *p;
  79.  
  80. #ifdef __linux__
  81.     extern int  optind;
  82.     extern char *optarg;
  83.     extern char *__progname;
  84.     __progname = argv[0];
  85. #endif
  86.  
  87.     if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
  88.         if (p = getenv("COLUMNS"))
  89.             termwidth = atoi(p);
  90.     } else
  91.         termwidth = win.ws_col;
  92.  
  93.     tflag = xflag = 0;
  94.     while ((ch = getopt(argc, argv, "c:s:tx")) != EOF)
  95.         switch(ch) {
  96.         case 'c':
  97.             termwidth = atoi(optarg);
  98.             break;
  99.         case 's':
  100.             separator = optarg;
  101.             break;
  102.         case 't':
  103.             tflag = 1;
  104.             break;
  105.         case 'x':
  106.             xflag = 1;
  107.             break;
  108.         case '?':
  109.         default:
  110.             usage();
  111.         }
  112.     argc -= optind;
  113.     argv += optind;
  114.  
  115.     if (!*argv)
  116.         input(stdin);
  117.     else for (; *argv; ++argv)
  118.         if (fp = fopen(*argv, "r")) {
  119.             input(fp);
  120.             (void)fclose(fp);
  121.         } else {
  122.             warn("%s", *argv);
  123.             eval = 1;
  124.         }
  125.  
  126.     if (!entries)
  127.         exit(eval);
  128.  
  129.     if (tflag)
  130.         maketbl();
  131.     else if (maxlength >= termwidth)
  132.         print();
  133.     else if (xflag)
  134.         c_columnate();
  135.     else
  136.         r_columnate();
  137.     exit(eval);
  138. }
  139.  
  140. #define    TAB    8
  141. void
  142. c_columnate()
  143. {
  144.     int chcnt, col, cnt, endcol, numcols;
  145.     char **lp;
  146.  
  147.     maxlength = (maxlength + TAB) & ~(TAB - 1);
  148.     numcols = termwidth / maxlength;
  149.     endcol = maxlength;
  150.     for (chcnt = col = 0, lp = list;; ++lp) {
  151.         chcnt += printf("%s", *lp);
  152.         if (!--entries)
  153.             break;
  154.         if (++col == numcols) {
  155.             chcnt = col = 0;
  156.             endcol = maxlength;
  157.             putchar('\n');
  158.         } else {
  159.             while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
  160.                 (void)putchar('\t');
  161.                 chcnt = cnt;
  162.             }
  163.             endcol += maxlength;
  164.         }
  165.     }
  166.     if (chcnt)
  167.         putchar('\n');
  168. }
  169.  
  170. void
  171. r_columnate()
  172. {
  173.     int base, chcnt, cnt, col, endcol, numcols, numrows, row;
  174.  
  175.     maxlength = (maxlength + TAB) & ~(TAB - 1);
  176.     numcols = termwidth / maxlength;
  177.     numrows = entries / numcols;
  178.     if (entries % numcols)
  179.         ++numrows;
  180.  
  181.     for (row = 0; row < numrows; ++row) {
  182.         endcol = maxlength;
  183.         for (base = row, chcnt = col = 0; col < numcols; ++col) {
  184.             chcnt += printf("%s", list[base]);
  185.             if ((base += numrows) >= entries)
  186.                 break;
  187.             while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
  188.                 (void)putchar('\t');
  189.                 chcnt = cnt;
  190.             }
  191.             endcol += maxlength;
  192.         }
  193.         putchar('\n');
  194.     }
  195. }
  196.  
  197. void
  198. print()
  199. {
  200.     int cnt;
  201.     char **lp;
  202.  
  203.     for (cnt = entries, lp = list; cnt--; ++lp)
  204.         (void)printf("%s\n", *lp);
  205. }
  206.  
  207. typedef struct _tbl {
  208.     char **list;
  209.     int cols, *len;
  210. } TBL;
  211. #define    DEFCOLS    25
  212.  
  213. void
  214. maketbl()
  215. {
  216.     TBL *t;
  217.     int coloff, cnt;
  218.     char *p, **lp;
  219.     int *lens, maxcols;
  220.     TBL *tbl;
  221.     char **cols;
  222.  
  223.     t = tbl = emalloc(entries * sizeof(TBL));
  224.     cols = emalloc((maxcols = DEFCOLS) * sizeof(char *));
  225.     lens = emalloc(maxcols * sizeof(int));
  226.     for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
  227.         for (coloff = 0, p = *lp; cols[coloff] = strtok(p, separator);
  228.             p = NULL)
  229.             if (++coloff == maxcols) {
  230.                 if (!(cols = realloc(cols, (u_int)maxcols +
  231.                     DEFCOLS * sizeof(char *))) ||
  232.                     !(lens = realloc(lens,
  233.                     (u_int)maxcols + DEFCOLS * sizeof(int))))
  234.                     err(1, NULL);
  235.                 memset((char *)lens + maxcols * sizeof(int),
  236.                     0, DEFCOLS * sizeof(int));
  237.                 maxcols += DEFCOLS;
  238.             }
  239.         t->list = emalloc(coloff * sizeof(char *));
  240.         t->len = emalloc(coloff * sizeof(int));
  241.         for (t->cols = coloff; --coloff >= 0;) {
  242.             t->list[coloff] = cols[coloff];
  243.             t->len[coloff] = strlen(cols[coloff]);
  244.             if (t->len[coloff] > lens[coloff])
  245.                 lens[coloff] = t->len[coloff];
  246.         }
  247.     }
  248.     for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
  249.         for (coloff = 0; coloff < t->cols  - 1; ++coloff)
  250.             (void)printf("%s%*s", t->list[coloff],
  251.                 lens[coloff] - t->len[coloff] + 2, " ");
  252.         (void)printf("%s\n", t->list[coloff]);
  253.     }
  254. }
  255.  
  256. #define    DEFNUM        1000
  257. #define    MAXLINELEN    (LINE_MAX + 1)
  258.  
  259. void
  260. input(fp)
  261.     FILE *fp;
  262. {
  263.     static int maxentry;
  264.     int len;
  265.     char *p, buf[MAXLINELEN];
  266.  
  267.     if (!list)
  268.         list = emalloc((maxentry = DEFNUM) * sizeof(char *));
  269.     while (fgets(buf, MAXLINELEN, fp)) {
  270.         for (p = buf; *p && isspace(*p); ++p);
  271.         if (!*p)
  272.             continue;
  273.         if (!(p = strchr(p, '\n'))) {
  274.             warnx("line too long");
  275.             eval = 1;
  276.             continue;
  277.         }
  278.         *p = '\0';
  279.         len = p - buf;
  280.         if (maxlength < len)
  281.             maxlength = len;
  282.         if (entries == maxentry) {
  283.             maxentry += DEFNUM;
  284.             if (!(list = realloc(list,
  285.                 (u_int)maxentry * sizeof(char *))))
  286.                 err(1, NULL);
  287.         }
  288.         list[entries++] = strdup(buf);
  289.     }
  290. }
  291.  
  292. void *
  293. emalloc(size)
  294.     int size;
  295. {
  296.     char *p;
  297.  
  298.     if (!(p = malloc(size)))
  299.         err(1, NULL);
  300.     memset(p, 0, size);
  301.     return (p);
  302. }
  303.  
  304. void
  305. usage()
  306. {
  307.  
  308.     (void)fprintf(stderr,
  309.         "usage: column [-tx] [-c columns] [file ...]\n");
  310.     exit(1);
  311. }
  312.