]> git.sur5r.net Git - openldap/blob - libraries/liblunicode/ucdata/ucgendat.c
Sync with HEAD
[openldap] / libraries / liblunicode / ucdata / ucgendat.c
1 /* $OpenLDAP$ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3  *
4  * Copyright 1998-2005 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[8192];
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;
1208     ac_uint4 code;
1209     char line[512], *s;
1210
1211     (void) memset((char *) compexs, 0, sizeof(compexs));
1212
1213     while (fgets(line, sizeof(line), in)) {
1214         if( (s=strchr(line, '\n')) ) *s = '\0';
1215         /*
1216          * Skip blank lines and lines that start with a '#'.
1217          */
1218         if (line[0] == 0 || line[0] == '#')
1219             continue;
1220
1221         /*
1222          * Collect the code.  Assume max 6 digits
1223          */
1224
1225         for (s = line, i = code = 0; *s != '#' && i < 6; i++, s++) {
1226             if (isspace(*s)) break;
1227             code <<= 4;
1228             if (*s >= '0' && *s <= '9')
1229                 code += *s - '0';
1230             else if (*s >= 'A' && *s <= 'F')
1231                 code += (*s - 'A') + 10;
1232             else if (*s >= 'a' && *s <= 'f')
1233                 code += (*s - 'a') + 10;
1234         }
1235         COMPEX_SET(code);
1236     }
1237 }
1238
1239 /*
1240  * Creates array of compositions from decomposition array
1241  */
1242 static void
1243 create_comps(void)
1244 {
1245     ac_uint4 i, cu;
1246
1247     comps = (_comp_t *) malloc(comps_used * sizeof(_comp_t));
1248
1249     for (i = cu = 0; i < decomps_used; i++) {
1250         if (decomps[i].used != 2 || COMPEX_TEST(decomps[i].code))
1251             continue;
1252         comps[cu].comp = decomps[i].code;
1253         comps[cu].count = 2;
1254         comps[cu].code1 = decomps[i].decomp[0];
1255         comps[cu].code2 = decomps[i].decomp[1];
1256         cu++;
1257     }
1258     comps_used = cu;
1259     qsort(comps, comps_used, sizeof(_comp_t), cmpcomps);
1260 }
1261
1262 #if HARDCODE_DATA
1263 static void
1264 write_case(FILE *out, _case_t *tab, int num, int first)
1265 {
1266     int i;
1267
1268     for (i=0; i<num; i++) {
1269         if (first) first = 0;
1270         else fprintf(out, ",");
1271         fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x",
1272                 tab[i].key, tab[i].other1, tab[i].other2);
1273     }
1274 }
1275
1276 #define PREF "static const "
1277
1278 #endif
1279
1280 static void
1281 write_cdata(char *opath)
1282 {
1283     FILE *out;
1284         ac_uint4 bytes;
1285     ac_uint4 i, idx, nprops;
1286     ac_uint2 casecnt[2];
1287     char path[BUFSIZ];
1288 #if HARDCODE_DATA
1289     int j, k;
1290
1291     /*****************************************************************
1292      *
1293      * Generate the ctype data.
1294      *
1295      *****************************************************************/
1296
1297     /*
1298      * Open the output file.
1299      */
1300     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "uctable.h", opath);
1301     if ((out = fopen(path, "w")) == 0)
1302       return;
1303 #else
1304     /*
1305      * Open the ctype.dat file.
1306      */
1307     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath);
1308     if ((out = fopen(path, "wb")) == 0)
1309       return;
1310 #endif
1311
1312     /*
1313      * Collect the offsets for the properties.  The offsets array is
1314      * on a 4-byte boundary to keep things efficient for architectures
1315      * that need such a thing.
1316      */
1317     for (i = idx = 0; i < NUMPROPS; i++) {
1318         propcnt[i] = (proptbl[i].used != 0) ? idx : 0xffff;
1319         idx += proptbl[i].used;
1320     }
1321
1322     /*
1323      * Add the sentinel index which is used by the binary search as the upper
1324      * bound for a search.
1325      */
1326     propcnt[i] = idx;
1327
1328     /*
1329      * Record the actual number of property lists.  This may be different than
1330      * the number of offsets actually written because of aligning on a 4-byte
1331      * boundary.
1332      */
1333     hdr[1] = NUMPROPS;
1334
1335     /*
1336      * Calculate the byte count needed and pad the property counts array to a
1337      * 4-byte boundary.
1338      */
1339     if ((bytes = sizeof(ac_uint2) * (NUMPROPS + 1)) & 3)
1340       bytes += 4 - (bytes & 3);
1341     nprops = bytes / sizeof(ac_uint2);
1342     bytes += sizeof(ac_uint4) * idx;
1343
1344 #if HARDCODE_DATA
1345     fprintf(out, PREF "ac_uint4 _ucprop_size = %d;\n\n", NUMPROPS);
1346
1347     fprintf(out, PREF "ac_uint2 _ucprop_offsets[] = {");
1348
1349     for (i = 0; i<nprops; i++) {
1350        if (i) fprintf(out, ",");
1351        if (!(i&7)) fprintf(out, "\n\t");
1352        else fprintf(out, " ");
1353        fprintf(out, "0x%04x", propcnt[i]);
1354     }
1355     fprintf(out, "\n};\n\n");
1356
1357     fprintf(out, PREF "ac_uint4 _ucprop_ranges[] = {");
1358
1359     k = 0;
1360     for (i = 0; i < NUMPROPS; i++) {
1361         if (proptbl[i].used > 0) {
1362           for (j=0; j<proptbl[i].used; j++) {
1363             if (k) fprintf(out, ",");
1364             if (!(k&3)) fprintf(out,"\n\t");
1365             else fprintf(out, " ");
1366             k++;
1367             fprintf(out, "0x%08x", proptbl[i].ranges[j]);
1368           }
1369         }
1370     }
1371     fprintf(out, "\n};\n\n");
1372 #else
1373     /*
1374      * Write the header.
1375      */
1376     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1377
1378     /*
1379      * Write the byte count.
1380      */
1381     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1382
1383     /*
1384      * Write the property list counts.
1385      */
1386     fwrite((char *) propcnt, sizeof(ac_uint2), nprops, out);
1387
1388     /*
1389      * Write the property lists.
1390      */
1391     for (i = 0; i < NUMPROPS; i++) {
1392         if (proptbl[i].used > 0)
1393           fwrite((char *) proptbl[i].ranges, sizeof(ac_uint4),
1394                  proptbl[i].used, out);
1395     }
1396
1397     fclose(out);
1398 #endif
1399
1400     /*****************************************************************
1401      *
1402      * Generate the case mapping data.
1403      *
1404      *****************************************************************/
1405
1406 #if HARDCODE_DATA
1407     fprintf(out, PREF "ac_uint4 _uccase_size = %d;\n\n",
1408         upper_used + lower_used + title_used);
1409
1410     fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%d, %d};\n\n",
1411         upper_used, lower_used);
1412     fprintf(out, PREF "ac_uint4 _uccase_map[] = {");
1413
1414     if (upper_used > 0)
1415       /*
1416        * Write the upper case table.
1417        */
1418       write_case(out, upper, upper_used, 1);
1419
1420     if (lower_used > 0)
1421       /*
1422        * Write the lower case table.
1423        */
1424       write_case(out, lower, lower_used, !upper_used);
1425
1426     if (title_used > 0)
1427       /*
1428        * Write the title case table.
1429        */
1430       write_case(out, title, title_used, !(upper_used||lower_used));
1431
1432     if (!(upper_used || lower_used || title_used))
1433         fprintf(out, "\t0");
1434
1435     fprintf(out, "\n};\n\n");
1436 #else
1437     /*
1438      * Open the case.dat file.
1439      */
1440     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath);
1441     if ((out = fopen(path, "wb")) == 0)
1442       return;
1443
1444     /*
1445      * Write the case mapping tables.
1446      */
1447     hdr[1] = upper_used + lower_used + title_used;
1448     casecnt[0] = upper_used;
1449     casecnt[1] = lower_used;
1450
1451     /*
1452      * Write the header.
1453      */
1454     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1455
1456     /*
1457      * Write the upper and lower case table sizes.
1458      */
1459     fwrite((char *) casecnt, sizeof(ac_uint2), 2, out);
1460
1461     if (upper_used > 0)
1462       /*
1463        * Write the upper case table.
1464        */
1465       fwrite((char *) upper, sizeof(_case_t), upper_used, out);
1466
1467     if (lower_used > 0)
1468       /*
1469        * Write the lower case table.
1470        */
1471       fwrite((char *) lower, sizeof(_case_t), lower_used, out);
1472
1473     if (title_used > 0)
1474       /*
1475        * Write the title case table.
1476        */
1477       fwrite((char *) title, sizeof(_case_t), title_used, out);
1478
1479     fclose(out);
1480 #endif
1481
1482     /*****************************************************************
1483      *
1484      * Generate the composition data.
1485      *
1486      *****************************************************************/
1487     
1488     /*
1489      * Create compositions from decomposition data
1490      */
1491     create_comps();
1492     
1493 #if HARDCODE_DATA
1494     fprintf(out, PREF "ac_uint4 _uccomp_size = %d;\n\n",
1495         comps_used * 4);
1496
1497     fprintf(out, PREF "ac_uint4 _uccomp_data[] = {");
1498
1499      /*
1500       * Now, if comps exist, write them out.
1501       */
1502     if (comps_used > 0) {
1503         for (i=0; i<comps_used; i++) {
1504             if (i) fprintf(out, ",");
1505             fprintf(out, "\n\t0x%08x, 0x%08x, 0x%08x, 0x%08x",
1506                 comps[i].comp, comps[i].count, comps[i].code1, comps[i].code2);
1507         }
1508     } else {
1509         fprintf(out, "\t0");
1510     }
1511     fprintf(out, "\n};\n\n");
1512 #else
1513     /*
1514      * Open the comp.dat file.
1515      */
1516     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath);
1517     if ((out = fopen(path, "wb")) == 0)
1518         return;
1519     
1520     /*
1521      * Write the header.
1522      */
1523     hdr[1] = (ac_uint2) comps_used * 4;
1524     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1525     
1526     /*
1527      * Write out the byte count to maintain header size.
1528      */
1529     bytes = comps_used * sizeof(_comp_t);
1530     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1531     
1532     /*
1533      * Now, if comps exist, write them out.
1534      */
1535     if (comps_used > 0)
1536         fwrite((char *) comps, sizeof(_comp_t), comps_used, out);
1537     
1538     fclose(out);
1539 #endif
1540     
1541     /*****************************************************************
1542      *
1543      * Generate the decomposition data.
1544      *
1545      *****************************************************************/
1546
1547     /*
1548      * Fully expand all decompositions before generating the output file.
1549      */
1550     expand_decomp();
1551
1552 #if HARDCODE_DATA
1553     fprintf(out, PREF "ac_uint4 _ucdcmp_size = %d;\n\n",
1554         decomps_used * 2);
1555
1556     fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {");
1557
1558     if (decomps_used) {
1559         /*
1560          * Write the list of decomp nodes.
1561          */
1562         for (i = idx = 0; i < decomps_used; i++) {
1563             fprintf(out, "\n\t0x%08x, 0x%08x,", decomps[i].code, idx);
1564             idx += decomps[i].used;
1565         }
1566
1567         /*
1568          * Write the sentinel index as the last decomp node.
1569          */
1570         fprintf(out, "\n\t0x%08x\n};\n\n", idx);
1571
1572         fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {");
1573         /*
1574          * Write the decompositions themselves.
1575          */
1576         k = 0;
1577         for (i = 0; i < decomps_used; i++)
1578           for (j=0; j<decomps[i].used; j++) {
1579             if (k) fprintf(out, ",");
1580             if (!(k&3)) fprintf(out,"\n\t");
1581             else fprintf(out, " ");
1582             k++;
1583             fprintf(out, "0x%08x", decomps[i].decomp[j]);
1584           }
1585         fprintf(out, "\n};\n\n");
1586     }
1587 #else
1588     /*
1589      * Open the decomp.dat file.
1590      */
1591     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath);
1592     if ((out = fopen(path, "wb")) == 0)
1593       return;
1594
1595     hdr[1] = decomps_used;
1596
1597     /*
1598      * Write the header.
1599      */
1600     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1601
1602     /*
1603      * Write a temporary byte count which will be calculated as the
1604      * decompositions are written out.
1605      */
1606     bytes = 0;
1607     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1608
1609     if (decomps_used) {
1610         /*
1611          * Write the list of decomp nodes.
1612          */
1613         for (i = idx = 0; i < decomps_used; i++) {
1614             fwrite((char *) &decomps[i].code, sizeof(ac_uint4), 1, out);
1615             fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1616             idx += decomps[i].used;
1617         }
1618
1619         /*
1620          * Write the sentinel index as the last decomp node.
1621          */
1622         fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1623
1624         /*
1625          * Write the decompositions themselves.
1626          */
1627         for (i = 0; i < decomps_used; i++)
1628           fwrite((char *) decomps[i].decomp, sizeof(ac_uint4),
1629                  decomps[i].used, out);
1630
1631         /*
1632          * Seek back to the beginning and write the byte count.
1633          */
1634         bytes = (sizeof(ac_uint4) * idx) +
1635             (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
1636         fseek(out, sizeof(ac_uint2) << 1, 0L);
1637         fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1638
1639         fclose(out);
1640     }
1641 #endif
1642
1643 #ifdef HARDCODE_DATA
1644     fprintf(out, PREF "ac_uint4 _uckdcmp_size = %d;\n\n",
1645         kdecomps_used * 2);
1646
1647     fprintf(out, PREF "ac_uint4 _uckdcmp_nodes[] = {");
1648
1649     if (kdecomps_used) {
1650         /*
1651          * Write the list of kdecomp nodes.
1652          */
1653         for (i = idx = 0; i < kdecomps_used; i++) {
1654             fprintf(out, "\n\t0x%08x, 0x%08x,", kdecomps[i].code, idx);
1655             idx += kdecomps[i].used;
1656         }
1657
1658         /*
1659          * Write the sentinel index as the last decomp node.
1660          */
1661         fprintf(out, "\n\t0x%08x\n};\n\n", idx);
1662
1663         fprintf(out, PREF "ac_uint4 _uckdcmp_decomp[] = {");
1664
1665         /*
1666          * Write the decompositions themselves.
1667          */
1668         k = 0;
1669         for (i = 0; i < kdecomps_used; i++)
1670           for (j=0; j<kdecomps[i].used; j++) {
1671             if (k) fprintf(out, ",");
1672             if (!(k&3)) fprintf(out,"\n\t");
1673             else fprintf(out, " ");
1674             k++;
1675             fprintf(out, "0x%08x", kdecomps[i].decomp[j]);
1676           }
1677         fprintf(out, "\n};\n\n");
1678     }
1679 #else
1680     /*
1681      * Open the kdecomp.dat file.
1682      */
1683     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath);
1684     if ((out = fopen(path, "wb")) == 0)
1685       return;
1686
1687     hdr[1] = kdecomps_used;
1688
1689     /*
1690      * Write the header.
1691      */
1692     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1693
1694     /*
1695      * Write a temporary byte count which will be calculated as the
1696      * decompositions are written out.
1697      */
1698     bytes = 0;
1699     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1700
1701     if (kdecomps_used) {
1702         /*
1703          * Write the list of kdecomp nodes.
1704          */
1705         for (i = idx = 0; i < kdecomps_used; i++) {
1706             fwrite((char *) &kdecomps[i].code, sizeof(ac_uint4), 1, out);
1707             fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1708             idx += kdecomps[i].used;
1709         }
1710
1711         /*
1712          * Write the sentinel index as the last decomp node.
1713          */
1714         fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
1715
1716         /*
1717          * Write the decompositions themselves.
1718          */
1719         for (i = 0; i < kdecomps_used; i++)
1720           fwrite((char *) kdecomps[i].decomp, sizeof(ac_uint4),
1721                  kdecomps[i].used, out);
1722
1723         /*
1724          * Seek back to the beginning and write the byte count.
1725          */
1726         bytes = (sizeof(ac_uint4) * idx) +
1727             (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
1728         fseek(out, sizeof(ac_uint2) << 1, 0L);
1729         fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1730
1731         fclose(out);
1732     }
1733 #endif
1734
1735     /*****************************************************************
1736      *
1737      * Generate the combining class data.
1738      *
1739      *****************************************************************/
1740 #ifdef HARDCODE_DATA
1741     fprintf(out, PREF "ac_uint4 _uccmcl_size = %d;\n\n", ccl_used);
1742
1743     fprintf(out, PREF "ac_uint4 _uccmcl_nodes[] = {");
1744
1745     if (ccl_used > 0) {
1746         /*
1747          * Write the combining class ranges out.
1748          */
1749         for (i = 0; i<ccl_used; i++) {
1750             if (i) fprintf(out, ",");
1751             if (!(i&3)) fprintf(out, "\n\t");
1752             else fprintf(out, " ");
1753             fprintf(out, "0x%08x", ccl[i]);
1754         }
1755     } else {
1756         fprintf(out, "\t0");
1757     }
1758     fprintf(out, "\n};\n\n");
1759 #else
1760     /*
1761      * Open the cmbcl.dat file.
1762      */
1763     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath);
1764     if ((out = fopen(path, "wb")) == 0)
1765       return;
1766
1767     /*
1768      * Set the number of ranges used.  Each range has a combining class which
1769      * means each entry is a 3-tuple.
1770      */
1771     hdr[1] = ccl_used / 3;
1772
1773     /*
1774      * Write the header.
1775      */
1776     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1777
1778     /*
1779      * Write out the byte count to maintain header size.
1780      */
1781     bytes = ccl_used * sizeof(ac_uint4);
1782     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1783
1784     if (ccl_used > 0)
1785       /*
1786        * Write the combining class ranges out.
1787        */
1788       fwrite((char *) ccl, sizeof(ac_uint4), ccl_used, out);
1789
1790     fclose(out);
1791 #endif
1792
1793     /*****************************************************************
1794      *
1795      * Generate the number data.
1796      *
1797      *****************************************************************/
1798
1799 #if HARDCODE_DATA
1800     fprintf(out, PREF "ac_uint4 _ucnum_size = %d;\n\n", ncodes_used<<1);
1801
1802     fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {");
1803
1804     /*
1805      * Now, if number mappings exist, write them out.
1806      */
1807     if (ncodes_used > 0) {
1808         for (i = 0; i<ncodes_used; i++) {
1809             if (i) fprintf(out, ",");
1810             if (!(i&1)) fprintf(out, "\n\t");
1811             else fprintf(out, " ");
1812             fprintf(out, "0x%08x, 0x%08x", ncodes[i].code, ncodes[i].idx);
1813         }
1814         fprintf(out, "\n};\n\n");
1815
1816         fprintf(out, PREF "short _ucnum_vals[] = {");
1817         for (i = 0; i<nums_used; i++) {
1818             if (i) fprintf(out, ",");
1819             if (!(i&3)) fprintf(out, "\n\t");
1820             else fprintf(out, " ");
1821             if (nums[i].numerator < 0) {
1822                 fprintf(out, "%6d, 0x%04x",
1823                   nums[i].numerator, nums[i].denominator);
1824             } else {
1825                 fprintf(out, "0x%04x, 0x%04x",
1826                   nums[i].numerator, nums[i].denominator);
1827             }
1828         }
1829         fprintf(out, "\n};\n\n");
1830     }
1831 #else
1832     /*
1833      * Open the num.dat file.
1834      */
1835     snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath);
1836     if ((out = fopen(path, "wb")) == 0)
1837       return;
1838
1839     /*
1840      * The count part of the header will be the total number of codes that
1841      * have numbers.
1842      */
1843     hdr[1] = (ac_uint2) (ncodes_used << 1);
1844     bytes = (ncodes_used * sizeof(_codeidx_t)) + (nums_used * sizeof(_num_t));
1845
1846     /*
1847      * Write the header.
1848      */
1849     fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
1850
1851     /*
1852      * Write out the byte count to maintain header size.
1853      */
1854     fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
1855
1856     /*
1857      * Now, if number mappings exist, write them out.
1858      */
1859     if (ncodes_used > 0) {
1860         fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out);
1861         fwrite((char *) nums, sizeof(_num_t), nums_used, out);
1862     }
1863 #endif
1864
1865     fclose(out);
1866 }
1867
1868 static void
1869 usage(char *prog)
1870 {
1871     fprintf(stderr,
1872             "Usage: %s [-o output-directory|-x composition-exclusions]", prog);
1873     fprintf(stderr, " datafile1 datafile2 ...\n\n");
1874     fprintf(stderr,
1875             "-o output-directory\n\t\tWrite the output files to a different");
1876     fprintf(stderr, " directory (default: .).\n");
1877     fprintf(stderr,
1878             "-x composition-exclusion\n\t\tFile of composition codes");
1879     fprintf(stderr, " that should be excluded.\n");
1880     exit(1);
1881 }
1882
1883 int
1884 main(int argc, char *argv[])
1885 {
1886     FILE *in;
1887     char *prog, *opath;
1888
1889     prog = lutil_progname( "ucgendat", argc, argv );
1890
1891     opath = 0;
1892     in = stdin;
1893
1894     argc--;
1895     argv++;
1896
1897     while (argc > 0) {
1898         if (argv[0][0] == '-') {
1899             switch (argv[0][1]) {
1900               case 'o':
1901                 argc--;
1902                 argv++;
1903                 opath = argv[0];
1904                 break;
1905               case 'x':
1906                 argc--;
1907                 argv++;
1908                 if ((in = fopen(argv[0], "r")) == 0)
1909                   fprintf(stderr,
1910                           "%s: unable to open composition exclusion file %s\n",
1911                           prog, argv[0]);
1912                 else {
1913                     read_compexdata(in);
1914                     fclose(in);
1915                     in = 0;
1916                 }
1917                 break;
1918               default:
1919                 usage(prog);
1920             }
1921         } else {
1922             if (in != stdin && in != NULL)
1923               fclose(in);
1924             if ((in = fopen(argv[0], "r")) == 0)
1925               fprintf(stderr, "%s: unable to open ctype file %s\n",
1926                       prog, argv[0]);
1927             else {
1928                 read_cdata(in);
1929                 fclose(in);
1930                 in = 0;
1931             }
1932         }
1933         argc--;
1934         argv++;
1935     }
1936
1937     if (opath == 0)
1938       opath = ".";
1939     write_cdata(opath);
1940
1941     return 0;
1942 }