[net.sources] range -- generate loop values for the Shell

bin@minster.UUCP (bin) (11/21/85)

# To unbundle, sh this file
echo README >&2
cat >README << 'End of README'
Here is the command we use to
generate values for Shell loops.  The syntax was intended to
match that of the Shell.  Originally, it was called `from',
which might be a better name, but it later clashed with another command.
It isn't spectacular, but I thought it would be nice to see some
source in this news group for a change (hint), however short.

Exercise: extend it to allow looping through string values
End of README
echo range.1 >&2
cat >range.1 << 'End of range.1'
.TH RANGE 1 local
.SH NAME
range \- generate loop values
.SH SYNOPSIS
.BI range " n1" " to" " n2"
[
.BI by " n3"
]
.SH DESCRIPTION
.I Range
writes the numbers from
.I n1
to
.I n2
one to a line on the standard output.
The increment
.I n3
defaults to
1
.RI ( n1 \(<= n2 )
or
\-1
.RI ( n2 < n1 ).
The command is often used with the Shell
.B for
statement.
.SH EXAMPLE
Set the Shell variable
.I a
to
the strings
.I 1
to
.I 10,
with the value increasing after each
execution of the loop.
.PP
.RS
.nf
for a in \`range 1 to 10\`
do
	echo $a
done
.fi
.RE
.SH SEE ALSO
apply(1), bc(1), sh(1)
.SH BUGS
There is no check for arithmetic overflow.
End of range.1
echo range.c >&2
cat >range.c << 'End of range.c'
/*
 * range a to b [by c]
 *	generate for-loop values for Shell
 */

#include <stdio.h>
#include <ctype.h>

long	atol();
void	usage();
long	number();
int	isnumeric();

int
main(argc, argv)
char **argv;
{
	register long a, b, c;

	if (argc < 4 || strcmp(argv[2], "to"))
		usage();
	a = number(argv[1]);
	b = number(argv[3]);
	c = a <= b? 1: -1;
	if (argc > 5) {
		if (strcmp(argv[4], "by"))
			usage();
		c = number(argv[5]);
	}
	if (c < 0)
		for (; a >= b; a += c)
			printf("%ld\n", a);
	else if (c == 0)
		printf("%ld\n", a);
	else
		for (; a <= b; a += c)
			printf("%ld\n", a);
	exit(0);
}

void
usage()
{
	fprintf(stderr, "Usage: range n1 to n2 [by n3]\n");
	exit(1);
}

long
number(s)
char *s;
{
	if (!isnumeric(s)) {
		fprintf(stderr, "range: ill-formed number `%s'\n", s);
		exit(1);
	}
	return(atol(s));
}

int
isnumeric(s)
register char *s;
{
	while (*s == ' ' || *s == '\t')
		s++;
	if (*s == '+' || *s == '-')
		s++;
	do {
		if (!isascii(*s) || !isdigit(*s))
			return(0);
	} while (*++s);
	return(1);
}
End of range.c