]>
git.cameronkatri.com Git - mandoc.git/blob - ascii.c
1 /* $Id: ascii.c,v 1.9 2009/07/27 12:02:49 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
33 #define ASCII_CHAR (1 << 0)
34 #define ASCII_STRING (1 << 1)
35 #define ASCII_BOTH (0x03)
39 const struct line
*line
;
43 #define CHAR(w, x, y, z) \
44 { (w), (y), (x), (z), ASCII_CHAR },
45 #define STRING(w, x, y, z) \
46 { (w), (y), (x), (z), ASCII_STRING },
47 #define BOTH(w, x, y, z) \
48 { (w), (y), (x), (z), ASCII_BOTH },
49 static const struct line lines
[] = {
59 static inline int match(const struct line
*,
60 const char *, size_t, int);
61 static const char * lookup(struct asciitab
*, const char *,
62 size_t, size_t *, int);
66 term_asciifree(void *arg
)
70 tab
= (struct asciitab
*)arg
;
87 * Constructs a very basic chaining hashtable. The hash routine
88 * is simply the integral value of the first character.
89 * Subsequent entries are chained in the order they're processed
90 * (they're in-line re-ordered during lookup).
93 if (NULL
== (tab
= malloc(sizeof(struct asciitab
))))
96 len
= sizeof(lines
) / sizeof(struct line
);
98 if (NULL
== (p
= calloc((size_t)len
, sizeof(struct linep
))))
101 htab
= calloc(ASCII_PRINT_HI
- ASCII_PRINT_LO
+ 1,
102 sizeof(struct linep
**));
107 for (i
= 0; i
< len
; i
++) {
108 assert(lines
[i
].codesz
> 0);
109 assert(lines
[i
].code
);
110 assert(lines
[i
].out
);
112 p
[i
].line
= &lines
[i
];
114 hash
= (int)lines
[i
].code
[0] - ASCII_PRINT_LO
;
116 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
])) {
121 for ( ; pp
->next
; pp
= pp
->next
)
135 term_a2ascii(void *arg
, const char *p
, size_t sz
, size_t *rsz
)
138 return(lookup((struct asciitab
*)arg
, p
,
139 sz
, rsz
, ASCII_CHAR
));
144 term_a2res(void *arg
, const char *p
, size_t sz
, size_t *rsz
)
147 return(lookup((struct asciitab
*)arg
, p
,
148 sz
, rsz
, ASCII_STRING
));
153 lookup(struct asciitab
*tab
, const char *p
,
154 size_t sz
, size_t *rsz
, int type
)
156 struct linep
*pp
, *prev
;
163 if (p
[0] < ASCII_PRINT_LO
|| p
[0] > ASCII_PRINT_HI
)
168 * Lookup the symbol in the symbol hash. See ascii2htab for the
169 * hashtable specs. This dynamically re-orders the hash chain
170 * to optimise for repeat hits.
173 hash
= (int)p
[0] - ASCII_PRINT_LO
;
176 if (NULL
== (pp
= ((struct linep
**)htab
)[hash
]))
179 if (NULL
== pp
->next
) {
180 if ( ! match(pp
->line
, p
, sz
, type
))
182 *rsz
= pp
->line
->outsz
;
183 return(pp
->line
->out
);
186 for (prev
= NULL
; pp
; pp
= pp
->next
) {
187 if ( ! match(pp
->line
, p
, sz
, type
)) {
192 /* Re-order the hash chain. */
195 prev
->next
= pp
->next
;
196 pp
->next
= ((struct linep
**)htab
)[hash
];
200 *rsz
= pp
->line
->outsz
;
201 return(pp
->line
->out
);
209 match(const struct line
*line
, const char *p
, size_t sz
, int type
)
212 if ( ! (line
->type
& type
))
214 if (line
->codesz
!= sz
)
216 return(0 == strncmp(line
->code
, p
, sz
));