xref: /csrg-svn/usr.bin/jot/jot.c (revision 62040)
160455Sbostic /*-
2*62040Sbostic  * Copyright (c) 1993
3*62040Sbostic  *	The Regents of the University of California.  All rights reserved.
460455Sbostic  *
560455Sbostic  * %sccs.include.redist.c%
660455Sbostic  */
713848Ssam 
813848Ssam #ifndef lint
9*62040Sbostic static char copyright[] =
10*62040Sbostic "@(#) Copyright (c) 1993\n\
11*62040Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1260455Sbostic #endif /* not lint */
1313848Ssam 
1460455Sbostic #ifndef lint
15*62040Sbostic static char sccsid[] = "@(#)jot.c	8.1 (Berkeley) 06/06/93";
1660455Sbostic #endif /* not lint */
1760455Sbostic 
1813848Ssam /*
1960455Sbostic  * jot - print sequential or random data
2060455Sbostic  *
2160455Sbostic  * Author:  John Kunze, Office of Comp. Affairs, UCB
2213848Ssam  */
2313848Ssam 
2460455Sbostic #include <ctype.h>
2560455Sbostic #include <limits.h>
2613848Ssam #include <stdio.h>
2760455Sbostic #include <stdlib.h>
2860455Sbostic #include <string.h>
2960455Sbostic #include <time.h>
3013848Ssam 
3113848Ssam #define	REPS_DEF	100
3213848Ssam #define	BEGIN_DEF	1
3313848Ssam #define	ENDER_DEF	100
3413848Ssam #define	STEP_DEF	1
3513848Ssam 
3613848Ssam #define	isdefault(s)	(strcmp((s), "-") == 0)
3713848Ssam 
3860455Sbostic double	begin;
3960455Sbostic double	ender;
4060455Sbostic double	s;
4160455Sbostic long	reps;
4213848Ssam int	randomize;
4313848Ssam int	infinity;
4413848Ssam int	boring;
4513848Ssam int	prec;
4613848Ssam int	dox;
4713848Ssam int	chardata;
4818503Sjak int	nofinalnl;
4960455Sbostic char	*sepstring = "\n";
5060455Sbostic char	format[BUFSIZ];
5113848Ssam 
5260455Sbostic void	error __P((char *, char *));
5360455Sbostic void	getargs __P((int, char *[]));
5460455Sbostic void	getformat __P((void));
5560455Sbostic int	getprec __P((char *));
5660455Sbostic void	putdata __P((double, long));
5713848Ssam 
5860455Sbostic int
main(argc,argv)5913848Ssam main(argc, argv)
6060455Sbostic 	int argc;
6160455Sbostic 	char *argv[];
6213848Ssam {
6313848Ssam 	double	xd, yd;
6413848Ssam 	long	id;
6513848Ssam 	register double	*x = &xd;
6613848Ssam 	register double	*y = &yd;
6713848Ssam 	register long	*i = &id;
6813848Ssam 
6913848Ssam 	getargs(argc, argv);
7013848Ssam 	if (randomize) {
7113848Ssam 		*x = (ender - begin) * (ender > begin ? 1 : -1);
7260455Sbostic 		srandom((int) s);
7313848Ssam 		for (*i = 1; *i <= reps || infinity; (*i)++) {
7460455Sbostic 			*y = (double) random() / INT_MAX;
7513848Ssam 			putdata(*y * *x + begin, reps - *i);
7613848Ssam 		}
7713848Ssam 	}
7813848Ssam 	else
7913848Ssam 		for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
8013848Ssam 			putdata(*x, reps - *i);
8118503Sjak 	if (!nofinalnl)
8218503Sjak 		putchar('\n');
8327015Slepreau 	exit(0);
8413848Ssam }
8513848Ssam 
8660455Sbostic void
getargs(ac,av)8713848Ssam getargs(ac, av)
8860455Sbostic 	int ac;
8960455Sbostic 	char *av[];
9013848Ssam {
9113848Ssam 	register unsigned int	mask = 0;
9213848Ssam 	register int		n = 0;
9313848Ssam 
9413848Ssam 	while (--ac && **++av == '-' && !isdefault(*av))
9513848Ssam 		switch ((*av)[1]) {
9613848Ssam 		case 'r':
9713848Ssam 			randomize = 1;
9813848Ssam 			break;
9913848Ssam 		case 'c':
10013848Ssam 			chardata = 1;
10113848Ssam 			break;
10218503Sjak 		case 'n':
10318503Sjak 			nofinalnl = 1;
10418503Sjak 			break;
10513848Ssam 		case 'b':
10613848Ssam 			boring = 1;
10713848Ssam 		case 'w':
10813848Ssam 			if ((*av)[2])
10913848Ssam 				strcpy(format, *av + 2);
11013848Ssam 			else if (!--ac)
11113848Ssam 				error("Need context word after -w or -b", "");
11213848Ssam 			else
11313848Ssam 				strcpy(format, *++av);
11413848Ssam 			break;
11513848Ssam 		case 's':
11613848Ssam 			if ((*av)[2])
11713848Ssam 				strcpy(sepstring, *av + 2);
11813848Ssam 			else if (!--ac)
11913848Ssam 				error("Need string after -s", "");
12013848Ssam 			else
12113848Ssam 				strcpy(sepstring, *++av);
12213848Ssam 			break;
12313848Ssam 		case 'p':
12413848Ssam 			if ((*av)[2])
12513848Ssam 				prec = atoi(*av + 2);
12613848Ssam 			else if (!--ac)
12713848Ssam 				error("Need number after -p", "");
12813848Ssam 			else
12913848Ssam 				prec = atoi(*++av);
13013848Ssam 			if (prec <= 0)
13113848Ssam 				error("Bad precision value", "");
13213848Ssam 			break;
13313848Ssam 		default:
13413848Ssam 			error("Unknown option %s", *av);
13513848Ssam 		}
13660455Sbostic 
13713848Ssam 	switch (ac) {	/* examine args right to left, falling thru cases */
13813848Ssam 	case 4:
13913848Ssam 		if (!isdefault(av[3])) {
14060455Sbostic 			if (!sscanf(av[3], "%lf", &s))
14113848Ssam 				error("Bad s value:  %s", av[3]);
14213848Ssam 			mask |= 01;
14313848Ssam 		}
14413848Ssam 	case 3:
14513848Ssam 		if (!isdefault(av[2])) {
14660455Sbostic 			if (!sscanf(av[2], "%lf", &ender))
14713848Ssam 				ender = av[2][strlen(av[2])-1];
14813848Ssam 			mask |= 02;
14913848Ssam 			if (!prec)
15013848Ssam 				n = getprec(av[2]);
15113848Ssam 		}
15213848Ssam 	case 2:
15313848Ssam 		if (!isdefault(av[1])) {
15460455Sbostic 			if (!sscanf(av[1], "%lf", &begin))
15513848Ssam 				begin = av[1][strlen(av[1])-1];
15613848Ssam 			mask |= 04;
15713848Ssam 			if (!prec)
15813848Ssam 				prec = getprec(av[1]);
15913848Ssam 			if (n > prec)		/* maximum precision */
16013848Ssam 				prec = n;
16113848Ssam 		}
16213848Ssam 	case 1:
16313848Ssam 		if (!isdefault(av[0])) {
16460455Sbostic 			if (!sscanf(av[0], "%ld", &reps))
16513848Ssam 				error("Bad reps value:  %s", av[0]);
16613848Ssam 			mask |= 010;
16713848Ssam 		}
16813848Ssam 		break;
16913848Ssam 	case 0:
17013848Ssam 		error("jot - print sequential or random data", "");
17113848Ssam 	default:
17213848Ssam 		error("Too many arguments.  What do you mean by %s?", av[4]);
17313848Ssam 	}
17413848Ssam 	getformat();
17513848Ssam 	while (mask)	/* 4 bit mask has 1's where last 4 args were given */
17613848Ssam 		switch (mask) {	/* fill in the 0's by default or computation */
17760455Sbostic 		case 001:
17813848Ssam 			reps = REPS_DEF;
17913848Ssam 			mask = 011;
18060455Sbostic 			break;
18160455Sbostic 		case 002:
18213848Ssam 			reps = REPS_DEF;
18313848Ssam 			mask = 012;
18460455Sbostic 			break;
18560455Sbostic 		case 003:
18613848Ssam 			reps = REPS_DEF;
18713848Ssam 			mask = 013;
18860455Sbostic 			break;
18960455Sbostic 		case 004:
19013848Ssam 			reps = REPS_DEF;
19113848Ssam 			mask = 014;
19260455Sbostic 			break;
19360455Sbostic 		case 005:
19413848Ssam 			reps = REPS_DEF;
19513848Ssam 			mask = 015;
19660455Sbostic 			break;
19760455Sbostic 		case 006:
19813848Ssam 			reps = REPS_DEF;
19913848Ssam 			mask = 016;
20060455Sbostic 			break;
20160455Sbostic 		case 007:
20213848Ssam 			if (randomize) {
20313848Ssam 				reps = REPS_DEF;
20413848Ssam 				mask = 0;
20513848Ssam 				break;
20613848Ssam 			}
20713848Ssam 			if (s == 0.0) {
20813848Ssam 				reps = 0;
20913848Ssam 				mask = 0;
21013848Ssam 				break;
21113848Ssam 			}
21213848Ssam 			reps = (ender - begin + s) / s;
21313848Ssam 			if (reps <= 0)
21413848Ssam 				error("Impossible stepsize", "");
21513848Ssam 			mask = 0;
21660455Sbostic 			break;
21760455Sbostic 		case 010:
21813848Ssam 			begin = BEGIN_DEF;
21913848Ssam 			mask = 014;
22060455Sbostic 			break;
22160455Sbostic 		case 011:
22213848Ssam 			begin = BEGIN_DEF;
22313848Ssam 			mask = 015;
22460455Sbostic 			break;
22560455Sbostic 		case 012:
22613848Ssam 			s = (randomize ? time(0) : STEP_DEF);
22713848Ssam 			mask = 013;
22860455Sbostic 			break;
22960455Sbostic 		case 013:
23013848Ssam 			if (randomize)
23113848Ssam 				begin = BEGIN_DEF;
23213848Ssam 			else if (reps == 0)
23313848Ssam 				error("Must specify begin if reps == 0", "");
23413848Ssam 			begin = ender - reps * s + s;
23513848Ssam 			mask = 0;
23660455Sbostic 			break;
23760455Sbostic 		case 014:
23813848Ssam 			s = (randomize ? time(0) : STEP_DEF);
23913848Ssam 			mask = 015;
24060455Sbostic 			break;
24160455Sbostic 		case 015:
24213848Ssam 			if (randomize)
24313848Ssam 				ender = ENDER_DEF;
24413848Ssam 			else
24513848Ssam 				ender = begin + reps * s - s;
24613848Ssam 			mask = 0;
24760455Sbostic 			break;
24860455Sbostic 		case 016:
24913848Ssam 			if (randomize)
25013848Ssam 				s = time(0);
25113848Ssam 			else if (reps == 0)
25260455Sbostic 				error("Infinite sequences cannot be bounded",
25360455Sbostic 				    "");
25413848Ssam 			else if (reps == 1)
25513848Ssam 				s = 0.0;
25613848Ssam 			else
25713848Ssam 				s = (ender - begin) / (reps - 1);
25813848Ssam 			mask = 0;
25960455Sbostic 			break;
26060455Sbostic 		case 017:		/* if reps given and implied, */
26160455Sbostic 			if (!randomize && s != 0.0) {
26213848Ssam 				long t = (ender - begin + s) / s;
26313848Ssam 				if (t <= 0)
26413848Ssam 					error("Impossible stepsize", "");
26513848Ssam 				if (t < reps)		/* take lesser */
26613848Ssam 					reps = t;
26713848Ssam 			}
26813848Ssam 			mask = 0;
26913848Ssam 			break;
27013848Ssam 		default:
27113848Ssam 			error("Bad mask", "");
27213848Ssam 		}
27313848Ssam 	if (reps == 0)
27413848Ssam 		infinity = 1;
27513848Ssam }
27613848Ssam 
27760455Sbostic void
putdata(x,notlast)27813848Ssam putdata(x, notlast)
27960455Sbostic 	double x;
28060455Sbostic 	long notlast;
28113848Ssam {
28213848Ssam 	long		d = x;
28313848Ssam 	register long	*dp = &d;
28413848Ssam 
28513848Ssam 	if (boring)				/* repeated word */
28613848Ssam 		printf(format);
28713848Ssam 	else if (dox)				/* scalar */
28813848Ssam 		printf(format, *dp);
28913848Ssam 	else					/* real */
29013848Ssam 		printf(format, x);
29113848Ssam 	if (notlast != 0)
29213848Ssam 		fputs(sepstring, stdout);
29313848Ssam }
29413848Ssam 
29560455Sbostic void
error(msg,s)29613848Ssam error(msg, s)
29760455Sbostic 	char *msg, *s;
29813848Ssam {
29913848Ssam 	fprintf(stderr, "jot: ");
30013848Ssam 	fprintf(stderr, msg, s);
30160455Sbostic 	fprintf(stderr,
30260455Sbostic 	    "\nusage:  jot [ options ] [ reps [ begin [ end [ s ] ] ] ]\n");
30313848Ssam 	if (strncmp("jot - ", msg, 6) == 0)
30460455Sbostic 		fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
30513848Ssam 			"-r		random data\n",
30613848Ssam 			"-c		character data\n",
30718503Sjak 			"-n		no final newline\n",
30813848Ssam 			"-b word		repeated word\n",
30913848Ssam 			"-w word		context word\n",
31013848Ssam 			"-s string	data separator\n",
31113848Ssam 			"-p precision	number of characters\n");
31213848Ssam 	exit(1);
31313848Ssam }
31413848Ssam 
31560455Sbostic int
getprec(s)31613848Ssam getprec(s)
31760455Sbostic 	char *s;
31813848Ssam {
31913848Ssam 	register char	*p;
32013848Ssam 	register char	*q;
32113848Ssam 
32213848Ssam 	for (p = s; *p; p++)
32313848Ssam 		if (*p == '.')
32413848Ssam 			break;
32513848Ssam 	if (!*p)
32660455Sbostic 		return (0);
32713848Ssam 	for (q = ++p; *p; p++)
32813848Ssam 		if (!isdigit(*p))
32913848Ssam 			break;
33060455Sbostic 	return (p - q);
33113848Ssam }
33213848Ssam 
33360455Sbostic void
getformat()33413848Ssam getformat()
33513848Ssam {
33613848Ssam 	register char	*p;
33713848Ssam 
33813848Ssam 	if (boring)				/* no need to bother */
33913848Ssam 		return;
34013848Ssam 	for (p = format; *p; p++)		/* look for '%' */
34113848Ssam 		if (*p == '%' && *(p+1) != '%')	/* leave %% alone */
34213848Ssam 			break;
34313848Ssam 	if (!*p && !chardata)
34413848Ssam 		sprintf(p, "%%.%df", prec);
34513848Ssam 	else if (!*p && chardata) {
34613848Ssam 		strcpy(p, "%c");
34713848Ssam 		dox = 1;
34813848Ssam 	}
34913848Ssam 	else if (!*(p+1))
35013848Ssam 		strcat(format, "%");		/* cannot end in single '%' */
35113848Ssam 	else {
35213848Ssam 		while (!isalpha(*p))
35313848Ssam 			p++;
35413848Ssam 		switch (*p) {
35513848Ssam 		case 'f': case 'e': case 'g': case '%':
35613848Ssam 			break;
35713848Ssam 		case 's':
35813848Ssam 			error("Cannot convert numeric data to strings", "");
35913848Ssam 			break;
36013848Ssam 		/* case 'd': case 'o': case 'x': case 'D': case 'O': case 'X':
36113848Ssam 		case 'c': case 'u': */
36213848Ssam 		default:
36313848Ssam 			dox = 1;
36413848Ssam 			break;
36513848Ssam 		}
36613848Ssam 	}
36713848Ssam }
368