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 * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3127953Scharnierstatic const char copyright[] =
321590Srgrimes"@(#) Copyright (c) 1993\n\
331590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
341590Srgrimes#endif /* not lint */
351590Srgrimes
361590Srgrimes#ifndef lint
3795618Smarkmstatic const char sccsid[] = "@(#)rs.c	8.1 (Berkeley) 6/6/93";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes/*
411590Srgrimes *	rs - reshape a data array
421590Srgrimes *	Author:  John Kunze, Office of Comp. Affairs, UCB
431590Srgrimes *		BEWARE: lots of unfinished edges
441590Srgrimes */
451590Srgrimes
4695618Smarkm#include <sys/cdefs.h>
4795618Smarkm__FBSDID("$FreeBSD$");
4895618Smarkm
4927953Scharnier#include <err.h>
501590Srgrimes#include <ctype.h>
51218411Sjh#include <limits.h>
521590Srgrimes#include <stdio.h>
531590Srgrimes#include <stdlib.h>
5433648Sjb#include <string.h>
551590Srgrimes
56227177Sedstatic long	flags;
571590Srgrimes#define	TRANSPOSE	000001
581590Srgrimes#define	MTRANSPOSE	000002
591590Srgrimes#define	ONEPERLINE	000004
601590Srgrimes#define	ONEISEPONLY	000010
611590Srgrimes#define	ONEOSEPONLY	000020
621590Srgrimes#define	NOTRIMENDCOL	000040
631590Srgrimes#define	SQUEEZE		000100
641590Srgrimes#define	SHAPEONLY	000200
651590Srgrimes#define	DETAILSHAPE	000400
661590Srgrimes#define	RIGHTADJUST	001000
671590Srgrimes#define	NULLPAD		002000
681590Srgrimes#define	RECYCLE		004000
691590Srgrimes#define	SKIPPRINT	010000
701590Srgrimes#define	ICOLBOUNDS	020000
711590Srgrimes#define	OCOLBOUNDS	040000
721590Srgrimes#define ONEPERCHAR	0100000
731590Srgrimes#define NOARGS		0200000
741590Srgrimes
75227177Sedstatic short	*colwidths;
76227177Sedstatic short	*cord;
77227177Sedstatic short	*icbd;
78227177Sedstatic short	*ocbd;
79227177Sedstatic int	nelem;
80227177Sedstatic char	**elem;
81227177Sedstatic char	**endelem;
82227177Sedstatic char	*curline;
83227177Sedstatic int	allocsize = BUFSIZ;
84227177Sedstatic int	curlen;
85227177Sedstatic int	irows, icols;
86227177Sedstatic int	orows = 0, ocols = 0;
87227177Sedstatic int	maxlen;
88227177Sedstatic int	skip;
89227177Sedstatic int	propgutter;
90227177Sedstatic char	isep = ' ', osep = ' ';
91227177Sedstatic char	blank[] = "";
92227177Sedstatic int	owidth = 80, gutter = 2;
931590Srgrimes
94227177Sedstatic void	  getargs(int, char *[]);
95227177Sedstatic void	  getfile(void);
96227177Sedstatic int	  getline(void);
97227177Sedstatic char	 *getlist(short **, char *);
98227177Sedstatic char	 *getnum(int *, char *, int);
99227177Sedstatic char	**getptrs(char **);
100227177Sedstatic void	  prepfile(void);
101227177Sedstatic void	  prints(char *, int);
102227177Sedstatic void	  putfile(void);
10392921Simpstatic void usage(void);
1041590Srgrimes
10583303Sru#define	INCR(ep) do {			\
10683303Sru	if (++ep >= endelem)		\
10783303Sru		ep = getptrs(ep);	\
10883303Sru} while(0)
10983303Sru
1101590Srgrimesint
11195618Smarkmmain(int argc, 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
124227177Sedstatic void
12595618Smarkmgetfile(void)
1261590Srgrimes{
12795618Smarkm	char *p;
12895618Smarkm	char *endp;
12983303Sru	char **ep;
130218410Sjh	int c;
1311590Srgrimes	int multisep = (flags & ONEISEPONLY ? 0 : 1);
1321590Srgrimes	int nullpad = flags & NULLPAD;
1331590Srgrimes	char **padto;
1341590Srgrimes
1351590Srgrimes	while (skip--) {
136218410Sjh		c = getline();
1371590Srgrimes		if (flags & SKIPPRINT)
1381590Srgrimes			puts(curline);
139218410Sjh		if (c == EOF)
140218410Sjh			return;
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	do {
1571590Srgrimes		if (flags & ONEPERLINE) {
15883303Sru			*ep = curline;
15983303Sru			INCR(ep);		/* prepare for next entry */
1601590Srgrimes			if (maxlen < curlen)
1611590Srgrimes				maxlen = curlen;
1621590Srgrimes			irows++;
1631590Srgrimes			continue;
1641590Srgrimes		}
1651590Srgrimes		for (p = curline, endp = curline + curlen; p < endp; p++) {
1661590Srgrimes			if (*p == isep && multisep)
1671590Srgrimes				continue;	/* eat up column separators */
1681590Srgrimes			if (*p == isep)		/* must be an empty column */
16995618Smarkm				*ep = blank;
1701590Srgrimes			else			/* store column entry */
1711590Srgrimes				*ep = p;
1721590Srgrimes			while (p < endp && *p != isep)
1731590Srgrimes				p++;		/* find end of entry */
1741590Srgrimes			*p = '\0';		/* mark end of entry */
1751590Srgrimes			if (maxlen < p - *ep)	/* update maxlen */
1761590Srgrimes				maxlen = p - *ep;
17783303Sru			INCR(ep);		/* prepare for next entry */
1781590Srgrimes		}
1791590Srgrimes		irows++;			/* update row count */
1801590Srgrimes		if (nullpad) {			/* pad missing entries */
1811590Srgrimes			padto = elem + irows * icols;
18283303Sru			while (ep < padto) {
18395618Smarkm				*ep = blank;
18483303Sru				INCR(ep);
18583303Sru			}
1861590Srgrimes		}
1871590Srgrimes	} while (getline() != EOF);
1881590Srgrimes	*ep = 0;				/* mark end of pointers */
1891590Srgrimes	nelem = ep - elem;
1901590Srgrimes}
1911590Srgrimes
192227177Sedstatic void
19395618Smarkmputfile(void)
1941590Srgrimes{
19595618Smarkm	char **ep;
19695618Smarkm	int i, j, k;
1971590Srgrimes
1981590Srgrimes	ep = elem;
1991590Srgrimes	if (flags & TRANSPOSE)
2001590Srgrimes		for (i = 0; i < orows; i++) {
2011590Srgrimes			for (j = i; j < nelem; j += orows)
2021590Srgrimes				prints(ep[j], (j - i) / orows);
2031590Srgrimes			putchar('\n');
2041590Srgrimes		}
2051590Srgrimes	else
20615909Sjoerg		for (i = k = 0; i < orows; i++) {
20715909Sjoerg			for (j = 0; j < ocols; j++, k++)
20815909Sjoerg				if (k < nelem)
20915909Sjoerg					prints(ep[k], j);
2101590Srgrimes			putchar('\n');
2111590Srgrimes		}
2121590Srgrimes}
2131590Srgrimes
214227177Sedstatic void
21595618Smarkmprints(char *s, int col)
2161590Srgrimes{
21795618Smarkm	int n;
21895618Smarkm	char *p = s;
2191590Srgrimes
2201590Srgrimes	while (*p)
2211590Srgrimes		p++;
2221590Srgrimes	n = (flags & ONEOSEPONLY ? 1 : colwidths[col] - (p - s));
2231590Srgrimes	if (flags & RIGHTADJUST)
2241590Srgrimes		while (n-- > 0)
2251590Srgrimes			putchar(osep);
2261590Srgrimes	for (p = s; *p; p++)
2271590Srgrimes		putchar(*p);
2281590Srgrimes	while (n-- > 0)
2291590Srgrimes		putchar(osep);
2301590Srgrimes}
2311590Srgrimes
23227953Scharnierstatic void
23395618Smarkmusage(void)
2341590Srgrimes{
2351590Srgrimes	fprintf(stderr,
23627953Scharnier		"usage: rs [-[csCS][x][kKgGw][N]tTeEnyjhHmz] [rows [cols]]\n");
2371590Srgrimes	exit(1);
2381590Srgrimes}
2391590Srgrimes
240227177Sedstatic void
24195618Smarkmprepfile(void)
2421590Srgrimes{
24395618Smarkm	char **ep;
24495618Smarkm	int  i;
24595618Smarkm	int  j;
2461590Srgrimes	char **lp;
2471590Srgrimes	int colw;
24883296Sru	int max;
2491590Srgrimes	int n;
2501590Srgrimes
2511590Srgrimes	if (!nelem)
2521590Srgrimes		exit(0);
2531590Srgrimes	gutter += maxlen * propgutter / 100.0;
2541590Srgrimes	colw = maxlen + gutter;
2551590Srgrimes	if (flags & MTRANSPOSE) {
2561590Srgrimes		orows = icols;
2571590Srgrimes		ocols = irows;
2581590Srgrimes	}
2591590Srgrimes	else if (orows == 0 && ocols == 0) {	/* decide rows and cols */
2601590Srgrimes		ocols = owidth / colw;
26183298Sru		if (ocols == 0) {
26227953Scharnier			warnx("display width %d is less than column width %d",
26327953Scharnier					owidth, colw);
26483298Sru			ocols = 1;
26583298Sru		}
2661590Srgrimes		if (ocols > nelem)
2671590Srgrimes			ocols = nelem;
2681590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2691590Srgrimes	}
2701590Srgrimes	else if (orows == 0)			/* decide on rows */
2711590Srgrimes		orows = nelem / ocols + (nelem % ocols ? 1 : 0);
2721590Srgrimes	else if (ocols == 0)			/* decide on cols */
2731590Srgrimes		ocols = nelem / orows + (nelem % orows ? 1 : 0);
2741590Srgrimes	lp = elem + orows * ocols;
2751590Srgrimes	while (lp > endelem) {
2761590Srgrimes		getptrs(elem + nelem);
2771590Srgrimes		lp = elem + orows * ocols;
2781590Srgrimes	}
2791590Srgrimes	if (flags & RECYCLE) {
2801590Srgrimes		for (ep = elem + nelem; ep < lp; ep++)
2811590Srgrimes			*ep = *(ep - nelem);
2821590Srgrimes		nelem = lp - elem;
2831590Srgrimes	}
2841590Srgrimes	if (!(colwidths = (short *) malloc(ocols * sizeof(short))))
28527953Scharnier		errx(1, "malloc");
2861590Srgrimes	if (flags & SQUEEZE) {
28783296Sru		ep = elem;
2881590Srgrimes		if (flags & TRANSPOSE)
28983296Sru			for (i = 0; i < ocols; i++) {
29083296Sru				max = 0;
29183296Sru				for (j = 0; *ep != NULL && j < orows; j++)
2921590Srgrimes					if ((n = strlen(*ep++)) > max)
2931590Srgrimes						max = n;
2941590Srgrimes				colwidths[i] = max + gutter;
2951590Srgrimes			}
2961590Srgrimes		else
2971590Srgrimes			for (i = 0; i < ocols; i++) {
29883296Sru				max = 0;
2991590Srgrimes				for (j = i; j < nelem; j += ocols)
3001590Srgrimes					if ((n = strlen(ep[j])) > max)
3011590Srgrimes						max = n;
3021590Srgrimes				colwidths[i] = max + gutter;
3031590Srgrimes			}
3041590Srgrimes	}
3051590Srgrimes	/*	for (i = 0; i < orows; i++) {
3061590Srgrimes			for (j = i; j < nelem; j += orows)
3071590Srgrimes				prints(ep[j], (j - i) / orows);
3081590Srgrimes			putchar('\n');
3091590Srgrimes		}
3101590Srgrimes	else
3111590Srgrimes		for (i = 0; i < orows; i++) {
3121590Srgrimes			for (j = 0; j < ocols; j++)
3131590Srgrimes				prints(*ep++, j);
3141590Srgrimes			putchar('\n');
3151590Srgrimes		}*/
3161590Srgrimes	else
3171590Srgrimes		for (i = 0; i < ocols; i++)
3181590Srgrimes			colwidths[i] = colw;
3191590Srgrimes	if (!(flags & NOTRIMENDCOL)) {
3201590Srgrimes		if (flags & RIGHTADJUST)
3211590Srgrimes			colwidths[0] -= gutter;
3221590Srgrimes		else
3231590Srgrimes			colwidths[ocols - 1] = 0;
3241590Srgrimes	}
3251590Srgrimes	n = orows * ocols;
3261590Srgrimes	if (n > nelem && (flags & RECYCLE))
3271590Srgrimes		nelem = n;
3281590Srgrimes	/*for (i = 0; i < ocols; i++)
32927953Scharnier		warnx("%d is colwidths, nelem %d", colwidths[i], nelem);*/
3301590Srgrimes}
3311590Srgrimes
332218411Sjh#define	BSIZE	(LINE_MAX * 2)
333227177Sedstatic char	ibuf[BSIZE];
3341590Srgrimes
335227177Sedstatic int
33695618Smarkmgetline(void)	/* get line; maintain curline, curlen; manage storage */
3371590Srgrimes{
3381590Srgrimes	static	int putlength;
3391590Srgrimes	static	char *endblock = ibuf + BSIZE;
34095618Smarkm	char *p;
34195618Smarkm	int c, i;
3421590Srgrimes
3431590Srgrimes	if (!irows) {
3441590Srgrimes		curline = ibuf;
3451590Srgrimes		putlength = flags & DETAILSHAPE;
3461590Srgrimes	}
3471590Srgrimes	else if (skip <= 0) {			/* don't waste storage */
3481590Srgrimes		curline += curlen + 1;
34998003Stjr		if (putlength) {	/* print length, recycle storage */
3501590Srgrimes			printf(" %d line %d\n", curlen, irows);
35198003Stjr			curline = ibuf;
35298003Stjr		}
3531590Srgrimes	}
354218411Sjh	if (!putlength && endblock - curline < LINE_MAX + 1) { /* need storage */
3551590Srgrimes		/*ww = endblock-curline; tt += ww;*/
3561590Srgrimes		/*printf("#wasted %d total %d\n",ww,tt);*/
3571590Srgrimes		if (!(curline = (char *) malloc(BSIZE)))
35827953Scharnier			errx(1, "file too large");
3591590Srgrimes		endblock = curline + BSIZE;
3601590Srgrimes		/*printf("#endb %d curline %d\n",endblock,curline);*/
3611590Srgrimes	}
362218411Sjh	for (p = curline, i = 0;; *p++ = c, i++) {
363218411Sjh		if ((c = getchar()) == EOF)
3641590Srgrimes			break;
365218411Sjh		if (i >= LINE_MAX)
366218411Sjh			errx(1, "maximum line length (%d) exceeded", LINE_MAX);
367218411Sjh		if (c == '\n')
368218411Sjh			break;
369218411Sjh	}
3701590Srgrimes	*p = '\0';
371218411Sjh	curlen = i;
3721590Srgrimes	return(c);
3731590Srgrimes}
3741590Srgrimes
375227177Sedstatic char **
37695618Smarkmgetptrs(char **sp)
3771590Srgrimes{
37883303Sru	char **p;
3791590Srgrimes
38083303Sru	allocsize += allocsize;
38183303Sru	p = (char **)realloc(elem, allocsize * sizeof(char *));
38283303Sru	if (p == NULL)
38383303Sru		err(1, "no memory");
38483303Sru
38583303Sru	sp += (p - elem);
38683303Sru	endelem = (elem = p) + allocsize;
38783303Sru	return(sp);
3881590Srgrimes}
3891590Srgrimes
390227177Sedstatic void
39195618Smarkmgetargs(int ac, char *av[])
3921590Srgrimes{
39395618Smarkm	char *p;
3941590Srgrimes
3951590Srgrimes	if (ac == 1) {
3961590Srgrimes		flags |= NOARGS | TRANSPOSE;
3971590Srgrimes	}
3981590Srgrimes	while (--ac && **++av == '-')
3991590Srgrimes		for (p = *av+1; *p; p++)
4001590Srgrimes			switch (*p) {
4011590Srgrimes			case 'T':
4021590Srgrimes				flags |= MTRANSPOSE;
4031590Srgrimes			case 't':
4041590Srgrimes				flags |= TRANSPOSE;
4051590Srgrimes				break;
4061590Srgrimes			case 'c':		/* input col. separator */
4071590Srgrimes				flags |= ONEISEPONLY;
4081590Srgrimes			case 's':		/* one or more allowed */
4091590Srgrimes				if (p[1])
4101590Srgrimes					isep = *++p;
4111590Srgrimes				else
4121590Srgrimes					isep = '\t';	/* default is ^I */
4131590Srgrimes				break;
4141590Srgrimes			case 'C':
4151590Srgrimes				flags |= ONEOSEPONLY;
4161590Srgrimes			case 'S':
4171590Srgrimes				if (p[1])
4181590Srgrimes					osep = *++p;
4191590Srgrimes				else
4201590Srgrimes					osep = '\t';	/* default is ^I */
4211590Srgrimes				break;
4221590Srgrimes			case 'w':		/* window width, default 80 */
4231590Srgrimes				p = getnum(&owidth, p, 0);
4241590Srgrimes				if (owidth <= 0)
42527953Scharnier					errx(1, "width must be a positive integer");
4261590Srgrimes				break;
4271590Srgrimes			case 'K':			/* skip N lines */
4281590Srgrimes				flags |= SKIPPRINT;
4291590Srgrimes			case 'k':			/* skip, do not print */
4301590Srgrimes				p = getnum(&skip, p, 0);
4311590Srgrimes				if (!skip)
4321590Srgrimes					skip = 1;
4331590Srgrimes				break;
4341590Srgrimes			case 'm':
4351590Srgrimes				flags |= NOTRIMENDCOL;
4361590Srgrimes				break;
4371590Srgrimes			case 'g':		/* gutter space */
4381590Srgrimes				p = getnum(&gutter, p, 0);
4391590Srgrimes				break;
4401590Srgrimes			case 'G':
4411590Srgrimes				p = getnum(&propgutter, p, 0);
4421590Srgrimes				break;
4431590Srgrimes			case 'e':		/* each line is an entry */
4441590Srgrimes				flags |= ONEPERLINE;
4451590Srgrimes				break;
4461590Srgrimes			case 'E':
4471590Srgrimes				flags |= ONEPERCHAR;
4481590Srgrimes				break;
4491590Srgrimes			case 'j':			/* right adjust */
4501590Srgrimes				flags |= RIGHTADJUST;
4511590Srgrimes				break;
4521590Srgrimes			case 'n':	/* null padding for missing values */
4531590Srgrimes				flags |= NULLPAD;
4541590Srgrimes				break;
4551590Srgrimes			case 'y':
4561590Srgrimes				flags |= RECYCLE;
4571590Srgrimes				break;
4581590Srgrimes			case 'H':			/* print shape only */
4591590Srgrimes				flags |= DETAILSHAPE;
4601590Srgrimes			case 'h':
4611590Srgrimes				flags |= SHAPEONLY;
4621590Srgrimes				break;
4631590Srgrimes			case 'z':			/* squeeze col width */
4641590Srgrimes				flags |= SQUEEZE;
4651590Srgrimes				break;
4661590Srgrimes			/*case 'p':
4671590Srgrimes				ipagespace = atoi(++p);	(default is 1)
4681590Srgrimes				break;*/
4691590Srgrimes			case 'o':			/* col order */
4701590Srgrimes				p = getlist(&cord, p);
4711590Srgrimes				break;
4721590Srgrimes			case 'b':
4731590Srgrimes				flags |= ICOLBOUNDS;
4741590Srgrimes				p = getlist(&icbd, p);
4751590Srgrimes				break;
4761590Srgrimes			case 'B':
4771590Srgrimes				flags |= OCOLBOUNDS;
4781590Srgrimes				p = getlist(&ocbd, p);
4791590Srgrimes				break;
4801590Srgrimes			default:
48127953Scharnier				usage();
4821590Srgrimes			}
4831590Srgrimes	/*if (!osep)
4841590Srgrimes		osep = isep;*/
4851590Srgrimes	switch (ac) {
4861590Srgrimes	/*case 3:
4871590Srgrimes		opages = atoi(av[2]);*/
4881590Srgrimes	case 2:
489145617Srobert		if ((ocols = atoi(av[1])) < 0)
490145617Srobert			ocols = 0;
4911590Srgrimes	case 1:
492145617Srobert		if ((orows = atoi(av[0])) < 0)
493145617Srobert			orows = 0;
4941590Srgrimes	case 0:
4951590Srgrimes		break;
4961590Srgrimes	default:
49727953Scharnier		errx(1, "too many arguments");
4981590Srgrimes	}
4991590Srgrimes}
5001590Srgrimes
501227177Sedstatic char *
50295618Smarkmgetlist(short **list, char *p)
5031590Srgrimes{
50495618Smarkm	int count = 1;
50595618Smarkm	char *t;
5061590Srgrimes
5071590Srgrimes	for (t = p + 1; *t; t++) {
508132205Stjr		if (!isdigit((unsigned char)*t))
50927953Scharnier			errx(1,
51027953Scharnier	"option %.1s requires a list of unsigned numbers separated by commas", t);
5111590Srgrimes		count++;
512132205Stjr		while (*t && isdigit((unsigned char)*t))
5131590Srgrimes			t++;
5141590Srgrimes		if (*t != ',')
5151590Srgrimes			break;
5161590Srgrimes	}
5171590Srgrimes	if (!(*list = (short *) malloc(count * sizeof(short))))
51827953Scharnier		errx(1, "no list space");
5191590Srgrimes	count = 0;
5201590Srgrimes	for (t = p + 1; *t; t++) {
5211590Srgrimes		(*list)[count++] = atoi(t);
5221590Srgrimes		printf("++ %d ", (*list)[count-1]);
5231590Srgrimes		fflush(stdout);
524132205Stjr		while (*t && isdigit((unsigned char)*t))
5251590Srgrimes			t++;
5261590Srgrimes		if (*t != ',')
5271590Srgrimes			break;
5281590Srgrimes	}
5291590Srgrimes	(*list)[count] = 0;
5301590Srgrimes	return(t - 1);
5311590Srgrimes}
5321590Srgrimes
53395618Smarkm/*
53495618Smarkm * num = number p points to; if (strict) complain
53595618Smarkm * returns pointer to end of num
53695618Smarkm */
537227177Sedstatic char *
53895618Smarkmgetnum(int *num, char *p, int strict)
5391590Srgrimes{
54095618Smarkm	char *t = p;
5411590Srgrimes
542132205Stjr	if (!isdigit((unsigned char)*++t)) {
5431590Srgrimes		if (strict || *t == '-' || *t == '+')
54427953Scharnier			errx(1, "option %.1s requires an unsigned integer", p);
5451590Srgrimes		*num = 0;
5461590Srgrimes		return(p);
5471590Srgrimes	}
5481590Srgrimes	*num = atoi(t);
5491590Srgrimes	while (*++t)
550132205Stjr		if (!isdigit((unsigned char)*t))
5511590Srgrimes			break;
5521590Srgrimes	return(--t);
5531590Srgrimes}
554