~ubuntu-branches/ubuntu/maverick/krb5/maverick

« back to all changes in this revision

Viewing changes to src/lib/krb5/unicode/ucdata/ucdata.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Hartman
  • Date: 2009-05-07 16:16:34 UTC
  • mfrom: (13.1.7 sid)
  • Revision ID: james.westby@ubuntu.com-20090507161634-xqyk0s9na0le4flj
Tags: 1.7dfsg~beta1-4
When  decrypting the TGS response fails with the subkey, try with the
session key to work around Heimdal bug, Closes: #527353 

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $OpenLDAP: pkg/ldap/libraries/liblunicode/ucdata/ucdata.c,v 1.36 2008/01/07 23:20:05 kurt Exp $ */
 
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
 
3
 *
 
4
 * Copyright 1998-2008 The OpenLDAP Foundation.
 
5
 * All rights reserved.
 
6
 *
 
7
 * Redistribution and use in source and binary forms, with or without
 
8
 * modification, are permitted only as authorized by the OpenLDAP
 
9
 * Public License.
 
10
 *
 
11
 * A copy of this license is available in file LICENSE in the
 
12
 * top-level directory of the distribution or, alternatively, at
 
13
 * <http://www.OpenLDAP.org/license.html>.
 
14
 */
 
15
/* Copyright 2001 Computing Research Labs, New Mexico State University
 
16
 *
 
17
 * Permission is hereby granted, free of charge, to any person obtaining a
 
18
 * copy of this software and associated documentation files (the "Software"),
 
19
 * to deal in the Software without restriction, including without limitation
 
20
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
21
 * and/or sell copies of the Software, and to permit persons to whom the
 
22
 * Software is furnished to do so, subject to the following conditions:
 
23
 *
 
24
 * The above copyright notice and this permission notice shall be included in
 
25
 * all copies or substantial portions of the Software.
 
26
 *
 
27
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
28
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
29
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
30
 * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
 
31
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
 
32
 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 
33
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
34
 */
 
35
/* $Id: ucdata.c,v 1.4 2001/01/02 18:46:20 mleisher Exp $" */
 
36
 
 
37
#include "k5-int.h"
 
38
#include "k5-utf8.h"
 
39
#include "k5-unicode.h"
 
40
 
 
41
#include "ucdata.h"
 
42
 
 
43
#ifndef HARDCODE_DATA
 
44
#define HARDCODE_DATA   1
 
45
#endif
 
46
 
 
47
#if HARDCODE_DATA
 
48
#include "uctable.h"
 
49
#endif
 
50
 
 
51
/**************************************************************************
 
52
 *
 
53
 * Miscellaneous types, data, and support functions.
 
54
 *
 
55
 **************************************************************************/
 
56
 
 
57
typedef struct {
 
58
    krb5_ui_2 bom;
 
59
    krb5_ui_2 cnt;
 
60
    union {
 
61
        krb5_ui_4 bytes;
 
62
        krb5_ui_2 len[2]; 
 
63
    } size;
 
64
} _ucheader_t;
 
65
 
 
66
/*
 
67
 * A simple array of 32-bit masks for lookup.
 
68
 */
 
69
static krb5_ui_4 masks32[32] = {
 
70
        0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL,
 
71
        0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL,
 
72
        0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL,
 
73
        0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL,
 
74
        0x00010000UL, 0x00020000UL, 0x00040000UL, 0x00080000UL,
 
75
        0x00100000UL, 0x00200000UL, 0x00400000UL, 0x00800000UL,
 
76
        0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
 
77
        0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL
 
78
};
 
79
 
 
80
#define endian_short(cc) (((cc) >> 8) | (((cc) & 0xff) << 8))
 
81
#define endian_long(cc) ((((cc) & 0xff) << 24)|((((cc) >> 8) & 0xff) << 16)|\
 
82
                        ((((cc) >> 16) & 0xff) << 8)|((cc) >> 24))
 
83
 
 
84
#if !HARDCODE_DATA
 
85
static FILE *
 
86
_ucopenfile(char *paths, char *filename, char *mode)
 
87
{
 
88
    FILE *f;
 
89
    char *fp, *dp, *pp, path[BUFSIZ];
 
90
 
 
91
    if (filename == 0 || *filename == 0)
 
92
      return 0;
 
93
 
 
94
    dp = paths;
 
95
    while (dp && *dp) {
 
96
        pp = path;
 
97
        while (*dp && *dp != ':')
 
98
          *pp++ = *dp++;
 
99
        *pp++ = *LDAP_DIRSEP;
 
100
 
 
101
        fp = filename;
 
102
        while (*fp)
 
103
          *pp++ = *fp++;
 
104
        *pp = 0;
 
105
 
 
106
        if ((f = fopen(path, mode)) != 0)
 
107
          return f;
 
108
 
 
109
        if (*dp == ':')
 
110
          dp++;
 
111
    }
 
112
 
 
113
    return 0;
 
114
}
 
115
#endif
 
116
 
 
117
/**************************************************************************
 
118
 *
 
119
 * Support for the character properties.
 
120
 *
 
121
 **************************************************************************/
 
122
 
 
123
#if !HARDCODE_DATA
 
124
 
 
125
static krb5_ui_4 _ucprop_size;
 
126
static krb5_ui_2 *_ucprop_offsets;
 
127
static krb5_ui_4 *_ucprop_ranges;
 
128
 
 
129
/*
 
130
 * Return -1 on error, 0 if okay
 
131
 */
 
132
static int
 
133
_ucprop_load(char *paths, int reload)
 
