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
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.
13 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
17 * CHARMAP file handling for localedef.
29 #include "localedef.h"
30 #include "parser.tab.h"
32 static avl_tree_t cmap_sym
;
33 static avl_tree_t cmap_wc
;
35 typedef struct charmap
{
43 * Array of POSIX specific portable characters.
48 } portable_chars
[] = {
51 { "backspace", '\b' },
53 { "carriage-return", '\r' },
55 { "vertical-tab", '\v' },
56 { "form-feed", '\f' },
58 { "exclamation-mark", '!' },
59 { "quotation-mark", '"' },
60 { "number-sign", '#' },
61 { "dollar-sign", '$' },
62 { "percent-sign", '%' },
64 { "apostrophe", '\'' },
65 { "left-parenthesis", '(' },
66 { "right-parenthesis", '(' },
70 { "hyphen-minus", '-' },
88 { "less-than-sign", '<' },
89 { "equals-sign", '=' },
90 { "greater-than-sign", '>' },
91 { "question-mark", '?' },
92 { "commercial-at", '@' },
93 { "left-square-bracket", '[' },
94 { "backslash", '\\' },
95 { "reverse-solidus", '\\' },
96 { "right-square-bracket", ']' },
97 { "circumflex", '^' },
98 { "circumflex-accent", '^' },
100 { "underscore", '_' },
101 { "grave-accent", '`' },
102 { "left-brace", '{' },
103 { "left-curly-bracket", '{' },
104 { "vertical-line", '|' },
105 { "right-brace", '}' },
106 { "right-curly-bracket", '}' },
164 cmap_compare_sym(const void *n1
, const void *n2
)
166 const charmap_t
*c1
= n1
;
167 const charmap_t
*c2
= n2
;
170 rv
= strcmp(c1
->name
, c2
->name
);
171 return ((rv
< 0) ? -1 : (rv
> 0) ? 1 : 0);
175 cmap_compare_wc(const void *n1
, const void *n2
)
177 const charmap_t
*c1
= n1
;
178 const charmap_t
*c2
= n2
;
180 return ((c1
->wc
< c2
->wc
) ? -1 : (c1
->wc
> c2
->wc
) ? 1 : 0);
186 avl_create(&cmap_sym
, cmap_compare_sym
, sizeof (charmap_t
),
187 offsetof(charmap_t
, avl_sym
));
189 avl_create(&cmap_wc
, cmap_compare_wc
, sizeof (charmap_t
),
190 offsetof(charmap_t
, avl_wc
));
194 add_charmap_impl(const char *sym
, wchar_t wc
, int nodups
)
204 * also possibly insert the wide mapping, although note that there
205 * can only be one of these per wide character code.
207 if ((wc
!= (wchar_t)-1) &&
208 ((avl_find(&cmap_wc
, &srch
, &where
)) == NULL
)) {
209 if ((n
= calloc(1, sizeof (*n
))) == NULL
) {
210 errf(_("out of memory"));
214 avl_insert(&cmap_wc
, n
, where
);
218 if (avl_find(&cmap_sym
, &srch
, &where
) != NULL
) {
220 errf(_("duplicate character definition"));
224 if ((n
== NULL
) && ((n
= calloc(1, sizeof (*n
))) == NULL
)) {
225 errf(_("out of memory"));
231 avl_insert(&cmap_sym
, n
, where
);
236 add_charmap(const char *sym
, int c
)
238 add_charmap_impl(sym
, c
, 1);
242 add_charmap_undefined(char *sym
)
245 charmap_t
*cm
= NULL
;
248 cm
= avl_find(&cmap_sym
, &srch
, NULL
);
250 if ((undefok
== 0) && ((cm
== NULL
) || (cm
->wc
== (wchar_t)-1))) {
251 warn(_("undefined symbol <%s>"), sym
);
252 add_charmap_impl(sym
, -1, 0);
259 add_charmap_range(char *s
, char *e
, int wc
)
266 static const char *digits
= "0123456789";
271 if (((si
= strcspn(s
, digits
)) == 0) || (si
== ls
) ||
272 (strncmp(s
, e
, si
) != 0) ||
273 (strspn(s
+ si
, digits
) != (ls
- si
)) ||
274 (strspn(e
+ si
, digits
) != (le
- si
)) ||
275 ((sn
= atoi(s
+ si
)) > ((en
= atoi(e
+ si
))))) {
276 errf(_("malformed charmap range"));
282 for (i
= sn
; i
<= en
; i
++) {
284 (void) asprintf(&nn
, "%s%0*u", s
, ls
- si
, i
);
286 errf(_("out of memory"));
290 add_charmap_impl(nn
, wc
, 1);
298 add_charmap_char(const char *name
, int val
)
300 add_charmap_impl(name
, val
, 0);
304 * POSIX insists that certain entries be present, even when not in the
305 * original charmap file.
308 add_charmap_posix(void)
312 for (i
= 0; portable_chars
[i
].name
; i
++) {
313 add_charmap_char(portable_chars
[i
].name
, portable_chars
[i
].ch
);
318 lookup_charmap(const char *sym
, wchar_t *wc
)
324 n
= avl_find(&cmap_sym
, &srch
, NULL
);
325 if (n
&& n
->wc
!= (wchar_t)-1) {
334 check_charmap(wchar_t wc
)
339 return (avl_find(&cmap_wc
, &srch
, NULL
) ? 0 : -1);