xref: /freebsd/usr.bin/rs/rs.cc (revision 42d10b1b56f2f7739081487814f90a22b81792ee)
1*42d10b1bSJohn Baldwin /*-
2*42d10b1bSJohn Baldwin  * SPDX-License-Identifier: BSD-3-Clause
3*42d10b1bSJohn Baldwin  *
4*42d10b1bSJohn Baldwin  * Copyright (c) 1993
5*42d10b1bSJohn Baldwin  *	The Regents of the University of California.  All rights reserved.
6*42d10b1bSJohn Baldwin  *
7*42d10b1bSJohn Baldwin  * Redistribution and use in source and binary forms, with or without
8*42d10b1bSJohn Baldwin  * modification, are permitted provided that the following conditions
9*42d10b1bSJohn Baldwin  * are met:
10*42d10b1bSJohn Baldwin  * 1. Redistributions of source code must retain the above copyright
11*42d10b1bSJohn Baldwin  *    notice, this list of conditions and the following disclaimer.
12*42d10b1bSJohn Baldwin  * 2. Redistributions in binary form must reproduce the above copyright
13*42d10b1bSJohn Baldwin  *    notice, this list of conditions and the following disclaimer in the
14*42d10b1bSJohn Baldwin  *    documentation and/or other materials provided with the distribution.
15*42d10b1bSJohn Baldwin  * 3. Neither the name of the University nor the names of its contributors
16*42d10b1bSJohn Baldwin  *    may be used to endorse or promote products derived from this software
17*42d10b1bSJohn Baldwin  *    without specific prior written permission.
18*42d10b1bSJohn Baldwin  *
19*42d10b1bSJohn Baldwin  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*42d10b1bSJohn Baldwin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*42d10b1bSJohn Baldwin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*42d10b1bSJohn Baldwin  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*42d10b1bSJohn Baldwin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*42d10b1bSJohn Baldwin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*42d10b1bSJohn Baldwin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*42d10b1bSJohn Baldwin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*42d10b1bSJohn Baldwin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*42d10b1bSJohn Baldwin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*42d10b1bSJohn Baldwin  * SUCH DAMAGE.
30*42d10b1bSJohn Baldwin  */
31*42d10b1bSJohn Baldwin 
32*42d10b1bSJohn Baldwin /*
33*42d10b1bSJohn Baldwin  *	rs - reshape a data array
34*42d10b1bSJohn Baldwin  *	Author:  John Kunze, Office of Comp. Affairs, UCB
35*42d10b1bSJohn Baldwin  *		BEWARE: lots of unfinished edges
36*42d10b1bSJohn Baldwin  */
37*42d10b1bSJohn Baldwin 
38*42d10b1bSJohn Baldwin #include <err.h>
39*42d10b1bSJohn Baldwin #include <ctype.h>
40*42d10b1bSJohn Baldwin #include <limits.h>
41*42d10b1bSJohn Baldwin #include <stdio.h>
42*42d10b1bSJohn Baldwin #include <stdlib.h>
43*42d10b1bSJohn Baldwin #include <string.h>
44*42d10b1bSJohn Baldwin #include <vector>
45*42d10b1bSJohn Baldwin 
46*42d10b1bSJohn Baldwin static long	flags;
47*42d10b1bSJohn Baldwin #define	TRANSPOSE	000001
48*42d10b1bSJohn Baldwin #define	MTRANSPOSE	000002
49*42d10b1bSJohn Baldwin #define	ONEPERLINE	000004
50*42d10b1bSJohn Baldwin #define	ONEISEPONLY	000010
51*42d10b1bSJohn Baldwin #define	ONEOSEPONLY	000020
52*42d10b1bSJohn Baldwin #define	NOTRIMENDCOL	000040
53*42d10b1bSJohn Baldwin #define	SQUEEZE		000100
54*42d10b1bSJohn Baldwin #define	SHAPEONLY	000200
55*42d10b1bSJohn Baldwin #define	DETAILSHAPE	000400
56*42d10b1bSJohn Baldwin #define	RIGHTADJUST	001000
57*42d10b1bSJohn Baldwin #define	NULLPAD		002000
58*42d10b1bSJohn Baldwin #define	RECYCLE		004000
59*42d10b1bSJohn Baldwin #define	SKIPPRINT	010000
60*42d10b1bSJohn Baldwin #define	ICOLBOUNDS	020000
61*42d10b1bSJohn Baldwin #define	OCOLBOUNDS	040000
62*42d10b1bSJohn Baldwin #define ONEPERCHAR	0100000
63*42d10b1bSJohn Baldwin #define NOARGS		0200000
64*42d10b1bSJohn Baldwin 
65*42d10b1bSJohn Baldwin static short	*colwidths;
66*42d10b1bSJohn Baldwin static short	*cord;
67*42d10b1bSJohn Baldwin static short	*icbd;
68*42d10b1bSJohn Baldwin static short	*ocbd;
69*42d10b1bSJohn Baldwin static std::vector<char *> elem;
70*42d10b1bSJohn Baldwin static char	*curline;
71*42d10b1bSJohn Baldwin static size_t	curlen;
72*42d10b1bSJohn Baldwin static size_t	irows, icols;
73*42d10b1bSJohn Baldwin static size_t	orows = 0, ocols = 0;
74*42d10b1bSJohn Baldwin static size_t	maxlen;
75*42d10b1bSJohn Baldwin static int	skip;
76*42d10b1bSJohn Baldwin static int	propgutter;
77*42d10b1bSJohn Baldwin static char	isep = ' ', osep = ' ';
78*42d10b1bSJohn Baldwin static char	blank[] = "";
79*42d10b1bSJohn Baldwin static int	owidth = 80, gutter = 2;
80*42d10b1bSJohn Baldwin 
81*42d10b1bSJohn Baldwin static void	  getargs(int, char *[]);
82*42d10b1bSJohn Baldwin static void	  getfile(void);
83*42d10b1bSJohn Baldwin static int	  get_line(void);
84*42d10b1bSJohn Baldwin static char	 *getlist(short **, char *);
85*42d10b1bSJohn Baldwin static char	 *getnum(int *, char *, int);
86*42d10b1bSJohn Baldwin static void	  prepfile(void);
87*42d10b1bSJohn Baldwin static void	  prints(char *, int);
88*42d10b1bSJohn Baldwin static void	  putfile(void);
89*42d10b1bSJohn Baldwin static void usage(void);
90*42d10b1bSJohn Baldwin 
91*42d10b1bSJohn Baldwin int
92*42d10b1bSJohn Baldwin main(int argc, char *argv[])
93*42d10b1bSJohn Baldwin {
94*42d10b1bSJohn Baldwin 	getargs(argc, argv);
95*42d10b1bSJohn Baldwin 	getfile();
96*42d10b1bSJohn Baldwin 	if (flags & SHAPEONLY) {
97*42d10b1bSJohn Baldwin 		printf("%zu %zu\n", irows, icols);
98*42d10b1bSJohn Baldwin 		exit(0);
99*42d10b1bSJohn Baldwin 	}
100*42d10b1bSJohn Baldwin 	prepfile();
101*42d10b1bSJohn Baldwin 	putfile();
102*42d10b1bSJohn Baldwin 	exit(0);
103*42d10b1bSJohn Baldwin }
104*42d10b1bSJohn Baldwin 
105*42d10b1bSJohn Baldwin static void
106*42d10b1bSJohn Baldwin getfile(void)
107*42d10b1bSJohn Baldwin {
108*42d10b1bSJohn Baldwin 	char *p, *sp;
109*42d10b1bSJohn Baldwin 	char *endp;
110*42d10b1bSJohn Baldwin 	int c;
111*42d10b1bSJohn Baldwin 	int multisep = (flags & ONEISEPONLY ? 0 : 1);
112*42d10b1bSJohn Baldwin 	int nullpad = flags & NULLPAD;
113*42d10b1bSJohn Baldwin 	size_t len, padto;
114*42d10b1bSJohn Baldwin 
115*42d10b1bSJohn Baldwin 	while (skip--) {
116*42d10b1bSJohn Baldwin 		c = get_line();
117*42d10b1bSJohn Baldwin 		if (flags & SKIPPRINT)
118*42d10b1bSJohn Baldwin 			puts(curline);
119*42d10b1bSJohn Baldwin 		if (c == EOF)
120*42d10b1bSJohn Baldwin 			return;
121*42d10b1bSJohn Baldwin 	}
122*42d10b1bSJohn Baldwin 	get_line();
123*42d10b1bSJohn Baldwin 	if (flags & NOARGS && curlen < (size_t)owidth)
124*42d10b1bSJohn Baldwin 		flags |= ONEPERLINE;
125*42d10b1bSJohn Baldwin 	if (flags & ONEPERLINE)
126*42d10b1bSJohn Baldwin 		icols = 1;
127*42d10b1bSJohn Baldwin 	else				/* count cols on first line */
128*42d10b1bSJohn Baldwin 		for (p = curline, endp = curline + curlen; p < endp; p++) {
129*42d10b1bSJohn Baldwin 			if (*p == isep && multisep)
130*42d10b1bSJohn Baldwin 				continue;
131*42d10b1bSJohn Baldwin 			icols++;
132*42d10b1bSJohn Baldwin 			while (*p && *p != isep)
133*42d10b1bSJohn Baldwin 				p++;
134*42d10b1bSJohn Baldwin 		}
135*42d10b1bSJohn Baldwin 	do {
136*42d10b1bSJohn Baldwin 		if (flags & ONEPERLINE) {
137*42d10b1bSJohn Baldwin 			elem.push_back(curline);
138*42d10b1bSJohn Baldwin 			if (maxlen < curlen)
139*42d10b1bSJohn Baldwin 				maxlen = curlen;
140*42d10b1bSJohn Baldwin 			irows++;
141*42d10b1bSJohn Baldwin 			continue;
142*42d10b1bSJohn Baldwin 		}
143*42d10b1bSJohn Baldwin 		for (p = curline, endp = curline + curlen; p < endp; p++) {
144*42d10b1bSJohn Baldwin 			if (*p == isep && multisep)
145*42d10b1bSJohn Baldwin 				continue;	/* eat up column separators */
146*42d10b1bSJohn Baldwin 			if (*p == isep)		/* must be an empty column */
147*42d10b1bSJohn Baldwin 				elem.push_back(blank);
148*42d10b1bSJohn Baldwin 			else			/* store column entry */
149*42d10b1bSJohn Baldwin 				elem.push_back(p);
150*42d10b1bSJohn Baldwin 			sp = p;
151*42d10b1bSJohn Baldwin 			while (p < endp && *p != isep)
152*42d10b1bSJohn Baldwin 				p++;		/* find end of entry */
153*42d10b1bSJohn Baldwin 			*p = '\0';		/* mark end of entry */
154*42d10b1bSJohn Baldwin 			len = p - sp;
155*42d10b1bSJohn Baldwin 			if (maxlen < len)	/* update maxlen */
156*42d10b1bSJohn Baldwin 				maxlen = len;
157*42d10b1bSJohn Baldwin 		}
158*42d10b1bSJohn Baldwin 		irows++;			/* update row count */
159*42d10b1bSJohn Baldwin 		if (nullpad) {			/* pad missing entries */
160*42d10b1bSJohn Baldwin 			padto = irows * icols;
161*42d10b1bSJohn Baldwin 			elem.resize(padto, blank);
162*42d10b1bSJohn Baldwin 		}
163*42d10b1bSJohn Baldwin 	} while (get_line() != EOF);
164*42d10b1bSJohn Baldwin }
165*42d10b1bSJohn Baldwin 
166*42d10b1bSJohn Baldwin static void
167*42d10b1bSJohn Baldwin putfile(void)
168*42d10b1bSJohn Baldwin {
169*42d10b1bSJohn Baldwin 	size_t i, j, k;
170*42d10b1bSJohn Baldwin 
171*42d10b1bSJohn Baldwin 	if (flags & TRANSPOSE)
172*42d10b1bSJohn Baldwin 		for (i = 0; i < orows; i++) {
173*42d10b1bSJohn Baldwin 			for (j = i; j < elem.size(); j += orows)
174*42d10b1bSJohn Baldwin 				prints(elem[j], (j - i) / orows);
175*42d10b1bSJohn Baldwin 			putchar('\n');
176*42d10b1bSJohn Baldwin 		}
177*42d10b1bSJohn Baldwin 	else
178*42d10b1bSJohn Baldwin 		for (i = k = 0; i < orows; i++) {
179*42d10b1bSJohn Baldwin 			for (j = 0; j < ocols; j++, k++)
180*42d10b1bSJohn Baldwin 				if (k < elem.size())
181*42d10b1bSJohn Baldwin 					prints(elem[k], j);
182*42d10b1bSJohn Baldwin 			putchar('\n');
183*42d10b1bSJohn Baldwin 		}
184*42d10b1bSJohn Baldwin }
185*42d10b1bSJohn Baldwin 
186*42d10b1bSJohn Baldwin static void
187*42d10b1bSJohn Baldwin prints(char *s, int col)
188*42d10b1bSJohn Baldwin {
189*42d10b1bSJohn Baldwin 	int n;
190*42d10b1bSJohn Baldwin 	char *p = s;
191*42d10b1bSJohn Baldwin 
192*42d10b1bSJohn Baldwin 	while (*p)
193*42d10b1bSJohn Baldwin 		p++;
194*42d10b1bSJohn Baldwin 	n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
195*42d10b1bSJohn Baldwin 	if (flags & RIGHTADJUST)
196*42d10b1bSJohn Baldwin 		while (n-- > 0)
197*42d10b1bSJohn Baldwin 			putchar(osep);
198*42d10b1bSJohn Baldwin 	for (p = s; *p; p++)
199*42d10b1bSJohn Baldwin 		putchar(*p);
200*42d10b1bSJohn Baldwin 	while (n-- > 0)
201*42d10b1bSJohn Baldwin 		putchar(osep);
202*42d10b1bSJohn Baldwin }
203*42d10b1bSJohn Baldwin 
204*42d10b1bSJohn Baldwin static void
205*42d10b1bSJohn Baldwin usage(void)
206*42d10b1bSJohn Baldwin {
207*42d10b1bSJohn Baldwin 	fprintf(stderr,
208*42d10b1bSJohn Baldwin 		"usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
209*42d10b1bSJohn Baldwin 	exit(1);
210*42d10b1bSJohn Baldwin }
211*42d10b1bSJohn Baldwin 
212*42d10b1bSJohn Baldwin static void
213*42d10b1bSJohn Baldwin prepfile(void)
214*42d10b1bSJohn Baldwin {
215*42d10b1bSJohn Baldwin 	size_t i, j;
216*42d10b1bSJohn Baldwin 	size_t colw, max, n, orig_size, padto;
217*42d10b1bSJohn Baldwin 
218*42d10b1bSJohn Baldwin 	if (elem.empty())
219*42d10b1bSJohn Baldwin 		exit(0);
220*42d10b1bSJohn Baldwin 	gutter += maxlen * propgutter / 100.0;
221*42d10b1bSJohn Baldwin 	colw = maxlen + gutter;
222*42d10b1bSJohn Baldwin 	if (flags & MTRANSPOSE) {
223*42d10b1bSJohn Baldwin 		orows = icols;
224*42d10b1bSJohn Baldwin 		ocols = irows;
225*42d10b1bSJohn Baldwin 	}
226*42d10b1bSJohn Baldwin 	else if (orows == 0 && ocols == 0) {	/* decide rows and cols */
227*42d10b1bSJohn Baldwin 		ocols = owidth / colw;
228*42d10b1bSJohn Baldwin 		if (ocols == 0) {
229*42d10b1bSJohn Baldwin 			warnx("display width %d is less than column width %zu",
230*42d10b1bSJohn Baldwin 					owidth, colw);
231*42d10b1bSJohn Baldwin 			ocols = 1;
232*42d10b1bSJohn Baldwin 		}
233*42d10b1bSJohn Baldwin 		if (ocols > elem.size())
234*42d10b1bSJohn Baldwin 			ocols = elem.size();
235*42d10b1bSJohn Baldwin 		orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0);
236*42d10b1bSJohn Baldwin 	}
237*42d10b1bSJohn Baldwin 	else if (orows == 0)			/* decide on rows */
238*42d10b1bSJohn Baldwin 		orows = elem.size() / ocols + (elem.size() % ocols ? 1 : 0);
239*42d10b1bSJohn Baldwin 	else if (ocols == 0)			/* decide on cols */
240*42d10b1bSJohn Baldwin 		ocols = elem.size() / orows + (elem.size() % orows ? 1 : 0);
241*42d10b1bSJohn Baldwin 	padto = orows * ocols;
242*42d10b1bSJohn Baldwin 	orig_size = elem.size();
243*42d10b1bSJohn Baldwin 	if (flags & RECYCLE) {
244*42d10b1bSJohn Baldwin 		for (i = 0; elem.size() < padto; i++)
245*42d10b1bSJohn Baldwin 			elem.push_back(elem[i % orig_size]);
246*42d10b1bSJohn Baldwin 	}
247*42d10b1bSJohn Baldwin 	if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
248*42d10b1bSJohn Baldwin 		errx(1, "malloc");
249*42d10b1bSJohn Baldwin 	if (flags & SQUEEZE) {
250*42d10b1bSJohn Baldwin 		if (flags & TRANSPOSE) {
251*42d10b1bSJohn Baldwin 			auto it = elem.begin();
252*42d10b1bSJohn Baldwin 			for (i = 0; i < ocols; i++) {
253*42d10b1bSJohn Baldwin 				max = 0;
254*42d10b1bSJohn Baldwin 				for (j = 0; it != elem.end() && j < orows; j++)
255*42d10b1bSJohn Baldwin 					if ((n = strlen(*it++)) > max)
256*42d10b1bSJohn Baldwin 						max = n;
257*42d10b1bSJohn Baldwin 				colwidths[i] = max + gutter;
258*42d10b1bSJohn Baldwin 			}
259*42d10b1bSJohn Baldwin 		} else {
260*42d10b1bSJohn Baldwin 			for (i = 0; i < ocols; i++) {
261*42d10b1bSJohn Baldwin 				max = 0;
262*42d10b1bSJohn Baldwin 				for (j = i; j < elem.size(); j += ocols)
263*42d10b1bSJohn Baldwin 					if ((n = strlen(elem[j])) > max)
264*42d10b1bSJohn Baldwin 						max = n;
265*42d10b1bSJohn Baldwin 				colwidths[i] = max + gutter;
266*42d10b1bSJohn Baldwin 			}
267*42d10b1bSJohn Baldwin 		}
268*42d10b1bSJohn Baldwin 	}
269*42d10b1bSJohn Baldwin 	/*	for (i = 0; i < orows; i++) {
270*42d10b1bSJohn Baldwin 			for (j = i; j < elem.size(); j += orows)
271*42d10b1bSJohn Baldwin 				prints(elem[j], (j - i) / orows);
272*42d10b1bSJohn Baldwin 			putchar('\n');
273*42d10b1bSJohn Baldwin 		}
274*42d10b1bSJohn Baldwin 	else {
275*42d10b1bSJohn Baldwin 		auto it = elem.begin();
276*42d10b1bSJohn Baldwin 		for (i = 0; i < orows; i++) {
277*42d10b1bSJohn Baldwin 			for (j = 0; j < ocols; j++)
278*42d10b1bSJohn Baldwin 				prints(*it++, j);
279*42d10b1bSJohn Baldwin 			putchar('\n');
280*42d10b1bSJohn Baldwin 		}*/
281*42d10b1bSJohn Baldwin 	else
282*42d10b1bSJohn Baldwin 		for (i = 0; i < ocols; i++)
283*42d10b1bSJohn Baldwin 			colwidths[i] = colw;
284*42d10b1bSJohn Baldwin 	if (!(flags & NOTRIMENDCOL)) {
285*42d10b1bSJohn Baldwin 		if (flags & RIGHTADJUST)
286*42d10b1bSJohn Baldwin 			colwidths[0] -= gutter;
287*42d10b1bSJohn Baldwin 		else
288*42d10b1bSJohn Baldwin 			colwidths[ocols - 1] = 0;
289*42d10b1bSJohn Baldwin 	}
290*42d10b1bSJohn Baldwin 	/*for (i = 0; i < ocols; i++)
291*42d10b1bSJohn Baldwin 		warnx("%d is colwidths, nelem %zu", colwidths[i], elem.size());*/
292*42d10b1bSJohn Baldwin }
293*42d10b1bSJohn Baldwin 
294*42d10b1bSJohn Baldwin #define	BSIZE	(LINE_MAX * 2)
295*42d10b1bSJohn Baldwin static char	ibuf[BSIZE];
296*42d10b1bSJohn Baldwin 
297*42d10b1bSJohn Baldwin static int
298*42d10b1bSJohn Baldwin get_line(void)	/* get line; maintain curline, curlen; manage storage */
299*42d10b1bSJohn Baldwin {
300*42d10b1bSJohn Baldwin 	static	int putlength;
301*42d10b1bSJohn Baldwin 	static	char *endblock = ibuf + BSIZE;
302*42d10b1bSJohn Baldwin 	char *p;
303*42d10b1bSJohn Baldwin 	int c, i;
304*42d10b1bSJohn Baldwin 
305*42d10b1bSJohn Baldwin 	if (irows == 0) {
306*42d10b1bSJohn Baldwin 		curline = ibuf;
307*42d10b1bSJohn Baldwin 		putlength = flags & DETAILSHAPE;
308*42d10b1bSJohn Baldwin 	}
309*42d10b1bSJohn Baldwin 	else if (skip <= 0) {			/* don't waste storage */
310*42d10b1bSJohn Baldwin 		curline += curlen + 1;
311*42d10b1bSJohn Baldwin 		if (putlength) {	/* print length, recycle storage */
312*42d10b1bSJohn Baldwin 			printf(" %zu line %zu\n", curlen, irows);
313*42d10b1bSJohn Baldwin 			curline = ibuf;
314*42d10b1bSJohn Baldwin 		}
315*42d10b1bSJohn Baldwin 	}
316*42d10b1bSJohn Baldwin 	if (!putlength && endblock - curline < LINE_MAX + 1) { /* need storage */
317*42d10b1bSJohn Baldwin 		/*ww = endblock-curline; tt += ww;*/
318*42d10b1bSJohn Baldwin 		/*printf("#wasted %d total %d\n",ww,tt);*/
319*42d10b1bSJohn Baldwin 		if (!(curline = (char *) malloc(BSIZE)))
320*42d10b1bSJohn Baldwin 			errx(1, "file too large");
321*42d10b1bSJohn Baldwin 		endblock = curline + BSIZE;
322*42d10b1bSJohn Baldwin 		/*printf("#endb %d curline %d\n",endblock,curline);*/
323*42d10b1bSJohn Baldwin 	}
324*42d10b1bSJohn Baldwin 	for (p = curline, i = 0;; *p++ = c, i++) {
325*42d10b1bSJohn Baldwin 		if ((c = getchar()) == EOF)
326*42d10b1bSJohn Baldwin 			break;
327*42d10b1bSJohn Baldwin 		if (i >= LINE_MAX)
328*42d10b1bSJohn Baldwin 			errx(1, "maximum line length (%d) exceeded", LINE_MAX);
329*42d10b1bSJohn Baldwin 		if (c == '\n')
330*42d10b1bSJohn Baldwin 			break;
331*42d10b1bSJohn Baldwin 	}
332*42d10b1bSJohn Baldwin 	*p = '\0';
333*42d10b1bSJohn Baldwin 	curlen = i;
334*42d10b1bSJohn Baldwin 	return(c);
335*42d10b1bSJohn Baldwin }
336*42d10b1bSJohn Baldwin 
337*42d10b1bSJohn Baldwin static void
338*42d10b1bSJohn Baldwin getargs(int ac, char *av[])
339*42d10b1bSJohn Baldwin {
340*42d10b1bSJohn Baldwin 	long val;
341*42d10b1bSJohn Baldwin 	char *p;
342*42d10b1bSJohn Baldwin 
343*42d10b1bSJohn Baldwin 	if (ac == 1) {
344*42d10b1bSJohn Baldwin 		flags |= NOARGS | TRANSPOSE;
345*42d10b1bSJohn Baldwin 	}
346*42d10b1bSJohn Baldwin 	while (--ac && **++av == '-')
347*42d10b1bSJohn Baldwin 		for (p = *av+1; *p; p++)
348*42d10b1bSJohn Baldwin 			switch (*p) {
349*42d10b1bSJohn Baldwin 			case 'T':
350*42d10b1bSJohn Baldwin 				flags |= MTRANSPOSE;
351*42d10b1bSJohn Baldwin 				/* FALLTHROUGH */
352*42d10b1bSJohn Baldwin 			case 't':
353*42d10b1bSJohn Baldwin 				flags |= TRANSPOSE;
354*42d10b1bSJohn Baldwin 				break;
355*42d10b1bSJohn Baldwin 			case 'c':		/* input col. separator */
356*42d10b1bSJohn Baldwin 				flags |= ONEISEPONLY;
357*42d10b1bSJohn Baldwin 				/* FALLTHROUGH */
358*42d10b1bSJohn Baldwin 			case 's':		/* one or more allowed */
359*42d10b1bSJohn Baldwin 				if (p[1])
360*42d10b1bSJohn Baldwin 					isep = *++p;
361*42d10b1bSJohn Baldwin 				else
362*42d10b1bSJohn Baldwin 					isep = '\t';	/* default is ^I */
363*42d10b1bSJohn Baldwin 				break;
364*42d10b1bSJohn Baldwin 			case 'C':
365*42d10b1bSJohn Baldwin 				flags |= ONEOSEPONLY;
366*42d10b1bSJohn Baldwin 				/* FALLTHROUGH */
367*42d10b1bSJohn Baldwin 			case 'S':
368*42d10b1bSJohn Baldwin 				if (p[1])
369*42d10b1bSJohn Baldwin 					osep = *++p;
370*42d10b1bSJohn Baldwin 				else
371*42d10b1bSJohn Baldwin 					osep = '\t';	/* default is ^I */
372*42d10b1bSJohn Baldwin 				break;
373*42d10b1bSJohn Baldwin 			case 'w':		/* window width, default 80 */
374*42d10b1bSJohn Baldwin 				p = getnum(&owidth, p, 0);
375*42d10b1bSJohn Baldwin 				if (owidth <= 0)
376*42d10b1bSJohn Baldwin 					errx(1, "width must be a positive integer");
377*42d10b1bSJohn Baldwin 				break;
378*42d10b1bSJohn Baldwin 			case 'K':			/* skip N lines */
379*42d10b1bSJohn Baldwin 				flags |= SKIPPRINT;
380*42d10b1bSJohn Baldwin 				/* FALLTHROUGH */
381*42d10b1bSJohn Baldwin 			case 'k':			/* skip, do not print */
382*42d10b1bSJohn Baldwin 				p = getnum(&skip, p, 0);
383*42d10b1bSJohn Baldwin 				if (!skip)
384*42d10b1bSJohn Baldwin 					skip = 1;
385*42d10b1bSJohn Baldwin 				break;
386*42d10b1bSJohn Baldwin 			case 'm':
387*42d10b1bSJohn Baldwin 				flags |= NOTRIMENDCOL;
388*42d10b1bSJohn Baldwin 				break;
389*42d10b1bSJohn Baldwin 			case 'g':		/* gutter space */
390*42d10b1bSJohn Baldwin 				p = getnum(&gutter, p, 0);
391*42d10b1bSJohn Baldwin 				break;
392*42d10b1bSJohn Baldwin 			case 'G':
393*42d10b1bSJohn Baldwin 				p = getnum(&propgutter, p, 0);
394*42d10b1bSJohn Baldwin 				break;
395*42d10b1bSJohn Baldwin 			case 'e':		/* each line is an entry */
396*42d10b1bSJohn Baldwin 				flags |= ONEPERLINE;
397*42d10b1bSJohn Baldwin 				break;
398*42d10b1bSJohn Baldwin 			case 'E':
399*42d10b1bSJohn Baldwin 				flags |= ONEPERCHAR;
400*42d10b1bSJohn Baldwin 				break;
401*42d10b1bSJohn Baldwin 			case 'j':			/* right adjust */
402*42d10b1bSJohn Baldwin 				flags |= RIGHTADJUST;
403*42d10b1bSJohn Baldwin 				break;
404*42d10b1bSJohn Baldwin 			case 'n':	/* null padding for missing values */
405*42d10b1bSJohn Baldwin 				flags |= NULLPAD;
406*42d10b1bSJohn Baldwin 				break;
407*42d10b1bSJohn Baldwin 			case 'y':
408*42d10b1bSJohn Baldwin 				flags |= RECYCLE;
409*42d10b1bSJohn Baldwin 				break;
410*42d10b1bSJohn Baldwin 			case 'H':			/* print shape only */
411*42d10b1bSJohn Baldwin 				flags |= DETAILSHAPE;
412*42d10b1bSJohn Baldwin 				/* FALLTHROUGH */
413*42d10b1bSJohn Baldwin 			case 'h':
414*42d10b1bSJohn Baldwin 				flags |= SHAPEONLY;
415*42d10b1bSJohn Baldwin 				break;
416*42d10b1bSJohn Baldwin 			case 'z':			/* squeeze col width */
417*42d10b1bSJohn Baldwin 				flags |= SQUEEZE;
418*42d10b1bSJohn Baldwin 				break;
419*42d10b1bSJohn Baldwin 			/*case 'p':
420*42d10b1bSJohn Baldwin 				ipagespace = atoi(++p);	(default is 1)
421*42d10b1bSJohn Baldwin 				break;*/
422*42d10b1bSJohn Baldwin 			case 'o':			/* col order */
423*42d10b1bSJohn Baldwin 				p = getlist(&cord, p);
424*42d10b1bSJohn Baldwin 				break;
425*42d10b1bSJohn Baldwin 			case 'b':
426*42d10b1bSJohn Baldwin 				flags |= ICOLBOUNDS;
427*42d10b1bSJohn Baldwin 				p = getlist(&icbd, p);
428*42d10b1bSJohn Baldwin 				break;
429*42d10b1bSJohn Baldwin 			case 'B':
430*42d10b1bSJohn Baldwin 				flags |= OCOLBOUNDS;
431*42d10b1bSJohn Baldwin 				p = getlist(&ocbd, p);
432*42d10b1bSJohn Baldwin 				break;
433*42d10b1bSJohn Baldwin 			default:
434*42d10b1bSJohn Baldwin 				usage();
435*42d10b1bSJohn Baldwin 			}
436*42d10b1bSJohn Baldwin 	/*if (!osep)
437*42d10b1bSJohn Baldwin 		osep = isep;*/
438*42d10b1bSJohn Baldwin 	switch (ac) {
439*42d10b1bSJohn Baldwin #if 0
440*42d10b1bSJohn Baldwin 	case 3:
441*42d10b1bSJohn Baldwin 		opages = atoi(av[2]);
442*42d10b1bSJohn Baldwin 		/* FALLTHROUGH */
443*42d10b1bSJohn Baldwin #endif
444*42d10b1bSJohn Baldwin 	case 2:
445*42d10b1bSJohn Baldwin 		val = strtol(av[1], NULL, 10);
446*42d10b1bSJohn Baldwin 		if (val >= 0)
447*42d10b1bSJohn Baldwin 			ocols = val;
448*42d10b1bSJohn Baldwin 		/* FALLTHROUGH */
449*42d10b1bSJohn Baldwin 	case 1:
450*42d10b1bSJohn Baldwin 		val = strtol(av[0], NULL, 10);
451*42d10b1bSJohn Baldwin 		if (val >= 0)
452*42d10b1bSJohn Baldwin 			orows = val;
453*42d10b1bSJohn Baldwin 		/* FALLTHROUGH */
454*42d10b1bSJohn Baldwin 	case 0:
455*42d10b1bSJohn Baldwin 		break;
456*42d10b1bSJohn Baldwin 	default:
457*42d10b1bSJohn Baldwin 		errx(1, "too many arguments");
458*42d10b1bSJohn Baldwin 	}
459*42d10b1bSJohn Baldwin }
460*42d10b1bSJohn Baldwin 
461*42d10b1bSJohn Baldwin static char *
462*42d10b1bSJohn Baldwin getlist(short **list, char *p)
463*42d10b1bSJohn Baldwin {
464*42d10b1bSJohn Baldwin 	int count = 1;
465*42d10b1bSJohn Baldwin 	char *t;
466*42d10b1bSJohn Baldwin 
467*42d10b1bSJohn Baldwin 	for (t = p + 1; *t; t++) {
468*42d10b1bSJohn Baldwin 		if (!isdigit((unsigned char)*t))
469*42d10b1bSJohn Baldwin 			errx(1,
470*42d10b1bSJohn Baldwin 	"option %.1s requires a list of unsigned numbers separated by commas", t);
471*42d10b1bSJohn Baldwin 		count++;
472*42d10b1bSJohn Baldwin 		while (*t && isdigit((unsigned char)*t))
473*42d10b1bSJohn Baldwin 			t++;
474*42d10b1bSJohn Baldwin 		if (*t != ',')
475*42d10b1bSJohn Baldwin 			break;
476*42d10b1bSJohn Baldwin 	}
477*42d10b1bSJohn Baldwin 	if (!(*list = (short *) malloc(count * sizeof(short))))
478*42d10b1bSJohn Baldwin 		errx(1, "no list space");
479*42d10b1bSJohn Baldwin 	count = 0;
480*42d10b1bSJohn Baldwin 	for (t = p + 1; *t; t++) {
481*42d10b1bSJohn Baldwin 		(*list)[count++] = atoi(t);
482*42d10b1bSJohn Baldwin 		printf("++ %d ", (*list)[count-1]);
483*42d10b1bSJohn Baldwin 		fflush(stdout);
484*42d10b1bSJohn Baldwin 		while (*t && isdigit((unsigned char)*t))
485*42d10b1bSJohn Baldwin 			t++;
486*42d10b1bSJohn Baldwin 		if (*t != ',')
487*42d10b1bSJohn Baldwin 			break;
488*42d10b1bSJohn Baldwin 	}
489*42d10b1bSJohn Baldwin 	(*list)[count] = 0;
490*42d10b1bSJohn Baldwin 	return(t - 1);
491*42d10b1bSJohn Baldwin }
492*42d10b1bSJohn Baldwin 
493*42d10b1bSJohn Baldwin /*
494*42d10b1bSJohn Baldwin  * num = number p points to; if (strict) complain
495*42d10b1bSJohn Baldwin  * returns pointer to end of num
496*42d10b1bSJohn Baldwin  */
497*42d10b1bSJohn Baldwin static char *
498*42d10b1bSJohn Baldwin getnum(int *num, char *p, int strict)
499*42d10b1bSJohn Baldwin {
500*42d10b1bSJohn Baldwin 	char *t = p;
501*42d10b1bSJohn Baldwin 
502*42d10b1bSJohn Baldwin 	if (!isdigit((unsigned char)*++t)) {
503*42d10b1bSJohn Baldwin 		if (strict || *t == '-' || *t == '+')
504*42d10b1bSJohn Baldwin 			errx(1, "option %.1s requires an unsigned integer", p);
505*42d10b1bSJohn Baldwin 		*num = 0;
506*42d10b1bSJohn Baldwin 		return(p);
507*42d10b1bSJohn Baldwin 	}
508*42d10b1bSJohn Baldwin 	*num = atoi(t);
509*42d10b1bSJohn Baldwin 	while (*++t)
510*42d10b1bSJohn Baldwin 		if (!isdigit((unsigned char)*t))
511*42d10b1bSJohn Baldwin 			break;
512*42d10b1bSJohn Baldwin 	return(--t);
513*42d10b1bSJohn Baldwin }
514