1 |
|
|
/* $OpenBSD: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $ */ |
2 |
|
|
|
3 |
|
|
/**************************************************************************** |
4 |
|
|
* Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * |
5 |
|
|
* * |
6 |
|
|
* Permission is hereby granted, free of charge, to any person obtaining a * |
7 |
|
|
* copy of this software and associated documentation files (the * |
8 |
|
|
* "Software"), to deal in the Software without restriction, including * |
9 |
|
|
* without limitation the rights to use, copy, modify, merge, publish, * |
10 |
|
|
* distribute, distribute with modifications, sublicense, and/or sell * |
11 |
|
|
* copies of the Software, and to permit persons to whom the Software is * |
12 |
|
|
* furnished to do so, subject to the following conditions: * |
13 |
|
|
* * |
14 |
|
|
* The above copyright notice and this permission notice shall be included * |
15 |
|
|
* in all copies or substantial portions of the Software. * |
16 |
|
|
* * |
17 |
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * |
18 |
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * |
19 |
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * |
20 |
|
|
* IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * |
21 |
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * |
22 |
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * |
23 |
|
|
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. * |
24 |
|
|
* * |
25 |
|
|
* Except as contained in this notice, the name(s) of the above copyright * |
26 |
|
|
* holders shall not be used in advertising or otherwise to promote the * |
27 |
|
|
* sale, use or other dealings in this Software without prior written * |
28 |
|
|
* authorization. * |
29 |
|
|
****************************************************************************/ |
30 |
|
|
|
31 |
|
|
/**************************************************************************** |
32 |
|
|
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * |
33 |
|
|
* and: Eric S. Raymond <esr@snark.thyrsus.com> * |
34 |
|
|
* and: Thomas E. Dickey 1996-on * |
35 |
|
|
****************************************************************************/ |
36 |
|
|
|
37 |
|
|
/* |
38 |
|
|
* comp_hash.c --- Routines to deal with the hashtable of capability |
39 |
|
|
* names. |
40 |
|
|
* |
41 |
|
|
*/ |
42 |
|
|
|
43 |
|
|
#define USE_TERMLIB 1 |
44 |
|
|
#include <curses.priv.h> |
45 |
|
|
|
46 |
|
|
#include <tic.h> |
47 |
|
|
#include <hashsize.h> |
48 |
|
|
|
49 |
|
|
#ifdef MAIN_PROGRAM |
50 |
|
|
#include <ctype.h> |
51 |
|
|
#undef DEBUG |
52 |
|
|
#define DEBUG(level, params) /*nothing */ |
53 |
|
|
#endif |
54 |
|
|
|
55 |
|
|
MODULE_ID("$Id: comp_hash.c,v 1.8 2010/01/12 23:22:06 nicm Exp $") |
56 |
|
|
|
57 |
|
|
static int hash_function(const char *); |
58 |
|
|
|
59 |
|
|
/* |
60 |
|
|
* _nc_make_hash_table() |
61 |
|
|
* |
62 |
|
|
* Takes the entries in table[] and hashes them into hash_table[] |
63 |
|
|
* by name. There are CAPTABSIZE entries in table[] and HASHTABSIZE |
64 |
|
|
* slots in hash_table[]. |
65 |
|
|
* |
66 |
|
|
*/ |
67 |
|
|
|
68 |
|
|
#ifdef MAIN_PROGRAM |
69 |
|
|
|
70 |
|
|
#undef MODULE_ID |
71 |
|
|
#define MODULE_ID(id) /*nothing */ |
72 |
|
|
#include <tinfo/doalloc.c> |
73 |
|
|
|
74 |
|
|
static void |
75 |
|
|
_nc_make_hash_table(struct name_table_entry *table, |
76 |
|
|
short *hash_table) |
77 |
|
|
{ |
78 |
|
|
short i; |
79 |
|
|
int hashvalue; |
80 |
|
|
int collisions = 0; |
81 |
|
|
|
82 |
✓✓ |
7964 |
for (i = 0; i < HASHTABSIZE; i++) { |
83 |
|
3976 |
hash_table[i] = -1; |
84 |
|
|
} |
85 |
✓✓ |
3984 |
for (i = 0; i < CAPTABSIZE; i++) { |
86 |
|
1988 |
hashvalue = hash_function(table[i].nte_name); |
87 |
|
|
|
88 |
✓✓ |
1988 |
if (hash_table[hashvalue] >= 0) |
89 |
|
500 |
collisions++; |
90 |
|
|
|
91 |
✓✗ |
1988 |
if (hash_table[hashvalue] != 0) |
92 |
|
1988 |
table[i].nte_link = hash_table[hashvalue]; |
93 |
|
1988 |
hash_table[hashvalue] = i; |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
DEBUG(4, ("Hash table complete: %d collisions out of %d entries", |
97 |
|
|
collisions, CAPTABSIZE)); |
98 |
|
4 |
} |
99 |
|
|
#endif |
100 |
|
|
|
101 |
|
|
/* |
102 |
|
|
* int hash_function(string) |
103 |
|
|
* |
104 |
|
|
* Computes the hashing function on the given string. |
105 |
|
|
* |
106 |
|
|
* The current hash function is the sum of each consectutive pair |
107 |
|
|
* of characters, taken as two-byte integers, mod HASHTABSIZE. |
108 |
|
|
* |
109 |
|
|
*/ |
110 |
|
|
|
111 |
|
|
static int |
112 |
|
|
hash_function(const char *string) |
113 |
|
|
{ |
114 |
|
|
long sum = 0; |
115 |
|
|
|
116 |
|
|
DEBUG(9, ("hashing %s", string)); |
117 |
✓✓ |
17512 |
while (*string) { |
118 |
|
5774 |
sum += (long) (*string + (*(string + 1) << 8)); |
119 |
|
5774 |
string++; |
120 |
|
|
} |
121 |
|
|
|
122 |
|
|
DEBUG(9, ("sum is %ld", sum)); |
123 |
|
1988 |
return (int) (sum % HASHTABSIZE); |
124 |
|
|
} |
125 |
|
|
|
126 |
|
|
/* |
127 |
|
|
* struct name_table_entry * |
128 |
|
|
* find_entry(string) |
129 |
|
|
* |
130 |
|
|
* Finds the entry for the given string in the hash table if present. |
131 |
|
|
* Returns a pointer to the entry in the table or 0 if not found. |
132 |
|
|
* |
133 |
|
|
*/ |
134 |
|
|
|
135 |
|
|
#ifndef MAIN_PROGRAM |
136 |
|
|
NCURSES_EXPORT(struct name_table_entry const *) |
137 |
|
|
_nc_find_entry(const char *string, |
138 |
|
|
const short *hash_table) |
139 |
|
|
{ |
140 |
|
|
int hashvalue; |
141 |
|
|
struct name_table_entry const *ptr = 0; |
142 |
|
|
struct name_table_entry const *real_table; |
143 |
|
|
|
144 |
|
|
hashvalue = hash_function(string); |
145 |
|
|
|
146 |
|
|
if (hash_table[hashvalue] >= 0) { |
147 |
|
|
real_table = _nc_get_table(hash_table != _nc_get_hash_table(FALSE)); |
148 |
|
|
ptr = real_table + hash_table[hashvalue]; |
149 |
|
|
while (strcmp(ptr->nte_name, string) != 0) { |
150 |
|
|
if (ptr->nte_link < 0) |
151 |
|
|
return 0; |
152 |
|
|
ptr = real_table + (ptr->nte_link + hash_table[HASHTABSIZE]); |
153 |
|
|
} |
154 |
|
|
} |
155 |
|
|
|
156 |
|
|
return (ptr); |
157 |
|
|
} |
158 |
|
|
|
159 |
|
|
/* |
160 |
|
|
* struct name_table_entry * |
161 |
|
|
* find_type_entry(string, type, table) |
162 |
|
|
* |
163 |
|
|
* Finds the first entry for the given name with the given type in the |
164 |
|
|
* given table if present (as distinct from find_entry, which finds the |
165 |
|
|
* the last entry regardless of type). You can use this if you detect |
166 |
|
|
* a name clash. It's slower, though. Returns a pointer to the entry |
167 |
|
|
* in the table or 0 if not found. |
168 |
|
|
*/ |
169 |
|
|
|
170 |
|
|
NCURSES_EXPORT(struct name_table_entry const *) |
171 |
|
|
_nc_find_type_entry(const char *string, |
172 |
|
|
int type, |
173 |
|
|
const struct name_table_entry *table) |
174 |
|
|
{ |
175 |
|
|
struct name_table_entry const *ptr; |
176 |
|
|
|
177 |
|
|
for (ptr = table; ptr < table + CAPTABSIZE; ptr++) { |
178 |
|
|
if (ptr->nte_type == type && strcmp(string, ptr->nte_name) == 0) |
179 |
|
|
return (ptr); |
180 |
|
|
} |
181 |
|
|
|
182 |
|
|
return ((struct name_table_entry *) NULL); |
183 |
|
|
} |
184 |
|
|
#endif |
185 |
|
|
|
186 |
|
|
#ifdef MAIN_PROGRAM |
187 |
|
|
/* |
188 |
|
|
* This filter reads from standard input a list of tab-delimited columns, |
189 |
|
|
* (e.g., from Caps.filtered) computes the hash-value of a specified column and |
190 |
|
|
* writes the hashed tables to standard output. |
191 |
|
|
* |
192 |
|
|
* By compiling the hash table at build time, we're able to make the entire |
193 |
|
|
* set of terminfo and termcap tables readonly (and also provide some runtime |
194 |
|
|
* performance enhancement). |
195 |
|
|
*/ |
196 |
|
|
|
197 |
|
|
#define MAX_COLUMNS BUFSIZ /* this _has_ to be worst-case */ |
198 |
|
|
|
199 |
|
|
static char ** |
200 |
|
|
parse_columns(char *buffer) |
201 |
|
|
{ |
202 |
|
|
static char **list; |
203 |
|
|
|
204 |
|
|
int col = 0; |
205 |
|
|
|
206 |
✓✓✗✓
|
8428 |
if (list == 0 && (list = typeCalloc(char *, MAX_COLUMNS)) == 0) |
207 |
|
|
return (0); |
208 |
|
|
|
209 |
✓✓ |
4212 |
if (*buffer != '#') { |
210 |
✓✓ |
22584 |
while (*buffer != '\0') { |
211 |
|
|
char *s; |
212 |
✓✓✓✓
|
377176 |
for (s = buffer; (*s != '\0') && !isspace(UChar(*s)); s++) |
213 |
|
|
/*EMPTY */ ; |
214 |
✓✗ |
22580 |
if (s != buffer) { |
215 |
|
22580 |
char mark = *s; |
216 |
|
22580 |
*s = '\0'; |
217 |
✗✗ |
22580 |
if ((s - buffer) > 1 |
218 |
✓✓ |
42064 |
&& (*buffer == '"') |
219 |
✗✓ |
19484 |
&& (s[-1] == '"')) { /* strip the quotes */ |
220 |
|
|
assert(s > buffer + 1); |
221 |
|
|
s[-1] = '\0'; |
222 |
|
|
buffer++; |
223 |
|
|
} |
224 |
|
22580 |
list[col] = buffer; |
225 |
|
22580 |
col++; |
226 |
✓✓ |
22580 |
if (mark == '\0') |
227 |
|
1988 |
break; |
228 |
✓✗✓✓
|
51512 |
while (*++s && isspace(UChar(*s))) |
229 |
|
|
/*EMPTY */ ; |
230 |
|
|
buffer = s; |
231 |
✓✓ |
20592 |
} else |
232 |
|
|
break; |
233 |
✓✓ |
20592 |
} |
234 |
|
|
} |
235 |
|
4212 |
return col ? list : 0; |
236 |
|
4212 |
} |
237 |
|
|
|
238 |
|
|
int |
239 |
|
|
main(int argc, char **argv) |
240 |
|
|
{ |
241 |
|
8 |
struct name_table_entry *name_table = typeCalloc(struct |
242 |
|
|
name_table_entry, CAPTABSIZE); |
243 |
|
4 |
short *hash_table = typeCalloc(short, HASHTABSIZE); |
244 |
|
|
const char *root_name = ""; |
245 |
|
|
int column = 0; |
246 |
|
|
int bigstring = 0; |
247 |
|
|
int n; |
248 |
|
4 |
char buffer[BUFSIZ]; |
249 |
|
|
|
250 |
|
|
static const char *typenames[] = |
251 |
|
|
{"BOOLEAN", "NUMBER", "STRING"}; |
252 |
|
|
|
253 |
|
|
short BoolCount = 0; |
254 |
|
|
short NumCount = 0; |
255 |
|
|
short StrCount = 0; |
256 |
|
|
|
257 |
|
|
/* The first argument is the column-number (starting with 0). |
258 |
|
|
* The second is the root name of the tables to generate. |
259 |
|
|
*/ |
260 |
|
4 |
if (argc <= 3 |
261 |
✓✗ |
8 |
|| (column = atoi(argv[1])) <= 0 |
262 |
✓✗ |
4 |
|| (column >= MAX_COLUMNS) |
263 |
|
4 |
|| *(root_name = argv[2]) == 0 |
264 |
✓✗ |
8 |
|| (bigstring = atoi(argv[3])) < 0 |
265 |
✗✓ |
8 |
|| name_table == 0 |
266 |
|
4 |
|| hash_table == 0) { |
267 |
|
|
fprintf(stderr, "usage: make_hash column root_name bigstring\n"); |
268 |
|
|
exit(EXIT_FAILURE); |
269 |
|
|
} |
270 |
|
|
|
271 |
|
|
/* |
272 |
|
|
* Read the table into our arrays. |
273 |
|
|
*/ |
274 |
✓✓✓✗
|
8432 |
for (n = 0; (n < CAPTABSIZE) && fgets(buffer, BUFSIZ, stdin);) { |
275 |
|
4212 |
char **list, *nlp = strchr(buffer, '\n'); |
276 |
✓✗ |
4212 |
if (nlp) |
277 |
|
4212 |
*nlp = '\0'; |
278 |
|
4212 |
list = parse_columns(buffer); |
279 |
✓✓ |
4212 |
if (list == 0) /* blank or comment */ |
280 |
|
2224 |
continue; |
281 |
|
1988 |
name_table[n].nte_link = -1; /* end-of-hash */ |
282 |
|
1988 |
name_table[n].nte_name = strdup(list[column]); |
283 |
✓✓ |
1988 |
if (!strcmp(list[2], "bool")) { |
284 |
|
176 |
name_table[n].nte_type = BOOLEAN; |
285 |
|
176 |
name_table[n].nte_index = BoolCount++; |
286 |
✓✓ |
1988 |
} else if (!strcmp(list[2], "num")) { |
287 |
|
156 |
name_table[n].nte_type = NUMBER; |
288 |
|
156 |
name_table[n].nte_index = NumCount++; |
289 |
✓✗ |
1812 |
} else if (!strcmp(list[2], "str")) { |
290 |
|
1656 |
name_table[n].nte_type = STRING; |
291 |
|
1656 |
name_table[n].nte_index = StrCount++; |
292 |
|
|
} else { |
293 |
|
|
fprintf(stderr, "Unknown type: %s\n", list[2]); |
294 |
|
|
exit(EXIT_FAILURE); |
295 |
|
|
} |
296 |
|
1988 |
n++; |
297 |
|
1988 |
} |
298 |
|
4 |
_nc_make_hash_table(name_table, hash_table); |
299 |
|
|
|
300 |
|
|
/* |
301 |
|
|
* Write the compiled tables to standard output |
302 |
|
|
*/ |
303 |
✓✗ |
4 |
if (bigstring) { |
304 |
|
|
int len = 0; |
305 |
|
|
int nxt; |
306 |
|
|
|
307 |
|
4 |
printf("static const char %s_names_text[] = \\\n", root_name); |
308 |
✓✓ |
3984 |
for (n = 0; n < CAPTABSIZE; n++) { |
309 |
|
1988 |
nxt = (int) strlen(name_table[n].nte_name) + 5; |
310 |
✓✓ |
1988 |
if (nxt + len > 72) { |
311 |
|
224 |
printf("\\\n"); |
312 |
|
|
len = 0; |
313 |
|
224 |
} |
314 |
|
1988 |
printf("\"%s\\0\" ", name_table[n].nte_name); |
315 |
|
1988 |
len += nxt; |
316 |
|
|
} |
317 |
|
4 |
printf(";\n\n"); |
318 |
|
|
|
319 |
|
|
len = 0; |
320 |
|
4 |
printf("static name_table_data const %s_names_data[] =\n", |
321 |
|
|
root_name); |
322 |
|
4 |
printf("{\n"); |
323 |
✓✓ |
3984 |
for (n = 0; n < CAPTABSIZE; n++) { |
324 |
|
1988 |
printf("\t{ %15d,\t%10s,\t%3d, %3d }%c\n", |
325 |
|
|
len, |
326 |
|
1988 |
typenames[name_table[n].nte_type], |
327 |
|
1988 |
name_table[n].nte_index, |
328 |
|
1988 |
name_table[n].nte_link, |
329 |
|
1988 |
n < CAPTABSIZE - 1 ? ',' : ' '); |
330 |
|
1988 |
len += (int) strlen(name_table[n].nte_name) + 1; |
331 |
|
|
} |
332 |
|
4 |
printf("};\n\n"); |
333 |
|
4 |
printf("static struct name_table_entry *_nc_%s_table = 0;\n\n", root_name); |
334 |
|
4 |
} else { |
335 |
|
|
|
336 |
|
|
printf("static struct name_table_entry %s _nc_%s_table[] =\n", |
337 |
|
|
bigstring ? "" : "const", |
338 |
|
|
root_name); |
339 |
|
|
printf("{\n"); |
340 |
|
|
for (n = 0; n < CAPTABSIZE; n++) { |
341 |
|
|
snprintf(buffer, sizeof(buffer), "\"%s\"", |
342 |
|
|
name_table[n].nte_name); |
343 |
|
|
printf("\t{ %15s,\t%10s,\t%3d, %3d }%c\n", |
344 |
|
|
buffer, |
345 |
|
|
typenames[name_table[n].nte_type], |
346 |
|
|
name_table[n].nte_index, |
347 |
|
|
name_table[n].nte_link, |
348 |
|
|
n < CAPTABSIZE - 1 ? ',' : ' '); |
349 |
|
|
} |
350 |
|
|
printf("};\n\n"); |
351 |
|
|
} |
352 |
|
|
|
353 |
|
4 |
printf("static const short _nc_%s_hash_table[%d] =\n", |
354 |
|
|
root_name, |
355 |
|
|
HASHTABSIZE + 1); |
356 |
|
4 |
printf("{\n"); |
357 |
✓✓ |
7960 |
for (n = 0; n < HASHTABSIZE; n++) { |
358 |
|
3976 |
printf("\t%3d,\n", hash_table[n]); |
359 |
|
|
} |
360 |
|
4 |
printf("\t0\t/* base-of-table */\n"); |
361 |
|
4 |
printf("};\n\n"); |
362 |
|
|
|
363 |
|
4 |
printf("#if (BOOLCOUNT!=%d)||(NUMCOUNT!=%d)||(STRCOUNT!=%d)\n", |
364 |
|
4 |
BoolCount, NumCount, StrCount); |
365 |
|
4 |
printf("#error\t--> term.h and comp_captab.c disagree about the <--\n"); |
366 |
|
4 |
printf("#error\t--> numbers of booleans, numbers and/or strings <--\n"); |
367 |
|
4 |
printf("#endif\n\n"); |
368 |
|
|
|
369 |
|
4 |
free(hash_table); |
370 |
|
|
return EXIT_SUCCESS; |
371 |
|
4 |
} |
372 |
|
|
#endif |