Print this page
2964 need POSIX 2008 locale object support
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Approved by: TBD
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libc/port/locale/collate.c
+++ new/usr/src/lib/libc/port/locale/collate.c
1 1 /*
2 - * Copright 2010 Nexenta Systems, Inc. All rights reserved.
2 + * Copyright 2014 Garrett D'Amore <garrett@damore.org>
3 + * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
3 4 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
4 5 * at Electronni Visti IA, Kiev, Ukraine.
5 6 * All rights reserved.
6 7 *
7 8 * Redistribution and use in source and binary forms, with or without
8 9 * modification, are permitted provided that the following conditions
9 10 * are met:
10 11 * 1. Redistributions of source code must retain the above copyright
11 12 * notice, this list of conditions and the following disclaimer.
12 13 * 2. Redistributions in binary form must reproduce the above copyright
13 14 * notice, this list of conditions and the following disclaimer in the
14 15 * documentation and/or other materials provided with the distribution.
15 16 *
16 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
20 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 27 * SUCH DAMAGE.
27 28 */
28 29
29 30 #include "lint.h"
30 31 #include "file64.h"
31 32 #include <stdio.h>
32 33 #include <stdlib.h>
33 34 #include <stddef.h>
34 35 #include <string.h>
35 36 #include <wchar.h>
36 37 #include <errno.h>
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
37 38 #include <unistd.h>
38 39 #include <ctype.h>
39 40 #include <unistd.h>
40 41 #include <fcntl.h>
41 42 #include <assert.h>
42 43 #include <sys/stat.h>
43 44 #include <sys/mman.h>
44 45
45 46 #include "collate.h"
46 47 #include "setlocale.h"
47 -#include "ldpart.h"
48 48
49 49 /*
50 50 * See the comments in usr/src/cmd/localedef/collate.c for further
51 51 * information. It would also be very helpful to have a copy of the
52 52 * POSIX standard for collation (in the locale format manual page)
53 53 * handy (www.opengroup.org).
54 54 */
55 55
56 -static collate_subst_t *subst_table[COLL_WEIGHTS_MAX];
57 -static collate_char_t *char_pri_table;
58 -static collate_large_t *large_pri_table;
59 -static collate_chain_t *chain_pri_table;
60 -static char *cache = NULL;
61 -static size_t cachesz;
62 -static char collate_encoding[ENCODING_LEN + 1];
56 +/*
57 + * POSIX uses empty tables and falls down to strcmp.
58 + */
59 +struct lc_collate lc_collate_posix = {
60 + .lc_is_posix = 1,
61 +};
63 62
64 -/* Exposed externally to other parts of libc. */
65 -collate_info_t *_collate_info;
66 -int _collate_load_error = 1;
63 +struct locdata __posix_collate_locdata = {
64 + .l_lname = "C",
65 + .l_data = { &lc_collate_posix }
66 +};
67 67
68 68
69 -int
70 -_collate_load_tables(const char *encoding)
69 +struct locdata *
70 +__lc_collate_load(const char *locname)
71 71 {
72 72 int i, chains, z;
73 73 char buf[PATH_MAX];
74 74 char *TMP;
75 75 char *map;
76 76 collate_info_t *info;
77 77 struct stat sbuf;
78 78 int fd;
79 + struct locdata *ldata;
80 + struct lc_collate *lcc;
79 81
80 - /* 'encoding' must be already checked. */
81 - if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
82 - _collate_load_error = 1;
83 - return (_LDP_CACHE);
84 - }
85 -
86 82 /*
87 - * If the locale name is the same as our cache, use the cache.
88 - */
89 - if (cache && (strncmp(encoding, collate_encoding, ENCODING_LEN) == 0)) {
90 - _collate_load_error = 0;
91 - return (_LDP_CACHE);
92 - }
93 -
94 - /*
95 83 * Slurp the locale file into the cache.
96 84 */
97 85
98 86 (void) snprintf(buf, sizeof (buf), "%s/%s/LC_COLLATE/LCL_DATA",
99 - _PathLocale, encoding);
87 + _PathLocale, locname);
100 88
101 - if ((fd = open(buf, O_RDONLY)) < 0)
102 - return (_LDP_ERROR);
89 + if ((fd = open(buf, O_RDONLY)) < 0) {
90 + errno = EINVAL;
91 + return (NULL);
92 + }
103 93 if (fstat(fd, &sbuf) < 0) {
104 94 (void) close(fd);
105 - return (_LDP_ERROR);
95 + errno = EINVAL;
96 + return (NULL);
106 97 }
107 98 if (sbuf.st_size < (COLLATE_STR_LEN + sizeof (info))) {
108 99 (void) close(fd);
109 100 errno = EINVAL;
110 - return (_LDP_ERROR);
101 + return (NULL);
111 102 }
112 103 map = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
113 104 (void) close(fd);
114 105 if ((TMP = map) == NULL) {
115 - return (_LDP_ERROR);
106 + errno = EINVAL;
107 + return (NULL);
116 108 }
117 109
118 110 if (strncmp(TMP, COLLATE_VERSION, COLLATE_STR_LEN) != 0) {
119 111 (void) munmap(map, sbuf.st_size);
120 112 errno = EINVAL;
121 - return (_LDP_ERROR);
113 + return (NULL);
122 114 }
123 115 TMP += COLLATE_STR_LEN;
124 116
125 117 info = (void *)TMP;
126 118 TMP += sizeof (*info);
127 119
128 120 if ((info->directive_count < 1) ||
129 121 (info->directive_count >= COLL_WEIGHTS_MAX) ||
130 122 ((chains = info->chain_count) < 0)) {
131 123 (void) munmap(map, sbuf.st_size);
132 124 errno = EINVAL;
133 - return (_LDP_ERROR);
125 + return (NULL);
134 126 }
135 127
136 128 i = (sizeof (collate_char_t) * (UCHAR_MAX + 1)) +
137 129 (sizeof (collate_chain_t) * chains) +
138 130 (sizeof (collate_large_t) * info->large_count);
139 - for (z = 0; z < (info->directive_count); z++) {
131 + for (z = 0; z < info->directive_count; z++) {
140 132 i += sizeof (collate_subst_t) * info->subst_count[z];
141 133 }
142 134 if (i != (sbuf.st_size - (TMP - map))) {
143 135 (void) munmap(map, sbuf.st_size);
144 136 errno = EINVAL;
145 - return (_LDP_ERROR);
137 + return (NULL);
146 138 }
147 139
148 - char_pri_table = (void *)TMP;
140 +
141 + if ((ldata = __locdata_alloc(locname, sizeof (*lcc))) == NULL) {
142 + (void) munmap(map, sbuf.st_size);
143 + return (NULL);
144 + }
145 + lcc = ldata->l_data[0];
146 + ldata->l_map = map;
147 + ldata->l_map_len = sbuf.st_size;
148 +
149 + lcc->lc_info = info;
150 + lcc->lc_directive_count = info->directive_count;
151 + lcc->lc_large_count = info->large_count;
152 +
153 + for (z = 0; z < COLL_WEIGHTS_MAX; z++) {
154 + lcc->lc_directive[z] = info->directive[z];
155 + lcc->lc_subst_count[z] = info->subst_count[z];
156 + lcc->lc_pri_count[z] = info->pri_count[z];
157 + lcc->lc_undef_pri[z] = info->undef_pri[z];
158 + }
159 +
160 + lcc->lc_char_table = (void *)TMP;
149 161 TMP += sizeof (collate_char_t) * (UCHAR_MAX + 1);
150 162
151 - for (z = 0; z < info->directive_count; z++) {
152 - if (info->subst_count[z] > 0) {
153 - subst_table[z] = (void *)TMP;
154 - TMP += info->subst_count[z] * sizeof (collate_subst_t);
163 + for (z = 0; z < lcc->lc_directive_count; z++) {
164 + int count;
165 + if ((count = lcc->lc_subst_count[z]) > 0) {
166 + lcc->lc_subst_table[z] = (void *)TMP;
167 + TMP += count * sizeof (collate_subst_t);
155 168 } else {
156 - subst_table[z] = NULL;
169 + lcc->lc_subst_table[z] = NULL;
157 170 }
158 171 }
159 172
160 173 if (chains > 0) {
161 - chain_pri_table = (void *)TMP;
174 + lcc->lc_chain_table = (void *)TMP;
162 175 TMP += chains * sizeof (collate_chain_t);
163 176 } else
164 - chain_pri_table = NULL;
165 - if (info->large_count > 0)
166 - large_pri_table = (void *)TMP;
177 + lcc->lc_chain_table = NULL;
178 + lcc->lc_chain_count = chains;
179 + if (lcc->lc_large_count > 0)
180 + lcc->lc_large_table = (void *)TMP;
167 181 else
168 - large_pri_table = NULL;
182 + lcc->lc_large_table = NULL;
169 183
170 - (void) strlcpy(collate_encoding, encoding, ENCODING_LEN);
171 - _collate_info = info;
172 -
173 - if (cache)
174 - (void) munmap(cache, cachesz);
175 -
176 - cache = map;
177 - cachesz = sbuf.st_size;
178 - _collate_load_error = 0;
179 -
180 - return (_LDP_LOADED);
184 + return (ldata);
181 185 }
182 186
183 -static int32_t *
184 -substsearch(const wchar_t key, int pass)
187 +static const int32_t *
188 +substsearch(const struct lc_collate *lcc, const wchar_t key, int pass)
185 189 {
186 - collate_subst_t *p;
187 - int n = _collate_info->subst_count[pass];
190 + const collate_subst_t *p;
191 + int n = lcc->lc_subst_count[pass];
188 192
189 193 if (n == 0)
190 194 return (NULL);
191 195
192 - if (pass >= _collate_info->directive_count)
196 + if (pass >= lcc->lc_directive_count)
193 197 return (NULL);
194 198
195 199 if (!(key & COLLATE_SUBST_PRIORITY))
196 200 return (NULL);
197 201
198 - p = subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY);
202 + p = lcc->lc_subst_table[pass] + (key & ~COLLATE_SUBST_PRIORITY);
199 203 assert(p->key == key);
200 204 return (p->pri);
201 205 }
202 206
203 207 /*
204 208 * Note: for performance reasons, we have expanded bsearch here. This avoids
205 209 * function call overhead with each comparison.
206 210 */
207 211
208 212 static collate_chain_t *
209 -chainsearch(const wchar_t *key, int *len)
213 +chainsearch(const struct lc_collate *lcc, const wchar_t *key, int *len)
210 214 {
211 215 int low;
212 216 int high;
213 217 int next, compar, l;
214 218 collate_chain_t *p;
215 219 collate_chain_t *tab;
216 220
217 - if (_collate_info->chain_count == 0)
221 + if (lcc->lc_info->chain_count == 0)
218 222 return (NULL);
219 223
220 224 low = 0;
221 - high = _collate_info->chain_count - 1;
222 - tab = chain_pri_table;
225 + high = lcc->lc_info->chain_count - 1;
226 + tab = lcc->lc_chain_table;
223 227
224 228 while (low <= high) {
225 229 next = (low + high) / 2;
226 230 p = tab + next;
227 231 compar = *key - *p->str;
228 232 if (compar == 0) {
229 233 l = wcsnlen(p->str, COLLATE_STR_LEN);
230 234 compar = wcsncmp(key, p->str, l);
231 235 if (compar == 0) {
232 236 *len = l;
233 237 return (p);
234 238 }
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
235 239 }
236 240 if (compar > 0)
237 241 low = next + 1;
238 242 else
239 243 high = next - 1;
240 244 }
241 245 return (NULL);
242 246 }
243 247
244 248 static collate_large_t *
245 -largesearch(const wchar_t key)
249 +largesearch(const struct lc_collate *lcc, const wchar_t key)
246 250 {
247 251 int low = 0;
248 - int high = _collate_info->large_count - 1;
252 + int high = lcc->lc_info->large_count - 1;
249 253 int next, compar;
250 254 collate_large_t *p;
251 - collate_large_t *tab = large_pri_table;
255 + collate_large_t *tab = lcc->lc_large_table;
252 256
253 - if (_collate_info->large_count == 0)
257 + if (lcc->lc_info->large_count == 0)
254 258 return (NULL);
255 259
256 260 while (low <= high) {
257 261 next = (low + high) / 2;
258 262 p = tab + next;
259 263 compar = key - p->val;
260 264 if (compar == 0)
261 265 return (p);
262 266 if (compar > 0)
263 267 low = next + 1;
264 268 else
265 269 high = next - 1;
266 270 }
267 271 return (NULL);
268 272 }
269 273
270 274 void
271 -_collate_lookup(const wchar_t *t, int *len, int *pri, int which, int **state)
275 +_collate_lookup(const struct lc_collate *lcc, const wchar_t *t,
276 + int *len, int *pri, int which, const int **state)
272 277 {
273 278 collate_chain_t *p2;
274 279 collate_large_t *match;
275 - collate_info_t *info = _collate_info;
276 280 int p, l;
277 - int *sptr;
281 + const int *sptr;
278 282
279 283 /*
280 284 * If this is the "last" pass for the UNDEFINED, then
281 285 * we just return the priority itself.
282 286 */
283 - if (which >= info->directive_count) {
287 + if (which >= lcc->lc_directive_count) {
284 288 *pri = *t;
285 289 *len = 1;
286 290 *state = NULL;
287 291 return;
288 292 }
289 293
290 294 /*
291 295 * If we have remaining substitution data from a previous
292 296 * call, consume it first.
293 297 */
294 298 if ((sptr = *state) != NULL) {
295 299 *pri = *sptr;
296 300 sptr++;
297 301 *state = *sptr ? sptr : NULL;
298 302 *len = 0;
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
299 303 return;
300 304 }
301 305
302 306 /* No active substitutions */
303 307 *len = 1;
304 308
305 309 /*
306 310 * Check for composites such as dipthongs that collate as a
307 311 * single element (aka chains or collating-elements).
308 312 */
309 - if (((p2 = chainsearch(t, &l)) != NULL) &&
313 + if (((p2 = chainsearch(lcc, t, &l)) != NULL) &&
310 314 ((p = p2->pri[which]) >= 0)) {
311 315
312 316 *len = l;
313 317 *pri = p;
314 318
315 319 } else if (*t <= UCHAR_MAX) {
316 320
317 321 /*
318 322 * Character is a small (8-bit) character.
319 323 * We just look these up directly for speed.
320 324 */
321 - *pri = char_pri_table[*t].pri[which];
325 + *pri = lcc->lc_char_table[*t].pri[which];
322 326
323 - } else if ((info->large_count > 0) &&
324 - ((match = largesearch(*t)) != NULL)) {
327 + } else if ((lcc->lc_info->large_count > 0) &&
328 + ((match = largesearch(lcc, *t)) != NULL)) {
325 329
326 330 /*
327 331 * Character was found in the extended table.
328 332 */
329 333 *pri = match->pri.pri[which];
330 334
331 335 } else {
332 336 /*
333 337 * Character lacks a specific definition.
334 338 */
335 - if (info->directive[which] & DIRECTIVE_UNDEFINED) {
339 + if (lcc->lc_directive[which] & DIRECTIVE_UNDEFINED) {
336 340 /* Mask off sign bit to prevent ordering confusion. */
337 341 *pri = (*t & COLLATE_MAX_PRIORITY);
338 342 } else {
339 - *pri = info->undef_pri[which];
343 + *pri = lcc->lc_undef_pri[which];
340 344 }
341 345 /* No substitutions for undefined characters! */
342 346 return;
343 347 }
344 348
345 349 /*
346 350 * Try substituting (expanding) the character. We are
347 351 * currently doing this *after* the chain compression. I
348 352 * think it should not matter, but this way might be slightly
349 353 * faster.
350 354 *
351 355 * We do this after the priority search, as this will help us
352 356 * to identify a single key value. In order for this to work,
353 357 * its important that the priority assigned to a given element
354 358 * to be substituted be unique for that level. The localedef
355 359 * code ensures this for us.
356 360 */
357 - if ((sptr = substsearch(*pri, which)) != NULL) {
361 + if ((sptr = substsearch(lcc, *pri, which)) != NULL) {
358 362 if ((*pri = *sptr) != 0) {
359 363 sptr++;
360 364 *state = *sptr ? sptr : NULL;
361 365 }
362 366 }
363 367
364 368 }
365 369
366 370 /*
367 371 * This is the meaty part of wcsxfrm & strxfrm. Note that it does
368 372 * NOT NULL terminate. That is left to the caller.
369 373 */
370 374 size_t
371 -_collate_wxfrm(const wchar_t *src, wchar_t *xf, size_t room)
375 +_collate_wxfrm(const struct lc_collate *lcc, const wchar_t *src, wchar_t *xf,
376 + size_t room)
372 377 {
373 378 int pri;
374 379 int len;
375 380 const wchar_t *t;
376 381 wchar_t *tr = NULL;
377 382 int direc;
378 383 int pass;
379 - int32_t *state;
384 + const int32_t *state;
380 385 size_t want = 0;
381 386 size_t need = 0;
387 + int ndir = lcc->lc_directive_count;
382 388
383 389 assert(src);
384 390
385 - for (pass = 0; pass <= _collate_info->directive_count; pass++) {
391 + for (pass = 0; pass <= ndir; pass++) {
386 392
387 393 state = NULL;
388 394
389 395 if (pass != 0) {
390 396 /* insert level separator from the previous pass */
391 397 if (room) {
392 398 *xf++ = 1;
393 399 room--;
394 400 }
395 401 want++;
396 402 }
397 403
398 404 /* special pass for undefined */
399 - if (pass == _collate_info->directive_count) {
405 + if (pass == ndir) {
400 406 direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
401 407 } else {
402 - direc = _collate_info->directive[pass];
408 + direc = lcc->lc_directive[pass];
403 409 }
404 410
405 411 t = src;
406 412
407 413 if (direc & DIRECTIVE_BACKWARD) {
408 414 wchar_t *bp, *fp, c;
409 415 if (tr)
410 416 free(tr);
411 417 if ((tr = wcsdup(t)) == NULL) {
412 418 errno = ENOMEM;
413 419 goto fail;
414 420 }
415 421 bp = tr;
416 422 fp = tr + wcslen(tr) - 1;
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
417 423 while (bp < fp) {
418 424 c = *bp;
419 425 *bp++ = *fp;
420 426 *fp-- = c;
421 427 }
422 428 t = (const wchar_t *)tr;
423 429 }
424 430
425 431 if (direc & DIRECTIVE_POSITION) {
426 432 while (*t || state) {
427 - _collate_lookup(t, &len, &pri, pass, &state);
433 + _collate_lookup(lcc, t, &len, &pri, pass,
434 + &state);
428 435 t += len;
429 436 if (pri <= 0) {
430 437 if (pri < 0) {
431 438 errno = EINVAL;
432 439 goto fail;
433 440 }
434 441 pri = COLLATE_MAX_PRIORITY;
435 442 }
436 443 if (room) {
437 444 *xf++ = pri;
438 445 room--;
439 446 }
440 447 want++;
441 448 need = want;
442 449 }
443 450 } else {
444 451 while (*t || state) {
445 - _collate_lookup(t, &len, &pri, pass, &state);
452 + _collate_lookup(lcc, t, &len, &pri, pass,
453 + &state);
446 454 t += len;
447 455 if (pri <= 0) {
448 456 if (pri < 0) {
449 457 errno = EINVAL;
450 458 goto fail;
451 459 }
452 460 continue;
453 461 }
454 462 if (room) {
455 463 *xf++ = pri;
456 464 room--;
457 465 }
458 466 want++;
459 467 need = want;
460 468 }
461 469 }
462 470 }
463 471
464 472 end:
465 473 if (tr)
466 474 free(tr);
467 475 return (need);
468 476
469 477 fail:
470 478 if (tr)
471 479 free(tr);
472 480 return ((size_t)(-1));
473 481 }
474 482
475 483 /*
476 484 * In the non-POSIX case, we transform each character into a string of
477 485 * characters representing the character's priority. Since char is usually
478 486 * signed, we are limited by 7 bits per byte. To avoid zero, we need to add
479 487 * XFRM_OFFSET, so we can't use a full 7 bits. For simplicity, we choose 6
480 488 * bits per byte.
481 489 *
482 490 * It turns out that we sometimes have real priorities that are
483 491 * 31-bits wide. (But: be careful using priorities where the high
484 492 * order bit is set -- i.e. the priority is negative. The sort order
485 493 * may be surprising!)
486 494 *
487 495 * TODO: This would be a good area to optimize somewhat. It turns out
488 496 * that real prioririties *except for the last UNDEFINED pass* are generally
489 497 * very small. We need the localedef code to precalculate the max
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
490 498 * priority for us, and ideally also give us a mask, and then we could
491 499 * severely limit what we expand to.
492 500 */
493 501 #define XFRM_BYTES 6
494 502 #define XFRM_OFFSET ('0') /* make all printable characters */
495 503 #define XFRM_SHIFT 6
496 504 #define XFRM_MASK ((1 << XFRM_SHIFT) - 1)
497 505 #define XFRM_SEP ('.') /* chosen to be less than XFRM_OFFSET */
498 506
499 507 static int
500 -xfrm(unsigned char *p, int pri, int pass)
508 +xfrm(locale_t loc, unsigned char *p, int pri, int pass)
501 509 {
502 510 /* we use unsigned to ensure zero fill on right shift */
503 - uint32_t val = (uint32_t)_collate_info->pri_count[pass];
511 + uint32_t val = (uint32_t)loc->collate->lc_pri_count[pass];
504 512 int nc = 0;
505 513
506 514 while (val) {
507 515 *p = (pri & XFRM_MASK) + XFRM_OFFSET;
508 516 pri >>= XFRM_SHIFT;
509 517 val >>= XFRM_SHIFT;
510 518 p++;
511 519 nc++;
512 520 }
513 521 return (nc);
514 522 }
515 523
516 524 size_t
517 -_collate_sxfrm(const wchar_t *src, char *xf, size_t room)
525 +_collate_sxfrm(const wchar_t *src, char *xf, size_t room, locale_t loc)
518 526 {
519 527 int pri;
520 528 int len;
521 529 const wchar_t *t;
522 530 wchar_t *tr = NULL;
523 531 int direc;
524 532 int pass;
525 - int32_t *state;
533 + const int32_t *state;
526 534 size_t want = 0;
527 535 size_t need = 0;
528 536 int b;
529 537 uint8_t buf[XFRM_BYTES];
538 + const struct lc_collate *lcc = loc->collate;
539 + int ndir = lcc->lc_directive_count;
530 540
531 541 assert(src);
532 542
533 - for (pass = 0; pass <= _collate_info->directive_count; pass++) {
543 + for (pass = 0; pass <= ndir; pass++) {
534 544
535 545 state = NULL;
536 546
537 547 if (pass != 0) {
538 548 /* insert level separator from the previous pass */
539 549 if (room) {
540 550 *xf++ = XFRM_SEP;
541 551 room--;
542 552 }
543 553 want++;
544 554 }
545 555
546 556 /* special pass for undefined */
547 - if (pass == _collate_info->directive_count) {
557 + if (pass == ndir) {
548 558 direc = DIRECTIVE_FORWARD | DIRECTIVE_UNDEFINED;
549 559 } else {
550 - direc = _collate_info->directive[pass];
560 + direc = lcc->lc_directive[pass];
551 561 }
552 562
553 563 t = src;
554 564
555 565 if (direc & DIRECTIVE_BACKWARD) {
556 566 wchar_t *bp, *fp, c;
557 567 if (tr)
558 568 free(tr);
559 569 if ((tr = wcsdup(t)) == NULL) {
560 570 errno = ENOMEM;
561 571 goto fail;
562 572 }
563 573 bp = tr;
564 574 fp = tr + wcslen(tr) - 1;
565 575 while (bp < fp) {
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
566 576 c = *bp;
567 577 *bp++ = *fp;
568 578 *fp-- = c;
569 579 }
570 580 t = (const wchar_t *)tr;
571 581 }
572 582
573 583 if (direc & DIRECTIVE_POSITION) {
574 584 while (*t || state) {
575 585
576 - _collate_lookup(t, &len, &pri, pass, &state);
586 + _collate_lookup(lcc, t, &len, &pri, pass,
587 + &state);
577 588 t += len;
578 589 if (pri <= 0) {
579 590 if (pri < 0) {
580 591 errno = EINVAL;
581 592 goto fail;
582 593 }
583 594 pri = COLLATE_MAX_PRIORITY;
584 595 }
585 596
586 - b = xfrm(buf, pri, pass);
597 + b = xfrm(loc, buf, pri, pass);
587 598 want += b;
588 599 if (room) {
589 600 while (b) {
590 601 b--;
591 602 if (room) {
592 603 *xf++ = buf[b];
593 604 room--;
594 605 }
595 606 }
596 607 }
597 608 need = want;
598 609 }
599 610 } else {
600 611 while (*t || state) {
601 - _collate_lookup(t, &len, &pri, pass, &state);
612 + _collate_lookup(lcc, t, &len, &pri, pass,
613 + &state);
602 614 t += len;
603 615 if (pri <= 0) {
604 616 if (pri < 0) {
605 617 errno = EINVAL;
606 618 goto fail;
607 619 }
608 620 continue;
609 621 }
610 622
611 - b = xfrm(buf, pri, pass);
623 + b = xfrm(loc, buf, pri, pass);
612 624 want += b;
613 625 if (room) {
614 626
615 627 while (b) {
616 628 b--;
617 629 if (room) {
618 630 *xf++ = buf[b];
619 631 room--;
620 632 }
621 633 }
622 634 }
623 635 need = want;
624 636 }
625 637 }
626 638 }
627 639
628 640 end:
629 641 if (tr)
630 642 free(tr);
631 643 return (need);
632 644
633 645 fail:
634 646 if (tr)
635 647 free(tr);
636 648 return ((size_t)(-1));
637 649 }
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX