Mercurial > hg > xemacs-beta
diff lib-src/yow.c @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | 15872534500d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib-src/yow.c Mon Aug 13 08:45:50 2007 +0200 @@ -0,0 +1,180 @@ +/* + * yow.c + * + * Print a quotation from Zippy the Pinhead. + * Qux <Kaufman-David@Yale> March 6, 1986 + * + * With dynamic memory allocation. + */ + +/* Synched up with: FSF 19.28. */ + +#include <config.h> + +#include <stdio.h> +#include <ctype.h> +#include <../src/paths.h> /* For PATH_DATA. */ + +#if __STDC__ || defined(STDC_HEADERS) +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <time.h> /* for time() */ +#endif + +#define BUFSIZE 80 +#define SEP '\0' + +#ifndef YOW_FILE +#define YOW_FILE "yow.lines" +#endif + +void yow (FILE *fp); +void setup_yow (FILE *fp); + +#ifdef MSDOS +#define rootrelativepath(rel) \ +({\ + static char res[BUFSIZE], *p;\ + strcpy (res, argv[0]);\ + p = res + strlen (res);\ + while (p != res && *p != '/' && *p != '\\' && *p != ':') p--;\ + strcpy (p + 1, "../");\ + strcpy (p + 4, rel);\ + &res;}) +#endif + +void +main (argc, argv) + int argc; + char *argv[]; +{ + FILE *fp; + char file[BUFSIZ]; + + if (argc > 2 && !strcmp (argv[1], "-f")) + strcpy (file, argv[2]); + else +#ifdef PATH_DATA +#ifdef vms + sprintf (file, "%s%s", PATH_DATA, YOW_FILE); +#else + sprintf (file, "%s/%s", PATH_DATA, YOW_FILE); +#endif +#else /* !PATH_DATA */ + { + fprintf (stderr, + "%s: the location of the \"%s\" file was not supplied at compile-time.\n\ + You must supply it with the -f command-line option.\n", + argv[0], YOW_FILE); + exit (1); + } +#endif + + if ((fp = fopen(file, "r")) == NULL) { + perror(file); + exit(1); + } + + /* initialize random seed */ + srand((int) (getpid() + time((time_t *) 0))); + + setup_yow(fp); + yow(fp); + fclose(fp); + exit(0); +} + +static long len = -1; +static long header_len; + +#define AVG_LEN 40 /* average length of a quotation */ + +/* Sets len and header_len */ +void +setup_yow(fp) + FILE *fp; +{ + int c; + + /* Get length of file */ + /* Because the header (stuff before the first SEP) can be very long, + * thus biasing our search in favor of the first quotation in the file, + * we explicitly skip that. */ + while ((c = getc(fp)) != SEP) { + if (c == EOF) { + fprintf(stderr, "File contains no separators.\n"); + exit(2); + } + } + header_len = ftell(fp); + if (header_len > AVG_LEN) + header_len -= AVG_LEN; /* allow the first quotation to appear */ + + if (fseek(fp, 0L, 2) == -1) { + perror("fseek 1"); + exit(1); + } + len = ftell(fp) - header_len; +} + + +/* go to a random place in the file and print the quotation there */ +void +yow (fp) + FILE *fp; +{ + long offset; + int c, i = 0; + char *buf; + unsigned int bufsize; + + offset = rand() % len + header_len; + if (fseek(fp, offset, 0) == -1) { + perror("fseek 2"); + exit(1); + } + + /* Read until SEP, read next line, print it. + (Note that we will never print anything before the first separator.) + If we hit EOF looking for the first SEP, just recurse. */ + while ((c = getc(fp)) != SEP) + if (c == EOF) { + yow(fp); + return; + } + + /* Skip leading whitespace, then read in a quotation. + If we hit EOF before we find a non-whitespace char, recurse. */ + while (isspace(c = getc(fp))) + ; + if (c == EOF) { + yow(fp); + return; + } + + bufsize = BUFSIZE; + buf = (char *) malloc(bufsize); + if (buf == (char *)0) { + fprintf(stderr, "can't allocate any memory\n"); + exit (3); + } + + buf[i++] = c; + while ((c = getc(fp)) != SEP && c != EOF) { + buf[i++] = c; + + if (i == bufsize-1) { + /* Yow! Is this quotation too long yet? */ + bufsize *= 2; + buf = (char *)realloc(buf, bufsize); + if (buf == (char *)0) { + fprintf(stderr, "can't allocate more memory\n"); + exit (3); + } + } + } + buf[i++] = 0; + printf("%s\n", buf); +} +