2 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
3 * at Electronni Visti IA, Kiev, Ukraine.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD: src/lib/libc/locale/collate.c,v 1.35 2005/02/27 20:31:13 ru Exp $");
31 #include "xlocale_private.h"
32 /* assumes the locale_t variable is named loc */
33 #define __collate_chain_equiv_table (loc->__lc_collate->__chain_equiv_table)
34 #define __collate_chain_pri_table (loc->__lc_collate->__chain_pri_table)
35 #define __collate_char_pri_table (loc->__lc_collate->__char_pri_table)
36 #define __collate_info (&loc->__lc_collate->__info)
37 #define __collate_large_char_pri_table (loc->__lc_collate->__large_char_pri_table)
38 #define __collate_substitute_table (loc->__lc_collate->__substitute_table)
40 #include "namespace.h"
41 #include <arpa/inet.h>
51 #include "un-namespace.h"
54 #include "setlocale.h"
57 #include "libc_private.h"
59 #if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
60 static void wntohl(wchar_t *, int);
61 #endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
62 void __collate_err(int ex
, const char *f
) __dead2
;
65 * Normally, the __collate_* routines should all be __private_extern__,
66 * but grep is using them (3715846). Until we can provide an alternative,
67 * we leave them public, and provide a read-only __collate_load_error variable
69 #undef __collate_load_error
70 int __collate_load_error
= 1;
72 __private_extern__
int
73 __collate_load_tables(const char *encoding
, locale_t loc
)
76 int i
, saverr
, chains
, z
;
77 char strbuf
[STR_LEN
], buf
[PATH_MAX
];
78 struct __xlocale_st_collate
*TMP
;
79 static struct __xlocale_st_collate
*cache
= NULL
;
80 struct __collate_st_info info
;
83 /* 'encoding' must be already checked. */
84 if (strcmp(encoding
, "C") == 0 || strcmp(encoding
, "POSIX") == 0) {
85 loc
->__collate_load_error
= 1;
86 if (loc
== &__global_locale
)
87 __collate_load_error
= 1;
88 XL_RELEASE(loc
->__lc_collate
);
89 loc
->__lc_collate
= NULL
;
94 * If the locale name is the same as our cache, use the cache.
96 if (cache
&& strcmp(encoding
, cache
->__encoding
) == 0) {
97 loc
->__collate_load_error
= 0;
98 if (loc
== &__global_locale
)
99 __collate_load_error
= 0;
100 XL_RELEASE(loc
->__lc_collate
);
101 loc
->__lc_collate
= cache
;
102 XL_RETAIN(loc
->__lc_collate
);
107 * Slurp the locale file into the cache.
110 /* 'PathLocale' must be already set & checked. */
111 /* Range checking not needed, encoding has fixed size */
112 (void)strcpy(buf
, _PathLocale
);
113 (void)strcat(buf
, "/");
114 (void)strcat(buf
, encoding
);
115 (void)strcat(buf
, "/LC_COLLATE");
116 if ((fp
= fopen(buf
, "r")) == NULL
)
119 if (fread(strbuf
, sizeof(strbuf
), 1, fp
) != 1) {
126 if (strcmp(strbuf
, COLLATE_VERSION1_1A
) == 0)
134 if (fread(&info
, sizeof(info
), 1, fp
) != 1) {
140 #if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
141 for(z
= 0; z
< info
.directive_count
; z
++) {
142 info
.undef_pri
[z
] = ntohl(info
.undef_pri
[z
]);
143 info
.subst_count
[z
] = ntohl(info
.subst_count
[z
]);
145 info
.chain_count
= ntohl(info
.chain_count
);
146 info
.large_pri_count
= ntohl(info
.large_pri_count
);
147 #endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
148 if ((chains
= info
.chain_count
) < 0) {
156 i
= sizeof(struct __xlocale_st_collate
)
157 + sizeof(struct __collate_st_chain_pri
) * chains
158 + sizeof(struct __collate_st_large_char_pri
) * info
.large_pri_count
;
159 for(z
= 0; z
< info
.directive_count
; z
++)
160 i
+= sizeof(struct __collate_st_subst
) * info
.subst_count
[z
];
161 if ((TMP
= (struct __xlocale_st_collate
*)malloc(i
)) == NULL
) {
167 TMP
->__refcount
= 2; /* one for the locale, one for the cache */
168 TMP
->__free_extra
= NULL
;
170 #define FREAD(a, b, c, d) \
172 if (fread(a, b, c, d) != c) { \
177 return (_LDP_ERROR); \
181 /* adjust size to read the remaining in one chunk */
182 i
-= offsetof(struct __xlocale_st_collate
, __char_pri_table
);
183 FREAD(TMP
->__char_pri_table
, i
, 1, fp
);
186 vp
= (void *)(TMP
+ 1);
188 /* the COLLATE_SUBST_DUP optimization relies on COLL_WEIGHTS_MAX == 2 */
189 if (info
.subst_count
[0] > 0) {
190 TMP
->__substitute_table
[0] = (struct __collate_st_subst
*)vp
;
191 vp
+= info
.subst_count
[0] * sizeof(struct __collate_st_subst
);
193 TMP
->__substitute_table
[0] = NULL
;
194 if (info
.flags
& COLLATE_SUBST_DUP
)
195 TMP
->__substitute_table
[1] = TMP
->__substitute_table
[0];
196 else if (info
.subst_count
[1] > 0) {
197 TMP
->__substitute_table
[1] = (struct __collate_st_subst
*)vp
;
198 vp
+= info
.subst_count
[1] * sizeof(struct __collate_st_subst
);
200 TMP
->__substitute_table
[1] = NULL
;
203 TMP
->__chain_pri_table
= (struct __collate_st_chain_pri
*)vp
;
204 vp
+= chains
* sizeof(struct __collate_st_chain_pri
);
206 TMP
->__chain_pri_table
= NULL
;
207 if (info
.large_pri_count
> 0)
208 TMP
->__large_char_pri_table
= (struct __collate_st_large_char_pri
*)vp
;
210 TMP
->__large_char_pri_table
= NULL
;
212 #if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
214 struct __collate_st_char_pri
*p
= TMP
->__char_pri_table
;
215 for(i
= UCHAR_MAX
+ 1; i
-- > 0; p
++) {
216 for(z
= 0; z
< info
.directive_count
; z
++)
217 p
->pri
[z
] = ntohl(p
->pri
[z
]);
220 for(z
= 0; z
< info
.directive_count
; z
++)
221 if (info
.subst_count
[z
] > 0) {
222 struct __collate_st_subst
*p
= TMP
->__substitute_table
[z
];
223 for(i
= info
.subst_count
[z
]; i
-- > 0; p
++) {
224 p
->val
= ntohl(p
->val
);
225 wntohl(p
->str
, STR_LEN
);
229 struct __collate_st_chain_pri
*p
= TMP
->__chain_pri_table
;
230 for(i
= chains
; i
-- > 0; p
++) {
231 wntohl(p
->str
, STR_LEN
);
232 for(z
= 0; z
< info
.directive_count
; z
++)
233 p
->pri
[z
] = ntohl(p
->pri
[z
]);
236 if (info
.large_pri_count
> 0) {
237 struct __collate_st_large_char_pri
*p
= TMP
->__large_char_pri_table
;
238 for(i
= info
.large_pri_count
; i
-- > 0; p
++) {
239 p
->val
= ntohl(p
->val
);
240 for(z
= 0; z
< info
.directive_count
; z
++)
241 p
->pri
.pri
[z
] = ntohl(p
->pri
.pri
[z
]);
244 #endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
245 (void)strcpy(TMP
->__encoding
, encoding
);
246 (void)memcpy(&TMP
->__info
, &info
, sizeof(info
));
249 XL_RELEASE(loc
->__lc_collate
);
250 loc
->__lc_collate
= cache
;
251 /* no need to retain, since we set __refcount to 2 above */
253 loc
->__collate_substitute_nontrivial
= (info
.subst_count
[0] > 0 || info
.subst_count
[1] > 0);
254 loc
->__collate_load_error
= 0;
255 if (loc
== &__global_locale
)
256 __collate_load_error
= 0;
258 return (_LDP_LOADED
);
262 __collate_wcsnlen(const wchar_t *s
, int len
)
265 while (*s
&& n
< len
) {
272 static struct __collate_st_subst
*
273 substsearch(const wchar_t key
, struct __collate_st_subst
*tab
, int n
)
278 struct __collate_st_subst
*p
;
280 while (low
<= high
) {
281 next
= (low
+ high
) / 2;
283 compar
= key
- p
->val
;
294 __private_extern__
wchar_t *
295 __collate_substitute(const wchar_t *s
, int which
, locale_t loc
)
297 int dest_len
, len
, nlen
;
298 int n
, delta
, nsubst
;
299 wchar_t *dest_str
= NULL
;
301 struct __collate_st_subst
*subst
, *match
;
303 if (s
== NULL
|| *s
== '\0')
304 return (__collate_wcsdup(L
""));
305 dest_len
= wcslen(s
);
306 nsubst
= __collate_info
->subst_count
[which
];
308 return __collate_wcsdup(s
);
309 subst
= __collate_substitute_table
[which
];
310 delta
= dest_len
/ 4;
313 dest_str
= (wchar_t *)malloc((dest_len
+= delta
) * sizeof(wchar_t));
314 if (dest_str
== NULL
)
315 __collate_err(EX_OSERR
, __func__
);
318 if ((match
= substsearch(*s
, subst
, nsubst
)) != NULL
) {
320 n
= __collate_wcsnlen(fp
, STR_LEN
);
326 if (dest_len
<= nlen
) {
327 dest_str
= reallocf(dest_str
, (dest_len
= nlen
+ delta
) * sizeof(wchar_t));
328 if (dest_str
== NULL
)
329 __collate_err(EX_OSERR
, __func__
);
331 wcsncpy(dest_str
+ len
, fp
, n
);
339 static struct __collate_st_chain_pri
*
340 chainsearch(const wchar_t *key
, int *len
, locale_t loc
)
343 int high
= __collate_info
->chain_count
- 1;
345 struct __collate_st_chain_pri
*p
;
346 struct __collate_st_chain_pri
*tab
= __collate_chain_pri_table
;
348 while (low
<= high
) {
349 next
= (low
+ high
) / 2;
351 compar
= *key
- *p
->str
;
353 l
= __collate_wcsnlen(p
->str
, STR_LEN
);
354 compar
= wcsncmp(key
, p
->str
, l
);
368 static struct __collate_st_large_char_pri
*
369 largesearch(const wchar_t key
, locale_t loc
)
372 int high
= __collate_info
->large_pri_count
- 1;
374 struct __collate_st_large_char_pri
*p
;
375 struct __collate_st_large_char_pri
*tab
= __collate_large_char_pri_table
;
377 while (low
<= high
) {
378 next
= (low
+ high
) / 2;
380 compar
= key
- p
->val
;
391 __private_extern__
void
392 __collate_lookup_l(const wchar_t *t
, int *len
, int *prim
, int *sec
, locale_t loc
)
394 struct __collate_st_chain_pri
*p2
;
399 p2
= chainsearch(t
, &l
, loc
);
400 /* use the chain if prim >= 0 */
401 if (p2
&& p2
->pri
[0] >= 0) {
407 if (*t
<= UCHAR_MAX
) {
408 *prim
= __collate_char_pri_table
[*t
].pri
[0];
409 *sec
= __collate_char_pri_table
[*t
].pri
[1];
412 if (__collate_info
->large_pri_count
> 0) {
413 struct __collate_st_large_char_pri
*match
;
414 match
= largesearch(*t
, loc
);
416 *prim
= match
->pri
.pri
[0];
417 *sec
= match
->pri
.pri
[1];
421 *prim
= (l
= __collate_info
->undef_pri
[0]) >= 0 ? l
: *t
- l
;
422 *sec
= (l
= __collate_info
->undef_pri
[1]) >= 0 ? l
: *t
- l
;
426 * This is only provided for programs (like grep) that are calling this
427 * private function. This will go away eventually.
430 __collate_lookup(const unsigned char *t
, int *len
, int *prim
, int *sec
)
432 locale_t loc
= __current_locale();
433 wchar_t *w
= __collate_mbstowcs((const char *)t
, loc
);
436 __collate_lookup_l(w
, len
, prim
, sec
, loc
);
442 __private_extern__
void
443 __collate_lookup_which(const wchar_t *t
, int *len
, int *pri
, int which
, locale_t loc
)
445 struct __collate_st_chain_pri
*p2
;
450 p2
= chainsearch(t
, &l
, loc
);
453 /* use the chain if pri >= 0 */
460 if (*t
<= UCHAR_MAX
) {
461 *pri
= __collate_char_pri_table
[*t
].pri
[which
];
464 if (__collate_info
->large_pri_count
> 0) {
465 struct __collate_st_large_char_pri
*match
;
466 match
= largesearch(*t
, loc
);
468 *pri
= match
->pri
.pri
[which
];
472 *pri
= (l
= __collate_info
->undef_pri
[which
]) >= 0 ? l
: *t
- l
;
475 __private_extern__
wchar_t *
476 __collate_mbstowcs(const char *s
, locale_t loc
)
478 static const mbstate_t initial
;
486 if ((len
= mbsrtowcs_l(NULL
, &ss
, 0, &st
, loc
)) == (size_t)-1)
488 if ((wcs
= (wchar_t *)malloc((len
+ 1) * sizeof(wchar_t))) == NULL
)
489 __collate_err(EX_OSERR
, __func__
);
491 mbsrtowcs_l(wcs
, &s
, len
, &st
, loc
);
497 __private_extern__
wchar_t *
498 __collate_wcsdup(const wchar_t *s
)
500 size_t len
= wcslen(s
) + 1;
503 if ((wcs
= (wchar_t *)malloc(len
* sizeof(wchar_t))) == NULL
)
504 __collate_err(EX_OSERR
, __func__
);
509 __private_extern__
void
510 __collate_xfrm(const wchar_t *src
, wchar_t **xf
, locale_t loc
)
515 wchar_t *tt
= NULL
, *tr
= NULL
;
518 struct __collate_st_info
*info
= __collate_info
;
521 for(pass
= 0; pass
< COLL_WEIGHTS_MAX
; pass
++)
523 for(pass
= 0; pass
< info
->directive_count
; pass
++) {
524 direc
= info
->directive
[pass
];
525 if (pass
== 0 || !(info
->flags
& COLLATE_SUBST_DUP
)) {
529 tt
= __collate_substitute(src
, pass
, loc
);
531 if (direc
& DIRECTIVE_BACKWARD
) {
536 tr
= __collate_wcsdup(tt
? tt
: src
);
538 fp
= tr
+ wcslen(tr
) - 1;
544 t
= (const wchar_t *)tr
;
546 t
= (const wchar_t *)tt
;
548 t
= (const wchar_t *)src
;
550 if ((xf
[pass
] = (wchar_t *)malloc(sizeof(wchar_t) * (wcslen(t
) + 1))) == NULL
) {
557 if (direc
& DIRECTIVE_POSITION
) {
559 __collate_lookup_which(t
, &len
, &pri
, pass
, loc
);
567 pri
= COLLATE_MAX_PRIORITY
;
573 __collate_lookup_which(t
, &len
, &pri
, pass
, loc
);
595 __private_extern__
void
596 __collate_err(int ex
, const char *f
)
602 _write(STDERR_FILENO
, s
, strlen(s
));
603 _write(STDERR_FILENO
, ": ", 2);
605 _write(STDERR_FILENO
, s
, strlen(s
));
606 _write(STDERR_FILENO
, ": ", 2);
607 s
= strerror(serrno
);
608 _write(STDERR_FILENO
, s
, strlen(s
));
609 _write(STDERR_FILENO
, "\n", 1);
614 * __collate_collating_symbol takes the multibyte string specified by
615 * src and slen, and using ps, converts that to a wide character. Then
616 * it is checked to verify it is a collating symbol, and then copies
617 * it to the wide character string specified by dst and dlen (the
618 * results are not null terminated). The length of the wide characters
619 * copied to dst is returned if successful. Zero is returned if no such
620 * collating symbol exists. (size_t)-1 is returned if there are wide-character
621 * conversion errors, if the length of the converted string is greater that
622 * STR_LEN or if dlen is too small. It is up to the calling routine to
623 * preserve the mbstate_t structure as needed.
625 __private_extern__
size_t
626 __collate_collating_symbol(wchar_t *dst
, size_t dlen
, const char *src
, size_t slen
, mbstate_t *ps
, locale_t loc
)
628 wchar_t wname
[STR_LEN
];
633 if (loc
->__collate_load_error
) {
636 if (slen
!= 1 || !isascii(*src
))
641 for(wp
= wname
, len
= 0; slen
> 0; len
++) {
642 l
= mbrtowc_l(&w
, src
, slen
, ps
, loc
);
643 if (l
== (size_t)-1 || l
== (size_t)-2)
651 slen
= (long)slen
- (long)l
;
653 if (len
== 0 || len
> dlen
)
656 if (*wname
<= UCHAR_MAX
) {
657 if (__collate_char_pri_table
[*wname
].pri
[0] >= 0) {
663 } else if (__collate_info
->large_pri_count
> 0) {
664 struct __collate_st_large_char_pri
*match
;
665 match
= largesearch(*wname
, loc
);
666 if (match
&& match
->pri
.pri
[0] >= 0) {
675 if (__collate_info
->chain_count
> 0) {
676 struct __collate_st_chain_pri
*match
;
678 match
= chainsearch(wname
, &ll
, loc
);
682 wcsncpy(dst
, wname
, dlen
);
690 * __collate_equiv_class returns the equivalence class number for the symbol
691 * specified by src and slen, using ps to convert from multi-byte to wide
692 * character. Zero is returned if the symbol is not in an equivalence
693 * class. -1 is returned if there are wide character conversion error,
694 * if there are any greater-than-8-bit characters or if a multi-byte symbol
695 * is greater or equal to STR_LEN in length. It is up to the calling
696 * routine to preserve the mbstate_t structure as needed.
698 __private_extern__
int
699 __collate_equiv_class(const char *src
, size_t slen
, mbstate_t *ps
, locale_t loc
)
701 wchar_t wname
[STR_LEN
];
707 if (loc
->__collate_load_error
)
709 for(wp
= wname
, len
= 0; slen
> 0; len
++) {
710 l
= mbrtowc_l(&w
, src
, slen
, ps
, loc
);
711 if (l
== (size_t)-1 || l
== (size_t)-2)
719 slen
= (long)slen
- (long)l
;
725 if (*wname
<= UCHAR_MAX
)
726 e
= __collate_char_pri_table
[*wname
].pri
[0];
727 else if (__collate_info
->large_pri_count
> 0) {
728 struct __collate_st_large_char_pri
*match
;
729 match
= largesearch(*wname
, loc
);
731 e
= match
->pri
.pri
[0];
734 return IGNORE_EQUIV_CLASS
;
735 return e
> 0 ? e
: 0;
738 if (__collate_info
->chain_count
> 0) {
739 struct __collate_st_chain_pri
*match
;
741 match
= chainsearch(wname
, &ll
, loc
);
745 return IGNORE_EQUIV_CLASS
;
746 return e
< 0 ? -e
: e
;
753 * __collate_equiv_match tries to match any single or multi-character symbol
754 * in equivalence class equiv_class in the multi-byte string specified by src
755 * and slen. If start is non-zero, it is taken to be the first (pre-converted)
756 * wide character. Subsequence wide characters, if needed, will use ps in
757 * the conversion. On a successful match, the length of the matched string
758 * is returned (including the start character). If dst is non-NULL, the
759 * matched wide-character string is copied to dst, a wide character array of
760 * length dlen (the results are not zero-terminated). If rlen is non-NULL,
761 * the number of character in src actually used is returned. Zero is
762 * returned by __collate_equiv_match if there is no match. (size_t)-1 is
763 * returned on error: if there were conversion errors or if dlen is too small
764 * to accept the results. On no match or error, ps is restored to its incoming
768 __collate_equiv_match(int equiv_class
, wchar_t *dst
, size_t dlen
, wchar_t start
, const char *src
, size_t slen
, mbstate_t *ps
, size_t *rlen
, locale_t loc
)
773 wchar_t buf
[STR_LEN
], *wp
;
777 struct __collate_st_chain_pri
*ch
= NULL
;
780 if (loc
->__collate_load_error
)
782 if (equiv_class
== IGNORE_EQUIV_CLASS
)
792 /* convert up to the max chain length */
793 while(sl
> 0 && len
< __collate_info
->chain_max_len
) {
794 l
= mbrtowc_l(&w
, s
, sl
, ps
, loc
);
795 if (l
== (size_t)-1 || l
== (size_t)-2 || l
== 0)
804 if (len
> 1 && (ch
= chainsearch(buf
, &i
, loc
)) != NULL
) {
808 if (e
== equiv_class
)
811 /* try single character */
813 if (*buf
<= UCHAR_MAX
) {
814 if (equiv_class
== __collate_char_pri_table
[*buf
].pri
[0])
816 } else if (__collate_info
->large_pri_count
> 0) {
817 struct __collate_st_large_char_pri
*match
;
818 match
= largesearch(*buf
, loc
);
819 if (match
&& equiv_class
== match
->pri
.pri
[0])
827 /* if we converted more than we used, restore to initial and reconvert
828 * up to what did match */
837 l
= mbrtowc_l(&w
, src
, slen
, ps
, loc
);
849 for(wp
= buf
; len
> 0; len
--)
858 * __collate_equiv_value returns the primary collation value for the given
859 * collating symbol specified by str and len. Zero or negative is return
860 * if the collating symbol was not found. (Use by the bracket code in TRE.)
862 __private_extern__
int
863 __collate_equiv_value(locale_t loc
, const wchar_t *str
, size_t len
)
867 if (len
< 1 || len
>= STR_LEN
)
871 if (loc
->__collate_load_error
)
872 return (len
== 1 && *str
<= UCHAR_MAX
) ? *str
: -1;
876 if (*str
<= UCHAR_MAX
)
877 e
= __collate_char_pri_table
[*str
].pri
[0];
878 else if (__collate_info
->large_pri_count
> 0) {
879 struct __collate_st_large_char_pri
*match
;
880 match
= largesearch(*str
, loc
);
882 e
= match
->pri
.pri
[0];
885 return IGNORE_EQUIV_CLASS
;
886 return e
> 0 ? e
: 0;
888 if (__collate_info
->chain_count
> 0) {
889 wchar_t name
[STR_LEN
];
890 struct __collate_st_chain_pri
*match
;
893 wcsncpy(name
, str
, len
);
895 match
= chainsearch(name
, &ll
, loc
);
899 return IGNORE_EQUIV_CLASS
;
900 return e
< 0 ? -e
: e
;
906 #if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
908 wntohl(wchar_t *str
, int len
)
910 for(; *str
&& len
> 0; str
++, len
--)
913 #endif /* __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN */
921 if (c
>=32 && c
<= 126)
922 sprintf(buf
, "'%c' ", c
);
924 sprintf(buf
, "\\x{%02x}", c
);
929 showwcs(const wchar_t *t
, int len
)
934 for(; *t
&& len
> 0; len
--, t
++) {
935 if (*t
>=32 && *t
<= 126)
938 sprintf(cp
, "\\x{%02x}", *t
);
947 __collate_print_tables()
950 locale_t loc
= __current_locale();
952 printf("Info: p=%d s=%d f=0x%02x m=%d dc=%d up=%d us=%d pc=%d sc=%d cc=%d lc=%d\n",
953 __collate_info
->directive
[0], __collate_info
->directive
[1],
954 __collate_info
->flags
, __collate_info
->chain_max_len
,
955 __collate_info
->directive_count
,
956 __collate_info
->undef_pri
[0], __collate_info
->undef_pri
[1],
957 __collate_info
->subst_count
[0], __collate_info
->subst_count
[1],
958 __collate_info
->chain_count
, __collate_info
->large_pri_count
);
959 for(z
= 0; z
< __collate_info
->directive_count
; z
++) {
960 if (__collate_info
->subst_count
[z
] > 0) {
961 struct __collate_st_subst
*p2
= __collate_substitute_table
[z
];
962 if (z
== 0 && (__collate_info
->flags
& COLLATE_SUBST_DUP
))
963 printf("Both substitute tables:\n");
965 printf("Substitute table %d:\n", z
);
966 for (i
= __collate_info
->subst_count
[z
]; i
-- > 0; p2
++)
967 printf("\t%s --> \"%s\"\n",
969 showwcs(p2
->str
, STR_LEN
));
972 if (__collate_info
->chain_count
> 0) {
973 printf("Chain priority table:\n");
974 struct __collate_st_chain_pri
*p2
= __collate_chain_pri_table
;
975 for (i
= __collate_info
->chain_count
; i
-- > 0; p2
++) {
976 printf("\t\"%s\" :", showwcs(p2
->str
, STR_LEN
));
977 for(z
= 0; z
< __collate_info
->directive_count
; z
++)
978 printf(" %d", p2
->pri
[z
]);
982 printf("Char priority table:\n");
984 struct __collate_st_char_pri
*p2
= __collate_char_pri_table
;
985 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++, p2
++) {
986 printf("\t%s :", show(i
));
987 for(z
= 0; z
< __collate_info
->directive_count
; z
++)
988 printf(" %d", p2
->pri
[z
]);
992 if (__collate_info
->large_pri_count
> 0) {
993 struct __collate_st_large_char_pri
*p2
= __collate_large_char_pri_table
;
994 printf("Large priority table:\n");
995 for (i
= __collate_info
->large_pri_count
; i
-- > 0; p2
++) {
996 printf("\t%s :", show(p2
->val
));
997 for(z
= 0; z
< __collate_info
->directive_count
; z
++)
998 printf(" %d", p2
->pri
.pri
[z
]);