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