rs.c revision 98003
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
4195618Smarkmstatic const char sccsid[] = "@(#)rs.c	8.1 (Berkeley) 6/6/93";
421590Srgrimes#endif /* not lint */
431590Srgrimes
441590Srgrimes/*
451590Srgrimes *	rs - reshape a data array
461590Srgrimes *	Author:  John Kunze, Office of Comp. Affairs, UCB
471590Srgrimes *		BEWARE: lots of unfinished edges
481590Srgrimes */
491590Srgrimes
5095618Smarkm#include <sys/cdefs.h>
5195618Smarkm__FBSDID("$FreeBSD: head/usr.bin/rs/rs.c 98003 2002-06-07 07:08:06Z tjr $");
5295618Smarkm
5327953Scharnier#include <err.h>
541590Srgrimes#include <ctype.h>
551590Srgrimes#include <stdio.h>
561590Srgrimes#include <stdlib.h>
5733648Sjb#include <string.h>
581590Srgrimes
591590Srgrimeslong	flags;
601590Srgrimes#define	TRANSPOSE	000001
611590Srgrimes#define	MTRANSPOSE	000002
621590Srgrimes#define	ONEPERLINE	000004
631590Srgrimes#define	ONEISEPONLY	000010
641590Srgrimes#define	ONEOSEPONLY	000020
651590Srgrimes#define	NOTRIMENDCOL	000040
661590Srgrimes#define	SQUEEZE		000100
671590Srgrimes#define	SHAPEONLY	000200
681590Srgrimes#define	DETAILSHAPE	000400
691590Srgrimes#define	RIGHTADJUST	001000
701590Srgrimes#define	NULLPAD		002000
711590Srgrimes#define	RECYCLE		004000
721590Srgrimes#define	SKIPPRINT	010000
731590Srgrimes#define	ICOLBOUNDS	020000
741590Srgrimes#define	OCOLBOUNDS	040000
751590Srgrimes#define ONEPERCHAR	0100000
761590Srgrimes#define NOARGS		0200000
771590Srgrimes
781590Srgrimesshort	*colwidths;
791590Srgrimesshort	*cord;
801590Srgrimesshort	*icbd;
811590Srgrimesshort	*ocbd;
821590Srgrimesint	nelem;
831590Srgrimeschar	**elem;
841590Srgrimeschar	**endelem;
851590Srgrimeschar	*curline;
861590Srgrimesint	allocsize = BUFSIZ;
871590Srgrimesint	curlen;
881590Srgrimesint	irows, icols;
891590Srgrimesint	orows, ocols;
901590Srgrimesint	maxlen;
911590Srgrimesint	skip;
921590Srgrimesint	propgutter;
931590Srgrimeschar	isep = ' ', osep = ' ';
9495618Smarkmchar	blank[] = "";
951590Srgrimesint	owidth = 80, gutter = 2;
961590Srgrimes
9792921Simpvoid	  getargs(int, char *[]);
9892921Simpvoid	  getfile(void);
9992921Simpint	  getline(void);
10092921Simpchar	 *getlist(short **, char *);
10192921Simpchar	 *getnum(int *, char *, int);
10292921Simpchar	**getptrs(char **);
10392921Simpvoid	  prepfile(void);
10492921Simpvoid	  prints(char *, int);
10592921Simpvoid	  putfile(void);
10692921Simpstatic void usage(void);
1071590Srgrimes
10883303Sru#define	INCR(ep) do {			\
10983303Sru	if (++ep >= endelem)		\
11083303Sru		ep = getptrs(ep);	\
11183303Sru} while(0)
11283303Sru
1131590Srgrimesint
11495618Smarkmmain(int argc, char *argv[])
1151590Srgrimes{
1161590Srgrimes	getargs(argc, argv);
1171590Srgrimes	getfile();
1181590Srgrimes	if (flags & SHAPEONLY) {
1191590Srgrimes		printf("%d %d\n", irows, icols);
1201590Srgrimes		exit(0);
1211590Srgrimes	}
1221590Srgrimes	prepfile();
1231590Srgrimes	putfile();
1241590Srgrimes	exit(0);
1251590Srgrimes}
1261590Srgrimes
1271590Srgrimesvoid
12895618Smarkmgetfile(void)
1291590Srgrimes{
13095618Smarkm	char *p;
13195618Smarkm	char *endp;
13283303Sru	char **ep;
1331590Srgrimes	int multisep = (flags & ONEISEPONLY ? 0 : 1);
1341590Srgrimes	int nullpad = flags & NULLPAD;
1351590Srgrimes	char **padto;
1361590Srgrimes
1371590Srgrimes	while (skip--) {
1381590Srgrimes		getline();
1391590Srgrimes		if (flags & SKIPPRINT)
1401590Srgrimes			puts(curline);
1411590Srgrimes	}
1421590Srgrimes	getline();
1431590Srgrimes	if (flags & NOARGS && curlen < owidth)
1441590Srgrimes		flags |= ONEPERLINE;
1451590Srgrimes	if (flags & ONEPERLINE)
1461590Srgrimes		icols = 1;
1471590Srgrimes	else				/* count cols on first line */
1481590Srgrimes		for (p = curline, endp = curline + curlen; p < endp; p++) {
1491590Srgrimes			if (*p == isep && multisep)
1501590Srgrimes				continue;
1511590Srgrimes			icols++;
1521590Srgrimes			while (*p && *p != isep)
1531590Srgrimes				p++;
1541590Srgrimes		}
1551590Srgrimes	ep = getptrs(elem);
1561590Srgrimes	p = curline;
1571590Srgrimes	do {
1581590Srgrimes		if (flags & ONEPERLINE) {
15983303Sru			*ep = curline;
16083303Sru			INCR(ep);		/* prepare for next entry */
1611590Srgrimes			if (maxlen < curlen)
1621590Srgrimes				maxlen = curlen;
1631590Srgrimes			irows++;
1641590Srgrimes			continue;
1651590Srgrimes		}
1661590Srgrimes		for (p = curline, endp = curline + curlen; p < endp; p++) {
1671590Srgrimes			if (*p == isep && multisep)
1681590Srgrimes				continue;	/* eat up column separators */
1691590Srgrimes			if (*p == isep)		/* must be an empty column */
17095618Smarkm				*ep = blank;
1711590Srgrimes			else			/* store column entry */
1721590Srgrimes				*ep = p;
1731590Srgrimes			while (p < endp && *p != isep)
1741590Srgrimes				p++;		/* find end of entry */
1751590Srgrimes			*p = '\0';		/* mark end of entry */
1761590Srgrimes			if (maxlen < p - *ep)	/* update maxlen */
1771590Srgrimes				maxlen = p - *ep;
17883303Sru			INCR(ep);		/* prepare for next entry */
1791590Srgrimes		}
1801590Srgrimes		irows++;			/* update row count */
1811590Srgrimes		if (nullpad) {			/* pad missing entries */
1821590Srgrimes			padto = elem + irows * icols;
18383303Sru			while (ep < padto) {
18495618Smarkm				*ep = blank;
18583303Sru				INCR(ep);
18683303Sru			}
1871590Srgrimes		}
1881590Srgrimes	} while (getline() != EOF);
1891590Srgrimes	*ep = 0;				/* mark end of pointers */
1901590Srgrimes	nelem = ep - elem;
1911590Srgrimes}
1921590Srgrimes
1931590Srgrimesvoid
19495618Smarkmputfile(void)
1951590Srgrimes{
19695618Smarkm	char **ep;
19795618Smarkm	int i, j, k;
1981590Srgrimes
1991590Srgrimes	ep = elem;
2001590Srgrimes	if (flags & TRANSPOSE)
2011590Srgrimes		for (i = 0; i < orows; i++) {
2021590Srgrimes			for (j = i; j < nelem; j += orows)
2031590Srgrimes				prints(ep[j], (j - i) / orows);
2041590Srgrimes			putchar('\n');
2051590Srgrimes		}
2061590Srgrimes	else
20715909Sjoerg		for (i = k = 0; i < orows; i++) {
20815909Sjoerg			for (j = 0; j < ocols; j++, k++)
20915909Sjoerg				if (k < nelem)
21015909Sjoerg					prints(ep[k], j);
2111590Srgrimes			putchar('\n');
2121590Srgrimes		}
2131590Srgrimes}
2141590Srgrimes
2151590Srgrimesvoid
21695618Smarkmprints(char *s, int col)
2171590Srgrimes{
21895618Smarkm	int n;
21995618Smarkm	char *p = s;
2201590Srgrimes
2211590Srgrimes	while (*p)
2221590Srgrimes		p++;
2231590Srgrimes	n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
2241590Srgrimes	if (flags & RIGHTADJUST)
2251590Srgrimes		while (n-- > 0)
2261590Srgrimes			putchar(osep);
2271590Srgrimes	for (p = s; *p; p++)
2281590Srgrimes		putchar(*p);
2291590Srgrimes	while (n-- > 0)
2301590Srgrimes		putchar(osep);
2311590Srgrimes}
2321590Srgrimes
23327953Scharnierstatic void
23495618Smarkmusage(void)
2351590Srgrimes{
2361590Srgrimes	fprintf(stderr,
23727953Scharnier		"usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
2381590Srgrimes	exit(1);
2391590Srgrimes}
2401590Srgrimes
2411590Srgrimesvoid
24295618Smarkmprepfile(void)
2431590Srgrimes{
24495618Smarkm	char **ep;
24595618Smarkm	int  i;
24695618Smarkm	int  j;
2471590Srgrimes	char **lp;
2481590Srgrimes	int colw;
24983296Sru	int max;
2501590Srgrimes	int n;
2511590Srgrimes
2521590Srgrimes	if (!nelem)
2531590Srgrimes		exit(0);
2541590Srgrimes	gutter += maxlen * propgutter / 100.0;
2551590Srgrimes	colw = maxlen + gutter;
2561590Srgrimes	if (flags & MTRANSPOSE) {
2571590Srgrimes		orows = icols;
2581590Srgrimes		ocols = irows;
2591590Srgrimes	}
2601590Srgrimes	else if (orows == 0 && ocols == 0) {	/* decide rows and cols */
2611590Srgrimes		ocols = owidth / colw;
26283298Sru		if (ocols == 0) {
26327953Scharnier			warnx("display width %d is less than column width %d",
26427953Scharnier					owidth, colw);
26583298Sru			ocols = 1;
26683298Sru		}
2671590Srgrimes		if (ocols > nelem)
2681590Srgrimes			ocols = nelem;
2691590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2701590Srgrimes	}
2711590Srgrimes	else if (orows == 0)			/* decide on rows */
2721590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2731590Srgrimes	else if (ocols == 0)			/* decide on cols */
2741590Srgrimes		ocols = nelem / orows + (nelem % orows ? 1 : 0);
2751590Srgrimes	lp = elem + orows * ocols;
2761590Srgrimes	while (lp > endelem) {
2771590Srgrimes		getptrs(elem + nelem);
2781590Srgrimes		lp = elem + orows * ocols;
2791590Srgrimes	}
2801590Srgrimes	if (flags & RECYCLE) {
2811590Srgrimes		for (ep = elem + nelem; ep < lp; ep++)
2821590Srgrimes			*ep = *(ep - nelem);
2831590Srgrimes		nelem = lp - elem;
2841590Srgrimes	}
2851590Srgrimes	if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
28627953Scharnier		errx(1, "malloc");
2871590Srgrimes	if (flags & SQUEEZE) {
28883296Sru		ep = elem;
2891590Srgrimes		if (flags & TRANSPOSE)
29083296Sru			for (i = 0; i < ocols; i++) {
29183296Sru				max = 0;
29283296Sru				for (j = 0; *ep != NULL && j < orows; j++)
2931590Srgrimes					if ((n = strlen(*ep++)) > max)
2941590Srgrimes						max = n;
2951590Srgrimes				colwidths[i] = max + gutter;
2961590Srgrimes			}
2971590Srgrimes		else
2981590Srgrimes			for (i = 0; i < ocols; i++) {
29983296Sru				max = 0;
3001590Srgrimes				for (j = i; j < nelem; j += ocols)
3011590Srgrimes					if ((n = strlen(ep[j])) > max)
3021590Srgrimes						max = n;
3031590Srgrimes				colwidths[i] = max + gutter;
3041590Srgrimes			}
3051590Srgrimes	}
3061590Srgrimes	/*	for (i = 0; i < orows; i++) {
3071590Srgrimes			for (j = i; j < nelem; j += orows)
3081590Srgrimes				prints(ep[j], (j - i) / orows);
3091590Srgrimes			putchar('\n');
3101590Srgrimes		}
3111590Srgrimes	else
3121590Srgrimes		for (i = 0; i < orows; i++) {
3131590Srgrimes			for (j = 0; j < ocols; j++)
3141590Srgrimes				prints(*ep++, j);
3151590Srgrimes			putchar('\n');
3161590Srgrimes		}*/
3171590Srgrimes	else
3181590Srgrimes		for (i = 0; i < ocols; i++)
3191590Srgrimes			colwidths[i] = colw;
3201590Srgrimes	if (!(flags & NOTRIMENDCOL)) {
3211590Srgrimes		if (flags & RIGHTADJUST)
3221590Srgrimes			colwidths[0] -= gutter;
3231590Srgrimes		else
3241590Srgrimes			colwidths[ocols - 1] = 0;
3251590Srgrimes	}
3261590Srgrimes	n = orows * ocols;
3271590Srgrimes	if (n > nelem && (flags & RECYCLE))
3281590Srgrimes		nelem = n;
3291590Srgrimes	/*for (i = 0; i < ocols; i++)
33027953Scharnier		warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/
3311590Srgrimes}
3321590Srgrimes
3331590Srgrimes#define	BSIZE	2048
3341590Srgrimeschar	ibuf[BSIZE];		/* two screenfuls should do */
3351590Srgrimes
3361590Srgrimesint
33795618Smarkmgetline(void)	/* get line; maintain curline, curlen; manage storage */
3381590Srgrimes{
3391590Srgrimes	static	int putlength;
3401590Srgrimes	static	char *endblock = ibuf + BSIZE;
34195618Smarkm	char *p;
34295618Smarkm	int c, i;
3431590Srgrimes
3441590Srgrimes	if (!irows) {
3451590Srgrimes		curline = ibuf;
3461590Srgrimes		putlength = flags & DETAILSHAPE;
3471590Srgrimes	}
3481590Srgrimes	else if (skip <= 0) {			/* don't waste storage */
3491590Srgrimes		curline += curlen + 1;
35098003Stjr		if (putlength) {	/* print length, recycle storage */
3511590Srgrimes			printf(" %d line %d\n", curlen, irows);
35298003Stjr			curline = ibuf;
35398003Stjr		}
3541590Srgrimes	}
3551590Srgrimes	if (!putlength && endblock - curline < BUFSIZ) {   /* need storage */
3561590Srgrimes		/*ww = endblock-curline; tt += ww;*/
3571590Srgrimes		/*printf("#wasted %d total %d\n",ww,tt);*/
3581590Srgrimes		if (!(curline = (char *) malloc(BSIZE)))
35927953Scharnier			errx(1, "file too large");
3601590Srgrimes		endblock = curline + BSIZE;
3611590Srgrimes		/*printf("#endb %d curline %d\n",endblock,curline);*/
3621590Srgrimes	}
3631590Srgrimes	for (p = curline, i = 1; i < BUFSIZ; *p++ = c, i++)
3641590Srgrimes		if ((c = getchar()) == EOF || c == '\n')
3651590Srgrimes			break;
3661590Srgrimes	*p = '\0';
3671590Srgrimes	curlen = i - 1;
3681590Srgrimes	return(c);
3691590Srgrimes}
3701590Srgrimes
3711590Srgrimeschar **
37295618Smarkmgetptrs(char **sp)
3731590Srgrimes{
37483303Sru	char **p;
3751590Srgrimes
37683303Sru	allocsize += allocsize;
37783303Sru	p = (char **)realloc(elem, allocsize * sizeof(char *));
37883303Sru	if (p == NULL)
37983303Sru		err(1, "no memory");
38083303Sru
38183303Sru	sp += (p - elem);
38283303Sru	endelem = (elem = p) + allocsize;
38383303Sru	return(sp);
3841590Srgrimes}
3851590Srgrimes
3861590Srgrimesvoid
38795618Smarkmgetargs(int ac, char *av[])
3881590Srgrimes{
38995618Smarkm	char *p;
3901590Srgrimes
3911590Srgrimes	if (ac == 1) {
3921590Srgrimes		flags |= NOARGS | TRANSPOSE;
3931590Srgrimes	}
3941590Srgrimes	while (--ac && **++av == '-')
3951590Srgrimes		for (p = *av+1; *p; p++)
3961590Srgrimes			switch (*p) {
3971590Srgrimes			case 'T':
3981590Srgrimes				flags |= MTRANSPOSE;
3991590Srgrimes			case 't':
4001590Srgrimes				flags |= TRANSPOSE;
4011590Srgrimes				break;
4021590Srgrimes			case 'c':		/* input col. separator */
4031590Srgrimes				flags |= ONEISEPONLY;
4041590Srgrimes			case 's':		/* one or more allowed */
4051590Srgrimes				if (p[1])
4061590Srgrimes					isep = *++p;
4071590Srgrimes				else
4081590Srgrimes					isep = '\t';	/* default is ^I */
4091590Srgrimes				break;
4101590Srgrimes			case 'C':
4111590Srgrimes				flags |= ONEOSEPONLY;
4121590Srgrimes			case 'S':
4131590Srgrimes				if (p[1])
4141590Srgrimes					osep = *++p;
4151590Srgrimes				else
4161590Srgrimes					osep = '\t';	/* default is ^I */
4171590Srgrimes				break;
4181590Srgrimes			case 'w':		/* window width, default 80 */
4191590Srgrimes				p = getnum(&owidth, p, 0);
4201590Srgrimes				if (owidth <= 0)
42127953Scharnier					errx(1, "width must be a positive integer");
4221590Srgrimes				break;
4231590Srgrimes			case 'K':			/* skip N lines */
4241590Srgrimes				flags |= SKIPPRINT;
4251590Srgrimes			case 'k':			/* skip, do not print */
4261590Srgrimes				p = getnum(&skip, p, 0);
4271590Srgrimes				if (!skip)
4281590Srgrimes					skip = 1;
4291590Srgrimes				break;
4301590Srgrimes			case 'm':
4311590Srgrimes				flags |= NOTRIMENDCOL;
4321590Srgrimes				break;
4331590Srgrimes			case 'g':		/* gutter space */
4341590Srgrimes				p = getnum(&gutter, p, 0);
4351590Srgrimes				break;
4361590Srgrimes			case 'G':
4371590Srgrimes				p = getnum(&propgutter, p, 0);
4381590Srgrimes				break;
4391590Srgrimes			case 'e':		/* each line is an entry */
4401590Srgrimes				flags |= ONEPERLINE;
4411590Srgrimes				break;
4421590Srgrimes			case 'E':
4431590Srgrimes				flags |= ONEPERCHAR;
4441590Srgrimes				break;
4451590Srgrimes			case 'j':			/* right adjust */
4461590Srgrimes				flags |= RIGHTADJUST;
4471590Srgrimes				break;
4481590Srgrimes			case 'n':	/* null padding for missing values */
4491590Srgrimes				flags |= NULLPAD;
4501590Srgrimes				break;
4511590Srgrimes			case 'y':
4521590Srgrimes				flags |= RECYCLE;
4531590Srgrimes				break;
4541590Srgrimes			case 'H':			/* print shape only */
4551590Srgrimes				flags |= DETAILSHAPE;
4561590Srgrimes			case 'h':
4571590Srgrimes				flags |= SHAPEONLY;
4581590Srgrimes				break;
4591590Srgrimes			case 'z':			/* squeeze col width */
4601590Srgrimes				flags |= SQUEEZE;
4611590Srgrimes				break;
4621590Srgrimes			/*case 'p':
4631590Srgrimes				ipagespace = atoi(++p);	(default is 1)
4641590Srgrimes				break;*/
4651590Srgrimes			case 'o':			/* col order */
4661590Srgrimes				p = getlist(&cord, p);
4671590Srgrimes				break;
4681590Srgrimes			case 'b':
4691590Srgrimes				flags |= ICOLBOUNDS;
4701590Srgrimes				p = getlist(&icbd, p);
4711590Srgrimes				break;
4721590Srgrimes			case 'B':
4731590Srgrimes				flags |= OCOLBOUNDS;
4741590Srgrimes				p = getlist(&ocbd, p);
4751590Srgrimes				break;
4761590Srgrimes			default:
47727953Scharnier				usage();
4781590Srgrimes			}
4791590Srgrimes	/*if (!osep)
4801590Srgrimes		osep = isep;*/
4811590Srgrimes	switch (ac) {
4821590Srgrimes	/*case 3:
4831590Srgrimes		opages = atoi(av[2]);*/
4841590Srgrimes	case 2:
4851590Srgrimes		ocols = atoi(av[1]);
4861590Srgrimes	case 1:
4871590Srgrimes		orows = atoi(av[0]);
4881590Srgrimes	case 0:
4891590Srgrimes		break;
4901590Srgrimes	default:
49127953Scharnier		errx(1, "too many arguments");
4921590Srgrimes	}
4931590Srgrimes}
4941590Srgrimes
4951590Srgrimeschar *
49695618Smarkmgetlist(short **list, char *p)
4971590Srgrimes{
49895618Smarkm	int count = 1;
49995618Smarkm	char *t;
5001590Srgrimes
5011590Srgrimes	for (t = p + 1; *t; t++) {
5021590Srgrimes		if (!isdigit(*t))
50327953Scharnier			errx(1,
50427953Scharnier	"option %.1s requires a list of unsigned numbers separated by commas", t);
5051590Srgrimes		count++;
5061590Srgrimes		while (*t && isdigit(*t))
5071590Srgrimes			t++;
5081590Srgrimes		if (*t != ',')
5091590Srgrimes			break;
5101590Srgrimes	}
5111590Srgrimes	if (!(*list = (short *) malloc(count * sizeof(short))))
51227953Scharnier		errx(1, "no list space");
5131590Srgrimes	count = 0;
5141590Srgrimes	for (t = p + 1; *t; t++) {
5151590Srgrimes		(*list)[count++] = atoi(t);
5161590Srgrimes		printf("++ %d ", (*list)[count-1]);
5171590Srgrimes		fflush(stdout);
5181590Srgrimes		while (*t && isdigit(*t))
5191590Srgrimes			t++;
5201590Srgrimes		if (*t != ',')
5211590Srgrimes			break;
5221590Srgrimes	}
5231590Srgrimes	(*list)[count] = 0;
5241590Srgrimes	return(t - 1);
5251590Srgrimes}
5261590Srgrimes
52795618Smarkm/*
52895618Smarkm * num = number p points to; if (strict) complain
52995618Smarkm * returns pointer to end of num
53095618Smarkm */
5311590Srgrimeschar *
53295618Smarkmgetnum(int *num, char *p, int strict)
5331590Srgrimes{
53495618Smarkm	char *t = p;
5351590Srgrimes
5361590Srgrimes	if (!isdigit(*++t)) {
5371590Srgrimes		if (strict || *t == '-' || *t == '+')
53827953Scharnier			errx(1, "option %.1s requires an unsigned integer", p);
5391590Srgrimes		*num = 0;
5401590Srgrimes		return(p);
5411590Srgrimes	}
5421590Srgrimes	*num = atoi(t);
5431590Srgrimes	while (*++t)
5441590Srgrimes		if (!isdigit(*t))
5451590Srgrimes			break;
5461590Srgrimes	return(--t);
5471590Srgrimes}
548