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 *
nextword(fp)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
dictseek(fp,offset,ptrname)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 *
opendict(dict)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
loaddict(fp)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
loadindex(indexfile)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