Annotation of src/usr.bin/jot/jot.c, Revision 1.8
1.8 ! pjanzen 1: /* $OpenBSD: jot.c,v 1.7 2000/12/21 15:34:51 aaron Exp $ */
1.1 deraadt 2: /* $NetBSD: jot.c,v 1.3 1994/12/02 20:29:43 pk Exp $ */
3:
4: /*-
5: * Copyright (c) 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: #ifndef lint
38: static char copyright[] =
39: "@(#) Copyright (c) 1993\n\
40: The Regents of the University of California. All rights reserved.\n";
41: #endif /* not lint */
42:
43: #ifndef lint
44: #if 0
45: static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93";
46: #endif
1.8 ! pjanzen 47: static char rcsid[] = "$OpenBSD: jot.c,v 1.7 2000/12/21 15:34:51 aaron Exp $";
1.1 deraadt 48: #endif /* not lint */
49:
50: /*
51: * jot - print sequential or random data
52: *
53: * Author: John Kunze, Office of Comp. Affairs, UCB
54: */
55:
1.7 aaron 56: #include <err.h>
1.1 deraadt 57: #include <ctype.h>
58: #include <limits.h>
59: #include <stdio.h>
60: #include <stdlib.h>
61: #include <string.h>
62: #include <time.h>
63:
64: #define REPS_DEF 100
65: #define BEGIN_DEF 1
66: #define ENDER_DEF 100
67: #define STEP_DEF 1
68:
1.8 ! pjanzen 69: #define is_default(s) (strcmp((s), "-") == 0)
1.1 deraadt 70:
71: double begin;
72: double ender;
73: double s;
74: long reps;
75: int randomize;
76: int infinity;
77: int boring;
78: int prec;
79: int dox;
80: int chardata;
81: int nofinalnl;
82: char sepstring[BUFSIZ] = "\n";
83: char format[BUFSIZ];
84:
1.7 aaron 85: void getargs __P((int, char *[]));
86: void getformat __P((void));
87: int getprec __P((char *));
88: void putdata __P((double, long));
89: static void usage __P((void));
1.1 deraadt 90:
91: int
92: main(argc, argv)
93: int argc;
94: char *argv[];
95: {
96: double xd, yd;
97: long id;
1.8 ! pjanzen 98: double *x = &xd;
! 99: double *y = &yd;
! 100: long *i = &id;
! 101: unsigned int mask = 0;
! 102: int n = 0;
! 103: int ch;
1.1 deraadt 104:
1.8 ! pjanzen 105: while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1)
! 106: switch((char)ch) {
1.1 deraadt 107: case 'r':
108: randomize = 1;
109: break;
110: case 'c':
111: chardata = 1;
112: break;
113: case 'n':
114: nofinalnl = 1;
115: break;
116: case 'b':
117: boring = 1;
1.8 ! pjanzen 118: if (strlcpy(format, optarg, sizeof(format)) >=
! 119: sizeof(format))
! 120: errx(1, "-b word too long");
! 121: break;
1.1 deraadt 122: case 'w':
1.8 ! pjanzen 123: if (strlcpy(format, optarg, sizeof(format)) >=
! 124: sizeof(format))
! 125: errx(1, "-w word too long");
1.1 deraadt 126: break;
127: case 's':
1.8 ! pjanzen 128: if (strlcpy(sepstring, optarg, sizeof(sepstring)) >=
! 129: sizeof(sepstring))
! 130: errx(1, "-s word too long");
1.1 deraadt 131: break;
132: case 'p':
1.8 ! pjanzen 133: prec = atoi(optarg);
1.1 deraadt 134: if (prec <= 0)
1.8 ! pjanzen 135: errx(1, "bad precision value");
1.1 deraadt 136: break;
137: default:
1.7 aaron 138: usage();
1.1 deraadt 139: }
1.8 ! pjanzen 140: argc -= optind;
! 141: argv += optind;
1.1 deraadt 142:
1.8 ! pjanzen 143: switch (argc) { /* examine args right to left, falling thru cases */
1.1 deraadt 144: case 4:
1.8 ! pjanzen 145: if (!is_default(argv[3])) {
! 146: if (!sscanf(argv[3], "%lf", &s))
! 147: errx(1, "Bad s value: %s", argv[3]);
1.1 deraadt 148: mask |= 01;
149: }
150: case 3:
1.8 ! pjanzen 151: if (!is_default(argv[2])) {
! 152: if (!sscanf(argv[2], "%lf", &ender))
! 153: ender = argv[2][strlen(argv[2])-1];
1.1 deraadt 154: mask |= 02;
155: if (!prec)
1.8 ! pjanzen 156: n = getprec(argv[2]);
1.1 deraadt 157: }
158: case 2:
1.8 ! pjanzen 159: if (!is_default(argv[1])) {
! 160: if (!sscanf(argv[1], "%lf", &begin))
! 161: begin = argv[1][strlen(argv[1])-1];
1.1 deraadt 162: mask |= 04;
163: if (!prec)
1.8 ! pjanzen 164: prec = getprec(argv[1]);
1.1 deraadt 165: if (n > prec) /* maximum precision */
166: prec = n;
167: }
168: case 1:
1.8 ! pjanzen 169: if (!is_default(argv[0])) {
! 170: if (!sscanf(argv[0], "%ld", &reps))
! 171: errx(1, "Bad reps value: %s", argv[0]);
1.1 deraadt 172: mask |= 010;
173: }
174: break;
175: case 0:
1.8 ! pjanzen 176: usage();
! 177: break;
1.1 deraadt 178: default:
1.8 ! pjanzen 179: errx(1, "Too many arguments. What do you mean by %s?", argv[4]);
1.1 deraadt 180: }
181: getformat();
182: while (mask) /* 4 bit mask has 1's where last 4 args were given */
183: switch (mask) { /* fill in the 0's by default or computation */
184: case 001:
185: reps = REPS_DEF;
186: mask = 011;
187: break;
188: case 002:
189: reps = REPS_DEF;
190: mask = 012;
191: break;
192: case 003:
193: reps = REPS_DEF;
194: mask = 013;
195: break;
196: case 004:
197: reps = REPS_DEF;
198: mask = 014;
199: break;
200: case 005:
201: reps = REPS_DEF;
202: mask = 015;
203: break;
204: case 006:
205: reps = REPS_DEF;
206: mask = 016;
207: break;
208: case 007:
209: if (randomize) {
210: reps = REPS_DEF;
211: mask = 0;
212: break;
213: }
214: if (s == 0.0) {
215: reps = 0;
216: mask = 0;
217: break;
218: }
219: reps = (ender - begin + s) / s;
220: if (reps <= 0)
1.7 aaron 221: errx(1, "Impossible stepsize");
1.1 deraadt 222: mask = 0;
223: break;
224: case 010:
225: begin = BEGIN_DEF;
226: mask = 014;
227: break;
228: case 011:
229: begin = BEGIN_DEF;
230: mask = 015;
231: break;
232: case 012:
1.6 aaron 233: s = (randomize ? time(NULL) : STEP_DEF);
1.1 deraadt 234: mask = 013;
235: break;
236: case 013:
237: if (randomize)
238: begin = BEGIN_DEF;
239: else if (reps == 0)
1.7 aaron 240: errx(1, "Must specify begin if reps == 0");
1.1 deraadt 241: begin = ender - reps * s + s;
242: mask = 0;
243: break;
244: case 014:
1.6 aaron 245: s = (randomize ? time(NULL) : STEP_DEF);
1.1 deraadt 246: mask = 015;
247: break;
248: case 015:
249: if (randomize)
250: ender = ENDER_DEF;
251: else
252: ender = begin + reps * s - s;
253: mask = 0;
254: break;
255: case 016:
256: if (randomize)
1.6 aaron 257: s = time(NULL);
1.1 deraadt 258: else if (reps == 0)
1.7 aaron 259: errx(1, "Infinite sequences cannot be bounded");
1.1 deraadt 260: else if (reps == 1)
261: s = 0.0;
262: else
263: s = (ender - begin) / (reps - 1);
264: mask = 0;
265: break;
266: case 017: /* if reps given and implied, */
267: if (!randomize && s != 0.0) {
268: long t = (ender - begin + s) / s;
269: if (t <= 0)
1.7 aaron 270: errx(1, "Impossible stepsize");
1.1 deraadt 271: if (t < reps) /* take lesser */
272: reps = t;
273: }
274: mask = 0;
275: break;
276: default:
1.8 ! pjanzen 277: errx(1, "bad mask");
1.1 deraadt 278: }
279: if (reps == 0)
280: infinity = 1;
1.8 ! pjanzen 281: if (randomize) {
! 282: *x = (ender - begin) * (ender > begin ? 1 : -1);
! 283: for (*i = 1; *i <= reps || infinity; (*i)++) {
! 284: *y = (double) arc4random() / ULONG_MAX;
! 285: putdata(*y * *x + begin, reps - *i);
! 286: }
! 287: }
! 288: else
! 289: for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
! 290: putdata(*x, reps - *i);
! 291: if (!nofinalnl)
! 292: putchar('\n');
! 293: exit(0);
1.1 deraadt 294: }
295:
296: void
297: putdata(x, notlast)
298: double x;
299: long notlast;
300: {
301: long d = x;
1.8 ! pjanzen 302: long *dp = &d;
1.1 deraadt 303:
304: if (boring) /* repeated word */
305: printf("%s", format);
306: else if (dox) /* scalar */
307: printf(format, *dp);
308: else /* real */
309: printf(format, x);
310: if (notlast != 0)
311: fputs(sepstring, stdout);
312: }
313:
1.7 aaron 314: static void
315: usage(void)
1.1 deraadt 316: {
1.7 aaron 317: (void)fprintf(stderr, "usage: jot [-cnr] [-b word] [-w word] "
318: "[-s string] [-p precision] [reps [begin [end [s]]]]\n");
1.1 deraadt 319: exit(1);
320: }
321:
322: int
323: getprec(s)
324: char *s;
325: {
1.8 ! pjanzen 326: char *p;
! 327: char *q;
1.1 deraadt 328:
329: for (p = s; *p; p++)
330: if (*p == '.')
331: break;
332: if (!*p)
333: return (0);
334: for (q = ++p; *p; p++)
335: if (!isdigit(*p))
336: break;
337: return (p - q);
338: }
339:
340: void
341: getformat()
342: {
1.8 ! pjanzen 343: char *p;
! 344: size_t sz;
1.1 deraadt 345:
346: if (boring) /* no need to bother */
347: return;
348: for (p = format; *p; p++) /* look for '%' */
1.8 ! pjanzen 349: if (*p == '%') {
! 350: if (*(p+1) != '%')
! 351: break;
! 352: p++; /* leave %% alone */
! 353: }
! 354: sz = sizeof(format) - strlen(format) - 1;
! 355: if (!*p && !chardata) {
! 356: if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
! 357: errx(1, "-w word too long");
! 358: } else if (!*p && chardata) {
! 359: if (strlcpy(p, "%c", sz) >= sz)
! 360: errx(1, "-w word too long");
1.1 deraadt 361: dox = 1;
1.8 ! pjanzen 362: } else if (!*(p+1)) {
! 363: if (sz <= 0)
! 364: errx(1, "-w word too long");
1.1 deraadt 365: strcat(format, "%"); /* cannot end in single '%' */
1.8 ! pjanzen 366: } else {
! 367: for (; *p && !isalpha(*p); p++)
! 368: /* Certain nonalphanumerics we can't allow */
! 369: if (*p == '$' || *p == '*')
! 370: break;
! 371: /* Allow 'l' prefix, but no other. */
! 372: if (*p == 'l')
1.1 deraadt 373: p++;
374: switch (*p) {
375: case 'f': case 'e': case 'g': case '%':
1.8 ! pjanzen 376: case 'E': case 'G':
1.1 deraadt 377: break;
378: case 's':
1.8 ! pjanzen 379: errx(1, "cannot convert numeric data to strings");
1.1 deraadt 380: break;
1.8 ! pjanzen 381: case 'd': case 'o': case 'x': case 'u':
! 382: case 'D': case 'O': case 'X': case 'U':
! 383: case 'c': case 'i':
1.1 deraadt 384: dox = 1;
385: break;
1.8 ! pjanzen 386: default:
! 387: errx(1, "unknown or invalid format `%s'", format);
1.1 deraadt 388: }
1.8 ! pjanzen 389: /* Need to check for trailing stuff to print */
! 390: for (; *p; p++) /* look for '%' */
! 391: if (*p == '%') {
! 392: if (*(p+1) != '%')
! 393: break;
! 394: p++; /* leave %% alone */
! 395: }
! 396: if (*p)
! 397: errx(1, "unknown or invalid format `%s'", format);
1.1 deraadt 398: }
399: }