xref: /original-bsd/games/boggle/boggle/word.c (revision 3705696b)
1 /*-
2  * Copyright (c) 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Barry Brachman.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)word.c	8.1 (Berkeley) 06/11/93";
13 #endif /* not lint */
14 
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 
22 #include "bog.h"
23 #include "extern.h"
24 
25 static char *dictspace, *dictend;
26 static char *sp;
27 
28 static int first = 1, lastch = 0;
29 
30 /*
31  * Return the next word in the compressed dictionary in 'buffer' or
32  * NULL on end-of-file
33  */
34 char *
35 nextword(fp)
36 	FILE *fp;
37 {
38 	extern int wordlen;
39 	register int ch, pcount;
40 	register char *p;
41 	static char buf[MAXWORDLEN + 1];
42 
43 	if (fp == NULL) {
44 		if (sp == dictend)
45 			return (NULL);
46 
47 		p = buf + (int) *sp++;
48 
49 		/*
50 		 * The dictionary ends with a null byte
51 		 */
52 		while (*sp >= 'a')
53 			if ((*p++ = *sp++) == 'q')
54 				*p++ = 'u';
55 	} else {
56 		if (first) {
57 			if ((pcount = getc(fp)) == EOF)
58 				return (NULL);
59 			first = 0;
60 		} else if ((pcount = lastch) == EOF)
61 			return (NULL);
62 
63 		p = buf + pcount;
64 
65 		while ((ch = getc(fp)) != EOF && ch >= 'a')
66 			if ((*p++ = ch) == 'q')
67 				*p++ = 'u';
68 		lastch = ch;
69 	}
70 	wordlen = (int) (p - buf);
71 	*p = '\0';
72 	return (buf);
73 }
74 
75 /*
76  * Reset the state of nextword() and do the fseek()
77  */
78 long
79 dictseek(fp, offset, ptrname)
80 	FILE *fp;
81 	long offset;
82 	int ptrname;
83 {
84 	if (fp == NULL) {
85 		if ((sp = dictspace + offset) >= dictend)
86 			return (-1);
87 		return (0);
88 	}
89 
90 	first = 1;
91 	return (fseek(fp, offset, ptrname));
92 }
93 
94 FILE *
95 opendict(dict)
96 	char *dict;
97 {
98 	FILE *fp;
99 
100 	if ((fp = fopen(dict, "r")) == NULL)
101 		return (NULL);
102 	return (fp);
103 }
104 
105 /*
106  * Load the given dictionary and initialize the pointers
107  */
108 int
109 loaddict(fp)
110 	FILE *fp;
111 {
112 	struct stat statb;
113 	long n;
114 	int st;
115 	char *p;
116 
117 	if (fstat(fileno(fp), &statb) < 0) {
118 		(void)fclose(fp);
119 		return (-1);
120 	}
121 
122 	/*
123 	 * An extra character (a sentinel) is allocated and set to null
124 	 * to improve the expansion loop in nextword().
125 	 */
126 	if ((dictspace = malloc(statb.st_size + 1)) == NULL) {
127 		(void)fclose(fp);
128 		return (-1);
129 	}
130 	n = (long)statb.st_size;
131 	sp = dictspace;
132 	dictend = dictspace + n;
133 
134 	p = dictspace;
135 	st = -1;
136 	while (n > 0 && (st = fread(p, 1, BUFSIZ, fp)) > 0) {
137 		p += st;
138 		n -= st;
139 	}
140 	if (st < 0) {
141 		(void)fclose(fp);
142 		(void)fprintf(stderr, "Error reading dictionary\n");
143 		return (-1);
144 	}
145 	*p = '\0';
146 	return (0);
147 }
148 
149 /*
150  * Dependent on the exact format of the index file:
151  * Starting offset field begins in column 1 and length field in column 9
152  * Taking the easy way out, the input buffer is made "large" and a check
153  * is made for lines that are too long
154  */
155 int
156 loadindex(indexfile)
157 	char *indexfile;
158 {
159 	register int i, j;
160 	char buf[BUFSIZ];
161 	FILE *fp;
162 	extern struct dictindex dictindex[];
163 
164 	if ((fp = fopen(indexfile, "r")) == NULL) {
165 		(void) fprintf(stderr, "Can't open '%s'\n", indexfile);
166 		return (-1);
167 	}
168 	i = 0;
169 	while (fgets(buf, sizeof(buf), fp) != NULL) {
170 		if (strchr(buf, '\n') == NULL) {
171 			(void)fprintf(stderr,
172 				"A line in the index file is too long\n");
173 			return(-1);
174 		}
175 		j = *buf - 'a';
176 		if (i != j) {
177 		    (void) fprintf(stderr, "Bad index order\n");
178 		    return(-1);
179 		}
180 		dictindex[j].start = atol(buf + 1);
181 		dictindex[j].length = atol(buf + 9) - dictindex[j].start;
182 		i++;
183 	}
184 	if (i != 26) {
185 		(void) fprintf(stderr, "Bad index length\n");
186 		return(-1);
187 	}
188 	(void) fclose(fp);
189 	return(0);
190 }
191