]> git.sur5r.net Git - openldap/blobdiff - libraries/liblunicode/ucdata/ucgendat.c
ITS#5887 add native support for cipher suites for GnuTLS >= 2.2.0
[openldap] / libraries / liblunicode / ucdata / ucgendat.c
index 09107ac0b05ccfdd031630f3a13a507643478d76..538d4293c474f4dad2506a6bc41c9c21fe33ad7d 100644 (file)
@@ -1,6 +1,18 @@
 /* $OpenLDAP$ */
-/*
- * Copyright 2001 Computing Research Labs, New Mexico State University
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 1998-2009 The OpenLDAP Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* Copyright 2001 Computing Research Labs, New Mexico State University
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
 #include "ldap_config.h"
 
 #include <stdio.h>
+#include <ac/ctype.h>
 #include <ac/stdlib.h>
 #include <ac/string.h>
 #include <ac/unistd.h>
 
+#include <ac/bytes.h>
+
+#include <lutil.h>
+
+#ifndef HARDCODE_DATA
+#define        HARDCODE_DATA   1
+#endif
+
+#undef ishdigit
 #define ishdigit(cc) (((cc) >= '0' && (cc) <= '9') ||\
                       ((cc) >= 'A' && (cc) <= 'F') ||\
                       ((cc) >= 'a' && (cc) <= 'f'))
@@ -38,7 +60,7 @@
  * A header written to the output file with the byte-order-mark and the number
  * of property nodes.
  */
-static unsigned short hdr[2] = {0xfeff, 0};
+static ac_uint2 hdr[2] = {0xfeff, 0};
 
 #define NUMPROPS 50
 #define NEEDPROPS (NUMPROPS + (4 - (NUMPROPS & 3)))
@@ -75,9 +97,9 @@ static _prop_t props[NUMPROPS] = {
 };
 
 typedef struct {
-    unsigned long *ranges;
-    unsigned short used;
-    unsigned short size;
+    ac_uint4 *ranges;
+    ac_uint2 used;
+    ac_uint2 size;
 } _ranges_t;
 
 static _ranges_t proptbl[NUMPROPS];
@@ -85,87 +107,92 @@ static _ranges_t proptbl[NUMPROPS];
 /*
  * Make sure this array is sized to be on a 4-byte boundary at compile time.
  */
-static unsigned short propcnt[NEEDPROPS];
+static ac_uint2 propcnt[NEEDPROPS];
 
 /*
  * Array used to collect a decomposition before adding it to the decomposition
  * table.
  */
-static unsigned long dectmp[64];
-static unsigned long dectmp_size;
+static ac_uint4 dectmp[64];
+static ac_uint4 dectmp_size;
 
 typedef struct {
-    unsigned long code;
-    unsigned short size;
-    unsigned short used;
-    unsigned long *decomp;
+    ac_uint4 code;
+    ac_uint2 size;
+    ac_uint2 used;
+    ac_uint4 *decomp;
 } _decomp_t;
 
 /*
  * List of decomposition.  Created and expanded in order as the characters are
- * encountered.
+ * encountered. First list contains canonical mappings, second also includes
+ * compatibility mappings.
  */
 static _decomp_t *decomps;
-static unsigned long decomps_used;
-static unsigned long decomps_size;
+static ac_uint4 decomps_used;
+static ac_uint4 decomps_size;
+
+static _decomp_t *kdecomps;
+static ac_uint4 kdecomps_used;
+static ac_uint4 kdecomps_size;
 
 /*
  * Composition exclusion table stuff.
  */
-#define COMPEX_SET(c) (compexs[(c) >> 15] |= (1 << ((c) & 31)))
-#define COMPEX_TEST(c) (compexs[(c) >> 15] & (1 << ((c) & 31)))
-static unsigned long compexs[2048];
+#define COMPEX_SET(c) (compexs[(c) >> 5] |= (1 << ((c) & 31)))
+#define COMPEX_TEST(c) (compexs[(c) >> 5] & (1 << ((c) & 31)))
+static ac_uint4 compexs[8192];
 
 /*
  * Struct for holding a composition pair, and array of composition pairs
  */
 typedef struct {
-    unsigned long comp;
-    unsigned long count;
-    unsigned long code1;
-    unsigned long code2;
+    ac_uint4 comp;
+    ac_uint4 count;
+    ac_uint4 code1;
+    ac_uint4 code2;
 } _comp_t;
 
 static _comp_t *comps;
-static unsigned long comps_used;
+static ac_uint4 comps_used;
 
 /*
  * Types and lists for handling lists of case mappings.
  */
 typedef struct {
-    unsigned long key;
-    unsigned long other1;
-    unsigned long other2;
+    ac_uint4 key;
+    ac_uint4 other1;
+    ac_uint4 other2;
 } _case_t;
 
 static _case_t *upper;
 static _case_t *lower;
 static _case_t *title;
-static unsigned long upper_used;
-static unsigned long upper_size;
-static unsigned long lower_used;
-static unsigned long lower_size;
-static unsigned long title_used;
-static unsigned long title_size;
+static ac_uint4 upper_used;
+static ac_uint4 upper_size;
+static ac_uint4 lower_used;
+static ac_uint4 lower_size;
+static ac_uint4 title_used;
+static ac_uint4 title_size;
 
 /*
  * Array used to collect case mappings before adding them to a list.
  */
