]>
git.cameronkatri.com Git - mandoc.git/blob - ascii.c
1 /* $Id: ascii.c,v 1.4 2009/03/20 21:58:38 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
[] = {
60 static inline int match(const struct line
*,
61 const char *, size_t);
65 term_asciifree(void *arg
)
69 tab
= (struct asciitab
*)arg
;
86 * Constructs a very basic chaining hashtable. The hash routine
87 * is simply the integral value of the first character.
88 * Subsequent entries are chained in the order they're processed
89 * (they're in-line re-ordered during lookup).
92 if (NULL
== (tab
= malloc(sizeof(struct asciitab
))))
95 len
= sizeof(lines
) / sizeof(struct line
);
97 if (NULL
== (p
= calloc((size_t)len
, sizeof(struct linep
))))
100 htab
= calloc(ASCII_PRINT_HI
- ASCII_PRINT_LO
+ 1,
101 sizeof(struct linep
**));
106 for (i
= 0; i
< len
; i
++) {
107 assert(lines
[i
].codesz
> 0);
108 assert(lines
[i
].code
);
109 assert(lines
[i
].out
);
111 p
[i
].line
= &lines
[i
];
113 hash
= (int)lines
[i
].code
[0] - ASCII_PRINT_LO
;
115 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
])) {
120 for ( ; pp
->next
; pp
= pp
->next
)
134 term_a2ascii(void *arg
, const char *p
, size_t sz
, size_t *rsz
)
136 struct asciitab
*tab
;
137 struct linep
*pp
, *prev
;
141 tab
= (struct asciitab
*)arg
;
146 assert(p
[0] >= ASCII_PRINT_LO
&& p
[0] <= ASCII_PRINT_HI
);
149 * Lookup the symbol in the symbol hash. See ascii2htab for the
150 * hashtable specs. This dynamically re-orders the hash chain
151 * to optimise for repeat hits.
154 hash
= (int)p
[0] - ASCII_PRINT_LO
;
156 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
]))
159 if (NULL
== pp
->next
) {
160 if ( ! match(pp
->line
, p
, sz
))
162 *rsz
= pp
->line
->outsz
;
163 return(pp
->line
->out
);
166 for (prev
= NULL
; pp
; pp
= pp
->next
) {
167 if ( ! match(pp
->line
, p
, sz
)) {
172 /* Re-order the hash chain. */
175 prev
->next
= pp
->next
;
176 pp
->next
= ((struct linep
**)htab
)[hash
];
180 *rsz
= pp
->line
->outsz
;
181 return(pp
->line
->out
);
189 match(const struct line
*line
, const char *p
, size_t sz
)
192 if (line
->codesz
!= sz
)
194 return(0 == strncmp(line
->code
, p
, sz
));