134
{
 
135
    FILE *in;
 
136
    krb5_ui_4 size, i;
 
137
    _ucheader_t hdr;
 
138
 
 
139
    if (_ucprop_size > 0) {
 
140
        if (!reload)
 
141
          /*
 
142
           * The character properties have already been loaded.
 
143
           */
 
144
          return 0;
 
145
 
 
146
        /*
 
147
         * Unload the current character property data in preparation for
 
148
         * loading a new copy.  Only the first array has to be deallocated
 
149
         * because all the memory for the arrays is allocated as a single
 
150
         * block.
 
151
         */
 
152
        free((char *) _ucprop_offsets);
 
153
        _ucprop_size = 0;
 
154
    }
 
155
 
 
156
    if ((in = _ucopenfile(paths, "ctype.dat", "rb")) == 0)
 
157
      return -1;
 
158
 
 
159
    /*
 
160
     * Load the header.
 
161
     */
 
162
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
163
 
 
164
    if (hdr.bom == 0xfffe) {
 
165
        hdr.cnt = endian_short(hdr.cnt);
 
166
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
167
    }
 
168
 
 
169
    if ((_ucprop_size = hdr.cnt) == 0) {
 
170
        fclose(in);
 
171
        return -1;
 
172
    }
 
173
 
 
174
    /*
 
175
     * Allocate all the storage needed for the lookup table.
 
176
     */
 
177
    _ucprop_offsets = (krb5_ui_2 *) malloc(hdr.size.bytes);
 
178
 
 
179
    /*
 
180
     * Calculate the offset into the storage for the ranges.  The offsets
 
181
     * array is on a 4-byte boundary and one larger than the value provided in
 
182
     * the header count field.  This means the offset to the ranges must be
 
183
     * calculated after aligning the count to a 4-byte boundary.
 
184
     */
 
185
    if ((size = ((hdr.cnt + 1) * sizeof(krb5_ui_2))) & 3)
 
186
      size += 4 - (size & 3);
 
187
    size >>= 1;
 
188
    _ucprop_ranges = (krb5_ui_4 *) (_ucprop_offsets + size);
 
189
 
 
190
    /*
 
191
     * Load the offset array.
 
192
     */
 
193
    fread((char *) _ucprop_offsets, sizeof(krb5_ui_2), size, in);
 
194
 
 
195
    /*
 
196
     * Do an endian swap if necessary.  Don't forget there is an extra node on
 
197
     * the end with the final index.
 
198
     */
 
199
    if (hdr.bom == 0xfffe) {
 
200
        for (i = 0; i <= _ucprop_size; i++)
 
201
          _ucprop_offsets[i] = endian_short(_ucprop_offsets[i]);
 
202
    }
 
203
 
 
204
    /*
 
205
     * Load the ranges.  The number of elements is in the last array position
 
206
     * of the offsets.
 
207
     */
 
208
    fread((char *) _ucprop_ranges, sizeof(krb5_ui_4),
 
209
          _ucprop_offsets[_ucprop_size], in);
 
210
 
 
211
    fclose(in);
 
212
 
 
213
    /*
 
214
     * Do an endian swap if necessary.
 
215
     */
 
216
    if (hdr.bom == 0xfffe) {
 
217
        for (i = 0; i < _ucprop_offsets[_ucprop_size]; i++)
 
218
          _ucprop_ranges[i] = endian_long(_ucprop_ranges[i]);
 
219
    }
 
220
    return 0;
 
221
}
 
222
 
 
223
static void
 
224
_ucprop_unload(void)
 
225
{
 
226
    if (_ucprop_size == 0)
 
227
      return;
 
228
 
 
229
    /*
 
230
     * Only need to free the offsets because the memory is allocated as a
 
231
     * single block.
 
232
     */
 
233
    free((char *) _ucprop_offsets);
 
234
    _ucprop_size = 0;
 
235
}
 
236
#endif
 
237
 
 
238
static int
 
239
_ucprop_lookup(krb5_ui_4 code, krb5_ui_4 n)
 
240
{
 
241
    long l, r, m;
 
242
 
 
243
    if (_ucprop_size == 0)
 
244
      return 0;
 
245
 
 
246
    /*
 
247
     * There is an extra node on the end of the offsets to allow this routine
 
248
     * to work right.  If the index is 0xffff, then there are no nodes for the
 
249
     * property.
 
250
     */
 
251
    if ((l = _ucprop_offsets[n]) == 0xffff)
 
252
      return 0;
 
253
 
 
254
    /*
 
255
     * Locate the next offset that is not 0xffff.  The sentinel at the end of
 
256
     * the array is the max index value.
 
257
     */
 
258
    for (m = 1;
 
259
         n + m < _ucprop_size && _ucprop_offsets[n + m] == 0xffff; m++) ;
 
260
 
 
261
    r = _ucprop_offsets[n + m] - 1;
 
262
 
 
263
    while (l <= r) {
 
264
        /*
 
265
         * Determine a "mid" point and adjust to make sure the mid point is at
 
266
         * the beginning of a range pair.
 
267
         */
 
268
        m = (l + r) >> 1;
 
269
        m -= (m & 1);
 
270
        if (code > _ucprop_ranges[m + 1])
 
271
          l = m + 2;
 
272
        else if (code < _ucprop_ranges[m])
 
273
          r = m - 2;
 
274
        else if (code >= _ucprop_ranges[m] && code <= _ucprop_ranges[m + 1])
 
275
          return 1;
 
276
    }
 
277
    return 0;
 
278
}
 
279
 
 
280
int
 
281
ucisprop(krb5_ui_4 code, krb5_ui_4 mask1, krb5_ui_4 mask2)
 
282
{
 
283
    krb5_ui_4 i;
 
284
 
 
285
    if (mask1 == 0 && mask2 == 0)
 
286
      return 0;
 
287
 
 
288
    for (i = 0; mask1 && i < 32; i++) {
 
289
        if ((mask1 & masks32[i]) && _ucprop_lookup(code, i))
 
290
          return 1;
 
291
    }
 
292
 
 
293
    for (i = 32; mask2 && i < _ucprop_size; i++) {
 
294
        if ((mask2 & masks32[i & 31]) && _ucprop_lookup(code, i))
 
295
          return 1;
 
296
    }
 
297
 
 
298
    return 0;
 
299
}
 
300
 
 
301
/**************************************************************************
 
302
 *
 
303
 * Support for case mapping.
 
304
 *
 
305
 **************************************************************************/
 
306
 
 
307
#if !HARDCODE_DATA
 
308
 
 
309
/* These record the number of slots in the map.
 
310
 * There are 3 words per slot.
 
311
 */
 
312
static krb5_ui_4 _uccase_size;
 
313
static krb5_ui_2 _uccase_len[2];
 
314
static krb5_ui_4 *_uccase_map;
 
315
 
 
316
/*
 
317
 * Return -1 on error, 0 if okay
 
318
 */
 
319
static int
 
320
_uccase_load(char *paths, int reload)
 
321
{
 
322
    FILE *in;
 
323
    krb5_ui_4 i;
 
324
    _ucheader_t hdr;
 
325
 
 
326
    if (_uccase_size > 0) {
 
327
        if (!reload)
 
328
          /*
 
329
           * The case mappings have already been loaded.
 
330
           */
 
331
          return 0;
 
332
 
 
333
        free((char *) _uccase_map);
 
334
        _uccase_size = 0;
 
335
    }
 
336
 
 
337
    if ((in = _ucopenfile(paths, "case.dat", "rb")) == 0)
 
338
      return -1;
 
339
 
 
340
    /*
 
341
     * Load the header.
 
342
     */
 
343
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
344
 
 
345
    if (hdr.bom == 0xfffe) {
 
346
        hdr.cnt = endian_short(hdr.cnt);
 
347
        hdr.size.len[0] = endian_short(hdr.size.len[0]);
 
348
        hdr.size.len[1] = endian_short(hdr.size.len[1]);
 
349
    }
 
350
 
 
351
    /*
 
352
     * Set the node count and lengths of the upper and lower case mapping
 
353
     * tables.
 
354
     */
 
355
    _uccase_size = hdr.cnt;
 
356
    _uccase_len[0] = hdr.size.len[0];
 
357
    _uccase_len[1] = hdr.size.len[1];
 
358
 
 
359
    _uccase_map = (krb5_ui_4 *)
 
360
        malloc(_uccase_size * 3 * sizeof(krb5_ui_4));
 
361
 
 
362
    /*
 
363
     * Load the case mapping table.
 
364
     */
 
365
    fread((char *) _uccase_map, sizeof(krb5_ui_4), _uccase_size * 3, in);
 
366
 
 
367
    /*
 
368
     * Do an endian swap if necessary.
 
369
     */
 
370
    if (hdr.bom == 0xfffe) {
 
371
        for (i = 0; i < _uccase_size * 3; i++)
 
372
          _uccase_map[i] = endian_long(_uccase_map[i]);
 
373
    }
 
374
    fclose(in);
 
375
    return 0;
 
376
}
 
377
 
 
378
static void
 
379
_uccase_unload(void)
 
380
{
 
381
    if (_uccase_size == 0)
 
382
      return;
 
383
 
 
384
    free((char *) _uccase_map);
 
385
    _uccase_size = 0;
 
386
}
 
387
#endif
 
388
 
 
389
static krb5_ui_4
 
390
_uccase_lookup(krb5_ui_4 code, long l, long r, int field)
 
391
{
 
392
    long m;
 
393
        const krb5_ui_4 *tmp;
 
394
 
 
395
    /*
 
396
     * Do the binary search.
 
397
     */
 
398
    while (l <= r) {
 
399
        /*
 
400
         * Determine a "mid" point and adjust to make sure the mid point is at
 
401
         * the beginning of a case mapping triple.
 
402
         */
 
403
        m = (l + r) >> 1;
 
404
                tmp = &_uccase_map[m*3];
 
405
        if (code > *tmp)
 
406
          l = m + 1;
 
407
        else if (code < *tmp)
 
408
          r = m - 1;
 
409
        else if (code == *tmp)
 
410
          return tmp[field];
 
411
    }
 
412
 
 
413
    return code;
 
414
}
 
415
 
 
416
krb5_ui_4
 
417
uctoupper(krb5_ui_4 code)
 
418
{
 
419
    int field;
 
420
    long l, r;
 
421
 
 
422
    if (ucisupper(code))
 
423
      return code;
 
424
 
 
425
    if (ucislower(code)) {
 
426
        /*
 
427
         * The character is lower case.
 
428
         */
 
429
        field = 2;
 
430
        l = _uccase_len[0];
 
431
        r = (l + _uccase_len[1]) - 1;
 
432
    } else {
 
433
        /*
 
434
         * The character is title case.
 
435
         */
 
436
        field = 1;
 
437
        l = _uccase_len[0] + _uccase_len[1];
 
438
        r = _uccase_size - 1;
 
439
    }
 
440
    return _uccase_lookup(code, l, r, field);
 
441
}
 
442
 
 
443
krb5_ui_4
 
444
uctolower(krb5_ui_4 code)
 
445
{
 
446
    int field;
 
447
    long l, r;
 
448
 
 
449
    if (ucislower(code))
 
450
      return code;
 
451
 
 
452
    if (ucisupper(code)) {
 
453
        /*
 
454
         * The character is upper case.
 
455
         */
 
456
        field = 1;
 
457
        l = 0;
 
458
        r = _uccase_len[0] - 1;
 
459
    } else {
 
460
        /*
 
461
         * The character is title case.
 
462
         */
 
463
        field = 2;
 
464
        l = _uccase_len[0] + _uccase_len[1];
 
465
        r = _uccase_size - 1;
 
466
    }
 
467
    return _uccase_lookup(code, l, r, field);
 
468
}
 
469
 
 
470
krb5_ui_4
 
471
uctotitle(krb5_ui_4 code)
 
472
{
 
473
    int field;
 
474
    long l, r;
 
475
 
 
476
    if (ucistitle(code))
 
477
      return code;
 
478
 
 
479
    /*
 
480
     * The offset will always be the same for converting to title case.
 
481
     */
 
482
    field = 2;
 
483
 
 
484
    if (ucisupper(code)) {
 
485
        /*
 
486
         * The character is upper case.
 
487
         */
 
488
        l = 0;
 
489
        r = _uccase_len[0] - 1;
 
490
    } else {
 
491
        /*
 
492
         * The character is lower case.
 
493
         */
 
494
        l = _uccase_len[0];
 
495
        r = (l + _uccase_len[1]) - 1;
 
496
    }
 
497
    return _uccase_lookup(code, l, r, field);
 
498
}
 
499
 
 
500
/**************************************************************************
 
501
 *
 
502
 * Support for compositions.
 
503
 *
 
504
 **************************************************************************/
 
505
 
 
506
#if !HARDCODE_DATA
 
507
 
 
508
static krb5_ui_4  _uccomp_size;
 
509
static krb5_ui_4 *_uccomp_data;
 
510
 
 
511
/*
 
512
 * Return -1 on error, 0 if okay
 
513
 */
 
514
static int
 
515
_uccomp_load(char *paths, int reload)
 
516
{
 
517
    FILE *in;
 
518
    krb5_ui_4 size, i;
 
519
    _ucheader_t hdr;
 
520
 
 
521
    if (_uccomp_size > 0) {
 
522
        if (!reload)
 
523
            /*
 
524
             * The compositions have already been loaded.
 
525
             */
 
526
            return 0;
 
527
 
 
528
        free((char *) _uccomp_data);
 
529
        _uccomp_size = 0;
 
530
    }
 
531
 
 
532
    if ((in = _ucopenfile(paths, "comp.dat", "rb")) == 0)
 
533
        return -1;
 
534
 
 
535
    /*
 
536
     * Load the header.
 
537
     */
 
538
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
539
 
 
540
    if (hdr.bom == 0xfffe) {
 
541
        hdr.cnt = endian_short(hdr.cnt);
 
542
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
543
    }
 
544
 
 
545
    _uccomp_size = hdr.cnt;
 
546
    _uccomp_data = (krb5_ui_4 *) malloc(hdr.size.bytes);
 
547
 
 
548
    /*
 
549
     * Read the composition data in.
 
550
     */
 
551
    size = hdr.size.bytes / sizeof(krb5_ui_4);
 
552
    fread((char *) _uccomp_data, sizeof(krb5_ui_4), size, in);
 
553
 
 
554
    /*
 
555
     * Do an endian swap if necessary.
 
556
     */
 
557
    if (hdr.bom == 0xfffe) {
 
558
        for (i = 0; i < size; i++)
 
559
            _uccomp_data[i] = endian_long(_uccomp_data[i]);
 
560
    }
 
561
 
 
562
    /*
 
563
     * Assume that the data is ordered on count, so that all compositions
 
564
     * of length 2 come first. Only handling length 2 for now.
 
565
     */
 
566
    for (i = 1; i < size; i += 4)
 
567
      if (_uccomp_data[i] != 2)
 
568
        break;
 
569
    _uccomp_size = i - 1;
 
570
 
 
571
    fclose(in);
 
572
    return 0;
 
573
}
 
574
 
 
575
static void
 
576
_uccomp_unload(void)
 
577
{
 
578
    if (_uccomp_size == 0)
 
579
        return;
 
580
 
 
581
    free((char *) _uccomp_data);
 
582
    _uccomp_size = 0;
 
583
}
 
584
#endif
 
585
 
 
586
int
 
587
uccomp(krb5_ui_4 node1, krb5_ui_4 node2, krb5_ui_4 *comp)
 
588
{
 
589
    int l, r, m;
 
590
 
 
591
    l = 0;
 
592
    r = _uccomp_size - 1;
 
593
 
 
594
    while (l <= r) {
 
595
        m = ((r + l) >> 1);
 
596
        m -= m & 3;
 
597
        if (node1 > _uccomp_data[m+2])
 
598
          l = m + 4;
 
599
        else if (node1 < _uccomp_data[m+2])
 
600
          r = m - 4;
 
601
        else if (node2 > _uccomp_data[m+3])
 
602
          l = m + 4;
 
603
        else if (node2 < _uccomp_data[m+3])
 
604
          r = m - 4;
 
605
        else {
 
606
            *comp = _uccomp_data[m];
 
607
            return 1;
 
608
        }
 
609
    }
 
610
    return 0;
 
611
}
 
612
 
 
613
int
 
614
uccomp_hangul(krb5_ui_4 *str, int len)
 
615
{
 
616
    const int SBase = 0xAC00, LBase = 0x1100,
 
617
        VBase = 0x1161, TBase = 0x11A7,
 
618
        LCount = 19, VCount = 21, TCount = 28,
 
619
        NCount = VCount * TCount,   /* 588 */
 
620
        SCount = LCount * NCount;   /* 11172 */
 
621
    
 
622
    int i, rlen;
 
623
    krb5_ui_4 ch, last, lindex, sindex;
 
624
 
 
625
    last = str[0];
 
626
    rlen = 1;
 
627
    for ( i = 1; i < len; i++ ) {
 
628
        ch = str[i];
 
629
 
 
630
        /* check if two current characters are L and V */
 
631
        lindex = last - LBase;
 
632
        if (lindex < (krb5_ui_4) LCount) {
 
633
            krb5_ui_4 vindex = ch - VBase;
 
634
            if (vindex < (krb5_ui_4) VCount) {
 
635
                /* make syllable of form LV */
 
636
                last = SBase + (lindex * VCount + vindex) * TCount;
 
637
                str[rlen-1] = last; /* reset last */
 
638
                continue;
 
639
            }
 
640
        }
 
641
        
 
642
        /* check if two current characters are LV and T */
 
643
        sindex = last - SBase;
 
644
        if (sindex < (krb5_ui_4) SCount
 
645
                        && (sindex % TCount) == 0)
 
646
                {
 
647
            krb5_ui_4 tindex = ch - TBase;
 
648
            if (tindex <= (krb5_ui_4) TCount) {
 
649
                /* make syllable of form LVT */
 
650
                last += tindex;
 
651
                str[rlen-1] = last; /* reset last */
 
652
                continue;
 
653
            }
 
654
        }
 
655
 
 
656
        /* if neither case was true, just add the character */
 
657
        last = ch;
 
658
        str[rlen] = ch;
 
659
        rlen++;
 
660
    }
 
661
    return rlen;
 
662
}
 
663
 
 
664
int
 
665
uccanoncomp(krb5_ui_4 *str, int len)
 
666
{
 
667
    int i, stpos, copos;
 
668
    krb5_ui_4 cl, prevcl, st, ch, co;
 
669
 
 
670
    st = str[0];
 
671
    stpos = 0;
 
672
    copos = 1;
 
673
    prevcl = uccombining_class(st) == 0 ? 0 : 256;
 
674
        
 
675
    for (i = 1; i < len; i++) {
 
676
        ch = str[i];
 
677
        cl = uccombining_class(ch);
 
678
        if (uccomp(st, ch, &co) && (prevcl < cl || prevcl == 0))
 
679
          st = str[stpos] = co;
 
680
        else {
 
681
            if (cl == 0) {
 
682
                stpos = copos;
 
683
                st = ch;
 
684
            }
 
685
            prevcl = cl;
 
686
            str[copos++] = ch;
 
687
        }
 
688
    }
 
689
 
 
690
    return uccomp_hangul(str, copos);
 
691
}
 
692
 
 
693
/**************************************************************************
 
694
 *
 
695
 * Support for decompositions.
 
696
 *
 
697
 **************************************************************************/
 
698
 
 
699
#if !HARDCODE_DATA
 
700
 
 
701
static krb5_ui_4  _ucdcmp_size;
 
702
static krb5_ui_4 *_ucdcmp_nodes;
 
703
static krb5_ui_4 *_ucdcmp_decomp;
 
704
 
 
705
static krb5_ui_4  _uckdcmp_size;
 
706
static krb5_ui_4 *_uckdcmp_nodes;
 
707
static krb5_ui_4 *_uckdcmp_decomp;
 
708
 
 
709
/*
 
710
 * Return -1 on error, 0 if okay
 
711
 */
 
712
static int
 
713
_ucdcmp_load(char *paths, int reload)
 
714
{
 
715
    FILE *in;
 
716
    krb5_ui_4 size, i;
 
717
    _ucheader_t hdr;
 
718
 
 
719
    if (_ucdcmp_size > 0) {
 
720
        if (!reload)
 
721
            /*
 
722
             * The decompositions have already been loaded.
 
723
             */
 
724
          return 0;
 
725
 
 
726
        free((char *) _ucdcmp_nodes);
 
727
        _ucdcmp_size = 0;
 
728
    }
 
729
 
 
730
    if ((in = _ucopenfile(paths, "decomp.dat", "rb")) == 0)
 
731
        return -1;
 
732
 
 
733
    /*
 
734
     * Load the header.
 
735
     */
 
736
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
737
 
 
738
    if (hdr.bom == 0xfffe) {
 
739
        hdr.cnt = endian_short(hdr.cnt);
 
740
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
741
    }
 
742
 
 
743
    _ucdcmp_size = hdr.cnt << 1;
 
744
    _ucdcmp_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
 
745
    _ucdcmp_decomp = _ucdcmp_nodes + (_ucdcmp_size + 1);
 
746
 
 
747
    /*
 
748
     * Read the decomposition data in.
 
749
     */
 
750
    size = hdr.size.bytes / sizeof(krb5_ui_4);
 
751
    fread((char *) _ucdcmp_nodes, sizeof(krb5_ui_4), size, in);
 
752
 
 
753
    /*
 
754
     * Do an endian swap if necessary.
 
755
     */
 
756
    if (hdr.bom == 0xfffe) {
 
757
        for (i = 0; i < size; i++)
 
758
            _ucdcmp_nodes[i] = endian_long(_ucdcmp_nodes[i]);
 
759
    }
 
760
    fclose(in);
 
761
    return 0;
 
762
}
 
763
 
 
764
/*
 
765
 * Return -1 on error, 0 if okay
 
766
 */
 
767
static int
 
768
_uckdcmp_load(char *paths, int reload)
 
769
{
 
770
    FILE *in;
 
771
    krb5_ui_4 size, i;
 
772
    _ucheader_t hdr;
 
773
 
 
774
    if (_uckdcmp_size > 0) {
 
775
        if (!reload)
 
776
            /*
 
777
             * The decompositions have already been loaded.
 
778
             */
 
779
          return 0;
 
780
 
 
781
        free((char *) _uckdcmp_nodes);
 
782
        _uckdcmp_size = 0;
 
783
    }
 
784
 
 
785
    if ((in = _ucopenfile(paths, "kdecomp.dat", "rb")) == 0)
 
786
        return -1;
 
787
 
 
788
    /*
 
789
     * Load the header.
 
790
     */
 
791
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
792
 
 
793
    if (hdr.bom == 0xfffe) {
 
794
        hdr.cnt = endian_short(hdr.cnt);
 
795
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
796
    }
 
797
 
 
798
    _uckdcmp_size = hdr.cnt << 1;
 
799
    _uckdcmp_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
 
800
    _uckdcmp_decomp = _uckdcmp_nodes + (_uckdcmp_size + 1);
 
801
 
 
802
    /*
 
803
     * Read the decomposition data in.
 
804
     */
 
805
    size = hdr.size.bytes / sizeof(krb5_ui_4);
 
806
    fread((char *) _uckdcmp_nodes, sizeof(krb5_ui_4), size, in);
 
807
 
 
808
    /*
 
809
     * Do an endian swap if necessary.
 
810
     */
 
811
    if (hdr.bom == 0xfffe) {
 
812
        for (i = 0; i < size; i++)
 
813
            _uckdcmp_nodes[i] = endian_long(_uckdcmp_nodes[i]);
 
814
    }
 
815
    fclose(in);
 
816
    return 0;
 
817
}
 
818
 
 
819
static void
 
820
_ucdcmp_unload(void)
 
821
{
 
822
    if (_ucdcmp_size == 0)
 
823
      return;
 
824
 
 
825
    /*
 
826
     * Only need to free the offsets because the memory is allocated as a
 
827
     * single block.
 
828
     */
 
829
    free((char *) _ucdcmp_nodes);
 
830
    _ucdcmp_size = 0;
 
831
}
 
832
 
 
833
static void
 
834
_uckdcmp_unload(void)
 
835
{
 
836
    if (_uckdcmp_size == 0)
 
837
      return;
 
838
 
 
839
    /*
 
840
     * Only need to free the offsets because the memory is allocated as a
 
841
     * single block.
 
842
     */
 
843
    free((char *) _uckdcmp_nodes);
 
844
    _uckdcmp_size = 0;
 
845
}
 
846
#endif
 
847
 
 
848
int
 
849
ucdecomp(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 **decomp)
 
850
{
 
851
    long l, r, m;
 
852
 
 
853
    if (code < _ucdcmp_nodes[0]) {
 
854
        return 0;
 
855
    }
 
856
 
 
857
    l = 0;
 
858
    r = _ucdcmp_nodes[_ucdcmp_size] - 1;
 
859
 
 
860
    while (l <= r) {
 
861
        /*
 
862
         * Determine a "mid" point and adjust to make sure the mid point is at
 
863
         * the beginning of a code+offset pair.
 
864
         */
 
865
        m = (l + r) >> 1;
 
866
        m -= (m & 1);
 
867
        if (code > _ucdcmp_nodes[m])
 
868
          l = m + 2;
 
869
        else if (code < _ucdcmp_nodes[m])
 
870
          r = m - 2;
 
871
        else if (code == _ucdcmp_nodes[m]) {
 
872
            *num = _ucdcmp_nodes[m + 3] - _ucdcmp_nodes[m + 1];
 
873
            *decomp = (krb5_ui_4*)&_ucdcmp_decomp[_ucdcmp_nodes[m + 1]];
 
874
            return 1;
 
875
        }
 
876
    }
 
877
    return 0;
 
878
}
 
879
 
 
880
int
 
881
uckdecomp(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 **decomp)
 
882
{
 
883
    long l, r, m;
 
884
 
 
885
    if (code < _uckdcmp_nodes[0]) {
 
886
        return 0;
 
887
    }
 
888
    
 
889
    l = 0;
 
890
    r = _uckdcmp_nodes[_uckdcmp_size] - 1;
 
891
 
 
892
    while (l <= r) {
 
893
        /*
 
894
         * Determine a "mid" point and adjust to make sure the mid point is at
 
895
         * the beginning of a code+offset pair.
 
896
         */
 
897
        m = (l + r) >> 1;
 
898
        m -= (m & 1);
 
899
        if (code > _uckdcmp_nodes[m])
 
900
          l = m + 2;
 
901
        else if (code < _uckdcmp_nodes[m])
 
902
          r = m - 2;
 
903
        else if (code == _uckdcmp_nodes[m]) {
 
904
            *num = _uckdcmp_nodes[m + 3] - _uckdcmp_nodes[m + 1];
 
905
            *decomp = (krb5_ui_4*)&_uckdcmp_decomp[_uckdcmp_nodes[m + 1]];
 
906
            return 1;
 
907
        }
 
908
    }
 
909
    return 0;
 
910
}
 
911
 
 
912
int
 
913
ucdecomp_hangul(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 decomp[])
 
914
{
 
915
    if (!ucishangul(code))
 
916
      return 0;
 
917
 
 
918
    code -= 0xac00;
 
919
    decomp[0] = 0x1100 + (krb5_ui_4) (code / 588);
 
920
    decomp[1] = 0x1161 + (krb5_ui_4) ((code % 588) / 28);
 
921
    decomp[2] = 0x11a7 + (krb5_ui_4) (code % 28);
 
922
    *num = (decomp[2] != 0x11a7) ? 3 : 2;
 
923
 
 
924
    return 1;
 
925
}
 
926
 
 
927
/* mode == 0 for canonical, mode == 1 for compatibility */
 
928
static int
 
929
uccanoncompatdecomp(const krb5_ui_4 *in, int inlen,
 
930
                    krb5_ui_4 **out, int *outlen, short mode)
 
931
{
 
932
    int l, size;
 
933
        unsigned i, j, k;
 
934
    krb5_ui_4 num, class, *decomp, hangdecomp[3];
 
935
 
 
936
    size = inlen * 2;
 
937
    *out = (krb5_ui_4 *) malloc(size * sizeof(**out));
 
938
    if (*out == NULL)
 
939
        return *outlen = -1;
 
940
 
 
941
    i = 0;
 
942
    for (j = 0; j < (unsigned) inlen; j++) {
 
943
        if (mode ? uckdecomp(in[j], &num, &decomp) : ucdecomp(in[j], &num, &decomp)) {
 
944
            if ( size - i < num) {
 
945
                size = inlen + i - j + num - 1;
 
946
                *out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
 
947
                if (*out == NULL)
 
948
                    return *outlen = -1;
 
949
            }
 
950
            for (k = 0; k < num; k++) {
 
951
                class = uccombining_class(decomp[k]);
 
952
                if (class == 0) {
 
953
                    (*out)[i] = decomp[k];
 
954
                } else {
 
955
                    for (l = i; l > 0; l--)
 
956
                        if (class >= uccombining_class((*out)[l-1]))
 
957
                            break;
 
958
                    memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out));
 
959
                    (*out)[l] = decomp[k];
 
960
                }
 
961
                i++;
 
962
            }
 
963
        } else if (ucdecomp_hangul(in[j], &num, hangdecomp)) {
 
964
            if (size - i < num) {
 
965
                size = inlen + i - j + num - 1;
 
966
                *out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
 
967
                if (*out == NULL)
 
968
                    return *outlen = -1;
 
969
            }
 
970
            for (k = 0; k < num; k++) {
 
971
                (*out)[i] = hangdecomp[k];
 
972
                i++;
 
973
            }
 
974
        } else {
 
975
            if (size - i < 1) {
 
976
                size = inlen + i - j;
 
977
                *out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
 
978
                if (*out == NULL)
 
979
                    return *outlen = -1;
 
980
            }
 
981
            class = uccombining_class(in[j]);
 
982
            if (class == 0) {
 
983
                (*out)[i] = in[j];
 
984
            } else {
 
985
                for (l = i; l > 0; l--)
 
986
                    if (class >= uccombining_class((*out)[l-1]))
 
987
                        break;
 
988
                memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out));
 
