X-Git-Url: https://git.cameronkatri.com/bsdgames-darwin.git/blobdiff_plain/d087297b8c8efc2cbbbe4595863b6f22ae50a989..c8f75ed90de51b0cc71da2c6c9d5fc42192076f8:/primes/primes.c?ds=sidebyside diff --git a/primes/primes.c b/primes/primes.c index d9f27fe0..67fa6a4f 100644 --- a/primes/primes.c +++ b/primes/primes.c @@ -1,6 +1,8 @@ +/* $NetBSD: primes.c,v 1.9 1999/09/08 21:17:55 jsm Exp $ */ + /* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Landon Curt Noll. @@ -34,23 +36,26 @@ * SUCH DAMAGE. */ +#include #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ - All rights reserved.\n"; +__COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"); #endif /* not lint */ #ifndef lint -/*static char sccsid[] = "from: @(#)primes.c 5.4 (Berkeley) 6/1/90";*/ -static char rcsid[] = "$Id: primes.c,v 1.3 1994/03/01 01:07:48 cgd Exp $"; +#if 0 +static char sccsid[] = "@(#)primes.c 8.5 (Berkeley) 5/10/95"; +#else +__RCSID("$NetBSD: primes.c,v 1.9 1999/09/08 21:17:55 jsm Exp $"); +#endif #endif /* not lint */ /* * primes - generate a table of primes between two values * - * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo + * By: Landon Curt Noll chongo@toad.com, ...!{sun,tolsoft}!hoptoad!chongo * - * chongo /\oo/\ + * chongo /\oo/\ * * usage: * primes [start [stop]] @@ -59,16 +64,19 @@ static char rcsid[] = "$Id: primes.c,v 1.3 1994/03/01 01:07:48 cgd Exp $"; * the value 4294967295 (2^32-1) is assumed. If start is * omitted, start is read from standard input. * - * Prints "ouch" if start or stop is bogus. - * * validation check: there are 664579 primes between 0 and 10^7 */ -#include -#include -#include #include +#include +#include #include +#include +#include +#include +#include +#include + #include "primes.h" /* @@ -88,208 +96,124 @@ char table[TABSIZE]; /* Eratosthenes sieve of odd numbers */ * We are able to sieve 2^32-1 because this byte table yields all primes * up to 65537 and 65537^2 > 2^32-1. */ -extern ubig prime[]; -extern ubig *pr_limit; /* largest prime in the prime array */ +extern const ubig prime[]; +extern const ubig *pr_limit; /* largest prime in the prime array */ /* * To avoid excessive sieves for small factors, we use the table below to * setup our sieve blocks. Each element represents a odd number starting * with 1. All non-zero elements are factors of 3, 5, 7, 11 and 13. */ -extern char pattern[]; -extern int pattern_size; /* length of pattern array */ +extern const char pattern[]; +extern const int pattern_size; /* length of pattern array */ -#define MAX_LINE 255 /* max line allowed on stdin */ - -char *read_num_buf(); /* read a number buffer */ -void primes(); /* print the primes in range */ -char *program; /* our name */ +int main __P((int, char *[])); +void primes __P((ubig, ubig)); +ubig read_num_buf __P((void)); +void usage __P((void)) __attribute__((__noreturn__)); +int main(argc, argv) - int argc; /* arg count */ - char *argv[]; /* args */ + int argc; + char *argv[]; { - char buf[MAX_LINE+1]; /* input buffer */ - char *ret; /* return result */ - ubig start; /* where to start generating */ - ubig stop; /* don't generate at or above this value */ + ubig start; /* where to start generating */ + ubig stop; /* don't generate at or above this value */ + int ch; + char *p; + + while ((ch = getopt(argc, argv, "")) != -1) + switch (ch) { + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; - /* - * parse args - */ - program = argv[0]; start = 0; stop = BIG; - if (argc == 3) { - /* convert low and high args */ - if (read_num_buf(NULL, argv[1]) == NULL) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - if (read_num_buf(NULL, argv[2]) == NULL) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - if (sscanf(argv[1], "%lu", &start) != 1) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - if (sscanf(argv[2], "%lu", &stop) != 1) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - - } else if (argc == 2) { - /* convert low arg */ - if (read_num_buf(NULL, argv[1]) == NULL) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - if (sscanf(argv[1], "%lu", &start) != 1) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - - } else { - /* read input until we get a good line */ - if (read_num_buf(stdin, buf) != NULL) { - /* convert the buffer */ - if (sscanf(buf, "%lu", &start) != 1) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); - } - } else { - exit(0); - } - } - if (start > stop) { - fprintf(stderr, "%s: ouch\n", program); - exit(1); + /* + * Convert low and high args. Strtoul(3) sets errno to + * ERANGE if the number is too large, but, if there's + * a leading minus sign it returns the negation of the + * result of the conversion, which we'd rather disallow. + */ + switch (argc) { + case 2: + /* Start and stop supplied on the command line. */ + if (argv[0][0] == '-' || argv[1][0] == '-') + errx(1, "negative numbers aren't permitted."); + + errno = 0; + start = strtoul(argv[0], &p, 10); + if (errno) + err(1, "%s", argv[0]); + if (*p != '\0') + errx(1, "%s: illegal numeric format.", argv[0]); + + errno = 0; + stop = strtoul(argv[1], &p, 10); + if (errno) + err(1, "%s", argv[1]); + if (*p != '\0') + errx(1, "%s: illegal numeric format.", argv[1]); + break; + case 1: + /* Start on the command line. */ + if (argv[0][0] == '-') + errx(1, "negative numbers aren't permitted."); + + errno = 0; + start = strtoul(argv[0], &p, 10); + if (errno) + err(1, "%s", argv[0]); + if (*p != '\0') + errx(1, "%s: illegal numeric format.", argv[0]); + break; + case 0: + start = read_num_buf(); + break; + default: + usage(); } + + if (start > stop) + errx(1, "start value must be less than stop value."); primes(start, stop); exit(0); } /* - * read_num_buf - read a number buffer from a stream - * - * Read a number on a line of the form: - * - * ^[ \t]*\(+?[0-9][0-9]\)*.*$ - * - * where ? is a 1-or-0 operator and the number is within \( \). - * - * If does not match the above pattern, it is ignored and a new - * line is read. If the number is too large or small, we will - * print ouch and read a new line. - * - * We have to be very careful on how we check the magnitude of the - * input. We can not use numeric checks because of the need to - * check values against maximum numeric values. - * - * This routine will return a line containing a ascii number between - * 0 and BIG, or it will return NULL. - * - * If the stream is NULL then buf will be processed as if were - * a single line stream. - * - * returns: - * char * pointer to leading digit or + - * NULL EOF or error + * read_num_buf -- + * This routine returns a number n, where 0 <= n && n <= BIG. */ -char * -read_num_buf(input, buf) - FILE *input; /* input stream or NULL */ - char *buf; /* input buffer */ +ubig +read_num_buf() { - static char limit[MAX_LINE+1]; /* ascii value of BIG */ - static int limit_len; /* digit count of limit */ - int len; /* digits in input (excluding +/-) */ - char *s; /* line start marker */ - char *d; /* first digit, skip +/- */ - char *p; /* scan pointer */ - char *z; /* zero scan pointer */ - - /* form the ascii value of BIG if needed */ - if (!isascii(limit[0]) || !isdigit(limit[0])) { - sprintf(limit, "%lu", BIG); - limit_len = strlen(limit); - } - - /* - * the search for a good line - */ - if (input != NULL && fgets(buf, MAX_LINE, input) == NULL) { - /* error or EOF */ - return NULL; - } - do { - - /* ignore leading whitespace */ - for (s=buf; *s && s < buf+MAX_LINE; ++s) { - if (!isascii(*s) || !isspace(*s)) { - break; - } - } - - /* object if - */ - if (*s == '-') { - fprintf(stderr, "%s: ouch for minuses\n", program); - continue; - } - - /* skip over any leading + */ - if (*s == '+') { - d = s+1; - } else { - d = s; - } - - /* note leading zeros */ - for (z=d; *z && z < buf+MAX_LINE; ++z) { - if (*z != '0') { - break; - } - } - - /* scan for the first non-digit/non-plus/non-minus */ - for (p=d; *p && p < buf+MAX_LINE; ++p) { - if (!isascii(*p) || !isdigit(*p)) { - break; - } - } + ubig val; + char *p, buf[100]; /* > max number of digits. */ - /* ignore empty lines */ - if (p == d) { - continue; + for (;;) { + if (fgets(buf, sizeof(buf), stdin) == NULL) { + if (ferror(stdin)) + err(1, "stdin"); + exit(0); } - *p = '\0'; - - /* object if too many digits */ - len = strlen(z); - len = (len<=0) ? 1 : len; - /* accept if digit count is below limit */ - if (len < limit_len) { - /* we have good input */ - return s; - - /* reject very large numbers */ - } else if (len > limit_len) { - fprintf(stderr, "%s: %s too big\n", program, z); + for (p = buf; isblank(*p); ++p); + if (*p == '\n' || *p == '\0') continue; - - /* carefully check against near limit numbers */ - } else if (strcmp(z, limit) > 0) { - fprintf(stderr, "%s: %s a bit too big\n", program, z); - continue; - } - /* number is near limit, but is under it */ - return s; - } while (input != NULL && fgets(buf, MAX_LINE, input) != NULL); - - /* error or EOF */ - return NULL; + if (*p == '-') + errx(1, "negative numbers aren't permitted."); + errno = 0; + val = strtoul(buf, &p, 10); + if (errno) + err(1, "%s", buf); + if (*p != '\n') + errx(1, "%s: illegal numeric format.", buf); + return (val); + } } /* @@ -300,16 +224,16 @@ primes(start, stop) ubig start; /* where to start generating */ ubig stop; /* don't generate at or above this value */ { - register char *q; /* sieve spot */ - register ubig factor; /* index and factor */ - register char *tab_lim; /* the limit to sieve on the table */ - register ubig *p; /* prime table pointer */ - register ubig fact_lim; /* highest prime for current block */ + char *q; /* sieve spot */ + ubig factor; /* index and factor */ + char *tab_lim; /* the limit to sieve on the table */ + const ubig *p; /* prime table pointer */ + ubig fact_lim; /* highest prime for current block */ /* - * NetBSD has no problems with handling conversion - * between doubles and unsigned long, so we can go - * all the way to BIG. + * A number of systems can not convert double values into unsigned + * longs when the values are larger than the largest signed value. + * We don't have this problem, so we can go all the way to BIG. */ if (start < 3) { start = (ubig)2; @@ -337,10 +261,9 @@ primes(start, stop) if (start <= *pr_limit) { /* skip primes up to the start value */ for (p = &prime[0], factor = prime[0]; - factor < stop && p <= pr_limit; - factor = *(++p)) { + factor < stop && p <= pr_limit; factor = *(++p)) { if (factor >= start) { - printf("%u\n", factor); + printf("%lu\n", (unsigned long) factor); } } /* return early if we are done */ @@ -363,8 +286,7 @@ primes(start, stop) memcpy(table, &pattern[factor], pattern_size-factor); /* main block pattern copies */ for (fact_lim=pattern_size-factor; - fact_lim+pattern_size<=TABSIZE; - fact_lim+=pattern_size) { + fact_lim+pattern_size<=TABSIZE; fact_lim+=pattern_size) { memcpy(&table[fact_lim], pattern, pattern_size); } /* final block pattern copy */ @@ -388,10 +310,10 @@ primes(start, stop) do { /* determine the factor's initial sieve point */ q = (char *)(start%factor); /* temp storage for mod */ - if ((int)q & 0x1) { - q = &table[(factor-(int)q)/2]; + if ((long)q & 0x1) { + q = &table[(factor-(long)q)/2]; } else { - q = &table[q ? factor-((int)q/2) : 0]; + q = &table[q ? factor-((long)q/2) : 0]; } /* sive for our current factor */ for ( ; q < tab_lim; q += factor) { @@ -404,8 +326,15 @@ primes(start, stop) */ for (q = table; q < tab_lim; ++q, start+=2) { if (*q) { - printf("%u\n", start); + printf("%lu\n", (unsigned long) start); } } } } + +void +usage() +{ + (void)fprintf(stderr, "usage: primes [start [stop]]\n"); + exit(1); +}