]>
Commit | Line | Data |
---|---|---|
5b2abdfb A |
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 | * $FreeBSD: src/lib/libc/locale/collate.c,v 1.21.2.1 2001/03/05 10:10:22 obrien Exp $ | |
28 | */ | |
29 | ||
30 | #include <rune.h> | |
31 | #include <stdio.h> | |
32 | #include <stdlib.h> | |
33 | #include <string.h> | |
34 | #include <errno.h> | |
35 | #include <unistd.h> | |
36 | #include <sysexits.h> | |
37 | #include <crt_externs.h> | |
38 | #include "collate.h" | |
39 | #include "setlocale.h" | |
40 | ||
41 | int __collate_load_error = 1; | |
42 | int __collate_substitute_nontrivial; | |
43 | char __collate_version[STR_LEN]; | |
44 | u_char __collate_substitute_table[UCHAR_MAX + 1][STR_LEN]; | |
45 | struct __collate_st_char_pri __collate_char_pri_table[UCHAR_MAX + 1]; | |
46 | struct __collate_st_chain_pri __collate_chain_pri_table[TABLE_SIZE]; | |
47 | ||
48 | #define FREAD(a, b, c, d) \ | |
49 | do { \ | |
50 | if (fread(a, b, c, d) != c) { \ | |
51 | fclose(d); \ | |
52 | return -1; \ | |
53 | } \ | |
54 | } while(0) | |
55 | ||
56 | void __collate_err(int ex, const char *f) ; | |
57 | ||
58 | int | |
59 | __collate_load_tables(encoding) | |
60 | char *encoding; | |
61 | { | |
62 | char buf[PATH_MAX]; | |
63 | FILE *fp; | |
64 | int i, save_load_error; | |
65 | ||
66 | save_load_error = __collate_load_error; | |
67 | __collate_load_error = 1; | |
68 | if (!encoding) { | |
69 | __collate_load_error = save_load_error; | |
70 | return -1; | |
71 | } | |
72 | if (!strcmp(encoding, "C") || !strcmp(encoding, "POSIX")) | |
73 | return 0; | |
74 | if (!_PathLocale) { | |
75 | __collate_load_error = save_load_error; | |
76 | return -1; | |
77 | } | |
78 | /* Range checking not needed, encoding has fixed size */ | |
79 | (void) strcpy(buf, _PathLocale); | |
80 | (void) strcat(buf, "/"); | |
81 | (void) strcat(buf, encoding); | |
82 | (void) strcat(buf, "/LC_COLLATE"); | |
83 | if ((fp = fopen(buf, "r")) == NULL) { | |
84 | __collate_load_error = save_load_error; | |
85 | return -1; | |
86 | } | |
87 | FREAD(__collate_version, sizeof(__collate_version), 1, fp); | |
88 | if (strcmp(__collate_version, COLLATE_VERSION) != 0) { | |
89 | fclose(fp); | |
90 | return -1; | |
91 | } | |
92 | FREAD(__collate_substitute_table, sizeof(__collate_substitute_table), | |
93 | 1, fp); | |
94 | FREAD(__collate_char_pri_table, sizeof(__collate_char_pri_table), 1, | |
95 | fp); | |
96 | FREAD(__collate_chain_pri_table, sizeof(__collate_chain_pri_table), 1, | |
97 | fp); | |
98 | fclose(fp); | |
99 | __collate_load_error = 0; | |
100 | ||
101 | __collate_substitute_nontrivial = 0; | |
102 | for (i = 0; i < UCHAR_MAX + 1; i++) { | |
103 | if (__collate_substitute_table[i][0] != i || | |
104 | __collate_substitute_table[i][1] != 0) { | |
105 | __collate_substitute_nontrivial = 1; | |
106 | break; | |
107 | } | |
108 | } | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
113 | u_char * | |
114 | __collate_substitute(s) | |
115 | const u_char *s; | |
116 | { | |
117 | int dest_len, len, nlen; | |
118 | int delta = strlen(s); | |
119 | u_char *dest_str = NULL; | |
120 | ||
121 | if(s == NULL || *s == '\0') | |
122 | return __collate_strdup(""); | |
123 | delta += delta / 8; | |
124 | dest_str = malloc(dest_len = delta); | |
125 | if(dest_str == NULL) | |
126 | __collate_err(EX_OSERR, __FUNCTION__); | |
127 | len = 0; | |
128 | while(*s) { | |
129 | nlen = len + strlen(__collate_substitute_table[*s]); | |
130 | if (dest_len <= nlen) { | |
131 | dest_str = reallocf(dest_str, dest_len = nlen + delta); | |
132 | if(dest_str == NULL) | |
133 | __collate_err(EX_OSERR, __FUNCTION__); | |
134 | } | |
135 | strcpy(dest_str + len, __collate_substitute_table[*s++]); | |
136 | len = nlen; | |
137 | } | |
138 | return dest_str; | |
139 | } | |
140 | ||
141 | void | |
142 | __collate_lookup(t, len, prim, sec) | |
143 | const u_char *t; | |
144 | int *len, *prim, *sec; | |
145 | { | |
146 | struct __collate_st_chain_pri *p2; | |
147 | ||
148 | *len = 1; | |
149 | *prim = *sec = 0; | |
150 | for(p2 = __collate_chain_pri_table; p2->str[0]; p2++) { | |
151 | if(strncmp(t, p2->str, strlen(p2->str)) == 0) { | |
152 | *len = strlen(p2->str); | |
153 | *prim = p2->prim; | |
154 | *sec = p2->sec; | |
155 | return; | |
156 | } | |
157 | } | |
158 | *prim = __collate_char_pri_table[*t].prim; | |
159 | *sec = __collate_char_pri_table[*t].sec; | |
160 | } | |
161 | ||
162 | u_char * | |
163 | __collate_strdup(s) | |
164 | u_char *s; | |
165 | { | |
166 | u_char *t = strdup(s); | |
167 | ||
168 | if (t == NULL) | |
169 | __collate_err(EX_OSERR, __FUNCTION__); | |
170 | return t; | |
171 | } | |
172 | ||
173 | void | |
174 | __collate_err(int ex, const char *f) | |
175 | { | |
176 | char **__progname = _NSGetProgname(); | |
177 | const char *s; | |
178 | int serrno = errno; | |
179 | ||
180 | s = *__progname; | |
181 | write(STDERR_FILENO, s, strlen(s)); | |
182 | write(STDERR_FILENO, ": ", 2); | |
183 | s = f; | |
184 | write(STDERR_FILENO, s, strlen(s)); | |
185 | write(STDERR_FILENO, ": ", 2); | |
186 | s = strerror(serrno); | |
187 | write(STDERR_FILENO, s, strlen(s)); | |
188 | write(STDERR_FILENO, "\n", 1); | |
189 | exit(ex); | |
190 | } | |
191 | ||
192 | #ifdef COLLATE_DEBUG | |
193 | void | |
194 | __collate_print_tables() | |
195 | { | |
196 | int i; | |
197 | struct __collate_st_chain_pri *p2; | |
198 | ||
199 | printf("Substitute table:\n"); | |
200 | for (i = 0; i < UCHAR_MAX + 1; i++) | |
201 | if (i != *__collate_substitute_table[i]) | |
202 | printf("\t'%c' --> \"%s\"\n", i, | |
203 | __collate_substitute_table[i]); | |
204 | printf("Chain priority table:\n"); | |
205 | for (p2 = __collate_chain_pri_table; p2->str[0]; p2++) | |
206 | printf("\t\"%s\" : %d %d\n\n", p2->str, p2->prim, p2->sec); | |
207 | printf("Char priority table:\n"); | |
208 | for (i = 0; i < UCHAR_MAX + 1; i++) | |
209 | printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim, | |
210 | __collate_char_pri_table[i].sec); | |
211 | } | |
212 | #endif |