989
                (*out)[l] = in[j];
 
990
            }
 
991
            i++;
 
992
        }
 
993
    }
 
994
    return *outlen = i;
 
995
}
 
996
 
 
997
int
 
998
uccanondecomp(const krb5_ui_4 *in, int inlen,
 
999
              krb5_ui_4 **out, int *outlen)
 
1000
{
 
1001
    return uccanoncompatdecomp(in, inlen, out, outlen, 0);
 
1002
}
 
1003
 
 
1004
int
 
1005
uccompatdecomp(const krb5_ui_4 *in, int inlen,
 
1006
               krb5_ui_4 **out, int *outlen)
 
1007
{
 
1008
    return uccanoncompatdecomp(in, inlen, out, outlen, 1);
 
1009
}
 
1010
 
 
1011
/**************************************************************************
 
1012
 *
 
1013
 * Support for combining classes.
 
1014
 *
 
1015
 **************************************************************************/
 
1016
 
 
1017
#if !HARDCODE_DATA
 
1018
static krb5_ui_4  _uccmcl_size;
 
1019
static krb5_ui_4 *_uccmcl_nodes;
 
1020
 
 
1021
/*
 
1022
 * Return -1 on error, 0 if okay
 
1023
 */
 
1024
static int
 
1025
_uccmcl_load(char *paths, int reload)
 
1026
{
 
1027
    FILE *in;
 
1028
    krb5_ui_4 i;
 
1029
    _ucheader_t hdr;
 
1030
 
 
1031
    if (_uccmcl_size > 0) {
 
1032
        if (!reload)
 
1033
            /*
 
1034
             * The combining classes have already been loaded.
 
1035
             */
 
1036
            return 0;
 
1037
 
 
1038
        free((char *) _uccmcl_nodes);
 
1039
        _uccmcl_size = 0;
 
1040
    }
 
1041
 
 
1042
    if ((in = _ucopenfile(paths, "cmbcl.dat", "rb")) == 0)
 
1043
        return -1;
 
1044
 
 
1045
    /*
 
1046
     * Load the header.
 
1047
     */
 
1048
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
1049
 
 
1050
    if (hdr.bom == 0xfffe) {
 
1051
        hdr.cnt = endian_short(hdr.cnt);
 
1052
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
1053
    }
 
1054
 
 
1055
    _uccmcl_size = hdr.cnt * 3;
 
1056
    _uccmcl_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
 
1057
 
 
1058
    /*
 
1059
     * Read the combining classes in.
 
1060
     */
 
1061
    fread((char *) _uccmcl_nodes, sizeof(krb5_ui_4), _uccmcl_size, in);
 
1062
 
 
1063
    /*
 
1064
     * Do an endian swap if necessary.
 
1065
     */
 
1066
    if (hdr.bom == 0xfffe) {
 
1067
        for (i = 0; i < _uccmcl_size; i++)
 
1068
            _uccmcl_nodes[i] = endian_long(_uccmcl_nodes[i]);
 
1069
    }
 
1070
    fclose(in);
 
1071
    return 0;
 
1072
}
 
1073
 
 
1074
static void
 
1075
_uccmcl_unload(void)
 
1076
{
 
1077
    if (_uccmcl_size == 0)
 
1078
      return;
 
1079
 
 
1080
    free((char *) _uccmcl_nodes);
 
1081
    _uccmcl_size = 0;
 
1082
}
 
1083
#endif
 
1084
 
 
1085
krb5_ui_4
 
1086
uccombining_class(krb5_ui_4 code)
 
1087
{
 
1088
    long l, r, m;
 
1089
 
 
1090
    l = 0;
 
1091
    r = _uccmcl_size - 1;
 
1092
 
 
1093
    while (l <= r) {
 
1094
        m = (l + r) >> 1;
 
1095
        m -= (m % 3);
 
1096
        if (code > _uccmcl_nodes[m + 1])
 
1097
          l = m + 3;
 
1098
        else if (code < _uccmcl_nodes[m])
 
1099
          r = m - 3;
 
1100
        else if (code >= _uccmcl_nodes[m] && code <= _uccmcl_nodes[m + 1])
 
1101
          return _uccmcl_nodes[m + 2];
 
1102
    }
 
1103
    return 0;
 
1104
}
 
1105
 
 
1106
/**************************************************************************
 
1107
 *
 
1108
 * Support for numeric values.
 
1109
 *
 
1110
 **************************************************************************/
 
1111
 
 
1112
#if !HARDCODE_DATA
 
1113
static krb5_ui_4 *_ucnum_nodes;
 
1114
static krb5_ui_4 _ucnum_size;
 
1115
static short *_ucnum_vals;
 
1116
 
 
1117
/*
 
1118
 * Return -1 on error, 0 if okay
 
1119
 */
 
1120
static int
 
1121
_ucnumb_load(char *paths, int reload)
 
1122
{
 
1123
    FILE *in;
 
1124
    krb5_ui_4 size, i;
 
1125
    _ucheader_t hdr;
 
1126
 
 
1127
    if (_ucnum_size > 0) {
 
1128
        if (!reload)
 
1129
          /*
 
1130
           * The numbers have already been loaded.
 
1131
           */
 
1132
          return 0;
 
1133
 
 
1134
        free((char *) _ucnum_nodes);
 
1135
        _ucnum_size = 0;
 
1136
    }
 
1137
 
 
1138
    if ((in = _ucopenfile(paths, "num.dat", "rb")) == 0)
 
1139
      return -1;
 
1140
 
 
1141
    /*
 
1142
     * Load the header.
 
1143
     */
 
1144
    fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
 
1145
 
 
1146
    if (hdr.bom == 0xfffe) {
 
1147
        hdr.cnt = endian_short(hdr.cnt);
 
1148
        hdr.size.bytes = endian_long(hdr.size.bytes);
 
1149
    }
 
1150
 
 
1151
    _ucnum_size = hdr.cnt;
 
1152
    _ucnum_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
 
1153
    _ucnum_vals = (short *) (_ucnum_nodes + _ucnum_size);
 
1154
 
 
1155
    /*
 
1156
     * Read the combining classes in.
 
1157
     */
 
1158
    fread((char *) _ucnum_nodes, sizeof(unsigned char), hdr.size.bytes, in);
 
1159
 
 
1160
    /*
 
1161
     * Do an endian swap if necessary.
 
1162
     */
 
1163
    if (hdr.bom == 0xfffe) {
 
1164
        for (i = 0; i < _ucnum_size; i++)
 
1165
          _ucnum_nodes[i] = endian_long(_ucnum_nodes[i]);
 
1166
 
 
1167
        /*
 
1168
         * Determine the number of values that have to be adjusted.
 
1169
         */
 
1170
        size = (hdr.size.bytes -
 
1171
                (_ucnum_size * (sizeof(krb5_ui_4) << 1))) /
 
1172
            sizeof(short);
 
1173
 
 
1174
        for (i = 0; i < size; i++)
 
1175
          _ucnum_vals[i] = endian_short(_ucnum_vals[i]);
 
1176
    }
 
1177
    fclose(in);
 
1178
    return 0;
 
1179
}
 
