rs.c revision 83296
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3527953Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4127953Scharnier#if 0
421590Srgrimesstatic char sccsid[] = "@(#)rs.c	8.1 (Berkeley) 6/6/93";
4327953Scharnier#endif
4427953Scharnierstatic const char rcsid[] =
4550477Speter  "$FreeBSD: head/usr.bin/rs/rs.c 83296 2001-09-10 11:43:40Z ru $";
461590Srgrimes#endif /* not lint */
471590Srgrimes
481590Srgrimes/*
491590Srgrimes *	rs - reshape a data array
501590Srgrimes *	Author:  John Kunze, Office of Comp. Affairs, UCB
511590Srgrimes *		BEWARE: lots of unfinished edges
521590Srgrimes */
531590Srgrimes
5427953Scharnier#include <err.h>
551590Srgrimes#include <ctype.h>
561590Srgrimes#include <stdio.h>
571590Srgrimes#include <stdlib.h>
5833648Sjb#include <string.h>
591590Srgrimes
601590Srgrimeslong	flags;
611590Srgrimes#define	TRANSPOSE	000001
621590Srgrimes#define	MTRANSPOSE	000002
631590Srgrimes#define	ONEPERLINE	000004
641590Srgrimes#define	ONEISEPONLY	000010
651590Srgrimes#define	ONEOSEPONLY	000020
661590Srgrimes#define	NOTRIMENDCOL	000040
671590Srgrimes#define	SQUEEZE		000100
681590Srgrimes#define	SHAPEONLY	000200
691590Srgrimes#define	DETAILSHAPE	000400
701590Srgrimes#define	RIGHTADJUST	001000
711590Srgrimes#define	NULLPAD		002000
721590Srgrimes#define	RECYCLE		004000
731590Srgrimes#define	SKIPPRINT	010000
741590Srgrimes#define	ICOLBOUNDS	020000
751590Srgrimes#define	OCOLBOUNDS	040000
761590Srgrimes#define ONEPERCHAR	0100000
771590Srgrimes#define NOARGS		0200000
781590Srgrimes
791590Srgrimesshort	*colwidths;
801590Srgrimesshort	*cord;
811590Srgrimesshort	*icbd;
821590Srgrimesshort	*ocbd;
831590Srgrimesint	nelem;
841590Srgrimeschar	**elem;
851590Srgrimeschar	**endelem;
861590Srgrimeschar	*curline;
871590Srgrimesint	allocsize = BUFSIZ;
881590Srgrimesint	curlen;
891590Srgrimesint	irows, icols;
901590Srgrimesint	orows, ocols;
911590Srgrimesint	maxlen;
921590Srgrimesint	skip;
931590Srgrimesint	propgutter;
941590Srgrimeschar	isep = ' ', osep = ' ';
951590Srgrimesint	owidth = 80, gutter = 2;
961590Srgrimes
971590Srgrimesvoid	  getargs __P((int, char *[]));
981590Srgrimesvoid	  getfile __P((void));
991590Srgrimesint	  getline __P((void));
1001590Srgrimeschar	 *getlist __P((short **, char *));
1011590Srgrimeschar	 *getnum __P((int *, char *, int));
1021590Srgrimeschar	**getptrs __P((char **));
1031590Srgrimesvoid	  prepfile __P((void));
1041590Srgrimesvoid	  prints __P((char *, int));
1051590Srgrimesvoid	  putfile __P((void));
10627953Scharnierstatic void usage __P((void));
1071590Srgrimes
1081590Srgrimesint
1091590Srgrimesmain(argc, argv)
1101590Srgrimes	int argc;
1111590Srgrimes	char *argv[];
1121590Srgrimes{
1131590Srgrimes	getargs(argc, argv);
1141590Srgrimes	getfile();
1151590Srgrimes	if (flags & SHAPEONLY) {
1161590Srgrimes		printf("%d %d\n", irows, icols);
1171590Srgrimes		exit(0);
1181590Srgrimes	}
1191590Srgrimes	prepfile();
1201590Srgrimes	putfile();
1211590Srgrimes	exit(0);
1221590Srgrimes}
1231590Srgrimes
1241590Srgrimesvoid
1251590Srgrimesgetfile()
1261590Srgrimes{
1271590Srgrimes	register char *p;
1281590Srgrimes	register char *endp;
1291590Srgrimes	register char **ep = 0;
1301590Srgrimes	int multisep = (flags & ONEISEPONLY ? 0 : 1);
1311590Srgrimes	int nullpad = flags & NULLPAD;
1321590Srgrimes	char **padto;
1331590Srgrimes
1341590Srgrimes	while (skip--) {
1351590Srgrimes		getline();
1361590Srgrimes		if (flags & SKIPPRINT)
1371590Srgrimes			puts(curline);
1381590Srgrimes	}
1391590Srgrimes	getline();
1401590Srgrimes	if (flags & NOARGS && curlen < owidth)
1411590Srgrimes		flags |= ONEPERLINE;
1421590Srgrimes	if (flags & ONEPERLINE)
1431590Srgrimes		icols = 1;
1441590Srgrimes	else				/* count cols on first line */
1451590Srgrimes		for (p = curline, endp = curline + curlen; p < endp; p++) {
1461590Srgrimes			if (*p == isep && multisep)
1471590Srgrimes				continue;
1481590Srgrimes			icols++;
1491590Srgrimes			while (*p && *p != isep)
1501590Srgrimes				p++;
1511590Srgrimes		}
1521590Srgrimes	ep = getptrs(elem);
1531590Srgrimes	p = curline;
1541590Srgrimes	do {
1551590Srgrimes		if (flags & ONEPERLINE) {
1561590Srgrimes			*ep++ = curline;
1571590Srgrimes			if (maxlen < curlen)
1581590Srgrimes				maxlen = curlen;
1591590Srgrimes			irows++;
1601590Srgrimes			continue;
1611590Srgrimes		}
1621590Srgrimes		for (p = curline, endp = curline + curlen; p < endp; p++) {
1631590Srgrimes			if (*p == isep && multisep)
1641590Srgrimes				continue;	/* eat up column separators */
1651590Srgrimes			if (*p == isep)		/* must be an empty column */
1661590Srgrimes				*ep = "";
1671590Srgrimes			else			/* store column entry */
1681590Srgrimes				*ep = p;
1691590Srgrimes			while (p < endp && *p != isep)
1701590Srgrimes				p++;		/* find end of entry */
1711590Srgrimes			*p = '\0';		/* mark end of entry */
1721590Srgrimes			if (maxlen < p - *ep)	/* update maxlen */
1731590Srgrimes				maxlen = p - *ep;
1741590Srgrimes			ep++;			/* prepare for next entry */
1751590Srgrimes		}
1761590Srgrimes		irows++;			/* update row count */
1771590Srgrimes		if (nullpad) {			/* pad missing entries */
1781590Srgrimes			padto = elem + irows * icols;
1791590Srgrimes			while  (ep < padto)
1801590Srgrimes				*ep++ = "";
1811590Srgrimes		}
1821590Srgrimes	if (ep > endelem)			/* if low on pointers */
1831590Srgrimes		ep = getptrs(ep);		/* get some more */
1841590Srgrimes	} while (getline() != EOF);
1851590Srgrimes	*ep = 0;				/* mark end of pointers */
1861590Srgrimes	nelem = ep - elem;
1871590Srgrimes}
1881590Srgrimes
1891590Srgrimesvoid
1901590Srgrimesputfile()
1911590Srgrimes{
1921590Srgrimes	register char **ep;
19315909Sjoerg	register int i, j, k;
1941590Srgrimes
1951590Srgrimes	ep = elem;
1961590Srgrimes	if (flags & TRANSPOSE)
1971590Srgrimes		for (i = 0; i < orows; i++) {
1981590Srgrimes			for (j = i; j < nelem; j += orows)
1991590Srgrimes				prints(ep[j], (j - i) / orows);
2001590Srgrimes			putchar('\n');
2011590Srgrimes		}
2021590Srgrimes	else
20315909Sjoerg		for (i = k = 0; i < orows; i++) {
20415909Sjoerg			for (j = 0; j < ocols; j++, k++)
20515909Sjoerg				if (k < nelem)
20615909Sjoerg					prints(ep[k], j);
2071590Srgrimes			putchar('\n');
2081590Srgrimes		}
2091590Srgrimes}
2101590Srgrimes
2111590Srgrimesvoid
2121590Srgrimesprints(s, col)
2131590Srgrimes	char *s;
2141590Srgrimes	int col;
2151590Srgrimes{
2161590Srgrimes	register int n;
2171590Srgrimes	register char *p = s;
2181590Srgrimes
2191590Srgrimes	while (*p)
2201590Srgrimes		p++;
2211590Srgrimes	n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
2221590Srgrimes	if (flags & RIGHTADJUST)
2231590Srgrimes		while (n-- > 0)
2241590Srgrimes			putchar(osep);
2251590Srgrimes	for (p = s; *p; p++)
2261590Srgrimes		putchar(*p);
2271590Srgrimes	while (n-- > 0)
2281590Srgrimes		putchar(osep);
2291590Srgrimes}
2301590Srgrimes
23127953Scharnierstatic void
23227953Scharnierusage()
2331590Srgrimes{
2341590Srgrimes	fprintf(stderr,
23527953Scharnier		"usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
2361590Srgrimes	exit(1);
2371590Srgrimes}
2381590Srgrimes
2391590Srgrimesvoid
2401590Srgrimesprepfile()
2411590Srgrimes{
2421590Srgrimes	register char **ep;
2431590Srgrimes	register int  i;
2441590Srgrimes	register int  j;
2451590Srgrimes	char **lp;
2461590Srgrimes	int colw;
24783296Sru	int max;
2481590Srgrimes	int n;
2491590Srgrimes
2501590Srgrimes	if (!nelem)
2511590Srgrimes		exit(0);
2521590Srgrimes	gutter += maxlen * propgutter / 100.0;
2531590Srgrimes	colw = maxlen + gutter;
2541590Srgrimes	if (flags & MTRANSPOSE) {
2551590Srgrimes		orows = icols;
2561590Srgrimes		ocols = irows;
2571590Srgrimes	}
2581590Srgrimes	else if (orows == 0 && ocols == 0) {	/* decide rows and cols */
2591590Srgrimes		ocols = owidth / colw;
2601590Srgrimes		if (ocols == 0)
26127953Scharnier			warnx("display width %d is less than column width %d",
26227953Scharnier					owidth, colw);
2631590Srgrimes		if (ocols > nelem)
2641590Srgrimes			ocols = nelem;
2651590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2661590Srgrimes	}
2671590Srgrimes	else if (orows == 0)			/* decide on rows */
2681590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2691590Srgrimes	else if (ocols == 0)			/* decide on cols */
2701590Srgrimes		ocols = nelem / orows + (nelem % orows ? 1 : 0);
2711590Srgrimes	lp = elem + orows * ocols;
2721590Srgrimes	while (lp > endelem) {
2731590Srgrimes		getptrs(elem + nelem);
2741590Srgrimes		lp = elem + orows * ocols;
2751590Srgrimes	}
2761590Srgrimes	if (flags & RECYCLE) {
2771590Srgrimes		for (ep = elem + nelem; ep < lp; ep++)
2781590Srgrimes			*ep = *(ep - nelem);
2791590Srgrimes		nelem = lp - elem;
2801590Srgrimes	}
2811590Srgrimes	if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
28227953Scharnier		errx(1, "malloc");
2831590Srgrimes	if (flags & SQUEEZE) {
28483296Sru		ep = elem;
2851590Srgrimes		if (flags & TRANSPOSE)
28683296Sru			for (i = 0; i < ocols; i++) {
28783296Sru				max = 0;
28883296Sru				for (j = 0; *ep != NULL && j < orows; j++)
2891590Srgrimes					if ((n = strlen(*ep++)) > max)
2901590Srgrimes						max = n;
2911590Srgrimes				colwidths[i] = max + gutter;
2921590Srgrimes			}
2931590Srgrimes		else
2941590Srgrimes			for (i = 0; i < ocols; i++) {
29583296Sru				max = 0;
2961590Srgrimes				for (j = i; j < nelem; j += ocols)
2971590Srgrimes					if ((n = strlen(ep[j])) > max)
2981590Srgrimes						max = n;
2991590Srgrimes				colwidths[i] = max + gutter;
3001590Srgrimes			}
3011590Srgrimes	}
3021590Srgrimes	/*	for (i = 0; i < orows; i++) {
3031590Srgrimes			for (j = i; j < nelem; j += orows)
3041590Srgrimes				prints(ep[j], (j - i) / orows);
3051590Srgrimes			putchar('\n');
3061590Srgrimes		}
3071590Srgrimes	else
3081590Srgrimes		for (i = 0; i < orows; i++) {
3091590Srgrimes			for (j = 0; j < ocols; j++)
3101590Srgrimes				prints(*ep++, j);
3111590Srgrimes			putchar('\n');
3121590Srgrimes		}*/
3131590Srgrimes	else
3141590Srgrimes		for (i = 0; i < ocols; i++)
3151590Srgrimes			colwidths[i] = colw;
3161590Srgrimes	if (!(flags & NOTRIMENDCOL)) {
3171590Srgrimes		if (flags & RIGHTADJUST)
3181590Srgrimes			colwidths[0] -= gutter;
3191590Srgrimes		else
3201590Srgrimes			colwidths[ocols - 1] = 0;
3211590Srgrimes	}
3221590Srgrimes	n = orows * ocols;
3231590Srgrimes	if (n > nelem && (flags & RECYCLE))
3241590Srgrimes		nelem = n;
3251590Srgrimes	/*for (i = 0; i < ocols; i++)
32627953Scharnier		warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/
3271590Srgrimes}
3281590Srgrimes
3291590Srgrimes#define	BSIZE	2048
3301590Srgrimeschar	ibuf[BSIZE];		/* two screenfuls should do */
3311590Srgrimes
3321590Srgrimesint
3331590Srgrimesgetline()	/* get line; maintain curline, curlen; manage storage */
3341590Srgrimes{
3351590Srgrimes	static	int putlength;
3361590Srgrimes	static	char *endblock = ibuf + BSIZE;
3371590Srgrimes	register char *p;
3381590Srgrimes	register int c, i;
3391590Srgrimes
3401590Srgrimes	if (!irows) {
3411590Srgrimes		curline = ibuf;
3421590Srgrimes		putlength = flags & DETAILSHAPE;
3431590Srgrimes	}
3441590Srgrimes	else if (skip <= 0) {			/* don't waste storage */
3451590Srgrimes		curline += curlen + 1;
3461590Srgrimes		if (putlength)		/* print length, recycle storage */
3471590Srgrimes			printf(" %d line %d\n", curlen, irows);
3481590Srgrimes	}
3491590Srgrimes	if (!putlength && endblock - curline < BUFSIZ) {   /* need storage */
3501590Srgrimes		/*ww = endblock-curline; tt += ww;*/
3511590Srgrimes		/*printf("#wasted %d total %d\n",ww,tt);*/
3521590Srgrimes		if (!(curline = (char *) malloc(BSIZE)))
35327953Scharnier			errx(1, "file too large");
3541590Srgrimes		endblock = curline + BSIZE;
3551590Srgrimes		/*printf("#endb %d curline %d\n",endblock,curline);*/
3561590Srgrimes	}
3571590Srgrimes	for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
3581590Srgrimes		if ((c = getchar()) == EOF || c == '\n')
3591590Srgrimes			break;
3601590Srgrimes	*p = '\0';
3611590Srgrimes	curlen = i - 1;
3621590Srgrimes	return(c);
3631590Srgrimes}
3641590Srgrimes
3651590Srgrimeschar **
3661590Srgrimesgetptrs(sp)
3671590Srgrimes	char **sp;
3681590Srgrimes{
3691590Srgrimes	register char **p, **ep;
3701590Srgrimes
3711590Srgrimes	for (;;) {
3721590Srgrimes		allocsize += allocsize;
37327953Scharnier		if (!(p = (char **) malloc(allocsize * sizeof(char *))))
37427953Scharnier			errx(1, "malloc");
3751590Srgrimes		if ((endelem = p + allocsize - icols) <= p) {
3761590Srgrimes			free(p);
3771590Srgrimes			continue;
3781590Srgrimes		}
3791590Srgrimes		if (elem != 0)
3801590Srgrimes			free(elem);
3811590Srgrimes		ep = elem;
3821590Srgrimes		elem = p;
3831590Srgrimes		while (ep < sp)
3841590Srgrimes			*p++ = *ep++;
3851590Srgrimes		return(p);
3861590Srgrimes	}
3871590Srgrimes}
3881590Srgrimes
3891590Srgrimesvoid
3901590Srgrimesgetargs(ac, av)
3911590Srgrimes	int ac;
3921590Srgrimes	char *av[];
3931590Srgrimes{
3941590Srgrimes	register char *p;
3951590Srgrimes
3961590Srgrimes	if (ac == 1) {
3971590Srgrimes		flags |= NOARGS | TRANSPOSE;
3981590Srgrimes	}
3991590Srgrimes	while (--ac && **++av == '-')
4001590Srgrimes		for (p = *av+1; *p; p++)
4011590Srgrimes			switch (*p) {
4021590Srgrimes			case 'T':
4031590Srgrimes				flags |= MTRANSPOSE;
4041590Srgrimes			case 't':
4051590Srgrimes				flags |= TRANSPOSE;
4061590Srgrimes				break;
4071590Srgrimes			case 'c':		/* input col. separator */
4081590Srgrimes				flags |= ONEISEPONLY;
4091590Srgrimes			case 's':		/* one or more allowed */
4101590Srgrimes				if (p[1])
4111590Srgrimes					isep = *++p;
4121590Srgrimes				else
4131590Srgrimes					isep = '\t';	/* default is ^I */
4141590Srgrimes				break;
4151590Srgrimes			case 'C':
4161590Srgrimes				flags |= ONEOSEPONLY;
4171590Srgrimes			case 'S':
4181590Srgrimes				if (p[1])
4191590Srgrimes					osep = *++p;
4201590Srgrimes				else
4211590Srgrimes					osep = '\t';	/* default is ^I */
4221590Srgrimes				break;
4231590Srgrimes			case 'w':		/* window width, default 80 */
4241590Srgrimes				p = getnum(&owidth, p, 0);
4251590Srgrimes				if (owidth <= 0)
42627953Scharnier					errx(1, "width must be a positive integer");
4271590Srgrimes				break;
4281590Srgrimes			case 'K':			/* skip N lines */
4291590Srgrimes				flags |= SKIPPRINT;
4301590Srgrimes			case 'k':			/* skip, do not print */
4311590Srgrimes				p = getnum(&skip, p, 0);
4321590Srgrimes				if (!skip)
4331590Srgrimes					skip = 1;
4341590Srgrimes				break;
4351590Srgrimes			case 'm':
4361590Srgrimes				flags |= NOTRIMENDCOL;
4371590Srgrimes				break;
4381590Srgrimes			case 'g':		/* gutter space */
4391590Srgrimes				p = getnum(&gutter, p, 0);
4401590Srgrimes				break;
4411590Srgrimes			case 'G':
4421590Srgrimes				p = getnum(&propgutter, p, 0);
4431590Srgrimes				break;
4441590Srgrimes			case 'e':		/* each line is an entry */
4451590Srgrimes				flags |= ONEPERLINE;
4461590Srgrimes				break;
4471590Srgrimes			case 'E':
4481590Srgrimes				flags |= ONEPERCHAR;
4491590Srgrimes				break;
4501590Srgrimes			case 'j':			/* right adjust */
4511590Srgrimes				flags |= RIGHTADJUST;
4521590Srgrimes				break;
4531590Srgrimes			case 'n':	/* null padding for missing values */
4541590Srgrimes				flags |= NULLPAD;
4551590Srgrimes				break;
4561590Srgrimes			case 'y':
4571590Srgrimes				flags |= RECYCLE;
4581590Srgrimes				break;
4591590Srgrimes			case 'H':			/* print shape only */
4601590Srgrimes				flags |= DETAILSHAPE;
4611590Srgrimes			case 'h':
4621590Srgrimes				flags |= SHAPEONLY;
4631590Srgrimes				break;
4641590Srgrimes			case 'z':			/* squeeze col width */
4651590Srgrimes				flags |= SQUEEZE;
4661590Srgrimes				break;
4671590Srgrimes			/*case 'p':
4681590Srgrimes				ipagespace = atoi(++p);	(default is 1)
4691590Srgrimes				break;*/
4701590Srgrimes			case 'o':			/* col order */
4711590Srgrimes				p = getlist(&cord, p);
4721590Srgrimes				break;
4731590Srgrimes			case 'b':
4741590Srgrimes				flags |= ICOLBOUNDS;
4751590Srgrimes				p = getlist(&icbd, p);
4761590Srgrimes				break;
4771590Srgrimes			case 'B':
4781590Srgrimes				flags |= OCOLBOUNDS;
4791590Srgrimes				p = getlist(&ocbd, p);
4801590Srgrimes				break;
4811590Srgrimes			default:
48227953Scharnier				usage();
4831590Srgrimes			}
4841590Srgrimes	/*if (!osep)
4851590Srgrimes		osep = isep;*/
4861590Srgrimes	switch (ac) {
4871590Srgrimes	/*case 3:
4881590Srgrimes		opages = atoi(av[2]);*/
4891590Srgrimes	case 2:
4901590Srgrimes		ocols = atoi(av[1]);
4911590Srgrimes	case 1:
4921590Srgrimes		orows = atoi(av[0]);
4931590Srgrimes	case 0:
4941590Srgrimes		break;
4951590Srgrimes	default:
49627953Scharnier		errx(1, "too many arguments");
4971590Srgrimes	}
4981590Srgrimes}
4991590Srgrimes
5001590Srgrimeschar *
5011590Srgrimesgetlist(list, p)
5021590Srgrimes	short **list;
5031590Srgrimes	char *p;
5041590Srgrimes{
5051590Srgrimes	register int count = 1;
5061590Srgrimes	register char *t;
5071590Srgrimes
5081590Srgrimes	for (t = p + 1; *t; t++) {
5091590Srgrimes		if (!isdigit(*t))
51027953Scharnier			errx(1,
51127953Scharnier	"option %.1s requires a list of unsigned numbers separated by commas", t);
5121590Srgrimes		count++;
5131590Srgrimes		while (*t && isdigit(*t))
5141590Srgrimes			t++;
5151590Srgrimes		if (*t != ',')
5161590Srgrimes			break;
5171590Srgrimes	}
5181590Srgrimes	if (!(*list = (short *) malloc(count * sizeof(short))))
51927953Scharnier		errx(1, "no list space");
5201590Srgrimes	count = 0;
5211590Srgrimes	for (t = p + 1; *t; t++) {
5221590Srgrimes		(*list)[count++] = atoi(t);
5231590Srgrimes		printf("++ %d ", (*list)[count-1]);
5241590Srgrimes		fflush(stdout);
5251590Srgrimes		while (*t && isdigit(*t))
5261590Srgrimes			t++;
5271590Srgrimes		if (*t != ',')
5281590Srgrimes			break;
5291590Srgrimes	}
5301590Srgrimes	(*list)[count] = 0;
5311590Srgrimes	return(t - 1);
5321590Srgrimes}
5331590Srgrimes
5341590Srgrimeschar *
5351590Srgrimesgetnum(num, p, strict)	/* num = number p points to; if (strict) complain */
5361590Srgrimes	int *num, strict;	/* returns pointer to end of num */
5371590Srgrimes	char *p;
5381590Srgrimes{
5391590Srgrimes	register char *t = p;
5401590Srgrimes
5411590Srgrimes	if (!isdigit(*++t)) {
5421590Srgrimes		if (strict || *t == '-' || *t == '+')
54327953Scharnier			errx(1, "option %.1s requires an unsigned integer", p);
5441590Srgrimes		*num = 0;
5451590Srgrimes		return(p);
5461590Srgrimes	}
5471590Srgrimes	*num = atoi(t);
5481590Srgrimes	while (*++t)
5491590Srgrimes		if (!isdigit(*t))
5501590Srgrimes			break;
5511590Srgrimes	return(--t);
5521590Srgrimes}
553