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