1180
 
 
1181
static void
 
1182
_ucnumb_unload(void)
 
1183
{
 
1184
    if (_ucnum_size == 0)
 
1185
      return;
 
1186
 
 
1187
    free((char *) _ucnum_nodes);
 
1188
    _ucnum_size = 0;
 
1189
}
 
1190
#endif
 
1191
 
 
1192
int
 
1193
ucnumber_lookup(krb5_ui_4 code, struct ucnumber *num)
 
1194
{
 
1195
    long l, r, m;
 
1196
    short *vp;
 
1197
 
 
1198
    l = 0;
 
1199
    r = _ucnum_size - 1;
 
1200
    while (l <= r) {
 
1201
        /*
 
1202
         * Determine a "mid" point and adjust to make sure the mid point is at
 
1203
         * the beginning of a code+offset pair.
 
1204
         */
 
1205
        m = (l + r) >> 1;
 
1206
        m -= (m & 1);
 
1207
        if (code > _ucnum_nodes[m])
 
1208
          l = m + 2;
 
1209
        else if (code < _ucnum_nodes[m])
 
1210
          r = m - 2;
 
1211
        else {
 
1212
            vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1];
 
1213
            num->numerator = (int) *vp++;
 
1214
            num->denominator = (int) *vp;
 
1215
            return 1;
 
1216
        }
 
1217
    }
 
1218
    return 0;
 
1219
}
 
1220
 
 
1221
int
 
1222
ucdigit_lookup(krb5_ui_4 code, int *digit)
 
1223
{
 
1224
    long l, r, m;
 
1225
    short *vp;
 
1226
 
 
1227
    l = 0;
 
1228
    r = _ucnum_size - 1;
 
1229
    while (l <= r) {
 
1230
        /*
 
1231
         * Determine a "mid" point and adjust to make sure the mid point is at
 
1232
         * the beginning of a code+offset pair.
 
1233
         */
 
1234
        m = (l + r) >> 1;
 
1235
        m -= (m & 1);
 
1236
        if (code > _ucnum_nodes[m])
 
1237
          l = m + 2;
 
1238
        else if (code < _ucnum_nodes[m])
 
1239
          r = m - 2;
 
1240
        else {
 
1241
            vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1];
 
1242
            if (*vp == *(vp + 1)) {
 
1243
              *digit = *vp;
 
1244
              return 1;
 
1245
            }
 
1246
            return 0;
 
1247
        }
 
1248
    }
 
1249
    return 0;
 
1250
}
 
1251
 
 
1252
struct ucnumber
 
1253
ucgetnumber(krb5_ui_4 code)
 
1254
{
 
1255
    struct ucnumber num;
 
1256
 
 
1257
    /*
 
1258
     * Initialize with some arbitrary value, because the caller simply cannot
 
1259
     * tell for sure if the code is a number without calling the ucisnumber()
 
1260
     * macro before calling this function.
 
1261
     */
 
1262
    num.numerator = num.denominator = -111;
 
1263
 
 
1264
    (void) ucnumber_lookup(code, &num);
 
1265
 
 
1266
    return num;
 
1267
}
 
1268
 
 
1269
int
 
1270
ucgetdigit(krb5_ui_4 code)
 
1271
{
 
1272
    int dig;
 
1273
 
 
1274
    /*
 
1275
     * Initialize with some arbitrary value, because the caller simply cannot
 
1276
     * tell for sure if the code is a number without calling the ucisdigit()
 
1277
     * macro before calling this function.
 
1278
     */
 
1279
    dig = -111;
 
1280
 
 
1281
    (void) ucdigit_lookup(code, &dig);
 
1282
 
 
1283
    return dig;
 
1284
}
 
1285
 
 
1286
/**************************************************************************
 
1287
 *
 
1288
 * Setup and cleanup routines.
 
1289
 *
 
1290
 **************************************************************************/
 
1291
 
 
1292
#if HARDCODE_DATA
 
1293
int ucdata_load(char *paths, int masks) { return 0; }
 
1294
void ucdata_unload(int masks) { }
 
1295
int ucdata_reload(char *paths, int masks) { return 0; }
 
1296
#else
 
1297
/*
 
1298
 * Return 0 if okay, negative on error
 
1299
 */
 
1300
int
 
1301
ucdata_load(char *paths, int masks)
 
1302
{
 
1303
    int error = 0;
 
1304
 
 
1305
    if (masks & UCDATA_CTYPE)
 
1306
      error |= _ucprop_load(paths, 0) < 0 ? UCDATA_CTYPE : 0;
 
1307
    if (masks & UCDATA_CASE)
 
1308
      error |= _uccase_load(paths, 0) < 0 ? UCDATA_CASE : 0;
 
1309
    if (masks & UCDATA_DECOMP)
 
1310
      error |= _ucdcmp_load(paths, 0) < 0 ? UCDATA_DECOMP : 0;
 
1311
    if (masks & UCDATA_CMBCL)
 
1312
      error |= _uccmcl_load(paths, 0) < 0 ? UCDATA_CMBCL : 0;
 
1313
    if (masks & UCDATA_NUM)
 
1314
      error |= _ucnumb_load(paths, 0) < 0 ? UCDATA_NUM : 0;
 
1315
    if (masks & UCDATA_COMP)
 
1316
      error |= _uccomp_load(paths, 0) < 0 ? UCDATA_COMP : 0;
 
1317
    if (masks & UCDATA_KDECOMP)
 
1318
      error |= _uckdcmp_load(paths, 0) < 0 ? UCDATA_KDECOMP : 0;
 
1319
 
 
1320
    return -error;
 
1321
}
 
1322
 
 
1323
void
 
1324
ucdata_unload(int masks)
 
1325
{
 
1326
    if (masks & UCDATA_CTYPE)
 
1327
      _ucprop_unload();
 
1328
    if (masks & UCDATA_CASE)
 
1329
      _uccase_unload();
 
1330
    if (masks & UCDATA_DECOMP)
 
1331
      _ucdcmp_unload();
 
1332
    if (masks & UCDATA_CMBCL)
 
1333
      _uccmcl_unload();
 
1334
    if (masks & UCDATA_NUM)
 
1335
      _ucnumb_unload();
 
1336
    if (masks & UCDATA_COMP)
 
1337
      _uccomp_unload();
 
1338
    if (masks & UCDATA_KDECOMP)
 
1339
      _uckdcmp_unload();
 
1340
}
 
1341
 
 
1342
/*
 
1343
 * Return 0 if okay, negative on error
 
1344
 */
 
