From 94b5353c71e7246077d468afe68d51ce85fc213d Mon Sep 17 00:00:00 2001 From: cgd Date: Thu, 23 Mar 1995 08:28:00 +0000 Subject: merge with Lite, new RCS id conventions, etc. --- primes/primes.c | 315 ++++++++++++++++++++++---------------------------------- 1 file changed, 121 insertions(+), 194 deletions(-) (limited to 'primes/primes.c') diff --git a/primes/primes.c b/primes/primes.c index d9f27fe0..57e00731 100644 --- a/primes/primes.c +++ b/primes/primes.c @@ -1,6 +1,8 @@ +/* $NetBSD: primes.c,v 1.4 1995/03/23 08:35:55 cgd 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. @@ -35,22 +37,25 @@ */ #ifndef lint -char copyright[] = -"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ - All rights reserved.\n"; +static char 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.4 (Berkeley) 3/21/94"; +#else +static char rcsid[] = "$NetBSD: primes.c,v 1.4 1995/03/23 08:35:55 cgd 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,18 @@ 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 "primes.h" /* @@ -99,197 +106,112 @@ extern ubig *pr_limit; /* largest prime in the prime array */ extern char pattern[]; extern 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 */ +void primes __P((ubig, ubig)); +ubig read_num_buf __P((void)); +void usage __P((void)); +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, "")) != EOF) + 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); + } } /* @@ -307,9 +229,9 @@ primes(start, stop) register 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,8 +259,7 @@ 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); } @@ -363,8 +284,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 */ @@ -409,3 +329,10 @@ primes(start, stop) } } } + +void +usage() +{ + (void)fprintf(stderr, "usage: primes [start [stop]]\n"); + exit(1); +} -- cgit v1.2.3-56-ge451