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
27 * $FreeBSD: src/lib/libc/locale/collate.c,v 1.21.2.4 2002/10/11 10:36:47 ache Exp $
28 * $DragonFly: src/lib/libc/locale/collate.c,v 1.7 2005/11/13 01:20:49 swildner Exp $
31 #include "namespace.h"
32 #include <arpa/inet.h>
40 #include "un-namespace.h"
44 #define ENCODING_LEN 31
46 #define _LDP_ERROR (-1)
49 int __collate_load_error
= 1;
50 int __collate_substitute_nontrivial
;
52 u_char __collate_substitute_table
[UCHAR_MAX
+ 1][STR_LEN
];
53 struct __collate_st_char_pri __collate_char_pri_table
[UCHAR_MAX
+ 1];
54 struct __collate_st_chain_pri
*__collate_chain_pri_table
;
56 void __collate_err(int ex
, const char *f
) __dead2
;
59 __collate_load_tables(const char *encoding
)
62 int i
, saverr
, chains
;
64 char strbuf
[STR_LEN
], buf
[PATH_MAX
];
65 void *TMP_substitute_table
, *TMP_char_pri_table
, *TMP_chain_pri_table
;
66 static char collate_encoding
[ENCODING_LEN
+ 1];
68 /* 'encoding' must be already checked. */
69 if (strcmp(encoding
, "C") == 0 || strcmp(encoding
, "POSIX") == 0) {
70 __collate_load_error
= 1;
75 * If the locale name is the same as our cache, use the cache.
77 if (strcmp(encoding
, collate_encoding
) == 0) {
78 __collate_load_error
= 0;
83 * Slurp the locale file into the cache.
86 /* 'PathLocale' must be already set & checked. */
87 /* Range checking not needed, encoding has fixed size */
88 strcpy(buf
, _PathLocale
);
90 strcat(buf
, encoding
);
91 strcat(buf
, "/LC_COLLATE");
92 if ((fp
= fopen(buf
, "r")) == NULL
)
95 if (fread(strbuf
, sizeof(strbuf
), 1, fp
) != 1) {
102 if (strcmp(strbuf
, COLLATE_VERSION
) == 0)
104 else if (strcmp(strbuf
, COLLATE_VERSION1_1
) == 0)
112 if (fread(&u32
, sizeof(u32
), 1, fp
) != 1) {
118 if ((chains
= (int)ntohl(u32
)) < 1) {
126 if ((TMP_substitute_table
=
127 malloc(sizeof(__collate_substitute_table
))) == NULL
) {
133 if ((TMP_char_pri_table
=
134 malloc(sizeof(__collate_char_pri_table
))) == NULL
) {
136 free(TMP_substitute_table
);
141 if ((TMP_chain_pri_table
=
142 malloc(sizeof(*__collate_chain_pri_table
) * chains
)) == NULL
) {
144 free(TMP_substitute_table
);
145 free(TMP_char_pri_table
);
151 #define FREAD(a, b, c, d) \
153 if ( fread(a, b, c, d) != c) { \
155 free(TMP_substitute_table); \
156 free(TMP_char_pri_table); \
157 free(TMP_chain_pri_table); \
160 return (_LDP_ERROR); \
164 FREAD(TMP_substitute_table
, sizeof(__collate_substitute_table
), 1, fp
);
165 FREAD(TMP_char_pri_table
, sizeof(__collate_char_pri_table
), 1, fp
);
166 FREAD(TMP_chain_pri_table
,
167 sizeof(*__collate_chain_pri_table
), chains
, fp
);
170 strcpy(collate_encoding
, encoding
);
171 if (__collate_substitute_table_ptr
!= NULL
)
172 free(__collate_substitute_table_ptr
);
173 __collate_substitute_table_ptr
= TMP_substitute_table
;
174 if (__collate_char_pri_table_ptr
!= NULL
)
175 free(__collate_char_pri_table_ptr
);
176 __collate_char_pri_table_ptr
= TMP_char_pri_table
;
177 if (__collate_chain_pri_table
!= NULL
)
178 free(__collate_chain_pri_table
);
179 __collate_chain_pri_table
= TMP_chain_pri_table
;
181 __collate_substitute_nontrivial
= 0;
182 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++) {
183 if (__collate_substitute_table
[i
][0] != i
||
184 __collate_substitute_table
[i
][1] != 0) {
185 __collate_substitute_nontrivial
= 1;
189 __collate_load_error
= 0;
191 return (_LDP_LOADED
);
195 __collate_substitute(const u_char
*s
)
197 int dest_len
, len
, nlen
;
198 int delta
= strlen(s
);
199 u_char
*dest_str
= NULL
;
201 if (s
== NULL
|| *s
== '\0')
202 return (__collate_strdup(""));
204 dest_str
= malloc(dest_len
= delta
);
205 if (dest_str
== NULL
)
206 __collate_err(EX_OSERR
, __func__
);
209 nlen
= len
+ strlen(__collate_substitute_table
[*s
]);
210 if (dest_len
<= nlen
) {
211 dest_str
= reallocf(dest_str
, dest_len
= nlen
+ delta
);
212 if (dest_str
== NULL
)
213 __collate_err(EX_OSERR
, __func__
);
215 strcpy(dest_str
+ len
, __collate_substitute_table
[*s
++]);
222 __collate_lookup(const u_char
*t
, int *len
, int *prim
, int *sec
)
224 struct __collate_st_chain_pri
*p2
;
228 for (p2
= __collate_chain_pri_table
; p2
->str
[0] != '\0'; p2
++) {
229 if (*t
== p2
->str
[0] &&
230 strncmp(t
, p2
->str
, strlen(p2
->str
)) == 0) {
231 *len
= strlen(p2
->str
);
237 *prim
= __collate_char_pri_table
[*t
].prim
;
238 *sec
= __collate_char_pri_table
[*t
].sec
;
242 __collate_strdup(u_char
*s
)
244 u_char
*t
= strdup(s
);
247 __collate_err(EX_OSERR
, __func__
);
252 __collate_err(int ex
, const char *f
)
254 const char *progname
;
257 progname
= _getprogname();
258 _write(STDERR_FILENO
, progname
, strlen(progname
));
259 _write(STDERR_FILENO
, ": ", 2);
260 _write(STDERR_FILENO
, f
, strlen(f
));
261 _write(STDERR_FILENO
, ": ", 2);
262 f
= strerror(serrno
);
263 _write(STDERR_FILENO
, f
, strlen(f
));
264 _write(STDERR_FILENO
, "\n", 1);
270 __collate_print_tables(void)
273 struct __collate_st_chain_pri
*p2
;
275 printf("Substitute table:\n");
276 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++)
277 if (i
!= *__collate_substitute_table
[i
])
278 printf("\t'%c' --> \"%s\"\n", i
,
279 __collate_substitute_table
[i
]);
280 printf("Chain priority table:\n");
281 for (p2
= __collate_chain_pri_table
; p2
->str
[0] != '\0'; p2
++)
282 printf("\t\"%s\" : %d %d\n", p2
->str
, p2
->prim
, p2
->sec
);
283 printf("Char priority table:\n");
284 for (i
= 0; i
< UCHAR_MAX
+ 1; i
++)
285 printf("\t'%c' : %d %d\n", i
, __collate_char_pri_table
[i
].prim
,
286 __collate_char_pri_table
[i
].sec
);