]> git.cameronkatri.com Git - mandoc.git/blob - mdoc_hash.c
Hash now accepts `br'. This needs work (way to sparse).
[mandoc.git] / mdoc_hash.c
1 /* $Id: mdoc_hash.c,v 1.6 2009/07/17 10:56:27 kristaps Exp $ */
2 /*
3 * Copyright (c) 2008, 2009 Kristaps Dzonsons <kristaps@kth.se>
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 #include <assert.h>
18 #include <ctype.h>
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "libmdoc.h"
24
25 #define ADJUST_MAJOR(x) \
26 do if (37 == (x)) \
27 (x) = 0; /* % -> 00 */ \
28 else if (91 > (x)) \
29 (x) -= 64; /* A-Z -> 01 - 26 */ \
30 else \
31 (x) -= 70; /* a-z -> 27 - 52 */ \
32 while (/*CONSTCOND*/0)
33
34 #define ADJUST_MINOR(y) \
35 do if (49 == (y)) \
36 (y) = 0; /* 1 -> 00 */ \
37 else if (91 > (y)) \
38 (y) -= 65; /* A-Z -> 00 - 25 */ \
39 else \
40 (y) -= 97; /* a-z -> 00 - 25 */ \
41 while (/*CONSTCOND*/0)
42
43 #define INDEX(maj, min) \
44 ((maj) * 26 * 3) + ((min) * 3)
45
46 #define SLOTCMP(slot, val) \
47 (mdoc_macronames[(slot)][0] == (val)[0] && \
48 mdoc_macronames[(slot)][1] == (val)[1] && \
49 (0 == (val)[2] || \
50 mdoc_macronames[(slot)][2] == (val)[2]))
51
52
53 void
54 mdoc_hash_free(void *htab)
55 {
56
57 free(htab);
58 }
59
60
61
62 void *
63 mdoc_hash_alloc(void)
64 {
65 int i, major, minor, ind;
66 const void **htab;
67
68 htab = calloc(26 * 3 * 52, sizeof(struct mdoc_macro *));
69 if (NULL == htab)
70 return(NULL);
71
72 for (i = 0; i < MDOC_MAX; i++) {
73 major = mdoc_macronames[i][0];
74 assert(isalpha((u_char)major) || 37 == major);
75
76 ADJUST_MAJOR(major);
77
78 minor = mdoc_macronames[i][1];
79 assert(isalpha((u_char)minor) || 49 == minor);
80
81 ADJUST_MINOR(minor);
82
83 ind = INDEX(major, minor);
84
85 if (NULL == htab[ind]) {
86 htab[ind] = &mdoc_macros[i];
87 continue;
88 }
89
90 if (NULL == htab[++ind]) {
91 htab[ind] = &mdoc_macros[i];
92 continue;
93 }
94
95 assert(NULL == htab[++ind]);
96 htab[ind] = &mdoc_macros[i];
97 }
98
99 return((void *)htab);
100 }
101
102
103 int
104 mdoc_hash_find(const void *arg, const char *tmp)
105 {
106 int major, minor, ind, slot;
107 const void **htab;
108
109 htab = /* LINTED */
110 (const void **)arg;
111
112 if (0 == (major = tmp[0]))
113 return(MDOC_MAX);
114 if (0 == (minor = tmp[1]))
115 return(MDOC_MAX);
116
117 if (tmp[2] && tmp[3])
118 return(MDOC_MAX);
119
120 if (37 != major && ! isalpha((u_char)major))
121 return(MDOC_MAX);
122 if (49 != minor && ! isalpha((u_char)minor))
123 return(MDOC_MAX);
124
125 ADJUST_MAJOR(major);
126 ADJUST_MINOR(minor);
127
128 ind = INDEX(major, minor);
129
130 if (htab[ind]) {
131 slot = htab[ind] - /* LINTED */
132 (void *)mdoc_macros;
133 assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
134 slot /= sizeof(struct mdoc_macro);
135 if (SLOTCMP(slot, tmp))
136 return(slot);
137 ind++;
138 }
139
140 if (htab[ind]) {
141 slot = htab[ind] - /* LINTED */
142 (void *)mdoc_macros;
143 assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
144 slot /= sizeof(struct mdoc_macro);
145 if (SLOTCMP(slot, tmp))
146 return(slot);
147 ind++;
148 }
149
150 if (NULL == htab[ind])
151 return(MDOC_MAX);
152 slot = htab[ind] - /* LINTED */
153 (void *)mdoc_macros;
154 assert(0 == (size_t)slot % sizeof(struct mdoc_macro));
155 slot /= sizeof(struct mdoc_macro);
156 if (SLOTCMP(slot, tmp))
157 return(slot);
158
159 return(MDOC_MAX);
160 }
161