jot.c revision 1590
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
351590Srgrimesstatic 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
411590Srgrimesstatic char sccsid[] = "@(#)jot.c	8.1 (Berkeley) 6/6/93";
421590Srgrimes#endif /* not lint */
431590Srgrimes
441590Srgrimes/*
451590Srgrimes * jot - print sequential or random data
461590Srgrimes *
471590Srgrimes * Author:  John Kunze, Office of Comp. Affairs, UCB
481590Srgrimes */
491590Srgrimes
501590Srgrimes#include <ctype.h>
511590Srgrimes#include <limits.h>
521590Srgrimes#include <stdio.h>
531590Srgrimes#include <stdlib.h>
541590Srgrimes#include <string.h>
551590Srgrimes#include <time.h>
561590Srgrimes
571590Srgrimes#define	REPS_DEF	100
581590Srgrimes#define	BEGIN_DEF	1
591590Srgrimes#define	ENDER_DEF	100
601590Srgrimes#define	STEP_DEF	1
611590Srgrimes
621590Srgrimes#define	isdefault(s)	(strcmp((s), "-") == 0)
631590Srgrimes
641590Srgrimesdouble	begin;
651590Srgrimesdouble	ender;
661590Srgrimesdouble	s;
671590Srgrimeslong	reps;
681590Srgrimesint	randomize;
691590Srgrimesint	infinity;
701590Srgrimesint	boring;
711590Srgrimesint	prec;
721590Srgrimesint	dox;
731590Srgrimesint	chardata;
741590Srgrimesint	nofinalnl;
751590Srgrimeschar	*sepstring = "\n";
761590Srgrimeschar	format[BUFSIZ];
771590Srgrimes
781590Srgrimesvoid	error __P((char *, char *));
791590Srgrimesvoid	getargs __P((int, char *[]));
801590Srgrimesvoid	getformat __P((void));
811590Srgrimesint	getprec __P((char *));
821590Srgrimesvoid	putdata __P((double, long));
831590Srgrimes
841590Srgrimesint
851590Srgrimesmain(argc, argv)
861590Srgrimes	int argc;
871590Srgrimes	char *argv[];
881590Srgrimes{
891590Srgrimes	double	xd, yd;
901590Srgrimes	long	id;
911590Srgrimes	register double	*x = &xd;
921590Srgrimes	register double	*y = &yd;
931590Srgrimes	register long	*i = &id;
941590Srgrimes
951590Srgrimes	getargs(argc, argv);
961590Srgrimes	if (randomize) {
971590Srgrimes		*x = (ender - begin) * (ender > begin ? 1 : -1);
981590Srgrimes		srandom((int) s);
991590Srgrimes		for (*i = 1; *i <= reps || infinity; (*i)++) {
1001590Srgrimes			*y = (double) random() / INT_MAX;
1011590Srgrimes			putdata(*y * *x + begin, reps - *i);
1021590Srgrimes		}
1031590Srgrimes	}
1041590Srgrimes	else
1051590Srgrimes		for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
1061590Srgrimes			putdata(*x, reps - *i);
1071590Srgrimes	if (!nofinalnl)
1081590Srgrimes		putchar('\n');
1091590Srgrimes	exit(0);
1101590Srgrimes}
1111590Srgrimes
1121590Srgrimesvoid
1131590Srgrimesgetargs(ac, av)
1141590Srgrimes	int ac;
1151590Srgrimes	char *av[];
1161590Srgrimes{
1171590Srgrimes	register unsigned int	mask = 0;
1181590Srgrimes	register int		n = 0;
1191590Srgrimes
1201590Srgrimes	while (--ac && **++av == '-' && !isdefault(*av))
1211590Srgrimes		switch ((*av)[1]) {
1221590Srgrimes		case 'r':
1231590Srgrimes			randomize = 1;
1241590Srgrimes			break;
1251590Srgrimes		case 'c':
1261590Srgrimes			chardata = 1;
1271590Srgrimes			break;
1281590Srgrimes		case 'n':
1291590Srgrimes			nofinalnl = 1;
1301590Srgrimes			break;
1311590Srgrimes		case 'b':
1321590Srgrimes			boring = 1;
1331590Srgrimes		case 'w':
1341590Srgrimes			if ((*av)[2])
1351590Srgrimes				strcpy(format, *av + 2);
1361590Srgrimes			else if (!--ac)
1371590Srgrimes				error("Need context word after -w or -b", "");
1381590Srgrimes			else
1391590Srgrimes				strcpy(format, *++av);
1401590Srgrimes			break;
1411590Srgrimes		case 's':
1421590Srgrimes			if ((*av)[2])
1431590Srgrimes				strcpy(sepstring, *av + 2);
1441590Srgrimes			else if (!--ac)
1451590Srgrimes				error("Need string after -s", "");
1461590Srgrimes			else
1471590Srgrimes				strcpy(sepstring, *++av);
1481590Srgrimes			break;
1491590Srgrimes		case 'p':
1501590Srgrimes			if ((*av)[2])
1511590Srgrimes				prec = atoi(*av + 2);
1521590Srgrimes			else if (!--ac)
1531590Srgrimes				error("Need number after -p", "");
1541590Srgrimes			else
1551590Srgrimes				prec = atoi(*++av);
1561590Srgrimes			if (prec <= 0)
1571590Srgrimes				error("Bad precision value", "");
1581590Srgrimes			break;
1591590Srgrimes		default:
1601590Srgrimes			error("Unknown option %s", *av);
1611590Srgrimes		}
1621590Srgrimes
1631590Srgrimes	switch (ac) {	/* examine args right to left, falling thru cases */
1641590Srgrimes	case 4:
1651590Srgrimes		if (!isdefault(av[3])) {
1661590Srgrimes			if (!sscanf(av[3], "%lf", &s))
1671590Srgrimes				error("Bad s value:  %s", av[3]);
1681590Srgrimes			mask |= 01;
1691590Srgrimes		}
1701590Srgrimes	case 3:
1711590Srgrimes		if (!isdefault(av[2])) {
1721590Srgrimes			if (!sscanf(av[2], "%lf", &ender))
1731590Srgrimes				ender = av[2][strlen(av[2])-1];
1741590Srgrimes			mask |= 02;
1751590Srgrimes			if (!prec)
1761590Srgrimes				n = getprec(av[2]);
1771590Srgrimes		}
1781590Srgrimes	case 2:
1791590Srgrimes		if (!isdefault(av[1])) {
1801590Srgrimes			if (!sscanf(av[1], "%lf", &begin))
1811590Srgrimes				begin = av[1][strlen(av[1])-1];
1821590Srgrimes			mask |= 04;
1831590Srgrimes			if (!prec)
1841590Srgrimes				prec = getprec(av[1]);
1851590Srgrimes			if (n > prec)		/* maximum precision */
1861590Srgrimes				prec = n;
1871590Srgrimes		}
1881590Srgrimes	case 1:
1891590Srgrimes		if (!isdefault(av[0])) {
1901590Srgrimes			if (!sscanf(av[0], "%ld", &reps))
1911590Srgrimes				error("Bad reps value:  %s", av[0]);
1921590Srgrimes			mask |= 010;
1931590Srgrimes		}
1941590Srgrimes		break;
1951590Srgrimes	case 0:
1961590Srgrimes		error("jot - print sequential or random data", "");
1971590Srgrimes	default:
1981590Srgrimes		error("Too many arguments.  What do you mean by %s?", av[4]);
1991590Srgrimes	}
2001590Srgrimes	getformat();
2011590Srgrimes	while (mask)	/* 4 bit mask has 1's where last 4 args were given */
2021590Srgrimes		switch (mask) {	/* fill in the 0's by default or computation */
2031590Srgrimes		case 001:
2041590Srgrimes			reps = REPS_DEF;
2051590Srgrimes			mask = 011;
2061590Srgrimes			break;
2071590Srgrimes		case 002:
2081590Srgrimes			reps = REPS_DEF;
2091590Srgrimes			mask = 012;
2101590Srgrimes			break;
2111590Srgrimes		case 003:
2121590Srgrimes			reps = REPS_DEF;
2131590Srgrimes			mask = 013;
2141590Srgrimes			break;
2151590Srgrimes		case 004:
2161590Srgrimes			reps = REPS_DEF;
2171590Srgrimes			mask = 014;
2181590Srgrimes			break;
2191590Srgrimes		case 005:
2201590Srgrimes			reps = REPS_DEF;
2211590Srgrimes			mask = 015;
2221590Srgrimes			break;
2231590Srgrimes		case 006:
2241590Srgrimes			reps = REPS_DEF;
2251590Srgrimes			mask = 016;
2261590Srgrimes			break;
2271590Srgrimes		case 007:
2281590Srgrimes			if (randomize) {
2291590Srgrimes				reps = REPS_DEF;
2301590Srgrimes				mask = 0;
2311590Srgrimes				break;
2321590Srgrimes			}
2331590Srgrimes			if (s == 0.0) {
2341590Srgrimes				reps = 0;
2351590Srgrimes				mask = 0;
2361590Srgrimes				break;
2371590Srgrimes			}
2381590Srgrimes			reps = (ender - begin + s) / s;
2391590Srgrimes			if (reps <= 0)
2401590Srgrimes				error("Impossible stepsize", "");
2411590Srgrimes			mask = 0;
2421590Srgrimes			break;
2431590Srgrimes		case 010:
2441590Srgrimes			begin = BEGIN_DEF;
2451590Srgrimes			mask = 014;
2461590Srgrimes			break;
2471590Srgrimes		case 011:
2481590Srgrimes			begin = BEGIN_DEF;
2491590Srgrimes			mask = 015;
2501590Srgrimes			break;
2511590Srgrimes		case 012:
2521590Srgrimes			s = (randomize ? time(0) : STEP_DEF);
2531590Srgrimes			mask = 013;
2541590Srgrimes			break;
2551590Srgrimes		case 013:
2561590Srgrimes			if (randomize)
2571590Srgrimes				begin = BEGIN_DEF;
2581590Srgrimes			else if (reps == 0)
2591590Srgrimes				error("Must specify begin if reps == 0", "");
2601590Srgrimes			begin = ender - reps * s + s;
2611590Srgrimes			mask = 0;
2621590Srgrimes			break;
2631590Srgrimes		case 014:
2641590Srgrimes			s = (randomize ? time(0) : STEP_DEF);
2651590Srgrimes			mask = 015;
2661590Srgrimes			break;
2671590Srgrimes		case 015:
2681590Srgrimes			if (randomize)
2691590Srgrimes				ender = ENDER_DEF;
2701590Srgrimes			else
2711590Srgrimes				ender = begin + reps * s - s;
2721590Srgrimes			mask = 0;
2731590Srgrimes			break;
2741590Srgrimes		case 016:
2751590Srgrimes			if (randomize)
2761590Srgrimes				s = time(0);
2771590Srgrimes			else if (reps == 0)
2781590Srgrimes				error("Infinite sequences cannot be bounded",
2791590Srgrimes				    "");
2801590Srgrimes			else if (reps == 1)
2811590Srgrimes				s = 0.0;
2821590Srgrimes			else
2831590Srgrimes				s = (ender - begin) / (reps - 1);
2841590Srgrimes			mask = 0;
2851590Srgrimes			break;
2861590Srgrimes		case 017:		/* if reps given and implied, */
2871590Srgrimes			if (!randomize && s != 0.0) {
2881590Srgrimes				long t = (ender - begin + s) / s;
2891590Srgrimes				if (t <= 0)
2901590Srgrimes					error("Impossible stepsize", "");
2911590Srgrimes				if (t < reps)		/* take lesser */
2921590Srgrimes					reps = t;
2931590Srgrimes			}
2941590Srgrimes			mask = 0;
2951590Srgrimes			break;
2961590Srgrimes		default:
2971590Srgrimes			error("Bad mask", "");
2981590Srgrimes		}
2991590Srgrimes	if (reps == 0)
3001590Srgrimes		infinity = 1;
3011590Srgrimes}
3021590Srgrimes
3031590Srgrimesvoid
3041590Srgrimesputdata(x, notlast)
3051590Srgrimes	double x;
3061590Srgrimes	long notlast;
3071590Srgrimes{
3081590Srgrimes	long		d = x;
3091590Srgrimes	register long	*dp = &d;
3101590Srgrimes
3111590Srgrimes	if (boring)				/* repeated word */
3121590Srgrimes		printf(format);
3131590Srgrimes	else if (dox)				/* scalar */
3141590Srgrimes		printf(format, *dp);
3151590Srgrimes	else					/* real */
3161590Srgrimes		printf(format, x);
3171590Srgrimes	if (notlast != 0)
3181590Srgrimes		fputs(sepstring, stdout);
3191590Srgrimes}
3201590Srgrimes
3211590Srgrimesvoid
3221590Srgrimeserror(msg, s)
3231590Srgrimes	char *msg, *s;
3241590Srgrimes{
3251590Srgrimes	fprintf(stderr, "jot: ");
3261590Srgrimes	fprintf(stderr, msg, s);
3271590Srgrimes	fprintf(stderr,
3281590Srgrimes	    "\nusage:  jot [ options ] [ reps [ begin [ end [ s ] ] ] ]\n");
3291590Srgrimes	if (strncmp("jot - ", msg, 6) == 0)
3301590Srgrimes		fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
3311590Srgrimes			"-r		random data\n",
3321590Srgrimes			"-c		character data\n",
3331590Srgrimes			"-n		no final newline\n",
3341590Srgrimes			"-b word		repeated word\n",
3351590Srgrimes			"-w word		context word\n",
3361590Srgrimes			"-s string	data separator\n",
3371590Srgrimes			"-p precision	number of characters\n");
3381590Srgrimes	exit(1);
3391590Srgrimes}
3401590Srgrimes
3411590Srgrimesint
3421590Srgrimesgetprec(s)
3431590Srgrimes	char *s;
3441590Srgrimes{
3451590Srgrimes	register char	*p;
3461590Srgrimes	register char	*q;
3471590Srgrimes
3481590Srgrimes	for (p = s; *p; p++)
3491590Srgrimes		if (*p == '.')
3501590Srgrimes			break;
3511590Srgrimes	if (!*p)
3521590Srgrimes		return (0);
3531590Srgrimes	for (q = ++p; *p; p++)
3541590Srgrimes		if (!isdigit(*p))
3551590Srgrimes			break;
3561590Srgrimes	return (p - q);
3571590Srgrimes}
3581590Srgrimes
3591590Srgrimesvoid
3601590Srgrimesgetformat()
3611590Srgrimes{
3621590Srgrimes	register char	*p;
3631590Srgrimes
3641590Srgrimes	if (boring)				/* no need to bother */
3651590Srgrimes		return;
3661590Srgrimes	for (p = format; *p; p++)		/* look for '%' */
3671590Srgrimes		if (*p == '%' && *(p+1) != '%')	/* leave %% alone */
3681590Srgrimes			break;
3691590Srgrimes	if (!*p && !chardata)
3701590Srgrimes		sprintf(p, "%%.%df", prec);
3711590Srgrimes	else if (!*p && chardata) {
3721590Srgrimes		strcpy(p, "%c");
3731590Srgrimes		dox = 1;
3741590Srgrimes	}
3751590Srgrimes	else if (!*(p+1))
3761590Srgrimes		strcat(format, "%");		/* cannot end in single '%' */
3771590Srgrimes	else {
3781590Srgrimes		while (!isalpha(*p))
3791590Srgrimes			p++;
3801590Srgrimes		switch (*p) {
3811590Srgrimes		case 'f': case 'e': case 'g': case '%':
3821590Srgrimes			break;
3831590Srgrimes		case 's':
3841590Srgrimes			error("Cannot convert numeric data to strings", "");
3851590Srgrimes			break;
3861590Srgrimes		/* case 'd': case 'o': case 'x': case 'D': case 'O': case 'X':
3871590Srgrimes		case 'c': case 'u': */
3881590Srgrimes		default:
3891590Srgrimes			dox = 1;
3901590Srgrimes			break;
3911590Srgrimes		}
3921590Srgrimes	}
3931590Srgrimes}
394