Importing usr.bin/jot

No Minix-specific changes needed.

Change-Id: I0f45ea7f45d6a254de9383fc4f9ff5e35a013d6b
This commit is contained in:
Thomas Cort 2013-11-06 17:23:38 -05:00
parent d44a5ed1c1
commit 075dbe55f3
6 changed files with 616 additions and 1 deletions

View file

@ -363,6 +363,7 @@
./usr/bin/isoinfo minix-sys ./usr/bin/isoinfo minix-sys
./usr/bin/isoread minix-sys ./usr/bin/isoread minix-sys
./usr/bin/join minix-sys ./usr/bin/join minix-sys
./usr/bin/jot minix-sys
./usr/bin/kill minix-sys obsolete ./usr/bin/kill minix-sys obsolete
./usr/bin/kyua minix-sys kyua ./usr/bin/kyua minix-sys kyua
./usr/bin/lam minix-sys ./usr/bin/lam minix-sys
@ -1941,6 +1942,7 @@
./usr/man/man1/isoread.1 minix-sys ./usr/man/man1/isoread.1 minix-sys
./usr/man/man1/jobs.1 minix-sys ./usr/man/man1/jobs.1 minix-sys
./usr/man/man1/join.1 minix-sys ./usr/man/man1/join.1 minix-sys
./usr/man/man1/jot.1 minix-sys
./usr/man/man1/kill.1 minix-sys ./usr/man/man1/kill.1 minix-sys
./usr/man/man1/ksh.1 minix-sys ./usr/man/man1/ksh.1 minix-sys
./usr/man/man1/kyua.1 minix-sys kyua ./usr/man/man1/kyua.1 minix-sys kyua

View file

@ -176,6 +176,7 @@
2012/10/17 12:00:00,usr.bin/indent 2012/10/17 12:00:00,usr.bin/indent
2012/10/17 12:00:00,usr.bin/infocmp 2012/10/17 12:00:00,usr.bin/infocmp
2012/10/17 12:00:00,usr.bin/join 2012/10/17 12:00:00,usr.bin/join
2012/10/17 12:00:00,usr.bin/jot
2012/10/17 12:00:00,usr.bin/lam 2012/10/17 12:00:00,usr.bin/lam
2011/01/17 18:11:10,usr.bin/ldd 2011/01/17 18:11:10,usr.bin/ldd
2013/10/18 12:00:00,usr.bin/leave 2013/10/18 12:00:00,usr.bin/leave

View file

@ -12,7 +12,7 @@ SUBDIR= asa \
env expand \ env expand \
finger fold from \ finger fold from \
fsplit ftp genassym getopt \ fsplit ftp genassym getopt \
head hexdump indent infocmp join \ head hexdump indent infocmp join jot \
lam ldd leave \ lam ldd leave \
lock login logname lorder m4 \ lock login logname lorder m4 \
machine make man menuc mesg \ machine make man menuc mesg \

10
usr.bin/jot/Makefile Normal file
View file

@ -0,0 +1,10 @@
# $NetBSD: Makefile,v 1.6 2011/08/16 10:37:21 christos Exp $
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= jot
DPADD= ${LIBMATH}
LDADD= -lm
COPTS.jot.c += -Wno-format-nonliteral
.include <bsd.prog.mk>

203
usr.bin/jot/jot.1 Normal file
View file

