1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
14 * Copyright 2013 David Hoeppner. All rights reserved.
15 */
16
17 /*
18 * Character map handling for iconv.
19 */
20
21 #include <sys/avl.h>
22
23 #include <stddef.h>
24
25 #include "iconv.h"
26 #include "parser.tab.h"
27
28 /*
29 * AVL trees for the from and to charmaps.
30 */
31 static avl_tree_t from_cmap_sym;
32 static avl_tree_t from_cmap_wc;
33 static avl_tree_t to_cmap_sym;
34 static avl_tree_t to_cmap_wc;
35
36 static avl_tree_t *current_cmap_sym = &from_cmap_sym;
37 static avl_tree_t *current_cmap_wc = &from_cmap_wc;
38
39 typedef struct charmap {
40 const char *name;
41 wchar_t wc;
42 avl_node_t avl_sym;
43 avl_node_t avl_wc;
44 } charmap_t;
45
46 static int
47 cmap_compare_sym(const void *n1, const void *n2)
48 {
49 const charmap_t *c1 = n1;
50 const charmap_t *c2 = n2;
51 int rv;
52
53 rv = strcmp(c1->name, c2->name);
54 return ((rv < 0) ? -1 : (rv > 0) ? 1 : 0);
55 }
56
57 static int
58 cmap_compare_wc(const void *n1, const void *n2)
59 {
60 const charmap_t *c1 = n1;
61 const charmap_t *c2 = n2;
62
63 return ((c1->wc < c2->wc) ? -1 : (c1->wc > c2->wc) ? 1 : 0);
64 }
65
66 void
67 init_charmap(void)
68 {
69 avl_create(&from_cmap_sym, cmap_compare_sym, sizeof (charmap_t),
70 offsetof(charmap_t, avl_sym));
71
72 avl_create(&from_cmap_wc, cmap_compare_wc, sizeof (charmap_t),
73 offsetof(charmap_t, avl_wc));
74
75 avl_create(&to_cmap_sym, cmap_compare_sym, sizeof (charmap_t),
76 offsetof(charmap_t, avl_sym));
77
78 avl_create(&to_cmap_wc, cmap_compare_wc, sizeof (charmap_t),
79 offsetof(charmap_t, avl_wc));
80 }
81
82 /*
83 * Switches from fromcharmap to tocharmap.
84 */
85 void
86 switch_charmap(void)
87 {
88 current_cmap_sym = &to_cmap_sym;
89 current_cmap_wc = &to_cmap_wc;
90 }
91
92 static void
93 add_charmap_impl(char *sym, wchar_t wc, int nodups)
94 {
95 charmap_t srch;
96 charmap_t *n = NULL;
97 avl_index_t where;
98
99 srch.wc = wc;
100 srch.name = sym;
101
102 /*
103 * Also possibly insert the wide mapping, although note that there
104 * can only be one of these per wide character code.
105 */
106 if ((wc != -1) && ((avl_find(current_cmap_wc, &srch, &where)) == NULL)) {
107 if ((n = calloc(1, sizeof (*n))) == NULL) {
108 errf(_("out of memory"));
109 return;
110 }
111
112 n->wc = wc;
113 avl_insert(current_cmap_wc, n, where);
114 }
115
116 if (sym != NULL) {
117 if (avl_find(current_cmap_sym, &srch, &where) != NULL) {
118 if (nodups == 1) {
119 errf(_("duplicate character definition"));
120 }
121
122 return;
123 }
124
125 if ((n == NULL) && ((n = calloc(1, sizeof (*n))) == NULL)) {
126 errf(_("out of memory"));
127 return;
128 }
129
130 n->wc = wc;
131 n->name = sym;
132 printf("ADDING %s\n", sym);
133 avl_insert(current_cmap_sym, n, where);
134 }
135 }
136
137 void
138 add_charmap(char *sym, int c)
139 {
140 add_charmap_impl(sym, c, 1);
141 }
142
143 void
144 add_charmap_range(char *s, char *e, int wc)
145 {
146
147 }