]> git.sur5r.net Git - openldap/blob - libraries/liblunicode/ucdata/ucgendat.c
7403a1dd81a7a11a3d92db1779ba9e80545c1b15
[openldap] / libraries / liblunicode / ucdata / ucgendat.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2004 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: ucgendat.c,v 1.4 2001/01/02 18:46:20 mleisher Exp $" */
36
37 #include "portable.h"
38 #include "ldap_config.h"
39
40 #include <stdio.h>
41 #include <ac/stdlib.h>
42 #include <ac/string.h>
43 #include <ac/unistd.h>
44
45 #include <ac/bytes.h>
46
47 #include <lutil.h>
48
49 #ifndef HARDCODE_DATA
50 #define HARDCODE_DATA   1
51 #endif
52
53 #undef ishdigit
54 #define ishdigit(cc) (((cc) >= '0' && (cc) <= '9') ||\
55                       ((cc) >= 'A' && (cc) <= 'F') ||\
56                       ((cc) >= 'a' && (cc) <= 'f'))
57
58 /*
59  * A header written to the output file with the byte-order-mark and the number
60  * of property nodes.
61  */
62 static ac_uint2 hdr[2] = {0xfeff, 0};
63
64 #define NUMPROPS 50
65 #define NEEDPROPS (NUMPROPS + (4 - (NUMPROPS & 3)))
66
67 typedef struct {
68     char *name;
69     int len;
70 } _prop_t;
71
72 /*
73  * List of properties expected to be found in the Unicode Character Database
74  * including some implementation specific properties.
75  *
76  * The implementation specific properties are:
77  * Cm = Composed (can be decomposed)
78  * Nb = Non-breaking
79  * Sy = Symmetric (has left and right forms)
80  * Hd = Hex digit
81  * Qm = Quote marks
82  * Mr = Mirroring
83  * Ss = Space, other
84  * Cp = Defined character
85  */
86 static _prop_t props[NUMPROPS] = {
87     {"Mn", 2}, {"Mc", 2}, {"Me", 2}, {"Nd", 2}, {"Nl", 2}, {"No", 2},
88     {"Zs", 2}, {"Zl", 2}, {"Zp", 2}, {"Cc", 2}, {"Cf", 2}, {"Cs", 2},
89     {"Co", 2}, {"Cn", 2}, {"Lu", 2}, {"Ll", 2}, {"Lt", 2}, {"Lm", 2},
90     {"Lo", 2}, {"Pc", 2}, {"Pd", 2}, {"Ps", 2}, {"Pe", 2}, {"Po", 2},
91     {"Sm", 2}, {"Sc", 2}, {"Sk", 2}, {"So", 2}, {"L",  1}, {"R",  1},
92     {"EN", 2}, {"ES", 2}, {"ET", 2}, {"AN", 2}, {"CS", 2}, {"B",  1},
93     {"S",  1}, {"WS", 2}, {"ON", 2},
94     {"Cm", 2}, {"Nb", 2}, {"Sy", 2}, {"Hd", 2}, {"Qm", 2}, {"Mr", 2},
95     {"Ss", 2}, {"Cp", 2}, {"Pi", 2}, {"Pf", 2}, {"AL", 2}
96 };
97
98 typedef struct {
99     ac_uint4 *ranges;
100     ac_uint2 used;
101     ac_uint2 size;
102 } _ranges_t;
103
104 static _ranges_t proptbl[NUMPROPS];
105
106 /*
107  * Make sure this array is sized to be on a 4-byte boundary at compile time.
108  */
109 static ac_uint2 propcnt[NEEDPROPS];
110
111 /*
112  * Array used to collect a decomposition before adding it to the decomposition
113  * table.
114  */
115 static ac_uint4 dectmp[64];
116 static ac_uint4 dectmp_size;
117
118 typedef struct {
119     ac_uint4 code;
120     ac_uint2 size;
121     ac_uint2 used;
122     ac_uint4 *decomp;
123 } _decomp_t;
124
125 /*
126  * List of decomposition.  Created and expanded in order as the characters are
127  * encountered. First list contains canonical mappings, second also includes
128  * compatibility mappings.
129  */
130 static _decomp_t *decomps;
131 static ac_uint4 decomps_used;
132 static ac_uint4 decomps_size;
133
134 static _decomp_t *kdecomps;
135 static ac_uint4 kdecomps_used;
136 static ac_uint4 kdecomps_size;
137
138 /*
139  * Composition exclusion table stuff.
140  */
141 #define COMPEX_SET(c) (compexs[(c) >> 5] |= (1 << ((c) & 31)))
142 #define COMPEX_TEST(c) (compexs[(c) >> 5] & (1 << ((c) & 31)))
143 static ac_uint4 compexs[2048];
144
145 /*
146  * Struct for holding a composition pair, and array of composition pairs
147  */
148 typedef struct {
149     ac_uint4 comp;
150     ac_uint4 count;
151     ac_uint4 code1;
152     ac_uint4 code2;
153 } _comp_t;
154
155 static _comp_t *comps;
156 static ac_uint4 comps_used;
157
158 /*
159  * Types and lists for handling lists of case mappings.
160  */
161 typedef struct {
162     ac_uint4 key;
163     ac_uint4 other1;
164     ac_uint4 other2;
165 } _case_t;
166
167 static _case_t *upper;
168 static _case_t *lower;
169 static _case_t *title;
170 static ac_uint4 upper_used;
171 static ac_uint4 upper_size;
172 static ac_uint4 lower_used;
173 static ac_uint4 lower_size;
174 static ac_uint4 title_used;
175 static ac_uint4 title_size;
176
177 /*
178  * Array used to collect case mappings before adding them to a list.
179  */
180 static ac_uint4 cases[3];
181
182 /*
183  * An array to hold ranges for combining classes.
184  */
185 static ac_uint4 *ccl;
186 static ac_uint4 ccl_used;
187 static ac_uint4 ccl_size;
188
189 /*
190  * Structures for handling numbers.
191  */
192 typedef struct {
193     ac_uint4 code;
194     ac_uint4 idx;
195 } _codeidx_t;
196
197 typedef struct {
198     short numerator;
199     short denominator;
200 } _num_t;
201
202 /*
203  * Arrays to hold the mapping of codes to numbers.
204  */
205 static _codeidx_t *ncodes;
206 static ac_uint4 ncodes_used;
207 static ac_uint4 ncodes_size;
208
209 static _num_t *nums;
210 static ac_uint4 nums_used;
211 static ac_uint4 nums_size;
212
213 /*
214  * Array for holding numbers.
215  */
216 static _num_t *nums;
217 static ac_uint4 nums_used;
218 static ac_uint4 nums_size;
219
220 static void
221 add_range(ac_uint4 start, ac_uint4 end, char *p1, char *p2)
222 {
223     int i, j, k, len;
224     _ranges_t *rlp;
225     char *name;
226
227     for (k = 0; k < 2; k++) {
228         if (k == 0) {
229             name = p1;
230             len = 2;
231         } else {
232             if (p2 == 0)
233               break;
234
235             name = p2;
236             len = 1;
237         }
238
239         for (i = 0; i < NUMPROPS; i++) {
240             if (props[i].len == len && memcmp(props[i].name, name, len) == 0)
241               break;
242         }
243
244         if (i == NUMPROPS)
245           continue;
246
247         rlp = &proptbl[i];
248
249         /*
250          * Resize the range list if necessary.
251          */
252         if (rlp->used == rlp->size) {
253             if (rlp->size == 0)
254               rlp->ranges = (ac_uint4 *)
255                   malloc(sizeof(ac_uint4) << 3);
256             else
257               rlp->ranges = (ac_uint4 *)
258                   realloc((char *) rlp->ranges,
259                           sizeof(ac_uint4) * (rlp->size + 8));
260             rlp->size += 8;
261         }
262
263         /*
264          * If this is the first code for this property list, just add it
265          * and return.
266          */
267         if (rlp->used == 0) {
268             rlp->ranges[0] = start;
269             rlp->ranges[1] = end;
270             rlp->used += 2;
271             continue;
272         }
273
274         /*
275          * Optimize the case of adding the range to the end.
276          */
277         j = rlp->used - 1;
278         if (start > rlp->ranges[j]) {
279             j = rlp->used;
280             rlp->ranges[j++] = start;
281             rlp->ranges[j++] = end;
282             rlp->used = j;
283             continue;
284         }
285
286         /*
287          * Need to locate the insertion point.
288          */
289         for (i = 0;
290              i < rlp->used && start > rlp->ranges[i + 1] + 1; i += 2) ;
291
292         /*
293          * If the start value lies in the current range, then simply set the
294          * new end point of the range to the end value passed as a parameter.
295          */
296         if (rlp->ranges[i] <= start && start <= rlp->ranges[i + 1] + 1) {
297             rlp->ranges[i + 1] = end;
298             return;
299         }
300
301         /*
302          * Shift following values up by two.
303          */
304         for (j = rlp->used; j > i; j -= 2) {
305             rlp->ranges[j] = rlp->ranges[j - 2];
306             rlp->ranges[j + 1] = rlp->ranges[j - 1];
307         }
308
309         /*
310          * Add the new range at the insertion point.
311          */
312         rlp->ranges[i] = start;
313         rlp->ranges[i + 1] = end;
314         rlp->used += 2;
315     }
316 }
317
318 static void
319 ordered_range_insert(ac_uint4 c, char *name, int len)
320 {
321     int i, j;
322     ac_uint4 s, e;
323     _ranges_t *rlp;
324
325     if (len == 0)
326       return;
327
328     /*
329      * Deal with directionality codes introduced in Unicode 3.0.
330      */
331     if ((len == 2 && memcmp(name, "BN", 2) == 0) ||
332         (len == 3 &&
333          (memcmp(name, "NSM", 3) == 0 || memcmp(name, "PDF", 3) == 0 ||
334           memcmp(name, "LRE", 3) == 0 || memcmp(name, "LRO", 3) == 0 ||
335           memcmp(name, "RLE", 3) == 0 || memcmp(name, "RLO", 3) == 0))) {
336         /*
337          * Mark all of these as Other Neutral to preserve compatibility with
338          * older versions.
339          */
340         len = 2;
341         name = "ON";
342     }
343
344     for (i = 0; i < NUMPROPS; i++) {
345         if (props[i].len == len && memcmp(props[i].name, name, len) == 0)
346           break;
347     }
348
349     if (i == NUMPROPS)
350       return;
351
352     /*
353      * Have a match, so insert the code in order.
354      */
355     rlp = &proptbl[i];
356
357     /*
358      * Resize the range list if necessary.
359      */
360     if (rlp->used == rlp->size) {
361         if (rlp->size == 0)
362           rlp->ranges = (ac_uint4 *)
363               malloc(sizeof(ac_uint4) << 3);
364         else
365           rlp->ranges = (ac_uint4 *)
366               realloc((char *) rlp->ranges,
367                       sizeof(ac_uint4) * (rlp->size + 8));
368         rlp->size += 8;
369     }
370
371     /*
372      * If this is the first code for this property list, just add it
373      * and return.
374      */
375     if (rlp->used == 0) {
376         rlp->ranges[0] = rlp->ranges[1] = c;
377         rlp->used += 2;
378         return;
379     }
380
381     /*
382      * Optimize the cases of extending the last range and adding new ranges to
383      * the end.
384      */
385     j = rlp->used - 1;
386     e = rlp->ranges[j];
387     s = rlp->ranges[j - 1];
388
389     if (c == e + 1) {
390         /*
391          * Extend the last range.
392          */
393         rlp->ranges[j] = c;
394         return;
395     }
396
397     if (c > e + 1) {
398         /*
399          * Start another range on the end.
400          */
401         j = rlp->used;
402         rlp->ranges[j] = rlp->ranges[j + 1] = c;
403         rlp->used += 2;
404         return;
405     }
406
407     if (c >= s)
408       /*
409        * The code is a duplicate of a code in the last range, so just return.
410        */
411       return;
412
413     /*
414      * The code should be inserted somewhere before the last range in the
415      * list.  Locate the insertion point.
416      */
417     for (i = 0;
418          i < rlp->used && c > rlp->ranges[i + 1] + 1; i += 2) ;
419
420     s = rlp->ranges[i];
421     e = rlp->ranges[i + 1];
422
423     if (c == e + 1)
424       /*
425        * Simply extend the current range.
426        */
427       rlp->ranges[i + 1] = c;
428     else if (c < s) {
429         /*
430          * Add a new entry before the current location.  Shift all entries
431          * before the current one up by one to make room.
432          */
433         for (j = rlp->used; j > i; j -= 2) {
434             rlp->ranges[j] = rlp->ranges[j - 2];
435             rlp->ranges[j + 1] = rlp->ranges[j - 1];
436         }
437         rlp->ranges[i] = rlp->ranges[i + 1] = c;
438
439         rlp->used += 2;
440     }
441 }
442
443 static void
444 add_decomp(ac_uint4 code, short compat)
445 {
446     ac_uint4 i, j, size;
447     _decomp_t **pdecomps;
448     ac_uint4 *pdecomps_used;
449     ac_uint4 *pdecomps_size;
450
451     if (compat) {
452         pdecomps = &kdecomps;
453         pdecomps_used = &kdecomps_used;
454         pdecomps_size = &kdecomps_size;
455     } else {
456         pdecomps = &decomps;
457         pdecomps_used = &decomps_used;
458         pdecomps_size = &decomps_size;
459     }
460     
461     /*
462      * Add the code to the composite property.
463      */
464     if (!compat) {
465         ordered_range_insert(code, "Cm", 2);
466     }
467
468     /*
469      * Locate the insertion point for the code.
470      */
471     for (i = 0; i < *pdecomps_used && code > (*pdecomps)[i].code; i++) ;
472
473     /*
474      * Allocate space for a new decomposition.
475      */
476     if (*pdecomps_used == *pdecomps_size) {
477         if (*pdecomps_size == 0)
478           *pdecomps = (_decomp_t *) malloc(sizeof(_decomp_t) << 3);
479         else
480           *pdecomps = (_decomp_t *)
481               realloc((char *) *pdecomps,
482                       sizeof(_decomp_t) * (*pdecomps_size + 8));
483         (void) memset((char *) (*pdecomps + *pdecomps_size), '\0',
484                       sizeof(_decomp_t) << 3);
485         *pdecomps_size += 8;
486     }
487
488     if (i < *pdecomps_used && code != (*pdecomps)[i].code) {
489         /*
490          * Shift the decomps up by one if the codes don't match.
491          */
492         for (j = *pdecomps_used; j > i; j--)
493           (void) AC_MEMCPY((char *) &(*pdecomps)[j], (char *) &(*pdecomps)[j - 1],
494                         sizeof(_decomp_t));
495     }
496
497     /*
498      * Insert or replace a decomposition.
499      */
500     size = dectmp_size + (4 - (dectmp_size & 3));
501     if ((*pdecomps)[i].size < size) {
502         if ((*pdecomps)[i].size == 0)
503           (*pdecomps)[i].decomp = (ac_uint4 *)
504               malloc(sizeof(ac_uint4) * size);
505         else
506           (*pdecomps)[i].decomp = (ac_uint4 *)
507               realloc((char *) (*pdecomps)[i].decomp,
508                       sizeof(ac_uint4) * size);
509         (*pdecomps)[i].size = size;
510     }
511
512     if ((*pdecomps)[i].code != code)
513       (*pdecomps_used)++;
514
515     (*pdecomps)[i].code = code;
516     (*pdecomps)[i].used = dectmp_size;
517     (void) AC_MEMCPY((char *) (*pdecomps)[i].decomp, (char *) dectmp,
518                   sizeof(ac_uint4) * dectmp_size);
519
520     /*
521      * NOTICE: This needs changing later so it is more general than simply
522      * pairs.  This calculation is done here to simplify allocation elsewhere.
523      */
524     if (!compat && dectmp_size == 2)
525       comps_used++;
526 }
527
528 static void
529 add_title(ac_uint4 code)
530 {
531     ac_uint4 i, j;
532
533     /*
534      * Always map the code to itself.
535      */
536     cases[2] = code;
537
538     if (title_used == title_size) {
539         if (title_size == 0)
540           title = (_case_t *) malloc(sizeof(_case_t) << 3);
541         else
542           title = (_case_t *) realloc((char *) title,
543                                       sizeof(_case_t) * (title_size + 8));
544         title_size += 8;
545     }
546
547     /*
548      * Locate the insertion point.
549      */
550     for (i = 0; i < title_used && code > title[i].key; i++) ;
551
552     if (i < title_used) {
553         /*
554          * Shift the array up by one.
555          */
556         for (j = title_used; j > i; j--)
557           (void) AC_MEMCPY((char *) &title[j], (char *) &title[j - 1],
558                         sizeof(_case_t));
559     }
560
561     title[i].key = cases[2];    /* Title */
562     title[i].other1 = cases[0]; /* Upper */
563     title[i].other2 = cases[1]; /* Lower */
564
565     title_used++;
566 }
567
568 static void
569 add_upper(ac_uint4 code)
570 {
571     ac_uint4 i, j;
572
573     /*
574      * Always map the code to itself.
575      */
576     cases[0] = code;
577
578     /*
579      * If the title case character is not present, then make it the same as
580      * the upper case.
581      */
582     if (cases[2] == 0)
583       cases[2] = code;
584
585     if (upper_used == upper_size) {
586         if (upper_size == 0)
587           upper = (_case_t *) malloc(sizeof(_case_t) << 3);
588         else
589           upper = (_case_t *) realloc((char *) upper,
590                                       sizeof(_case_t) * (upper_size + 8));
591         upper_size += 8;
592     }
593
594     /*
595      * Locate the insertion point.
596      */
597     for (i = 0; i < upper_used && code > upper[i].key; i++) ;
598
599     if (i < upper_used) {
600         /*
601          * Shift the array up by one.
602          */
603         for (j = upper_used; j > i; j--)
604           (void) AC_MEMCPY((char *) &upper[j], (char *) &upper[j - 1],
605                         sizeof(_case_t));
606     }
607
608     upper[i].key = cases[0];    /* Upper */
609     upper[i].other1 = cases[1]; /* Lower */
610     upper[i].other2 = cases[2]; /* Title */
611
612     upper_used++;
613 }
614
615 static void
616 add_lower(ac_uint4 code)
617 {
618     ac_uint4 i, j;
619
620     /*
621      * Always map the code to itself.
622      */
623     cases[1] = code;
624
625     /*
626      * If the title case character is empty, then make it the same as the
627      * upper case.
628      */
629     if (cases[2] == 0)
630       cases[2] = cases[0];
631
632     if (lower_used == lower_size) {
633         if (lower_size == 0)
634           lower = (_case_t *) malloc(sizeof(_case_t) << 3);
635         else
636           lower = (_case_t *) realloc((char *) lower,
637                                       sizeof(_case_t) * (lower_size + 8));
638         lower_size += 8;
639     }
640
641     /*
642      * Locate the insertion point.
643      */
644     for (i = 0; i < lower_used && code > lower[i].key; i++) ;
645
646     if (i < lower_used) {
647         /*
648          * Shift the array up by one.
649          */
650         for (j = lower_used; j > i; j--)
651           (void) AC_MEMCPY((char *) &lower[j], (char *) &lower[j - 1],
652                         sizeof(_case_t));
653     }
654
655     lower[i].key = cases[1];    /* Lower */
656     lower[i].other1 = cases[0]; /* Upper */
657     lower[i].other2 = cases[2]; /* Title */
658
659     lower_used++;
660 }
661
662 static void
663 ordered_ccl_insert(ac_uint4 c, ac_uint4 ccl_code)
664 {
665     ac_uint4 i, j;
666
667     if (ccl_used == ccl_size) {
668         if (ccl_size == 0)
669           ccl = (ac_uint4 *) malloc(sizeof(ac_uint4) * 24);
670         else
671           ccl = (ac_uint4 *)
672               realloc((char *) ccl, sizeof(ac_uint4) * (ccl_size + 24));
673         ccl_size += 24;
674     }
675
676     /*
677      * Optimize adding the first item.
678      */
679     if (ccl_used == 0) {
680         ccl[0] = ccl[1] = c;
681         ccl[2] = ccl_code;
682         ccl_used += 3;
683         return;
684     }
685
686     /*
687      * Handle the special case of extending the range on the end.  This
688      * requires that the combining class codes are the same.
689      */
690     if (ccl_code == ccl[ccl_used - 1] && c == ccl[ccl_used - 2] + 1) {
691         ccl[ccl_used - 2] = c;
692         return;
693     }
694
695     /*
696      * Handle the special case of adding another range on the end.
697      */
698     if (c > ccl[ccl_used - 2] + 1 ||
699         (c == ccl[ccl_used - 2] + 1 && ccl_code != ccl[ccl_used - 1])) {
700         ccl[ccl_used++] = c;
701         ccl[ccl_used++] = c;
702         ccl[ccl_used++] = ccl_code;
703         return;
704     }
705
706     /*
707      * Locate either the insertion point or range for the code.
708      */
709     for (i = 0; i < ccl_used && c > ccl[i + 1] + 1; i += 3) ;
710
711     if (ccl_code == ccl[i + 2] && c == ccl[i + 1] + 1) {
712         /*
713          * Extend an existing range.
714          */
715         ccl[i + 1] = c;
716         return;
717     } else if (c < ccl[i]) {
718         /*
719          * Start a new range before the current location.
720          */
721         for (j = ccl_used; j > i; j -= 3) {
722             ccl[j] = ccl[j - 3];
723             ccl[j - 1] = ccl[j - 4];
724             ccl[j - 2] = ccl[j - 5];
725         }
726         ccl[i] = ccl[i + 1] = c;
727         ccl[i + 2] = ccl_code;
728     }
729 }
730
731 /*
732  * Adds a number if it does not already exist and returns an index value
733  * multiplied by 2.
734  */
735 static ac_uint4
736 make_number(short num, short denom)
737 {
738     ac_uint4 n;
739
740     /*
741      * Determine if the number already exists.
742      */
743     for (n = 0; n < nums_used; n++) {
744         if (nums[n].numerator == num && nums[n].denominator == denom)
745           return n << 1;
746     }
747
748     if (nums_used == nums_size) {
749         if (nums_size == 0)
750           nums = (_num_t *) malloc(sizeof(_num_t) << 3);
751         else
752           nums = (_num_t *) realloc((char *) nums,
753                                     sizeof(_num_t) * (nums_size + 8));
754         nums_size += 8;
755     }
756
757     n = nums_used++;
758     nums[n].numerator = num;
759     nums[n].denominator = denom;
760
761     return n << 1;
762 }
763
764 static void
765 add_number(ac_uint4 code, short num, short denom)
766 {
767     ac_uint4 i, j;
768
769     /*
770      * Insert the code in order.
771      */
772     for (i = 0; i < ncodes_used && code > ncodes[i].code; i++) ;
773
774     /*
775      * Handle the case of the codes matching and simply replace the number
776      * that was there before.
777      */
778     if (i < ncodes_used && code == ncodes[i].code) {
779         ncodes[i].idx = make_number(num, denom);
780         return;
781     }
782
783     /*
784      * Resize the array if necessary.
785      */
786     if (ncodes_used == ncodes_size) {
787         if (ncodes_size == 0)
788           ncodes = (_codeidx_t *) malloc(sizeof(_codeidx_t) << 3);
789         else
790           ncodes = (_codeidx_t *)
791               realloc((char *) ncodes, sizeof(_codeidx_t) * (ncodes_size + 8));
792
793         ncodes_size += 8;
794     }
795
796     /*
797      * Shift things around to insert the code if necessary.
798      */
799     if (i < ncodes_used) {
800         for (j = ncodes_used; j > i; j--) {
801             ncodes[j].code = ncodes[j - 1].code;
802             ncodes[j].idx = ncodes[j - 1].idx;
803         }
804     }
805     ncodes[i].code = code;
806     ncodes[i].idx = make_number(num, denom);
807
808     ncodes_used++;
809 }
810
811 /*
812  * This routine assumes that the line is a valid Unicode Character Database
813  * entry.
814  */
815 static void
816 read_cdata(FILE *in)
817 {
818     ac_uint4 i, lineno, skip, code, ccl_code;
819     short wnum, neg, number[2], compat;
820     char line[512], *s, *e;
821
822     lineno = skip = 0;
823     while (fgets(line, sizeof(line), in)) {
824         if( (s=strchr(line, '\n')) ) *s = '\0';
825         lineno++;
826
827         /*
828          * Skip blank lines and lines that start with a '#'.
829          */
830         if (line[0] == 0 || line[0] == '#')
831           continue;
832
833         /*
834          * If lines need to be skipped, do it here.
835          */
836         if (skip) {
837             skip--;
838             continue;
839         }
840
841         /*
842          * Collect the code.  The code can be up to 6 hex digits in length to
843          * allow surrogates to be specified.
844          */
845         for (s = line, i = code = 0; *s != ';' && i < 6; i++, s++) {
846             code <<= 4;
847             if (*s >= '0' && *s <= '9')
848               code += *s - '0';
849             else if (*s >= 'A' && *s <= 'F')
850               code += (*s - 'A') + 10;
851             else if (*s >= 'a' && *s <= 'f')
852               code += (*s - 'a') + 10;
853         }
854
855         /*
856          * Handle the following special cases:
857          * 1. 4E00-9FA5 CJK Ideographs.
858          * 2. AC00-D7A3 Hangul Syllables.
859          * 3. D800-DFFF Surrogates.
860          * 4. E000-F8FF Private Use Area.
861          * 5. F900-FA2D Han compatibility.
862          * ...Plus additional ranges in newer Unicode versions...
863          */
864         switch (code) {
865           case 0x3400:
866             /* CJK Ideograph Extension A */
867             add_range(0x3400, 0x4db5, "Lo", "L");
868
869             add_range(0x3400, 0x4db5, "Cp", 0);
870
871             skip = 1;
872             break;
873           case 0x4e00:
874             /*
875              * The Han ideographs.
876              */
877             add_range(0x4e00, 0x9fff, "Lo", "L");
878
879             /*
880              * Add the characters to the defined category.
881              */
882             add_range(0x4e00, 0x9fa5, "Cp", 0);
883
884             skip = 1;
885             break;
886           case 0xac00:
887             /*
888              * The Hangul syllables.
889              */
890             add_range(0xac00, 0xd7a3, "Lo", "L");
891
892             /*
893              * Add the characters to the defined category.
894              */
895             add_range(0xac00, 0xd7a3, "Cp", 0);
896
897             skip = 1;
898             break;
899           case 0xd800:
900             /*
901              * Make a range of all surrogates and assume some default
902              * properties.
903              */
904             add_range(0x010000, 0x10ffff, "Cs", "L");
905             skip = 5;
906             break;
907           case 0xe000:
908             /*
909              * The Private Use area.  Add with a default set of properties.
910              */
911             add_range(0xe000, 0xf8ff, "Co", "L");
912             skip = 1;
913             break;
914           case 0xf900:
915             /*
916              * The CJK compatibility area.
917              */
918             add_range(0xf900, 0xfaff, "Lo", "L");
919
920             /*
921              * Add the characters to the defined category.
922              */
923             add_range(0xf900, 0xfaff, "Cp", 0);
924
925             skip = 1;
926             break;
927           case 0x20000:
928             /* CJK Ideograph Extension B */
929             add_range(0x20000, 0x2a6d6, "Lo", "L");
930
931             add_range(0x20000, 0x2a6d6, "Cp", 0);
932
933             skip = 1;
934             break;
935           case 0xf0000:
936             /* Plane 15 private use */
937             add_range(0xf0000, 0xffffd, "Co", "L");
938             skip = 1;
939             break;
940
941           case 0x100000:
942             /* Plane 16 private use */
943             add_range(0x100000, 0x10fffd, "Co", "L");
944             skip = 1;
945             break;
946         }
947
948         if (skip)
949           continue;
950
951         /*
952          * Add the code to the defined category.
953          */
954         ordered_range_insert(code, "Cp", 2);
955
956         /*
957          * Locate the first character property field.
958          */
959         for (i = 0; *s != 0 && i < 2; s++) {
960             if (*s == ';')
961               i++;
962         }
963         for (e = s; *e && *e != ';'; e++) ;
964     
965         ordered_range_insert(code, s, e - s);
966
967         /*
968          * Locate the combining class code.
969          */
970         for (s = e; *s != 0 && i < 3; s++) {
971             if (*s == ';')
972               i++;
973         }
974
975         /*
976          * Convert the combining class code from decimal.
977          */
978         for (ccl_code = 0, e = s; *e && *e != ';'; e++)
979           ccl_code = (ccl_code * 10) + (*e - '0');
980
981         /*
982          * Add the code if it not 0.
983          */
984         if (ccl_code != 0)
985           ordered_ccl_insert(code, ccl_code);
986
987         /*
988          * Locate the second character property field.
989          */
990         for (s = e; *s != 0 && i < 4; s++) {
991             if (*s == ';')
992               i++;
993         }
994         for (e = s; *e && *e != ';'; e++) ;
995
996         ordered_range_insert(code, s, e - s);
997
998         /*
999          * Check for a decomposition.
1000          */
1001         s = ++e;
1002         if (*s != ';') {
1003             compat = *s == '<';
1004             if (compat) {
1005                 /*
1006                  * Skip compatibility formatting tag.
1007                  */
1008                 while (*s++ != '>');
1009             }
1010             /*
1011              * Collect the codes of the decomposition.
1012              */
1013             for (dectmp_size = 0; *s != ';'; ) {
1014                 /*
1015                  * Skip all leading non-hex digits.
1016                  */
1017                 while (!ishdigit(*s))
1018                   s++;
1019
1020                 for (dectmp[dectmp_size] = 0; ishdigit(*s); s++) {
1021                     dectmp[dectmp_size] <<= 4;
1022                     if (*s >= '0' && *s <= '9')
1023                       dectmp[dectmp_size] += *s - '0';
1024                     else if (*s >= 'A' && *s <= 'F')
1025                       dectmp[dectmp_size] += (*s - 'A') + 10;
1026                     else if (*s >= 'a' && *s <= 'f')
1027                       dectmp[dectmp_size] += (*s - 'a') + 10;
1028                 }
1029                 dectmp_size++;
1030             }
1031
1032             /*
1033              * If there are any codes in the temporary decomposition array,
1034              * then add the character with its decomposition.
1035              */
1036             if (dectmp_size > 0) {
1037                 if (!compat) {
1038                     add_decomp(code, 0);
1039                 }
1040                 add_decomp(code, 1);
1041             }
1042         }
1043
1044         /*
1045          * Skip to the number field.
1046          */
1047         for (i = 0; i < 3 && *s; s++) {
1048             if (*s == ';')
1049               i++;
1050         }
1051
1052         /*
1053          * Scan the number in.
1054          */
1055         number[0] = number[1] = 0;
1056         for (e = s, neg = wnum = 0; *e && *e != ';'; e++) {
1057             if (*e == '-') {
1058                 neg = 1;
1059                 continue;
1060             }
1061
1062             if (*e == '/') {
1063                 /*
1064                  * Move the the denominator of the fraction.
1065                  */
1066                 if (neg)
1067                   number[wnum] *= -1;
1068                 neg = 0;
1069                 e++;
1070                 wnum++;
1071             }
1072             number[wnum] = (number[wnum] * 10) + (*e - '0');
1073         }
1074
1075         if (e > s) {
1076             /*
1077              * Adjust the denominator in case of integers and add the number.
1078              */
1079             if (wnum == 0)
1080               number[1] = 1;
1081
1082             add_number(code, number[0], number[1]);
1083         }
1084
1085         /*
1086          * Skip to the start of the possible case mappings.
1087          */
1088         for (s = e, i = 0; i < 4 && *s; s++) {
1089             if (*s == ';')
1090               i++;
1091         }
1092
1093         /*
1094          * Collect the case mappings.
1095          */
1096         cases[0] = cases[1] = cases[2] = 0;
1097         for (i = 0; i < 3; i++) {
1098             while (ishdigit(*s)) {
1099                 cases[i] <<= 4;
1100                 if (*s >= '0' && *s <= '9')
1101                   cases[i] += *s - '0';
1102                 else if (*s >= 'A' && *s <= 'F')
1103                   cases[i] += (*s - 'A') + 10;
1104                 else if (*s >= 'a' && *s <= 'f')
1105                   cases[i] += (*s - 'a') + 10;
1106                 s++;
1107             }
1108             if (*s == ';')
1109               s++;
1110         }
1111         if (cases[0] && cases[1])
1112           /*
1113            * Add the upper and lower mappings for a title case character.
1114            */
1115           add_title(code);
1116         else if (cases[1])
1117           /*
1118            * Add the lower and title case mappings for the upper case
1119            * character.
1120            */
1121           add_upper(code);
1122         else if (cases[0])
1123           /*
1124            * Add the upper and title case mappings for the lower case
1125            * character.
1126            */
1127           add_lower(code);
1128     }
1129 }
1130
1131 static _decomp_t *
1132 find_decomp(ac_uint4 code, short compat)
1133 {
1134     long l, r, m;
1135     _decomp_t *decs;
1136     
1137     l = 0;
1138     r = (compat ? kdecomps_used : decomps_used) - 1;
1139     decs = compat ? kdecomps : decomps;
1140     while (l <= r) {
1141         m = (l + r) >> 1;
1142         if (code > decs[m].code)
1143           l = m + 1;
1144         else if (code < decs[m].code)
1145           r = m - 1;
1146         else
1147           return &decs[m];
1148     }
1149     return 0;
1150 }
1151
1152 static void
1153 decomp_it(_decomp_t *d, short compat)
1154 {
1155     ac_uint4 i;
1156     _decomp_t *dp;
1157
1158     for (i = 0; i < d->used; i++) {
1159         if ((dp = find_decomp(d->decomp[i], compat)) != 0)
1160           decomp_it(dp, compat);
1161         else
1162           dectmp[dectmp_size++] = d->decomp[i];
1163     }
1164 }
1165
1166 /*
1167  * Expand all decompositions by recursively decomposing each character
1168  * in the decomposition.
1169  */
1170 static void
1171 expand_decomp(void)
1172 {
1173     ac_uint4 i;
1174
1175     for (i = 0; i < decomps_used; i++) {
1176         dectmp_size = 0;
1177         decomp_it(&decomps[i], 0);
1178         if (dectmp_size > 0)
1179           add_decomp(decomps[i].code, 0);
1180     }
1181
1182     for (i = 0; i < kdecomps_used; i++) {
1183         dectmp_size = 0;
1184         decomp_it(&kdecomps[i], 1);
1185         if (dectmp_size > 0)
1186           add_decomp(kdecomps[i].code, 1);
1187     }
1188 }
1189
1190 static int
1191 cmpcomps(const void *v_comp1, const void *v_comp2)
1192 {
1193         const _comp_t *comp1 = v_comp1, *comp2 = v_comp2;
1194     long diff = comp1->code1 - comp2->code1;
1195
1196     if (!diff)
1197         diff = comp1->code2 - comp2->code2;
1198     return (int) diff;
1199 }
1200
1201 /*
1202  * Load composition exclusion data
1203  */
1204 static void
1205 read_compexdata(FILE *in)
1206 {
1207     ac_uint2 i, code;
1208     char line[512], *s;
1209
1210     (void) memset((char *) compexs, 0, sizeof(ac_uint4) << 11);
1211
1212     while (fgets(line, sizeof(line), in)) {
1213         if( (s=strchr(line, '\n')) ) *s = '\0';
1214         /*
1215          * Skip blank lines and lines that start with a '#'.
1216          */
1217         if (line[0] == 0 || line[0] == '#')
1218             continue;
1219
1220         /*
1221          * Collect the code.  Assume max 4 digits
1222          */
1223
1224         for (s = line, i = code = 0; *s != '#' && i < 4; i++, s++) {
1225             code <<= 4;
1226             if (*s >= '0' && *s <= '9')
1227                 code += *s - '0';
1228             else if (*s >= 'A' && *s <= 'F')
1229                 code += (*s - 'A') + 10;
1230             else if (*s >= 'a' && *s <= 'f')
1231                 code += (*s - 'a') + 10;
1232         }
1233         COMPEX_SET(code);
1234     }
1235 }
1236
1237 /*
1238  * Creates array of compositions from decomposition array
1239  */
1240 static void
1241 create_comps(void)
1242 {
1243     ac_uint4 i, cu;
1244
1245     comps = (_comp_t *) malloc(comps_used * sizeof(_comp_t));
1246
1247     for (i = cu = 0; i < decomps_used; i++) {
1248         if (decomps[i].used != 2 || COMPEX_TEST(decomps[i].code))
1249             continue;
1250         comps[cu].comp = decomps[i].code;
1251         comps[cu].count = 2;
1252         comps[cu].code1 = decomps[i].decomp[0];
1253         comps[cu].code2 = decomps[i].decomp[1];
1254         cu++;
1255     }
1256     comps_used = cu;
1257     qsort(comps, comps_used, sizeof(_comp_t), cmpcomps);
1258 }
1259
1260 #if HARDCODE_DATA
1261 static void
1262 write_case(FILE *out, _case_t *tab, int num, int first)
1263 {
1264     int i;
1265
1266     for (i=0; i<num; i++) {
1267         if (first) first = 0;
1268         else fprintf(out, ",");
1269         fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x",
1270                 tab[i].key, tab[i].other1, tab[i].other2);
1271     }
1272 }
1273
1274 #define PREF "static const "
1275
1276 #endif
1277
1278 static void
1279 write_cdata(char *opath)
1280 {
1281     FILE *out;
1282         ac_uint4 bytes;
1283     ac_uint4 i, idx, nprops;
1284     ac_uint2 casecnt[2];
1285     char path[BUFSIZ];
1286 #if HARDCODE_DATA
1287     int j, k;
1288
1289     /*****************************************************************
1290      *
1291      * Generate the ctype data.
1292      *
1293      *****************************************************************/
1294
1295     /*
1296      * Open the output file.
1297      */
1298     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "uctable.h", opath);
1299     if ((out = fopen(path, "w")) == 0)
1300       return;
1301 #else
1302     /*
1303      * Open the ctype.dat file.
1304      */
1305     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath);
1306     if ((out = fopen(path, "wb")) == 0)
1307       return;
1308 #endif
1309
1310     /*
1311      * Collect the offsets for the properties.  The offsets array is
1312      * on a 4-byte boundary to keep things efficient for architectures
1313      * that need such a thing.
1314      */
1315     for (i = idx = 0; i < NUMPROPS; i++) {
1316         propcnt[i] = (proptbl[i].used != 0) ? idx : 0xffff;
1317         idx += proptbl[i].used;
1318     }
1319
1320     /*
1321      * Add the sentinel index which is used by the binary search as the upper
1322      * bound for a search.
1323      */
1324     propcnt[i] = idx;
1325
1326     /*
1327      * Record the actual number of property lists.  This may be different than
1328      * the number of offsets actually written because of aligning on a 4-byte
1329      * boundary.
1330      */
1331     hdr[1] = NUMPROPS;
1332
1333     /*
1334      * Calculate the byte count needed and pad the property counts array to a
1335      * 4-byte boundary.
1336      */
1337     if ((bytes = sizeof(ac_uint2) * (NUMPROPS + 1)) & 3)
1338       bytes += 4 - (bytes & 3);
1339     nprops = bytes / sizeof(ac_uint2);
1340     bytes += sizeof(ac_uint4) * idx;
1341
1342 #if HARDCODE_DATA
1343     fprintf(out, PREF "ac_uint4 _ucprop_size = %d;\n\n", NUMPROPS);
1344
1345     fprintf(out, PREF "ac_uint2 _ucprop_offsets[] = {");
1346
1347     for (i = 0; i<nprops; i++) {
1348        if (i) fprintf(out, ",");
1349        if (!(i&7)) fprintf(out, "\n\t");
1350        else fprintf(out, " ");
1351        fprintf(out, "0x%04x", propcnt[i]);
1352     }
1353     fprintf(out, "\n};\n\n");
1354
1355     fprintf(out, PREF "ac_uint4 _ucprop_ranges[] = {");
1356
1357     k = 0;
1358     for (i = 0; i < NUMPROPS; i++) {
1359         if (proptbl[i].used > 0) {
1360           for (j=0; j<proptbl[i].used; j++) {
1361             if (k) fprintf(out, ",");
1362             if (!(k&3)) fprintf(out,"\n\t");
1363             else fprintf(out, " ");
1364             k++;
1365             fprintf(out, "0x%08x", proptbl[i].ranges[j]);
1366           }
1367         }
1368     }
1369     fprintf(out, "\n};\n\n");
1370 #else
1371     /*
1372      * Write the header.
1373      */
1374     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1375
1376     /*
1377      * Write the byte count.
1378      */
1379     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1380
1381     /*
1382      * Write the property list counts.
1383      */
1384     fwrite((char *) propcnt, sizeof(ac_uint2), nprops, out);
1385
1386     /*
1387      * Write the property lists.
1388      */
1389     for (i = 0; i < NUMPROPS; i++) {
1390         if (proptbl[i].used > 0)
1391           fwrite((char *) proptbl[i].ranges, sizeof(ac_uint4),
1392                  proptbl[i].used, out);
1393     }
1394
1395     fclose(out);
1396 #endif
1397
1398     /*****************************************************************
1399      *
1400      * Generate the case mapping data.
1401      *
1402      *****************************************************************/
1403
1404 #if HARDCODE_DATA
1405     fprintf(out, PREF "ac_uint4 _uccase_size = %d;\n\n",
1406         upper_used + lower_used + title_used);
1407
1408     fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%d, %d};\n\n",
1409         upper_used, lower_used);
1410     fprintf(out, PREF "ac_uint4 _uccase_map[] = {");
1411
1412     if (upper_used > 0)
1413       /*
1414        * Write the upper case table.
1415        */
1416       write_case(out, upper, upper_used, 1);
1417
1418     if (lower_used > 0)
1419       /*
1420        * Write the lower case table.
1421        */
1422       write_case(out, lower, lower_used, !upper_used);
1423
1424     if (title_used > 0)
1425       /*
1426        * Write the title case table.
1427        */
1428       write_case(out, title, title_used, !(upper_used||lower_used));
1429
1430     if (!(upper_used || lower_used || title_used))
1431         fprintf(out, "\t0");
1432
1433     fprintf(out, "\n};\n\n");
1434 #else
1435     /*
1436      * Open the case.dat file.
1437      */
1438     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath);
1439     if ((out = fopen(path, "wb")) == 0)
1440       return;
1441
1442     /*
1443      * Write the case mapping tables.
1444      */
1445     hdr[1] = upper_used + lower_used + title_used;
1446     casecnt[0] = upper_used;
1447     casecnt[1] = lower_used;
1448
1449     /*
1450      * Write the header.
1451      */
1452     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1453
1454     /*
1455      * Write the upper and lower case table sizes.
1456      */
1457     fwrite((char *) casecnt, sizeof(ac_uint2), 2, out);
1458
1459     if (upper_used > 0)
1460       /*
1461        * Write the upper case table.
1462        */
1463       fwrite((char *) upper, sizeof(_case_t), upper_used, out);
1464
1465     if (lower_used > 0)
1466       /*
1467        * Write the lower case table.
1468        */
1469       fwrite((char *) lower, sizeof(_case_t), lower_used, out);
1470
1471     if (title_used > 0)
1472       /*
1473        * Write the title case table.
1474        */
1475       fwrite((char *) title, sizeof(_case_t), title_used, out);
1476
1477     fclose(out);
1478 #endif
1479
1480     /*****************************************************************
1481      *
1482      * Generate the composition data.
1483      *
1484      *****************************************************************/
1485     
1486     /*
1487      * Create compositions from decomposition data
1488      */
1489     create_comps();
1490     
1491 #if HARDCODE_DATA
1492     fprintf(out, PREF "ac_uint4 _uccomp_size = %d;\n\n",
1493         comps_used * 4);
1494
1495     fprintf(out, PREF "ac_uint4 _uccomp_data[] = {");
1496
1497      /*
1498       * Now, if comps exist, write them out.
1499       */
1500     if (comps_used > 0) {
1501         for (i=0; i<comps_used; i++) {
1502             if (i) fprintf(out, ",");
1503             fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x, 0x%08x",
1504                 comps[i].comp, comps[i].count, comps[i].code1, comps[i].code2);
1505         }
1506     } else {
1507         fprintf(out, "\t0");
1508     }
1509     fprintf(out, "\n};\n\n");
1510 #else
1511     /*
1512      * Open the comp.dat file.
1513      */
1514     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath);
1515     if ((out = fopen(path, "wb")) == 0)
1516         return;
1517     
1518     /*
1519      * Write the header.
1520      */
1521     hdr[1] = (ac_uint2) comps_used * 4;
1522     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1523     
1524     /*
1525      * Write out the byte count to maintain header size.
1526      */
1527     bytes = comps_used * sizeof(_comp_t);
1528     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1529     
1530     /*
1531      * Now, if comps exist, write them out.
1532      */
1533     if (comps_used > 0)
1534         fwrite((char *) comps, sizeof(_comp_t), comps_used, out);
1535     
1536     fclose(out);
1537 #endif
1538     
1539     /*****************************************************************
1540      *
1541      * Generate the decomposition data.
1542      *
1543      *****************************************************************/
1544
1545     /*
1546      * Fully expand all decompositions before generating the output file.
1547      */
1548     expand_decomp();
1549
1550 #if HARDCODE_DATA
1551     fprintf(out, PREF "ac_uint4 _ucdcmp_size = %d;\n\n",
1552         decomps_used * 2);
1553
1554     fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {");
1555
1556     if (decomps_used) {
1557         /*
1558          * Write the list of decomp nodes.
1559          */
1560         for (i = idx = 0; i < decomps_used; i++) {
1561             fprintf(out, "\n\t0x%08x, 0x%08x,", decomps[i].code, idx);
1562             idx += decomps[i].used;
1563         }
1564
1565         /*
1566          * Write the sentinel index as the last decomp node.
1567          */
1568         fprintf(out, "\n\t0x%08x\n};\n\n", idx);
1569
1570         fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {");
1571         /*
1572          * Write the decompositions themselves.
1573          */
1574         k = 0;
1575         for (i = 0; i < decomps_used; i++)
1576           for (j=0; j<decomps[i].used; j++) {
1577             if (k) fprintf(out, ",");
1578             if (!(k&3)) fprintf(out,"\n\t");
1579             else fprintf(out, " ");
1580             k++;
1581             fprintf(out, "0x%08x", decomps[i].decomp[j]);
1582           }
1583         fprintf(out, "\n};\n\n");
1584     }
1585 #else
1586     /*
1587      * Open the decomp.dat file.
1588      */
1589     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath);
1590     if ((out = fopen(path, "wb")) == 0)
1591       return;
1592
1593     hdr[1] = decomps_used;
1594
1595     /*
1596      * Write the header.
1597      */
1598     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1599
1600     /*
1601      * Write a temporary byte count which will be calculated as the
1602      * decompositions are written out.
1603      */
1604     bytes = 0;
1605     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1606
1607     if (decomps_used) {
1608         /*
1609          * Write the list of decomp nodes.
1610          */
1611         for (i = idx = 0; i < decomps_used; i++) {
1612             fwrite((char *) &decomps[i].code, sizeof(ac_uint4), 1, out);
1613             fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1614             idx += decomps[i].used;
1615         }
1616
1617         /*
1618          * Write the sentinel index as the last decomp node.
1619          */
1620         fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1621
1622         /*
1623          * Write the decompositions themselves.
1624          */
1625         for (i = 0; i < decomps_used; i++)
1626           fwrite((char *) decomps[i].decomp, sizeof(ac_uint4),
1627                  decomps[i].used, out);
1628
1629         /*
1630          * Seek back to the beginning and write the byte count.
1631          */
1632         bytes = (sizeof(ac_uint4) * idx) +
1633             (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
1634         fseek(out, sizeof(ac_uint2) << 1, 0L);
1635         fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1636
1637         fclose(out);
1638     }
1639 #endif
1640
1641 #ifdef HARDCODE_DATA
1642     fprintf(out, PREF "ac_uint4 _uckdcmp_size = %d;\n\n",
1643         kdecomps_used * 2);
1644
1645     fprintf(out, PREF "ac_uint4 _uckdcmp_nodes[] = {");
1646
1647     if (kdecomps_used) {
1648         /*
1649          * Write the list of kdecomp nodes.
1650          */
1651         for (i = idx = 0; i < kdecomps_used; i++) {
1652             fprintf(out, "\n\t0x%08x, 0x%08x,", kdecomps[i].code, idx);
1653             idx += kdecomps[i].used;
1654         }
1655
1656         /*
1657          * Write the sentinel index as the last decomp node.
1658          */
1659         fprintf(out, "\n\t0x%08x\n};\n\n", idx);
1660
1661         fprintf(out, PREF "ac_uint4 _uckdcmp_decomp[] = {");
1662
1663         /*
1664          * Write the decompositions themselves.
1665          */
1666         k = 0;
1667         for (i = 0; i < kdecomps_used; i++)
1668           for (j=0; j<kdecomps[i].used; j++) {
1669             if (k) fprintf(out, ",");
1670             if (!(k&3)) fprintf(out,"\n\t");
1671             else fprintf(out, " ");
1672             k++;
1673             fprintf(out, "0x%08x", kdecomps[i].decomp[j]);
1674           }
1675         fprintf(out, "\n};\n\n");
1676     }
1677 #else
1678     /*
1679      * Open the kdecomp.dat file.
1680      */
1681     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath);
1682     if ((out = fopen(path, "wb")) == 0)
1683       return;
1684
1685     hdr[1] = kdecomps_used;
1686
1687     /*
1688      * Write the header.
1689      */
1690     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1691
1692     /*
1693      * Write a temporary byte count which will be calculated as the
1694      * decompositions are written out.
1695      */
1696     bytes = 0;
1697     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1698
1699     if (kdecomps_used) {
1700         /*
1701          * Write the list of kdecomp nodes.
1702          */
1703         for (i = idx = 0; i < kdecomps_used; i++) {
1704             fwrite((char *) &kdecomps[i].code, sizeof(ac_uint4), 1, out);
1705             fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1706             idx += kdecomps[i].used;
1707         }
1708
1709         /*
1710          * Write the sentinel index as the last decomp node.
1711          */
1712         fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1713
1714         /*
1715          * Write the decompositions themselves.
1716          */
1717         for (i = 0; i < kdecomps_used; i++)
1718           fwrite((char *) kdecomps[i].decomp, sizeof(ac_uint4),
1719                  kdecomps[i].used, out);
1720
1721         /*
1722          * Seek back to the beginning and write the byte count.
1723          */
1724         bytes = (sizeof(ac_uint4) * idx) +
1725             (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
1726         fseek(out, sizeof(ac_uint2) << 1, 0L);
1727         fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1728
1729         fclose(out);
1730     }
1731 #endif
1732
1733     /*****************************************************************
1734      *
1735      * Generate the combining class data.
1736      *
1737      *****************************************************************/
1738 #ifdef HARDCODE_DATA
1739     fprintf(out, PREF "ac_uint4 _uccmcl_size = %d;\n\n", ccl_used);
1740
1741     fprintf(out, PREF "ac_uint4 _uccmcl_nodes[] = {");
1742
1743     if (ccl_used > 0) {
1744         /*
1745          * Write the combining class ranges out.
1746          */
1747         for (i = 0; i<ccl_used; i++) {
1748             if (i) fprintf(out, ",");
1749             if (!(i&3)) fprintf(out, "\n\t");
1750             else fprintf(out, " ");
1751             fprintf(out, "0x%08x", ccl[i]);
1752         }
1753     } else {
1754         fprintf(out, "\t0");
1755     }
1756     fprintf(out, "\n};\n\n");
1757 #else
1758     /*
1759      * Open the cmbcl.dat file.
1760      */
1761     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath);
1762     if ((out = fopen(path, "wb")) == 0)
1763       return;
1764
1765     /*
1766      * Set the number of ranges used.  Each range has a combining class which
1767      * means each entry is a 3-tuple.
1768      */
1769     hdr[1] = ccl_used / 3;
1770
1771     /*
1772      * Write the header.
1773      */
1774     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1775
1776     /*
1777      * Write out the byte count to maintain header size.
1778      */
1779     bytes = ccl_used * sizeof(ac_uint4);
1780     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1781
1782     if (ccl_used > 0)
1783       /*
1784        * Write the combining class ranges out.
1785        */
1786       fwrite((char *) ccl, sizeof(ac_uint4), ccl_used, out);
1787
1788     fclose(out);
1789 #endif
1790
1791     /*****************************************************************
1792      *
1793      * Generate the number data.
1794      *
1795      *****************************************************************/
1796
1797 #if HARDCODE_DATA
1798     fprintf(out, PREF "ac_uint4 _ucnum_size = %d;\n\n", ncodes_used<<1);
1799
1800     fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {");
1801
1802     /*
1803      * Now, if number mappings exist, write them out.
1804      */
1805     if (ncodes_used > 0) {
1806         for (i = 0; i<ncodes_used; i++) {
1807             if (i) fprintf(out, ",");
1808             if (!(i&1)) fprintf(out, "\n\t");
1809             else fprintf(out, " ");
1810             fprintf(out, "0x%08x, 0x%08x", ncodes[i].code, ncodes[i].idx);
1811         }
1812         fprintf(out, "\n};\n\n");
1813
1814         fprintf(out, PREF "short _ucnum_vals[] = {");
1815         for (i = 0; i<nums_used; i++) {
1816             if (i) fprintf(out, ",");
1817             if (!(i&3)) fprintf(out, "\n\t");
1818             else fprintf(out, " ");
1819             if (nums[i].numerator < 0) {
1820                 fprintf(out, "%6d, 0x%04x",
1821                   nums[i].numerator, nums[i].denominator);
1822             } else {
1823                 fprintf(out, "0x%04x, 0x%04x",
1824                   nums[i].numerator, nums[i].denominator);
1825             }
1826         }
1827         fprintf(out, "\n};\n\n");
1828     }
1829 #else
1830     /*
1831      * Open the num.dat file.
1832      */
1833     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath);
1834     if ((out = fopen(path, "wb")) == 0)
1835       return;
1836
1837     /*
1838      * The count part of the header will be the total number of codes that
1839      * have numbers.
1840      */
1841     hdr[1] = (ac_uint2) (ncodes_used << 1);
1842     bytes = (ncodes_used * sizeof(_codeidx_t)) + (nums_used * sizeof(_num_t));
1843
1844     /*
1845      * Write the header.
1846      */
1847     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1848
1849     /*
1850      * Write out the byte count to maintain header size.
1851      */
1852     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1853
1854     /*
1855      * Now, if number mappings exist, write them out.
1856      */
1857     if (ncodes_used > 0) {
1858         fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out);
1859         fwrite((char *) nums, sizeof(_num_t), nums_used, out);
1860     }
1861 #endif
1862
1863     fclose(out);
1864 }
1865
1866 static void
1867 usage(char *prog)
1868 {
1869     fprintf(stderr,
1870             "Usage: %s [-o output-directory|-x composition-exclusions]", prog);
1871     fprintf(stderr, " datafile1 datafile2 ...\n\n");
1872     fprintf(stderr,
1873             "-o output-directory\n\t\tWrite the output files to a different");
1874     fprintf(stderr, " directory (default: .).\n");
1875     fprintf(stderr,
1876             "-x composition-exclusion\n\t\tFile of composition codes");
1877     fprintf(stderr, " that should be excluded.\n");
1878     exit(1);
1879 }
1880
1881 int
1882 main(int argc, char *argv[])
1883 {
1884     FILE *in;
1885     char *prog, *opath;
1886
1887     prog = lutil_progname( "ucgendat", argc, argv );
1888
1889     opath = 0;
1890     in = stdin;
1891
1892     argc--;
1893     argv++;
1894
1895     while (argc > 0) {
1896         if (argv[0][0] == '-') {
1897             switch (argv[0][1]) {
1898               case 'o':
1899                 argc--;
1900                 argv++;
1901                 opath = argv[0];
1902                 break;
1903               case 'x':
1904                 argc--;
1905                 argv++;
1906                 if ((in = fopen(argv[0], "r")) == 0)
1907                   fprintf(stderr,
1908                           "%s: unable to open composition exclusion file %s\n",
1909                           prog, argv[0]);
1910                 else {
1911                     read_compexdata(in);
1912                     fclose(in);
1913                     in = 0;
1914                 }
1915                 break;
1916               default:
1917                 usage(prog);
1918             }
1919         } else {
1920             if (in != stdin && in != NULL)
1921               fclose(in);
1922             if ((in = fopen(argv[0], "r")) == 0)
1923               fprintf(stderr, "%s: unable to open ctype file %s\n",
1924                       prog, argv[0]);
1925             else {
1926                 read_cdata(in);
1927                 fclose(in);
1928                 in = 0;
1929             }
1930         }
1931         argc--;
1932         argv++;
1933     }
1934
1935     if (opath == 0)
1936       opath = ".";
1937     write_cdata(opath);
1938
1939     return 0;
1940 }