1345
int
 
1346
ucdata_reload(char *paths, int masks)
 
1347
{
 
1348
    int error = 0;
 
1349
 
 
1350
    if (masks & UCDATA_CTYPE)
 
1351
        error |= _ucprop_load(paths, 1) < 0 ? UCDATA_CTYPE : 0;
 
1352
    if (masks & UCDATA_CASE)
 
1353
        error |= _uccase_load(paths, 1) < 0 ? UCDATA_CASE : 0;
 
1354
    if (masks & UCDATA_DECOMP)
 
1355
        error |= _ucdcmp_load(paths, 1) < 0 ? UCDATA_DECOMP : 0;
 
1356
    if (masks & UCDATA_CMBCL)
 
1357
        error |= _uccmcl_load(paths, 1) < 0 ? UCDATA_CMBCL : 0;
 
1358
    if (masks & UCDATA_NUM)
 
1359
        error |= _ucnumb_load(paths, 1) < 0 ? UCDATA_NUM : 0;
 
1360
    if (masks & UCDATA_COMP)
 
1361
        error |= _uccomp_load(paths, 1) < 0 ? UCDATA_COMP : 0;
 
1362
    if (masks & UCDATA_KDECOMP)
 
1363
        error |= _uckdcmp_load(paths, 1) < 0 ? UCDATA_KDECOMP : 0;
 
1364
 
 
1365
    return -error;
 
1366
}
 
1367
#endif
 
1368
 
 
1369
#ifdef TEST
 
1370
 
 
1371
void
 
1372
main(void)
 
1373
{
 
1374
    int dig;
 
1375
    krb5_ui_4 i, lo, *dec;
 
1376
    struct ucnumber num;
 
1377
 
 
1378
/*    ucdata_setup("."); */
 
1379
 
 
1380
    if (ucisweak(0x30))
 
1381
      printf("WEAK\n");
 
1382
    else
 
1383
      printf("NOT WEAK\n");
 
1384
 
 
1385
    printf("LOWER 0x%04lX\n", uctolower(0xff3a));
 
1386
    printf("UPPER 0x%04lX\n", uctoupper(0xff5a));
 
1387
 
 
1388
    if (ucisalpha(0x1d5))
 
1389
      printf("ALPHA\n");
 
1390
    else
 
1391
      printf("NOT ALPHA\n");
 
1392
 
 
1393
    if (ucisupper(0x1d5)) {
 
1394
        printf("UPPER\n");
 
1395
        lo = uctolower(0x1d5);
 
1396
        printf("0x%04lx\n", lo);
 
1397
        lo = uctotitle(0x1d5);
 
1398
        printf("0x%04lx\n", lo);
 
1399
    } else
 
1400
      printf("NOT UPPER\n");
 
1401
 
 
1402
    if (ucistitle(0x1d5))
 
1403
      printf("TITLE\n");
 
1404
    else
 
1405
      printf("NOT TITLE\n");
 
1406
 
 
1407
    if (uciscomposite(0x1d5))
 
1408
      printf("COMPOSITE\n");
 
1409
    else
 
1410
      printf("NOT COMPOSITE\n");
 
1411
 
 
1412
    if (ucdecomp(0x1d5, &lo, &dec)) {
 
1413
        for (i = 0; i < lo; i++)
 
1414
          printf("0x%04lx ", dec[i]);
 
1415
        putchar('\n');
 
1416
    }
 
1417
 
 
1418
    if ((lo = uccombining_class(0x41)) != 0)
 
1419
      printf("0x41 CCL %ld\n", lo);
 
1420
 
 
1421
    if (ucisxdigit(0xfeff))
 
1422
      printf("0xFEFF HEX DIGIT\n");
 
1423
    else
 
1424
      printf("0xFEFF NOT HEX DIGIT\n");
 
1425
 
 
1426
    if (ucisdefined(0x10000))
 
1427
      printf("0x10000 DEFINED\n");
 
1428
    else
 
1429
      printf("0x10000 NOT DEFINED\n");
 
1430
 
 
1431
    if (ucnumber_lookup(0x30, &num)) {
 
1432
        if (num.denominator != 1)
 
1433
          printf("UCNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator);
 
1434
        else
 
1435
          printf("UCNUMBER: 0x30 = %d\n", num.numerator);
 
1436
    } else
 
1437
      printf("UCNUMBER: 0x30 NOT A NUMBER\n");
 
1438
 
 
1439
    if (ucnumber_lookup(0xbc, &num)) {
 
1440
        if (num.denominator != 1)
 
1441
          printf("UCNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator);
 
1442
        else
 
1443
          printf("UCNUMBER: 0xbc = %d\n", num.numerator);
 
1444
    } else
 
1445
      printf("UCNUMBER: 0xbc NOT A NUMBER\n");
 
1446
 
 
1447
 
 
1448
    if (ucnumber_lookup(0xff19, &num)) {
 
1449
        if (num.denominator != 1)
 
1450
          printf("UCNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator);
 
1451
        else
 
1452
          printf("UCNUMBER: 0xff19 = %d\n", num.numerator);
 
1453
    } else
 
1454
      printf("UCNUMBER: 0xff19 NOT A NUMBER\n");
 
1455
 
 
1456
    if (ucnumber_lookup(0x4e00, &num)) {
 
1457
        if (num.denominator != 1)
 
1458
          printf("UCNUMBER: 0x4e00 = %d/%d\n", num.numerator, num.denominator);
 
1459
        else
 
1460
          printf("UCNUMBER: 0x4e00 = %d\n", num.numerator);
 
1461
    } else
 
1462
      printf("UCNUMBER: 0x4e00 NOT A NUMBER\n");
 
1463
 
 
1464
    if (ucdigit_lookup(0x06f9, &dig))
 
1465
      printf("UCDIGIT: 0x6f9 = %d\n", dig);
 
1466
    else
 
1467
      printf("UCDIGIT: 0x6f9 NOT A NUMBER\n");
 
1468
 
 
1469
    dig = ucgetdigit(0x0969);
 
1470
    printf("UCGETDIGIT: 0x969 = %d\n", dig);
 
1471
 
 
1472
    num = ucgetnumber(0x30);
 
1473
    if (num.denominator != 1)
 
1474
      printf("UCGETNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator);
 
1475
    else
 
1476
      printf("UCGETNUMBER: 0x30 = %d\n", num.numerator);
 
1477
 
 
1478
    num = ucgetnumber(0xbc);
 
1479
    if (num.denominator != 1)
 
1480
      printf("UCGETNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator);
 
1481
    else
 
1482
      printf("UCGETNUMBER: 0xbc = %d\n", num.numerator);
 
1483
 
 
1484
    num = ucgetnumber(0xff19);
 
1485
    if (num.denominator != 1)
 
1486
      printf("UCGETNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator);
 
1487
    else
 
1488
      printf("UCGETNUMBER: 0xff19 = %d\n", num.numerator);
 
1489
 
 
1490
/*    ucdata_cleanup(); */
 
1491
    exit(0);
 
1492
}
 
1493
 
 
1494
#endif /* TEST */