jot.c revision 62871
11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 3. All advertising materials mentioning features or use of this software 141590Srgrimes * must display the following acknowledgement: 151590Srgrimes * This product includes software developed by the University of 161590Srgrimes * California, Berkeley and its contributors. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3527423Scharnierstatic const char copyright[] = 361590Srgrimes"@(#) Copyright (c) 1993\n\ 371590Srgrimes The Regents of the University of California. All rights reserved.\n"; 381590Srgrimes#endif /* not lint */ 391590Srgrimes 401590Srgrimes#ifndef lint 4127423Scharnier#if 0 421590Srgrimesstatic char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93"; 4327423Scharnier#endif 4427423Scharnierstatic const char rcsid[] = 4550477Speter "$FreeBSD: head/usr.bin/jot/jot.c 62871 2000-07-10 06:02:13Z kris $"; 461590Srgrimes#endif /* not lint */ 471590Srgrimes 481590Srgrimes/* 491590Srgrimes * jot - print sequential or random data 501590Srgrimes * 511590Srgrimes * Author: John Kunze, Office of Comp. Affairs, UCB 521590Srgrimes */ 531590Srgrimes 541590Srgrimes#include <ctype.h> 5527423Scharnier#include <err.h> 561590Srgrimes#include <limits.h> 571590Srgrimes#include <stdio.h> 581590Srgrimes#include <stdlib.h> 591590Srgrimes#include <string.h> 601590Srgrimes#include <time.h> 6123511Sache#include <unistd.h> 621590Srgrimes 631590Srgrimes#define REPS_DEF 100 641590Srgrimes#define BEGIN_DEF 1 651590Srgrimes#define ENDER_DEF 100 661590Srgrimes#define STEP_DEF 1 671590Srgrimes 681590Srgrimes#define isdefault(s) (strcmp((s), "-") == 0) 691590Srgrimes 701590Srgrimesdouble begin; 711590Srgrimesdouble ender; 721590Srgrimesdouble s; 731590Srgrimeslong reps; 741590Srgrimesint randomize; 751590Srgrimesint infinity; 761590Srgrimesint boring; 771590Srgrimesint prec; 7855515Ssheldonhint longdata; 7948995Ssheldonhint intdata; 801590Srgrimesint chardata; 8148995Ssheldonhint nosign; 821590Srgrimesint nofinalnl; 831590Srgrimeschar *sepstring = "\n"; 841590Srgrimeschar format[BUFSIZ]; 851590Srgrimes 861590Srgrimesvoid getargs __P((int, char *[])); 871590Srgrimesvoid getformat __P((void)); 8827423Scharnierint getprec __P((char *)); 8955515Ssheldonhint putdata __P((double, long)); 9027423Scharnierstatic void usage __P((void)); 911590Srgrimes 921590Srgrimesint 931590Srgrimesmain(argc, argv) 941590Srgrimes int argc; 951590Srgrimes char *argv[]; 961590Srgrimes{ 971590Srgrimes double xd, yd; 981590Srgrimes long id; 991590Srgrimes register double *x = &xd; 1001590Srgrimes register double *y = &yd; 1011590Srgrimes register long *i = &id; 1021590Srgrimes 1031590Srgrimes getargs(argc, argv); 1041590Srgrimes if (randomize) { 1051590Srgrimes *x = (ender - begin) * (ender > begin ? 1 : -1); 1061590Srgrimes for (*i = 1; *i <= reps || infinity; (*i)++) { 10747107Skris *y = (double) arc4random() / ULONG_MAX; 10855515Ssheldonh if (putdata(*y * *x + begin, reps - *i)) 10955515Ssheldonh errx(1, "range error in conversion"); 1101590Srgrimes } 11148995Ssheldonh } else 1121590Srgrimes for (*i = 1, *x = begin; *i <= reps || infinity; (*i)++, *x += s) 11355515Ssheldonh if (putdata(*x, reps - *i)) 11455515Ssheldonh errx(1, "range error in conversion"); 1151590Srgrimes if (!nofinalnl) 1161590Srgrimes putchar('\n'); 1171590Srgrimes exit(0); 1181590Srgrimes} 1191590Srgrimes 1201590Srgrimesvoid 1211590Srgrimesgetargs(ac, av) 1221590Srgrimes int ac; 1231590Srgrimes char *av[]; 1241590Srgrimes{ 1251590Srgrimes register unsigned int mask = 0; 1261590Srgrimes register int n = 0; 1271590Srgrimes 1281590Srgrimes while (--ac && **++av == '-' && !isdefault(*av)) 1291590Srgrimes switch ((*av)[1]) { 1301590Srgrimes case 'r': 1311590Srgrimes randomize = 1; 1321590Srgrimes break; 1331590Srgrimes case 'c': 1341590Srgrimes chardata = 1; 1351590Srgrimes break; 1361590Srgrimes case 'n': 1371590Srgrimes nofinalnl = 1; 1381590Srgrimes break; 1391590Srgrimes case 'b': 1401590Srgrimes boring = 1; 1411590Srgrimes case 'w': 1421590Srgrimes if ((*av)[2]) 1431590Srgrimes strcpy(format, *av + 2); 1441590Srgrimes else if (!--ac) 14527423Scharnier errx(1, "need context word after -w or -b"); 1461590Srgrimes else 1471590Srgrimes strcpy(format, *++av); 1481590Srgrimes break; 1491590Srgrimes case 's': 1501590Srgrimes if ((*av)[2]) 15113101Sjoerg sepstring = *av + 2; 1521590Srgrimes else if (!--ac) 15327423Scharnier errx(1, "need string after -s"); 1541590Srgrimes else 15513101Sjoerg sepstring = *++av; 1561590Srgrimes break; 1571590Srgrimes case 'p': 1581590Srgrimes if ((*av)[2]) 1591590Srgrimes prec = atoi(*av + 2); 1601590Srgrimes else if (!--ac) 16127423Scharnier errx(1, "need number after -p"); 1621590Srgrimes else 1631590Srgrimes prec = atoi(*++av); 1641590Srgrimes if (prec <= 0) 16527423Scharnier errx(1, "bad precision value"); 1661590Srgrimes break; 1671590Srgrimes default: 16827423Scharnier usage(); 1691590Srgrimes } 1701590Srgrimes 1711590Srgrimes switch (ac) { /* examine args right to left, falling thru cases */ 1721590Srgrimes case 4: 1731590Srgrimes if (!isdefault(av[3])) { 1741590Srgrimes if (!sscanf(av[3], "%lf", &s)) 17527423Scharnier errx(1, "bad s value: %s", av[3]); 1761590Srgrimes mask |= 01; 1771590Srgrimes } 1781590Srgrimes case 3: 1791590Srgrimes if (!isdefault(av[2])) { 1801590Srgrimes if (!sscanf(av[2], "%lf", &ender)) 1811590Srgrimes ender = av[2][strlen(av[2])-1]; 1821590Srgrimes mask |= 02; 1831590Srgrimes if (!prec) 1841590Srgrimes n = getprec(av[2]); 1851590Srgrimes } 1861590Srgrimes case 2: 1871590Srgrimes if (!isdefault(av[1])) { 1881590Srgrimes if (!sscanf(av[1], "%lf", &begin)) 1891590Srgrimes begin = av[1][strlen(av[1])-1]; 1901590Srgrimes mask |= 04; 1911590Srgrimes if (!prec) 1921590Srgrimes prec = getprec(av[1]); 1931590Srgrimes if (n > prec) /* maximum precision */ 1941590Srgrimes prec = n; 1951590Srgrimes } 1961590Srgrimes case 1: 1971590Srgrimes if (!isdefault(av[0])) { 1981590Srgrimes if (!sscanf(av[0], "%ld", &reps)) 19927423Scharnier errx(1, "bad reps value: %s", av[0]); 2001590Srgrimes mask |= 010; 2011590Srgrimes } 2021590Srgrimes break; 2031590Srgrimes case 0: 20427423Scharnier usage(); 2051590Srgrimes default: 20627423Scharnier errx(1, "too many arguments. What do you mean by %s?", av[4]); 2071590Srgrimes } 2081590Srgrimes getformat(); 2091590Srgrimes while (mask) /* 4 bit mask has 1's where last 4 args were given */ 2101590Srgrimes switch (mask) { /* fill in the 0's by default or computation */ 2111590Srgrimes case 001: 2121590Srgrimes reps = REPS_DEF; 2131590Srgrimes mask = 011; 2141590Srgrimes break; 2151590Srgrimes case 002: 2161590Srgrimes reps = REPS_DEF; 2171590Srgrimes mask = 012; 2181590Srgrimes break; 2191590Srgrimes case 003: 2201590Srgrimes reps = REPS_DEF; 2211590Srgrimes mask = 013; 2221590Srgrimes break; 2231590Srgrimes case 004: 2241590Srgrimes reps = REPS_DEF; 2251590Srgrimes mask = 014; 2261590Srgrimes break; 2271590Srgrimes case 005: 2281590Srgrimes reps = REPS_DEF; 2291590Srgrimes mask = 015; 2301590Srgrimes break; 2311590Srgrimes case 006: 2321590Srgrimes reps = REPS_DEF; 2331590Srgrimes mask = 016; 2341590Srgrimes break; 2351590Srgrimes case 007: 2361590Srgrimes if (randomize) { 2371590Srgrimes reps = REPS_DEF; 2381590Srgrimes mask = 0; 2391590Srgrimes break; 2401590Srgrimes } 2411590Srgrimes if (s == 0.0) { 2421590Srgrimes reps = 0; 2431590Srgrimes mask = 0; 2441590Srgrimes break; 2451590Srgrimes } 2461590Srgrimes reps = (ender - begin + s) / s; 2471590Srgrimes if (reps <= 0) 24827423Scharnier errx(1, "impossible stepsize"); 2491590Srgrimes mask = 0; 2501590Srgrimes break; 2511590Srgrimes case 010: 2521590Srgrimes begin = BEGIN_DEF; 2531590Srgrimes mask = 014; 2541590Srgrimes break; 2551590Srgrimes case 011: 2561590Srgrimes begin = BEGIN_DEF; 2571590Srgrimes mask = 015; 2581590Srgrimes break; 2591590Srgrimes case 012: 26024419Sache s = (randomize ? -1.0 : STEP_DEF); 2611590Srgrimes mask = 013; 2621590Srgrimes break; 2631590Srgrimes case 013: 2641590Srgrimes if (randomize) 2651590Srgrimes begin = BEGIN_DEF; 2661590Srgrimes else if (reps == 0) 26727423Scharnier errx(1, "must specify begin if reps == 0"); 26824419Sache else 26924419Sache begin = ender - reps * s + s; 2701590Srgrimes mask = 0; 2711590Srgrimes break; 2721590Srgrimes case 014: 27324419Sache s = (randomize ? -1.0 : STEP_DEF); 2741590Srgrimes mask = 015; 2751590Srgrimes break; 2761590Srgrimes case 015: 2771590Srgrimes if (randomize) 2781590Srgrimes ender = ENDER_DEF; 2791590Srgrimes else 2801590Srgrimes ender = begin + reps * s - s; 2811590Srgrimes mask = 0; 2821590Srgrimes break; 2831590Srgrimes case 016: 2841590Srgrimes if (randomize) 28524419Sache s = -1.0; 2861590Srgrimes else if (reps == 0) 28727423Scharnier errx(1, "infinite sequences cannot be bounded"); 2881590Srgrimes else if (reps == 1) 2891590Srgrimes s = 0.0; 2901590Srgrimes else 2911590Srgrimes s = (ender - begin) / (reps - 1); 2921590Srgrimes mask = 0; 2931590Srgrimes break; 2941590Srgrimes case 017: /* if reps given and implied, */ 2951590Srgrimes if (!randomize && s != 0.0) { 2961590Srgrimes long t = (ender - begin + s) / s; 2971590Srgrimes if (t <= 0) 29827423Scharnier errx(1, "impossible stepsize"); 2991590Srgrimes if (t < reps) /* take lesser */ 3001590Srgrimes reps = t; 3011590Srgrimes } 3021590Srgrimes mask = 0; 3031590Srgrimes break; 3041590Srgrimes default: 30527423Scharnier errx(1, "bad mask"); 3061590Srgrimes } 3071590Srgrimes if (reps == 0) 3081590Srgrimes infinity = 1; 3091590Srgrimes} 3101590Srgrimes 31155515Ssheldonhint 3121590Srgrimesputdata(x, notlast) 3131590Srgrimes double x; 3141590Srgrimes long notlast; 3151590Srgrimes{ 3161590Srgrimes 31755515Ssheldonh if (boring) 31862871Skris printf("%s", format); 31955515Ssheldonh else if (longdata && nosign) { 32055515Ssheldonh if (x <= (double)ULONG_MAX && x >= (double)0) 32155515Ssheldonh printf(format, (unsigned long)x); 32255515Ssheldonh else 32355515Ssheldonh return (1); 32455515Ssheldonh } else if (longdata) { 32555515Ssheldonh if (x <= (double)LONG_MAX && x >= (double)LONG_MIN) 32655515Ssheldonh printf(format, (long)x); 32755515Ssheldonh else 32855515Ssheldonh return (1); 32955515Ssheldonh } else if (chardata || (intdata && !nosign)) { 33055515Ssheldonh if (x <= (double)INT_MAX && x >= (double)INT_MIN) 33155515Ssheldonh printf(format, (int)x); 33255515Ssheldonh else 33355515Ssheldonh return (1); 33455515Ssheldonh } else if (intdata) { 33555515Ssheldonh if (x <= (double)UINT_MAX && x >= (double)0) 33655515Ssheldonh printf(format, (unsigned int)x); 33755515Ssheldonh else 33855515Ssheldonh return (1); 33955515Ssheldonh 34055515Ssheldonh } else 3411590Srgrimes printf(format, x); 3421590Srgrimes if (notlast != 0) 3431590Srgrimes fputs(sepstring, stdout); 34455515Ssheldonh 34555515Ssheldonh return (0); 3461590Srgrimes} 3471590Srgrimes 34827423Scharnierstatic void 34927423Scharnierusage() 3501590Srgrimes{ 35127423Scharnier fprintf(stderr, "%s\n%s\n", 35230908Scharnier "usage: jot [-cnr] [-b word] [-w word] [-s string] [-p precision]", 35330908Scharnier " [reps [begin [end [s]]]]"); 3541590Srgrimes exit(1); 3551590Srgrimes} 3561590Srgrimes 3571590Srgrimesint 3581590Srgrimesgetprec(s) 3591590Srgrimes char *s; 3601590Srgrimes{ 3611590Srgrimes register char *p; 3621590Srgrimes register char *q; 3631590Srgrimes 3641590Srgrimes for (p = s; *p; p++) 3651590Srgrimes if (*p == '.') 3661590Srgrimes break; 3671590Srgrimes if (!*p) 3681590Srgrimes return (0); 3691590Srgrimes for (q = ++p; *p; p++) 3701590Srgrimes if (!isdigit(*p)) 3711590Srgrimes break; 3721590Srgrimes return (p - q); 3731590Srgrimes} 3741590Srgrimes 3751590Srgrimesvoid 3761590Srgrimesgetformat() 3771590Srgrimes{ 3781590Srgrimes register char *p; 37955515Ssheldonh int dot, hash, space, sign, numbers = 0; 38048995Ssheldonh char *s; 3811590Srgrimes 3821590Srgrimes if (boring) /* no need to bother */ 3831590Srgrimes return; 3841590Srgrimes for (p = format; *p; p++) /* look for '%' */ 3851590Srgrimes if (*p == '%' && *(p+1) != '%') /* leave %% alone */ 3861590Srgrimes break; 3871590Srgrimes if (!*p && !chardata) 3881590Srgrimes sprintf(p, "%%.%df", prec); 3891590Srgrimes else if (!*p && chardata) { 3901590Srgrimes strcpy(p, "%c"); 39148995Ssheldonh intdata = 1; 39248995Ssheldonh } else if (!*(p+1)) 3931590Srgrimes strcat(format, "%"); /* cannot end in single '%' */ 3941590Srgrimes else { 39548995Ssheldonh /* 39648995Ssheldonh * Allow conversion format specifiers of the form 39748995Ssheldonh * %[#][ ][{+,-}][0-9]*[.[0-9]*]? where ? must be one of 39848995Ssheldonh * [l]{d,i,o,u,x} or {f,e,g,E,G,d,o,x,D,O,U,X,c,u} 39948995Ssheldonh */ 40048995Ssheldonh s = p++; 40148995Ssheldonh dot = hash = space = sign = numbers = 0; 40248995Ssheldonh while (!isalpha(*p)) { 40348995Ssheldonh if (isdigit(*p)) { 40448995Ssheldonh numbers++; 40548995Ssheldonh p++; 40648995Ssheldonh } else if ((*p == '#' && !(numbers|dot|sign|space| 40748995Ssheldonh hash++)) || 40848995Ssheldonh (*p == ' ' && !(numbers|dot|space++)) || 40948995Ssheldonh ((*p == '+' || *p == '-') && !(numbers|dot|sign++)) 41048995Ssheldonh || (*p == '.' && !(dot++))) 41148995Ssheldonh p++; 41248995Ssheldonh else 41355515Ssheldonh goto fmt_broken; 41448995Ssheldonh } 41555515Ssheldonh if (*p == 'l') { 41655515Ssheldonh longdata = 1; 41755515Ssheldonh if (*++p == 'l') { 41855515Ssheldonh if (p[1] != '\0') 41955515Ssheldonh p++; 42055515Ssheldonh goto fmt_broken; 42155515Ssheldonh } 42255515Ssheldonh } 42348995Ssheldonh switch (*p) { 42448995Ssheldonh case 'o': case 'u': case 'x': case 'X': 42548995Ssheldonh intdata = nosign = 1; 4261590Srgrimes break; 42748995Ssheldonh case 'd': case 'i': 42848995Ssheldonh intdata = 1; 42948995Ssheldonh break; 43048995Ssheldonh case 'D': 43155515Ssheldonh if (!longdata) { 43248995Ssheldonh intdata = 1; 43348995Ssheldonh break; 43448995Ssheldonh } 43548995Ssheldonh case 'O': case 'U': 43655515Ssheldonh if (!longdata) { 43748995Ssheldonh intdata = nosign = 1; 43848995Ssheldonh break; 43948995Ssheldonh } 44048995Ssheldonh case 'c': 44155515Ssheldonh if (!(intdata | longdata)) { 44248995Ssheldonh chardata = 1; 44348995Ssheldonh break; 44448995Ssheldonh } 44555515Ssheldonh case 'h': case 'n': case 'p': case 'q': case 's': case 'L': 44648995Ssheldonh case '$': case '*': 44755515Ssheldonh goto fmt_broken; 44848995Ssheldonh case 'f': case 'e': case 'g': case 'E': case 'G': 44955515Ssheldonh if (!longdata) 45048995Ssheldonh break; 45148995Ssheldonh /* FALLTHROUGH */ 4521590Srgrimes default: 45355515Ssheldonhfmt_broken: 45448995Ssheldonh *++p = '\0'; 45548995Ssheldonh errx(1, "illegal or unsupported format '%s'", s); 45648995Ssheldonh /* NOTREACHED */ 4571590Srgrimes } 45848995Ssheldonh while (*++p) 45948995Ssheldonh if (*p == '%' && *(p+1) && *(p+1) != '%') 46048995Ssheldonh errx(1, "too many conversions"); 46148995Ssheldonh else if (*p == '%' && *(p+1) == '%') 46248995Ssheldonh p++; 46348995Ssheldonh else if (*p == '%' && !*(p+1)) { 46448995Ssheldonh strcat(format, "%"); 46548995Ssheldonh break; 46648995Ssheldonh } 4671590Srgrimes } 4681590Srgrimes} 469