comparison lib-src/yow.c @ 428:3ecd8885ac67 r21-2-22

Import from CVS: tag r21-2-22
author cvs
date Mon, 13 Aug 2007 11:28:15 +0200
parents
children 84b14dcb0985
comparison
equal deleted inserted replaced
427:0a0253eac470 428:3ecd8885ac67
1 /*
2 * yow.c
3 *
4 * Print a quotation from Zippy the Pinhead.
5 * Qux <Kaufman-David@Yale> March 6, 1986
6 *
7 * With dynamic memory allocation.
8 */
9
10 /* Synched up with: FSF 19.28. */
11
12 #define DONT_ENCAPSULATE
13 #include <../src/config.h>
14
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <../src/paths.h> /* For PATH_DATA. */
18
19 #if __STDC__ || defined(STDC_HEADERS)
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <time.h> /* for time() */
24 #endif
25
26 #define BUFSIZE 80
27 #define SEP '\0'
28
29 #ifndef YOW_FILE
30 #define YOW_FILE "yow.lines"
31 #endif
32
33 void yow (FILE *fp);
34 void setup_yow (FILE *fp);
35
36 #ifdef MSDOS
37 #define rootrelativepath(rel) \
38 ({\
39 static char res[BUFSIZE], *p;\
40 strcpy (res, argv[0]);\
41 p = res + strlen (res);\
42 while (p != res && *p != '/' && *p != '\\' && *p != ':') p--;\
43 strcpy (p + 1, "../");\
44 strcpy (p + 4, rel);\
45 &res;})
46 #endif
47
48 int
49 main (int argc, char *argv[])
50 {
51 FILE *fp;
52 char file[BUFSIZ];
53
54 if (argc > 2 && !strcmp (argv[1], "-f"))
55 strcpy (file, argv[2]);
56 else
57 #ifdef PATH_DATA
58 #ifdef vms
59 sprintf (file, "%s%s", PATH_DATA, YOW_FILE);
60 #else
61 sprintf (file, "%s/%s", PATH_DATA, YOW_FILE);
62 #endif
63 #else /* !PATH_DATA */
64 {
65 fprintf (stderr,
66 "%s: the location of the \"%s\" file was not supplied at compile-time.\n\
67 You must supply it with the -f command-line option.\n",
68 argv[0], YOW_FILE);
69 exit (1);
70 }
71 #endif
72
73 if ((fp = fopen(file, "r")) == NULL) {
74 perror(file);
75 exit(1);
76 }
77
78 /* initialize random seed */
79 srand((int) (getpid() + time((time_t *) 0)));
80
81 setup_yow(fp);
82 yow(fp);
83 fclose(fp);
84 return 0;
85 }
86
87 static long len = -1;
88 static long header_len;
89
90 #define AVG_LEN 40 /* average length of a quotation */
91
92 /* Sets len and header_len */
93 void
94 setup_yow(fp)
95 FILE *fp;
96 {
97 int c;
98
99 /* Get length of file */
100 /* Because the header (stuff before the first SEP) can be very long,
101 * thus biasing our search in favor of the first quotation in the file,
102 * we explicitly skip that. */
103 while ((c = getc(fp)) != SEP) {
104 if (c == EOF) {
105 fprintf(stderr, "File contains no separators.\n");
106 exit(2);
107 }
108 }
109 header_len = ftell(fp);
110 if (header_len > AVG_LEN)
111 header_len -= AVG_LEN; /* allow the first quotation to appear */
112
113 if (fseek(fp, 0L, 2) == -1) {
114 perror("fseek 1");
115 exit(1);
116 }
117 len = ftell(fp) - header_len;
118 }
119
120
121 /* go to a random place in the file and print the quotation there */
122 void
123 yow (fp)
124 FILE *fp;
125 {
126 long offset;
127 int c, i = 0;
128 char *buf;
129 unsigned int bufsize;
130
131 offset = rand() % len + header_len;
132 if (fseek(fp, offset, 0) == -1) {
133 perror("fseek 2");
134 exit(1);
135 }
136
137 /* Read until SEP, read next line, print it.
138 (Note that we will never print anything before the first separator.)
139 If we hit EOF looking for the first SEP, just recurse. */
140 while ((c = getc(fp)) != SEP)
141 if (c == EOF) {
142 yow(fp);
143 return;
144 }
145
146 /* Skip leading whitespace, then read in a quotation.
147 If we hit EOF before we find a non-whitespace char, recurse. */
148 while (isspace(c = getc(fp)))
149 ;
150 if (c == EOF) {
151 yow(fp);
152 return;
153 }
154
155 bufsize = BUFSIZE;
156 buf = (char *) malloc(bufsize);
157 if (buf == (char *)0) {
158 fprintf(stderr, "can't allocate any memory\n");
159 exit (3);
160 }
161
162 buf[i++] = c;
163 while ((c = getc(fp)) != SEP && c != EOF) {
164 buf[i++] = c;
165
166 if (i == bufsize-1) {
167 /* Yow! Is this quotation too long yet? */
168 bufsize *= 2;
169 buf = (char *)realloc(buf, bufsize);
170 if (buf == (char *)0) {
171 fprintf(stderr, "can't allocate more memory\n");
172 exit (3);
173 }
174 }
175 }
176 buf[i++] = 0;
177 printf("%s\n", buf);
178 }
179