Commit | Line | Data |
---|---|---|
070c62a6 | 1 | /* $Id: man_hash.c,v 1.27 2014/04/20 16:46:04 schwarze Exp $ */ |
80387638 SW |
2 | /* |
3 | * Copyright (c) 2008, 2009, 2010 Kristaps Dzonsons <kristaps@bsd.lv> | |
4 | * | |
5 | * Permission to use, copy, modify, and distribute this software for any | |
6 | * purpose with or without fee is hereby granted, provided that the above | |
7 | * copyright notice and this permission notice appear in all copies. | |
8 | * | |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | */ | |
17 | #ifdef HAVE_CONFIG_H | |
18 | #include "config.h" | |
19 | #endif | |
20 | ||
21 | #include <sys/types.h> | |
22 | ||
23 | #include <assert.h> | |
24 | #include <ctype.h> | |
25 | #include <limits.h> | |
80387638 SW |
26 | #include <string.h> |
27 | ||
60e1e752 | 28 | #include "man.h" |
80387638 SW |
29 | #include "mandoc.h" |
30 | #include "libman.h" | |
31 | ||
32 | #define HASH_DEPTH 6 | |
33 | ||
34 | #define HASH_ROW(x) do { \ | |
36342e81 | 35 | if (isupper((unsigned char)(x))) \ |
80387638 SW |
36 | (x) -= 65; \ |
37 | else \ | |
38 | (x) -= 97; \ | |
39 | (x) *= HASH_DEPTH; \ | |
40 | } while (/* CONSTCOND */ 0) | |
41 | ||
42 | /* | |
43 | * Lookup table is indexed first by lower-case first letter (plus one | |
44 | * for the period, which is stored in the last row), then by lower or | |
45 | * uppercase second letter. Buckets correspond to the index of the | |
46 | * macro (the integer value of the enum stored as a char to save a bit | |
47 | * of space). | |
48 | */ | |
36342e81 | 49 | static unsigned char table[26 * HASH_DEPTH]; |
80387638 | 50 | |
070c62a6 | 51 | |
80387638 SW |
52 | /* |
53 | * XXX - this hash has global scope, so if intended for use as a library | |
54 | * with multiple callers, it will need re-invocation protection. | |
55 | */ | |
56 | void | |
57 | man_hash_init(void) | |
58 | { | |
59 | int i, j, x; | |
60 | ||
61 | memset(table, UCHAR_MAX, sizeof(table)); | |
62 | ||
070c62a6 | 63 | assert(MAN_MAX < UCHAR_MAX); |
80387638 SW |
64 | |
65 | for (i = 0; i < (int)MAN_MAX; i++) { | |
66 | x = man_macronames[i][0]; | |
67 | ||
36342e81 | 68 | assert(isalpha((unsigned char)x)); |
80387638 SW |
69 | |
70 | HASH_ROW(x); | |
71 | ||
72 | for (j = 0; j < HASH_DEPTH; j++) | |
73 | if (UCHAR_MAX == table[x + j]) { | |
36342e81 | 74 | table[x + j] = (unsigned char)i; |
80387638 SW |
75 | break; |
76 | } | |
77 | ||
78 | assert(j < HASH_DEPTH); | |
79 | } | |
80 | } | |
81 | ||
80387638 SW |
82 | enum mant |
83 | man_hash_find(const char *tmp) | |
84 | { | |
85 | int x, y, i; | |
86 | enum mant tok; | |
87 | ||
88 | if ('\0' == (x = tmp[0])) | |
89 | return(MAN_MAX); | |
36342e81 | 90 | if ( ! (isalpha((unsigned char)x))) |
80387638 SW |
91 | return(MAN_MAX); |
92 | ||
93 | HASH_ROW(x); | |
94 | ||
95 | for (i = 0; i < HASH_DEPTH; i++) { | |
96 | if (UCHAR_MAX == (y = table[x + i])) | |
97 | return(MAN_MAX); | |
98 | ||
99 | tok = (enum mant)y; | |
100 | if (0 == strcmp(tmp, man_macronames[tok])) | |
101 | return(tok); | |
102 | } | |
103 | ||
104 | return(MAN_MAX); | |
105 | } |