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
↓ 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;
↓ 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           */
↓ 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;
↓ 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;
↓ 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;
↓ 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                                          }
↓ open down ↓ 16 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX