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 "namespace.h"
33 /* until we have arpa/inet.h in libc */
34 #include <exec/types.h>
35 #include <aros/macros.h>
36 #define ntohl(x) AROS_BE2LONG(x)
38 #include <arpa/inet.h>
46 #include "un-namespace.h"
49 #include "setlocale.h"
52 #include "libc_private.h"
54 int __collate_load_error
= 1;
55 int __collate_substitute_nontrivial
;
57 u_char __collate_substitute_table
[UCHAR_MAX
+ 1][STR_LEN
];
58 struct __collate_st_char_pri __collate_char_pri_table
[UCHAR_MAX
+ 1];
59 struct __collate_st_chain_pri
*__collate_chain_pri_table
;
61 void __collate_err(int ex
, const char *f
) __dead2
;
64 __collate_load_tables(const char *encoding
)
67 int i
, saverr
, chains
;
69 char strbuf
[STR_LEN
], buf
[PATH_MAX
];
70 void *TMP_substitute_table
, *TMP_char_pri_table
, *TMP_chain_pri_table
;
71 static char collate_encoding
[ENCODING_LEN
+ 1];
73 /* 'encoding' must be already checked. */
74 if (strcmp(encoding
, "C") == 0 || strcmp(encoding
, "POSIX") == 0) {
75 __collate_load_error
= 1;
80 * If the locale name is the same as our cache, use the cache.
82 if (strcmp(encoding
, collate_encoding
) == 0) {
83 __collate_load_error
= 0;
88 * Slurp the locale file into the cache.
91 /* 'PathLocale' must be already set & checked. */
92 /* Range checking not needed, encoding has fixed size */
93 (void)strcpy(buf
, _PathLocale
);
94 (void)strcat(buf
, "/");
95 (void)strcat(buf
, encoding
);
96 (void)strcat(buf
, "/LC_COLLATE");
97 if ((fp
= fopen(buf
, "r")) == NULL
)
100 if (fread(strbuf
, sizeof(strbuf
), 1, fp
) != 1) {
107 if (strcmp(strbuf
, COLLATE_VERSION
) == 0)
109 else if (strcmp(strbuf
, COLLATE_VERSION1_2
) == 0)
117 if (fread(&u32
, sizeof(u32
), 1, fp
) != 1) {
123 if ((chains
= (int)ntohl(u32
)) < 1) {
131 if ((TMP_substitute_table
=
132 malloc(sizeof(__collate_substitute_table
))) == NULL
) {
138 if ((TMP_char_pri_table
=
139 malloc(sizeof(__collate_char_pri_table
))) == NULL
) {
141 free(TMP_substitute_table
);
146 if ((TMP_chain_pri_table
=
147 malloc(sizeof(*__collate_chain_pri_table
) * chains
)) == NULL
) {
149 free(TMP_substitute_table
);
150 free(TMP_char_pri_table
);
156 #define FREAD(a, b, c, d) \
158 if (fread(a, b, c, d) != c) { \
160 free(TMP_substitute_table); \
161 free(TMP_char_pri_table); \
162 free(TMP_chain_pri_table); \
165 return (_LDP_ERROR); \
169 FREAD(TMP_substitute_table
, sizeof(__collate_substitute_table
), 1, fp
);
170 FREAD(TMP_char_pri_table
, sizeof(__collate_char_pri_table
), 1, fp
);
171 FREAD(TMP_chain_pri_table
,
172 sizeof(*__collate_chain_pri_table
), chains
, fp
);
175 (void)strcpy(collate_encoding
, encoding
);
176 if (__collate_substitute_table_ptr
!= NULL
)
177 free(__collate_substitute_table_ptr
);
178 __collate_substitute_table_ptr
= TMP_substitute_table
;
179 if (__collate_char_pri_table_ptr
!= NULL
)
180 free(__collate_char_pri_table_ptr
);
181 __collate_char_pri_table_ptr
= TMP_char_pri_table
;
182 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++) {
183 __collate_char_pri_table
[i
].prim
=
184 ntohl(__collate_char_pri_table
[i
].prim
);
185 __collate_char_pri_table
[i
].sec
=
186 ntohl(__collate_char_pri_table
[i
].sec
);
188 if (__collate_chain_pri_table
!= NULL
)
189 free(__collate_chain_pri_table
);
190 __collate_chain_pri_table
= TMP_chain_pri_table
;
191 for (i
= 0; i
< chains
; i
++) {
192 __collate_chain_pri_table
[i
].prim
=
193 ntohl(__collate_chain_pri_table
[i
].prim
);
194 __collate_chain_pri_table
[i
].sec
=
195 ntohl(__collate_chain_pri_table
[i
].sec
);
197 __collate_substitute_nontrivial
= 0;
198 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++) {
199 if (__collate_substitute_table
[i
][0] != i
||
200 __collate_substitute_table
[i
][1] != 0) {
201 __collate_substitute_nontrivial
= 1;
205 __collate_load_error
= 0;
207 return (_LDP_LOADED
);
211 __collate_substitute(const u_char
*s
)
213 int dest_len
, len
, nlen
;
214 int delta
= strlen(s
);
215 u_char
*dest_str
= NULL
;
217 if (s
== NULL
|| *s
== '\0')
218 return (__collate_strdup(""));
220 dest_str
= malloc(dest_len
= delta
);
221 if (dest_str
== NULL
)
222 __collate_err(EX_OSERR
, __func__
);
225 nlen
= len
+ strlen(__collate_substitute_table
[*s
]);
226 if (dest_len
<= nlen
) {
227 dest_str
= reallocf(dest_str
, dest_len
= nlen
+ delta
);
228 if (dest_str
== NULL
)
229 __collate_err(EX_OSERR
, __func__
);
231 (void)strcpy(dest_str
+ len
, __collate_substitute_table
[*s
++]);
238 __collate_lookup(const u_char
*t
, int *len
, int *prim
, int *sec
)
240 struct __collate_st_chain_pri
*p2
;
244 for (p2
= __collate_chain_pri_table
; p2
->str
[0] != '\0'; p2
++) {
245 if (*t
== p2
->str
[0] &&
246 strncmp(t
, p2
->str
, strlen(p2
->str
)) == 0) {
247 *len
= strlen(p2
->str
);
253 *prim
= __collate_char_pri_table
[*t
].prim
;
254 *sec
= __collate_char_pri_table
[*t
].sec
;
258 __collate_strdup(u_char
*s
)
260 u_char
*t
= strdup(s
);
263 __collate_err(EX_OSERR
, __func__
);
268 __collate_err(int ex
, const char *f
)
273 #ifndef __AROS__ /* fix this some day */
275 _write(STDERR_FILENO
, s
, strlen(s
));
277 _write(STDERR_FILENO
, ": ", 2);
279 _write(STDERR_FILENO
, s
, strlen(s
));
280 _write(STDERR_FILENO
, ": ", 2);
281 s
= strerror(serrno
);
282 _write(STDERR_FILENO
, s
, strlen(s
));
283 _write(STDERR_FILENO
, "\n", 1);
289 __collate_print_tables()
292 struct __collate_st_chain_pri
*p2
;
294 printf("Substitute table:\n");
295 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++)
296 if (i
!= *__collate_substitute_table
[i
])
297 printf("\t'%c' --> \"%s\"\n", i
,
298 __collate_substitute_table
[i
]);
299 printf("Chain priority table:\n");
300 for (p2
= __collate_chain_pri_table
; p2
->str
[0] != '\0'; p2
++)
301 printf("\t\"%s\" : %d %d\n", p2
->str
, p2
->prim
, p2
->sec
);
302 printf("Char priority table:\n");
303 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++)
304 printf("\t'%c' : %d %d\n", i
, __collate_char_pri_table
[i
].prim
,
305 __collate_char_pri_table
[i
].sec
);