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