If no sys/param.h, default to 8k.
[bpt/emacs.git] / lib-src / yow.c
CommitLineData
701570d7
RS
1/*
2 * yow.c
bc851190
RS
3 *
4 * Print a quotation from Zippy the Pinhead.
5 * Qux <Kaufman-David@Yale> March 6, 1986
c76d4b42
RS
6 *
7 * This file is in the public domain because the author published it
8 * with no copyright notice before the US signed the Bern Convention.
bc851190 9 *
701570d7 10 * With dynamic memory allocation.
bc851190
RS
11 */
12
701570d7
RS
13#include <stdio.h>
14#include <ctype.h>
21af68b6 15#include <../src/paths.h> /* For PATH_DATA. */
701570d7
RS
16
17#define BUFSIZE 80
bc851190 18#define SEP '\0'
701570d7
RS
19
20#ifndef YOW_FILE
bc851190 21#define YOW_FILE "yow.lines"
701570d7 22#endif
bc851190 23
35ebc5cf
RS
24#ifdef MSDOS
25#define rootrelativepath(rel) \
26({\
27 static char res[BUFSIZE], *p;\
28 strcpy (res, argv[0]);\
29 p = res + strlen (res);\
30 while (p != res && *p != '/' && *p != '\\' && *p != ':') p--;\
31 strcpy (p + 1, "../");\
32 strcpy (p + 4, rel);\
33 &res;})
34#endif
35
b3dcbddb
DM
36char *malloc(), *realloc();
37
38void yow();
39void setup_yow();
40
340ff9de 41int
bc851190
RS
42main (argc, argv)
43 int argc;
44 char *argv[];
45{
46 FILE *fp;
47 char file[BUFSIZ];
bc851190
RS
48
49 if (argc > 2 && !strcmp (argv[1], "-f"))
50 strcpy (file, argv[2]);
51 else
52#ifdef vms
4bcffd8e 53 sprintf (file, "%s%s", PATH_DATA, YOW_FILE);
bc851190 54#else
4bcffd8e 55 sprintf (file, "%s/%s", PATH_DATA, YOW_FILE);
bc851190
RS
56#endif
57
58 if ((fp = fopen(file, "r")) == NULL) {
b3dcbddb 59 fprintf(stderr, "yow: ");
bc851190
RS
60 perror(file);
61 exit(1);
62 }
63
64 /* initialize random seed */
65 srand((int) (getpid() + time((long *) 0)));
66
701570d7 67 setup_yow(fp);
bc851190
RS
68 yow(fp);
69 fclose(fp);
340ff9de 70 return 0;
bc851190
RS
71}
72
701570d7
RS
73static long len = -1;
74static long header_len;
75
76#define AVG_LEN 40 /* average length of a quotation */
77
78/* Sets len and header_len */
79void
80setup_yow(fp)
81 FILE *fp;
82{
83 int c;
84
85 /* Get length of file */
86 /* Because the header (stuff before the first SEP) can be very long,
87 * thus biasing our search in favor of the first quotation in the file,
88 * we explicitly skip that. */
89 while ((c = getc(fp)) != SEP) {
90 if (c == EOF) {
b3dcbddb 91 fprintf(stderr, "yow: file contains no separators\n");
701570d7
RS
92 exit(2);
93 }
94 }
95 header_len = ftell(fp);
96 if (header_len > AVG_LEN)
97 header_len -= AVG_LEN; /* allow the first quotation to appear */
98
99 if (fseek(fp, 0L, 2) == -1) {
b3dcbddb 100 perror("yow");
701570d7
RS
101 exit(1);
102 }
103 len = ftell(fp) - header_len;
104}
105
106
107/* go to a random place in the file and print the quotation there */
bc851190
RS
108void
109yow (fp)
110 FILE *fp;
111{
bc851190
RS
112 long offset;
113 int c, i = 0;
701570d7
RS
114 char *buf;
115 unsigned int bufsize;
bc851190 116
701570d7 117 offset = rand() % len + header_len;
bc851190 118 if (fseek(fp, offset, 0) == -1) {
b3dcbddb 119 perror("yow");
bc851190
RS
120 exit(1);
121 }
122
123 /* Read until SEP, read next line, print it.
eb8c3be9 124 (Note that we will never print anything before the first separator.)
bc851190
RS
125 If we hit EOF looking for the first SEP, just recurse. */
126 while ((c = getc(fp)) != SEP)
127 if (c == EOF) {
128 yow(fp);
129 return;
130 }
131
132 /* Skip leading whitespace, then read in a quotation.
133 If we hit EOF before we find a non-whitespace char, recurse. */
134 while (isspace(c = getc(fp)))
135 ;
136 if (c == EOF) {
137 yow(fp);
138 return;
139 }
701570d7
RS
140
141 bufsize = BUFSIZE;
142 buf = malloc(bufsize);
143 if (buf == (char *)0) {
b3dcbddb 144 fprintf(stderr, "yow: virtual memory exhausted\n");
701570d7
RS
145 exit (3);
146 }
147
bc851190
RS
148 buf[i++] = c;
149 while ((c = getc(fp)) != SEP && c != EOF) {
150 buf[i++] = c;
701570d7
RS
151
152 if (i == bufsize-1) {
bc851190 153 /* Yow! Is this quotation too long yet? */
701570d7
RS
154 bufsize *= 2;
155 buf = realloc(buf, bufsize);
156 if (buf == (char *)0) {
b3dcbddb 157 fprintf(stderr, "yow: virtual memory exhausted\n");
701570d7
RS
158 exit (3);
159 }
160 }
bc851190
RS
161 }
162 buf[i++] = 0;
163 printf("%s\n", buf);
164}
165