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