Deleted Added
full compact
collate.c (101478) collate.c (101498)
1/*-
2 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
3 * at Electronni Visti IA, Kiev, Ukraine.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
3 * at Electronni Visti IA, Kiev, Ukraine.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
14 *
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
25 * SUCH DAMAGE.
26 */
27
28#include <sys/cdefs.h>
29__FBSDID("$FreeBSD: head/lib/libc/locale/collate.c 101478 2002-08-07 18:02:45Z ache $");
29__FBSDID("$FreeBSD: head/lib/libc/locale/collate.c 101498 2002-08-08 05:51:54Z ache $");
30
31#include "namespace.h"
32#include <rune.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37#include <unistd.h>
38#include <sysexits.h>
39#include "un-namespace.h"
40
41#include "collate.h"
42#include "setlocale.h"
30
31#include "namespace.h"
32#include <rune.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37#include <unistd.h>
38#include <sysexits.h>
39#include "un-namespace.h"
40
41#include "collate.h"
42#include "setlocale.h"
43#include "ldpart.h"
43
44#include "libc_private.h"
45
46int __collate_load_error = 1;
47int __collate_substitute_nontrivial;
44
45#include "libc_private.h"
46
47int __collate_load_error = 1;
48int __collate_substitute_nontrivial;
48char __collate_version[STR_LEN];
49
49u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
50struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
51struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
52
50u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN];
51struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1];
52struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE];
53
53#define FREAD(a, b, c, d) \
54 do { \
55 if (fread(a, b, c, d) != c) { \
56 (void)fclose(d); \
57 return -1; \
58 } \
59 } while(0)
60
61void __collate_err(int ex, const char *f) __dead2;
62
63int
54void __collate_err(int ex, const char *f) __dead2;
55
56int
64__collate_load_tables(encoding)
65 char *encoding;
57__collate_load_tables(const char *encoding)
66{
58{
67 char buf[PATH_MAX];
68 FILE *fp;
59 FILE *fp;
69 int i, save_load_error;
60 int i, saverr;
61 char collate_version[STR_LEN];
62 char buf[PATH_MAX];
63 char *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table;
64 static char collate_encoding[ENCODING_LEN + 1];
70
65
71 save_load_error = __collate_load_error;
72 __collate_load_error = 1;
73 if (!encoding) {
74 __collate_load_error = save_load_error;
75 return -1;
66 /* 'encoding' must be already checked. */
67 if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
68 __collate_load_error = 1;
69 return (_LDP_CACHE);
76 }
70 }
77 if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX"))
78 return 0;
79 if (!_PathLocale) {
80 __collate_load_error = save_load_error;
81 return -1;
71
72 /*
73 * If the locale name is the same as our cache, use the cache.
74 */
75 if (strcmp(encoding, collate_encoding) == 0) {
76 __collate_load_error = 0;
77 return (_LDP_CACHE);
82 }
78 }
79
80 /*
81 * Slurp the locale file into the cache.
82 */
83
84 /* 'PathLocale' must be already set & checked. */
83 /* Range checking not needed, encoding has fixed size */
84 (void)strcpy(buf, _PathLocale);
85 (void)strcat(buf, "/");
86 (void)strcat(buf, encoding);
87 (void)strcat(buf, "/LC_COLLATE");
85 /* Range checking not needed, encoding has fixed size */
86 (void)strcpy(buf, _PathLocale);
87 (void)strcat(buf, "/");
88 (void)strcat(buf, encoding);
89 (void)strcat(buf, "/LC_COLLATE");
88 if ((fp = fopen(buf, "r")) == NULL) {
89 __collate_load_error = save_load_error;
90 return -1;
90 if ((fp = fopen(buf, "r")) == NULL)
91 return (_LDP_ERROR);
92
93 if ((TMP_substitute_table =
94 malloc(sizeof(__collate_substitute_table))) == NULL) {
95 (void)fclose(fp);
96 errno = ENOMEM;
97 return (_LDP_ERROR);
91 }
98 }
92 FREAD(__collate_version, sizeof(__collate_version), 1, fp);
93 if (strcmp(__collate_version, COLLATE_VERSION) != 0) {
99 if ((TMP_char_pri_table =
100 malloc(sizeof(__collate_char_pri_table))) == NULL) {
101 free(TMP_substitute_table);
94 (void)fclose(fp);
102 (void)fclose(fp);
95 return -1;
103 errno = ENOMEM;
104 return (_LDP_ERROR);
96 }
105 }
97 FREAD(__collate_substitute_table, sizeof(__collate_substitute_table),
98 1, fp);
99 FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1,
100 fp);
101 FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1,
102 fp);
106 if ((TMP_chain_pri_table =
107 malloc(sizeof(__collate_chain_pri_table))) == NULL) {
108 free(TMP_substitute_table);
109 free(TMP_char_pri_table);
110 (void)fclose(fp);
111 errno = ENOMEM;
112 return (_LDP_ERROR);
113 }
114
115#define FREAD(a, b, c, d) \
116{ \
117 if (fread(a, b, c, d) != c) { \
118 saverr = errno; \
119 free(TMP_substitute_table); \
120 free(TMP_char_pri_table); \
121 free(TMP_chain_pri_table); \
122 (void)fclose(d); \
123 errno = saverr; \
124 return (_LDP_ERROR); \
125 } \
126}
127
128 FREAD(collate_version, sizeof(collate_version), 1, fp);
129 if (strcmp(collate_version, COLLATE_VERSION) != 0) {
130 free(TMP_substitute_table);
131 free(TMP_char_pri_table);
132 free(TMP_chain_pri_table);
133 (void)fclose(fp);
134 errno = EFTYPE;
135 return (_LDP_ERROR);
136 }
137 FREAD(TMP_substitute_table, sizeof(__collate_substitute_table), 1, fp);
138 FREAD(TMP_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
139 FREAD(TMP_chain_pri_table, sizeof(__collate_chain_pri_table), 1, fp);
103 (void)fclose(fp);
140 (void)fclose(fp);
104 __collate_load_error = 0;
141
142 (void)strcpy(collate_encoding, encoding);
143 (void)memcpy(__collate_substitute_table, TMP_substitute_table,
144 sizeof(__collate_substitute_table));
145 (void)memcpy(__collate_char_pri_table, TMP_char_pri_table,
146 sizeof(__collate_char_pri_table));
147 (void)memcpy(__collate_chain_pri_table, TMP_chain_pri_table,
148 sizeof(__collate_chain_pri_table));
149 free(TMP_substitute_table);
150 free(TMP_char_pri_table);
151 free(TMP_chain_pri_table);
105
106 __collate_substitute_nontrivial = 0;
107 for (i = 0; i < UCHAR_MAX + 1; i++) {
108 if (__collate_substitute_table[i][0] != i ||
109 __collate_substitute_table[i][1] != 0) {
110 __collate_substitute_nontrivial = 1;
111 break;
112 }
113 }
152
153 __collate_substitute_nontrivial = 0;
154 for (i = 0; i < UCHAR_MAX + 1; i++) {
155 if (__collate_substitute_table[i][0] != i ||
156 __collate_substitute_table[i][1] != 0) {
157 __collate_substitute_nontrivial = 1;
158 break;
159 }
160 }
161 __collate_load_error = 0;
114
162
115 return 0;
163 return (_LDP_LOADED);
116}
117
118u_char *
119__collate_substitute(s)
120 const u_char *s;
121{
122 int dest_len, len, nlen;
123 int delta = strlen(s);
124 u_char *dest_str = NULL;
125
126 if (s == NULL || *s == '\0')
127 return (__collate_strdup(""));
128 delta += delta / 8;
129 dest_str = malloc(dest_len = delta);
130 if (dest_str == NULL)
131 __collate_err(EX_OSERR, __FUNCTION__);
132 len = 0;
133 while (*s) {
134 nlen = len + strlen(__collate_substitute_table[*s]);
135 if (dest_len <= nlen) {
136 dest_str = reallocf(dest_str, dest_len = nlen + delta);
137 if (dest_str == NULL)
138 __collate_err(EX_OSERR, __FUNCTION__);
139 }
140 (void)strcpy(dest_str + len, __collate_substitute_table[*s++]);
141 len = nlen;
142 }
143 return (dest_str);
144}
145
146void
147__collate_lookup(t, len, prim, sec)
148 const u_char *t;
149 int *len, *prim, *sec;
150{
151 struct __collate_st_chain_pri *p2;
152
153 *len = 1;
154 *prim = *sec = 0;
164}
165
166u_char *
167__collate_substitute(s)
168 const u_char *s;
169{
170 int dest_len, len, nlen;
171 int delta = strlen(s);
172 u_char *dest_str = NULL;
173
174 if (s == NULL || *s == '\0')
175 return (__collate_strdup(""));
176 delta += delta / 8;
177 dest_str = malloc(dest_len = delta);
178 if (dest_str == NULL)
179 __collate_err(EX_OSERR, __FUNCTION__);
180 len = 0;
181 while (*s) {
182 nlen = len + strlen(__collate_substitute_table[*s]);
183 if (dest_len <= nlen) {
184 dest_str = reallocf(dest_str, dest_len = nlen + delta);
185 if (dest_str == NULL)
186 __collate_err(EX_OSERR, __FUNCTION__);
187 }
188 (void)strcpy(dest_str + len, __collate_substitute_table[*s++]);
189 len = nlen;
190 }
191 return (dest_str);
192}
193
194void
195__collate_lookup(t, len, prim, sec)
196 const u_char *t;
197 int *len, *prim, *sec;
198{
199 struct __collate_st_chain_pri *p2;
200
201 *len = 1;
202 *prim = *sec = 0;
155 for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
156 if(strncmp(t, p2->str, strlen(p2->str)) == 0) {
203 for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) {
204 if (strncmp(t, p2->str, strlen(p2->str)) == 0) {
157 *len = strlen(p2->str);
158 *prim = p2->prim;
159 *sec = p2->sec;
160 return;
161 }
162 }
163 *prim = __collate_char_pri_table[*t].prim;
164 *sec = __collate_char_pri_table[*t].sec;
165}
166
167u_char *
168__collate_strdup(s)
169 u_char *s;
170{
171 u_char *t = strdup(s);
172
173 if (t == NULL)
174 __collate_err(EX_OSERR, __FUNCTION__);
175 return (t);
176}
177
178void
179__collate_err(int ex, const char *f)
180{
181 const char *s;
182 int serrno = errno;
183
184 s = _getprogname();
185 _write(STDERR_FILENO, s, strlen(s));
186 _write(STDERR_FILENO, ": ", 2);
187 s = f;
188 _write(STDERR_FILENO, s, strlen(s));
189 _write(STDERR_FILENO, ": ", 2);
190 s = strerror(serrno);
191 _write(STDERR_FILENO, s, strlen(s));
192 _write(STDERR_FILENO, "\n", 1);
193 exit(ex);
194}
195
196#ifdef COLLATE_DEBUG
197void
198__collate_print_tables()
199{
200 int i;
201 struct __collate_st_chain_pri *p2;
202
203 printf("Substitute table:\n");
204 for (i = 0; i < UCHAR_MAX + 1; i++)
205 if (i != *__collate_substitute_table[i])
206 printf("\t'%c' --> \"%s\"\n", i,
207 __collate_substitute_table[i]);
208 printf("Chain priority table:\n");
209 for (p2 = __collate_chain_pri_table; p2->str[0]; p2++)
210 printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec);
211 printf("Char priority table:\n");
212 for (i = 0; i < UCHAR_MAX + 1; i++)
213 printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
214 __collate_char_pri_table[i].sec);
215}
216#endif
205 *len = strlen(p2->str);
206 *prim = p2->prim;
207 *sec = p2->sec;
208 return;
209 }
210 }
211 *prim = __collate_char_pri_table[*t].prim;
212 *sec = __collate_char_pri_table[*t].sec;
213}
214
215u_char *
216__collate_strdup(s)
217 u_char *s;
218{
219 u_char *t = strdup(s);
220
221 if (t == NULL)
222 __collate_err(EX_OSERR, __FUNCTION__);
223 return (t);
224}
225
226void
227__collate_err(int ex, const char *f)
228{
229 const char *s;
230 int serrno = errno;
231
232 s = _getprogname();
233 _write(STDERR_FILENO, s, strlen(s));
234 _write(STDERR_FILENO, ": ", 2);
235 s = f;
236 _write(STDERR_FILENO, s, strlen(s));
237 _write(STDERR_FILENO, ": ", 2);
238 s = strerror(serrno);
239 _write(STDERR_FILENO, s, strlen(s));
240 _write(STDERR_FILENO, "\n", 1);
241 exit(ex);
242}
243
244#ifdef COLLATE_DEBUG
245void
246__collate_print_tables()
247{
248 int i;
249 struct __collate_st_chain_pri *p2;
250
251 printf("Substitute table:\n");
252 for (i = 0; i < UCHAR_MAX + 1; i++)
253 if (i != *__collate_substitute_table[i])
254 printf("\t'%c' --> \"%s\"\n", i,
255 __collate_substitute_table[i]);
256 printf("Chain priority table:\n");
257 for (p2 = __collate_chain_pri_table; p2->str[0]; p2++)
258 printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec);
259 printf("Char priority table:\n");
260 for (i = 0; i < UCHAR_MAX + 1; i++)
261 printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
262 __collate_char_pri_table[i].sec);
263}
264#endif