-static unsigned long cases[3];
+static ac_uint4 cases[3];
 
 /*
  * An array to hold ranges for combining classes.
  */
-static unsigned long *ccl;
-static unsigned long ccl_used;
-static unsigned long ccl_size;
+static ac_uint4 *ccl;
+static ac_uint4 ccl_used;
+static ac_uint4 ccl_size;
 
 /*
  * Structures for handling numbers.
  */
 typedef struct {
-    unsigned long code;
-    unsigned long idx;
+    ac_uint4 code;
+    ac_uint4 idx;
 } _codeidx_t;
 
 typedef struct {
@@ -177,22 +204,22 @@ typedef struct {
  * Arrays to hold the mapping of codes to numbers.
  */
 static _codeidx_t *ncodes;
-static unsigned long ncodes_used;
-static unsigned long ncodes_size;
+static ac_uint4 ncodes_used;
+static ac_uint4 ncodes_size;
 
 static _num_t *nums;
-static unsigned long nums_used;
-static unsigned long nums_size;
+static ac_uint4 nums_used;
+static ac_uint4 nums_size;
 
 /*
  * Array for holding numbers.
  */
 static _num_t *nums;
-static unsigned long nums_used;
-static unsigned long nums_size;
+static ac_uint4 nums_used;
+static ac_uint4 nums_size;
 
 static void
-add_range(unsigned long start, unsigned long end, char *p1, char *p2)
+add_range(ac_uint4 start, ac_uint4 end, char *p1, char *p2)
 {
     int i, j, k, len;
     _ranges_t *rlp;
@@ -225,12 +252,12 @@ add_range(unsigned long start, unsigned long end, char *p1, char *p2)
          */
         if (rlp->used == rlp->size) {
             if (rlp->size == 0)
-              rlp->ranges = (unsigned long *)
-                  malloc(sizeof(unsigned long) << 3);
+              rlp->ranges = (ac_uint4 *)
+                  malloc(sizeof(ac_uint4) << 3);
             else
-              rlp->ranges = (unsigned long *)
+              rlp->ranges = (ac_uint4 *)
                   realloc((char *) rlp->ranges,
-                          sizeof(unsigned long) * (rlp->size + 8));
+                          sizeof(ac_uint4) * (rlp->size + 8));
             rlp->size += 8;
         }
 
@@ -290,10 +317,10 @@ add_range(unsigned long start, unsigned long end, char *p1, char *p2)
 }
 
 static void
-ordered_range_insert(unsigned long c, char *name, int len)
+ordered_range_insert(ac_uint4 c, char *name, int len)
 {
     int i, j;
-    unsigned long s, e;
+    ac_uint4 s, e;
     _ranges_t *rlp;
 
     if (len == 0)
@@ -333,12 +360,12 @@ ordered_range_insert(unsigned long c, char *name, int len)
      */
     if (rlp->used == rlp->size) {
         if (rlp->size == 0)
-          rlp->ranges = (unsigned long *)
-              malloc(sizeof(unsigned long) << 3);
+          rlp->ranges = (ac_uint4 *)
+              malloc(sizeof(ac_uint4) << 3);
         else
-          rlp->ranges = (unsigned long *)
+          rlp->ranges = (ac_uint4 *)
               realloc((char *) rlp->ranges,
-                      sizeof(unsigned long) * (rlp->size + 8));
+                      sizeof(ac_uint4) * (rlp->size + 8));
         rlp->size += 8;
     }
 
@@ -415,41 +442,56 @@ ordered_range_insert(unsigned long c, char *name, int len)
 }
 
 static void
