(insert-directory): Insert free space only when listing a full directory.
[emacs.git] / lib-src / yow.c
blobc658b15e41f2a57c59e8be0cd3af17d079dcd877
1 /*
2 * yow.c
3 *
4 * Print a quotation from Zippy the Pinhead.
5 * Qux <Kaufman-David@Yale> March 6, 1986
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.
9 *
10 * With dynamic memory allocation.
13 #ifdef HAVE_CONFIG_H
14 #include <config.h>
15 #endif
17 #include <stdio.h>
18 #include <ctype.h>
19 #ifdef HAVE_STRING_H
20 #include <string.h>
21 #endif
22 #ifdef TIME_WITH_SYS_TIME
23 #include <sys/time.h>
24 #include <time.h>
25 #else
26 #ifdef HAVE_SYS_TIME_H
27 #include <sys/time.h>
28 #else
29 #include <time.h>
30 #endif
31 #endif
32 #ifdef HAVE_UNISTD_H
33 #include <unistd.h>
34 #endif
35 #include "epaths.h" /* For PATH_DATA. */
37 #define BUFSIZE 80
38 #define SEP '\0'
40 #ifndef YOW_FILE
41 #define YOW_FILE "yow.lines"
42 #endif
44 #ifdef MSDOS
45 #define rootrelativepath(rel) \
46 ({\
47 static char res[BUFSIZE], *p;\
48 strcpy (res, argv[0]);\
49 p = res + strlen (res);\
50 while (p != res && *p != '/' && *p != '\\' && *p != ':') p--;\
51 strcpy (p + 1, "../");\
52 strcpy (p + 4, rel);\
53 &res;})
54 #endif
56 #ifndef HAVE_STDLIB_H
57 char *malloc __P ((size_t size))), *realloc __P ((POINTER_TYPE *ptr, size_t size));
58 #endif
60 void yow();
61 void setup_yow();
63 int
64 main (argc, argv)
65 int argc;
66 char *argv[];
68 FILE *fp;
69 char file[BUFSIZ];
71 if (argc > 2 && !strcmp (argv[1], "-f"))
72 strcpy (file, argv[2]);
73 else
74 #ifdef vms
75 sprintf (file, "%s%s", PATH_DATA, YOW_FILE);
76 #else
77 sprintf (file, "%s/%s", PATH_DATA, YOW_FILE);
78 #endif
80 if ((fp = fopen(file, "r")) == NULL) {
81 fprintf(stderr, "yow: ");
82 perror(file);
83 exit(1);
86 /* initialize random seed */
87 srand((int) (getpid() + time((time_t *) 0)));
89 setup_yow(fp);
90 yow(fp);
91 fclose(fp);
92 return 0;
95 static long len = -1;
96 static long header_len;
98 #define AVG_LEN 40 /* average length of a quotation */
100 /* Sets len and header_len */
101 void
102 setup_yow(fp)
103 FILE *fp;
105 int c;
107 /* Get length of file */
108 /* Because the header (stuff before the first SEP) can be very long,
109 * thus biasing our search in favor of the first quotation in the file,
110 * we explicitly skip that. */
111 while ((c = getc(fp)) != SEP) {
112 if (c == EOF) {
113 fprintf(stderr, "yow: file contains no separators\n");
114 exit(2);
117 header_len = ftell(fp);
118 if (header_len > AVG_LEN)
119 header_len -= AVG_LEN; /* allow the first quotation to appear */
121 if (fseek(fp, 0L, 2) == -1) {
122 perror("yow");
123 exit(1);
125 len = ftell(fp) - header_len;
129 /* go to a random place in the file and print the quotation there */
130 void
131 yow (fp)
132 FILE *fp;
134 long offset;
135 int c, i = 0;
136 char *buf;
137 unsigned int bufsize;
139 offset = rand() % len + header_len;
140 if (fseek(fp, offset, 0) == -1) {
141 perror("yow");
142 exit(1);
145 /* Read until SEP, read next line, print it.
146 (Note that we will never print anything before the first separator.)
147 If we hit EOF looking for the first SEP, just recurse. */
148 while ((c = getc(fp)) != SEP)
149 if (c == EOF) {
150 yow(fp);
151 return;
154 /* Skip leading whitespace, then read in a quotation.
155 If we hit EOF before we find a non-whitespace char, recurse. */
156 while (isspace(c = getc(fp)))
158 if (c == EOF) {
159 yow(fp);
160 return;
163 bufsize = BUFSIZE;
164 buf = malloc(bufsize);
165 if (buf == (char *)0) {
166 fprintf(stderr, "yow: virtual memory exhausted\n");
167 exit (3);
170 buf[i++] = c;
171 while ((c = getc(fp)) != SEP && c != EOF) {
172 buf[i++] = c;
174 if (i == bufsize-1) {
175 /* Yow! Is this quotation too long yet? */
176 bufsize *= 2;
177 buf = realloc(buf, bufsize);
178 if (buf == (char *)0) {
179 fprintf(stderr, "yow: virtual memory exhausted\n");
180 exit (3);
184 buf[i++] = 0;
185 printf("%s\n", buf);