Remove __P macros from src/usr.bin and src/usr.sbin.
[dragonfly.git] / usr.bin / column / column.c
CommitLineData
984263bc
MD
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 * $FreeBSD: src/usr.bin/column/column.c,v 1.4.6.2 2001/08/02 01:34:19 obrien Exp $
2d8a3be7 34 * $DragonFly: src/usr.bin/column/column.c,v 1.4 2003/11/03 19:31:29 eirikn Exp $
1de703da
MD
35 *
36 * @(#) Copyright (c) 1989, 1993, 1994 The Regents of the University of California. All rights reserved.
37 * @(#)column.c 8.4 (Berkeley) 5/4/95
984263bc
MD
38 */
39
984263bc
MD
40#include <sys/types.h>
41#include <sys/ioctl.h>
42
43#include <ctype.h>
44#include <err.h>
45#include <limits.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <string.h>
49#include <unistd.h>
50
51#define TAB 8
52
2d8a3be7
EN
53void c_columnate(void);
54void input(FILE *);
55void maketbl(void);
56void print(void);
57void r_columnate(void);
58void usage(void);
984263bc
MD
59
60int termwidth = 80; /* default terminal width */
61
62int entries; /* number of records */
63int eval; /* exit value */
64int maxlength; /* longest record */
65char **list; /* array of pointers to records */
66char *separator = "\t "; /* field separator for table option */
67
68int
16777b6b 69main(int argc, char **argv)
984263bc
MD
70{
71 struct winsize win;
72 FILE *fp;
73 int ch, tflag, xflag;
74 char *p;
75
76 if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) {
77 if ((p = getenv("COLUMNS")))
78 termwidth = atoi(p);
79 } else
80 termwidth = win.ws_col;
81
82 tflag = xflag = 0;
83 while ((ch = getopt(argc, argv, "c:s:tx")) != -1)
84 switch(ch) {
85 case 'c':
86 termwidth = atoi(optarg);
87 break;
88 case 's':
89 separator = optarg;
90 break;
91 case 't':
92 tflag = 1;
93 break;
94 case 'x':
95 xflag = 1;
96 break;
97 case '?':
98 default:
99 usage();
100 }
101 argc -= optind;
102 argv += optind;
103
104 if (!*argv)
105 input(stdin);
106 else for (; *argv; ++argv)
107 if ((fp = fopen(*argv, "r"))) {
108 input(fp);
109 (void)fclose(fp);
110 } else {
111 warn("%s", *argv);
112 eval = 1;
113 }
114
115 if (!entries)
116 exit(eval);
117
118 maxlength = (maxlength + TAB) & ~(TAB - 1);
119 if (tflag)
120 maketbl();
121 else if (maxlength >= termwidth)
122 print();
123 else if (xflag)
124 c_columnate();
125 else
126 r_columnate();
127 exit(eval);
128}
129
130void
16777b6b 131c_columnate(void)
984263bc
MD
132{
133 int chcnt, col, cnt, endcol, numcols;
134 char **lp;
135
136 numcols = termwidth / maxlength;
137 endcol = maxlength;
138 for (chcnt = col = 0, lp = list;; ++lp) {
139 chcnt += printf("%s", *lp);
140 if (!--entries)
141 break;
142 if (++col == numcols) {
143 chcnt = col = 0;
144 endcol = maxlength;
145 putchar('\n');
146 } else {
147 while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) {
148 (void)putchar('\t');
149 chcnt = cnt;
150 }
151 endcol += maxlength;
152 }
153 }
154 if (chcnt)
155 putchar('\n');
156}
157
158void
16777b6b 159r_columnate(void)
984263bc
MD
160{
161 int base, chcnt, cnt, col, endcol, numcols, numrows, row;
162
163 numcols = termwidth / maxlength;
164 numrows = entries / numcols;
165 if (entries % numcols)
166 ++numrows;
167
168 for (row = 0; row < numrows; ++row) {
169 endcol = maxlength;
170 for (base = row, chcnt = col = 0; col < numcols; ++col) {
171 chcnt += printf("%s", list[base]);
172 if ((base += numrows) >= entries)
173 break;
174 while ((cnt = ((chcnt + TAB) & ~(TAB - 1))) <= endcol) {
175 (void)putchar('\t');
176 chcnt = cnt;
177 }
178 endcol += maxlength;
179 }
180 putchar('\n');
181 }
182}
183
184void
16777b6b 185print(void)
984263bc
MD
186{
187 int cnt;
188 char **lp;
189
190 for (cnt = entries, lp = list; cnt--; ++lp)
191 (void)printf("%s\n", *lp);
192}
193
194typedef struct _tbl {
195 char **list;
196 int cols, *len;
197} TBL;
198#define DEFCOLS 25
199
200void
16777b6b 201maketbl(void)
984263bc
MD
202{
203 TBL *t;
204 int coloff, cnt;
205 char *p, **lp;
206 int *lens, maxcols;
207 TBL *tbl;
208 char **cols;
209
210 if ((t = tbl = calloc(entries, sizeof(TBL))) == NULL)
211 err(1, (char *)NULL);
212 if ((cols = calloc((maxcols = DEFCOLS), sizeof(char *))) == NULL)
213 err(1, (char *)NULL);
214 if ((lens = calloc(maxcols, sizeof(int))) == NULL)
215 err(1, (char *)NULL);
216 for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) {
217 for (coloff = 0, p = *lp; (cols[coloff] = strtok(p, separator));
218 p = NULL)
219 if (++coloff == maxcols) {
220 if (!(cols = realloc(cols, (u_int)maxcols +
221 DEFCOLS * sizeof(char *))) ||
222 !(lens = realloc(lens,
223 (u_int)maxcols + DEFCOLS * sizeof(int))))
224 err(1, NULL);
225 memset((char *)lens + maxcols * sizeof(int),
226 0, DEFCOLS * sizeof(int));
227 maxcols += DEFCOLS;
228 }
229 if ((t->list = calloc(coloff, sizeof(char *))) == NULL)
230 err(1, (char *)NULL);
231 if ((t->len = calloc(coloff, sizeof(int))) == NULL)
232 err(1, (char *)NULL);
233 for (t->cols = coloff; --coloff >= 0;) {
234 t->list[coloff] = cols[coloff];
235 t->len[coloff] = strlen(cols[coloff]);
236 if (t->len[coloff] > lens[coloff])
237 lens[coloff] = t->len[coloff];
238 }
239 }
240 for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) {
241 for (coloff = 0; coloff < t->cols - 1; ++coloff)
242 (void)printf("%s%*s", t->list[coloff],
243 lens[coloff] - t->len[coloff] + 2, " ");
244 (void)printf("%s\n", t->list[coloff]);
245 }
246}
247
248#define DEFNUM 1000
249#define MAXLINELEN (LINE_MAX + 1)
250
251void
16777b6b 252input(FILE *fp)
984263bc
MD
253{
254 static int maxentry;
255 int len;
256 char *p, buf[MAXLINELEN];
257
258 if (!list)
259 if ((list = calloc((maxentry = DEFNUM), sizeof(char *))) ==
260 NULL)
261 err(1, (char *)NULL);
262 while (fgets(buf, MAXLINELEN, fp)) {
263 for (p = buf; *p && isspace(*p); ++p);
264 if (!*p)
265 continue;
266 if (!(p = strchr(p, '\n'))) {
267 warnx("line too long");
268 eval = 1;
269 continue;
270 }
271 *p = '\0';
272 len = p - buf;
273 if (maxlength < len)
274 maxlength = len;
275 if (entries == maxentry) {
276 maxentry += DEFNUM;
277 if (!(list = realloc(list,
278 (u_int)maxentry * sizeof(char *))))
279 err(1, NULL);
280 }
281 list[entries++] = strdup(buf);
282 }
283}
284
285void
16777b6b 286usage(void)
984263bc
MD
287{
288
289 (void)fprintf(stderr,
290 "usage: column [-tx] [-c columns] [-s sep] [file ...]\n");
291 exit(1);
292}