-add_decomp(unsigned long code)
+add_decomp(ac_uint4 code, short compat)
 {
-    unsigned long i, j, size;
-
+    ac_uint4 i, j, size;
+    _decomp_t **pdecomps;
+    ac_uint4 *pdecomps_used;
+    ac_uint4 *pdecomps_size;
+
+    if (compat) {
+       pdecomps = &kdecomps;
+       pdecomps_used = &kdecomps_used;
+       pdecomps_size = &kdecomps_size;
+    } else {
+       pdecomps = &decomps;
+       pdecomps_used = &decomps_used;
+       pdecomps_size = &decomps_size;
+    }
+    
     /*
      * Add the code to the composite property.
      */
-    ordered_range_insert(code, "Cm", 2);
+    if (!compat) {
+       ordered_range_insert(code, "Cm", 2);
+    }
 
     /*
      * Locate the insertion point for the code.
      */
-    for (i = 0; i < decomps_used && code > decomps[i].code; i++) ;
+    for (i = 0; i < *pdecomps_used && code > (*pdecomps)[i].code; i++) ;
 
     /*
      * Allocate space for a new decomposition.
      */
-    if (decomps_used == decomps_size) {
-        if (decomps_size == 0)
-          decomps = (_decomp_t *) malloc(sizeof(_decomp_t) << 3);
+    if (*pdecomps_used == *pdecomps_size) {
+        if (*pdecomps_size == 0)
+          *pdecomps = (_decomp_t *) malloc(sizeof(_decomp_t) << 3);
         else
-          decomps = (_decomp_t *)
-              realloc((char *) decomps,
-                      sizeof(_decomp_t) * (decomps_size + 8));
-        (void) memset((char *) (decomps + decomps_size), '\0',
+          *pdecomps = (_decomp_t *)
+              realloc((char *) *pdecomps,
+                      sizeof(_decomp_t) * (*pdecomps_size + 8));
+        (void) memset((char *) (*pdecomps + *pdecomps_size), '\0',
                       sizeof(_decomp_t) << 3);
-        decomps_size += 8;
+        *pdecomps_size += 8;
     }
 
-    if (i < decomps_used && code != decomps[i].code) {
+    if (i < *pdecomps_used && code != (*pdecomps)[i].code) {
         /*
          * Shift the decomps up by one if the codes don't match.
          */
-        for (j = decomps_used; j > i; j--)
-          (void) AC_MEMCPY((char *) &decomps[j], (char *) &decomps[j - 1],
+        for (j = *pdecomps_used; j > i; j--)
+          (void) AC_MEMCPY((char *) &(*pdecomps)[j], (char *) &(*pdecomps)[j - 1],
                         sizeof(_decomp_t));
     }
 
@@ -457,37 +499,37 @@ add_decomp(unsigned long code)
      * Insert or replace a decomposition.
      */
     size = dectmp_size + (4 - (dectmp_size & 3));
-    if (decomps[i].size < size) {
-        if (decomps[i].size == 0)
-          decomps[i].decomp = (unsigned long *)
-              malloc(sizeof(unsigned long) * size);
+    if ((*pdecomps)[i].size < size) {
+        if ((*pdecomps)[i].size == 0)
+          (*pdecomps)[i].decomp = (ac_uint4 *)
+              malloc(sizeof(ac_uint4) * size);
         else
-          decomps[i].decomp = (unsigned long *)
-              realloc((char *) decomps[i].decomp,
-                      sizeof(unsigned long) * size);
-        decomps[i].size = size;
+          (*pdecomps)[i].decomp = (ac_uint4 *)
+              realloc((char *) (*pdecomps)[i].decomp,
+                      sizeof(ac_uint4) * size);
+        (*pdecomps)[i].size = size;
     }
 
-    if (decomps[i].code != code)
-      decomps_used++;
+    if ((*pdecomps)[i].code != code)
+      (*pdecomps_used)++;
 
-    decomps[i].code = code;
-    decomps[i].used = dectmp_size;
-    (void) AC_MEMCPY((char *) decomps[i].decomp, (char *) dectmp,
-                  sizeof(unsigned long) * dectmp_size);
+    (*pdecomps)[i].code = code;
+    (*pdecomps)[i].used = dectmp_size;
+    (void) AC_MEMCPY((char *) (*pdecomps)[i].decomp, (char *) dectmp,
+                  sizeof(ac_uint4) * dectmp_size);
 
     /*
      * NOTICE: This needs changing later so it is more general than simply
      * pairs.  This calculation is done here to simplify allocation elsewhere.
      */
-    if (dectmp_size == 2)
+    if (!compat && dectmp_size == 2)
       comps_used++;
 }
 
 static void
-add_title(unsigned long code)
+add_title(ac_uint4 code)
 {
-    unsigned long i, j;
+    ac_uint4 i, j;
 
     /*
      * Always map the code to itself.
@@ -525,9 +567,9 @@ add_title(unsigned long code)
 }
 
 static void
-add_upper(unsigned long code)
+add_upper(ac_uint4 code)
 {
-    unsigned long i, j;
+    ac_uint4 i, j;
 
     /*
      * Always map the code to itself.
@@ -572,9 +614,9 @@ add_upper(unsigned long code)
 }
 
 static void
-add_lower(unsigned long code)
+add_lower(ac_uint4 code)
 {
-    unsigned long i, j;
+    ac_uint4 i, j;
 
     /*
      * Always map the code to itself.
@@ -619,16 +661,16 @@ add_lower(unsigned long code)
 }
 
 static void
-ordered_ccl_insert(unsigned long c, unsigned long ccl_code)
+ordered_ccl_insert(ac_uint4 c, ac_uint4 ccl_code)
 {
-    unsigned long i, j;
+    ac_uint4 i, j;
 
     if (ccl_used == ccl_size) {
         if (ccl_size == 0)
-          ccl = (unsigned long *) malloc(sizeof(unsigned long) * 24);
+          ccl = (ac_uint4 *) malloc(sizeof(ac_uint4) * 24);
         else
-          ccl = (unsigned long *)
-              realloc((char *) ccl, sizeof(unsigned long) * (ccl_size + 24));
+          ccl = (ac_uint4 *)
+              realloc((char *) ccl, sizeof(ac_uint4) * (ccl_size + 24));
         ccl_size += 24;
     }
 
@@ -691,10 +733,10 @@ ordered_ccl_insert(unsigned long c, unsigned long ccl_code)
  * Adds a number if it does not already exist and returns an index value
  * multiplied by 2.
  */
-static unsigned long
+static ac_uint4
 make_number(short num, short denom)
 {
-    unsigned long n;
+    ac_uint4 n;
 
     /*
      * Determine if the number already exists.
@@ -721,9 +763,9 @@ make_number(short num, short denom)
 }
 
 static void
-add_number(unsigned long code, short num, short denom)
+add_number(ac_uint4 code, short num, short denom)
 {
-    unsigned long i, j;
+    ac_uint4 i, j;
 
     /*
      * Insert the code in order.
@@ -734,7 +776,7 @@ add_number(unsigned long code, short num, short denom)
      * Handle the case of the codes matching and simply replace the number
      * that was there before.
      */
-    if (ncodes_used > 0 && code == ncodes[i].code) {
+    if (i < ncodes_used && code == ncodes[i].code) {
         ncodes[i].idx = make_number(num, denom);
         return;
     }
@@ -774,12 +816,13 @@ add_number(unsigned long code, short num, short denom)
 static void
 read_cdata(FILE *in)
 {
-    unsigned long i, lineno, skip, code, ccl_code;
-    short wnum, neg, number[2];
+    ac_uint4 i, lineno, skip, code, ccl_code;
+    short wnum, neg, number[2], compat;
     char line[512], *s, *e;
 
     lineno = skip = 0;
-    while (fscanf(in, "%[^\n]\n", line) != EOF) {
+    while (fgets(line, sizeof(line), in)) {
+       if( (s=strchr(line, '\n')) ) *s = '\0';
         lineno++;
 
         /*
@@ -817,8 +860,17 @@ read_cdata(FILE *in)
          * 3. D800-DFFF Surrogates.
          * 4. E000-F8FF Private Use Area.
          * 5. F900-FA2D Han compatibility.
+        * ...Plus additional ranges in newer Unicode versions...
          */
         switch (code) {
+         case 0x3400:
+           /* CJK Ideograph Extension A */
+            add_range(0x3400, 0x4db5, "Lo", "L");
+
+            add_range(0x3400, 0x4db5, "Cp", 0);
+
+           skip = 1;
+           break;
           case 0x4e00:
             /*
              * The Han ideographs.
@@ -872,6 +924,26 @@ read_cdata(FILE *in)
             add_range(0xf900, 0xfaff, "Cp", 0);
 
             skip = 1;
+           break;
+         case 0x20000:
+           /* CJK Ideograph Extension B */
+            add_range(0x20000, 0x2a6d6, "Lo", "L");
+
+            add_range(0x20000, 0x2a6d6, "Cp", 0);
+
+           skip = 1;
+           break;
+         case 0xf0000:
+           /* Plane 15 private use */
+           add_range(0xf0000, 0xffffd, "Co", "L");
+           skip = 1;
+           break;
+
+         case 0x100000:
+           /* Plane 16 private use */
+           add_range(0x100000, 0x10fffd, "Co", "L");
+           skip = 1;
+           break;
         }
 
         if (skip)
@@ -928,7 +1000,14 @@ read_cdata(FILE *in)
          * Check for a decomposition.
          */
         s = ++e;
-        if (*s != ';' && *s != '<') {
+        if (*s != ';') {
+           compat = *s == '<';
+           if (compat) {
+               /*
+                * Skip compatibility formatting tag.
+                */
+               while (*s++ != '>');
+           }
             /*
              * Collect the codes of the decomposition.
              */
@@ -937,7 +1016,7 @@ read_cdata(FILE *in)
                  * Skip all leading non-hex digits.
                  */
                 while (!ishdigit(*s))
-                  s++;
+                 s++;
 
                 for (dectmp[dectmp_size] = 0; ishdigit(*s); s++) {
                     dectmp[dectmp_size] <<= 4;
@@ -955,8 +1034,12 @@ read_cdata(FILE *in)
              * If there are any codes in the temporary decomposition array,
              * then add the character with its decomposition.
              */
-            if (dectmp_size > 0)
-              add_decomp(code);
+            if (dectmp_size > 0) {
+               if (!compat) {
+                   add_decomp(code, 0);
+               }
+               add_decomp(code, 1);
+           }
         }
 
         /*
@@ -995,7 +1078,7 @@ read_cdata(FILE *in)
              * Adjust the denominator in case of integers and add the number.
              */
             if (wnum == 0)
-              number[1] = number[0];
+              number[1] = 1;
 
             add_number(code, number[0], number[1]);
         }
@@ -1047,33 +1130,35 @@ read_cdata(FILE *in)
 }
 
 static _decomp_t *
-find_decomp(unsigned long code)
+find_decomp(ac_uint4 code, short compat)
 {
     long l, r, m;
-
+    _decomp_t *decs;
+    
     l = 0;
-    r = decomps_used - 1;
+    r = (compat ? kdecomps_used : decomps_used) - 1;
+    decs = compat ? kdecomps : decomps;
     while (l <= r) {
         m = (l + r) >> 1;
-        if (code > decomps[m].code)
+        if (code > decs[m].code)
           l = m + 1;
-        else if (code < decomps[m].code)
+        else if (code < decs[m].code)
           r = m - 1;
         else
-          return &decomps[m];
+          return &decs[m];
     }
     return 0;
 }
 
 static void
-decomp_it(_decomp_t *d)
+decomp_it(_decomp_t *d, short compat)
 {
-    unsigned long i;
+    ac_uint4 i;
     _decomp_t *dp;
 
     for (i = 0; i < d->used; i++) {
-        if ((dp = find_decomp(d->decomp[i])) != 0)
-          decomp_it(dp);
+        if ((dp = find_decomp(d->decomp[i], compat)) != 0)
+          decomp_it(dp, compat);
         else
           dectmp[dectmp_size++] = d->decomp[i];
     }
@@ -1086,19 +1171,27 @@ decomp_it(_decomp_t *d)
 static void
 expand_decomp(void)
 {
-    unsigned long i;
+    ac_uint4 i;
 
     for (i = 0; i < decomps_used; i++) {
         dectmp_size = 0;
-        decomp_it(&decomps[i]);
+        decomp_it(&decomps[i], 0);
+        if (dectmp_size > 0)
+          add_decomp(decomps[i].code, 0);
+    }
+
+    for (i = 0; i < kdecomps_used; i++) {
+        dectmp_size = 0;
+        decomp_it(&kdecomps[i], 1);
         if (dectmp_size > 0)
-          add_decomp(decomps[i].code);
+          add_decomp(kdecomps[i].code, 1);
     }
 }
 
 static int
-cmpcomps(_comp_t *comp1, _comp_t *comp2)
+cmpcomps(const void *v_comp1, const void *v_comp2)
 {
+       const _comp_t *comp1 = v_comp1, *comp2 = v_comp2;
     long diff = comp1->code1 - comp2->code1;
 
     if (!diff)
@@ -1112,12 +1205,14 @@ cmpcomps(_comp_t *comp1, _comp_t *comp2)
 static void
 read_compexdata(FILE *in)
 {
-    unsigned short i, code;
+    ac_uint2 i;
+    ac_uint4 code;
     char line[512], *s;
 
-    (void) memset((char *) compexs, 0, sizeof(unsigned long) << 11);
+    (void) memset((char *) compexs, 0, sizeof(compexs));
 
-    while (fscanf(in, "%[^\n]\n", line) != EOF) {
+    while (fgets(line, sizeof(line), in)) {
+       if( (s=strchr(line, '\n')) ) *s = '\0';
         /*
          * Skip blank lines and lines that start with a '#'.
          */
@@ -1125,10 +1220,11 @@ read_compexdata(FILE *in)
            continue;
 
        /*
-         * Collect the code.  Assume max 4 digits
+         * Collect the code.  Assume max 6 digits
          */
 
-       for (s = line, i = code = 0; *s != '#' && i < 4; i++, s++) {
+       for (s = line, i = code = 0; *s != '#' && i < 6; i++, s++) {
+           if (isspace((unsigned char)*s)) break;
             code <<= 4;
             if (*s >= '0' && *s <= '9')
                code += *s - '0';
@@ -1147,7 +1243,7 @@ read_compexdata(FILE *in)
 static void
 create_comps(void)
 {
-    unsigned long i, cu;
+    ac_uint4 i, cu;
 
     comps = (_comp_t *) malloc(comps_used * sizeof(_comp_t));
 
@@ -1161,17 +1257,40 @@ create_comps(void)
        cu++;
     }
     comps_used = cu;
-    qsort(comps, comps_used, sizeof(_comp_t),
-         (int (*)(const void *, const void *)) cmpcomps);
+    qsort(comps, comps_used, sizeof(_comp_t), cmpcomps);
 }
 
+#if HARDCODE_DATA
+static void
+write_case(FILE *out, _case_t *tab, int num, int first)
+{
+    int i;
+
+    for (i=0; i<num; i++) {
+       if (first) first = 0;
+       else fprintf(out, ",");
+       fprintf(out, "\n\t0x%08lx, 0x%08lx, 0x%08lx",
+               (unsigned long) tab[i].key, (unsigned long) tab[i].other1,
+               (unsigned long) tab[i].other2);
+    }
+}
+
+#define PREF "static const "
+
+#endif
+
 static void
 write_cdata(char *opath)
 {
     FILE *out;
-    unsigned long i, idx, bytes, nprops;
-    unsigned short casecnt[2];
+       ac_uint4 bytes;
+    ac_uint4 i, idx, nprops;
+#if !(HARDCODE_DATA)
+    ac_uint2 casecnt[2];
+#endif
     char path[BUFSIZ];
+#if HARDCODE_DATA
+    int j, k;
 
     /*****************************************************************
      *
@@ -1179,12 +1298,20 @@ write_cdata(char *opath)
      *
      *****************************************************************/
 
+    /*
+     * Open the output file.
+     */
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "uctable.h", opath);
+    if ((out = fopen(path, "w")) == 0)
+      return;
+#else
     /*
      * Open the ctype.dat file.
      */
-    sprintf(path, "%s%sctype.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "ctype.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
+#endif
 
     /*
      * Collect the offsets for the properties.  The offsets array is
@@ -1213,36 +1340,66 @@ write_cdata(char *opath)
      * Calculate the byte count needed and pad the property counts array to a
      * 4-byte boundary.
      */
-    if ((bytes = sizeof(unsigned short) * (NUMPROPS + 1)) & 3)
+    if ((bytes = sizeof(ac_uint2) * (NUMPROPS + 1)) & 3)
       bytes += 4 - (bytes & 3);
-    nprops = bytes / sizeof(unsigned short);
-    bytes += sizeof(unsigned long) * idx;
-        
+    nprops = bytes / sizeof(ac_uint2);
+    bytes += sizeof(ac_uint4) * idx;
+
+#if HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _ucprop_size = %d;\n\n", NUMPROPS);
+
+    fprintf(out, PREF "ac_uint2 _ucprop_offsets[] = {");
+
+    for (i = 0; i<nprops; i++) {
+       if (i) fprintf(out, ",");
+       if (!(i&7)) fprintf(out, "\n\t");
+       else fprintf(out, " ");
+       fprintf(out, "0x%04x", propcnt[i]);
+    }
+    fprintf(out, "\n};\n\n");
+
+    fprintf(out, PREF "ac_uint4 _ucprop_ranges[] = {");
+
+    k = 0;
+    for (i = 0; i < NUMPROPS; i++) {
+       if (proptbl[i].used > 0) {
+         for (j=0; j<proptbl[i].used; j++) {
+           if (k) fprintf(out, ",");
+           if (!(k&3)) fprintf(out,"\n\t");
+           else fprintf(out, " ");
+           k++;
+           fprintf(out, "0x%08lx", (unsigned long) proptbl[i].ranges[j]);
+         }
+       }
+    }
+    fprintf(out, "\n};\n\n");
+#else
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write the byte count.
      */
-    fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
 
     /*
      * Write the property list counts.
      */
-    fwrite((char *) propcnt, sizeof(unsigned short), nprops, out);
+    fwrite((char *) propcnt, sizeof(ac_uint2), nprops, out);
 
     /*
      * Write the property lists.
      */
     for (i = 0; i < NUMPROPS; i++) {
         if (proptbl[i].used > 0)
-          fwrite((char *) proptbl[i].ranges, sizeof(unsigned long),
+          fwrite((char *) proptbl[i].ranges, sizeof(ac_uint4),
                  proptbl[i].used, out);
     }
 
     fclose(out);
+#endif
 
     /*****************************************************************
      *
@@ -1250,10 +1407,41 @@ write_cdata(char *opath)
      *
      *****************************************************************/
 
+#if HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _uccase_size = %ld;\n\n",
+        (long) (upper_used + lower_used + title_used));
+
+    fprintf(out, PREF "ac_uint2 _uccase_len[2] = {%ld, %ld};\n\n",
+        (long) upper_used, (long) lower_used);
+    fprintf(out, PREF "ac_uint4 _uccase_map[] = {");
+
+    if (upper_used > 0)
+      /*
+       * Write the upper case table.
+       */
+      write_case(out, upper, upper_used, 1);
+
+    if (lower_used > 0)
+      /*
+       * Write the lower case table.
+       */
+      write_case(out, lower, lower_used, !upper_used);
+
+    if (title_used > 0)
+      /*
+       * Write the title case table.
+       */
+      write_case(out, title, title_used, !(upper_used||lower_used));
+
+    if (!(upper_used || lower_used || title_used))
+       fprintf(out, "\t0");
+
+    fprintf(out, "\n};\n\n");
+#else
     /*
      * Open the case.dat file.
      */
-    sprintf(path, "%s%scase.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "case.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1267,12 +1455,12 @@ write_cdata(char *opath)
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write the upper and lower case table sizes.
      */
-    fwrite((char *) casecnt, sizeof(unsigned short), 2, out);
+    fwrite((char *) casecnt, sizeof(ac_uint2), 2, out);
 
     if (upper_used > 0)
       /*
@@ -1293,6 +1481,7 @@ write_cdata(char *opath)
       fwrite((char *) title, sizeof(_case_t), title_used, out);
 
     fclose(out);
+#endif
 
     /*****************************************************************
      *
@@ -1305,24 +1494,45 @@ write_cdata(char *opath)
      */
     create_comps();
     
+#if HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _uccomp_size = %ld;\n\n",
+        comps_used * 4L);
+
+    fprintf(out, PREF "ac_uint4 _uccomp_data[] = {");
+
+     /*
+      * Now, if comps exist, write them out.
+      */
+    if (comps_used > 0) {
+       for (i=0; i<comps_used; i++) {
+           if (i) fprintf(out, ",");
+           fprintf(out, "\n\t0x%08lx, 0x%08lx, 0x%08lx, 0x%08lx",
+               (unsigned long) comps[i].comp, (unsigned long) comps[i].count,
+               (unsigned long) comps[i].code1, (unsigned long) comps[i].code2);
+       }
+    } else {
+       fprintf(out, "\t0");
+    }
+    fprintf(out, "\n};\n\n");
+#else
     /*
      * Open the comp.dat file.
      */
-    sprintf(path, "%s%scomp.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "comp.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
        return;
     
     /*
      * Write the header.
      */
-    hdr[1] = (unsigned short) comps_used * 4;
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    hdr[1] = (ac_uint2) comps_used * 4;
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
     
     /*
      * Write out the byte count to maintain header size.
      */
     bytes = comps_used * sizeof(_comp_t);
-    fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
     
     /*
      * Now, if comps exist, write them out.
@@ -1331,6 +1541,7 @@ write_cdata(char *opath)
         fwrite((char *) comps, sizeof(_comp_t), comps_used, out);
     
     fclose(out);
+#endif
     
     /*****************************************************************
      *
@@ -1343,10 +1554,47 @@ write_cdata(char *opath)
      */
     expand_decomp();
 
+#if HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _ucdcmp_size = %ld;\n\n",
+        decomps_used * 2L);
+
+    fprintf(out, PREF "ac_uint4 _ucdcmp_nodes[] = {");
+
+    if (decomps_used) {
+       /*
+        * Write the list of decomp nodes.
+        */
+       for (i = idx = 0; i < decomps_used; i++) {
+           fprintf(out, "\n\t0x%08lx, 0x%08lx,",
+               (unsigned long) decomps[i].code, (unsigned long) idx);
+           idx += decomps[i].used;
+       }
+
+       /*
+        * Write the sentinel index as the last decomp node.
+        */
+       fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);
+
+       fprintf(out, PREF "ac_uint4 _ucdcmp_decomp[] = {");
+       /*
+        * Write the decompositions themselves.
+        */
+       k = 0;
+       for (i = 0; i < decomps_used; i++)
+         for (j=0; j<decomps[i].used; j++) {
+           if (k) fprintf(out, ",");
+           if (!(k&3)) fprintf(out,"\n\t");
+           else fprintf(out, " ");
+           k++;
+           fprintf(out, "0x%08lx", (unsigned long) decomps[i].decomp[j]);
+         }
+       fprintf(out, "\n};\n\n");
+    }
+#else
     /*
      * Open the decomp.dat file.
      */
-    sprintf(path, "%s%sdecomp.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "decomp.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1355,58 +1603,171 @@ write_cdata(char *opath)
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write a temporary byte count which will be calculated as the
      * decompositions are written out.
      */
     bytes = 0;
-    fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
 
     if (decomps_used) {
         /*
          * Write the list of decomp nodes.
          */
         for (i = idx = 0; i < decomps_used; i++) {
-            fwrite((char *) &decomps[i].code, sizeof(unsigned long), 1, out);
-            fwrite((char *) &idx, sizeof(unsigned long), 1, out);
+            fwrite((char *) &decomps[i].code, sizeof(ac_uint4), 1, out);
+            fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
             idx += decomps[i].used;
         }
 
         /*
          * Write the sentinel index as the last decomp node.
          */
-        fwrite((char *) &idx, sizeof(unsigned long), 1, out);
+        fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
 
         /*
          * Write the decompositions themselves.
          */
         for (i = 0; i < decomps_used; i++)
-          fwrite((char *) decomps[i].decomp, sizeof(unsigned long),
+          fwrite((char *) decomps[i].decomp, sizeof(ac_uint4),
                  decomps[i].used, out);
 
         /*
          * Seek back to the beginning and write the byte count.
          */
-        bytes = (sizeof(unsigned long) * idx) +
-            (sizeof(unsigned long) * ((hdr[1] << 1) + 1));
-        fseek(out, sizeof(unsigned short) << 1, 0L);
-        fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+        bytes = (sizeof(ac_uint4) * idx) +
+            (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
+        fseek(out, sizeof(ac_uint2) << 1, 0L);
+        fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
+
+        fclose(out);
+    }
+#endif
+
+#ifdef HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _uckdcmp_size = %ld;\n\n",
+        kdecomps_used * 2L);
+
+    fprintf(out, PREF "ac_uint4 _uckdcmp_nodes[] = {");
+
+    if (kdecomps_used) {
+       /*
+        * Write the list of kdecomp nodes.
+        */
+       for (i = idx = 0; i < kdecomps_used; i++) {
+           fprintf(out, "\n\t0x%08lx, 0x%08lx,",
+               (unsigned long) kdecomps[i].code, (unsigned long) idx);
+           idx += kdecomps[i].used;
+       }
+
+       /*
+        * Write the sentinel index as the last decomp node.
+        */
+       fprintf(out, "\n\t0x%08lx\n};\n\n", (unsigned long) idx);
+
+       fprintf(out, PREF "ac_uint4 _uckdcmp_decomp[] = {");
+
+       /*
+        * Write the decompositions themselves.
+        */
+       k = 0;
+       for (i = 0; i < kdecomps_used; i++)
+         for (j=0; j<kdecomps[i].used; j++) {
+           if (k) fprintf(out, ",");
+           if (!(k&3)) fprintf(out,"\n\t");
+           else fprintf(out, " ");
+           k++;
+           fprintf(out, "0x%08lx", (unsigned long) kdecomps[i].decomp[j]);
+         }
+       fprintf(out, "\n};\n\n");
+    }
+#else
+    /*
+     * Open the kdecomp.dat file.
+     */
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "kdecomp.dat", opath);
+    if ((out = fopen(path, "wb")) == 0)
+      return;
+
+    hdr[1] = kdecomps_used;
+
+    /*
+     * Write the header.
+     */
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
+
+    /*
+     * Write a temporary byte count which will be calculated as the
+     * decompositions are written out.
+     */
+    bytes = 0;
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
+
+    if (kdecomps_used) {
+        /*
+         * Write the list of kdecomp nodes.
+         */
+        for (i = idx = 0; i < kdecomps_used; i++) {
+            fwrite((char *) &kdecomps[i].code, sizeof(ac_uint4), 1, out);
+            fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
+            idx += kdecomps[i].used;
+        }
+
+        /*
+         * Write the sentinel index as the last decomp node.
+         */
+        fwrite((char *) &idx, sizeof(ac_uint4), 1, out);
+
+        /*
+         * Write the decompositions themselves.
+         */
+        for (i = 0; i < kdecomps_used; i++)
+          fwrite((char *) kdecomps[i].decomp, sizeof(ac_uint4),
+                 kdecomps[i].used, out);
+
+        /*
+         * Seek back to the beginning and write the byte count.
+         */
+        bytes = (sizeof(ac_uint4) * idx) +
+            (sizeof(ac_uint4) * ((hdr[1] << 1) + 1));
+        fseek(out, sizeof(ac_uint2) << 1, 0L);
+        fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
 
         fclose(out);
     }
+#endif
 
     /*****************************************************************
      *
      * Generate the combining class data.
      *
      *****************************************************************/
+#ifdef HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _uccmcl_size = %ld;\n\n", (long) ccl_used);
 
+    fprintf(out, PREF "ac_uint4 _uccmcl_nodes[] = {");
+
+    if (ccl_used > 0) {
+       /*
+        * Write the combining class ranges out.
+        */
+       for (i = 0; i<ccl_used; i++) {
+           if (i) fprintf(out, ",");
+           if (!(i&3)) fprintf(out, "\n\t");
+           else fprintf(out, " ");
+           fprintf(out, "0x%08lx", (unsigned long) ccl[i]);
+       }
+    } else {
+       fprintf(out, "\t0");
+    }
+    fprintf(out, "\n};\n\n");
+#else
     /*
      * Open the cmbcl.dat file.
      */
-    sprintf(path, "%s%scmbcl.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "cmbcl.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1419,21 +1780,22 @@ write_cdata(char *opath)
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write out the byte count to maintain header size.
      */
-    bytes = ccl_used * sizeof(unsigned long);
-    fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+    bytes = ccl_used * sizeof(ac_uint4);
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
 
     if (ccl_used > 0)
       /*
        * Write the combining class ranges out.
        */
-      fwrite((char *) ccl, sizeof(unsigned long), ccl_used, out);
+      fwrite((char *) ccl, sizeof(ac_uint4), ccl_used, out);
 
     fclose(out);
+#endif
 
     /*****************************************************************
      *
@@ -1441,10 +1803,45 @@ write_cdata(char *opath)
      *
      *****************************************************************/
 
+#if HARDCODE_DATA
+    fprintf(out, PREF "ac_uint4 _ucnum_size = %lu;\n\n",
+        (unsigned long)ncodes_used<<1);
+
+    fprintf(out, PREF "ac_uint4 _ucnum_nodes[] = {");
+
+    /*
+     * Now, if number mappings exist, write them out.
+     */
+    if (ncodes_used > 0) {
+       for (i = 0; i<ncodes_used; i++) {
+           if (i) fprintf(out, ",");
+           if (!(i&1)) fprintf(out, "\n\t");
+           else fprintf(out, " ");
+           fprintf(out, "0x%08lx, 0x%08lx",
+               (unsigned long) ncodes[i].code, (unsigned long) ncodes[i].idx);
+       }
+       fprintf(out, "\n};\n\n");
+
+       fprintf(out, PREF "short _ucnum_vals[] = {");
+       for (i = 0; i<nums_used; i++) {
+           if (i) fprintf(out, ",");
+           if (!(i&3)) fprintf(out, "\n\t");
+           else fprintf(out, " ");
+           if (nums[i].numerator < 0) {
+               fprintf(out, "%6d, 0x%04x",
+                 nums[i].numerator, nums[i].denominator);
+           } else {
+               fprintf(out, "0x%04x, 0x%04x",
+                 nums[i].numerator, nums[i].denominator);
+           }
+       }
+       fprintf(out, "\n};\n\n");
+    }
+#else
     /*
      * Open the num.dat file.
      */
-    sprintf(path, "%s%snum.dat", opath, LDAP_DIRSEP);
+    snprintf(path, sizeof path, "%s" LDAP_DIRSEP "num.dat", opath);
     if ((out = fopen(path, "wb")) == 0)
       return;
 
@@ -1452,18 +1849,18 @@ write_cdata(char *opath)
      * The count part of the header will be the total number of codes that
      * have numbers.
      */
-    hdr[1] = (unsigned short) (ncodes_used << 1);
+    hdr[1] = (ac_uint2) (ncodes_used << 1);
     bytes = (ncodes_used * sizeof(_codeidx_t)) + (nums_used * sizeof(_num_t));
 
     /*
      * Write the header.
      */
-    fwrite((char *) hdr, sizeof(unsigned short), 2, out);
+    fwrite((char *) hdr, sizeof(ac_uint2), 2, out);
 
     /*
      * Write out the byte count to maintain header size.
      */
-    fwrite((char *) &bytes, sizeof(unsigned long), 1, out);
+    fwrite((char *) &bytes, sizeof(ac_uint4), 1, out);
 
     /*
      * Now, if number mappings exist, write them out.
@@ -1472,6 +1869,7 @@ write_cdata(char *opath)
         fwrite((char *) ncodes, sizeof(_codeidx_t), ncodes_used, out);
         fwrite((char *) nums, sizeof(_num_t), nums_used, out);
     }
+#endif
 
     fclose(out);
 }
@@ -1497,10 +1895,7 @@ main(int argc, char *argv[])
     FILE *in;
     char *prog, *opath;
 
-    if ((prog = strrchr(argv[0], *LDAP_DIRSEP)) != 0)
-      prog++;
-    else
-      prog = argv[0];
+    prog = lutil_progname( "ucgendat", argc, argv );
 
     opath = 0;
     in = stdin;
@@ -1519,7 +1914,7 @@ main(int argc, char *argv[])
               case 'x':
                 argc--;
                 argv++;
-                if ((in = fopen(argv[0], "rb")) == 0)
+                if ((in = fopen(argv[0], "r")) == 0)
                   fprintf(stderr,
                           "%s: unable to open composition exclusion file %s\n",
                           prog, argv[0]);
@@ -1535,7 +1930,7 @@ main(int argc, char *argv[])
         } else {
             if (in != stdin && in != NULL)
               fclose(in);
-            if ((in = fopen(argv[0], "rb")) == 0)
+            if ((in = fopen(argv[0], "r")) == 0)
               fprintf(stderr, "%s: unable to open ctype file %s\n",
                       prog, argv[0]);
             else {