|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)column.c 5.6 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: #include <sys/types.h>
31: #include <sys/ioctl.h>
32: #include <stdio.h>
33: #include <string.h>
34: #include <ctype.h>
35:
36: int termwidth = 80; /* default terminal width */
37:
38: int entries; /* number of records */
39: int eval; /* exit value */
40: int maxlength; /* longest record */
41: char **list; /* array of pointers to records */
42: char *separator = "\t "; /* field separator for table option */
43:
44: main(argc, argv)
45: int argc;
46: char **argv;
47: {
48: extern char *optarg;
49: extern int errno, optind;
50: struct winsize win;
51: FILE *fp;
52: int ch, tflag, xflag;
53: char *p, *getenv();
54:
55: if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
56: if (p = getenv("COLUMNS"))
57: termwidth = atoi(p);
58: } else
59: termwidth = win.ws_col;
60:
61: xflag = 0;
62: while ((ch = getopt(argc, argv, "c:s:tx")) != EOF)
63: switch(ch) {
64: case 'c':
65: termwidth = atoi(optarg);
66: break;
67: case 's':
68: separator = optarg;
69: break;
70: case 't':
71: tflag = 1;
72: break;
73: case 'x':
74: xflag = 1;
75: break;
76: case '?':
77: default:
78: usage();
79: }
80: argc -= optind;
81: argv += optind;
82:
83: if (!*argv)
84: input(stdin);
85: else for (; *argv; ++argv)
86: if (fp = fopen(*argv, "r")) {
87: input(fp);
88: (void)fclose(fp);
89: } else {
90: (void)fprintf(stderr, "column: %s: %s\n", *argv,
91: strerror(errno));
92: eval = 1;
93: }
94:
95: if (!entries)
96: exit(eval);
97:
98: if (tflag)
99: maketbl();
100: else {
101: if (maxlength >= termwidth)
102: print();
103: if (xflag)
104: c_columnate();
105: else
106: r_columnate();
107: }
108: exit(eval);
109: }
110:
111: #define TAB 8
112: c_columnate()
113: {
114: register int chcnt, col, cnt, numcols;
115: int endcol;
116: char **lp;
117:
118: maxlength = (maxlength + TAB) & ~(TAB - 1);
119: numcols = termwidth / maxlength;
120: endcol = maxlength;
121: for (chcnt = col = 0, lp = list;; ++lp) {
122: chcnt += printf("%s", *lp);
123: if (!--entries)
124: break;
125: if (++col == numcols) {
126: chcnt = col = 0;
127: endcol = maxlength;
128: putchar('\n');
129: } else {
130: while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
131: (void)putchar('\t');
132: chcnt = cnt;
133: }
134: endcol += maxlength;
135: }
136: }
137: if (chcnt)
138: putchar('\n');
139: }
140:
141: r_columnate()
142: {
143: register int base, chcnt, cnt, col;
144: int endcol, numcols, numrows, row;
145:
146: maxlength = (maxlength + TAB) & ~(TAB - 1);
147: numcols = termwidth / maxlength;
148: numrows = entries / numcols;
149: if (entries % numcols)
150: ++numrows;
151:
152: for (row = 0; row < numrows; ++row) {
153: endcol = maxlength;
154: for (base = row, chcnt = col = 0; col < numcols; ++col) {
155: chcnt += printf("%s", list[base]);
156: if ((base += numrows) >= entries)
157: break;
158: while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) {
159: (void)putchar('\t');
160: chcnt = cnt;
161: }
162: endcol += maxlength;
163: }
164: putchar('\n');
165: }
166: }
167:
168: print()
169: {
170: register int cnt;
171: register char **lp;
172:
173: for (cnt = entries, lp = list; cnt--; ++lp)
174: (void)printf("%s\n", *lp);
175: }
176:
177: typedef struct _tbl {
178: char **list;
179: int cols, *len;
180: } TBL;
181: #define DEFCOLS 25
182:
183: maketbl()
184: {
185: register TBL *t;
186: register int coloff, cnt;
187: register char *p, **lp;
188: int *lens, maxcols;
189: TBL *tbl;
190: char **cols, *emalloc(), *realloc();
191:
192: t = tbl = (TBL *)emalloc(entries * sizeof(TBL));
193: cols = (char **)emalloc((maxcols = DEFCOLS) * sizeof(char *));
194: lens = (int *)emalloc(maxcols * sizeof(int));
195: for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
196: for (coloff = 0, p = *lp; cols[coloff] = strtok(p, separator);
197: p = NULL)
198: if (++coloff == maxcols) {
199: if (!(cols = (char **)realloc((char *)cols,
200: (u_int)maxcols + DEFCOLS * sizeof(char *))) ||
201: !(lens = (int *)realloc((char *)lens,
202: (u_int)maxcols + DEFCOLS * sizeof(int))))
203: nomem();
204: bzero((char *)lens + maxcols * sizeof(int),
205: DEFCOLS * sizeof(int));
206: maxcols += DEFCOLS;
207: }
208: t->list = (char **)emalloc(coloff * sizeof(char *));
209: t->len = (int *)emalloc(coloff * sizeof(int));
210: for (t->cols = coloff; --coloff >= 0;) {
211: t->list[coloff] = cols[coloff];
212: t->len[coloff] = strlen(cols[coloff]);
213: if (t->len[coloff] > lens[coloff])
214: lens[coloff] = t->len[coloff];
215: }
216: }
217: for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
218: for (coloff = 0; coloff < t->cols - 1; ++coloff)
219: (void)printf("%s%*s", t->list[coloff],
220: lens[coloff] - t->len[coloff] + 2, " ");
221: (void)printf("%s\n", t->list[coloff]);
222: }
223: }
224:
225: #define DEFNUM 1000
226: #define MAXLINELEN (2048 + 1)
227:
228: input(fp)
229: register FILE *fp;
230: {
231: static int maxentry;
232: register int len;
233: register char *p;
234: char buf[MAXLINELEN], *emalloc(), *realloc();
235:
236: if (!list)
237: list = (char **)emalloc((maxentry = DEFNUM) * sizeof(char *));
238: while (fgets(buf, MAXLINELEN, fp)) {
239: for (p = buf; *p && isspace(*p); ++p);
240: if (!*p)
241: continue;
242: if (!(p = index(p, '\n'))) {
243: (void)fprintf(stderr, "column: line too long.\n");
244: eval = 1;
245: continue;
246: }
247: *p = '\0';
248: len = p - buf;
249: if (maxlength < len)
250: maxlength = len;
251: if (entries == maxentry) {
252: maxentry += DEFNUM;
253: if (!(list =
254: (char **)realloc((char *)list,
255: (u_int)maxentry * sizeof(char *))))
256: nomem();
257: }
258: list[entries++] = strdup(buf);
259: }
260: }
261:
262: char *
263: emalloc(size)
264: int size;
265: {
266: char *p, *malloc();
267:
268: /* NOSTRICT */
269: if (!(p = malloc((u_int)size)))
270: nomem();
271: bzero(p, size);
272: return(p);
273: }
274:
275: nomem()
276: {
277: (void)fprintf(stderr, "column: out of memory.\n");
278: exit(1);
279: }
280:
281: usage()
282: {
283: (void)fprintf(stderr,
284: "usage: column [-tx] [-c columns] [file ...]\n");
285: exit(1);
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.