kernel - Remove cache ping-pong on common scheduler operations
[dragonfly.git] / usr.bin / jot / jot.c
blob9263b7d047dc6d399c08fcfa4a174b2ddadc82c8
1 /*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
29 * @(#) Copyright (c) 1993 The Regents of the University of California. All rights reserved.
30 * @(#)jot.c 8.1 (Berkeley) 6/6/93
31 * $FreeBSD: src/usr.bin/jot/jot.c,v 1.13.2.3 2001/12/17 13:49:50 gallatin Exp $
35 * jot - print sequential or random data
37 * Author: John Kunze, Office of Comp. Affairs, UCB
40 #include <ctype.h>
41 #include <err.h>
42 #include <limits.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <stdint.h>
46 #include <string.h>
47 #include <time.h>
48 #include <unistd.h>
50 #define REPS_DEF 100
51 #define BEGIN_DEF 1
52 #define ENDER_DEF 100
53 #define STEP_DEF 1
55 #define is_default(s) (strcmp((s), "-") == 0)
57 int randomize;
58 int infinity;
59 int boring;
60 int prec;
61 int longdata;
62 int intdata;
63 int chardata;
64 int nosign;
65 int nofinalnl;
66 static const char *sepstring = "\n";
67 static char format[BUFSIZ];
69 static void getformat(void);
70 static int getprec(const char *);
71 static int putdata(double, long);
72 static void usage(void) __dead2;
74 int
75 main(int argc, char **argv)
77 double xd, yd;
78 long id;
79 double *x = &xd;
80 double *y = &yd;
81 long *i = &id;
82 unsigned int mask = 0;
83 int n = 0;
84 int ch;
85 double begin = BEGIN_DEF;
86 double ender = ENDER_DEF;
87 double s = STEP_DEF;
88 long reps = REPS_DEF;
90 while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1)
91 switch ((char)ch) {
92 case 'r':
93 randomize = 1;
94 break;
95 case 'c':
96 chardata = 1;
97 break;
98 case 'n':
99 nofinalnl = 1;
100 break;
101 case 'b':
102 boring = 1;
103 /* FALLTHROUGH */
104 case 'w':
105 if (strlcpy(format, optarg, sizeof(format)) >=
106 sizeof(format))
107 errx(1, "-%c word too long", ch);
108 break;
109 case 's':
110 sepstring = optarg;
111 break;
112 case 'p':
113 prec = atoi(optarg);
114 if (prec <= 0)
115 errx(1, "bad precision value");
116 break;
117 default:
118 usage();
120 argc -= optind;
121 argv += optind;
123 switch (argc) { /* examine args right to left, falling thru cases */
124 case 4:
125 if (!is_default(argv[3])) {
126 if (!sscanf(argv[3], "%lf", &s))
127 errx(1, "bad s value: %s", argv[3]);
128 mask |= 01;
130 /* FALLTHROUGH */
131 case 3:
132 if (!is_default(argv[2])) {
133 if (!sscanf(argv[2], "%lf", &ender))
134 ender = argv[2][strlen(argv[2])-1];
135 mask |= 02;
136 if (!prec)
137 n = getprec(argv[2]);
139 /* FALLTHROUGH */
140 case 2:
141 if (!is_default(argv[1])) {
142 if (!sscanf(argv[1], "%lf", &begin))
143 begin = argv[1][strlen(argv[1])-1];
144 mask |= 04;
145 if (!prec)
146 prec = getprec(argv[1]);
147 if (n > prec) /* maximum precision */
148 prec = n;
150 /* FALLTHROUGH */
151 case 1:
152 if (!is_default(argv[0])) {
153 if (!sscanf(argv[0], "%ld", &reps))
154 errx(1, "bad reps value: %s", argv[0]);
155 mask |= 010;
157 break;
158 case 0:
159 usage();
160 default:
161 errx(1, "too many arguments. What do you mean by %s?",
162 argv[4]);
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 break;
171 case 002:
172 reps = REPS_DEF;
173 mask = 012;
174 break;
175 case 003:
176 reps = REPS_DEF;
177 mask = 013;
178 break;
179 case 004:
180 reps = REPS_DEF;
181 mask = 014;
182 break;
183 case 005:
184 reps = REPS_DEF;
185 mask = 015;
186 break;
187 case 006:
188 reps = REPS_DEF;
189 mask = 016;
190 break;
191 case 007:
192 if (randomize) {
193 reps = REPS_DEF;
194 mask = 0;
195 break;
197 if (s == 0.0) {
198 reps = 0;
199 mask = 0;
200 break;
202 reps = (ender - begin + s) / s;
203 if (reps <= 0)
204 errx(1, "impossible stepsize");
205 mask = 0;
206 break;
207 case 010:
208 begin = BEGIN_DEF;
209 mask = 014;
210 break;
211 case 011:
212 begin = BEGIN_DEF;
213 mask = 015;
214 break;
215 case 012:
216 s = (randomize ? time(NULL) : STEP_DEF);
217 mask = 013;
218 break;
219 case 013:
220 if (randomize)
221 begin = BEGIN_DEF;
222 else if (reps == 0)
223 errx(1, "must specify begin if reps == 0");
224 begin = ender - reps * s + s;
225 mask = 0;
226 break;
227 case 014:
228 s = (randomize ? -1.0 : STEP_DEF);
229 mask = 015;
230 break;
231 case 015:
232 if (randomize)
233 ender = ENDER_DEF;
234 else
235 ender = begin + reps * s - s;
236 mask = 0;
237 break;
238 case 016:
239 if (randomize)
240 s = -1.0;
241 else if (reps == 0)
242 errx(1, "infinite sequences cannot be bounded");
243 else if (reps == 1)
244 s = 0.0;
245 else
246 s = (ender - begin) / (reps - 1);
247 mask = 0;
248 break;
249 case 017: /* if reps given and implied, */
250 if (!randomize && s != 0.0) {
251 long t = (ender - begin + s) / s;
252 if (t <= 0)
253 errx(1, "impossible stepsize");
254 if (t < reps) /* take lesser */
255 reps = t;
257 mask = 0;
258 break;
259 default:
260 errx(1, "bad mask");
262 if (reps == 0)
263 infinity = 1;
264 if (randomize) {
265 *x = (ender - begin) * (ender > begin ? 1 : -1);
266 for (*i = 1; *i <= reps || infinity; (*i)++) {
267 *y = arc4random() / (double)0xffffffffU;
268 if (putdata(*y * *x + begin, reps - *i))
269 errx(1, "range error in conversion");
271 } else
272 for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
273 if (putdata(*x, reps - *i))
274 errx(1, "range error in conversion");
275 if (!nofinalnl)
276 putchar('\n');
277 exit(0);
280 static int
281 putdata(double x, long notlast)
284 if (boring)
285 printf("%s", format);
286 else if (longdata && nosign) {
287 if (x <= (double)ULONG_MAX && x >= (double)0)
288 printf(format, (unsigned long)x);
289 else
290 return (1);
291 } else if (longdata) {
292 if (x <= (double)LONG_MAX && x >= (double)LONG_MIN)
293 printf(format, (long)x);
294 else
295 return (1);
296 } else if (chardata || (intdata && !nosign)) {
297 if (x <= (double)INT_MAX && x >= (double)INT_MIN)
298 printf(format, (int)x);
299 else
300 return (1);
301 } else if (intdata) {
302 if (x <= (double)UINT_MAX && x >= (double)0)
303 printf(format, (unsigned int)x);
304 else
305 return (1);
307 } else
308 printf(format, x);
309 if (notlast != 0)
310 fputs(sepstring, stdout);
312 return (0);
315 static void
316 usage(void)
318 fprintf(stderr, "%s\n%s\n",
319 "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
320 " [reps [begin [end [s]]]]");
321 exit(1);
324 static int
325 getprec(const char *str)
327 const char *p;
328 const char *q;
330 for (p = str; *p; p++)
331 if (*p == '.')
332 break;
333 if (!*p)
334 return (0);
335 for (q = ++p; *p; p++)
336 if (!isdigit(*p))
337 break;
338 return (p - q);
341 static void
342 getformat(void)
344 char *p, *p2;
345 int dot, hash, space, sign, numbers = 0;
346 size_t sz;
348 if (boring) /* no need to bother */
349 return;
350 for (p = format; *p; p++) /* look for '%' */
351 if (*p == '%' && *(p+1) != '%') /* leave %% alone */
352 break;
353 sz = sizeof(format) - strlen(format) - 1;
354 if (!*p && !chardata) {
355 if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
356 errx(1, "-w word too long");
357 } else if (!*p && chardata) {
358 if (strlcpy(p, "%c", sz) >= sz)
359 errx(1, "-w word too long");
360 intdata = 1;
361 } else if (!*(p+1)) {
362 if (sz <= 0)
363 errx(1, "-w word too long");
364 strcat(format, "%"); /* cannot end in single '%' */
365 } else {
367 * Allow conversion format specifiers of the form
368 * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of
369 * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u}
371 p2 = p++;
372 dot = hash = space = sign = numbers = 0;
373 while (!isalpha(*p)) {
374 if (isdigit(*p)) {
375 numbers++;
376 p++;
377 } else if ((*p == '#' && !(numbers|dot|sign|space|
378 hash++)) ||
379 (*p == ' ' && !(numbers|dot|space++)) ||
380 ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
381 || (*p == '.' && !(dot++)))
382 p++;
383 else
384 goto fmt_broken;
386 if (*p == 'l') {
387 longdata = 1;
388 if (*++p == 'l') {
389 if (p[1] != '\0')
390 p++;
391 goto fmt_broken;
394 switch (*p) {
395 case 'o': case 'u': case 'x': case 'X':
396 intdata = nosign = 1;
397 break;
398 case 'd': case 'i':
399 intdata = 1;
400 break;
401 case 'D':
402 if (longdata)
403 goto fmt_broken;
404 intdata = 1;
405 break;
406 case 'O': case 'U':
407 if (longdata)
408 goto fmt_broken;
409 intdata = nosign = 1;
410 break;
411 case 'c':
412 if (!(intdata | longdata)) {
413 chardata = 1;
414 break;
416 case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
417 case '$': case '*':
418 goto fmt_broken;
419 case 'f': case 'e': case 'g': case 'E': case 'G':
420 if (!longdata)
421 break;
422 /* FALLTHROUGH */
423 default:
424 fmt_broken:
425 *++p = '\0';
426 errx(1, "illegal or unsupported format '%s'", p2);
427 /* NOTREACHED */
429 while (*++p)
430 if (*p == '%' && *(p+1) && *(p+1) != '%')
431 errx(1, "too many conversions");
432 else if (*p == '%' && *(p+1) == '%')
433 p++;
434 else if (*p == '%' && !*(p+1)) {
435 strcat(format, "%");
436 break;