@ -0,0 +1,203 @@
.\" $NetBSD: jot.1,v 1.12 2012/04/08 22:00:39 wiz Exp $
.\"
.\" Copyright (c) 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)jot.1 8.1 (Berkeley) 6/6/93
.\"
.Dd January 5, 2010
.Dt JOT 1
.Os
.Sh NAME
.Nm jot
.Nd print sequential or random data
.Sh SYNOPSIS
.Nm
.Op Fl cnr
.Op Fl b Ar word
.Op Fl p Ar precision
.Op Fl s Ar string
.Op Fl w Ar word
.Oo Ar reps
.Oo Ar begin
.Oo Ar end
.Op Ar s
.Oc
.Oc
.Oc
.Sh DESCRIPTION
The
.Nm jot
utility is used to print out increasing, decreasing, random,
or redundant data (usually numbers) one per line.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl b Ar word
Just print
.Ar word
repetitively.
.It Fl c
This is an abbreviation for
.Fl w Ar %c .
.It Fl n
Do not print the final newline normally appended to the output.
.It Fl p Ar precision
Print only as many digits or characters of the data
as indicated by the integer
.Ar precision .
In the absence of
.Fl p ,
the precision is the greater of the precisions of
.Ar begin
and
.Ar end .
The
.Fl p
option is overridden by whatever appears in a
.Xr printf 3
conversion following
.Fl w .
.It Fl r
Generate random data instead of sequential data, the default.
.It Fl s Ar string
Print data separated by
.Ar string .
Normally, newlines separate data.
.It Fl w Ar word
Print
.Ar word
with the generated data appended to it.
Octal, hexadecimal, exponential, ASCII, zero padded,
and right-adjusted representations
are possible by using the appropriate
.Xr printf 3
conversion specification inside
.Ar word ,
in which case the data are inserted rather than appended.
.El
.Pp
The last four arguments indicate, respectively,
the number of data, the lower bound, the upper bound,
and the step size or, for random data, the seed.
While at least one of them must appear,
any of the other three may be omitted, and
will be considered as such if given as
.Dq - .
Any three of these arguments determines the fourth.
If four are specified and the given and computed values of
.Ar reps
conflict, the lower value is used.
If fewer than three are specified, defaults are assigned
left to right, except for
.Ar s ,
which assumes its default unless both
.Ar begin
and
.Ar end
are given.
.Pp
Defaults for the four arguments are, respectively,
100, 1, 100, and 1, except that when random data are requested,
.Ar s
defaults to a seed depending upon the time of day.
.Ar reps
is expected to be an unsigned integer,
and if given as zero is taken to be infinite.
.Ar begin
and
.Ar end
may be given as real numbers or as characters
representing the corresponding value in ASCII.
The last argument must be a real number.
.Pp
Random numbers are obtained through
.Xr random 3 .
The name
.Nm jot
derives in part from
.Nm iota ,
a function in APL.
.Sh EXAMPLES
The command:
.Dl "jot - 42 87 1"
prints the integers from 42 to 87, inclusive.
.Pp
The command:
.Dl "jot 21 \-1 1.00"
prints 21 evenly spaced numbers increasing from \-1 to 1.
.Pp
The command:
.Dl "jot \-c 128 0"
prints the ASCII character set.
.Pp
The command:
.Dl "jot \-w xa%c 26 a"
prints the strings
.Dq xaa
through
.Dq xaz .
.Pp
The command:
.Dl "jot \-r \-c 160 a z | rs \-g 0 8"
prints 20 random 8-letter strings.
.Pp
The command:
.Dl "jot \-b y 0"
is equivalent to
.Xr yes 1 .
.Pp
The command:
.Dl "jot \-w %ds/old/new/ 30 2 \- 5"
prints thirty
.Xr ed 1
substitution commands applying to lines 2, 7, 12, etc.
.Pp
The command:
.Dl "jot 0 9 \- \-.5"
prints the stuttering sequence 9, 8, 8, 7, etc.
.Pp
The command:
.Dl "jot \-b x 512 \*[Gt] block"
creates a file containing exactly 1024 bytes.
.Pp
The command:
.Dl "expand \-\`jot \-s, \- 10 132 4\`"
sets tabs four spaces apart starting
from column 10 and ending in column 132.
.Pp
The command:
.Dl "grep \`jot \-s """" \-b . 80\`"
prints all lines 80 characters or longer.
.Sh SEE ALSO
.Xr ed 1 ,
.Xr expand 1 ,
.Xr rs 1 ,
.Xr seq 1 ,
.Xr yes 1 ,
.Xr printf 3 ,
.Xr random 3

399
usr.bin/jot/jot.c Normal file
View file

@ -0,0 +1,399 @@
/* $NetBSD: jot.c,v 1.25 2009/04/12 11:19:18 lukem Exp $ */
/*-
* Copyright (c) 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT("@(#) Copyright (c) 1993\
The Regents of the University of California. All rights reserved.");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)jot.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: jot.c,v 1.25 2009/04/12 11:19:18 lukem Exp $");
#endif /* not lint */
/*
* jot - print sequential or random data
*
* Author: John Kunze, Office of Comp. Affairs, UCB
*/
#include <ctype.h>
#include <err.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#define REPS_DEF 100
#define BEGIN_DEF 1
#define ENDER_DEF 100
#define STEP_DEF 1
#define is_default(s) (strcmp((s), "-") == 0)
static double begin = BEGIN_DEF;
static double ender = ENDER_DEF;
static double step = STEP_DEF;
static long reps = REPS_DEF;
static int randomize;
static int boring;
static int prec = -1;
static int dox;
static int chardata;
static int nofinalnl;
static const char *sepstring = "\n";
static char format[BUFSIZ];
static void getargs(int, char *[]);
static void getformat(void);
static int getprec(char *);
static void putdata(double, long);
static void usage(void) __dead;
int
main(int argc, char *argv[])
{
double x;
long i;
getargs(argc, argv);
if (randomize) {
x = ender - begin;
if (x < 0) {
x = -x;
begin = ender;
}
if (dox == 0)
/*
* We are printing floating point, generate random
* number that include both supplied limits.
* Due to FP routing for display the low and high
* values are likely to occur half as often as all
* the others.
*/
x /= (1u << 31) - 1.0;
else {
/*
* We are printing integers increase the range by
* one but ensure we never generate it.
* This makes all the integer values equally likely.
*/
x += 1.0;
x /= (1u << 31);
}
srandom((unsigned long) step);
for (i = 1; i <= reps || reps == 0; i++)
putdata(random() * x + begin, reps - i);
} else {
/*
* If we are going to display as integer, add 0.5 here
* and use floor(x) later to get sane rounding.
*/
x = begin;
if (dox)
x += 0.5;
for (i = 1; i <= reps || reps == 0; i++, x += step)
putdata(x, reps - i);
}
if (!nofinalnl)
putchar('\n');
exit(0);
}
static void
getargs(int argc, char *argv[])
{
unsigned int have = 0;
#define BEGIN 1
#define STEP 2 /* seed if -r */
#define REPS 4
#define ENDER 8
int n = 0;
long t;
char *ep;
for (;;) {
switch (getopt(argc, argv, "b:cnp:rs:w:")) {
default:
usage();
case -1:
break;
case 'c':
chardata = 1;
continue;
case 'n':
nofinalnl = 1;
continue;
case 'p':
prec = strtol(optarg, &ep, 0);
if (*ep != 0 || prec < 0)
errx(EXIT_FAILURE, "Bad precision value");
continue;
case 'r':
randomize = 1;
continue;
case 's':
sepstring = optarg;
continue;
case 'b':
boring = 1;
/* FALLTHROUGH */
case 'w':
strlcpy(format, optarg, sizeof(format));
continue;
}
break;
}
argc -= optind;
argv += optind;
switch (argc) { /* examine args right to left, falling thru cases */
case 4:
if (!is_default(argv[3])) {
step = strtod(argv[3], &ep);
if (*ep != 0)
errx(EXIT_FAILURE, "Bad step value: %s",
argv[3]);
have |= STEP;
}
case 3:
if (!is_default(argv[2])) {
if (!sscanf(argv[2], "%lf", &ender))
ender = argv[2][strlen(argv[2])-1];
have |= ENDER;
if (prec < 0)
n = getprec(argv[2]);
}
case 2:
if (!is_default(argv[1])) {
if (!sscanf(argv[1], "%lf", &begin))
begin = argv[1][strlen(argv[1])-1];
have |= BEGIN;
if (prec < 0)
prec = getprec(argv[1]);
if (n > prec) /* maximum precision */
prec = n;
}
case 1:
if (!is_default(argv[0])) {
reps = strtoul(argv[0], &ep, 0);
if (*ep != 0 || reps < 0)
errx(EXIT_FAILURE, "Bad reps value: %s",
argv[0]);
have |= REPS;
}
break;
case 0:
usage();
break;
default:
errx(EXIT_FAILURE,
"Too many arguments. What do you mean by %s?", argv[4]);
}
getformat();
if (prec == -1)
prec = 0;
if (randomize) {
/* 'step' is the seed here, use pseudo-random default */
if (!(have & STEP))
step = time(NULL) * getpid();
/* Take the default values for everything else */
return;
}
/*
* The loop we run uses begin/step/reps, so if we have been
* given an end value (ender) we must use it to replace the
* default values of the others.
* We will assume a begin of 0 and step of 1 if necessary.
*/
switch (have) {
case ENDER | STEP:
case ENDER | STEP | BEGIN:
/* Calculate reps */
if (step == 0.0)
reps = 0; /* ie infinite */
else {
reps = (ender - begin + step) / step;
if (reps <= 0)
errx(EXIT_FAILURE, "Impossible stepsize");
}
break;
case REPS | ENDER:
case REPS | ENDER | STEP:
/* Calculate begin */
if (reps == 0)
errx(EXIT_FAILURE,
"Must specify begin if reps == 0");
begin = ender - reps * step + step;
break;
case REPS | BEGIN | ENDER:
/* Calculate step */
if (reps == 0)
errx(EXIT_FAILURE,
"Infinite sequences cannot be bounded");
if (reps == 1)
step = 0.0;
else
step = (ender - begin) / (reps - 1);
break;
case REPS | BEGIN | ENDER | STEP:
/* reps given and implied - take smaller */
if (step == 0.0)
break;
t = (ender - begin + step) / step;
if (t <= 0)
errx(EXIT_FAILURE,
"Impossible stepsize");
if (t < reps)
reps = t;
break;
default:
/* No values can be calculated, use defaults */
break;
}
}
static void
putdata(double x, long notlast)
{
if (boring) /* repeated word */
printf("%s", format);
else if (dox) /* scalar */
printf(format, (long)floor(x));
else /* real */
printf(format, x);
if (notlast != 0)
fputs(sepstring, stdout);
}
__dead static void
usage(void)
{
(void)fprintf(stderr, "usage: %s [-cnr] [-b word] [-p precision] "
"[-s string] [-w word] [reps [begin [end [step | seed]]]]\n",
getprogname());
exit(1);
}
static int
getprec(char *num_str)
{
num_str = strchr(num_str, '.');
if (num_str == NULL)
return 0;
return strspn(num_str + 1, "0123456789");
}
static void
getformat(void)
{
char *p;
size_t sz;
if (boring) /* no need to bother */
return;
for (p = format; *p; p++) { /* look for '%' */
if (*p == '%') {
if (*(p+1) != '%')
break;
p++; /* leave %% alone */
}
}
sz = sizeof(format) - strlen(format) - 1;
if (!*p) {
if (chardata || prec == 0) {
if ((size_t)snprintf(p, sz, "%%%s", chardata ? "c" : "ld") >= sz)
errx(EXIT_FAILURE, "-w word too long");
dox = 1;
} else {
if (snprintf(p, sz, "%%.%df", prec) >= (int)sz)
errx(EXIT_FAILURE, "-w word too long");
}
} else if (!*(p+1)) {
if (sz <= 0)
errx(EXIT_FAILURE, "-w word too long");
strcat(format, "%"); /* cannot end in single '%' */
} else {
p++; /* skip leading % */
for(; *p && !isalpha((unsigned char)*p); p++) {
/* allow all valid printf(3) flags, but deny '*' */
if (!strchr("0123456789#-+. ", *p))
break;
}
/* Allow 'l' prefix, but no other. */
if (*p == 'l')
p++;
switch (*p) {
case 'f': case 'e': case 'g': case '%':
case 'E': case 'G':
break;
case 's':
errx(EXIT_FAILURE,
"cannot convert numeric data to strings");
break;
case 'd': case 'o': case 'x': case 'u':
case 'D': case 'O': case 'X': case 'U':
case 'c': case 'i':
dox = 1;
break;
default:
errx(EXIT_FAILURE, "unknown or invalid format `%s'",
format);
}
/* Need to check for trailing stuff to print */
for (; *p; p++) /* look for '%' */
if (*p == '%') {
if (*(p+1) != '%')
break;
p++; /* leave %% alone */
}
if (*p)
errx(EXIT_FAILURE, "unknown or invalid format `%s'",
format);
}
}