jot.c (7d71f06cb47227f16ac20155c202725aa2b3d9b2) jot.c (3241f274f1664e7bd5d6dbbf68cac86033134800)
1/*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
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

--- 48 unchanged lines hidden (view full) ---

57#include <stdio.h>
58#include <stdint.h>
59#include <stdlib.h>
60#include <stdbool.h>
61#include <string.h>
62#include <time.h>
63#include <unistd.h>
64
1/*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
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

--- 48 unchanged lines hidden (view full) ---

57#include <stdio.h>
58#include <stdint.h>
59#include <stdlib.h>
60#include <stdbool.h>
61#include <string.h>
62#include <time.h>
63#include <unistd.h>
64
65/* Defaults */
65#define REPS_DEF 100
66#define BEGIN_DEF 1
67#define ENDER_DEF 100
68#define STEP_DEF 1
69
66#define REPS_DEF 100
67#define BEGIN_DEF 1
68#define ENDER_DEF 100
69#define STEP_DEF 1
70
71/* Flags of options that have been set */
70#define HAVE_STEP 1
71#define HAVE_ENDER 2
72#define HAVE_BEGIN 4
73#define HAVE_REPS 8
74
75#define is_default(s) (*(s) == 0 || strcmp((s), "-") == 0)
76
72#define HAVE_STEP 1
73#define HAVE_ENDER 2
74#define HAVE_BEGIN 4
75#define HAVE_REPS 8
76
77#define is_default(s) (*(s) == 0 || strcmp((s), "-") == 0)
78
77double begin;
78double ender;
79double s;
80long reps;
81int randomize;
82int infinity;
83int boring;
84int prec;
85int longdata;
86int intdata;
87int chardata;
88int nosign;
89int nofinalnl;
90const char *sepstring = "\n";
91char format[BUFSIZ];
79static bool boring;
80static int prec;
81static bool longdata;
82static bool intdata;
83static bool chardata;
84static bool nosign;
85static const char *sepstring = "\n";
86static char format[BUFSIZ];
92
87
93void getformat(void);
94int getprec(char *);
95int putdata(double, long);
88static void getformat(void);
89static int getprec(const char *);
90static int putdata(double, bool);
96static void usage(void);
97
98int
99main(int argc, char **argv)
100{
91static void usage(void);
92
93int
94main(int argc, char **argv)
95{
101 double x, y;
102 long i;
103 unsigned int mask = 0;
104 int n = 0;
105 int ch;
106 bool use_random = false;
107 bool have_format = false;
96 bool have_format = false;
97 bool infinity = false;
98 bool nofinalnl = false;
99 bool randomize = false;
100 bool use_random = false;
101 int ch;
102 int mask = 0;
103 int n = 0;
104 double begin;
108 double divisor;
105 double divisor;
106 double ender;
107 double s;
108 double x, y;
109 long i;
110 long reps;
109
111
110 while ((ch = getopt(argc, argv, "rb:w:cs:np:")) != -1)
112 while ((ch = getopt(argc, argv, "b:cnp:rs:w:")) != -1)
111 switch (ch) {
113 switch (ch) {
112 case 'r':
113 randomize = 1;
114 break;
115 case 'c':
116 chardata = 1;
117 break;
118 case 'n':
119 nofinalnl = 1;
120 break;
121 case 'b':
114 case 'b':
122 boring = 1;
115 boring = true;
123 /* FALLTHROUGH */
124 case 'w':
125 if (strlcpy(format, optarg, sizeof(format)) >=
126 sizeof(format))
127 errx(1, "-%c word too long", ch);
128 have_format = true;
129 break;
116 /* FALLTHROUGH */
117 case 'w':
118 if (strlcpy(format, optarg, sizeof(format)) >=
119 sizeof(format))
120 errx(1, "-%c word too long", ch);
121 have_format = true;
122 break;
130 case 's':
131 sepstring = optarg;
123 case 'c':
124 chardata = true;
132 break;
125 break;
126 case 'n':
127 nofinalnl = true;
128 break;
133 case 'p':
134 prec = atoi(optarg);
135 if (prec <= 0)
136 errx(1, "bad precision value");
137 have_format = true;
138 break;
129 case 'p':
130 prec = atoi(optarg);
131 if (prec <= 0)
132 errx(1, "bad precision value");
133 have_format = true;
134 break;
135 case 'r':
136 randomize = true;
137 break;
138 case 's':
139 sepstring = optarg;
140 break;
139 default:
140 usage();
141 }
142 argc -= optind;
143 argv += optind;
144
145 switch (argc) { /* examine args right to left, falling thru cases */
146 case 4:

--- 111 unchanged lines hidden (view full) ---

258 reps = t;
259 }
260 mask = 0;
261 break;
262 default:
263 errx(1, "bad mask");
264 }
265 if (reps == 0)
141 default:
142 usage();
143 }
144 argc -= optind;
145 argv += optind;
146
147 switch (argc) { /* examine args right to left, falling thru cases */
148 case 4:

--- 111 unchanged lines hidden (view full) ---

260 reps = t;
261 }
262 mask = 0;
263 break;
264 default:
265 errx(1, "bad mask");
266 }
267 if (reps == 0)
266 infinity = 1;
268 infinity = true;
267 if (randomize) {
268 if (use_random) {
269 srandom((unsigned long)s);
270 divisor = (double)INT32_MAX + 1;
271 } else
272 divisor = (double)UINT32_MAX + 1;
273
274 /*
275 * Attempt to DWIM when the user has specified an
276 * integer range within that of the random number
277 * generator: distribute the numbers equally in
278 * the range [begin .. ender]. Jot's default %.0f
279 * format would make the appearance of the first and
280 * last specified value half as likely as the rest.
281 */
282 if (!have_format && prec == 0 &&
283 begin >= 0 && begin < divisor &&
284 ender >= 0 && ender < divisor) {
285 ender += 1;
269 if (randomize) {
270 if (use_random) {
271 srandom((unsigned long)s);
272 divisor = (double)INT32_MAX + 1;
273 } else
274 divisor = (double)UINT32_MAX + 1;
275
276 /*
277 * Attempt to DWIM when the user has specified an
278 * integer range within that of the random number
279 * generator: distribute the numbers equally in
280 * the range [begin .. ender]. Jot's default %.0f
281 * format would make the appearance of the first and
282 * last specified value half as likely as the rest.
283 */
284 if (!have_format && prec == 0 &&
285 begin >= 0 && begin < divisor &&
286 ender >= 0 && ender < divisor) {
287 ender += 1;
286 nosign = 1;
287 intdata = 1;
288 nosign = true;
289 intdata = true;
288 (void)strlcpy(format,
289 chardata ? "%c" : "%u", sizeof(format));
290 }
291 x = (ender - begin) * (ender > begin ? 1 : -1);
292 for (i = 1; i <= reps || infinity; i++) {
293 if (use_random)
294 y = random() / divisor;
295 else
296 y = arc4random() / divisor;
290 (void)strlcpy(format,
291 chardata ? "%c" : "%u", sizeof(format));
292 }
293 x = (ender - begin) * (ender > begin ? 1 : -1);
294 for (i = 1; i <= reps || infinity; i++) {
295 if (use_random)
296 y = random() / divisor;
297 else
298 y = arc4random() / divisor;
297 if (putdata(y * x + begin, reps - i))
299 if (putdata(y * x + begin, !(reps - i)))
298 errx(1, "range error in conversion");
299 }
300 } else
301 for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
300 errx(1, "range error in conversion");
301 }
302 } else
303 for (i = 1, x = begin; i <= reps || infinity; i++, x += s)
302 if (putdata(x, reps - i))
304 if (putdata(x, !(reps - i)))
303 errx(1, "range error in conversion");
304 if (!nofinalnl)
305 putchar('\n');
306 exit(0);
307}
308
305 errx(1, "range error in conversion");
306 if (!nofinalnl)
307 putchar('\n');
308 exit(0);
309}
310
309int
310putdata(double x, long int notlast)
311/*
312 * Send x to stdout using the specified format.
313 * Last is true if this is the set's last value.
314 * Return 0 if OK, or a positive number if the number passed was
315 * outside the range specified by the various flags.
316 */
317static int
318putdata(double x, bool last)
311{
312
313 if (boring)
314 printf("%s", format);
315 else if (longdata && nosign) {
316 if (x <= (double)ULONG_MAX && x >= (double)0)
317 printf(format, (unsigned long)x);
318 else

--- 11 unchanged lines hidden (view full) ---

330 } else if (intdata) {
331 if (x <= (double)UINT_MAX && x >= (double)0)
332 printf(format, (unsigned int)x);
333 else
334 return (1);
335
336 } else
337 printf(format, x);
319{
320
321 if (boring)
322 printf("%s", format);
323 else if (longdata && nosign) {
324 if (x <= (double)ULONG_MAX && x >= (double)0)
325 printf(format, (unsigned long)x);
326 else

--- 11 unchanged lines hidden (view full) ---

338 } else if (intdata) {
339 if (x <= (double)UINT_MAX && x >= (double)0)
340 printf(format, (unsigned int)x);
341 else
342 return (1);
343
344 } else
345 printf(format, x);
338 if (notlast != 0)
346 if (!last)
339 fputs(sepstring, stdout);
340
341 return (0);
342}
343
344static void
345usage(void)
346{
347 fprintf(stderr, "%s\n%s\n",
348 "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
349 " [reps [begin [end [s]]]]");
350 exit(1);
351}
352
347 fputs(sepstring, stdout);
348
349 return (0);
350}
351
352static void
353usage(void)
354{
355 fprintf(stderr, "%s\n%s\n",
356 "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]",
357 " [reps [begin [end [s]]]]");
358 exit(1);
359}
360
353int
354getprec(char *str)
361/*
362 * Return the number of digits following the number's decimal point.
363 * Return 0 if no decimal point is found.
364 */
365static int
366getprec(const char *str)
355{
367{
356 char *p;
357 char *q;
368 const char *p;
369 const char *q;
358
359 for (p = str; *p; p++)
360 if (*p == '.')
361 break;
362 if (!*p)
363 return (0);
364 for (q = ++p; *p; p++)
365 if (!isdigit((unsigned char)*p))
366 break;
367 return (p - q);
368}
369
370
371 for (p = str; *p; p++)
372 if (*p == '.')
373 break;
374 if (!*p)
375 return (0);
376 for (q = ++p; *p; p++)
377 if (!isdigit((unsigned char)*p))
378 break;
379 return (p - q);
380}
381
370void
382/*
383 * Set format, intdata, chardata, longdata, and nosign
384 * based on the command line arguments.
385 */
386static void
371getformat(void)
372{
373 char *p, *p2;
374 int dot, hash, space, sign, numbers = 0;
375 size_t sz;
376
377 if (boring) /* no need to bother */
378 return;
379 for (p = format; *p; p++) /* look for '%' */
380 if (*p == '%' && *(p+1) != '%') /* leave %% alone */
381 break;
382 sz = sizeof(format) - strlen(format) - 1;
383 if (!*p && !chardata) {
384 if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
385 errx(1, "-w word too long");
386 } else if (!*p && chardata) {
387 if (strlcpy(p, "%c", sz) >= sz)
388 errx(1, "-w word too long");
387getformat(void)
388{
389 char *p, *p2;
390 int dot, hash, space, sign, numbers = 0;
391 size_t sz;
392
393 if (boring) /* no need to bother */
394 return;
395 for (p = format; *p; p++) /* look for '%' */
396 if (*p == '%' && *(p+1) != '%') /* leave %% alone */
397 break;
398 sz = sizeof(format) - strlen(format) - 1;
399 if (!*p && !chardata) {
400 if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
401 errx(1, "-w word too long");
402 } else if (!*p && chardata) {
403 if (strlcpy(p, "%c", sz) >= sz)
404 errx(1, "-w word too long");
389 intdata = 1;
405 intdata = true;
390 } else if (!*(p+1)) {
391 if (sz <= 0)
392 errx(1, "-w word too long");
393 strcat(format, "%"); /* cannot end in single '%' */
394 } else {
395 /*
396 * Allow conversion format specifiers of the form
397 * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of

--- 10 unchanged lines hidden (view full) ---

408 (*p == ' ' && !(numbers|dot|space++)) ||
409 ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
410 || (*p == '.' && !(dot++)))
411 p++;
412 else
413 goto fmt_broken;
414 }
415 if (*p == 'l') {
406 } else if (!*(p+1)) {
407 if (sz <= 0)
408 errx(1, "-w word too long");
409 strcat(format, "%"); /* cannot end in single '%' */
410 } else {
411 /*
412 * Allow conversion format specifiers of the form
413 * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of

--- 10 unchanged lines hidden (view full) ---

424 (*p == ' ' && !(numbers|dot|space++)) ||
425 ((*p == '+' || *p == '-') && !(numbers|dot|sign++))
426 || (*p == '.' && !(dot++)))
427 p++;
428 else
429 goto fmt_broken;
430 }
431 if (*p == 'l') {
416 longdata = 1;
432 longdata = true;
417 if (*++p == 'l') {
418 if (p[1] != '\0')
419 p++;
420 goto fmt_broken;
421 }
422 }
423 switch (*p) {
424 case 'o': case 'u': case 'x': case 'X':
433 if (*++p == 'l') {
434 if (p[1] != '\0')
435 p++;
436 goto fmt_broken;
437 }
438 }
439 switch (*p) {
440 case 'o': case 'u': case 'x': case 'X':
425 intdata = nosign = 1;
441 intdata = nosign = true;
426 break;
427 case 'd': case 'i':
442 break;
443 case 'd': case 'i':
428 intdata = 1;
444 intdata = true;
429 break;
430 case 'D':
431 if (!longdata) {
445 break;
446 case 'D':
447 if (!longdata) {
432 intdata = 1;
448 intdata = true;
433 break;
434 }
435 case 'O': case 'U':
436 if (!longdata) {
449 break;
450 }
451 case 'O': case 'U':
452 if (!longdata) {
437 intdata = nosign = 1;
453 intdata = nosign = true;
438 break;
439 }
440 case 'c':
441 if (!(intdata | longdata)) {
454 break;
455 }
456 case 'c':
457 if (!(intdata | longdata)) {
442 chardata = 1;
458 chardata = true;
443 break;
444 }
445 case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
446 case '$': case '*':
447 goto fmt_broken;
448 case 'f': case 'e': case 'g': case 'E': case 'G':
449 if (!longdata)
450 break;

--- 18 unchanged lines hidden ---
459 break;
460 }
461 case 'h': case 'n': case 'p': case 'q': case 's': case 'L':
462 case '$': case '*':
463 goto fmt_broken;
464 case 'f': case 'e': case 'g': case 'E': case 'G':
465 if (!longdata)
466 break;

--- 18 unchanged lines hidden ---