Import mdocml-1.12.1
[dragonfly.git] / contrib / mdocml / chars.c
CommitLineData
36342e81 1/* $Id: chars.c,v 1.52 2011/11/08 00:15:23 kristaps Exp $ */
80387638 2/*
36342e81 3 * Copyright (c) 2009, 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
60e1e752 4 * Copyright (c) 2011 Ingo Schwarze <schwarze@openbsd.org>
80387638
SW
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include <assert.h>
a4c7eb57 23#include <ctype.h>
80387638
SW
24#include <stdlib.h>
25#include <string.h>
26
27#include "mandoc.h"
a4c7eb57 28#include "libmandoc.h"
80387638
SW
29
30#define PRINT_HI 126
31#define PRINT_LO 32
32
33struct ln {
34 struct ln *next;
35 const char *code;
36 const char *ascii;
37 int unicode;
80387638
SW
38};
39
36342e81 40#define LINES_MAX 328
80387638
SW
41
42#define CHAR(in, ch, code) \
a4c7eb57 43 { NULL, (in), (ch), (code) },
80387638
SW
44
45#define CHAR_TBL_START static struct ln lines[LINES_MAX] = {
46#define CHAR_TBL_END };
47
48#include "chars.in"
49
a4c7eb57 50struct mchars {
80387638
SW
51 struct ln **htab;
52};
53
36342e81
SW
54static const struct ln *find(const struct mchars *,
55 const char *, size_t);
80387638
SW
56
57void
a4c7eb57 58mchars_free(struct mchars *arg)
80387638 59{
80387638 60
a4c7eb57
SW
61 free(arg->htab);
62 free(arg);
80387638
SW
63}
64
a4c7eb57
SW
65struct mchars *
66mchars_alloc(void)
80387638 67{
a4c7eb57 68 struct mchars *tab;
80387638
SW
69 struct ln **htab;
70 struct ln *pp;
71 int i, hash;
72
73 /*
74 * Constructs a very basic chaining hashtable. The hash routine
75 * is simply the integral value of the first character.
36342e81 76 * Subsequent entries are chained in the order they're processed.
80387638
SW
77 */
78
a4c7eb57 79 tab = mandoc_malloc(sizeof(struct mchars));
60e1e752 80 htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
80387638
SW
81
82 for (i = 0; i < LINES_MAX; i++) {
83 hash = (int)lines[i].code[0] - PRINT_LO;
84
85 if (NULL == (pp = htab[hash])) {
86 htab[hash] = &lines[i];
87 continue;
88 }
89
90 for ( ; pp->next; pp = pp->next)
91 /* Scan ahead. */ ;
92 pp->next = &lines[i];
93 }
94
95 tab->htab = htab;
80387638
SW
96 return(tab);
97}
98
80387638 99int
36342e81 100mchars_spec2cp(const struct mchars *arg, const char *p, size_t sz)
80387638
SW
101{
102 const struct ln *ln;
103
a4c7eb57 104 ln = find(arg, p, sz);
80387638
SW
105 if (NULL == ln)
106 return(-1);
107 return(ln->unicode);
108}
109
a4c7eb57
SW
110char
111mchars_num2char(const char *p, size_t sz)
60e1e752
SW
112{
113 int i;
60e1e752 114
36342e81 115 if ((i = mandoc_strntoi(p, sz, 10)) < 0)
a4c7eb57 116 return('\0');
36342e81
SW
117 return(i > 0 && i < 256 && isprint(i) ?
118 /* LINTED */ i : '\0');
60e1e752
SW
119}
120
a4c7eb57
SW
121int
122mchars_num2uc(const char *p, size_t sz)
80387638 123{
a4c7eb57 124 int i;
80387638 125
36342e81 126 if ((i = mandoc_strntoi(p, sz, 16)) < 0)
a4c7eb57
SW
127 return('\0');
128 /* FIXME: make sure we're not in a bogus range. */
129 return(i > 0x80 && i <= 0x10FFFF ? i : '\0');
80387638
SW
130}
131
80387638 132const char *
36342e81
SW
133mchars_spec2str(const struct mchars *arg,
134 const char *p, size_t sz, size_t *rsz)
80387638
SW
135{
136 const struct ln *ln;
137
a4c7eb57 138 ln = find(arg, p, sz);
36342e81
SW
139 if (NULL == ln) {
140 *rsz = 1;
80387638 141 return(NULL);
36342e81 142 }
80387638
SW
143
144 *rsz = strlen(ln->ascii);
145 return(ln->ascii);
146}
147
80387638 148static const struct ln *
36342e81 149find(const struct mchars *tab, const char *p, size_t sz)
80387638 150{
36342e81 151 const struct ln *pp;
80387638
SW
152 int hash;
153
154 assert(p);
80387638 155
36342e81 156 if (0 == sz || p[0] < PRINT_LO || p[0] > PRINT_HI)
80387638
SW
157 return(NULL);
158
80387638 159 hash = (int)p[0] - PRINT_LO;
80387638 160
36342e81
SW
161 for (pp = tab->htab[hash]; pp; pp = pp->next)
162 if (0 == strncmp(pp->code, p, sz) &&
163 '\0' == pp->code[(int)sz])
164 return(pp);
80387638
SW
165
166 return(NULL);
167}