xref: /original-bsd/usr.bin/jot/jot.c (revision 4e9331e4)
1 /* Copyright (c) 1983 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)jot.c	4.3	(Berkeley)	04/05/86";
5 #endif not lint
6 
7 /*
8  *	jot - print sequential or random data
9  *	Author:  John Kunze, Office of Comp. Affairs, UCB
10  */
11 
12 #include <stdio.h>
13 #include <ctype.h>
14 
15 #define	REPS_DEF	100
16 #define	BEGIN_DEF	1
17 #define	ENDER_DEF	100
18 #define	STEP_DEF	1
19 
20 #define BSD4_2		1
21 #if BSD4_2
22 #define RAND		random
23 #define SRAND		srandom
24 long RAND();
25 #else
26 #define RAND		rand
27 #define SRAND		srand
28 #endif
29 
30 #define	isdefault(s)	(strcmp((s), "-") == 0)
31 #define	LARGESTINT	(~ (unsigned) 0 >> 1)
32 #define	CASE		break; case
33 
34 char	*sepstring = "\n";
35 char	format[BUFSIZ];
36 char	buf[BUFSIZ];
37 int	randomize;
38 int	infinity;
39 int	boring;
40 int	prec;
41 int	dox;
42 int	chardata;
43 int	nofinalnl;
44 
45 long	reps;
46 double	begin;
47 double	ender;
48 double	s;
49 
50 main(argc, argv)
51 int	argc;
52 char	**argv;
53 {
54 	double	xd, yd;
55 	long	id;
56 	register double	*x = &xd;
57 	register double	*y = &yd;
58 	register long	*i = &id;
59 
60 	setbuf(stdout, buf);
61 	getargs(argc, argv);
62 	if (randomize) {
63 		*x = (ender - begin) * (ender > begin ? 1 : -1);
64 		SRAND((int) s);
65 		for (*i = 1; *i <= reps || infinity; (*i)++) {
66 			*y = (double) RAND() / LARGESTINT;
67 			putdata(*y * *x + begin, reps - *i);
68 		}
69 	}
70 	else
71 		for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
72 			putdata(*x, reps - *i);
73 	if (!nofinalnl)
74 		putchar('\n');
75 	exit(0);
76 }
77 
78 getargs(ac, av)
79 int	ac;
80 char	**av;
81 {
82 	register unsigned int	mask = 0;
83 	register int		n = 0;
84 
85 	while (--ac && **++av == '-' && !isdefault(*av))
86 		switch ((*av)[1]) {
87 		case 'r':
88 			randomize = 1;
89 			break;
90 		case 'c':
91 			chardata = 1;
92 			break;
93 		case 'n':
94 			nofinalnl = 1;
95 			break;
96 		case 'b':
97 			boring = 1;
98 		case 'w':
99 			if ((*av)[2])
100 				strcpy(format, *av + 2);
101 			else if (!--ac)
102 				error("Need context word after -w or -b", "");
103 			else
104 				strcpy(format, *++av);
105 			break;
106 		case 's':
107 			if ((*av)[2])
108 				strcpy(sepstring, *av + 2);
109 			else if (!--ac)
110 				error("Need string after -s", "");
111 			else
112 				strcpy(sepstring, *++av);
113 			break;
114 		case 'p':
115 			if ((*av)[2])
116 				prec = atoi(*av + 2);
117 			else if (!--ac)
118 				error("Need number after -p", "");
119 			else
120 				prec = atoi(*++av);
121 			if (prec <= 0)
122 				error("Bad precision value", "");
123 			break;
124 		default:
125 			error("Unknown option %s", *av);
126 		}
127 	switch (ac) {	/* examine args right to left, falling thru cases */
128 	case 4:
129 		if (!isdefault(av[3])) {
130 			if (!sscanf(av[3], "%F", &s))
131 				error("Bad s value:  %s", av[3]);
132 			mask |= 01;
133 		}
134 	case 3:
135 		if (!isdefault(av[2])) {
136 			if (!sscanf(av[2], "%F", &ender))
137 				ender = av[2][strlen(av[2])-1];
138 			mask |= 02;
139 			if (!prec)
140 				n = getprec(av[2]);
141 		}
142 	case 2:
143 		if (!isdefault(av[1])) {
144 			if (!sscanf(av[1], "%F", &begin))
145 				begin = av[1][strlen(av[1])-1];
146 			mask |= 04;
147 			if (!prec)
148 				prec = getprec(av[1]);
149 			if (n > prec)		/* maximum precision */
150 				prec = n;
151 		}
152 	case 1:
153 		if (!isdefault(av[0])) {
154 			if (!sscanf(av[0], "%D", &reps))
155 				error("Bad reps value:  %s", av[0]);
156 			mask |= 010;
157 		}
158 		break;
159 	case 0:
160 		error("jot - print sequential or random data", "");
161 	default:
162 		error("Too many arguments.  What do you mean by %s?", av[4]);
163 	}
164 	getformat();
165 	while (mask)	/* 4 bit mask has 1's where last 4 args were given */
166 		switch (mask) {	/* fill in the 0's by default or computation */
167 		CASE 001:
168 			reps = REPS_DEF;
169 			mask = 011;
170 		CASE 002:
171 			reps = REPS_DEF;
172 			mask = 012;
173 		CASE 003:
174 			reps = REPS_DEF;
175 			mask = 013;
176 		CASE 004:
177 			reps = REPS_DEF;
178 			mask = 014;
179 		CASE 005:
180 			reps = REPS_DEF;
181 			mask = 015;
182 		CASE 006:
183 			reps = REPS_DEF;
184 			mask = 016;
185 		CASE 007:
186 			if (randomize) {
187 				reps = REPS_DEF;
188 				mask = 0;
189 				break;
190 			}
191 			if (s == 0.0) {
192 				reps = 0;
193 				mask = 0;
194 				break;
195 			}
196 			reps = (ender - begin + s) / s;
197 			if (reps <= 0)
198 				error("Impossible stepsize", "");
199 			mask = 0;
200 		CASE 010:
201 			begin = BEGIN_DEF;
202 			mask = 014;
203 		CASE 011:
204 			begin = BEGIN_DEF;
205 			mask = 015;
206 		CASE 012:
207 			s = (randomize ? time(0) : STEP_DEF);
208 			mask = 013;
209 		CASE 013:
210 			if (randomize)
211 				begin = BEGIN_DEF;
212 			else if (reps == 0)
213 				error("Must specify begin if reps == 0", "");
214 			begin = ender - reps * s + s;
215 			mask = 0;
216 		CASE 014:
217 			s = (randomize ? time(0) : STEP_DEF);
218 			mask = 015;
219 		CASE 015:
220 			if (randomize)
221 				ender = ENDER_DEF;
222 			else
223 				ender = begin + reps * s - s;
224 			mask = 0;
225 		CASE 016:
226 			if (randomize)
227 				s = time(0);
228 			else if (reps == 0)
229 				error("Infinite sequences cannot be bounded", "");
230 			else if (reps == 1)
231 				s = 0.0;
232 			else
233 				s = (ender - begin) / (reps - 1);
234 			mask = 0;
235 		CASE 017:
236 			if (!randomize && s != 0.0) {	/* if reps given and implied, */
237 				long t = (ender - begin + s) / s;
238 				if (t <= 0)
239 					error("Impossible stepsize", "");
240 				if (t < reps)		/* take lesser */
241 					reps = t;
242 			}
243 			mask = 0;
244 			break;
245 		default:
246 			error("Bad mask", "");
247 		}
248 	if (reps == 0)
249 		infinity = 1;
250 }
251 
252 putdata(x, notlast)
253 double	x;
254 long	notlast;
255 {
256 	long		d = x;
257 	register long	*dp = &d;
258 
259 	if (boring)				/* repeated word */
260 		printf(format);
261 	else if (dox)				/* scalar */
262 		printf(format, *dp);
263 	else					/* real */
264 		printf(format, x);
265 	if (notlast != 0)
266 		fputs(sepstring, stdout);
267 }
268 
269 error(msg, s)
270 char	*msg;
271 char	*s;
272 {
273 	char	buf[BUFSIZ];
274 
275 	setbuf(stderr, buf);
276 	fprintf(stderr, "jot: ");
277 	fprintf(stderr, msg, s);
278 	fprintf(stderr, "\nUsage:  jot [ options ] [ reps [ begin [ end [ s ] ] ] ]\n");
279 	if (strncmp("jot - ", msg, 6) == 0)
280 		fprintf(stderr, "Options:\n\t%s\t%s\t%s\t%s\t%s\t%s",
281 			"-r		random data\n",
282 			"-c		character data\n",
283 			"-n		no final newline\n",
284 			"-b word		repeated word\n",
285 			"-w word		context word\n",
286 			"-s string	data separator\n",
287 			"-p precision	number of characters\n");
288 	exit(1);
289 }
290 
291 getprec(s)
292 char	*s;
293 {
294 	register char	*p;
295 	register char	*q;
296 
297 	for (p = s; *p; p++)
298 		if (*p == '.')
299 			break;
300 	if (!*p)
301 		return(0);
302 	for (q = ++p; *p; p++)
303 		if (!isdigit(*p))
304 			break;
305 	return(p - q);
306 }
307 
308 getformat()
309 {
310 	register char	*p;
311 
312 	if (boring)				/* no need to bother */
313 		return;
314 	for (p = format; *p; p++)		/* look for '%' */
315 		if (*p == '%' && *(p+1) != '%')	/* leave %% alone */
316 			break;
317 	if (!*p && !chardata)
318 		sprintf(p, "%%.%df", prec);
319 	else if (!*p && chardata) {
320 		strcpy(p, "%c");
321 		dox = 1;
322 	}
323 	else if (!*(p+1))
324 		strcat(format, "%");		/* cannot end in single '%' */
325 	else {
326 		while (!isalpha(*p))
327 			p++;
328 		switch (*p) {
329 		case 'f': case 'e': case 'g': case '%':
330 			break;
331 		case 's':
332 			error("Cannot convert numeric data to strings", "");
333 			break;
334 		/* case 'd': case 'o': case 'x': case 'D': case 'O': case 'X':
335 		case 'c': case 'u': */
336 		default:
337 			dox = 1;
338 			break;
339 		}
340 	}
341 }
342