]>
git.cameronkatri.com Git - mandoc.git/blob - ascii.c
1 /* $Id: ascii.c,v 1.1 2009/03/16 22:19:19 kristaps Exp $ */
3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@openbsd.org>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
26 #define ASCII_PRINT_HI 126
27 #define ASCII_PRINT_LO 32
30 * Lookup and hashing routines for constructing the ASCII symbol table,
31 * which should contain a significant portion of mdoc(7)'s special
38 /* 32- and 64-bit alignment safe. */
44 const struct line
*line
;
48 #define LINE(w, x, y, z) \
49 { (w), (y), (x), (z) },
50 static const struct line lines
[] = {
55 static inline int match(const struct line
*,
56 const char *, size_t);
67 * Constructs a very basic chaining hashtable. The hash routine
68 * is simply the integral value of the first character.
69 * Subsequent entries are chained in the order they're processed
70 * (they're in-line re-ordered during lookup).
73 assert(0 == sizeof(lines
) % sizeof(struct line
));
74 len
= sizeof(lines
) / sizeof(struct line
);
76 if (NULL
== (p
= calloc((size_t)len
, sizeof(struct linep
))))
79 htab
= calloc(ASCII_PRINT_HI
- ASCII_PRINT_LO
+ 1,
80 sizeof(struct linep
**));
85 for (i
= 0; i
< len
; i
++) {
86 assert(lines
[i
].codesz
> 0);
87 assert(lines
[i
].code
);
90 p
[i
].line
= &lines
[i
];
92 hash
= (int)lines
[i
].code
[0] - ASCII_PRINT_LO
;
94 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
])) {
99 for ( ; pp
->next
; pp
= pp
->next
)
105 return((void *)htab
);
110 a2ascii(void *htabp
, const char *p
, size_t sz
, size_t *rsz
)
112 struct linep
*pp
, *prev
;
116 htab
= (void **)htabp
;
120 assert(p
[0] >= ASCII_PRINT_LO
&& p
[0] <= ASCII_PRINT_HI
);
123 * Lookup the symbol in the symbol hash. See ascii2htab for the
124 * hashtable specs. This dynamically re-orders the hash chain
125 * to optimise for repeat hits.
128 hash
= (int)p
[0] - ASCII_PRINT_LO
;
130 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
]))
133 if (NULL
== pp
->next
) {
134 if ( ! match(pp
->line
, p
, sz
))
136 *rsz
= pp
->line
->outsz
;
137 return(pp
->line
->out
);
140 for (prev
= NULL
; pp
; pp
= pp
->next
) {
141 if ( ! match(pp
->line
, p
, sz
)) {
146 /* Re-order the hash chain. */
149 prev
->next
= pp
->next
;
150 pp
->next
= ((struct linep
**)htab
)[hash
];
154 *rsz
= pp
->line
->outsz
;
155 return(pp
->line
->out
);
163 match(const struct line
*line
, const char *p
, size_t sz
)
166 if (line
->codesz
!= sz
)
168 return(0 == strncmp(line
->code
, p
, sz
));