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