]>
git.cameronkatri.com Git - mandoc.git/blob - ascii.c
1 /* $Id: ascii.c,v 1.8 2009/06/10 20:18:43 kristaps Exp $ */
3 * Copyright (c) 2009 Kristaps Dzonsons <kristaps@kth.se>
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.
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.
24 #define ASCII_PRINT_HI 126
25 #define ASCII_PRINT_LO 32
30 /* 32- and 64-bit alignment safe. */
36 const struct line
*line
;
40 #define LINE(w, x, y, z) \
41 { (w), (y), (x), (z) },
42 static const struct line lines
[] = {
52 static inline int match(const struct line
*,
53 const char *, size_t);
57 term_asciifree(void *arg
)
61 tab
= (struct asciitab
*)arg
;
78 * Constructs a very basic chaining hashtable. The hash routine
79 * is simply the integral value of the first character.
80 * Subsequent entries are chained in the order they're processed
81 * (they're in-line re-ordered during lookup).
84 if (NULL
== (tab
= malloc(sizeof(struct asciitab
))))
87 len
= sizeof(lines
) / sizeof(struct line
);
89 if (NULL
== (p
= calloc((size_t)len
, sizeof(struct linep
))))
92 htab
= calloc(ASCII_PRINT_HI
- ASCII_PRINT_LO
+ 1,
93 sizeof(struct linep
**));
98 for (i
= 0; i
< len
; i
++) {
99 assert(lines
[i
].codesz
> 0);
100 assert(lines
[i
].code
);
101 assert(lines
[i
].out
);
103 p
[i
].line
= &lines
[i
];
105 hash
= (int)lines
[i
].code
[0] - ASCII_PRINT_LO
;
107 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
])) {
112 for ( ; pp
->next
; pp
= pp
->next
)
126 term_a2ascii(void *arg
, const char *p
, size_t sz
, size_t *rsz
)
128 struct asciitab
*tab
;
129 struct linep
*pp
, *prev
;
133 tab
= (struct asciitab
*)arg
;
139 if (p
[0] < ASCII_PRINT_LO
|| p
[0] > ASCII_PRINT_HI
)
144 * Lookup the symbol in the symbol hash. See ascii2htab for the
145 * hashtable specs. This dynamically re-orders the hash chain
146 * to optimise for repeat hits.
149 hash
= (int)p
[0] - ASCII_PRINT_LO
;
151 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
]))
154 if (NULL
== pp
->next
) {
155 if ( ! match(pp
->line
, p
, sz
))
157 *rsz
= pp
->line
->outsz
;
158 return(pp
->line
->out
);
161 for (prev
= NULL
; pp
; pp
= pp
->next
) {
162 if ( ! match(pp
->line
, p
, sz
)) {
167 /* Re-order the hash chain. */
170 prev
->next
= pp
->next
;
171 pp
->next
= ((struct linep
**)htab
)[hash
];
175 *rsz
= pp
->line
->outsz
;
176 return(pp
->line
->out
);
184 match(const struct line
*line
, const char *p
, size_t sz
)
187 if (line
->codesz
!= sz
)
189 return(0 == strncmp(line
->code
, p
, sz
));