kernel - Fix broken assertion for "pv->pv_m != NULL" panic
[dragonfly.git] / usr.bin / jot / jot.c
blobd38d29c1d0f8118a98b15e56bc5e81ee976185a0
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 $
32 * $DragonFly: src/usr.bin/jot/jot.c,v 1.4 2004/07/31 10:19:53 eirikn Exp $
36 * jot - print sequential or random data
38 * Author: John Kunze, Office of Comp. Affairs, UCB
41 #include <ctype.h>
42 #include <err.h>
43 #include <limits.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <stdint.h>
47 #include <string.h>
48 #include <time.h>
49 #include <unistd.h>
51 #define REPS_DEF 100
52 #define BEGIN_DEF 1
53 #define ENDER_DEF 100
54 #define STEP_DEF 1
56 #define is_default(s) (strcmp((s), "-") == 0)
58 double begin;
59 double ender;
60 double s;
61 long reps;
62 int randomize;
63 int infinity;
64 int boring;
65 int prec;
66 int longdata;
67 int intdata;
68 int chardata;
69 int nosign;
70 int nofinalnl;
71 const char *sepstring = "\n";
72 char format[BUFSIZ];
74 void getformat(void);
75 int getprec(char *);
76 int putdata(double, long);
77 static void usage(void);
79 int
80 main(int argc, char **argv)
82 double xd, yd;
83 long id;
84 double *x = &xd;
85 double *y = &yd;
86 long *i = &id;
87 unsigned int mask = 0;
88 int n = 0;
89 int ch;
91 while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1)
92 switch ((char)ch) {
93 case 'r':
94 randomize = 1;
95 break;
96 case 'c':
97 chardata = 1;
98 break;
99 case 'n':
100 nofinalnl = 1;
101 break;
102 case 'b':
103 boring = 1;
104 /* FALLTHROUGH */
105 case 'w':
106 if (strlcpy(format, optarg, sizeof(format)) >=
107 sizeof(format))
108 errx(1, "-%c word too long", ch);
109 break;
110 case 's':
111 sepstring = optarg;
112 break;
113 case 'p':
114 prec = atoi(optarg);
115 if (prec <= 0)
116 errx(1, "bad precision value");
117 break;
118 default:
119 usage();
121 argc -= optind;
122 argv += optind;
124 switch (argc) { /* examine args right to left, falling thru cases */
125 case 4:
126 if (!is_default(argv[3])) {
127 if (!sscanf(argv[3], "%lf", &s))
128 errx(1, "bad s value: %s", argv[3]);
129 mask |= 01;
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 case 2:
140 if (!is_default(argv[1])) {
141 if (!sscanf(argv[1], "%lf", &begin))
142 begin = argv[1][strlen(argv[1])-1];
143 mask |= 04;
144 if (!prec)
145 prec = getprec(argv[1]);
146 if (n > prec) /* maximum precision */
147 prec = n;
149 case 1:
150 if (!is_default(argv[0])) {
151 if (!sscanf(argv[0], "%ld", &reps))
152 errx(1, "bad reps value: %s", argv[0]);
153 mask |= 010;
155 break;
156 case 0:
157 usage();
158 default:
159 errx(1, "too many arguments. What do you mean by %s?",
160 argv[4]);
162 getformat();
163 while (mask) /* 4 bit mask has 1's where last 4 args were given */
164 switch (mask) { /* fill in the 0's by default or computation */
165 case 001:
166 reps = REPS_DEF;
167 mask = 011;
168 break;
169 case 002:
170 reps = REPS_DEF;
171 mask = 012;
172 break;
173 case 003:
174 reps = REPS_DEF;
175 mask = 013;
176 break;
177 case 004:
178 reps = REPS_DEF;
179 mask = 014;
180 break;
181 case 005:
182 reps = REPS_DEF;
183 mask = 015;
184 break;
185 case 006:
186 reps = REPS_DEF;
187 mask = 016;
188 break;
189 case 007:
190 if (randomize) {
191 reps = REPS_DEF;
192 mask = 0;
193 break;
195 if (s == 0.0) {
196 reps = 0;
197 mask = 0;
198 break;
200 reps = (ender - begin + s) / s;
201 if (reps <= 0)
202 errx(1, "impossible stepsize");
203 mask = 0;
204 break;
205 case 010:
206 begin = BEGIN_DEF;
207 mask = 014;
208 break;
209 case 011:
210 begin = BEGIN_DEF;
211 mask = 015;
212 break;
213 case 012:
214 s = (randomize ? time(NULL) : STEP_DEF);
215 mask = 013;
216 break;
217 case 013:
218 if (randomize)
219 begin = BEGIN_DEF;
220 else if (reps == 0)
221 errx(1, "must specify begin if reps == 0");
222 begin = ender - reps * s + s;
223 mask = 0;
224 break;
225 case 014:
226 s = (randomize ? -1.0 : STEP_DEF);
227 mask = 015;
228 break;
229 case 015:
230 if (randomize)
231 ender = ENDER_DEF;
232 else
233 ender = begin + reps * s - s;
234 mask = 0;
235 break;
236 case 016:
237 if (randomize)
238 s = -1.0;
239 else if (reps == 0)
240 errx(1, "infinite sequences cannot be bounded");
241 else if (reps == 1)
242 s = 0.0;
243 else
244 s = (ender - begin) / (reps - 1);
245 mask = 0;
246 break;
247 case 017: /* if reps given and implied, */
248 if (!randomize && s != 0.0) {
249 long t = (ender - begin + s) / s;
250 if (t <= 0)
251 errx(1, "impossible stepsize");
252 if (t < reps) /* take lesser */
253 reps = t;
255 mask = 0;
256 break;
257 default:
258 errx(1, "bad mask");
260 if (reps == 0)
261 infinity = 1;
262 if (randomize) {
263 *x = (ender - begin) * (ender > begin ? 1 : -1);
264 for (*i = 1; *i <= reps || infinity; (*i)++) {
265 *y = arc4random() / (double)0xffffffffU;
266 if (putdata(*y * *x + begin, reps - *i))
267 errx(1, "range error in conversion");
269 } else
270 for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s)
271 if (putdata(*x, reps - *i))
272 errx(1, "range error in conversion");
273 if (!nofinalnl)
274 putchar('\n');
275 exit(0);
279 putdata(double x, long notlast)
282 if (boring)
283 printf("%s", format);
284 else if (longdata && nosign) {
285 if (x <= (double)ULONG_MAX && x >= (double)0)
286 printf(format, (unsigned long)x);
287 else
288 return (1);
289 } else if (longdata) {
290 if (x <= (double)LONG_MAX && x >= (double)LONG_MIN)
291 printf(format, (long)x);
292 else
293 return (1);
294 } else if (chardata || (intdata && !nosign)) {
295 if (x <= (double)INT_MAX && x >= (double)INT_MIN)
296 printf(format, (int)x);
297 else
298 return (1);
299 } else if (intdata) {
300 if (x <= (double)UINT_MAX && x >= (double)0)
301 printf(format, (unsigned int)x);
302 else
303 return (1);
305 } else
306 printf(format, x);
307 if (notlast != 0)
308 fputs(sepstring, stdout);
310 return (0);
313 static void
314 usage(void)
316 fprintf(stderr, "%s\n%s\n",
317 "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
318 " [reps [begin [end [s]]]]");
319 exit(1);
323 getprec(char *str)
325 char *p;
326 char *q;
328 for (p = str; *p; p++)
329 if (*p == '.')
330 break;
331 if (!*p)
332 return (0);
333 for (q = ++p; *p; p++)
334 if (!isdigit(*p))
335 break;
336 return (p - q);
339 void
340 getformat(void)
342 char *p, *p2;
343 int dot, hash, space, sign, numbers = 0;
344 size_t sz;
346 if (boring) /* no need to bother */
347 return;
348 for (p = format; *p; p++) /* look for '%' */
349 if (*p == '%' && *(p+1) != '%') /* leave %% alone */
350 break;
351 sz = sizeof(format) - strlen(format) - 1;
352 if (!*p && !chardata) {
353 if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
354 errx(1, "-w word too long");
355 } else if (!*p && chardata) {
356 if (strlcpy(p, "%c", sz) >= sz)
357 errx(1, "-w word too long");
358 intdata = 1;
359 } else if (!*(p+1)) {
360 if (sz <= 0)
361 errx(1, "-w word too long");
362 strcat(format, "%"); /* cannot end in single '%' */
363 } else {
365 * Allow conversion format specifiers of the form
366 * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of
367 * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u}
369 p2 = p++;
370 dot = hash = space = sign = numbers = 0;
371 while (!isalpha(*p)) {
372 if (isdigit(*p)) {
373 numbers++;
374 p++;
375 } else if ((*p == '#' && !(numbers|dot|sign|space|
376 hash++)) ||
377 (*p == ' ' && !(numbers|dot|space++)) ||
378 ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
379 || (*p == '.' && !(dot++)))
380 p++;
381 else
382 goto fmt_broken;
384 if (*p == 'l') {
385 longdata = 1;
386 if (*++p == 'l') {
387 if (p[1] != '\0')
388 p++;
389 goto fmt_broken;
392 switch (*p) {
393 case 'o': case 'u': case 'x': case 'X':
394 intdata = nosign = 1;
395 break;
396 case 'd': case 'i':
397 intdata = 1;
398 break;
399 case 'D':
400 if (!longdata) {
401 intdata = 1;
402 break;
404 case 'O': case 'U':
405 if (!longdata) {
406 intdata = nosign = 1;
407 break;
409 case 'c':
410 if (!(intdata | longdata)) {
411 chardata = 1;
412 break;
414 case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
415 case '$': case '*':
416 goto fmt_broken;
417 case 'f': case 'e': case 'g': case 'E': case 'G':
418 if (!longdata)
419 break;
420 /* FALLTHROUGH */
421 default:
422 fmt_broken:
423 *++p = '\0';
424 errx(1, "illegal or unsupported format '%s'", p2);
425 /* NOTREACHED */
427 while (*++p)
428 if (*p == '%' && *(p+1) && *(p+1) != '%')
429 errx(1, "too many conversions");
430 else if (*p == '%' && *(p+1) == '%')
431 p++;
432 else if (*p == '%' && !*(p+1)) {
433 strcat(format, "%");
434 break;