]> arthur.barton.de Git - netatalk.git/commitdiff
Merge master
authorFrank Lahm <franklahm@googlemail.com>
Sat, 23 Apr 2011 07:43:31 +0000 (09:43 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Sat, 23 Apr 2011 07:43:31 +0000 (09:43 +0200)
90 files changed:
NEWS
bin/Makefile.am
bin/ad/ad_cp.c
bin/ad/ad_mv.c
bin/ad/ad_util.c
bin/uniconv/uniconv.c
config/afpd.conf.tmpl
configure.in
contrib/macusers/macusers.in
contrib/misc/make-casetable.pl [new file with mode: 0755]
contrib/shell_utils/asip-status.pl.in
etc/afpd/Makefile.am
etc/afpd/acls.c
etc/afpd/afp_avahi.c
etc/afpd/afp_config.c
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/auth.c
etc/afpd/catsearch.c
etc/afpd/dircache.c
etc/afpd/dircache.h
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.h
etc/afpd/globals.h
etc/afpd/mangle.c
etc/afpd/ofork.c
etc/afpd/status.c
etc/afpd/unix.c
etc/afpd/volume.c
etc/afpd/volume.h
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cmd_dbd.h
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/comm.c
etc/cnid_dbd/db_param.c
etc/cnid_dbd/db_param.h
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
etc/uams/uams_dhx2_pam.c
include/atalk/dsi.h
include/atalk/unicode.h
include/atalk/util.h
libatalk/acl/unix.c
libatalk/cnid/dbd/cnid_dbd.c
libatalk/dsi/README
libatalk/dsi/dsi_close.c
libatalk/dsi/dsi_getsess.c
libatalk/dsi/dsi_opensess.c
libatalk/dsi/dsi_stream.c
libatalk/unicode/.gitignore
libatalk/unicode/Makefile.am
libatalk/unicode/ucs2_casetable.h [deleted file]
libatalk/unicode/utf16_case.c [new file with mode: 0644]
libatalk/unicode/utf16_casetable.h [new file with mode: 0644]
libatalk/unicode/util_unistr.c
libatalk/util/Makefile.am
libatalk/util/cnid.c [new file with mode: 0644]
libatalk/util/logger.c
libatalk/util/server_child.c
libatalk/util/socket.c
libatalk/vfs/ea_sys.c
libatalk/vfs/extattr.c
libatalk/vfs/unix.c
macros/db3-check.m4
man/man1/.gitignore
man/man1/Makefile.am
man/man1/ad.1
man/man1/afpldaptest.1.tmpl [new file with mode: 0644]
man/man1/afppasswd.1
man/man1/apple_dump.1
man/man1/asip-status.pl.1.tmpl
man/man1/megatron.1
man/man1/netatalk-config.1
man/man1/uniconv.1.tmpl
man/man5/AppleVolumes.default.5.tmpl
man/man5/Makefile.am
man/man5/afp_ldap.conf.5.tmpl
man/man5/afp_signature.conf.5.tmpl
man/man5/afp_voluuid.conf.5.tmpl [new file with mode: 0644]
man/man5/afpd.conf.5.tmpl
man/man5/netatalk.conf.5.tmpl
man/man8/afpd.8.tmpl
man/man8/cnid_metad.8.tmpl
test/afpd/subtests.c

diff --git a/NEWS b/NEWS
index f40686f5fdb3814126437f72b66fb6e4eab2818b..757b22a7d716020af4fa142e7d07d8bfe3c17317 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,28 @@
+Changes in 2.2beta4
+===================
+
+* NEW: afpd: new afpd.conf options "tcprcvbuf" and "tcpsndbuf" to customize
+       the corresponding TCP socket options.
+* NEW: afpd: new afpd.conf option "nozeroconf" which disabled automatic
+       Zeroconf service registration.
+* FIX: afpd: generate mersenne primes for DHX2 UAM once at startup,
+       not for every login
+* FIX: afpd: DSI streaming deadlock
+* FIX: afpd: extended sleep
+* FIX: afpd: directory cache
+* FIX: Support for platforms that do not have the *at functions
+* UPD: afpd: put POSIX write lock on volume files while reading them
+
+Changes in 2.2beta3
+===================
+
+* FIX: afpd: fix option volsizelimit to return a usefull value for the
+       volume free space using `du -sh` with popen
+* FIX: afpd: fix idle connection disconnects
+* FIX: afpd: don't disconnect sessions for clients if boottimes don't match
+* FIX: afpd: better handling of very long filenames that contain many
+       multibyte UTF-8 glyphs
+
 Changes in 2.2beta2
 ====================
 
@@ -77,6 +102,7 @@ Changes in 2.1.6
 * FIX: Solaris: configure script failed to enable DDP module
 * FIX: AppleDouble buffer overrun by extremely long filename
 * UPD: afpd: return version info with machine type in DSIGetStatus
+* UPD: dbd: use on-disk temporary rebuild db instead of in-memory db
 
 Changes in 2.1.5
 ================
index 1742ea6b54ead1da999d177b86cc338da4e5274e..f5d1448ae3621d70a8241af4864a925335693e68 100644 (file)
@@ -1,3 +1,7 @@
 # Makefile.am for bin/
 
-SUBDIRS = ad afppasswd cnid megatron uniconv misc
+SUBDIRS = afppasswd cnid megatron uniconv misc
+
+if HAVE_ATFUNCS
+SUBDIRS += ad
+endif
index 0ee0f405947717ff9e801c53d02310d5e72746d7..b0723b021976d69f4a778fdbeef3006d4c3489ea 100644 (file)
@@ -387,6 +387,10 @@ static int copy(const char *path,
     if (alarmed)
         return -1;
 
+    /* This currently doesn't work with "." */
+    if (strcmp(path, ".") == 0) {
+        ERROR("\".\" not supported");
+    }
     const char *dir = strrchr(path, '/');
     if (dir == NULL)
         dir = path;
index 0355364398e81183e566f040ee1a53e0d16d7265..156d648b004a5d2fe0f26a6a30ef1b95b4378651 100644 (file)
@@ -186,7 +186,7 @@ int ad_mv(int argc, char *argv[])
     set_signal();
     cnid_init();
     if (openvol(argv[argc - 1], &dvolume) != 0) {
-        SLOG("Error opening CNID database for %s: ", argv[argc - 1]);
+        SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]);
         return 1;
     }
 
@@ -198,7 +198,7 @@ int ad_mv(int argc, char *argv[])
         if (argc > 2)
             usage_mv();
         if (openvol(argv[0], &svolume) != 0) {
-            SLOG("Error opening CNID database for %s: ", argv[0]);
+            SLOG("Error opening CNID database for destination \"%s\": ", argv[0]);
             return 1;
         }
         rval = do_move(argv[0], argv[1]);
@@ -235,11 +235,8 @@ int ad_mv(int argc, char *argv[])
             rval = 1;
         } else {
             memmove(endp, p, (size_t)len + 1);
-            if (openvol(*argv, &svolume) != 0) {
-                SLOG("Error opening CNID database for %s: ", argv[0]);
-                rval = 1;
-                goto exit;
-            }
+            openvol(*argv, &svolume);
+
             if (do_move(*argv, path))
                 rval = 1;
             closevol(&svolume);
index 5a9b0973c7a2173f81a74850a594a07f7facb085..4a8ff11b62ecee83730290246975aa2ee597fa8c 100644 (file)
@@ -190,79 +190,6 @@ char *utompath(const struct volinfo *volinfo, const char *upath)
     return(m);
 }
 
-/*!
- * Build path relativ to volume root
- *
- * path might be:
- * (a) relative:
- *     "dir/subdir" with cwd: "/afp_volume/topdir"
- * (b) absolute:
- *     "/afp_volume/dir/subdir"
- *
- * @param path     (r) path relative to cwd() or absolute
- * @param volpath  (r) volume path that path is a subdir of (has been computed in volinfo funcs)
- *
- * @returns relative path in new bstring, caller must bdestroy it
- */
-static bstring rel_path_in_vol(const char *path, const char *volpath)
-{
-    EC_INIT;
-    int cwd = -1;
-    bstring fpath = NULL;
-    char *dname = NULL;
-    struct stat st;
-
-    if (path == NULL || volpath == NULL)
-        return NULL;
-
-    EC_NEG1_LOG(cwd = open(".", O_RDONLY));
-
-    EC_ZERO_LOGSTR(lstat(path, &st), "lstat(%s): %s", path, strerror(errno));
-    switch (S_IFMT & st.st_mode) {
-
-    case S_IFREG:
-    case S_IFLNK:
-        EC_NULL_LOG(dname = strdup(path));
-        EC_ZERO_LOGSTR(chdir(dirname(dname)), "chdir(%s): %s", dirname, strerror(errno));
-        free(dname);
-        dname = NULL;
-        EC_NULL(fpath = bfromcstr(getcwdpath()));
-        BSTRING_STRIP_SLASH(fpath);
-        EC_ZERO(bcatcstr(fpath, "/"));
-        EC_NULL_LOG(dname = strdup(path));
-        EC_ZERO(bcatcstr(fpath, basename(dname)));
-        break;
-
-    case S_IFDIR:
-        EC_ZERO_LOGSTR(chdir(path), "chdir(%s): %s", path, strerror(errno));
-        EC_NULL(fpath = bfromcstr(getcwdpath()));
-        break;
-
-    default:
-        SLOG("special: %s", path);
-        EC_FAIL;
-    }
-
-    BSTRING_STRIP_SLASH(fpath);
-
-    /*
-     * Now we have eg:
-     *   fpath:   /Volume/netatalk/dir/bla
-     *   volpath: /Volume/netatalk/
-     * we want: "dir/bla"
-     */
-    EC_ZERO(bdelete(fpath, 0, strlen(volpath)));
-
-EC_CLEANUP:
-    if (dname) free(dname);
-    if (cwd != -1) {
-        fchdir(cwd);
-        close(cwd);
-    }
-    if (ret != 0)
-        return NULL;
-    return fpath;
-}
 
 /*!
  * Convert dot encoding of basename _in place_
@@ -347,15 +274,16 @@ cnid_t cnid_for_path(const afpvol_t *vol,
     struct bstrList *l = NULL;
     struct stat st;
 
-    *did = htonl(1);
     cnid = htonl(2);
 
     EC_NULL(rpath = rel_path_in_vol(path, vol->volinfo.v_path));
     EC_NULL(statpath = bfromcstr(vol->volinfo.v_path));
+    EC_ZERO(bcatcstr(statpath, "/"));
 
     l = bsplit(rpath, '/');
     for (int i = 0; i < l->qty ; i++) {
         *did = cnid;
+
         EC_ZERO(bconcat(statpath, l->entry[i]));
         EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
                        "lstat(rpath: %s, elem: %s): %s: %s",
index 850c45d79747d13b77a15ed1bc3ca0d488efa3bf..5dfc823115bef5ea6f960d7429ce81012d0e559a 100644 (file)
@@ -389,7 +389,7 @@ static int init(char* path)
 {
        DIR* startdir;
 
-    if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, NULL, NULL)) ) {
+    if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, "localhost", "4700")) ) {
                 fprintf (stderr, "ERROR: cannot open CNID database in '%s'\n", path);
                 fprintf (stderr, "ERROR: check the logs for reasons, aborting\n");
                return -1;
index 377592120173b11d26a6d580bf016042fa5f9c19..0994a116d4821f1f2475fac5ccd889e1451e20db 100644 (file)
@@ -1,7 +1,8 @@
 #
 # CONFIGURATION FOR AFPD
 #
-# Each line defines a virtual server that should be available.
+# Each single line defines a virtual server that should be available.
+# Though, using "\" character, newline escaping is supported.
 # Empty lines and lines beginning with `#' are ignored.
 # Options in this file will override both compiled-in defaults
 # and command line options.
@@ -10,7 +11,7 @@
 
 #
 # Format:
-#  - [options]               to specify options for the default server
+#  - [options]               to specify options for the default server
 #  "Server name" [options]   to specify an additional server
 #
 
 #       4 servers w/ names server1-3 and one w/ the hostname. servers
 #       1-3 get routed to different ports with server 3 being bound 
 #       specifically to address 192.168.1.3
+#
 #           -
 #           server1 -port 12000
 #           server2 -port 12001
 #           server3 -port 12002 -ipaddr 192.168.1.3
 #
 #       a dedicated guest server, a user server, and a special
-#       ddp-only server:
-#           "Guest Volume" -uamlist uams_guest.so -loginmesg "Welcome guest!"
-#           "User Volume" -uamlist uams_clrtxt.so -port 12000
-#           "special" -notcp -defaultvol <path> -systemvol <path>
+#       AppleTalk-only server:
+#
+#           "Guest Server" -uamlist uams_guest.so \
+#                   -loginmesg "Welcome guest! I'm a public server."
+#           "User Server" -uamlist uams_dhx2.so -port 12000
+#           "special" -ddp -notcp -defaultvol <path> -systemvol <path>
 #
 
 
index 9da854d290693bfc352305a3574a5827a04f1951..ea334e47e72210699089039979e18396ca1bb73b 100644 (file)
@@ -70,10 +70,15 @@ if test x"$libltdl_cv_need_uscore" = xyes; then
 fi
 
 dnl Special hecks
+ac_neta_haveatfuncs=yes
+AC_CHECK_FUNCS(openat renameat fstatat unlinkat, , ac_neta_haveatfuncs=no)
+if test x"$ac_neta_haveatfuncs" = x"yes" ; then
+   AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)
+   AC_DEFINE([HAVE_ATFUNCS], 1, whether at funcs are available)
+fi
 AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include <time.h>])
 
 dnl these tests have been comfirmed to be needed in 2011
-AC_CHECK_FUNC(renameat, AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)) 
 AC_CHECK_FUNC(epoll_create, AC_DEFINE([HAVE_EPOLL], 1, Whether Linux epoll is available)) 
 AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect)
 AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen)
@@ -326,6 +331,7 @@ AM_CONDITIONAL(USE_GENTOO, test x$sysv_style = xgentoo)
 AM_CONDITIONAL(USE_DEBIAN, test x$sysv_style = xdebian)
 AM_CONDITIONAL(USE_UNDEF, test x$sysv_style = x)
 AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes)
+AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
 
 dnl --------------------- generate files
 
index cc0757637941870254d5a2dba46efd7b2ff10a1a..75ddb5c4366e41eb78b2e0d432a9209ae5a06470 100644 (file)
@@ -88,7 +88,7 @@ while (<PS>) {
                                 next if ($_ !~ /port: $ASIP_PORT_NO/);
                                 while (<PFILES>) {
                                         next if ($_ !~ /peername/);
-                                        if ($_ =~ /AF_INET. (.*) port/) {
+                                        if ($_ =~ /AF_INET (.*) port/) {
                                             $ip = $1;
                                             if ($ip =~ /::ffff:(.*)/ ) {
                                                 $ip = $1;
diff --git a/contrib/misc/make-casetable.pl b/contrib/misc/make-casetable.pl
new file mode 100755 (executable)
index 0000000..68bcfc9
--- /dev/null
@@ -0,0 +1,324 @@
+#!/usr/bin/perl
+#
+# usage: make-casetable.pl <infile> <outfile1> <outfile2>
+#        make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
+#
+# (c) 2011 by HAT <hat@fa2.so-net.ne.jp>
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+
+# See
+# http://www.unicode.org/reports/tr44/
+# http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
+
+# One block has 64 chars.
+#
+# BMP
+# block    0 = dummy
+# block    1 = U+0000 - U+003F
+# block    2 = U+0040 - U+007F
+# .....
+# block 1024 = U+FFC0 - U+FFFF
+# block 1025 = dummy
+#
+# Surrogate Pair
+# block  1024 = dummy
+# block  1025 = U+010000 - U+01003F
+# block  1026 = U+010040 - U+01007F
+# .....
+# block 17408 = U+10FFC0 - U+10FFFF
+# block 17409 = dummy
+#
+# Dummy block is for edge detection.
+# If block include upper/lower chars, block_enable[]=1.
+
+use strict;
+use warnings;
+
+our $code0;
+our $Name1;
+our $General_Category2;
+our $Canonical_Combining_Class3;
+our $Bidi_Class4;
+our $Decomposition_Mapping5;
+our $Numeric_Value6;
+our $Numeric_Value7;
+our $Numeric_Value8;
+our $Bidi_Mirrored9;
+our $Unicode_1_Name10;
+our $ISO_Comment11;
+our $Simple_Uppercase_Mapping12;
+our $Simple_Lowercase_Mapping13;
+our $Simple_Titlecase_Mapping14;
+
+our $hex_code0;
+our $Mapping;
+our $hex_Mapping;
+
+our $char;
+our $sp;
+our $block;
+
+our @table;
+our @table_sp;
+
+our @block_enable;
+our @block_enable_sp;
+
+our $table_no;
+our $block_start;
+our $block_end;
+our $char_start;
+our $char_end;
+
+open(CHEADER, ">$ARGV[1]");
+open(CSOURCE, ">$ARGV[2]");
+
+printf (CHEADER "\/\*\n");
+printf (CHEADER "DO NOT EDIT BY HAND\!\!\!\n");
+printf (CHEADER "\n");
+printf (CHEADER "This file is generated by\n");
+printf (CHEADER " contrib/misc/make-casetable.pl %s %s %s\n", $ARGV[0], $ARGV[1], $ARGV[2]);
+printf (CHEADER "\n");
+printf (CHEADER "%s is got from\n", $ARGV[0]);
+printf (CHEADER "http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt\n");
+printf (CHEADER "\*\/\n");
+printf (CHEADER "\n");
+
+printf (CSOURCE "\/\*\n");
+printf (CSOURCE "DO NOT EDIT BY HAND\!\!\!\n");
+printf (CSOURCE "\n");
+printf (CSOURCE "This file is generated by\n");
+printf (CSOURCE " contrib/misc/make-casetable.pl %s %s %s\n", $ARGV[0], $ARGV[1], $ARGV[2]);
+printf (CSOURCE "\n");
+printf (CSOURCE "%s is got from\n", $ARGV[0]);
+printf (CSOURCE "http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt\n");
+printf (CSOURCE "\*\/\n");
+printf (CSOURCE "\n");
+printf (CSOURCE "\#include \<netatalk\/endian.h\>\n");
+printf (CSOURCE "\#include \<atalk\/unicode.h\>\n");
+printf (CSOURCE "\#include \"%s\"\n", $ARGV[1]);
+printf (CSOURCE "\n");
+
+&make_array("upper");
+&make_array("lower");
+
+printf (CHEADER "\/\* EOF \*\/\n");
+printf (CSOURCE "\/\* EOF \*\/\n");
+
+close(CHEADER);
+close(CSOURCE);
+
+
+###########################################################################
+sub make_array{
+
+    # init table -----------------------------------------------------
+
+    for ($char = 0 ; $char <= 0xFFFF ; $char++) {
+        $table[$char][0] = $char;       # mapped char
+        $table[$char][1] = $char;       # orig char
+        $table[$char][2] = "";          # char name
+    }
+
+    for ($char = 0x10000 ; $char <= 0x10FFFF ; $char++) {
+        $sp = ((0xD800 - (0x10000 >> 10) + ($char >> 10)) << 16)
+            + (0xDC00 + ($char & 0x3FF));
+        $table_sp[$char][0] = $sp;      # mapped surrogate pair
+        $table_sp[$char][1] = $sp;      # orig surrogate pair
+        $table_sp[$char][2] = $char;    # mapped char
+        $table_sp[$char][3] = $char;    # orig char
+        $table_sp[$char][4] = "";       # char name
+    }
+
+    for ($block = 0 ; $block <= 1025 ; $block++) {
+        $block_enable[$block] = 0;
+    }
+
+    $block_enable[1] = 1;           # ASCII block is forcibly included
+    $block_enable[2] = 1;           # in the array for Speed-Up.
+
+    for ($block = 1024 ; $block <= 17409 ; $block++) {
+        $block_enable_sp[$block] = 0;
+    }
+
+    # write data to table --------------------------------------------
+
+    open(UNICODEDATA, "<$ARGV[0]");
+
+    while (<UNICODEDATA>) {
+        chop;
+        (
+            $code0,
+            $Name1,
+            $General_Category2,
+            $Canonical_Combining_Class3,
+            $Bidi_Class4,
+            $Decomposition_Mapping5,
+            $Numeric_Value6,
+            $Numeric_Value7,
+            $Numeric_Value8,
+            $Bidi_Mirrored9,
+            $Unicode_1_Name10,
+            $ISO_Comment11,
+            $Simple_Uppercase_Mapping12,
+            $Simple_Lowercase_Mapping13,
+            $Simple_Titlecase_Mapping14
+        ) = split(/\;/);
+
+        if ($_[0] eq "upper") {
+            $Mapping = $Simple_Uppercase_Mapping12;
+        } elsif ($_[0] eq "lower") {
+            $Mapping = $Simple_Lowercase_Mapping13;
+        } else {
+            exit(1);
+        }
+
+        next if ($Mapping eq "");
+
+        $hex_code0 = hex($code0);
+        $hex_Mapping = hex($Mapping);
+
+        if ($hex_code0 <= 0xFFFF) {
+            $table[$hex_code0][0] = $hex_Mapping;
+            #table[$hex_code0][1]   already set
+            $table[$hex_code0][2] = $Name1;
+            $block_enable[($hex_code0 / 64) +1] = 1;
+        } else {
+            $sp = ((0xD800 - (0x10000 >> 10) + ($hex_Mapping >> 10)) << 16)
+                + (0xDC00 + ($hex_Mapping & 0x3FF));
+            $table_sp[$hex_code0][0] = $sp;
+            #table_sp[$hex_code0][1]   already set
+            $table_sp[$hex_code0][2] = $hex_Mapping;
+            #table_sp[$hex_code0][3]   already set
+            $table_sp[$hex_code0][4] = $Name1;
+            $block_enable_sp[($hex_code0 / 64) +1] = 1;
+        }
+    }
+
+    close(UNICODEDATA);
+
+    # array for BMP --------------------------------------------------
+
+    printf(CSOURCE "\/*******************************************************************\n");
+    printf(CSOURCE " Convert a wide character to %s case.\n", $_[0]);
+    printf(CSOURCE "*******************************************************************\/\n");
+    printf(CSOURCE "ucs2\_t to%s\_w\(ucs2\_t val\)\n", $_[0]);
+    printf(CSOURCE "{\n");
+
+    $table_no = 1;
+
+    for ($block = 1 ; $block <= 1024 ; $block++) {
+
+        # rising edge detection
+        if ($block_enable[$block - 1] == 0 && $block_enable[$block] == 1) {
+            $block_start = $block;
+        }
+
+        # falling edge detection
+        if ($block_enable[$block] == 1 && $block_enable[$block + 1] == 0) {
+            $block_end = $block;
+
+            $char_start = ($block_start -1)* 64;
+            $char_end = ($block_end * 64) -1;
+
+            printf(CHEADER "static const u\_int16\_t %s\_table\_%d\[%d\] \= \{\n",
+                   $_[0], $table_no, $char_end - $char_start +1);
+
+            for ($char = $char_start ; $char <= $char_end ; $char++) {
+                printf(CHEADER "  0x%04X, /*U\+%04X*/ /*%s*/\n",
+                       $table[$char][0],
+                       $table[$char][1],
+                       $table[$char][2]
+                   );
+            }
+            printf(CHEADER "\}\;\n");
+            printf(CHEADER "\n");
+
+            if ($char_start == 0x0000) {
+                printf(CSOURCE "    if \( val \<\= 0x%04X)\n",
+                       $char_end);
+                printf(CSOURCE "        return %s\_table\_%d\[val]\;\n",
+                       $_[0], $table_no);
+            } else {
+                printf(CSOURCE "    if \( val \>\= 0x%04X \&\& val \<\= 0x%04X)\n",
+                       $char_start, $char_end);
+                printf(CSOURCE "        return %s\_table\_%d\[val-0x%04X\]\;\n",
+                       $_[0], $table_no, $char_start);
+            }
+            printf(CSOURCE "\n");
+
+            $table_no++;
+        }
+    }
+
+    printf(CSOURCE "\treturn \(val\)\;\n");
+    printf(CSOURCE "\}\n");
+    printf(CSOURCE "\n");
+
+    # array for Surrogate Pair ---------------------------------------
+
+    printf(CSOURCE "\/*******************************************************************\n");
+    printf(CSOURCE " Convert a surrogate pair to %s case.\n", $_[0]);
+    printf(CSOURCE "*******************************************************************\/\n");
+    printf(CSOURCE "u\_int32\_t to%s\_sp\(u\_int32\_t val\)\n", $_[0]);
+    printf(CSOURCE "{\n");
+
+    $table_no = 1;
+
+    for ($block = 1025 ; $block <= 17408 ; $block++) {
+
+        # rising edge detection
+        if ((($block_enable_sp[$block - 1] == 0) || ((($block - 1) & 0xF) == 0))
+                && ($block_enable_sp[$block] == 1)) {
+            $block_start = $block;
+        }
+
+        # falling edge detection
+        if (($block_enable_sp[$block] == 1) &&
+                ((($block - 1) & 0xF == 0xF) || ($block_enable_sp[$block + 1] == 0))) {
+            $block_end = $block;
+
+            $char_start = ($block_start -1)* 64;
+            $char_end = ($block_end * 64) -1;
+
+            printf(CHEADER "static const u\_int32\_t %s\_table\_sp\_%d\[%d\] \= \{\n",
+                   $_[0], $table_no, $char_end - $char_start +1);
+
+            for ($char = $char_start ; $char <= $char_end ; $char++) {
+                printf(CHEADER "  0x%08X, /*0x%08X*/ /*U\+%06X*/ /*U\+%06X*/ /*%s*/\n",
+                       $table_sp[$char][0],
+                       $table_sp[$char][1],
+                       $table_sp[$char][2],
+                       $table_sp[$char][3],
+                       $table_sp[$char][4]
+                   );
+            }
+            printf(CHEADER "\}\;\n");
+            printf(CHEADER "\n");
+
+            printf(CSOURCE "    if \( val \>\= 0x%08X \&\& val \<\= 0x%08X)\n",
+                   $table_sp[$char_start][1], $table_sp[$char_end][1]);
+            printf(CSOURCE "        return %s\_table\_sp\_%d\[val-0x%08X\]\;\n",
+                   $_[0], $table_no, $table_sp[$char_start][1]);
+            printf(CSOURCE "\n");
+
+            $table_no++;
+        }
+    }
+
+    printf(CSOURCE "\treturn \(val\)\;\n");
+    printf(CSOURCE "\}\n");
+    printf(CSOURCE "\n");
+}
+
+# EOF
index 4fc195df3ffcf94c0121a51c61b08f803944ed5c..ccd0332edd6c4ccf7094a71d2a1e08f8f743a9e4 100755 (executable)
@@ -7,38 +7,45 @@
 # author: James W. Abendschan  <jwa@jammed.com>
 # license: GPL - http://www.gnu.org/copyleft/gpl.html
 # url: http://www.jammed.com/~jwa/hacks/security/asip/
-# date: 7 May 1997 (v1.0)
+# Date: 7 May 1997 (v1.0) - original version
 # see also: 
 #   - http://developer.apple.com/techpubs/macos8/NetworkCommSvcs/AppleShare/
 #   - http://www2.opendoor.com/asip/   (excellent Mac sharing / security site)
 #
 # todo: log in as guest & get a list of shares
 #
-# $Id: asip-status.pl.in,v 1.2 2005-04-28 20:49:36 bfernhomberg Exp $
+
+#
+# This edition is a part of netatalk.
 #
 
 use strict;
 use IO::Socket;                        # sucks because Timeout doesn't
 
 my ($arg);
+my ($hostport);
 my ($host);
+my ($port);
 
 while ($arg = shift @ARGV)
 {
        $main::show_icon = 1 if ($arg eq "-i");
        $main::debug = 1 if ($arg eq "-d");
        $main::hexdump = 1 if ($arg eq "-x");
-       $host = $arg if ($arg !~ /^-/);
+       $hostport = $arg if ($arg !~ /^-/);
 }
 
-if ($host eq "")
+if ($hostport eq "")
 {
-       print "usage: $0 hostname [-i show icon] [-d debug] [-x hex dump]\n";
+       print "usage: $0 hostname[:port] [-i show icon] [-d debug] [-x hex dump]\n";
        exit(-1);
 }
 
+($host, $port) = split(/\:/, $hostport);
+$port = "548" if ($port eq "");
+
 my ($packet) = build_packet();
-my ($code) = sendpacket($host, 548, $packet);
+my ($code) = sendpacket($host, $port, $packet);
 exit $code;
 
 
@@ -205,6 +212,7 @@ sub parse_FPGetSrvrInfo()
 
        my ($icon_offset) = unpack("n", @packet[6] . @packet[7]);
        print "Volume Icon & Mask offset: $icon_offset\n" if ($main::debug);
+       print "Volume Icon & Mask: exist\n" if ($icon_offset);
 
        my ($flags) = unpack("n", @packet[8] . @packet[9]);
        my (@flags) = parse_afp_flags($flags);
@@ -269,7 +277,7 @@ sub parse_FPGetSrvrInfo()
                }
        }
 
-       draw_icon($icon_offset, @packet) if ($main::show_icon);
+       draw_icon($icon_offset, @packet) if ($main::show_icon && $icon_offset);
 
        return $allow_guest;
 }
index a661a5e4c7b8facc7e8ba3f85c051c8db53d179c..9b3fcae6063c5ecd7379a5e90642d841dc860a21 100644 (file)
@@ -44,7 +44,7 @@ afpd_LDADD =  \
        $(top_builddir)/libatalk/cnid/libcnid.la \
        $(top_builddir)/libatalk/libatalk.la \
        $(top_builddir)/libevent/libevent.la \
-       @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@
+       @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@
 
 afpd_LDFLAGS = -export-dynamic -static
 
index 206f2d9f2f774f58c46b4c90e5067ebfd3da7abb..43e91042f10e0ee3850a2d3cc312b7b51ee7a038 100644 (file)
@@ -128,9 +128,9 @@ static int solaris_acl_rights(const char *path,
             ||
             ((flags & ACE_OWNER) && (uuid == sb->st_uid))
             ||
-            ((flags & ACE_GROUP) && gmem(sb->st_gid))
+            ((flags & ACE_GROUP) && !(uuid == sb->st_uid) && gmem(sb->st_gid))
             ||
-            (flags & ACE_EVERYONE)
+            (flags & ACE_EVERYONE && !(uuid == sb->st_uid) && !gmem(sb->st_gid))
             ) {
             /* Found an applicable ACE */
             if (type == ACE_ACCESS_ALLOWED_ACE_TYPE)
@@ -438,14 +438,16 @@ static int posix_acl_rights(const char *path,
             gid = NULL;
             break;
         case ACL_GROUP_OBJ:
-            if (gmem(sb->st_gid)) {
+            if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
                 LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
                 rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));            
             }
             break;
         case ACL_OTHER:
-            LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
-            rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+            if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
+                LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
+                rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+            }
             break;
         default:
             continue;
index 28c72e22424ae96b3bef20dd9f9759951eec9d94..a06c7be4237209e35faa9a4bee6f16da6ff01d00 100644 (file)
@@ -94,19 +94,31 @@ static void register_stuff(void) {
 
             dsi = (DSI *)config->obj.handle;
             port = getip_port((struct sockaddr *)&dsi->server);
-            
-            if (convert_string(config->obj.options.unixcharset, CH_UTF8,
-                               config->obj.options.server ? config->obj.options.server : config->obj.options.hostname, -1,
-                               name, MAXINSTANCENAMELEN) <= 0) {
-                LOG ( log_error, logtype_afpd, "Could not set Zeroconf instance name");
+
+            if (convert_string(config->obj.options.unixcharset,
+                               CH_UTF8,
+                               config->obj.options.server ?
+                               config->obj.options.server :
+                               config->obj.options.hostname,
+                               -1,
+                               name,
+                               MAXINSTANCENAMELEN) <= 0) {
+                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
+                goto fail;
+            }
+            if ((dsi->bonjourname = strdup(name)) == NULL) {
+                LOG(log_error, logtype_afpd, "Could not set Zeroconf instance name");
                 goto fail;
+
             }
+            LOG(log_info, logtype_afpd, "Registering server '%s' with with Bonjour",
+                dsi->bonjourname);
 
             if (avahi_entry_group_add_service(ctx->group,
                                               AVAHI_IF_UNSPEC,
                                               AVAHI_PROTO_UNSPEC,
                                               0,
-                                              name,
+                                              dsi->bonjourname,
                                               AFP_DNS_SERVICE_TYPE,
                                               NULL,
                                               NULL,
@@ -121,7 +133,7 @@ static void register_stuff(void) {
                                                           AVAHI_IF_UNSPEC,
                                                           AVAHI_PROTO_UNSPEC,
                                                           0,
-                                                          name,
+                                                          dsi->bonjourname,
                                                           ADISK_SERVICE_TYPE,
                                                           NULL,
                                                           NULL,
index f3adf7bf05406687fc7dcf5ede83e8cc2bdee394..8c997ebe94f7999e0e51b248a304e95fd38997da 100644 (file)
@@ -210,6 +210,7 @@ static AFPConfig *DSIConfigInit(const struct afp_options *options,
         free(config);
         return NULL;
     }
+    dsi->dsireadbuf = options->dsireadbuf;
 
     if (options->flags & OPTION_PROXY) {
         LOG(log_note, logtype_afpd, "AFP/TCP proxy initialized for %s:%d (%s)",
@@ -425,8 +426,10 @@ AFPConfig *configinit(struct afp_options *cmdline)
         first = AFPConfigInit(cmdline, cmdline);
 
     /* Now register with zeroconf, we also need the volumes for that */
-    load_volumes(&first->obj);
-    zeroconf_register(first);
+    if (! (first->obj.options.flags & OPTION_NOZEROCONF)) {
+        load_volumes(&first->obj);
+        zeroconf_register(first);
+    }
 
     return first;
 }
index 11af0d101e78866df00091d89444d7b3b36612e9..96188688d88e899eb2adfd4bc774e1fb6772f4a7 100644 (file)
@@ -114,7 +114,7 @@ static void afp_dsi_die(int sig)
 
     dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN);
     afp_dsi_close(AFPobj);
-    if (sig) /* if no signal, assume dieing because logins are disabled &
+   if (sig) /* if no signal, assume dieing because logins are disabled &
                 don't log it (maintenance mode)*/
         LOG(log_info, logtype_afpd, "Connection terminated");
     if (sig == SIGTERM || sig == SIGALRM) {
@@ -280,7 +280,7 @@ static void alarm_handler(int sig _U_)
 
     if (dsi->flags & DSI_SLEEPING) {
         if (dsi->tickle > AFPobj->options.sleep) {
-            LOG(log_error, logtype_afpd, "afp_alarm: sleep time ended");
+            LOG(log_note, logtype_afpd, "afp_alarm: sleep time ended");
             afp_dsi_die(EXITERR_CLNT);
         }
         return;
@@ -288,7 +288,7 @@ static void alarm_handler(int sig _U_)
 
     if (dsi->flags & DSI_DISCONNECTED) {
         if (dsi->tickle > AFPobj->options.disconnected) {
-             LOG(log_error, logtype_afpd, "afp_alarm: no reconnect within 10 minutes, goodbye");
+            LOG(log_error, logtype_afpd, "afp_alarm: reconnect timer expired, goodbye");
             afp_dsi_die(EXITERR_CLNT);
         }
         return;
@@ -303,9 +303,11 @@ static void alarm_handler(int sig _U_)
     }
 
     if ((err = pollvoltime(AFPobj)) == 0)
+        LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle");
         err = dsi_tickle(AFPobj->handle);
     if (err <= 0) {
         LOG(log_error, logtype_afpd, "afp_alarm: connection problem, entering disconnected state");
+        dsi->proto_close(dsi);
         dsi->flags |= DSI_DISCONNECTED;
     }
 }
@@ -451,6 +453,26 @@ void afp_over_dsi(AFPObj *obj)
     if (dircache_init(obj->options.dircachesize) != 0)
         afp_dsi_die(EXITERR_SYS);
 
+    /* set TCP snd/rcv buf */
+    if (obj->options.tcp_rcvbuf) {
+        if (setsockopt(dsi->socket,
+                       SOL_SOCKET,
+                       SO_RCVBUF,
+                       &obj->options.tcp_rcvbuf,
+                       sizeof(obj->options.tcp_rcvbuf)) != 0) {
+            LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_RCVBUF): %s", strerror(errno));
+        }
+    }
+    if (obj->options.tcp_sndbuf) {
+        if (setsockopt(dsi->socket,
+                       SOL_SOCKET,
+                       SO_SNDBUF,
+                       &obj->options.tcp_sndbuf,
+                       sizeof(obj->options.tcp_sndbuf)) != 0) {
+            LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_SNDBUF): %s", strerror(errno));
+        }
+    }
+
     /* get stuck here until the end */
     while (1) {
         if (sigsetjmp(recon_jmp, 1) != 0)
@@ -469,6 +491,13 @@ void afp_over_dsi(AFPObj *obj)
             }
             /* Some error on the client connection, enter disconnected state */
             dsi->flags |= DSI_DISCONNECTED;
+
+            /* the client sometimes logs out (afp_logout) but doesn't close the DSI session */
+            if (dsi->flags & DSI_AFP_LOGGED_OUT) {
+                afp_dsi_close(obj);
+                exit(0);
+            }
+
             pause(); /* gets interrupted by SIGALARM or SIGURG tickle */
             continue; /* continue receiving until disconnect timer expires
                        * or a primary reconnect succeeds  */
@@ -506,20 +535,24 @@ void afp_over_dsi(AFPObj *obj)
             }
         }
 
-        if (cmd == DSIFUNC_TICKLE) {
-            /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */
-            if ((dsi->flags & DSI_DIE))
-                dsi_tickle(dsi);
-            pending_request(dsi);
-            continue;
-        } 
 
         dsi->flags |= DSI_DATA;
+        dsi->tickle = 0;
+
         switch(cmd) {
+
         case DSIFUNC_CLOSE:
+            LOG(log_debug, logtype_afpd, "DSI: close session request");
             afp_dsi_close(obj);
             LOG(log_note, logtype_afpd, "done");
-            return;
+            exit(0);
+
+        case DSIFUNC_TICKLE:
+            dsi->flags &= ~DSI_DATA; /* thats no data in the sense we use it in alarm_handler */
+            LOG(log_debug, logtype_afpd, "DSI: client tickle");
+            /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */
+            if ((dsi->flags & DSI_DIE))
+                dsi_tickle(dsi);
             break;
 
         case DSIFUNC_CMD:
@@ -535,12 +568,12 @@ void afp_over_dsi(AFPObj *obj)
             function = (u_char) dsi->commands[0];
 
             /* AFP replay cache */
-            rc_idx = REPLAYCACHE_SIZE % dsi->clientID;
+            rc_idx = dsi->clientID % REPLAYCACHE_SIZE;
             LOG(log_debug, logtype_afpd, "DSI request ID: %u", dsi->clientID);
 
             if (replaycache[rc_idx].DSIreqID == dsi->clientID
                 && replaycache[rc_idx].AFPcommand == function) {
-                LOG(log_debug, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s",
+                LOG(log_note, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s",
                     dsi->clientID, AfpNum2name(function));
                 err = replaycache[rc_idx].result;
             /* AFP replay cache end */
index fac01fdef357c906408c1858012c0e7905a903f9..ec4b762dfb1a7b84a9da7e98ad21518a63e9f208 100644 (file)
@@ -186,6 +186,9 @@ void afp_options_init(struct afp_options *options)
     options->dircachesize = DEFAULT_MAX_DIRCACHE_SIZE;
     options->flags |= OPTION_ACL2MACCESS;
     options->flags |= OPTION_UUID;
+    options->tcp_sndbuf = 0;    /* 0 means don't change OS default */
+    options->tcp_rcvbuf = 0;    /* 0 means don't change OS default */
+    options->dsireadbuf = 12;
 }
 
 /* parse an afpd.conf line. i'm doing it this way because it's
@@ -321,6 +324,12 @@ int afp_options_parseline(char *buf, struct afp_options *options)
         }
     }
 
+    if ((c = getoption(buf, "-dsireadbuf"))) {
+        options->dsireadbuf = atoi(c);
+        if (options->dsireadbuf < 6)
+            options->dsireadbuf = 6;
+    }
+
     if ((c = getoption(buf, "-server_quantum")))
         options->server_quantum = strtoul(c, NULL, 0);
 
@@ -461,6 +470,12 @@ int afp_options_parseline(char *buf, struct afp_options *options)
     if ((c = getoption(buf, "-dircachesize")))
         options->dircachesize = atoi(c);
      
+    if ((c = getoption(buf, "-tcpsndbuf")))
+        options->tcp_sndbuf = atoi(c);
+
+    if ((c = getoption(buf, "-tcprcvbuf")))
+        options->tcp_rcvbuf = atoi(c);
+
     return 1;
 }
 
index 9245293c80af9a1841a7556cb0026143d341dafb..0768d22d1d6cacc122b8293798dabe5e79a48ebf 100644 (file)
@@ -380,12 +380,14 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi
 }
 
 /* ---------------------- */
-int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
+int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     uint32_t data;
     DSI *dsi = (DSI *)AFPobj->handle;
 
     *rbuflen = 0;
+    ibuf += 2;
+    ibuflen -= 2;
 
     if (ibuflen < 4)
         return AFPERR_MISC;
@@ -401,19 +403,20 @@ int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbu
     if (data & AFPZZZ_EXT_WAKEUP) {
         /* wakeup request from exetended sleep */
         if (dsi->flags & DSI_EXTSLEEP) {
-            LOG(log_debug, logtype_afpd, "afp_zzz: waking up from extended sleep");
+            LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep");
             dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP);
         }
     } else {
         /* sleep request */
         dsi->flags |= DSI_SLEEPING;
         if (data & AFPZZZ_EXT_SLEEP) {
-            LOG(log_debug, logtype_afpd, "afp_zzz: entering extended sleep");
+            LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep");
             dsi->flags |= DSI_EXTSLEEP;
         } else {
-            LOG(log_debug, logtype_afpd, "afp_zzz: entering normal sleep");
+            LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep");
         }
     }
+
     /*
      * According to AFP 3.3 spec we should not return anything,
      * but eg 10.5.8 server still returns the numbers of hours
@@ -876,11 +879,15 @@ int afp_logincont(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *r
 }
 
 
-int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen  _U_)
+int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen)
 {
+    DSI *dsi = (DSI *)(obj->handle);
+
     LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
+    of_close_all_forks();
     close_all_vol();
-    obj->exit(0);
+    dsi->flags = DSI_AFP_LOGGED_OUT;
+    *rbuflen = 0;
     return AFP_OK;
 }
 
index 0faeef9494b92619dd6cbcf2f905d6ce88a12dd8..6a9161e2e8720743ca3cbbf4100b0980de9d34b0 100644 (file)
@@ -108,7 +108,8 @@ struct scrit {
  *
  */
 struct dsitem {
-       struct dir *dir; /* Structure describing this directory */
+//     struct dir *dir; /* Structure describing this directory */
+//  cnid_t did;      /* CNID of this directory           */
        int pidx;        /* Parent's dsitem structure index. */
        int checked;     /* Have we checked this directory ? */
        int path_len;
@@ -141,8 +142,7 @@ static int addstack(char *uname, struct dir *dir, int pidx)
 
        /* Put new element. Allocate and copy lname and path. */
        ds = dstack + dsidx++;
-       ds->dir = dir;
-    dir->d_flags |= DIRF_CACHELOCK;
+//     ds->did = dir->d_did;
        ds->pidx = pidx;
        ds->checked = 0;
        if (pidx >= 0) {
@@ -175,7 +175,6 @@ static int reducestack(void)
        while (dsidx > 0) {
                if (dstack[dsidx-1].checked) {
                        dsidx--;
-            dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK;
                        free(dstack[dsidx].path);
                } else
                        return dsidx - 1;
@@ -189,7 +188,6 @@ static void clearstack(void)
        save_cidx = -1;
        while (dsidx > 0) {
                dsidx--;
-        dstack[dsidx].dir->d_flags &= ~DIRF_CACHELOCK;
                free(dstack[dsidx].path);
        }
 } 
@@ -506,6 +504,7 @@ static int catsearch(struct vol *vol,
 {
     static u_int32_t cur_pos;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
     static DIR *dirpos;                 /* UNIX structure describing currently opened directory. */
+    struct dir *curdir;          /* struct dir of current directory */
        int cidx, r;
        struct dirent *entry;
        int result = AFP_OK;
@@ -576,8 +575,13 @@ static int catsearch(struct vol *vol,
                        } /* switch (errno) */
                        goto catsearch_end;
                }
+
+        if ((curdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
+            result = AFPERR_MISC;
+            goto catsearch_end;
+        }
                
-               while ((entry=readdir(dirpos)) != NULL) {
+               while ((entry = readdir(dirpos)) != NULL) {
                        (*pos)++;
 
                        if (!check_dirent(vol, entry->d_name))
@@ -606,10 +610,17 @@ static int catsearch(struct vol *vol,
                                   ALL dirsearch_byname will fail.
                                */
                 int unlen = strlen(path.u_name);
-                path.d_dir = dircache_search_by_name(vol, dstack[cidx].dir, path.u_name, unlen, path.st.st_ctime);
+                path.d_dir = dircache_search_by_name(vol,
+                                                     curdir,
+                                                     path.u_name,
+                                                     unlen,
+                                                     path.st.st_ctime);
                if (path.d_dir == NULL) {
                        /* path.m_name is set by adddir */
-                   if (NULL == (path.d_dir = dir_add( vol, dstack[cidx].dir, &path, unlen) ) ) {
+                   if ((path.d_dir = dir_add(vol,
+                                              curdir,
+                                              &path,
+                                              unlen)) == NULL) {
                                                result = AFPERR_MISC;
                                                goto catsearch_end;
                                        }
@@ -620,11 +631,10 @@ static int catsearch(struct vol *vol,
                                        result = AFPERR_MISC;
                                        goto catsearch_end;
                                } 
+            } else {
+               path.d_dir = curdir;
             }
-            else {
-               /* yes it sucks for directory d_dir is the directory, for file it's the parent directory*/
-               path.d_dir = dstack[cidx].dir;
-            }
+
                        ccr = crit_check(vol, &path);
 
                        /* bit 0 means that criteria has been met */
@@ -728,7 +738,7 @@ static int catsearch_db(struct vol *vol,
                             buffer,
                             MAXPATHLEN,
                             &flags) == (size_t)-1) {
-            LOG(log_error, logtype_cnid, "catsearch_db: conversion error");
+            LOG(log_error, logtype_afpd, "catsearch_db: conversion error");
             result = AFPERR_MISC;
             goto catsearch_end;
         }
@@ -1014,8 +1024,8 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
                /* length */
                memcpy(&namelen, spec1, sizeof(namelen));
                namelen = ntohs (namelen);
-               if (namelen > 255)  /* Safeguard */
-                       namelen = 255;
+               if (namelen > UTF8FILELEN_EARLY)  /* Safeguard */
+                       namelen = UTF8FILELEN_EARLY;
 
                memcpy (c1.utf8name, spec1+2, namelen);
                c1.utf8name[namelen] = 0;
index 52ef7478a3c2fc4d9379de3609c4090b90c136d5..9907c5dd35bddabc02bbcef02d94dc07503d2975 100644 (file)
@@ -96,8 +96,6 @@
  * We have/need two indexes:
  * - a DID/name index on the main dircache, another hashtable
  * - a queue index on the dircache, for evicting the oldest entries
- * The cache supports locking of struct dir elements through the DIRF_CACHELOCK flag. A dir
- * locked this way wont ever be removed from the cache, so be careful.
  *
  * Debugging
  * =========
@@ -241,7 +239,7 @@ static unsigned long queue_count;
  * The default is to remove the 256 oldest entries from the cache.
  * 1. Get the oldest entry
  * 2. If it's in use ie open forks reference it or it's curdir requeue it,
- *    or it's locked (from catsearch) dont remove it
+ *    dont remove it
  * 3. Remove the dir from the main cache and the didname index
  * 4. Free the struct dir structure and all its members
  */
@@ -259,8 +257,7 @@ static void dircache_evict(void)
         }
         queue_count--;
 
-        if (curdir == dir
-            || (dir->d_flags & DIRF_CACHELOCK)) {     /* 2 */
+        if (curdir == dir) {                          /* 2 */
             if ((dir->qidx_node = enqueue(index_queue, dir)) == NULL) {
                 dircache_dump();
                 AFP_PANIC("dircache_evict");
@@ -365,7 +362,11 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid)
  *
  * @returns pointer to struct dir if found in cache, else NULL
  */
-struct dir *dircache_search_by_name(const struct vol *vol, const struct dir *dir, char *name, int len, time_t ctime)
+struct dir *dircache_search_by_name(const struct vol *vol,
+                                    const struct dir *dir,
+                                    char *name,
+                                    int len,
+                                    time_t ctime)
 {
     struct dir *cdir = NULL;
     struct dir key;
@@ -421,19 +422,45 @@ struct dir *dircache_search_by_name(const struct vol *vol, const struct dir *dir
  *
  * @returns 0 on success, -1 on error which should result in an abort
  */
-int dircache_add(struct dir *dir)
+int dircache_add(const struct vol *vol,
+                 struct dir *dir)
 {
-   AFP_ASSERT(dir);
-   AFP_ASSERT(ntohl(dir->d_pdid) >= 2);
-   AFP_ASSERT(ntohl(dir->d_did) >= CNID_START);
-   AFP_ASSERT(dir->d_u_name);
-   AFP_ASSERT(dir->d_vid);
-   AFP_ASSERT(dircache->hash_nodecount <= dircache_maxsize);
+    struct dir *cdir = NULL;
+    struct dir key;
+    hnode_t *hn;
+
+    AFP_ASSERT(dir);
+    AFP_ASSERT(ntohl(dir->d_pdid) >= 2);
+    AFP_ASSERT(ntohl(dir->d_did) >= CNID_START);
+    AFP_ASSERT(dir->d_u_name);
+    AFP_ASSERT(dir->d_vid);
+    AFP_ASSERT(dircache->hash_nodecount <= dircache_maxsize);
 
     /* Check if cache is full */
     if (dircache->hash_nodecount == dircache_maxsize)
         dircache_evict();
 
+    /* 
+     * Make sure we don't add duplicates
+     */
+
+    /* Search primary cache by CNID */
+    key.d_vid = dir->d_vid;
+    key.d_did = dir->d_did;
+    if ((hn = hash_lookup(dircache, &key))) {
+        /* Found an entry with the same CNID, delete it */
+        dir_remove(vol, hnode_get(hn));
+        dircache_stat.expunged++;
+    }
+    key.d_vid = vol->v_vid;
+    key.d_pdid = dir->d_did;
+    key.d_u_name = dir->d_u_name;
+    if ((hn = hash_lookup(index_didname, &key))) {
+        /* Found an entry with the same DID/name, delete it */
+        dir_remove(vol, hnode_get(hn));
+        dircache_stat.expunged++;
+    }
+
     /* Add it to the main dircache */
     if (hash_alloc_insert(dircache, dir, dir) == 0) {
         dircache_dump();
@@ -474,11 +501,8 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
 {
     hnode_t *hn;
 
-   AFP_ASSERT(dir);
-   AFP_ASSERT((flags & ~(QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE)) == 0);
-
-    if (dir->d_flags & DIRF_CACHELOCK)
-        return;
+    AFP_ASSERT(dir);
+    AFP_ASSERT((flags & ~(QUEUE_INDEX | DIDNAME_INDEX | DIRCACHE)) == 0);
 
     if (flags & QUEUE_INDEX) {
         /* remove it from the queue index */
@@ -488,7 +512,7 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
 
     if (flags & DIDNAME_INDEX) {
         if ((hn = hash_lookup(index_didname, dir)) == NULL) {
-            LOG(log_error, logtype_default, "dircache_remove(%u,\"%s\"): not in didname index", 
+            LOG(log_error, logtype_afpd, "dircache_remove(%u,\"%s\"): not in didname index", 
                 ntohl(dir->d_did), cfrombstr(dir->d_u_name));
             dircache_dump();
             AFP_PANIC("dircache_remove");
@@ -498,7 +522,7 @@ void dircache_remove(const struct vol *vol _U_, struct dir *dir, int flags)
 
     if (flags & DIRCACHE) {
         if ((hn = hash_lookup(dircache, dir)) == NULL) {
-            LOG(log_error, logtype_default, "dircache_remove(%u,\"%s\"): not in dircache", 
+            LOG(log_error, logtype_afpd, "dircache_remove(%u,\"%s\"): not in dircache", 
                 ntohl(dir->d_did), cfrombstr(dir->d_u_name));
             dircache_dump();
             AFP_PANIC("dircache_remove");
@@ -614,13 +638,12 @@ void dircache_dump(void)
     i = 1;
     while ((hn = hash_scan_next(&hs))) {
         dir = hnode_get(hn);
-        fprintf(dump, "%05u: %3u  %6u  %6u  %s%s  %s\n",
+        fprintf(dump, "%05u: %3u  %6u  %6u %s    %s\n",
                 i++,
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
                 dir->d_fullpath ? "d" : "f",
-                (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 cfrombstr(dir->d_u_name));
     }
 
@@ -631,13 +654,12 @@ void dircache_dump(void)
     i = 1;
     while ((hn = hash_scan_next(&hs))) {
         dir = hnode_get(hn);
-        fprintf(dump, "%05u: %3u  %6u  %6u  %s%s  %s\n",
+        fprintf(dump, "%05u: %3u  %6u  %6u %s    %s\n",
                 i++,
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
                 dir->d_fullpath ? "d" : "f",
-                (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 cfrombstr(dir->d_u_name));
     }
 
@@ -649,17 +671,17 @@ void dircache_dump(void)
         if (n == index_queue)
             break;
         dir = (struct dir *)n->data;
-        fprintf(dump, "%05u: %3u  %6u  %6u  %s%s  %s\n",
+        fprintf(dump, "%05u: %3u  %6u  %6u %s    %s\n",
                 i,
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
                 dir->d_fullpath ? "d" : "f",
-                (dir->d_flags & DIRF_CACHELOCK) ? "l" : "-",
                 cfrombstr(dir->d_u_name));
         n = n->next;
     }
 
     fprintf(dump, "\n");
+    fflush(dump);
     return;
 }
index 69c5f9abebd40ae197cecae82a60f4421d81ae98..16c2df1dbde26ab5d3d994d429172a98fa9bcc7a 100644 (file)
@@ -32,7 +32,7 @@
 #define DIRCACHE_ALL  (DIRCACHE|DIDNAME_INDEX|QUEUE_INDEX)
 
 extern int        dircache_init(int reqsize);
-extern int        dircache_add(struct dir *);
+extern int        dircache_add(const struct vol *, struct dir *);
 extern void       dircache_remove(const struct vol *, struct dir *, int flag);
 extern struct dir *dircache_search_by_did(const struct vol *vol, cnid_t did);
 extern struct dir *dircache_search_by_name(const struct vol *, const struct dir *dir, char *name, int len, time_t ctime);
index 3edbec25966df7627cd97c702da2adec011f1b55..488f900a0a553e7ee278962e8a2f786087557d72 100644 (file)
@@ -28,6 +28,7 @@
 #include <atalk/unix.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/errchk.h>
 
 #include "directory.h"
 #include "dircache.h"
@@ -301,7 +302,7 @@ static int cname_mtouname(const struct vol *vol, const struct dir *dir, struct p
 {
     static char temp[ MAXPATHLEN + 1];
     char *t;
-    cnid_t fileid;
+    cnid_t fileid = 0;
 
     if (afp_version >= 30) {
         if (toUTF8) {
@@ -429,6 +430,84 @@ int get_afp_errno(const int param)
     return param;
 }
 
+/*!
+ * Resolve struct dir for an absolute path
+ *
+ * Given a path like "/Volumes/volume/dir/subdir" in a volume "/Volumes/volume" return
+ * a pointer to struct dir of "subdir".
+ * 1. Remove volue path from absolute path
+ * 2. start path
+ * 3. loop through all elements of the remaining path from 1.
+ * 4. we only allow dirs
+ * 5. search dircache
+ * 6. if not found in the dircache query the CNID database for the DID
+ * 7. and use dirlookup to resolve the DID to a it's struct dir *
+ *
+ * @param vol   (r) volume the path is in, must be known
+ * @param path  (r) absoule path
+ *
+ * @returns pointer to struct dir or NULL on error
+ */
+struct dir *dirlookup_bypath(const struct vol *vol, const char *path)
+{
+    EC_INIT;
+
+    struct dir *dir = NULL;
+    cnid_t cnid, did;
+    bstring rpath = NULL;
+    bstring statpath = NULL;
+    struct bstrList *l = NULL;
+    struct stat st;
+
+    cnid = htonl(2);
+    dir = vol->v_root;
+
+    EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */
+    EC_NULL(statpath = bfromcstr(vol->v_path));          /* 2. */
+
+    l = bsplit(rpath, '/');
+    for (int i = 0; i < l->qty ; i++) {                  /* 3. */
+        did = cnid;
+        EC_ZERO(bconcat(statpath, l->entry[i]));
+        EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
+                       "lstat(rpath: %s, elem: %s): %s: %s",
+                       cfrombstr(rpath), cfrombstr(l->entry[i]),
+                       cfrombstr(statpath), strerror(errno));
+
+        if (!(S_ISDIR(st.st_mode)))                      /* 4. */
+            EC_FAIL;
+
+        if ((dir = dircache_search_by_name(vol,          /* 5. */
+                                           dir,
+                                           cfrombstr(l->entry[i]),
+                                           blength(l->entry[i]),
+                                           st.st_ctime)) == NULL) {
+            if ((cnid = cnid_add(vol->v_cdb,             /* 6. */
+                                 &st,
+                                 did,
+                                 cfrombstr(l->entry[i]),
+                                 blength(l->entry[i]),
+                                 0)) == CNID_INVALID) {
+                EC_FAIL;
+            }
+
+            if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
+                EC_FAIL;
+        }
+
+        EC_ZERO(bcatcstr(statpath, "/"));
+    }
+
+EC_CLEANUP:
+    bdestroy(rpath);
+    bstrListDestroy(l);
+    bdestroy(statpath);
+    if (ret != 0)
+        return NULL;
+
+    return dir;
+}
+
 /*!
  * @brief Resolve a DID
  *
@@ -446,9 +525,6 @@ int get_afp_errno(const int param)
  * @param did   (r) DID to resolve
  *
  * @returns pointer to struct dir
- *
- * @note FIXME: OSX calls it with bogus id, ie file ID not folder ID,
- *       and we are really bad in this case.
  */
 struct dir *dirlookup(const struct vol *vol, cnid_t did)
 {
@@ -463,24 +539,28 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     int          utf8;
     int          err = 0;
 
-    LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {start}", ntohl(did));
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did));
 
     /* check for did 0, 1 and 2 */
     if (did == 0 || vol == NULL) { /* 1 */
         afp_errno = AFPERR_PARAM;
-        return NULL;
+        ret = NULL;
+        goto exit;
     } else if (did == DIRDID_ROOT_PARENT) {
         rootParent.d_vid = vol->v_vid;
-        return (&rootParent);
+        ret = &rootParent;
+        goto exit;
     } else if (did == DIRDID_ROOT) {
-        return vol->v_root;
+        ret = vol->v_root;
+        goto exit;
     }
 
     /* Search the cache */
     if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
         if (ret->d_fullpath == NULL) {                      /* 2b */
             afp_errno = AFPERR_BADTYPE;
-            return NULL;
+            ret = NULL;
+            goto exit;
         }
         if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) {
             LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
@@ -491,14 +571,18 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
                 LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {calling dir_remove()}", ntohl(did));
                 dir_remove(vol, ret);
                 afp_errno = AFPERR_NOOBJ;
-                return NULL;
+                ret = NULL;
+                goto exit;
             default:
-                return ret;
+                ret = ret;
+                goto exit;
             }
             /* DEADC0DE */
-            return NULL;
+            ret = NULL;
+            goto exit;            
         }
-        return ret;
+        ret = ret;
+        goto exit;
     }
 
     utf8 = utf8_encoding();
@@ -506,8 +590,12 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
 
     /* Get it from the database */
     cnid = did;
-    if ( (upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL 
-         || (upath = strdup(upath)) == NULL) { /* 3 */
+    if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) {
+        afp_errno = AFPERR_NOOBJ;
+        err = 1;
+        goto exit;
+    }
+    if ((upath = strdup(upath)) == NULL) { /* 3 */
         afp_errno = AFPERR_NOOBJ;
         err = 1;
         goto exit;
@@ -519,6 +607,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
      * - DIRDID_ROOT is hit
      * - a cached entry is found
      */
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid));
     if ((pdir = dirlookup(vol, pdid)) == NULL) {
         err = 1;
         goto exit;
@@ -573,14 +662,11 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
     
     /* Add it to the cache only if it's a dir */
-    if (dircache_add(ret) != 0) { /* 7 */
+    if (dircache_add(vol, ret) != 0) { /* 7 */
         err = 1;
         goto exit;
     }
 
-    LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {end: did:%u, path:'%s'}",
-        ntohl(did), ntohl(pdid), cfrombstr(ret->d_fullpath));
-
 exit:
     if (upath) free(upath);
     if (err) {
@@ -593,6 +679,10 @@ exit:
             ret = NULL;
         }
     }
+    if (ret)
+        LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"",
+            ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath));
+
     return ret;
 }
 
@@ -817,6 +907,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
     /* Get macname from unixname */
     if (path->m_name == NULL) {
         if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding())) == NULL) {
+            LOG(log_error, logtype_afpd, "dir_add(\"%s\"): can't assign macname", path->u_name);
             err = 2;
             goto exit;
         }
@@ -837,7 +928,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
         goto exit;
     }
 
-    if ((dircache_add(cdir)) != 0) { /* 4 */
+    if ((dircache_add(vol, cdir)) != 0) { /* 4 */
         LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstr(fullpath));
         exit(EXITERR_SYS);
     }
@@ -880,9 +971,9 @@ void dir_free_invalid_q(void)
  * @brief Remove a dir from a cache and queue it for freeing
  *
  * 1. Check if the dir is locked or has opened forks
- * 2. If it's a request to remove curdir, just chdir to volume root
- * 3. Remove it from the cache
- * 4. Queue it for removal
+ * 2. Remove it from the cache
+ * 3. Queue it for removal
+ * 4. If it's a request to remove curdir, mark curdir as invalid
  * 5. Mark it as invalid
  *
  * @param (r) pointer to struct vol
@@ -896,27 +987,21 @@ int dir_remove(const struct vol *vol, struct dir *dir)
     if (dir->d_did == DIRDID_ROOT_PARENT || dir->d_did == DIRDID_ROOT)
         return 0;
 
-    if (dir->d_flags & DIRF_CACHELOCK) { /* 1 */
-        LOG(log_warning, logtype_afpd, "dir_remove(did:%u,'%s'): dir is locked",
-            ntohl(dir->d_did), cfrombstr(dir->d_u_name));
-        return 0;
-    }
-
-    if (curdir == dir) {        /* 2 */
-        if (movecwd(vol, vol->v_root) < 0) {
-            LOG(log_error, logtype_afpd, "dir_remove: can't chdir to : %s", vol->v_root);
-        }
-    }
-
     LOG(log_debug, logtype_afpd, "dir_remove(did:%u,'%s'): {removing}",
         ntohl(dir->d_did), cfrombstr(dir->d_u_name));
 
-    dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 3 */
-    enqueue(invalid_dircache_entries, dir); /* 4 */
+    dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 2 */
+    enqueue(invalid_dircache_entries, dir); /* 3 */
+
+    if (curdir == dir)                      /* 4 */
+        curdir = NULL;
+
     dir->d_did = CNID_INVALID;              /* 5 */
+
     return 0;
 }
 
+#if 0 /* unused */
 /*!
  * @brief Modify a struct dir, adjust cache
  *
@@ -988,13 +1073,14 @@ int dir_modify(const struct vol *vol,
         dir->d_m_name_ucs2 = NULL;
 
     /* Re-add it to the cache */
-    if ((dircache_add(dir)) != 0) {
+    if ((dircache_add(vol, dir)) != 0) {
         dircache_dump();
         AFP_PANIC("dir_modify");
     }
 
     return ret;
 }
+#endif
 
 /*!
  * @brief Resolve a catalog node name path
@@ -1104,7 +1190,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
         /* 6*/
         for ( p = path; *data != 0 && len > 0; len-- ) {
             *p++ = *data++;
-            if (p > &path[ MAXPATHLEN]) {
+            if (p > &path[UTF8FILELEN_EARLY]) {   /* FIXME safeguard, limit of early Mac OS X */
                 afp_errno = AFPERR_PARAM;
                 return NULL;
             }
@@ -1253,21 +1339,19 @@ int movecwd(const struct vol *vol, struct dir *dir)
     AFP_ASSERT(vol);
     AFP_ASSERT(dir);
 
-    LOG(log_maxdebug, logtype_afpd, "movecwd(curdir:'%s', cwd:'%s')",
-        cfrombstr(curdir->d_fullpath), getcwdpath());
+    LOG(log_maxdebug, logtype_afpd, "movecwd: from: curdir:\"%s\", cwd:\"%s\"",
+        curdir ? cfrombstr(curdir->d_fullpath) : "INVALID", getcwdpath());
 
-    if ( dir == curdir)
-        return( 0 );
     if (dir->d_did == DIRDID_ROOT_PARENT) {
         curdir = &rootParent;
         return 0;
     }
 
-    LOG(log_debug, logtype_afpd, "movecwd(did:%u, '%s')",
+    LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")",
         ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
 
     if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) {
-        LOG(log_debug, logtype_afpd, "movecwd('%s'): ret: %u, %s",
+        LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): ret: %u, %s",
             cfrombstr(dir->d_fullpath), ret, strerror(errno));
         if (ret == 1) {
             /* p is a symlink or getcwd failed */
@@ -1328,10 +1412,18 @@ int file_access(struct path *path, int mode)
     struct maccess ma;
 
     accessmode(path->u_name, &ma, curdir, &path->st);
-    if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+
+    LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x",
+        path->u_name, ma.ma_user);
+
+    if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) {
+        LOG(log_debug, logtype_afpd, "file_access(\"%s\"): write access denied", path->u_name);
         return -1;
-    if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+    }
+    if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) {
+        LOG(log_debug, logtype_afpd, "file_access(\"%s\"): read access denied", path->u_name);
         return -1;
+    }
     return 0;
 
 }
@@ -2220,13 +2312,13 @@ int deletecurdir(struct vol *vol)
 {
     struct dirent *de;
     struct stat st;
-    struct dir  *fdir;
+    struct dir  *fdir, *pdir;
     DIR *dp;
     struct adouble  ad;
     u_int16_t       ashort;
     int err;
 
-    if ( dirlookup(vol, curdir->d_pdid) == NULL ) {
+    if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) {
         return( AFPERR_ACCESS );
     }
 
@@ -2244,6 +2336,8 @@ int deletecurdir(struct vol *vol)
     }
     err = vol->vfs->vfs_deletecurdir(vol);
     if (err) {
+        LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"",
+            curdir->d_fullpath);
         return err;
     }
 
@@ -2256,6 +2350,8 @@ int deletecurdir(struct vol *vol)
 
             /* bail if it's not a symlink */
             if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
+                LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty",
+                    curdir->d_fullpath);
                 closedir(dp);
                 return AFPERR_DIRNEMPT;
             }
@@ -2267,16 +2363,23 @@ int deletecurdir(struct vol *vol)
         }
     }
 
-    if ( movecwd(vol, dirlookup(vol, curdir->d_pdid)) < 0 ) {
+    if (movecwd(vol, pdir) < 0) {
         err = afp_errno;
         goto delete_done;
     }
 
+    LOG(log_debug, logtype_afpd, "deletecurdir: moved to \"%s\"",
+        cfrombstr(curdir->d_fullpath));
+
     err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name));
     if ( err ==  AFP_OK || err == AFPERR_NOOBJ) {
         cnid_delete(vol->v_cdb, fdir->d_did);
         dir_remove( vol, fdir );
+    } else {
+        LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error",
+            curdir->d_fullpath);
     }
+
 delete_done:
     if (dp) {
         /* inode is used as key for cnid.
index 731140ababecd7140946c7572b8b392615a7525e..1504c649dbb9ba55ea083f8bc95b6d701cf6b05c 100644 (file)
@@ -46,7 +46,6 @@
 
 #define DIRF_OFFCNT    (1<<4) /* offsprings count is valid */
 #define DIRF_CNID         (1<<5) /* renumerate id */
-#define DIRF_CACHELOCK (1<<6) /* lock in cache, don't remove in dircache_eviction, for catsearch */
 
 #define AFPDIR_READ    (1<<0)
 
@@ -115,6 +114,8 @@ extern int         dir_modify(const struct vol *vol, struct dir *dir, cnid_t pdi
                               const char *new_mname, const char *new_uname, bstring pdir_fullpath);
 extern int         dir_remove(const struct vol *vol, struct dir *dir);
 extern struct dir  *dirlookup (const struct vol *, cnid_t);
+extern struct dir *dirlookup_bypath(const struct vol *vol, const char *path);
+
 extern int         movecwd (const struct vol *, struct dir *);
 extern struct path *cname (struct vol *, struct dir *, char **);
 
index 79869dbd0d84fc3256ca7ec8999b02a323f1950f..1659fb77ff89cc5fbff15513fe5915600b718ae4 100644 (file)
@@ -155,7 +155,7 @@ for_each_dirent(const struct vol *vol, char *name, dir_loop fn, void *data)
    macnamelength(1) + macname(31) + utf8(4) + utf8namelen(2) + utf8name(255) +
    oddpadding(1) */
 
-#define REPLY_PARAM_MAXLEN (4 + 104 + 1 + MACFILELEN + 4 + 2 + 255 + 1)
+#define REPLY_PARAM_MAXLEN (4 + 104 + 1 + MACFILELEN + 4 + 2 + UTF8FILELEN_EARLY + 1)
 
 /* ----------------------------- */
 static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, 
@@ -284,11 +284,12 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
         sd.sd_last = sd.sd_buf;
         /* if dir was in the cache we don't have the inode */
         if (( !o_path->st_valid && lstat( ".", &o_path->st ) < 0 ) ||
-              (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) 
+            (ret = for_each_dirent(vol, ".", enumerate_loop, (void *)&sd)) < 0) 
         {
+            LOG(log_error, logtype_afpd, "enumerate: loop error: %s (%d)", strerror(errno), errno);
             switch (errno) {
             case EACCES:
-               return AFPERR_ACCESS;
+                return AFPERR_ACCESS;
             case ENOTDIR:
                 return AFPERR_BADTYPE;
             case ENOMEM:
index bd0e935c0fe8d2e44049b7471578cdf69e969e9f..0459656f1ed51572135398ef97adfd818470e5fa 100644 (file)
@@ -150,8 +150,8 @@ char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t
     else {
         u_int16_t temp;
 
-        if (aint > 255)  /* FIXME safeguard, anyway if no ascii char it's game over*/
-           aint = 255;
+        if (aint > UTF8FILELEN_EARLY)  /* FIXME safeguard, anyway if no ascii char it's game over*/
+           aint = UTF8FILELEN_EARLY;
 
         utf8 = vol->v_kTextEncoding;
         memcpy(data, &utf8, sizeof(utf8));
@@ -301,6 +301,8 @@ int getmetadata(struct vol *vol,
     struct stat         *st;
     struct maccess     ma;
 
+    LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name);
+
     upath = path->u_name;
     st = &path->st;
     data = buf;
@@ -333,7 +335,7 @@ int getmetadata(struct vol *vol,
                     exit(EXITERR_SYS);
                 }
 
-                if ((dircache_add(cachedfile)) != 0) {
+                if ((dircache_add(vol, cachedfile)) != 0) {
                     LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
                     exit(EXITERR_SYS);
                 }
@@ -598,6 +600,8 @@ int getfilparams(struct vol *vol,
     int                 opened = 0;
     int rc;    
 
+    LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
+
     opened = PARAM_NEED_ADP(bitmap);
     adp = NULL;
 
@@ -719,6 +723,17 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
 
     path = s_path->m_name;
     ad_setname(&ad, path);
+
+    struct stat st;
+    if (lstat(upath, &st) != 0) {
+        LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s",
+            upath, strerror(errno));
+        ad_close( adp, ADFLAGS_DF|ADFLAGS_HF);
+        return AFPERR_MISC;
+    }
+
+    (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
+
     ad_flush(&ad);
     ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
 
@@ -1063,6 +1078,9 @@ int renamefile(const struct vol *vol, int sdir_fd, char *src, char *dst, char *n
 {
     int                rc;
 
+    LOG(log_debug, logtype_afpd,
+        "renamefile: src[%d, \"%s\"] -> dst[\"%s\"]", sdir_fd, src, dst);
+
     if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) {
         switch ( errno ) {
         case ENOENT :
index bb2bdd1dd0011f21d0e9c001e981d9dd2f34cc76..1478299e262d297946cf9eed86434e6589c7d6b9 100644 (file)
@@ -230,7 +230,7 @@ static int moveandrename(const struct vol *vol,
                          char *newname,
                          int isdir)
 {
-    char            *p;
+    char            *oldunixname = NULL;
     char            *upath;
     int             rc;
     struct stat     *st, nst;
@@ -242,48 +242,52 @@ static int moveandrename(const struct vol *vol,
     cnid_t          id;
     int             cwd_fd = -1;
 
+    LOG(log_debug, logtype_afpd,
+        "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"",
+        cfrombstr(sdir->d_u_name), oldname, newname);
+
     ad_init(&ad, vol->v_adouble, vol->v_ad_options);
     adp = &ad;
     adflags = 0;
 
     if (!isdir) {
-        if ((p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding())) == NULL)
+        if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding()))) == NULL)
             return AFPERR_PARAM; /* can't convert */
+        id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname));
 
-#ifndef HAVE_RENAMEAT
+#ifndef HAVE_ATFUNCS
         /* Need full path */
-        id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p));
-        p = ctoupath( vol, sdir, oldname );
-        if (!p)
+        free(oldunixname);
+        if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL)
             return AFPERR_PARAM; /* pathname too long */
-#endif /* HAVE_RENAMEAT */
+#endif /* HAVE_ATFUNCS */
 
         path.st_valid = 0;
-        path.u_name = p;
-#ifdef HAVE_RENAMEAT
+        path.u_name = oldunixname;
+
+#ifdef HAVE_ATFUNCS
         opened = of_findnameat(sdir_fd, &path);
 #else
         opened = of_findname(&path);
-#endif /* HAVE_RENAMEAT */
+#endif /* HAVE_ATFUNCS */
+
         if (opened) {
             /* reuse struct adouble so it won't break locks */
             adp = opened->of_ad;
         }
     } else {
         id = sdir->d_did; /* we already have the CNID */
-        p = ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname );
-        if (!p) {
+        if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL)
             return AFPERR_PARAM;
-        }
         adflags = ADFLAGS_DIR;
     }
 
     /*
-     * p now points to either
+     * oldunixname now points to either
      *   a) full pathname of the source fs object (if renameat is not available)
      *   b) the oldname (renameat is available)
      * we are in the dest folder so we need to use 
-     *   a) p for ad_open
+     *   a) oldunixname for ad_open
      *   b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate
      */
 
@@ -295,7 +299,7 @@ static int moveandrename(const struct vol *vol,
             goto exit;
         }
     }
-    if (!ad_metadata(p, adflags, adp)) {
+    if (!ad_metadata(oldunixname, adflags, adp)) {
         u_int16_t bshort;
 
         ad_getattr(adp, &bshort);
@@ -332,7 +336,7 @@ static int moveandrename(const struct vol *vol,
         }
 
         if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) {
-            if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
+            if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
                 /* not the same file */
                 rc = AFPERR_EXIST;
                 goto exit;
@@ -350,12 +354,12 @@ static int moveandrename(const struct vol *vol,
         if (of_findname(&path)) {
             rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
         } else {
-            rc = renamefile(vol, sdir_fd, p, upath, newname, adp );
+            rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp );
             if (rc == AFP_OK)
                 of_rename(vol, opened, sdir, oldname, curdir, newname);
         }
     } else {
-        rc = renamedir(vol, sdir_fd, p, upath, sdir, curdir, newname);
+        rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname);
     }
     if ( rc == AFP_OK && id ) {
         /* renaming may have moved the file/dir across a filesystem */
@@ -371,6 +375,13 @@ static int moveandrename(const struct vol *vol,
             (void)dir_remove(vol, cacheddir);
         }
 
+        /* Fixup adouble info */
+        if (!ad_metadata(upath, adflags, adp)) {
+            ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp);
+            ad_flush(adp);
+            ad_close_metadata(adp);
+        }
+
         /* fix up the catalog entry */
         cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath));
     }
@@ -378,6 +389,8 @@ static int moveandrename(const struct vol *vol,
 exit:
     if (cwd_fd != -1)
         close(cwd_fd);
+    if (oldunixname)
+        free(oldunixname);
     return rc;
 }
 
@@ -612,7 +625,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
         memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1);
     }
 
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if ((sdir_fd = open(".", O_RDONLY)) == -1)
         return AFPERR_MISC;
 #endif
@@ -667,7 +680,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     }
 
 exit:
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (sdir_fd != -1)
         close(sdir_fd);
 #endif
index c1060dbe3492f569f57a28b0c296e436a85ceb84..e950aa0ffdf6aa72cb47d8e167ab078ca32fcd41 100644 (file)
@@ -68,12 +68,13 @@ extern int          of_stat      (struct path *);
 extern int          of_statdir   (struct vol *vol, struct path *);
 extern int          of_closefork (struct ofork *ofork);
 extern void         of_closevol  (const struct vol *vol);
+extern void         of_close_all_forks(void);
 extern struct adouble *of_ad     (const struct vol *, struct path *, struct adouble *);
 
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
 extern struct ofork *of_findnameat(int dirfd, struct path *path);
 extern int of_fstatat(int dirfd, struct path *path);
-#endif  /* HAVE_RENAMEAT */
+#endif  /* HAVE_ATFUNCS */
 
 
 /* in fork.c */
index 3a9c229c4ad077e7d1ee82cce6b8feffed294f99..4d81463d44dfadc860fa71a4fca423e7daa32820 100644 (file)
 #include <atalk/unicode.h>
 #include <atalk/uam.h>
 
-#define MACFILELEN 31
+/* #define DOSFILELEN 12 */             /* Type1, DOS-compat*/
+#define MACFILELEN 31                   /* Type2, HFS-compat */
+#define UTF8FILELEN_EARLY 255           /* Type3, early Mac OS X 10.0-10.4.? */
+/* #define UTF8FILELEN_NAME_MAX 765 */  /* Type3, 10.4.?- , getconf NAME_MAX */
+/* #define UTF8FILELEN_SPEC 0xFFFF */   /* Type3, spec on document */
+/* #define HFSPLUSFILELEN 510 */        /* HFS+ spec, 510byte = 255codepoint */
+
 #define MAXUSERLEN 256
 
 #define OPTION_DEBUG         (1 << 0)
@@ -50,8 +56,10 @@ struct afp_options {
     int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
     int sleep;                  /* Maximum time allowed to sleep (in tickles) */
     int disconnected;           /* Maximum time in disconnected state (in tickles) */
+    unsigned int tcp_sndbuf, tcp_rcvbuf;
     unsigned char passwdbits, passwdminlen, loginmaxfail;
     u_int32_t server_quantum;
+    int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
     char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
     char *uampath, *fqdn;
     char *pidfile;
index 91533e619a674d9748b5c1cc6f365c6d58952aae..cb2b60ed0c15e5bd63bb0cb1ca1c66e7a02089ba 100644 (file)
@@ -1,6 +1,4 @@
 /* 
- * $Id: mangle.c,v 1.19.4.2 2010-02-01 14:25:45 franklahm Exp $ 
- *
  * Copyright (c) 2002. Joe Marcus Clarke (marcus@marcuscom.com)
  * All Rights Reserved.  See COPYRIGHT.
  *
@@ -225,13 +223,22 @@ demangle_osx(const struct vol *vol, char *mfilename, cnid_t did, cnid_t *fileid)
     return private_demangle(vol, mfilename, did, fileid);
 }
 
+/* -------------------------------------------------------
+   FIXME !!!
+
+   Early Mac OS X (10.0-10.4.?) had the limitation up to 255 Byte.
+   Current implementation is:
+      volcharset -> UTF16-MAC -> truncated 255 UTF8-MAC
+
+   Recent Mac OS X (10.4.?-) don't have this limitation.
+   Desirable implementation is:
+      volcharset -> truncated 510 UTF16-MAC -> UTF8-MAC
 
-/* -----------------------
+   ------------------------
    with utf8 filename not always round trip
    filename   mac filename too long or first chars if unmatchable chars.
    uname      unix filename 
    id         file/folder ID or 0
-   
 */
 char *
 mangle(const struct vol *vol, char *filename, size_t filenamelen, char *uname, cnid_t id, int flags) {
@@ -243,7 +250,7 @@ mangle(const struct vol *vol, char *filename, size_t filenamelen, char *uname, c
     size_t maxlen;
     int k;
     
-    maxlen = (flags & 2)?255:MACFILELEN; /* was vol->max_filename */
+    maxlen = (flags & 2)?UTF8FILELEN_EARLY:MACFILELEN; /* was vol->max_filename */
     /* Do we really need to mangle this filename? */
     if (!(flags & 1) && filenamelen <= maxlen) {
        return filename;
index c3ca09c10cc5d4bc4df16c2e258e9524f0505ff4..7e2d3d57630a3b28a76011d227db44abacc8a5e0 100644 (file)
@@ -195,7 +195,7 @@ of_alloc(struct vol *vol,
            ad_open really does reinitialize the structure. */
         ad_init(ad, vol->v_adouble, vol->v_ad_options);
 
-        ad->ad_m_namelen = 255 +1;
+        ad->ad_m_namelen = UTF8FILELEN_EARLY +1;
         /* here's the deal: we allocate enough for the standard mac file length.
          * in the future, we'll reallocate in fairly large jumps in case
          * of long unicode names */
@@ -253,7 +253,7 @@ int of_stat(struct path *path)
 }
 
 
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
 int of_fstatat(int dirfd, struct path *path)
 {
     int ret;
@@ -266,7 +266,7 @@ int of_fstatat(int dirfd, struct path *path)
 
    return ret;
 }
-#endif /* HAVE_RENAMEAT */
+#endif /* HAVE_ATFUNCS */
 
 /* -------------------------- 
    stat the current directory.
@@ -346,7 +346,7 @@ struct ofork *of_findname(struct path *path)
  * @param dirfd     (r) directory fd
  * @param path      (rw) pointer to struct path
  */
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
 struct ofork *of_findnameat(int dirfd, struct path *path)
 {
     struct ofork *of;
@@ -455,3 +455,23 @@ void of_closevol(const struct vol *vol)
     return;
 }
 
+/* ----------------------
+   close all forks for a volume
+*/
+void of_close_all_forks(void)
+{
+    int refnum;
+
+    if (!oforks)
+        return;
+
+    for ( refnum = 0; refnum < nforks; refnum++ ) {
+        if (oforks[ refnum ] != NULL) {
+            if (of_closefork( oforks[ refnum ]) < 0 ) {
+                LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) );
+            }
+        }
+    }
+    return;
+}
+
index 1037f15a0c591c1d09d33ae062278f46eac58e65..24b6b8077a9223203a4fe4e78e817ee29113aa61 100644 (file)
@@ -609,14 +609,14 @@ server_signature_auto:
                 options->sigconffile, strerror(errno));
             goto server_signature_random;
         }
-    } else { /* conf file don't exist */
+    } else {                                                          /* conf file don't exist */
         if (( fd = creat(options->sigconffile, 0644 )) < 0 ) {
-            LOG(log_error, logtype_atalkd, "Cannot create %s (%s). Using one-time signature.",
+            LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s). Using one-time signature.",
                 options->sigconffile, strerror(errno));
             goto server_signature_random;
         }
         if (( fp = fdopen( fd, "w" )) == NULL ) {
-            LOG(log_error, logtype_atalkd, "Cannot fdopen %s (%s). Using one-time signature.",
+            LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s). Using one-time signature.",
                 options->sigconffile, strerror(errno));
             close(fd);
             goto server_signature_random;
index efc72923f6606a277674487317e702602f8b9d1d..232fb30349e328b366bdfd1758c6b3c1a38645b5 100644 (file)
@@ -140,6 +140,7 @@ mode_t mode;
 }
 
 #ifdef accessmode
+
 #undef accessmode
 #endif
 /*
index 2970bcc3b25e4ae343491f83951d7b0d4c302ec3..60fc73e9073292a3452a03559022769b616a459e 100644 (file)
@@ -29,6 +29,8 @@
 #include <atalk/vfs.h>
 #include <atalk/uuid.h>
 #include <atalk/ea.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
 
 #ifdef CNID_DB
 #include <atalk/cnid.h>
@@ -135,6 +137,8 @@ static void handle_special_folders (const struct vol *);
 static void deletevol(struct vol *vol);
 static void volume_free(struct vol *vol);
 static void check_ea_sys_support(struct vol *vol);
+static char *get_vol_uuid(const AFPObj *obj, const char *volname);
+static int readvolfile(AFPObj *obj, struct afp_volume_name *p1,char *p2, int user, struct passwd *pwent);
 
 static void volfree(struct vol_option *options, const struct vol_option *save)
 {
@@ -616,6 +620,7 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
     /* check duplicate */
     for ( volume = Volumes; volume; volume = volume->v_next ) {
         if (( strcasecmp_w( volume->v_u8mname, u8mtmpname ) == 0 ) || ( strcasecmp_w( volume->v_macname, mactmpname ) == 0 )){
+            LOG (log_error, logtype_afpd, "ERROR: Volume name is duplicated. Check AppleVolumes files.");
             if (volume->v_deleted) {
                 volume->v_new = hide = 1;
             }
@@ -784,7 +789,7 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
 
     /* get/store uuid from file */
     if (volume->v_flags & AFPVOL_TM) {
-        char *uuid = get_uuid(obj, volume->v_localname);
+        char *uuid = get_vol_uuid(obj, volume->v_localname);
         if (!uuid) {
             LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID",
                 volume->v_localname);
@@ -1075,7 +1080,7 @@ static int volfile_changed(struct afp_volume_name *p)
  *      <extension> TYPE [CREATOR]
  *
  */
-int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent)
+static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent)
 {
     FILE        *fp;
     char        path[MAXPATHLEN + 1];
@@ -1112,6 +1117,14 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str
         p1->mtime = st.st_mtime;
     }
 
+    if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
+        LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
+        if ( fclose( fp ) != 0 ) {
+            LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
+        }
+        return -1;
+    }
+
     memset(save_options, 0, sizeof(save_options));
 
     /* Enable some default options for all volumes */
@@ -1359,10 +1372,45 @@ static int getvolspace(struct vol *vol,
 
 getvolspace_done:
     if (vol->v_limitsize) {
-        /* FIXME: Free could be limit minus (total minus used), */
-        /* which will confuse the client less ? */
-        *xbfree = min(*xbfree, (vol->v_limitsize * 1024 * 1024));
+        bstring cmdstr;
+        if ((cmdstr = bformat("du -sh \"%s\" 2> /dev/null | cut -f1", vol->v_path)) == NULL)
+            return AFPERR_MISC;
+
+        FILE *cmd = popen(cfrombstr(cmdstr), "r");
+        bdestroy(cmdstr);
+        if (cmd == NULL)
+            return AFPERR_MISC;
+
+        char buf[100];
+        fgets(buf, 100, cmd);
+
+        if (pclose(cmd) == -1)
+            return AFPERR_MISC;
+
+        size_t multi = 0;
+        if (buf[strlen(buf) - 2] == 'G' || buf[strlen(buf) - 2] == 'g')
+            /* GB */
+            multi = 1024 * 1024 * 1024;
+        else if (buf[strlen(buf) - 2] == 'M' || buf[strlen(buf) - 2] == 'm')
+            /* MB */
+            multi = 1024 * 1024;
+        else if (buf[strlen(buf) - 2] == 'K' || buf[strlen(buf) - 2] == 'k')
+            /* MB */
+            multi = 1024;
+
+        char *p;
+        if (p = strchr(buf, ','))
+            /* ignore fraction */
+            *p = 0;
+        else
+            /* remove G|M|K char */
+            buf[strlen(buf) - 2] = 0;
+        /* now buf contains only digits */
+        long long used = atoll(buf) * multi;
+        LOG(log_debug, logtype_afpd, "volparams: used on volume: %llu bytes", used);
+
         *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+        *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used);
     }
 
     *bfree = min( *xbfree, maxsize);
@@ -1890,7 +1938,7 @@ static void check_ea_sys_support(struct vol *vol)
     if (vol->v_vfs_ea == AFPVOL_EA_AUTO) {
 
         if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) {
-            LOG(log_info, logtype_logger, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
+            LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
             vol->v_vfs_ea = AFPVOL_EA_NONE;
             return;
         }
@@ -1900,7 +1948,7 @@ static void check_ea_sys_support(struct vol *vol)
         process_uid = geteuid();
         if (process_uid)
             if (seteuid(0) == -1) {
-                LOG(log_error, logtype_logger, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno));
+                LOG(log_error, logtype_afpd, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno));
                 exit(EXITERR_SYS);
             }
 
@@ -1915,7 +1963,7 @@ static void check_ea_sys_support(struct vol *vol)
 
         if (process_uid) {
             if (seteuid(process_uid) == -1) {
-                LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+                LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
                 exit(EXITERR_SYS);
             }
         }
@@ -2051,7 +2099,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
      * FIXME file size
      */
     if (utf8_encoding()) {
-        volume->max_filename = 255;
+        volume->max_filename = UTF8FILELEN_EARLY;
     }
     else {
         volume->max_filename = MACFILELEN;
@@ -2554,7 +2602,7 @@ void unload_volumes_and_extmap(void)
  *
  * Returns pointer to allocated storage on success, NULL on error.
  */
-char *get_uuid(const AFPObj *obj, const char *volname)
+static char *get_vol_uuid(const AFPObj *obj, const char *volname)
 {
     char *volname_conf;
     char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p;
@@ -2606,12 +2654,12 @@ char *get_uuid(const AFPObj *obj, const char *volname)
 
     if (stat(obj->options.uuidconf, &tmpstat)) {                /* no file */
         if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) {
-            LOG(log_error, logtype_atalkd, "ERROR: Cannot create %s (%s).",
+            LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).",
                 obj->options.uuidconf, strerror(errno));
             return NULL;
         }
         if (( fp = fdopen( fd, "w" )) == NULL ) {
-            LOG(log_error, logtype_atalkd, "ERROR: Cannot fdopen %s (%s).",
+            LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).",
                 obj->options.uuidconf, strerror(errno));
             close(fd);
             return NULL;
@@ -2642,5 +2690,5 @@ char *get_uuid(const AFPObj *obj, const char *volname)
     fprintf(fp, "\"%s\"\t%36s\n", volname, cp);
     fclose(fp);
     
-    return strdup(uuid);
+    return strdup(cp);
 }
index 883b1d56729a526bfe84ed48395a7b843a44de01..a0b45940a1397036370df7029d3800c803100d08 100644 (file)
@@ -25,14 +25,8 @@ extern int              ustatfs_getvolspace (const struct vol *,
 extern void             setvoltime (AFPObj *, struct vol *);
 extern int              pollvoltime (AFPObj *);
 extern void             load_volumes (AFPObj *obj);
-extern int              readvolfile(AFPObj *obj,
-                                    struct afp_volume_name *p1,
-                                    char *p2,
-                                    int user,
-                                    struct passwd *pwent);
 extern const struct vol *getvolumes(void);
 extern void             unload_volumes_and_extmap(void);
-extern char             *get_uuid(const AFPObj *obj, const char *volname);
 
 /* FP functions */
 int afp_openvol      (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
index 0b81b8ccefe3777a89700d3834bcc409d1da9f02..5493a28059461cb525f49f99ecaa0cbf16dbb15d 100644 (file)
 #include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/volinfo.h>
+#include <atalk/util.h>
+
 #include "cmd_dbd.h"
 #include "dbd.h"
 #include "dbif.h"
 #include "db_param.h"
 
-#define LOCKFILENAME  "lock"
 #define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
 
 int nocniddb = 0;               /* Dont open CNID database, only scan filesystem */
-volatile sig_atomic_t alarmed;
 struct volinfo volinfo; /* needed by pack.c:idxname() */
+volatile sig_atomic_t alarmed;  /* flags for signals */
+int db_locked;                  /* have we got the fcntl lock on lockfile ? */
 
 static DBD *dbd;
 static int verbose;             /* Logging flag */
@@ -91,14 +93,14 @@ static struct db_param db_param = {
     NULL,                       /* Volume dirpath */
     1,                          /* bdb logfile autoremove */
     64 * 1024,                  /* bdb cachesize (64 MB) */
-    5000,                       /* maxlocks */
-    5000,                       /* maxlockobjs */
-    -1,                         /* not used ... */
-    -1,
-    "",
-    -1,
-    -1,
-    -1
+    DEFAULT_MAXLOCKS,           /* maxlocks */
+    DEFAULT_MAXLOCKOBJS,        /* maxlockobjs */
+    0,                          /* flush_interval */
+    0,                          /* flush_frequency */
+    0,                          /* usock_file */
+    -1,                         /* fd_table_size */
+    -1,                         /* idle_timeout */
+    -1                          /* max_vols */
 };
 static char dbpath[MAXPATHLEN+1];   /* Path to the dbd database */
 
@@ -166,71 +168,9 @@ static void set_signal(void)
     }        
 }
 
-static int get_lock(const char *dbpath)
-{
-    int lockfd;
-    char lockpath[PATH_MAX];
-    struct flock lock;
-    struct stat st;
-
-    if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
-        dbd_log( LOGSTD, ".AppleDB pathname too long");
-        exit(EXIT_FAILURE);
-    }
-    strncpy(lockpath, dbpath, PATH_MAX - 1);
-    strcat(lockpath, "/");
-    strcat(lockpath, LOCKFILENAME);
-
-    if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
-        dbd_log( LOGSTD, "Error opening lockfile: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    if ((stat(dbpath, &st)) != 0) {
-        dbd_log( LOGSTD, "Error statting lockfile: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
-        dbd_log( LOGSTD, "Error inheriting lockfile permissions: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-    
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type   = F_WRLCK;
-
-    if (fcntl(lockfd, F_SETLK, &lock) < 0) {
-        if (errno == EACCES || errno == EAGAIN) {
-            if (exclusive) {
-                dbd_log( LOGSTD, "Database is in use and exlusive was requested", strerror(errno));        
-                exit(EXIT_FAILURE);
-            };
-        } else {
-            dbd_log( LOGSTD, "Error getting fcntl F_WRLCK on lockfile: %s", strerror(errno));
-            exit(EXIT_FAILURE);
-       }
-    }
-    
-    return lockfd;
-}
-
-static void free_lock(int lockfd)
-{
-    struct flock lock;
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type = F_UNLCK;
-    fcntl(lockfd, F_SETLK, &lock);
-    close(lockfd);
-}
-
 static void usage (void)
 {
-    printf("Usage: dbd [-e|-v|-x] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u <path to netatalk volume>\n"
+    printf("Usage: dbd [-e|-t|-v|-x] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u <path to netatalk volume>\n"
            "dbd can dump, scan, reindex and rebuild Netatalk dbd CNID databases.\n"
            "dbd must be run with appropiate permissions i.e. as root.\n\n"
            "Main commands are:\n"
@@ -267,6 +207,7 @@ static void usage (void)
            "General options:\n"
            "   -e only work on inactive volumes and lock them (exclusive)\n"
            "   -x rebuild indexes (just for completeness, mostly useless!)\n"
+           "   -t show statistics while running\n"
            "   -v verbose\n\n"
            "WARNING:\n"
            "For -r -f restore of the CNID database from the adouble files, the CNID must of course\n"
@@ -289,7 +230,7 @@ int main(int argc, char **argv)
     /* Inhereting perms in ad_mkdir etc requires this */
     ad_setfuid(0);
 
-    while ((c = getopt(argc, argv, ":cdefinrsuvx")) != -1) {
+    while ((c = getopt(argc, argv, ":cdefinrstuvx")) != -1) {
         switch(c) {
         case 'c':
             flags |= DBD_FLAGS_CLEANUP;
@@ -310,6 +251,9 @@ int main(int argc, char **argv)
         case 'r':
             rebuild = 1;
             break;
+        case 't':
+            flags |= DBD_FLAGS_STATS;
+            break;
         case 'u':
             prep_upgrade = 1;
             break;
@@ -417,11 +361,18 @@ int main(int argc, char **argv)
         close(dbdirfd);
     }
 
-    /* 
-       Before we do anything else, check if there is an instance of cnid_dbd
-       running already and silently exit if yes.
-    */
-    lockfd = get_lock(dbpath);
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
+        goto exit_failure;
+    if (db_locked != LOCK_EXCL) {
+        /* Couldn't get exclusive lock, try shared lock if -e wasn't requested */
+        if (exclusive) {
+            dbd_log(LOGSTD, "Database is in use and exlusive was requested");
+            goto exit_failure;
+        }
+        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD)
+            goto exit_failure;
+    }
 
     /* Prepare upgrade ? */
     if (prep_upgrade) {
@@ -433,6 +384,9 @@ int main(int argc, char **argv)
     /* Check if -f is requested and wipe db if yes */
     if ((flags & DBD_FLAGS_FORCE) && rebuild && (volinfo.v_flags & AFPVOL_CACHE)) {
         char cmd[8 + MAXPATHLEN];
+        if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
+            goto exit_failure;
+
         snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
         dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
         system(cmd);
@@ -441,6 +395,8 @@ int main(int argc, char **argv)
             exit(EXIT_FAILURE);
         }
         dbd_log( LOGDEBUG, "Removed old database.");
+        if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
+            goto exit_failure;
     }
 
     /* 
@@ -450,12 +406,14 @@ int main(int argc, char **argv)
         if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
             goto exit_failure;
         
-        if (dbif_env_open(dbd, &db_param, exclusive ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
+        if (dbif_env_open(dbd,
+                          &db_param,
+                          (db_locked == LOCK_EXCL) ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
             dbd_log( LOGSTD, "error opening database!");
             goto exit_failure;
         }
 
-        if (exclusive)
+        if (db_locked == LOCK_EXCL)
             dbd_log( LOGDEBUG, "Finished recovery.");
 
         if (dbif_open(dbd, NULL, rebuildindexes) < 0) {
@@ -464,6 +422,14 @@ int main(int argc, char **argv)
         }
     }
 
+    /* Downgrade db lock if not running exclusive */
+    if (!exclusive && (db_locked == LOCK_EXCL)) {
+        if (get_lock(LOCK_UNLOCK, NULL) != 0)
+            goto exit_failure;
+        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
+            goto exit_failure;
+    }
+
     /* Now execute given command scan|rebuild|dump */
     if (dump && ! nocniddb) {
         if (dbif_dump(dbd, dumpindexes) < 0) {
@@ -476,16 +442,19 @@ int main(int argc, char **argv)
     }
 
     /* Cleanup */
-    if (! nocniddb && dbif_close(dbd) < 0) {
-        dbd_log( LOGSTD, "Error closing database");
-        goto exit_failure;
+    dbd_log(LOGDEBUG, "Closing db");
+    if (! nocniddb) {
+        if (dbif_close(dbd) < 0) {
+            dbd_log( LOGSTD, "Error closing database");
+            goto exit_failure;
+        }
     }
 
 exit_success:
     ret = 0;
 
 exit_failure:
-    free_lock(lockfd);
+    get_lock(0, NULL);
     
     if ((fchdir(cdir)) < 0)
         dbd_log(LOGSTD, "fchdir: %s", strerror(errno));
index ac6cde42112a9202214c869def22433fec056c0b..ef7829881b28a851cc335998b6db8dfacdac7da6 100644 (file)
@@ -14,6 +14,7 @@ typedef unsigned int dbd_flags_t;
 #define DBD_FLAGS_FORCE    (1 << 1)
 #define DBD_FLAGS_EXCL     (1 << 2)
 #define DBD_FLAGS_CLEANUP  (1 << 3) /* Dont create AD stuff, but cleanup orphaned */
+#define DBD_FLAGS_STATS    (1 << 4)
 
 #define ADv2_DIRNAME ".AppleDouble"
 
@@ -24,6 +25,7 @@ typedef unsigned int dbd_flags_t;
         (strcmp(a,c) b 0)
 
 extern int nocniddb; /* Dont open CNID database, only scan filesystem */
+extern int db_locked; /* have we got the fcntl lock on lockfd ? */
 extern volatile sig_atomic_t alarmed;
 
 extern void dbd_log(enum logtype lt, char *fmt, ...);
index f4122d84ccf71af47d23531bfc4204e69191ec97..8fb09624bd1850564f6eb3384efbad6d79c6e65c 100644 (file)
@@ -666,6 +666,8 @@ static int read_addir(void)
 /*
   Check CNID for a file/dir, both from db and from ad-file.
   For detailed specs see intro.
+
+  @return Correct CNID of object or CNID_INVALID (ie 0) on error
 */
 static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok, int adflags)
 {
@@ -673,6 +675,17 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
     cnid_t db_cnid, ad_cnid;
     struct adouble ad;
 
+    /* Force checkout every X items */
+    static int cnidcount = 0;
+    cnidcount++;
+    if (cnidcount > 10000) {
+        cnidcount = 0;
+        if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
+            dbd_log(LOGSTD, "Error checkpointing!");
+            return CNID_INVALID;
+        }
+    }
+
     /* Get CNID from ad-file if volume is using AFPVOL_CACHE */
     ad_cnid = 0;
     if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
@@ -680,10 +693,10 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
         if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
             
             if (dbd_flags & DBD_FLAGS_CLEANUP)
-                return 0;
+                return CNID_INVALID;
 
             dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
-            return 0;
+            return CNID_INVALID;
         }
 
         if (dbd_flags & DBD_FLAGS_FORCE) {
@@ -719,7 +732,8 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
 
     /* Query the database */
     ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
-    dbif_txn_close(dbd, ret);
+    if (dbif_txn_close(dbd, ret) != 0)
+        return CNID_INVALID;
     if (rply.result == CNID_DBD_RES_OK) {
         db_cnid = rply.cnid;
     } else if (rply.result == CNID_DBD_RES_NOTFOUND) {
@@ -741,14 +755,17 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
         if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
             rqst.cnid = db_cnid;
             ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-            dbif_txn_close(dbd, ret);
+            if (dbif_txn_close(dbd, ret) != 0)
+                return CNID_INVALID;
 
             rqst.cnid = ad_cnid;
             ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-            dbif_txn_close(dbd, ret);
+            if (dbif_txn_close(dbd, ret) != 0)
+                return CNID_INVALID;
 
             ret = dbd_rebuild_add(dbd, &rqst, &rply);
-            dbif_txn_close(dbd, ret);
+            if (dbif_txn_close(dbd, ret) != 0)
+                return CNID_INVALID;
         }
         return ad_cnid;
     } else if (ad_cnid && (db_cnid == 0)) {
@@ -763,7 +780,8 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
             if (ret == CNID_DBD_RES_OK) {
                 /* Occupied! Choose another, update ad-file */
                 ret = dbd_add(dbd, &rqst, &rply, 1);
-                dbif_txn_close(dbd, ret);
+                if (dbif_txn_close(dbd, ret) != 0)
+                    return CNID_INVALID;
                 db_cnid = rply.cnid;
                 dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
 
@@ -776,7 +794,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
                     if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
                         dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
                                 cwdbuf, name, strerror(errno));
-                        return 0;
+                        return CNID_INVALID;
                     }
                     ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
                     ad_flush(&ad);
@@ -789,7 +807,8 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
                     cwdbuf, name, ntohl(ad_cnid));
             rqst.cnid = ad_cnid;
             ret = dbd_rebuild_add(dbd, &rqst, &rply);
-            dbif_txn_close(dbd, ret);
+            if (dbif_txn_close(dbd, ret) != 0)
+                return CNID_INVALID;
         }
         return ad_cnid;
     } else if ((db_cnid == 0) && (ad_cnid == 0)) {
@@ -798,7 +817,8 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
         if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
             /* add to db */
             ret = dbd_add(dbd, &rqst, &rply, 1);
-            dbif_txn_close(dbd, ret);
+            if (dbif_txn_close(dbd, ret) != 0)
+                return CNID_INVALID;
             db_cnid = rply.cnid;
             dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
         }
@@ -814,7 +834,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
                 if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
                     dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
                             cwdbuf, name, strerror(errno));
-                    return 0;
+                    return CNID_INVALID;
                 }
                 ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
                 ad_flush(&ad);
@@ -824,7 +844,7 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
         return db_cnid;
     }
 
-    return 0;
+    return CNID_INVALID;
 }
 
 /*
@@ -921,6 +941,22 @@ static int dbd_readdir(int volroot, cnid_t did)
             continue;
         }
 
+        /**************************************************************************
+           Statistics
+         **************************************************************************/
+        static unsigned long long statcount = 0;
+        static time_t t = 0;
+
+        if (t == 0)
+            t = time(NULL);
+
+        statcount++;
+        if ((statcount % 10000) == 0) {
+            if (dbd_flags & DBD_FLAGS_STATS)            
+                dbd_log(LOGSTD, "Scanned: %10llu, time: %10llu s",
+                        statcount, (unsigned long long)(time(NULL) - t));
+        }
+
         /**************************************************************************
            Tests
         **************************************************************************/
@@ -942,13 +978,24 @@ static int dbd_readdir(int volroot, cnid_t did)
             cnid = check_cnid(ep->d_name, did, &st, adfile_ok, adflags);
 
             /* Now add this object to our rebuild dbd */
-            if (cnid) {
+            if (cnid && dbd_rebuild) {
+                static uint count = 0;
                 rqst.cnid = rply.cnid;
-                dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
+                ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
+                if (dbif_txn_close(dbd_rebuild, ret) != 0)
+                    return -1;
                 if (rply.result != CNID_DBD_RES_OK) {
-                    dbd_log( LOGDEBUG, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
+                    dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
                              cnid, cwdbuf, ep->d_name);
-                    longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+                    return -1;
+                }
+                count++;
+                if (count == 10000) {
+                    if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
+                        dbd_log(LOGSTD, "Error checkpointing!");
+                        return -1;
+                    }
+                    count = 0;
                 }
             }
         }
@@ -980,7 +1027,7 @@ static int dbd_readdir(int volroot, cnid_t did)
             close(cwd);
             *(strrchr(cwdbuf, '/')) = 0;
             if (ret < 0)
-                continue;
+                return -1;
         }
     }
 
@@ -1030,7 +1077,7 @@ static int scanvol(struct volinfo *vi, dbd_flags_t flags)
 */
 static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
 {
-    int ret, deleted = 0;
+    int ret = 0, deleted = 0;
     cnid_t dbd_cnid = 0, rebuild_cnid = 0;
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
@@ -1051,7 +1098,7 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
         if (alarmed)
             longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
 
-        if (deleted > 50) {
+        if (deleted > 1000) {
             deleted = 0;
             if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
                 dbd_log(LOGSTD, "Error checkpointing!");
@@ -1077,7 +1124,8 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
                             goto cleanup;
                         }
                         
-                        dbif_txn_close(dbd, ret);
+                        if (dbif_txn_close(dbd, ret) != 0)
+                            return;
                         deleted++;
                     }
                     /* Check if we got a termination signal */
@@ -1100,19 +1148,21 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
                     (void)dbif_txn_abort(dbd);
                     goto cleanup;
                 }
-                dbif_txn_close(dbd, ret);
+                if (dbif_txn_close(dbd, ret) != 0)
+                    return;
                 deleted++;
             }
             continue;
         }
 
         if (dbd_cnid > rebuild_cnid) {
+            dbif_idwalk(dbd, NULL, 1); /* Close cursor */
+            dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
+            (void)dbif_txn_close(dbd, 2);
+            (void)dbif_txn_close(dbd_rebuild, 2);                
             dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
             dbif_dump(dbd_rebuild, 0);
             dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
-            dbif_txn_close(dbd, ret);
-            dbif_idwalk(dbd, NULL, 1); /* Close cursor */
-            dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
             goto cleanup;
         }
     } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
@@ -1123,6 +1173,16 @@ cleanup:
     return;
 }
 
+static const char *get_tmpdb_path(void)
+{
+    pid_t pid = getpid();
+    static char path[MAXPATHLEN];
+    snprintf(path, MAXPATHLEN, "/tmp/tmpdb-dbd.%u", pid);
+    if (mkdir(path, 0755) != 0)
+        return NULL;
+    return path;
+}
+
 /*
   Main func called from cmd_dbd.c
 */
@@ -1130,9 +1190,13 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *vi, dbd_flags_t flags)
 {
     int ret = 0;
     struct db_param db_param = { 0 };
+    const char *tmpdb_path = NULL;
 
     /* Set cachesize for in-memory rebuild db */
-    db_param.cachesize = 128 * 1024 * 1024; /* 128 MB */
+    db_param.cachesize = 64 * 1024;         /* 64 MB */
+    db_param.maxlocks = DEFAULT_MAXLOCKS;
+    db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
+    db_param.logfile_autoremove = 1;
 
     /* Make it accessible for all funcs */
     dbd = dbd_ref;
@@ -1143,38 +1207,76 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *vi, dbd_flags_t flags)
         return -1;
     }
 
-    if (! nocniddb) {
-        /* Get volume stamp */
-        dbd_getstamp(dbd, &rqst, &rply);
-        if (rply.result != CNID_DBD_RES_OK)
-            goto exit_cleanup;
-        memcpy(stamp, rply.name, CNID_DEV_LEN);
-
-        /* open/create rebuild dbd, copy rootinfo key */
-        if (NULL == (dbd_rebuild = dbif_init(NULL, NULL)))
-            return -1;
-        if (0 != (dbif_open(dbd_rebuild, &db_param, 0)))
-            return -1;
-        if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild)))
-            goto exit_cleanup;
+    /* Get volume stamp */
+    dbd_getstamp(dbd, &rqst, &rply);
+    if (rply.result != CNID_DBD_RES_OK) {
+        ret = -1;
+        goto exit;
     }
+    memcpy(stamp, rply.name, CNID_DEV_LEN);
+
+    /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
+    if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) {
+        tmpdb_path = get_tmpdb_path();
+        if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) {
+            ret = -1;
+            goto exit;
+        }
 
-    if (setjmp(jmp) != 0)
-        goto exit_cleanup;      /* Got signal, jump from dbd_readdir */
+        if (dbif_env_open(dbd_rebuild,
+                          &db_param,
+                          DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN) < 0) {
+            dbd_log(LOGSTD, "error opening tmp database!");
+            goto exit;
+        }
+
+        if (0 != (dbif_open(dbd_rebuild, NULL, 0))) {
+            ret = -1;
+            goto exit;
+        }
+
+        if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) {
+            ret = -1;
+            goto exit;
+        }
+    }
+
+    if (setjmp(jmp) != 0) {
+        ret = 0;                /* Got signal, jump from dbd_readdir */
+        goto exit;
+    }
 
     /* scanvol */
-    if ( (scanvol(vi, flags)) != 0)
-        return -1;
+    if ( (scanvol(vi, flags)) != 0) {
+        ret = -1;
+        goto exit;
+    }
 
+exit:
     if (! nocniddb) {
-        /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
-           other clients in between our pass 1 and 2 */
-        if (flags & DBD_FLAGS_EXCL)
+        if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0)
+            ret = -1;
+        if (dbd_rebuild)
+            if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0)
+                ret = -1;
+        if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
+            /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
+               other clients in between our pass 1 and 2 */
             delete_orphaned_cnids(dbd, dbd_rebuild, flags);
     }
 
-exit_cleanup:
-    if (! nocniddb)
+    if (dbd_rebuild) {
+        dbd_log(LOGDEBUG, "Closing tmp db");
         dbif_close(dbd_rebuild);
+
+        if (tmpdb_path) {
+            char cmd[8 + MAXPATHLEN];
+            snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path);
+            dbd_log( LOGDEBUG, "Removing temp database '%s'", tmpdb_path);
+            system(cmd);
+            snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path);
+            system(cmd);
+        }        
+    }
     return ret;
 }
index 2f3b9150a1b7fd1278bc1746e7e1c4d9f86e5f7a..11987cc779b9225c01059cbbea1ad42fff44060e 100644 (file)
@@ -580,7 +580,8 @@ int main(int argc, char *argv[])
 
         /* Load .volinfo file */
         if ((volinfo = allocvolinfo(volpath)) == NULL) {
-            LOG(log_severe, logtype_cnid, "allocvolinfo: %s", strerror(errno));
+            LOG(log_severe, logtype_cnid, "allocvolinfo(\"%s\"): %s",
+                volpath, strerror(errno));
             goto loop_end;
         }
 
index 65ed8604ee827f73293f3815fa6ccf7314c8a7b9..64038714961320c2adc775d46cdf016d20939e4a 100644 (file)
@@ -9,6 +9,16 @@
 #include "config.h"
 #endif
 
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef __EXTENSIONS__
+# define __EXTENSIONS__
+#endif
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -18,7 +28,6 @@
 #include <sys/types.h>
 #include <sys/time.h>
 #include <sys/uio.h>
-#define _XPG4_2 1
 #include <sys/socket.h>
 #include <sys/select.h>
 #include <assert.h>
index e31e782759830629536f25a8d95dcffc7517b57c..c89f8e5cec00890c2d9b4a3e8410241cc7b684a7 100644 (file)
 #define DB_PARAM_FN       "db_param"
 #define MAXKEYLEN         64
 
-#define DEFAULT_LOGFILE_AUTOREMOVE 1
-#define DEFAULT_CACHESIZE          (8 * 1024) /* KB, so 8 MB */
-#define DEFAULT_MAXLOCKS           5000
-#define DEFAULT_MAXLOCKOBJS        5000
-#define DEFAULT_FLUSH_FREQUENCY    1000
-#define DEFAULT_FLUSH_INTERVAL     1800
-#define DEFAULT_USOCK_FILE         "usock"
-#define DEFAULT_FD_TABLE_SIZE      512
-#define DEFAULT_IDLE_TIMEOUT       (10 * 60)
-
 static struct db_param params;
 static int parse_err;
 
index d8f3c9103d278c2bbf03f5626f7788138d393e3a..fce1cb5a9ddc89883745a30d1a386ed4be3cca81 100644 (file)
@@ -9,6 +9,16 @@
 
 #include <sys/param.h>
 
+#define DEFAULT_LOGFILE_AUTOREMOVE 1
+#define DEFAULT_CACHESIZE          (8 * 1024) /* KB, so 8 MB */
+#define DEFAULT_MAXLOCKS           5000
+#define DEFAULT_MAXLOCKOBJS        5000
+#define DEFAULT_FLUSH_FREQUENCY    1000
+#define DEFAULT_FLUSH_INTERVAL     1800
+#define DEFAULT_USOCK_FILE         "usock"
+#define DEFAULT_FD_TABLE_SIZE      512
+#define DEFAULT_IDLE_TIMEOUT       (10 * 60)
+
 struct db_param {
     char *dir;
     int logfile_autoremove;
index 87ff2e9a2f006b2a9344eadd24e37c4b3b7c7b30..91d9bec00ff18d0ba16a1c52dfe5c64ba3a7ab66 100644 (file)
@@ -321,6 +321,91 @@ exit:
     return ret;
 }
 
+/*!
+ * Get lock on db lock file
+ *
+ * @args cmd       (r) lock command:
+ *                     LOCK_FREE:   close lockfd
+ *                     LOCK_UNLOCK: unlock lockm keep lockfd open
+ *                     LOCK_EXCL:   F_WRLCK on lockfd
+ *                     LOCK_SHRD:   F_RDLCK on lockfd
+ * @args dbpath    (r) path to lockfile, only used on first call,
+ *                     later the stored fd is used
+ * @returns            LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
+ *                     LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
+ *                     success, 0 if the lock couldn't be acquired, -1 on other errors
+ */
+int get_lock(int cmd, const char *dbpath)
+{
+    static int lockfd = -1;
+    int ret;
+    char lockpath[PATH_MAX];
+    struct stat st;
+
+    switch (cmd) {
+    case LOCK_FREE:
+        if (lockfd == -1)
+            return -1;
+        close(lockfd);
+        lockfd = -1;
+        return 0;
+
+    case LOCK_UNLOCK:
+        if (lockfd == -1)
+            return -1;
+        return unlock(lockfd, 0, SEEK_SET, 0);
+
+    case LOCK_EXCL:
+    case LOCK_SHRD:
+        if (lockfd == -1) {
+            if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
+                LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
+                return -1;
+            }
+            strncpy(lockpath, dbpath, PATH_MAX - 1);
+            strcat(lockpath, "/");
+            strcat(lockpath, LOCKFILENAME);
+
+            if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
+                LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((stat(dbpath, &st)) != 0) {
+                LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
+                LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
+                         strerror(errno));
+                return -1;
+            }
+        }
+    
+        if (cmd == LOCK_EXCL)
+            ret = write_lock(lockfd, 0, SEEK_SET, 0);
+        else
+            ret = read_lock(lockfd, 0, SEEK_SET, 0);
+
+        if (ret != 0) {
+            if (cmd == LOCK_SHRD)
+                LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
+            return 0; 
+        }
+
+        LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
+            cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");    
+        return cmd;
+
+    default:
+        return -1;
+    } /* switch(cmd) */
+
+    /* deadc0de, never get here */
+    return -1;
+}
+
 /* --------------- */
 DBD *dbif_init(const char *envhome, const char *filename)
 {
@@ -386,6 +471,8 @@ int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags)
         return -1;
     }
 
+    dbd->db_param = *dbp;
+
     if ((dbif_openlog(dbd)) != 0)
         return -1;
 
@@ -1005,25 +1092,30 @@ int dbif_txn_abort(DBD *dbd)
 }
 
 /* 
-   ret = 1 -> commit txn
-   ret = 0 -> abort txn -> exit!
+   ret = 1 -> commit txn if db_param.txn_frequency
+   ret = 0 -> abort txn db_param.txn_frequency -> exit!
    anything else -> exit!
+
+   @returns 0 on success (abort or commit), -1 on error
 */
-void dbif_txn_close(DBD *dbd, int ret)
+int dbif_txn_close(DBD *dbd, int ret)
 {
     if (ret == 0) {
         if (dbif_txn_abort(dbd) < 0) {
             LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!");
-            exit(EXIT_FAILURE);
+            return -1;
         }
     } else if (ret == 1) {
         ret = dbif_txn_commit(dbd);
         if (  ret < 0) {
             LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!");
-            exit(EXIT_FAILURE);
+            return -1;
         }
-    } else
-       exit(EXIT_FAILURE);
+    } else {
+        return -1;
+    }
+
+    return 0;
 }
 
 int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags)
index 2be8c0b1a5ac9469b2b8b3031c38eeaedb8c2d00..8c71de36b96221f598f64f4943b0878e7906f444 100644 (file)
 #define DBIF_IDX_DIDNAME   2
 #define DBIF_IDX_NAME      3
 
+/* get_lock cmd and return value */
+#define LOCKFILENAME  "lock"
+#define LOCK_FREE          0
+#define LOCK_UNLOCK        1
+#define LOCK_EXCL          2
+#define LOCK_SHRD          3
+
 /* Structures */
 typedef struct {
     char     *name;
@@ -75,6 +82,7 @@ typedef struct {
 
 typedef struct {
     DB_ENV   *db_env;
+    struct db_param db_param;
     DB_TXN   *db_txn;
     DBC      *db_cur;              /* for dbif_walk */
     char     *db_envhome;
@@ -84,6 +92,8 @@ typedef struct {
 } DBD;
 
 /* Functions */
+extern int get_lock(int cmd, const char *dbpath);
+
 extern DBD *dbif_init(const char *envhome, const char *dbname);
 extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
 extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
@@ -100,7 +110,7 @@ extern int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd);
 extern int dbif_txn_begin(DBD *);
 extern int dbif_txn_commit(DBD *);
 extern int dbif_txn_abort(DBD *);
-extern void dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */
+extern int dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */
 extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t);
 
 extern int dbif_dump(DBD *dbd, int dumpindexes);
index 1c951cb9c6d182c5d238b5de7bf99eb99ae6dbd6..4f5fd725b09fc4bbba95b5dca23d202a9af216d9 100644 (file)
 #include "dbd.h"
 #include "comm.h"
 
-#define LOCKFILENAME  "lock"
-
 /* 
    Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running.
    It's a likey performance hit, but it might we worth it.
  */
-#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER)
+#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN)
 
 /* Global, needed by pack.c:idxname() */
 struct volinfo volinfo;
 
 static DBD *dbd;
 static int exit_sig = 0;
+static int db_locked;
 
 static void sig_exit(int signo)
 {
@@ -248,34 +247,6 @@ static void switch_to_user(char *dir)
     }
 }
 
-/* ------------------------ */
-static int get_lock(void)
-{
-    int lockfd;
-    struct flock lock;
-
-    if ((lockfd = open(LOCKFILENAME, O_RDWR | O_CREAT, 0644)) < 0) {
-        LOG(log_error, logtype_cnid, "main: error opening lockfile: %s", strerror(errno));
-        exit(1);
-    }
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type   = F_WRLCK;
-
-    if (fcntl(lockfd, F_SETLK, &lock) < 0) {
-        if (errno == EACCES || errno == EAGAIN) {
-            LOG(log_error, logtype_cnid, "get_lock: locked");
-            exit(0);
-        } else {
-            LOG(log_error, logtype_cnid, "main: fcntl F_WRLCK lockfile: %s", strerror(errno));
-            exit(1);
-        }
-    }
-
-    return lockfd;
-}
 
 /* ----------------------- */
 static void set_signal(void)
@@ -299,25 +270,12 @@ static void set_signal(void)
     }
 }
 
-/* ----------------------- */
-static void free_lock(int lockfd)
-{
-    struct flock lock;
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type = F_UNLCK;
-    fcntl(lockfd, F_SETLK, &lock);
-    close(lockfd);
-}
-
 /* ------------------------ */
 int main(int argc, char *argv[])
 {
     struct db_param *dbp;
     int err = 0;
-    int lockfd, ctrlfd, clntfd;
+    int ctrlfd, clntfd;
     char *logconfig;
 
     set_processname("cnid_dbd");
@@ -355,9 +313,18 @@ int main(int argc, char *argv[])
 
     switch_to_user(dbpath);
 
-    /* Before we do anything else, check if there is an instance of cnid_dbd
-       running already and silently exit if yes. */
-    lockfd = get_lock();
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1) {
+        LOG(log_error, logtype_cnid, "main: fatal db lock error");
+        exit(1);
+    }
+    if (db_locked != LOCK_EXCL) {
+        /* Couldn't get exclusive lock, try shared lock  */
+        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) {
+            LOG(log_error, logtype_cnid, "main: fatal db lock error");
+            exit(1);
+        }
+    }
 
     set_signal();
 
@@ -371,7 +338,10 @@ int main(int argc, char *argv[])
     if (NULL == (dbd = dbif_init(dbpath, "cnid2.db")))
         exit(2);
 
-    if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0)
+    /* Only recover if we got the lock */
+    if (dbif_env_open(dbd,
+                      dbp,
+                      (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0)
         exit(2); /* FIXME: same exit code as failure for dbif_open() */
     LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
 
@@ -381,6 +351,19 @@ int main(int argc, char *argv[])
     }
     LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
 
+    /* Downgrade db lock  */
+    if (db_locked == LOCK_EXCL) {
+        if (get_lock(LOCK_UNLOCK, NULL) != 0) {
+            dbif_close(dbd);
+            exit(2);
+        }
+        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) {
+            dbif_close(dbd);
+            exit(2);
+        }
+    }
+
+
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
         dbif_close(dbd);
         exit(3);
@@ -395,8 +378,6 @@ int main(int argc, char *argv[])
     if (dbif_env_remove(dbpath) < 0)
         err++;
 
-    free_lock(lockfd);
-
     if (err)
         exit(4);
     else if (exit_sig)
index fde2df74549344320ed84db0b5288cb6bd49ef5a..46c0d9700b7248fae5a424dd52d9109135dfdd29 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: uams_dhx2_pam.c,v 1.12 2010-03-30 10:25:49 franklahm Exp $
- *
  * Copyright (c) 1990,1993 Regents of The University of Michigan.
  * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
  * All Rights Reserved.  See COPYRIGHT.
 #define PRIMEBITS 1024
 
 /* hash a number to a 16-bit quantity */
-#define dhxhash(a) ((((unsigned long) (a) >> 8) ^ \
+#define dhxhash(a) ((((unsigned long) (a) >> 8) ^   \
                      (unsigned long) (a)) & 0xffff)
 
 /* Some parameters need be maintained across calls */
-static gcry_mpi_t p, Ra;
+static gcry_mpi_t p, g, Ra;
 static gcry_mpi_t serverNonce;
 static char *K_MD5hash = NULL;
 static int K_hash_len;
@@ -64,7 +62,7 @@ static struct passwd *dhxpwd;
 /*********************************************************
  * Crypto helper func to generate p and g for use in DH.
  * libgcrypt doesn't provide one directly.
- * Algorithm taken from GNUTLS:gnutls_dh_primes.c 
+ * Algorithm taken from GNUTLS:gnutls_dh_primes.c
  *********************************************************/
 
 /**
@@ -72,13 +70,9 @@ static struct passwd *dhxpwd;
  * the Diffie-Hellman key exchange.
  * The bits value should be one of 768, 1024, 2048, 3072 or 4096.
  **/
-
-static int
-dh_params_generate (gcry_mpi_t *ret_p, gcry_mpi_t *ret_g, unsigned int bits) {
+static int dh_params_generate (unsigned int bits) {
 
     int result, times = 0, qbits;
-
-    gcry_mpi_t g = NULL, prime = NULL;
     gcry_mpi_t *factors = NULL;
     gcry_error_t err;
 
@@ -91,59 +85,47 @@ dh_params_generate (gcry_mpi_t *ret_p, gcry_mpi_t *ret_g, unsigned int bits) {
     }
 
     if (bits < 256)
-       qbits = bits / 2;
+        qbits = bits / 2;
     else
-       qbits = (bits / 40) + 105;
+        qbits = (bits / 40) + 105;
 
     if (qbits & 1) /* better have an even number */
-       qbits++;
+        qbits++;
 
     /* find a prime number of size bits. */
     do {
-       if (times) {
-           gcry_mpi_release (prime);
-           gcry_prime_release_factors (factors);
-       }
-       err = gcry_prime_generate (&prime, bits, qbits, &factors, NULL, NULL,
-                                  GCRY_STRONG_RANDOM, GCRY_PRIME_FLAG_SPECIAL_FACTOR);
-       if (err != 0) {
-           result = AFPERR_MISC;
-           goto error;
-       }
-       err = gcry_prime_check (prime, 0);
-       times++;
+        if (times) {
+            gcry_mpi_release(p);
+            gcry_prime_release_factors (factors);
+        }
+        err = gcry_prime_generate(&p, bits, qbits, &factors, NULL, NULL,
+                                  GCRY_STRONG_RANDOM, GCRY_PRIME_FLAG_SPECIAL_FACTOR);
+        if (err != 0) {
+            result = AFPERR_MISC;
+            goto error;
+        }
+        err = gcry_prime_check(p, 0);
+        times++;
     } while (err != 0 && times < 10);
-    
+
     if (err != 0) {
-       result = AFPERR_MISC;
-       goto error;
+        result = AFPERR_MISC;
+        goto error;
     }
 
     /* generate the group generator. */
-    err = gcry_prime_group_generator (&g, prime, factors, NULL);
+    err = gcry_prime_group_generator(&g, p, factors, NULL);
     if (err != 0) {
-       result = AFPERR_MISC;
-       goto error;
-    }
-    
-    gcry_prime_release_factors (factors);
-    factors = NULL;
-    
-    if (ret_g)
-       *ret_g = g;
-    else
-       gcry_mpi_release (g);
-    if (ret_p)
-       *ret_p = prime;
-    else
-       gcry_mpi_release (prime);
-    
+        result = AFPERR_MISC;
+        goto error;
+    }
+
+    gcry_prime_release_factors(factors);
+
     return 0;
 
 error:
-    gcry_prime_release_factors (factors);
-    gcry_mpi_release (g);
-    gcry_mpi_release (prime);
+    gcry_prime_release_factors(factors);
 
     return result;
 }
@@ -254,33 +236,23 @@ static struct pam_conv PAM_conversation = {
 
 
 static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
-                     char *rbuf, size_t *rbuflen)
+                      char *rbuf, size_t *rbuflen)
 {
     int ret;
     size_t nwritten;
-    gcry_mpi_t g, Ma;
+    gcry_mpi_t Ma;
     char *Ra_binary = NULL;
 
     *rbuflen = 0;
 
-    p = gcry_mpi_new(0);
-    g = gcry_mpi_new(0);
     Ra = gcry_mpi_new(0);
     Ma = gcry_mpi_new(0);
 
-    /* Generate p and g for DH */
-    ret = dh_params_generate( &p, &g, PRIMEBITS);
-    if (ret != 0) {
-       LOG(log_info, logtype_uams, "DHX2: Couldn't generate p and g");
-       ret = AFPERR_MISC;
-       goto error;
-    }
-
     /* Generate our random number Ra. */
     Ra_binary = calloc(1, PRIMEBITS/8);
     if (Ra_binary == NULL) {
-       ret = AFPERR_MISC;
-       goto error;
+        ret = AFPERR_MISC;
+        goto error;
     }
     gcry_randomize(Ra_binary, PRIMEBITS/8, GCRY_STRONG_RANDOM);
     gcry_mpi_scan(&Ra, GCRYMPI_FMT_USG, Ra_binary, PRIMEBITS/8, NULL);
@@ -302,8 +274,8 @@ static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
     /* g is next */
     gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, 4, &nwritten, g);
     if (nwritten < 4) {
-       memmove( rbuf+4-nwritten, rbuf, nwritten);
-       memset( rbuf, 0, 4-nwritten);
+        memmove( rbuf+4-nwritten, rbuf, nwritten);
+        memset( rbuf, 0, 4-nwritten);
     }
     rbuf += 4;
     *rbuflen += 4;
@@ -321,17 +293,16 @@ static int dhx2_setup(void *obj, char *ibuf _U_, size_t ibuflen _U_,
     /* Ma */
     gcry_mpi_print( GCRYMPI_FMT_USG, (unsigned char *)rbuf, PRIMEBITS/8, &nwritten, Ma);
     if (nwritten < PRIMEBITS/8) {
-       memmove(rbuf + (PRIMEBITS/8) - nwritten, rbuf, nwritten);
-       memset(rbuf, 0, (PRIMEBITS/8) - nwritten);
+        memmove(rbuf + (PRIMEBITS/8) - nwritten, rbuf, nwritten);
+        memset(rbuf, 0, (PRIMEBITS/8) - nwritten);
     }
     rbuf += PRIMEBITS/8;
     *rbuflen += PRIMEBITS/8;
 
     ret = AFPERR_AUTHCONT;
 
-error:                         /* We exit here anyway */
-    /* We will only need p and Ra later, but mustn't forget to release it ! */
-    gcry_mpi_release(g);
+error:              /* We exit here anyway */
+    /* We will need Ra later, but mustn't forget to release it ! */
     gcry_mpi_release(Ma);
     return ret;
 }
@@ -423,7 +394,6 @@ static int pam_login_ext(void *obj, char *uname, struct passwd **uam_pwd,
 }
 
 /* -------------------------------- */
-
 static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     int ret;
@@ -443,9 +413,9 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
 
     /* Packet size should be: Session ID + Ma + Encrypted client nonce */
     if (ibuflen != 2 + PRIMEBITS/8 + 16) {
-       LOG(log_error, logtype_uams, "DHX2: Paket length not correct");
+        LOG(log_error, logtype_uams, "DHX2: Paket length not correct");
         ret = AFPERR_PARAM;
-       goto error_noctx;
+        goto error_noctx;
     }
 
     /* Skip session id */
@@ -461,20 +431,20 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
     /* We need K in binary form in order to ... */
     K_bin = calloc(1, PRIMEBITS/8);
     if (K_bin == NULL) {
-       ret = AFPERR_MISC;
-       goto error_noctx;
+        ret = AFPERR_MISC;
+        goto error_noctx;
     }
     gcry_mpi_print(GCRYMPI_FMT_USG, K_bin, PRIMEBITS/8, &nwritten, K);
     if (nwritten < PRIMEBITS/8) {
-       memmove(K_bin + PRIMEBITS/8 - nwritten, K_bin, nwritten);
-       memset(K_bin, 0, PRIMEBITS/8 - nwritten);
+        memmove(K_bin + PRIMEBITS/8 - nwritten, K_bin, nwritten);
+        memset(K_bin, 0, PRIMEBITS/8 - nwritten);
     }
 
     /* ... generate the MD5 hash of K. K_MD5hash is what we actually use ! */
     K_MD5hash = calloc(1, K_hash_len = gcry_md_get_algo_dlen(GCRY_MD_MD5));
     if (K_MD5hash == NULL) {
-       ret = AFPERR_MISC;
-       goto error_noctx;
+        ret = AFPERR_MISC;
+        goto error_noctx;
     }
     gcry_md_hash_buffer(GCRY_MD_MD5, K_MD5hash, K_bin, PRIMEBITS/8);
     free(K_bin);
@@ -485,25 +455,25 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
     /* Set up our encryption context. */
     ctxerror = gcry_cipher_open( &ctx, GCRY_CIPHER_CAST5, GCRY_CIPHER_MODE_CBC, 0);
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
+        ret = AFPERR_MISC;
         goto error_ctx;
     }
     /* Set key */
     ctxerror = gcry_cipher_setkey(ctx, K_MD5hash, K_hash_len);
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
+        ret = AFPERR_MISC;
         goto error_ctx;
     }
     /* Set the initialization vector for client->server transfer. */
     ctxerror = gcry_cipher_setiv(ctx, dhx_c2siv, sizeof(dhx_c2siv));
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
+        ret = AFPERR_MISC;
         goto error_ctx;
     }
     /* Finally: decrypt client's md5_K(client nonce, C2SIV) inplace */
     ctxerror = gcry_cipher_decrypt(ctx, ibuf, 16, NULL, 0);
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
+        ret = AFPERR_MISC;
         goto error_ctx;
     }
     /* Pull out clients nonce */
@@ -530,14 +500,14 @@ static int logincont1(void *obj _U_, char *ibuf, size_t ibuflen, char *rbuf, siz
     /* Set the initialization vector for server->client transfer. */
     ctxerror = gcry_cipher_setiv(ctx, dhx_s2civ, sizeof(dhx_s2civ));
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
+        ret = AFPERR_MISC;
         goto error_ctx;
     }
     /* Encrypt md5_K(clientNonce+1, serverNonce) inplace */
     ctxerror = gcry_cipher_encrypt(ctx, rbuf, 32, NULL, 0);
     if (gcry_err_code(ctxerror) != GPG_ERR_NO_ERROR) {
-       ret = AFPERR_MISC;
-       goto error_ctx;
+        ret = AFPERR_MISC;
+        goto error_ctx;
     }
     rbuf += 32;
     *rbuflen += 32;
@@ -555,14 +525,13 @@ exit:
     gcry_mpi_release(K);
     gcry_mpi_release(Mb);
     gcry_mpi_release(Ra);
-    gcry_mpi_release(p);
     gcry_mpi_release(clientNonce);
     return ret;
 }
 
 static int logincont2(void *obj, struct passwd **uam_pwd,
-                     char *ibuf, size_t ibuflen,
-                     char *rbuf _U_, size_t *rbuflen)
+                      char *ibuf, size_t ibuflen,
+                      char *rbuf _U_, size_t *rbuflen)
 {
     int ret;
     int PAM_error;
@@ -617,7 +586,7 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
     gcry_mpi_scan(&retServerNonce, GCRYMPI_FMT_USG, ibuf, 16, NULL);
     gcry_mpi_sub_ui(retServerNonce, retServerNonce, 1);
     if ( gcry_mpi_cmp( serverNonce, retServerNonce) != 0) {
-       /* We're hacked!  */
+        /* We're hacked!  */
         ret = AFPERR_NOTAUTH;
         goto error_ctx;
     }
@@ -631,9 +600,9 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
     ret = AFPERR_NOTAUTH;
     PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &pamh);
     if (PAM_error != PAM_SUCCESS) {
-       LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-           pam_strerror(pamh,PAM_error));
-       goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
+            pam_strerror(pamh,PAM_error));
+        goto error_ctx;
     }
 
     /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
@@ -641,25 +610,25 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
     pam_set_item(pamh, PAM_RHOST, hostname);
     PAM_error = pam_authenticate(pamh, 0);
     if (PAM_error != PAM_SUCCESS) {
-       if (PAM_error == PAM_MAXTRIES)
-           ret = AFPERR_PWDEXPR;
-       LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-           pam_strerror(pamh, PAM_error));
-       goto error_ctx;
+        if (PAM_error == PAM_MAXTRIES)
+            ret = AFPERR_PWDEXPR;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
+            pam_strerror(pamh, PAM_error));
+        goto error_ctx;
     }
 
     PAM_error = pam_acct_mgmt(pamh, 0);
     if (PAM_error != PAM_SUCCESS ) {
-       LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-           pam_strerror(pamh, PAM_error));
-       if (PAM_error == PAM_NEW_AUTHTOK_REQD)    /* password expired */
-           ret = AFPERR_PWDEXPR;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
+            pam_strerror(pamh, PAM_error));
+        if (PAM_error == PAM_NEW_AUTHTOK_REQD)    /* password expired */
+            ret = AFPERR_PWDEXPR;
 #ifdef PAM_AUTHTOKEN_REQD
-       else if (PAM_error == PAM_AUTHTOKEN_REQD)
-           ret = AFPERR_PWDCHNG;
+        else if (PAM_error == PAM_AUTHTOKEN_REQD)
+            ret = AFPERR_PWDCHNG;
 #endif
-       else
-           goto error_ctx;
+        else
+            goto error_ctx;
     }
 
 #ifndef PAM_CRED_ESTABLISH
@@ -667,16 +636,16 @@ static int logincont2(void *obj, struct passwd **uam_pwd,
 #endif
     PAM_error = pam_setcred(pamh, PAM_CRED_ESTABLISH);
     if (PAM_error != PAM_SUCCESS) {
-       LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-           pam_strerror(pamh, PAM_error));
-       goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
+            pam_strerror(pamh, PAM_error));
+        goto error_ctx;
     }
 
     PAM_error = pam_open_session(pamh, 0);
     if (PAM_error != PAM_SUCCESS) {
-       LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-           pam_strerror(pamh, PAM_error));
-       goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
+            pam_strerror(pamh, PAM_error));
+        goto error_ctx;
     }
 
     memset(ibuf, 0, 256); /* zero out the password */
@@ -692,7 +661,7 @@ error_noctx:
     free(K_MD5hash);
     K_MD5hash=NULL;
     gcry_mpi_release(serverNonce);
-    gcry_mpi_release(retServerNonce);    
+    gcry_mpi_release(retServerNonce);
     return ret;
 }
 
@@ -728,7 +697,7 @@ static void pam_logout(void) {
  * --- Change pwd stuff --- */
 
 static int changepw_1(void *obj, char *uname,
-                     char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
+                      char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     *rbuflen = 0;
 
@@ -737,15 +706,15 @@ static int changepw_1(void *obj, char *uname,
     return( dhx2_setup(obj, ibuf, ibuflen, rbuf, rbuflen) );
 }
 
-static int changepw_2(void *obj, 
-                     char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
+static int changepw_2(void *obj,
+                      char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
 {
     return( logincont1(obj, ibuf, ibuflen, rbuf, rbuflen) );
 }
 
 static int changepw_3(void *obj _U_,
-                     char *ibuf, size_t ibuflen _U_, 
-                     char *rbuf _U_, size_t *rbuflen _U_)
+                      char *ibuf, size_t ibuflen _U_,
+                      char *rbuf _U_, size_t *rbuflen _U_)
 {
     int ret;
     int PAM_error;
@@ -812,14 +781,14 @@ static int changepw_3(void *obj _U_,
     ibuf += 16;
 
     /* ---- Start pwd changing with PAM --- */
-    ibuf[255] = '\0';          /* For safety */
+    ibuf[255] = '\0';       /* For safety */
     ibuf[511] = '\0';
 
     /* check if new and old password are equal */
     if (memcmp(ibuf, ibuf + 256, 255) == 0) {
-       LOG(log_info, logtype_uams, "DHX2 Chgpwd: new and old password are equal");
+        LOG(log_info, logtype_uams, "DHX2 Chgpwd: new and old password are equal");
         ret = AFPERR_PWDSAME;
-       goto error_ctx;
+        goto error_ctx;
     }
 
     /* Set these things up for the conv function. PAM_username was set in changepw_1 */
@@ -827,7 +796,7 @@ static int changepw_3(void *obj _U_,
     PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &lpamh);
     if (PAM_error != PAM_SUCCESS) {
         LOG(log_info, logtype_uams, "DHX2 Chgpwd: PAM error in pam_start");
-       ret = AFPERR_PARAM;
+        ret = AFPERR_PARAM;
         goto error_ctx;
     }
     pam_set_item(lpamh, PAM_TTY, "afpd");
@@ -837,21 +806,21 @@ static int changepw_3(void *obj _U_,
     seteuid(0);
     PAM_error = pam_authenticate(lpamh,0);
     if (PAM_error != PAM_SUCCESS) {
-       LOG(log_info, logtype_uams, "DHX2 Chgpwd: error authenticating with PAM");
-       seteuid(uid);
-       pam_end(lpamh, PAM_error);
-       ret = AFPERR_NOTAUTH;
-       goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2 Chgpwd: error authenticating with PAM");
+        seteuid(uid);
+        pam_end(lpamh, PAM_error);
+        ret = AFPERR_NOTAUTH;
+        goto error_ctx;
     }
     PAM_password = ibuf;
     PAM_error = pam_chauthtok(lpamh, 0);
     seteuid(uid); /* un-root ourselves. */
     memset(ibuf, 0, 512);
     if (PAM_error != PAM_SUCCESS) {
-       LOG(log_info, logtype_uams, "DHX2 Chgpwd: error changing pw with PAM");
-       pam_end(lpamh, PAM_error);
-       ret = AFPERR_ACCESS;
-       goto error_ctx;
+        LOG(log_info, logtype_uams, "DHX2 Chgpwd: error changing pw with PAM");
+        pam_end(lpamh, PAM_error);
+        ret = AFPERR_ACCESS;
+        goto error_ctx;
     }
     pam_end(lpamh, 0);
     ret = AFP_OK;
@@ -867,8 +836,8 @@ error_noctx:
 }
 
 static int dhx2_changepw(void *obj _U_, char *uname,
-                        struct passwd *pwd _U_, char *ibuf, size_t ibuflen _U_,
-                        char *rbuf _U_, size_t *rbuflen _U_)
+                         struct passwd *pwd _U_, char *ibuf, size_t ibuflen _U_,
+                         char *rbuf _U_, size_t *rbuflen _U_)
 {
     /* We use this to serialize the three incoming FPChangePassword calls */
     static int dhx2_changepw_status = 1;
@@ -877,22 +846,22 @@ static int dhx2_changepw(void *obj _U_, char *uname,
 
     switch (dhx2_changepw_status) {
     case 1:
-       ret = changepw_1( obj, uname, ibuf, ibuflen, rbuf, rbuflen);
-       if ( ret == AFPERR_AUTHCONT)
-           dhx2_changepw_status = 2;
-       break;
+        ret = changepw_1( obj, uname, ibuf, ibuflen, rbuf, rbuflen);
+        if ( ret == AFPERR_AUTHCONT)
+            dhx2_changepw_status = 2;
+        break;
     case 2:
-       ret = changepw_2( obj, ibuf, ibuflen, rbuf, rbuflen);
+        ret = changepw_2( obj, ibuf, ibuflen, rbuf, rbuflen);
         if ( ret == AFPERR_AUTHCONT)
             dhx2_changepw_status = 3;
-       else
-           dhx2_changepw_status = 1;
-       break;
+        else
+            dhx2_changepw_status = 1;
+        break;
     case 3:
-       ret = changepw_3( obj, ibuf, ibuflen, rbuf, rbuflen);
-       dhx2_changepw_status = 1; /* Whether is was succesfull or not: we
-                                    restart anyway !*/
-       break;
+        ret = changepw_3( obj, ibuf, ibuflen, rbuf, rbuflen);
+        dhx2_changepw_status = 1; /* Whether is was succesfull or not: we
+                                     restart anyway !*/
+        break;
     }
     return ret;
 }
@@ -904,6 +873,17 @@ static int uam_setup(const char *path)
         return -1;
     if (uam_register(UAM_SERVER_CHANGEPW, path, "DHX2", dhx2_changepw) < 0)
         return -1;
+
+    p = gcry_mpi_new(0);
+    g = gcry_mpi_new(0);
+
+    LOG(log_debug, logtype_uams, "DHX2: generating mersenne primes");
+    /* Generate p and g for DH */
+    if (dh_params_generate(PRIMEBITS) != 0) {
+        LOG(log_error, logtype_uams, "DHX2: Couldn't generate p and g");
+        return -1;
+    }
+
     return 0;
 }
 
@@ -911,6 +891,9 @@ static void uam_cleanup(void)
 {
     uam_unregister(UAM_SERVER_LOGIN, "DHX2");
     uam_unregister(UAM_SERVER_CHANGEPW, "DHX2");
+
+    gcry_mpi_release(p);
+    gcry_mpi_release(g);
 }
 
 
@@ -928,4 +911,3 @@ UAM_MODULE_EXPORT struct uam_export uams_dhx2_pam = {
 };
 
 #endif /* USE_PAM && UAM_DHX2 */
-
index e16681a4eee95bbafc3d376065c2264dac631345..7b90b38e561ab4c70eaee95c32718c889b5ddfb5 100644 (file)
@@ -51,6 +51,7 @@ struct dsi_block {
 
 #define DSI_CMDSIZ        8192 
 #define DSI_DATASIZ       8192
+
 /* child and parent processes might interpret a couple of these
  * differently. */
 typedef struct DSI {
@@ -87,16 +88,16 @@ typedef struct DSI {
 #endif 
 
 #ifdef USE_ZEROCONF
+  char *bonjourname;      /* server name as UTF8 maxlen MAXINSTANCENAMELEN */
   int zeroconf_registered;
 #endif
 
-  /* buffer for OSX deadlock */
+  /* DSI readahead buffer used for buffered reads in dsi_peek */
+  size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */
   char *buffer;
   char *start;
   char *eof;
   char *end;
-  int  maxsize;
-
 } DSI;
   
 /* DSI flags */
@@ -151,6 +152,7 @@ typedef struct DSI {
 #define DSI_NOREPLY          (1 << 6) /* in dsi_write we generate our own replies */
 #define DSI_RECONSOCKET      (1 << 7) /* we have a new socket from primary reconnect */
 #define DSI_RECONINPROG      (1 << 8) /* used in the new session in reconnect */
+#define DSI_AFP_LOGGED_OUT   (1 << 9) /* client called afp_logout, quit on next EOF from socket */
 
 /* basic initialization: dsi_init.c */
 extern DSI *dsi_init (const dsi_proto /*protocol*/,
index 1bb2ee3efdaad8c7f0a0528c40d392b5ebd49d24..27441549e2d803cd3e0f85b147673fb6aa3e51b0 100644 (file)
@@ -90,9 +90,13 @@ extern int atalk_iconv_close (atalk_iconv_t);
 extern struct charset_functions *find_charset_functions (const char *);
 extern int atalk_register_charset (struct charset_functions *);
 
+/* from utf16_case.c */
+extern ucs2_t    toupper_w  (ucs2_t);
+extern u_int32_t toupper_sp (u_int32_t);
+extern ucs2_t    tolower_w  (ucs2_t);
+extern u_int32_t tolower_sp (u_int32_t);
+
 /* from util_unistr.c */
-extern ucs2_t   toupper_w  (ucs2_t);
-extern ucs2_t   tolower_w  (ucs2_t);
 extern int      strupper_w (ucs2_t *);
 extern int      strlower_w (ucs2_t *);
 extern int      islower_w  (ucs2_t);
index 7b1b10fbe5f1ef56201089a88beee5818659eb3c..1a428bda88de08f5166f3bfe9c8c1176e92aaf4c 100644 (file)
@@ -15,7 +15,9 @@
 #include <sys/socket.h>
 #include <unistd.h>
 #include <poll.h>
+
 #include <atalk/unicode.h>
+#include <atalk/bstrlib.h>
 
 /* exit error codes */
 #define EXITERR_CLNT 1  /* client related error */
@@ -161,3 +163,9 @@ extern char *stripped_slashes_basename(char *p);
 extern int lchdir(const char *dir);
 extern void randombytes(void *buf, int n);
 #endif  /* _ATALK_UTIL_H */
+
+/******************************************************************
+ * cnid.c
+ *****************************************************************/
+
+extern bstring rel_path_in_vol(const char *path, const char *volpath);
index 57933f088e40d2e9d4210739af9050ca0683fe88..0ff0ea5b6c169597ef5208767231329d0d320354 100644 (file)
@@ -217,7 +217,7 @@ int nfsv4_chmod(char *name, mode_t mode)
 {
     int ret = -1;
     int noaces, nnaces;
-    ace_t *oacl = NULL, *nacl = NULL, *cacl;
+    ace_t *oacl = NULL, *nacl = NULL, *cacl = NULL;
 
     LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)",
         getcwdpath(), name, mode);
index 12287ff0c35d551adb36544443b1e0a25fc3f2be..b7e1f4035f856b3480ef37bfd249139e77624a58 100644 (file)
@@ -97,7 +97,7 @@ static int tsock_getfd(const char *host, const char *port)
         }
 
         if (setnonblock(sock, 1) != 0) {
-            LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(err));
+            LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(errno));
             close(sock);
             sock = -1;
             return -1;
index f34b81d256e33abef514797f6150353befebdfba..a929097c82ca6fd62028ed2180ac2737bde85f5c 100644 (file)
@@ -24,8 +24,8 @@ functions which need their own buffers: dsi_attention, dsi_tickle
 PERFORMANCE TWEAKING:
 sending complete packets or the header and a partial packet to the
 client should always be handled by proto_send. for dsi_tcp.c,
-proto_send will coalesce the header and data by using writev if
-USE_WRITEV is defined. in addition, appleshare sessions often involve
+proto_send will coalesce the header and data by using writev.
+in addition, appleshare sessions often involve
 the sending and receiving of many small packets. as a consequence, i
 use TCP_NODELAY to speed up the turnaround time.
 
index 42a65ecdf35493e36e5124c862579936ec3a8a5e..80bee3fe702a79cfbd18bd7a7ac4bd8539295aaf 100644 (file)
@@ -18,7 +18,7 @@
 void dsi_close(DSI *dsi)
 {
   /* server generated. need to set all the fields. */
-  if (!(dsi->flags & DSI_SLEEPING)) {
+  if (!(dsi->flags & DSI_SLEEPING) && !(dsi->flags & DSI_DISCONNECTED)) {
       dsi->header.dsi_flags = DSIFL_REQUEST;
       dsi->header.dsi_command = DSIFUNC_CLOSE;
       dsi->header.dsi_requestID = htons(dsi_serverID(dsi));
index 180049f23fbf07c6fa980bef24e8afa9831e9d61..5ea32b01a4afb8bccd46dce7ad76a2656a24880e 100644 (file)
@@ -35,12 +35,12 @@ afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval
   afp_child_t *child;
 
   if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
-      LOG(log_error, logtype_afpd, "dsi_getsess: %s", strerror(errno));
+      LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
       exit( EXITERR_CLNT );
   }
 
   if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
-      LOG(log_error, logtype_afpd, "dsi_getsess: setnonblock: %s", strerror(errno));
+      LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
       exit(EXITERR_CLNT);
   }
 
index e8818e6134bd81f5809a80e2b416284005cbbf72..2d7fd23b84c947789f060dfe7b89b3e3ab41f398 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: dsi_opensess.c,v 1.4 2005-09-07 15:27:29 didg Exp $
- *
  * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
  */
 #include <stdio.h>
 #include <string.h>
 #include <sys/types.h>
+#include <stdlib.h>
 
 #include <atalk/dsi.h>
+#include <atalk/util.h>
+#include <atalk/logger.h>
+
+static void dsi_init_buffer(DSI *dsi)
+{
+    size_t quantum = dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF;
+
+    /* default is 12 * 300k = 3,6 MB (Apr 2011) */
+    if ((dsi->buffer = malloc(dsi->dsireadbuf * quantum)) == NULL) {
+        LOG(log_error, logtype_dsi, "dsi_init_buffer: OOM");
+        AFP_PANIC("OOM in dsi_init_buffer");
+    }
+    dsi->start = dsi->buffer;
+    dsi->eof = dsi->buffer;
+    dsi->end = dsi->buffer + (dsi->dsireadbuf * quantum);
+}
 
 /* OpenSession. set up the connection */
 void dsi_opensession(DSI *dsi)
@@ -21,6 +36,12 @@ void dsi_opensession(DSI *dsi)
   u_int32_t i = 0; /* this serves double duty. it must be 4-bytes long */
   int offs;
 
+  dsi_init_buffer(dsi);
+  if (setnonblock(dsi->socket, 1) < 0) {
+      LOG(log_error, logtype_dsi, "dsi_opensession: setnonblock: %s", strerror(errno));
+      AFP_PANIC("setnonblock error");
+  }
+
   /* parse options */
   while (i < dsi->cmdlen) {
     switch (dsi->commands[i++]) {
index 149bc208edbc40338a85d18cd7c180451741ddd7..90df884efee6a1e054da359564a77f7e4122e4cd 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id: dsi_stream.c,v 1.20 2009-10-26 12:35:56 franklahm Exp $
- *
  * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu)
  * All rights reserved. See COPYRIGHT.
  *
@@ -15,8 +13,6 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#define USE_WRITEV
-
 #include <stdio.h>
 #include <stdlib.h>
 
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-
-#ifdef USE_WRITEV
 #include <sys/uio.h>
-#endif
 
 #include <atalk/logger.h>
 #include <atalk/dsi.h>
 #define MSG_DONTWAIT 0x40
 #endif
 
-/* ------------------------- 
- * we don't use a circular buffer.
-*/
-static void dsi_init_buffer(DSI *dsi)
-{
-    if (!dsi->buffer) {
-        /* XXX config options */
-        dsi->maxsize = 6 * dsi->server_quantum;
-        if (!dsi->maxsize)
-            dsi->maxsize = 6 * DSI_SERVQUANT_DEF;
-        dsi->buffer = malloc(dsi->maxsize);
-        if (!dsi->buffer) {
-            return;
-        }
-        dsi->start = dsi->buffer;
-        dsi->eof = dsi->buffer;
-        dsi->end = dsi->buffer + dsi->maxsize;
-    }
-}
-
-/* ---------------------- 
-   afpd is sleeping too much while trying to send something.
-   May be there's no reader or the reader is also sleeping in write,
-   look if there's some data for us to read, hopefully it will wake up
-   the reader so we can write again.
-*/
+/*
+ * afpd is sleeping too much while trying to send something.
+ * May be there's no reader or the reader is also sleeping in write,
+ * look if there's some data for us to read, hopefully it will wake up
+ * the reader so we can write again.
+ *
+ * @returns 0 when is possible to send again, -1 on error
+ */
 static int dsi_peek(DSI *dsi)
 {
+    static int warned = 0;
     fd_set readfds, writefds;
     int    len;
     int    maxfd;
     int    ret;
 
-    FD_ZERO(&readfds);
-    FD_ZERO(&writefds);
-    FD_SET( dsi->socket, &readfds);
-    FD_SET( dsi->socket, &writefds);
-    maxfd = dsi->socket +1;
+    LOG(log_debug, logtype_dsi, "dsi_peek");
+
+    maxfd = dsi->socket + 1;
 
     while (1) {
-        FD_SET( dsi->socket, &readfds);
+        FD_ZERO(&readfds);
+        FD_ZERO(&writefds);
+
+        if (dsi->eof < dsi->end) {
+            /* space in read buffer */
+            FD_SET( dsi->socket, &readfds);
+        } else {
+            if (!warned) {
+                warned = 1;
+                LOG(log_note, logtype_dsi, "dsi_peek: readahead buffer is full, possibly increase -dsireadbuf option");
+                LOG(log_note, logtype_dsi, "dsi_peek: dsireadbuf: %d, DSI quantum: %d, effective buffer size: %d",
+                    dsi->dsireadbuf,
+                    dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF,
+                    dsi->end - dsi->buffer);
+            }
+        }
+
         FD_SET( dsi->socket, &writefds);
 
         /* No timeout: if there's nothing to read nor nothing to write,
@@ -97,29 +87,35 @@ static int dsi_peek(DSI *dsi)
                 /* we might have been interrupted by out timer, so restart select */
                 continue;
             /* give up */
+            LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s",
+                ret, ret < 0 ? strerror(errno) : "");
+            return -1;
+        }
+
+        if (FD_ISSET(dsi->socket, &writefds)) {
+            /* we can write again */
+            LOG(log_debug, logtype_dsi, "dsi_peek: can write again");
             break;
         }
 
         /* Check if there's sth to read, hopefully reading that will unblock the client */
         if (FD_ISSET(dsi->socket, &readfds)) {
-            dsi_init_buffer(dsi);
-            len = dsi->end - dsi->eof;
-
-            if (len <= 0) {
-                /* ouch, our buffer is full ! fall back to blocking IO 
-                 * could block and disconnect but it's better than a cpu hog */
-                break;
+            len = dsi->end - dsi->eof; /* it's ensured above that there's space */
+
+            if ((len = read(dsi->socket, dsi->eof, len)) <= 0) {
+                if (len == 0) {
+                    LOG(log_error, logtype_dsi, "dsi_peek: EOF");
+                    return -1;
+                }
+                LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno));
+                if (errno == EAGAIN)
+                    continue;
+                return -1;
             }
+            LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len);
 
-            len = read(dsi->socket, dsi->eof, len);
-            if (len <= 0)
-                break;
             dsi->eof += len;
         }
-
-        if (FD_ISSET(dsi->socket, &writefds))
-            /* we can write again at last */
-            break;
     }
 
     return 0;
@@ -140,12 +136,6 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
 
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
 
-  /* non blocking mode */
-  if (setnonblock(dsi->socket, 1) < 0) {
-      LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
-      return -1;
-  }
-
   while (written < length) {
       len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
       if (len >= 0) {
@@ -157,6 +147,8 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
           continue;
 
       if (errno == EAGAIN || errno == EWOULDBLOCK) {
+          LOG(log_debug, logtype_dsi, "dsi_stream_write: send: %s", strerror(errno));
+
           if (mode == DSI_NOWAIT && written == 0) {
               /* DSI_NOWAIT is used by attention give up in this case. */
               written = -1;
@@ -180,11 +172,6 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
   dsi->write_count += written;
 
 exit:
-  if (setnonblock(dsi->socket, 0) < 0) {
-      LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
-      written = -1;
-  }
-
   dsi->in_write--;
   return written;
 }
@@ -198,15 +185,11 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
   size_t written;
   ssize_t len;
 
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
+
   dsi->in_write++;
   written = 0;
 
-  /* non blocking mode */
-  if (setnonblock(dsi->socket, 1) < 0) {
-      LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
-      return -1;
-  }
-
   while (written < length) {
     len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
         
@@ -225,7 +208,7 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
           }
           continue;
       }
-      LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno));
+      LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
       break;
     }
     else if (!len) {
@@ -237,11 +220,6 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
         written += len;
   }
 
-  if (setnonblock(dsi->socket, 0) < 0) {
-      LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
-      return -1;
-  }
-
   dsi->write_count += written;
   dsi->in_write--;
   return written;
@@ -254,20 +232,27 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
 static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
 {
     size_t nbe = 0;
-    
-    if (dsi->start) {        
-        nbe = dsi->eof - dsi->start;
 
-        if (nbe > 0) {
-           nbe = min((size_t)nbe, count);
-           memcpy(buf, dsi->start, nbe);
-           dsi->start += nbe;
+    if (dsi->buffer == NULL)
+        /* afpd master has no DSI buffering */
+        return 0;
 
-           if (dsi->eof == dsi->start) 
-               dsi->start = dsi->eof = dsi->buffer;
+    LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count);
+    
+    nbe = dsi->eof - dsi->start;
 
-        }
+    if (nbe > 0) {
+        nbe = min((size_t)nbe, count);
+        memcpy(buf, dsi->start, nbe);
+        dsi->start += nbe;
+
+        if (dsi->eof == dsi->start)
+            dsi->start = dsi->eof = dsi->buffer;
     }
+
+    LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u",
+        dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe);
+
     return nbe;
 }
 
@@ -281,46 +266,61 @@ static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
  */
 static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
 {
-    ssize_t nbe;
-    
+    ssize_t len;
+
+    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count);
+
     if (!count)
         return 0;
 
-    nbe = from_buf(dsi, buf, count); /* 1. */
-    if (nbe)
-        return nbe;             /* 2. */
+    len = from_buf(dsi, buf, count); /* 1. */
+    if (len)
+        return len;             /* 2. */
   
-    return read(dsi->socket, buf, count); /* 3. */
+    len = readt(dsi->socket, buf, count, 0, 1); /* 3. */
+
+    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len);
+
+    return len;
 }
 
 /*
  * Essentially a loop around buf_read() to ensure "length" bytes are read
  * from dsi->buffer and/or the socket.
+ *
+ * @returns length on success, some value smaller then length indicates an error
  */
 size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
 {
   size_t stored;
   ssize_t len;
 
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes)", length);
+
   stored = 0;
   while (stored < length) {
-    len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
-    if (len == -1 && errno == EINTR) {
-      continue;
-    } else if (len > 0) {
-      stored += len;
-    } else { /* eof or error */
-      /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
-      if (len || stored || dsi->read_count) {
-          if (! (dsi->flags & DSI_DISCONNECTED))
-              LOG(log_error, logtype_dsi, "dsi_stream_read(fd: %i): len:%d, %s",
-                  dsi->socket, len, (len < 0) ? strerror(errno) : "unexpected EOF");
+      len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
+      if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
+          LOG(log_debug, logtype_dsi, "dsi_stream_read: select read loop");
+          continue;
+      } else if (len > 0) {
+          stored += len;
+      } else { /* eof or error */
+          /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
+          if (len || stored || dsi->read_count) {
+              if (! (dsi->flags & DSI_DISCONNECTED)) {
+                  LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
+                      len, (len < 0) ? strerror(errno) : "unexpected EOF");
+              }
+              return 0;
+          }
+          break;
       }
-      break;
-    }
   }
 
   dsi->read_count += stored;
+
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes): got: %u", length, stored);
   return stored;
 }
 
@@ -332,8 +332,9 @@ static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t le
 {
   size_t len;
   size_t buflen;
+
+  LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
   
-  dsi_init_buffer(dsi);
   len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
   dsi->read_count += len;
   if (len == length) {          /* got enough bytes from there ? */
@@ -375,11 +376,12 @@ static void unblock_sig(DSI *dsi)
 int dsi_stream_send(DSI *dsi, void *buf, size_t length)
 {
   char block[DSI_BLOCKSIZ];
-#ifdef USE_WRITEV
   struct iovec iov[2];
   size_t towrite;
   ssize_t len;
-#endif /* USE_WRITEV */
+
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
+      length ? length : sizeof(block));
 
   block[0] = dsi->header.dsi_flags;
   block[1] = dsi->header.dsi_command;
@@ -397,7 +399,6 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
   
   /* block signals */
   block_sig(dsi);
-#ifdef USE_WRITEV
   iov[0].iov_base = block;
   iov[0].iov_len = sizeof(block);
   iov[1].iov_base = buf;
@@ -406,46 +407,36 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
   towrite = sizeof(block) + length;
   dsi->write_count += towrite;
   while (towrite > 0) {
-    if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || 
-       !len)
-      continue;
+      if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || (len == 0))
+          continue;
     
-    if ((size_t)len == towrite) /* wrote everything out */
-      break;
-    else if (len < 0) { /* error */
-      if (errno == EAGAIN || errno == EWOULDBLOCK) {
-          if (!dsi_peek(dsi)) {
-              continue;
+      if ((size_t)len == towrite) /* wrote everything out */
+          break;
+      else if (len < 0) { /* error */
+          if (errno == EAGAIN || errno == EWOULDBLOCK) {
+              if (!dsi_peek(dsi)) {
+                  continue;
+              }
           }
+          LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
+          unblock_sig(dsi);
+          return 0;
       }
-      LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
-      unblock_sig(dsi);
-      return 0;
-    }
     
-    towrite -= len;
-    if (towrite > length) { /* skip part of header */
-      iov[0].iov_base = (char *) iov[0].iov_base + len;
-      iov[0].iov_len -= len;
-    } else { /* skip to data */
-      if (iov[0].iov_len) {
-       len -= iov[0].iov_len;
-       iov[0].iov_len = 0;
+      towrite -= len;
+      if (towrite > length) { /* skip part of header */
+          iov[0].iov_base = (char *) iov[0].iov_base + len;
+          iov[0].iov_len -= len;
+      } else { /* skip to data */
+          if (iov[0].iov_len) {
+              len -= iov[0].iov_len;
+              iov[0].iov_len = 0;
+          }
+          iov[1].iov_base = (char *) iov[1].iov_base + len;
+          iov[1].iov_len -= len;
       }
-      iov[1].iov_base = (char *) iov[1].iov_base + len;
-      iov[1].iov_len -= len;
-    }
   }
   
-#else /* USE_WRITEV */
-  /* write the header then data */
-  if ((dsi_stream_write(dsi, block, sizeof(block), 1) != sizeof(block)) ||
-            (dsi_stream_write(dsi, buf, length, 0) != length)) {
-      unblock_sig(dsi);
-      return 0;
-  }
-#endif /* USE_WRITEV */
-
   unblock_sig(dsi);
   return 1;
 }
@@ -460,6 +451,8 @@ int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
 {
   char block[DSI_BLOCKSIZ];
 
+  LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
+
   /* read in the header */
   if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
     return 0;
index 7e49b1630554aeee5b1aa3529f3ae9daceeb009f..90f8ed5209e762a23044ac1dda5217896e70e734 100644 (file)
@@ -5,4 +5,4 @@ Makefile.in
 .deps
 .libs
 .gitignore
-charcnv.o iconv.o utf8.o util_unistr.o
+charcnv.o iconv.o utf16_case.o utf8.o util_unistr.o
index a697dfcdf966a4857fad0965ada03d1f37358124..b56f9f354d754e6fde0c155562bd8536fa7ca1f4 100644 (file)
@@ -12,10 +12,11 @@ libunicode_la_SOURCES = \
        util_unistr.c   \
        iconv.c         \
        charcnv.c       \
-       utf8.c
+       utf8.c          \
+       utf16_case.c
 
 libunicode_la_LIBADD = $(LIBUNICODE_DEPS)
 
-noinst_HEADERS = ucs2_casetable.h precompose.h byteorder.h
+noinst_HEADERS = utf16_casetable.h precompose.h byteorder.h
 
 LIBS=@ICONV_LIBS@
diff --git a/libatalk/unicode/ucs2_casetable.h b/libatalk/unicode/ucs2_casetable.h
deleted file mode 100644 (file)
index 8ac86da..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-static const u_int16_t upcase_table_1[64] = {
-0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,   /* 0x0040-0x0047 */ 
-0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,   /* 0x0048-0x004F */ 
-0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,   /* 0x0050-0x0057 */ 
-0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,   /* 0x0058-0x005F */ 
-0x0060, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,   /* 0x0060-0x0067 */ 
-0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,   /* 0x0068-0x006F */ 
-0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,   /* 0x0070-0x0077 */ 
-0x0058, 0x0059, 0x005A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F }; /* 0x0078-0x007F */
-
-static const u_int16_t upcase_table_2[512] = {
-0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,   /* 0x00C0-0x00C7 */ 
-0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,   /* 0x00C8-0x00CF */ 
-0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7,   /* 0x00D0-0x00D7 */ 
-0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF,   /* 0x00D8-0x00DF */ 
-0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7,   /* 0x00E0-0x00E7 */ 
-0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF,   /* 0x00E8-0x00EF */ 
-0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00F7,   /* 0x00F0-0x00F7 */ 
-0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x0178,   /* 0x00F8-0x00FF */ 
-0x0100, 0x0100, 0x0102, 0x0102, 0x0104, 0x0104, 0x0106, 0x0106,   /* 0x0100-0x0107 */ 
-0x0108, 0x0108, 0x010A, 0x010A, 0x010C, 0x010C, 0x010E, 0x010E,   /* 0x0108-0x010F */ 
-0x0110, 0x0110, 0x0112, 0x0112, 0x0114, 0x0114, 0x0116, 0x0116,   /* 0x0110-0x0117 */ 
-0x0118, 0x0118, 0x011A, 0x011A, 0x011C, 0x011C, 0x011E, 0x011E,   /* 0x0118-0x011F */ 
-0x0120, 0x0120, 0x0122, 0x0122, 0x0124, 0x0124, 0x0126, 0x0126,   /* 0x0120-0x0127 */ 
-0x0128, 0x0128, 0x012A, 0x012A, 0x012C, 0x012C, 0x012E, 0x012E,   /* 0x0128-0x012F */ 
-0x0130, 0x0131, 0x0132, 0x0132, 0x0134, 0x0134, 0x0136, 0x0136,   /* 0x0130-0x0137 */ 
-0x0138, 0x0139, 0x0139, 0x013B, 0x013B, 0x013D, 0x013D, 0x013F,   /* 0x0138-0x013F */ 
-0x013F, 0x0141, 0x0141, 0x0143, 0x0143, 0x0145, 0x0145, 0x0147,   /* 0x0140-0x0147 */ 
-0x0147, 0x0149, 0x014A, 0x014A, 0x014C, 0x014C, 0x014E, 0x014E,   /* 0x0148-0x014F */ 
-0x0150, 0x0150, 0x0152, 0x0152, 0x0154, 0x0154, 0x0156, 0x0156,   /* 0x0150-0x0157 */ 
-0x0158, 0x0158, 0x015A, 0x015A, 0x015C, 0x015C, 0x015E, 0x015E,   /* 0x0158-0x015F */ 
-0x0160, 0x0160, 0x0162, 0x0162, 0x0164, 0x0164, 0x0166, 0x0166,   /* 0x0160-0x0167 */ 
-0x0168, 0x0168, 0x016A, 0x016A, 0x016C, 0x016C, 0x016E, 0x016E,   /* 0x0168-0x016F */ 
-0x0170, 0x0170, 0x0172, 0x0172, 0x0174, 0x0174, 0x0176, 0x0176,   /* 0x0170-0x0177 */ 
-0x0178, 0x0179, 0x0179, 0x017B, 0x017B, 0x017D, 0x017D, 0x017F,   /* 0x0178-0x017F */ 
-0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,   /* 0x0180-0x0187 */ 
-0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,   /* 0x0188-0x018F */ 
-0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x0195, 0x0196, 0x0197,   /* 0x0190-0x0197 */ 
-0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x019E, 0x019F,   /* 0x0198-0x019F */ 
-0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,   /* 0x01A0-0x01A7 */ 
-0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,   /* 0x01A8-0x01AF */ 
-0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,   /* 0x01B0-0x01B7 */ 
-0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01BF,   /* 0x01B8-0x01BF */ 
-0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7,   /* 0x01C0-0x01C7 */ 
-0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, 0x01CD, 0x01CD, 0x01CF,   /* 0x01C8-0x01CF */ 
-0x01CF, 0x01D1, 0x01D1, 0x01D3, 0x01D3, 0x01D5, 0x01D5, 0x01D7,   /* 0x01D0-0x01D7 */ 
-0x01D7, 0x01D9, 0x01D9, 0x01DB, 0x01DB, 0x018E, 0x01DE, 0x01DE,   /* 0x01D8-0x01DF */ 
-0x01E0, 0x01E0, 0x01E2, 0x01E2, 0x01E4, 0x01E4, 0x01E6, 0x01E6,   /* 0x01E0-0x01E7 */ 
-0x01E8, 0x01E8, 0x01EA, 0x01EA, 0x01EC, 0x01EC, 0x01EE, 0x01EE,   /* 0x01E8-0x01EF */ 
-0x01F0, 0x01F1, 0x01F2, 0x01F1, 0x01F4, 0x01F4, 0x01F6, 0x01F7,   /* 0x01F0-0x01F7 */ 
-0x01F8, 0x01F9, 0x01FA, 0x01FA, 0x01FC, 0x01FC, 0x01FE, 0x01FE,   /* 0x01F8-0x01FF */ 
-0x0200, 0x0200, 0x0202, 0x0202, 0x0204, 0x0204, 0x0206, 0x0206,   /* 0x0200-0x0207 */ 
-0x0208, 0x0208, 0x020A, 0x020A, 0x020C, 0x020C, 0x020E, 0x020E,   /* 0x0208-0x020F */ 
-0x0210, 0x0210, 0x0212, 0x0212, 0x0214, 0x0214, 0x0216, 0x0216,   /* 0x0210-0x0217 */ 
-0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,   /* 0x0218-0x021F */ 
-0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,   /* 0x0220-0x0227 */ 
-0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,   /* 0x0228-0x022F */ 
-0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,   /* 0x0230-0x0237 */ 
-0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F,   /* 0x0238-0x023F */ 
-0x0240, 0x0241, 0x0242, 0x0243, 0x0244, 0x0245, 0x0246, 0x0247,   /* 0x0240-0x0247 */ 
-0x0248, 0x0249, 0x024A, 0x024B, 0x024C, 0x024D, 0x024E, 0x024F,   /* 0x0248-0x024F */ 
-0x0250, 0x0251, 0x0252, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,   /* 0x0250-0x0257 */ 
-0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,   /* 0x0258-0x025F */ 
-0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,   /* 0x0260-0x0267 */ 
-0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,   /* 0x0268-0x026F */ 
-0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,   /* 0x0270-0x0277 */ 
-0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,   /* 0x0278-0x027F */ 
-0x0280, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,   /* 0x0280-0x0287 */ 
-0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,   /* 0x0288-0x028F */ 
-0x0290, 0x0291, 0x01B7, 0x0293, 0x0294, 0x0295, 0x0296, 0x0297,   /* 0x0290-0x0297 */ 
-0x0298, 0x0299, 0x029A, 0x029B, 0x029C, 0x029D, 0x029E, 0x029F,   /* 0x0298-0x029F */ 
-0x02A0, 0x02A1, 0x02A2, 0x02A3, 0x02A4, 0x02A5, 0x02A6, 0x02A7,   /* 0x02A0-0x02A7 */ 
-0x02A8, 0x02A9, 0x02AA, 0x02AB, 0x02AC, 0x02AD, 0x02AE, 0x02AF,   /* 0x02A8-0x02AF */ 
-0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6, 0x02B7,   /* 0x02B0-0x02B7 */ 
-0x02B8, 0x02B9, 0x02BA, 0x02BB, 0x02BC, 0x02BD, 0x02BE, 0x02BF }; /* 0x02B8-0x02BF */
-
-static const u_int16_t upcase_table_3[384] = {
-0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0386, 0x0387,   /* 0x0380-0x0387 */ 
-0x0388, 0x0389, 0x038A, 0x038B, 0x038C, 0x038D, 0x038E, 0x038F,   /* 0x0388-0x038F */ 
-0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,   /* 0x0390-0x0397 */ 
-0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,   /* 0x0398-0x039F */ 
-0x03A0, 0x03A1, 0x03A2, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,   /* 0x03A0-0x03A7 */ 
-0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,   /* 0x03A8-0x03AF */ 
-0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,   /* 0x03B0-0x03B7 */ 
-0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,   /* 0x03B8-0x03BF */ 
-0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,   /* 0x03C0-0x03C7 */ 
-0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x03CF,   /* 0x03C8-0x03CF */ 
-0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,   /* 0x03D0-0x03D7 */ 
-0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,   /* 0x03D8-0x03DF */ 
-0x03E0, 0x03E1, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,   /* 0x03E0-0x03E7 */ 
-0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,   /* 0x03E8-0x03EF */ 
-0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,   /* 0x03F0-0x03F7 */ 
-0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,   /* 0x03F8-0x03FF */ 
-0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,   /* 0x0400-0x0407 */ 
-0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040D, 0x040E, 0x040F,   /* 0x0408-0x040F */ 
-0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,   /* 0x0410-0x0417 */ 
-0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,   /* 0x0418-0x041F */ 
-0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,   /* 0x0420-0x0427 */ 
-0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,   /* 0x0428-0x042F */ 
-0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,   /* 0x0430-0x0437 */ 
-0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,   /* 0x0438-0x043F */ 
-0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,   /* 0x0440-0x0447 */ 
-0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,   /* 0x0448-0x044F */ 
-0x0450, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407,   /* 0x0450-0x0457 */ 
-0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x045D, 0x040E, 0x040F,   /* 0x0458-0x045F */ 
-0x0460, 0x0460, 0x0462, 0x0462, 0x0464, 0x0464, 0x0466, 0x0466,   /* 0x0460-0x0467 */ 
-0x0468, 0x0468, 0x046A, 0x046A, 0x046C, 0x046C, 0x046E, 0x046E,   /* 0x0468-0x046F */ 
-0x0470, 0x0470, 0x0472, 0x0472, 0x0474, 0x0474, 0x0476, 0x0476,   /* 0x0470-0x0477 */ 
-0x0478, 0x0478, 0x047A, 0x047A, 0x047C, 0x047C, 0x047E, 0x047E,   /* 0x0478-0x047F */ 
-0x0480, 0x0480, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,   /* 0x0480-0x0487 */ 
-0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,   /* 0x0488-0x048F */ 
-0x0490, 0x0490, 0x0492, 0x0492, 0x0494, 0x0494, 0x0496, 0x0496,   /* 0x0490-0x0497 */ 
-0x0498, 0x0498, 0x049A, 0x049A, 0x049C, 0x049C, 0x049E, 0x049E,   /* 0x0498-0x049F */ 
-0x04A0, 0x04A0, 0x04A2, 0x04A2, 0x04A4, 0x04A4, 0x04A6, 0x04A6,   /* 0x04A0-0x04A7 */ 
-0x04A8, 0x04A8, 0x04AA, 0x04AA, 0x04AC, 0x04AC, 0x04AE, 0x04AE,   /* 0x04A8-0x04AF */ 
-0x04B0, 0x04B0, 0x04B2, 0x04B2, 0x04B4, 0x04B4, 0x04B6, 0x04B6,   /* 0x04B0-0x04B7 */ 
-0x04B8, 0x04B8, 0x04BA, 0x04BA, 0x04BC, 0x04BC, 0x04BE, 0x04BE,   /* 0x04B8-0x04BF */ 
-0x04C0, 0x04C1, 0x04C1, 0x04C3, 0x04C3, 0x04C5, 0x04C6, 0x04C7,   /* 0x04C0-0x04C7 */ 
-0x04C7, 0x04C9, 0x04CA, 0x04CB, 0x04CB, 0x04CD, 0x04CE, 0x04CF,   /* 0x04C8-0x04CF */ 
-0x04D0, 0x04D0, 0x04D2, 0x04D2, 0x04D4, 0x04D4, 0x04D6, 0x04D6,   /* 0x04D0-0x04D7 */ 
-0x04D8, 0x04D8, 0x04DA, 0x04DA, 0x04DC, 0x04DC, 0x04DE, 0x04DE,   /* 0x04D8-0x04DF */ 
-0x04E0, 0x04E0, 0x04E2, 0x04E2, 0x04E4, 0x04E4, 0x04E6, 0x04E6,   /* 0x04E0-0x04E7 */ 
-0x04E8, 0x04E8, 0x04EA, 0x04EA, 0x04EC, 0x04ED, 0x04EE, 0x04EE,   /* 0x04E8-0x04EF */ 
-0x04F0, 0x04F0, 0x04F2, 0x04F2, 0x04F4, 0x04F4, 0x04F6, 0x04F7,   /* 0x04F0-0x04F7 */ 
-0x04F8, 0x04F8, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF }; /* 0x04F8-0x04FF */
-
-static const u_int16_t upcase_table_4[128] = {
-0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,   /* 0x0540-0x0547 */ 
-0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,   /* 0x0548-0x054F */ 
-0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0557,   /* 0x0550-0x0557 */ 
-0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,   /* 0x0558-0x055F */ 
-0x0560, 0x0531, 0x0532, 0x0533, 0x0534, 0x0535, 0x0536, 0x0537,   /* 0x0560-0x0567 */ 
-0x0538, 0x0539, 0x053A, 0x053B, 0x053C, 0x053D, 0x053E, 0x053F,   /* 0x0568-0x056F */ 
-0x0540, 0x0541, 0x0542, 0x0543, 0x0544, 0x0545, 0x0546, 0x0547,   /* 0x0570-0x0577 */ 
-0x0548, 0x0549, 0x054A, 0x054B, 0x054C, 0x054D, 0x054E, 0x054F,   /* 0x0578-0x057F */ 
-0x0550, 0x0551, 0x0552, 0x0553, 0x0554, 0x0555, 0x0556, 0x0587,   /* 0x0580-0x0587 */ 
-0x0588, 0x0589, 0x058A, 0x058B, 0x058C, 0x058D, 0x058E, 0x058F,   /* 0x0588-0x058F */ 
-0x0590, 0x0591, 0x0592, 0x0593, 0x0594, 0x0595, 0x0596, 0x0597,   /* 0x0590-0x0597 */ 
-0x0598, 0x0599, 0x059A, 0x059B, 0x059C, 0x059D, 0x059E, 0x059F,   /* 0x0598-0x059F */ 
-0x05A0, 0x05A1, 0x05A2, 0x05A3, 0x05A4, 0x05A5, 0x05A6, 0x05A7,   /* 0x05A0-0x05A7 */ 
-0x05A8, 0x05A9, 0x05AA, 0x05AB, 0x05AC, 0x05AD, 0x05AE, 0x05AF,   /* 0x05A8-0x05AF */ 
-0x05B0, 0x05B1, 0x05B2, 0x05B3, 0x05B4, 0x05B5, 0x05B6, 0x05B7,   /* 0x05B0-0x05B7 */ 
-0x05B8, 0x05B9, 0x05BA, 0x05BB, 0x05BC, 0x05BD, 0x05BE, 0x05BF }; /* 0x05B8-0x05BF */
-
-static const u_int16_t upcase_table_5[512] = {
-0x1E00, 0x1E00, 0x1E02, 0x1E02, 0x1E04, 0x1E04, 0x1E06, 0x1E06,   /* 0x1E00-0x1E07 */ 
-0x1E08, 0x1E08, 0x1E0A, 0x1E0A, 0x1E0C, 0x1E0C, 0x1E0E, 0x1E0E,   /* 0x1E08-0x1E0F */ 
-0x1E10, 0x1E10, 0x1E12, 0x1E12, 0x1E14, 0x1E14, 0x1E16, 0x1E16,   /* 0x1E10-0x1E17 */ 
-0x1E18, 0x1E18, 0x1E1A, 0x1E1A, 0x1E1C, 0x1E1C, 0x1E1E, 0x1E1E,   /* 0x1E18-0x1E1F */ 
-0x1E20, 0x1E20, 0x1E22, 0x1E22, 0x1E24, 0x1E24, 0x1E26, 0x1E26,   /* 0x1E20-0x1E27 */ 
-0x1E28, 0x1E28, 0x1E2A, 0x1E2A, 0x1E2C, 0x1E2C, 0x1E2E, 0x1E2E,   /* 0x1E28-0x1E2F */ 
-0x1E30, 0x1E30, 0x1E32, 0x1E32, 0x1E34, 0x1E34, 0x1E36, 0x1E36,   /* 0x1E30-0x1E37 */ 
-0x1E38, 0x1E38, 0x1E3A, 0x1E3A, 0x1E3C, 0x1E3C, 0x1E3E, 0x1E3E,   /* 0x1E38-0x1E3F */ 
-0x1E40, 0x1E40, 0x1E42, 0x1E42, 0x1E44, 0x1E44, 0x1E46, 0x1E46,   /* 0x1E40-0x1E47 */ 
-0x1E48, 0x1E48, 0x1E4A, 0x1E4A, 0x1E4C, 0x1E4C, 0x1E4E, 0x1E4E,   /* 0x1E48-0x1E4F */ 
-0x1E50, 0x1E50, 0x1E52, 0x1E52, 0x1E54, 0x1E54, 0x1E56, 0x1E56,   /* 0x1E50-0x1E57 */ 
-0x1E58, 0x1E58, 0x1E5A, 0x1E5A, 0x1E5C, 0x1E5C, 0x1E5E, 0x1E5E,   /* 0x1E58-0x1E5F */ 
-0x1E60, 0x1E60, 0x1E62, 0x1E62, 0x1E64, 0x1E64, 0x1E66, 0x1E66,   /* 0x1E60-0x1E67 */ 
-0x1E68, 0x1E68, 0x1E6A, 0x1E6A, 0x1E6C, 0x1E6C, 0x1E6E, 0x1E6E,   /* 0x1E68-0x1E6F */ 
-0x1E70, 0x1E70, 0x1E72, 0x1E72, 0x1E74, 0x1E74, 0x1E76, 0x1E76,   /* 0x1E70-0x1E77 */ 
-0x1E78, 0x1E78, 0x1E7A, 0x1E7A, 0x1E7C, 0x1E7C, 0x1E7E, 0x1E7E,   /* 0x1E78-0x1E7F */ 
-0x1E80, 0x1E80, 0x1E82, 0x1E82, 0x1E84, 0x1E84, 0x1E86, 0x1E86,   /* 0x1E80-0x1E87 */ 
-0x1E88, 0x1E88, 0x1E8A, 0x1E8A, 0x1E8C, 0x1E8C, 0x1E8E, 0x1E8E,   /* 0x1E88-0x1E8F */ 
-0x1E90, 0x1E90, 0x1E92, 0x1E92, 0x1E94, 0x1E94, 0x1E96, 0x1E97,   /* 0x1E90-0x1E97 */ 
-0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,   /* 0x1E98-0x1E9F */ 
-0x1EA0, 0x1EA0, 0x1EA2, 0x1EA2, 0x1EA4, 0x1EA4, 0x1EA6, 0x1EA6,   /* 0x1EA0-0x1EA7 */ 
-0x1EA8, 0x1EA8, 0x1EAA, 0x1EAA, 0x1EAC, 0x1EAC, 0x1EAE, 0x1EAE,   /* 0x1EA8-0x1EAF */ 
-0x1EB0, 0x1EB0, 0x1EB2, 0x1EB2, 0x1EB4, 0x1EB4, 0x1EB6, 0x1EB6,   /* 0x1EB0-0x1EB7 */ 
-0x1EB8, 0x1EB8, 0x1EBA, 0x1EBA, 0x1EBC, 0x1EBC, 0x1EBE, 0x1EBE,   /* 0x1EB8-0x1EBF */ 
-0x1EC0, 0x1EC0, 0x1EC2, 0x1EC2, 0x1EC4, 0x1EC4, 0x1EC6, 0x1EC6,   /* 0x1EC0-0x1EC7 */ 
-0x1EC8, 0x1EC8, 0x1ECA, 0x1ECA, 0x1ECC, 0x1ECC, 0x1ECE, 0x1ECE,   /* 0x1EC8-0x1ECF */ 
-0x1ED0, 0x1ED0, 0x1ED2, 0x1ED2, 0x1ED4, 0x1ED4, 0x1ED6, 0x1ED6,   /* 0x1ED0-0x1ED7 */ 
-0x1ED8, 0x1ED8, 0x1EDA, 0x1EDA, 0x1EDC, 0x1EDC, 0x1EDE, 0x1EDE,   /* 0x1ED8-0x1EDF */ 
-0x1EE0, 0x1EE0, 0x1EE2, 0x1EE2, 0x1EE4, 0x1EE4, 0x1EE6, 0x1EE6,   /* 0x1EE0-0x1EE7 */ 
-0x1EE8, 0x1EE8, 0x1EEA, 0x1EEA, 0x1EEC, 0x1EEC, 0x1EEE, 0x1EEE,   /* 0x1EE8-0x1EEF */ 
-0x1EF0, 0x1EF0, 0x1EF2, 0x1EF2, 0x1EF4, 0x1EF4, 0x1EF6, 0x1EF6,   /* 0x1EF0-0x1EF7 */ 
-0x1EF8, 0x1EF8, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,   /* 0x1EF8-0x1EFF */ 
-0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,   /* 0x1F00-0x1F07 */ 
-0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,   /* 0x1F08-0x1F0F */ 
-0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F16, 0x1F17,   /* 0x1F10-0x1F17 */ 
-0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x1F1E, 0x1F1F,   /* 0x1F18-0x1F1F */ 
-0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,   /* 0x1F20-0x1F27 */ 
-0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,   /* 0x1F28-0x1F2F */ 
-0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,   /* 0x1F30-0x1F37 */ 
-0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,   /* 0x1F38-0x1F3F */ 
-0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F46, 0x1F47,   /* 0x1F40-0x1F47 */ 
-0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x1F4E, 0x1F4F,   /* 0x1F48-0x1F4F */ 
-0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,   /* 0x1F50-0x1F57 */ 
-0x1F58, 0x1F59, 0x1F5A, 0x1F5B, 0x1F5C, 0x1F5D, 0x1F5E, 0x1F5F,   /* 0x1F58-0x1F5F */ 
-0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,   /* 0x1F60-0x1F67 */ 
-0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,   /* 0x1F68-0x1F6F */ 
-0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,   /* 0x1F70-0x1F77 */ 
-0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x1F7E, 0x1F7F,   /* 0x1F78-0x1F7F */ 
-0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,   /* 0x1F80-0x1F87 */ 
-0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,   /* 0x1F88-0x1F8F */ 
-0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,   /* 0x1F90-0x1F97 */ 
-0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,   /* 0x1F98-0x1F9F */ 
-0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,   /* 0x1FA0-0x1FA7 */ 
-0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,   /* 0x1FA8-0x1FAF */ 
-0x1FB8, 0x1FB9, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,   /* 0x1FB0-0x1FB7 */ 
-0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF,   /* 0x1FB8-0x1FBF */ 
-0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,   /* 0x1FC0-0x1FC7 */ 
-0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,   /* 0x1FC8-0x1FCF */ 
-0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,   /* 0x1FD0-0x1FD7 */ 
-0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,   /* 0x1FD8-0x1FDF */ 
-0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,   /* 0x1FE0-0x1FE7 */ 
-0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,   /* 0x1FE8-0x1FEF */ 
-0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,   /* 0x1FF0-0x1FF7 */ 
-0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF }; /* 0x1FF8-0x1FFF */
-
-static const u_int16_t upcase_table_6[64] = {
-0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,   /* 0x2140-0x2147 */ 
-0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,   /* 0x2148-0x214F */ 
-0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,   /* 0x2150-0x2157 */ 
-0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,   /* 0x2158-0x215F */ 
-0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,   /* 0x2160-0x2167 */ 
-0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F,   /* 0x2168-0x216F */ 
-0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167,   /* 0x2170-0x2177 */ 
-0x2168, 0x2169, 0x216A, 0x216B, 0x216C, 0x216D, 0x216E, 0x216F }; /* 0x2178-0x217F */
-
-static const u_int16_t upcase_table_7[64] = {
-0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5, 0x24C6, 0x24C7,   /* 0x24C0-0x24C7 */ 
-0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD, 0x24CE, 0x24CF,   /* 0x24C8-0x24CF */ 
-0x24B6, 0x24B7, 0x24B8, 0x24B9, 0x24BA, 0x24BB, 0x24BC, 0x24BD,   /* 0x24D0-0x24D7 */ 
-0x24BE, 0x24BF, 0x24C0, 0x24C1, 0x24C2, 0x24C3, 0x24C4, 0x24C5,   /* 0x24D8-0x24DF */ 
-0x24C6, 0x24C7, 0x24C8, 0x24C9, 0x24CA, 0x24CB, 0x24CC, 0x24CD,   /* 0x24E0-0x24E7 */ 
-0x24CE, 0x24CF, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,   /* 0x24E8-0x24EF */ 
-0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,   /* 0x24F0-0x24F7 */ 
-0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF }; /* 0x24F8-0x24FF */
-
-static const u_int16_t upcase_table_8[64] = {
-0xFF40, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27,   /* 0xFF40-0xFF47 */ 
-0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F,   /* 0xFF48-0xFF4F */ 
-0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37,   /* 0xFF50-0xFF57 */ 
-0xFF38, 0xFF39, 0xFF3A, 0xFF5B, 0xFF5C, 0xFF5D, 0xFF5E, 0xFF5F,   /* 0xFF58-0xFF5F */ 
-0xFF60, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,   /* 0xFF60-0xFF67 */ 
-0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,   /* 0xFF68-0xFF6F */ 
-0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,   /* 0xFF70-0xFF77 */ 
-0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F }; /* 0xFF78-0xFF7F */
-
-
-
-static const u_int16_t lowcase_table_1[64] = {
-0x0040, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,   /* 0x0040-0x0047 */ 
-0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,   /* 0x0048-0x004F */ 
-0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,   /* 0x0050-0x0057 */ 
-0x0078, 0x0079, 0x007A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,   /* 0x0058-0x005F */ 
-0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,   /* 0x0060-0x0067 */ 
-0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,   /* 0x0068-0x006F */ 
-0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,   /* 0x0070-0x0077 */ 
-0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F }; /* 0x0078-0x007F */
-
-static const u_int16_t lowcase_table_2[384] = {
-0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,   /* 0x00C0-0x00C7 */ 
-0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,   /* 0x00C8-0x00CF */ 
-0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00D7,   /* 0x00D0-0x00D7 */ 
-0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00DF,   /* 0x00D8-0x00DF */ 
-0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7,   /* 0x00E0-0x00E7 */ 
-0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF,   /* 0x00E8-0x00EF */ 
-0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7,   /* 0x00F0-0x00F7 */ 
-0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,   /* 0x00F8-0x00FF */ 
-0x0101, 0x0101, 0x0103, 0x0103, 0x0105, 0x0105, 0x0107, 0x0107,   /* 0x0100-0x0107 */ 
-0x0109, 0x0109, 0x010B, 0x010B, 0x010D, 0x010D, 0x010F, 0x010F,   /* 0x0108-0x010F */ 
-0x0111, 0x0111, 0x0113, 0x0113, 0x0115, 0x0115, 0x0117, 0x0117,   /* 0x0110-0x0117 */ 
-0x0119, 0x0119, 0x011B, 0x011B, 0x011D, 0x011D, 0x011F, 0x011F,   /* 0x0118-0x011F */ 
-0x0121, 0x0121, 0x0123, 0x0123, 0x0125, 0x0125, 0x0127, 0x0127,   /* 0x0120-0x0127 */ 
-0x0129, 0x0129, 0x012B, 0x012B, 0x012D, 0x012D, 0x012F, 0x012F,   /* 0x0128-0x012F */ 
-0x0130, 0x0131, 0x0133, 0x0133, 0x0135, 0x0135, 0x0137, 0x0137,   /* 0x0130-0x0137 */ 
-0x0138, 0x013A, 0x013A, 0x013C, 0x013C, 0x013E, 0x013E, 0x0140,   /* 0x0138-0x013F */ 
-0x0140, 0x0142, 0x0142, 0x0144, 0x0144, 0x0146, 0x0146, 0x0148,   /* 0x0140-0x0147 */ 
-0x0148, 0x0149, 0x014B, 0x014B, 0x014D, 0x014D, 0x014F, 0x014F,   /* 0x0148-0x014F */ 
-0x0151, 0x0151, 0x0153, 0x0153, 0x0155, 0x0155, 0x0157, 0x0157,   /* 0x0150-0x0157 */ 
-0x0159, 0x0159, 0x015B, 0x015B, 0x015D, 0x015D, 0x015F, 0x015F,   /* 0x0158-0x015F */ 
-0x0161, 0x0161, 0x0163, 0x0163, 0x0165, 0x0165, 0x0167, 0x0167,   /* 0x0160-0x0167 */ 
-0x0169, 0x0169, 0x016B, 0x016B, 0x016D, 0x016D, 0x016F, 0x016F,   /* 0x0168-0x016F */ 
-0x0171, 0x0171, 0x0173, 0x0173, 0x0175, 0x0175, 0x0177, 0x0177,   /* 0x0170-0x0177 */ 
-0x00FF, 0x017A, 0x017A, 0x017C, 0x017C, 0x017E, 0x017E, 0x017F,   /* 0x0178-0x017F */ 
-0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,   /* 0x0180-0x0187 */ 
-0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,   /* 0x0188-0x018F */ 
-0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,   /* 0x0190-0x0197 */ 
-0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,   /* 0x0198-0x019F */ 
-0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x01A6, 0x01A8,   /* 0x01A0-0x01A7 */ 
-0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,   /* 0x01A8-0x01AF */ 
-0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,   /* 0x01B0-0x01B7 */ 
-0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,   /* 0x01B8-0x01BF */ 
-0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C5, 0x01C6, 0x01C9,   /* 0x01C0-0x01C7 */ 
-0x01C8, 0x01C9, 0x01CC, 0x01CB, 0x01CC, 0x01CE, 0x01CE, 0x01D0,   /* 0x01C8-0x01CF */ 
-0x01D0, 0x01D2, 0x01D2, 0x01D4, 0x01D4, 0x01D6, 0x01D6, 0x01D8,   /* 0x01D0-0x01D7 */ 
-0x01D8, 0x01DA, 0x01DA, 0x01DC, 0x01DC, 0x01DD, 0x01DF, 0x01DF,   /* 0x01D8-0x01DF */ 
-0x01E1, 0x01E1, 0x01E3, 0x01E3, 0x01E5, 0x01E5, 0x01E7, 0x01E7,   /* 0x01E0-0x01E7 */ 
-0x01E9, 0x01E9, 0x01EB, 0x01EB, 0x01ED, 0x01ED, 0x01EF, 0x01EF,   /* 0x01E8-0x01EF */ 
-0x01F0, 0x01F3, 0x01F2, 0x01F3, 0x01F5, 0x01F5, 0x01F6, 0x01F7,   /* 0x01F0-0x01F7 */ 
-0x01F8, 0x01F9, 0x01FB, 0x01FB, 0x01FD, 0x01FD, 0x01FF, 0x01FF,   /* 0x01F8-0x01FF */ 
-0x0201, 0x0201, 0x0203, 0x0203, 0x0205, 0x0205, 0x0207, 0x0207,   /* 0x0200-0x0207 */ 
-0x0209, 0x0209, 0x020B, 0x020B, 0x020D, 0x020D, 0x020F, 0x020F,   /* 0x0208-0x020F */ 
-0x0211, 0x0211, 0x0213, 0x0213, 0x0215, 0x0215, 0x0217, 0x0217,   /* 0x0210-0x0217 */ 
-0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F,   /* 0x0218-0x021F */ 
-0x0220, 0x0221, 0x0222, 0x0223, 0x0224, 0x0225, 0x0226, 0x0227,   /* 0x0220-0x0227 */ 
-0x0228, 0x0229, 0x022A, 0x022B, 0x022C, 0x022D, 0x022E, 0x022F,   /* 0x0228-0x022F */ 
-0x0230, 0x0231, 0x0232, 0x0233, 0x0234, 0x0235, 0x0236, 0x0237,   /* 0x0230-0x0237 */ 
-0x0238, 0x0239, 0x023A, 0x023B, 0x023C, 0x023D, 0x023E, 0x023F }; /* 0x0238-0x023F */
-
-static const u_int16_t lowcase_table_3[512] = {
-0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x03AC, 0x0387,   /* 0x0380-0x0387 */ 
-0x03AD, 0x03AE, 0x03AF, 0x038B, 0x03CC, 0x038D, 0x03CD, 0x03CE,   /* 0x0388-0x038F */ 
-0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,   /* 0x0390-0x0397 */ 
-0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,   /* 0x0398-0x039F */ 
-0x03C0, 0x03C1, 0x03A2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,   /* 0x03A0-0x03A7 */ 
-0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,   /* 0x03A8-0x03AF */ 
-0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,   /* 0x03B0-0x03B7 */ 
-0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,   /* 0x03B8-0x03BF */ 
-0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,   /* 0x03C0-0x03C7 */ 
-0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x03CF,   /* 0x03C8-0x03CF */ 
-0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,   /* 0x03D0-0x03D7 */ 
-0x03D8, 0x03D9, 0x03DA, 0x03DB, 0x03DC, 0x03DD, 0x03DE, 0x03DF,   /* 0x03D8-0x03DF */ 
-0x03E0, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,   /* 0x03E0-0x03E7 */ 
-0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,   /* 0x03E8-0x03EF */ 
-0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7,   /* 0x03F0-0x03F7 */ 
-0x03F8, 0x03F9, 0x03FA, 0x03FB, 0x03FC, 0x03FD, 0x03FE, 0x03FF,   /* 0x03F8-0x03FF */ 
-0x0400, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,   /* 0x0400-0x0407 */ 
-0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x040D, 0x045E, 0x045F,   /* 0x0408-0x040F */ 
-0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,   /* 0x0410-0x0417 */ 
-0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,   /* 0x0418-0x041F */ 
-0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,   /* 0x0420-0x0427 */ 
-0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,   /* 0x0428-0x042F */ 
-0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437,   /* 0x0430-0x0437 */ 
-0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,   /* 0x0438-0x043F */ 
-0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447,   /* 0x0440-0x0447 */ 
-0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,   /* 0x0448-0x044F */ 
-0x0450, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,   /* 0x0450-0x0457 */ 
-0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045D, 0x045E, 0x045F,   /* 0x0458-0x045F */ 
-0x0461, 0x0461, 0x0463, 0x0463, 0x0465, 0x0465, 0x0467, 0x0467,   /* 0x0460-0x0467 */ 
-0x0469, 0x0469, 0x046B, 0x046B, 0x046D, 0x046D, 0x046F, 0x046F,   /* 0x0468-0x046F */ 
-0x0471, 0x0471, 0x0473, 0x0473, 0x0475, 0x0475, 0x0477, 0x0477,   /* 0x0470-0x0477 */ 
-0x0479, 0x0479, 0x047B, 0x047B, 0x047D, 0x047D, 0x047F, 0x047F,   /* 0x0478-0x047F */ 
-0x0481, 0x0481, 0x0482, 0x0483, 0x0484, 0x0485, 0x0486, 0x0487,   /* 0x0480-0x0487 */ 
-0x0488, 0x0489, 0x048A, 0x048B, 0x048C, 0x048D, 0x048E, 0x048F,   /* 0x0488-0x048F */ 
-0x0491, 0x0491, 0x0493, 0x0493, 0x0495, 0x0495, 0x0497, 0x0497,   /* 0x0490-0x0497 */ 
-0x0499, 0x0499, 0x049B, 0x049B, 0x049D, 0x049D, 0x049F, 0x049F,   /* 0x0498-0x049F */ 
-0x04A1, 0x04A1, 0x04A3, 0x04A3, 0x04A5, 0x04A5, 0x04A7, 0x04A7,   /* 0x04A0-0x04A7 */ 
-0x04A9, 0x04A9, 0x04AB, 0x04AB, 0x04AD, 0x04AD, 0x04AF, 0x04AF,   /* 0x04A8-0x04AF */ 
-0x04B1, 0x04B1, 0x04B3, 0x04B3, 0x04B5, 0x04B5, 0x04B7, 0x04B7,   /* 0x04B0-0x04B7 */ 
-0x04B9, 0x04B9, 0x04BB, 0x04BB, 0x04BD, 0x04BD, 0x04BF, 0x04BF,   /* 0x04B8-0x04BF */ 
-0x04C0, 0x04C2, 0x04C2, 0x04C4, 0x04C4, 0x04C5, 0x04C6, 0x04C8,   /* 0x04C0-0x04C7 */ 
-0x04C8, 0x04C9, 0x04CA, 0x04CC, 0x04CC, 0x04CD, 0x04CE, 0x04CF,   /* 0x04C8-0x04CF */ 
-0x04D1, 0x04D1, 0x04D3, 0x04D3, 0x04D5, 0x04D5, 0x04D7, 0x04D7,   /* 0x04D0-0x04D7 */ 
-0x04D9, 0x04D9, 0x04DB, 0x04DB, 0x04DD, 0x04DD, 0x04DF, 0x04DF,   /* 0x04D8-0x04DF */ 
-0x04E1, 0x04E1, 0x04E3, 0x04E3, 0x04E5, 0x04E5, 0x04E7, 0x04E7,   /* 0x04E0-0x04E7 */ 
-0x04E9, 0x04E9, 0x04EB, 0x04EB, 0x04EC, 0x04ED, 0x04EF, 0x04EF,   /* 0x04E8-0x04EF */ 
-0x04F1, 0x04F1, 0x04F3, 0x04F3, 0x04F5, 0x04F5, 0x04F6, 0x04F7,   /* 0x04F0-0x04F7 */ 
-0x04F9, 0x04F9, 0x04FA, 0x04FB, 0x04FC, 0x04FD, 0x04FE, 0x04FF,   /* 0x04F8-0x04FF */ 
-0x0500, 0x0501, 0x0502, 0x0503, 0x0504, 0x0505, 0x0506, 0x0507,   /* 0x0500-0x0507 */ 
-0x0508, 0x0509, 0x050A, 0x050B, 0x050C, 0x050D, 0x050E, 0x050F,   /* 0x0508-0x050F */ 
-0x0510, 0x0511, 0x0512, 0x0513, 0x0514, 0x0515, 0x0516, 0x0517,   /* 0x0510-0x0517 */ 
-0x0518, 0x0519, 0x051A, 0x051B, 0x051C, 0x051D, 0x051E, 0x051F,   /* 0x0518-0x051F */ 
-0x0520, 0x0521, 0x0522, 0x0523, 0x0524, 0x0525, 0x0526, 0x0527,   /* 0x0520-0x0527 */ 
-0x0528, 0x0529, 0x052A, 0x052B, 0x052C, 0x052D, 0x052E, 0x052F,   /* 0x0528-0x052F */ 
-0x0530, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,   /* 0x0530-0x0537 */ 
-0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,   /* 0x0538-0x053F */ 
-0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,   /* 0x0540-0x0547 */ 
-0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F,   /* 0x0548-0x054F */ 
-0x0580, 0x0581, 0x0582, 0x0583, 0x0584, 0x0585, 0x0586, 0x0557,   /* 0x0550-0x0557 */ 
-0x0558, 0x0559, 0x055A, 0x055B, 0x055C, 0x055D, 0x055E, 0x055F,   /* 0x0558-0x055F */ 
-0x0560, 0x0561, 0x0562, 0x0563, 0x0564, 0x0565, 0x0566, 0x0567,   /* 0x0560-0x0567 */ 
-0x0568, 0x0569, 0x056A, 0x056B, 0x056C, 0x056D, 0x056E, 0x056F,   /* 0x0568-0x056F */ 
-0x0570, 0x0571, 0x0572, 0x0573, 0x0574, 0x0575, 0x0576, 0x0577,   /* 0x0570-0x0577 */ 
-0x0578, 0x0579, 0x057A, 0x057B, 0x057C, 0x057D, 0x057E, 0x057F }; /* 0x0578-0x057F */
-
-static const u_int16_t lowcase_table_4[512] = {
-0x1E01, 0x1E01, 0x1E03, 0x1E03, 0x1E05, 0x1E05, 0x1E07, 0x1E07,   /* 0x1E00-0x1E07 */ 
-0x1E09, 0x1E09, 0x1E0B, 0x1E0B, 0x1E0D, 0x1E0D, 0x1E0F, 0x1E0F,   /* 0x1E08-0x1E0F */ 
-0x1E11, 0x1E11, 0x1E13, 0x1E13, 0x1E15, 0x1E15, 0x1E17, 0x1E17,   /* 0x1E10-0x1E17 */ 
-0x1E19, 0x1E19, 0x1E1B, 0x1E1B, 0x1E1D, 0x1E1D, 0x1E1F, 0x1E1F,   /* 0x1E18-0x1E1F */ 
-0x1E21, 0x1E21, 0x1E23, 0x1E23, 0x1E25, 0x1E25, 0x1E27, 0x1E27,   /* 0x1E20-0x1E27 */ 
-0x1E29, 0x1E29, 0x1E2B, 0x1E2B, 0x1E2D, 0x1E2D, 0x1E2F, 0x1E2F,   /* 0x1E28-0x1E2F */ 
-0x1E31, 0x1E31, 0x1E33, 0x1E33, 0x1E35, 0x1E35, 0x1E37, 0x1E37,   /* 0x1E30-0x1E37 */ 
-0x1E39, 0x1E39, 0x1E3B, 0x1E3B, 0x1E3D, 0x1E3D, 0x1E3F, 0x1E3F,   /* 0x1E38-0x1E3F */ 
-0x1E41, 0x1E41, 0x1E43, 0x1E43, 0x1E45, 0x1E45, 0x1E47, 0x1E47,   /* 0x1E40-0x1E47 */ 
-0x1E49, 0x1E49, 0x1E4B, 0x1E4B, 0x1E4D, 0x1E4D, 0x1E4F, 0x1E4F,   /* 0x1E48-0x1E4F */ 
-0x1E51, 0x1E51, 0x1E53, 0x1E53, 0x1E55, 0x1E55, 0x1E57, 0x1E57,   /* 0x1E50-0x1E57 */ 
-0x1E59, 0x1E59, 0x1E5B, 0x1E5B, 0x1E5D, 0x1E5D, 0x1E5F, 0x1E5F,   /* 0x1E58-0x1E5F */ 
-0x1E61, 0x1E61, 0x1E63, 0x1E63, 0x1E65, 0x1E65, 0x1E67, 0x1E67,   /* 0x1E60-0x1E67 */ 
-0x1E69, 0x1E69, 0x1E6B, 0x1E6B, 0x1E6D, 0x1E6D, 0x1E6F, 0x1E6F,   /* 0x1E68-0x1E6F */ 
-0x1E71, 0x1E71, 0x1E73, 0x1E73, 0x1E75, 0x1E75, 0x1E77, 0x1E77,   /* 0x1E70-0x1E77 */ 
-0x1E79, 0x1E79, 0x1E7B, 0x1E7B, 0x1E7D, 0x1E7D, 0x1E7F, 0x1E7F,   /* 0x1E78-0x1E7F */ 
-0x1E81, 0x1E81, 0x1E83, 0x1E83, 0x1E85, 0x1E85, 0x1E87, 0x1E87,   /* 0x1E80-0x1E87 */ 
-0x1E89, 0x1E89, 0x1E8B, 0x1E8B, 0x1E8D, 0x1E8D, 0x1E8F, 0x1E8F,   /* 0x1E88-0x1E8F */ 
-0x1E91, 0x1E91, 0x1E93, 0x1E93, 0x1E95, 0x1E95, 0x1E96, 0x1E97,   /* 0x1E90-0x1E97 */ 
-0x1E98, 0x1E99, 0x1E9A, 0x1E9B, 0x1E9C, 0x1E9D, 0x1E9E, 0x1E9F,   /* 0x1E98-0x1E9F */ 
-0x1EA1, 0x1EA1, 0x1EA3, 0x1EA3, 0x1EA5, 0x1EA5, 0x1EA7, 0x1EA7,   /* 0x1EA0-0x1EA7 */ 
-0x1EA9, 0x1EA9, 0x1EAB, 0x1EAB, 0x1EAD, 0x1EAD, 0x1EAF, 0x1EAF,   /* 0x1EA8-0x1EAF */ 
-0x1EB1, 0x1EB1, 0x1EB3, 0x1EB3, 0x1EB5, 0x1EB5, 0x1EB7, 0x1EB7,   /* 0x1EB0-0x1EB7 */ 
-0x1EB9, 0x1EB9, 0x1EBB, 0x1EBB, 0x1EBD, 0x1EBD, 0x1EBF, 0x1EBF,   /* 0x1EB8-0x1EBF */ 
-0x1EC1, 0x1EC1, 0x1EC3, 0x1EC3, 0x1EC5, 0x1EC5, 0x1EC7, 0x1EC7,   /* 0x1EC0-0x1EC7 */ 
-0x1EC9, 0x1EC9, 0x1ECB, 0x1ECB, 0x1ECD, 0x1ECD, 0x1ECF, 0x1ECF,   /* 0x1EC8-0x1ECF */ 
-0x1ED1, 0x1ED1, 0x1ED3, 0x1ED3, 0x1ED5, 0x1ED5, 0x1ED7, 0x1ED7,   /* 0x1ED0-0x1ED7 */ 
-0x1ED9, 0x1ED9, 0x1EDB, 0x1EDB, 0x1EDD, 0x1EDD, 0x1EDF, 0x1EDF,   /* 0x1ED8-0x1EDF */ 
-0x1EE1, 0x1EE1, 0x1EE3, 0x1EE3, 0x1EE5, 0x1EE5, 0x1EE7, 0x1EE7,   /* 0x1EE0-0x1EE7 */ 
-0x1EE9, 0x1EE9, 0x1EEB, 0x1EEB, 0x1EED, 0x1EED, 0x1EEF, 0x1EEF,   /* 0x1EE8-0x1EEF */ 
-0x1EF1, 0x1EF1, 0x1EF3, 0x1EF3, 0x1EF5, 0x1EF5, 0x1EF7, 0x1EF7,   /* 0x1EF0-0x1EF7 */ 
-0x1EF9, 0x1EF9, 0x1EFA, 0x1EFB, 0x1EFC, 0x1EFD, 0x1EFE, 0x1EFF,   /* 0x1EF8-0x1EFF */ 
-0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,   /* 0x1F00-0x1F07 */ 
-0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,   /* 0x1F08-0x1F0F */ 
-0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F16, 0x1F17,   /* 0x1F10-0x1F17 */ 
-0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x1F1E, 0x1F1F,   /* 0x1F18-0x1F1F */ 
-0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,   /* 0x1F20-0x1F27 */ 
-0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,   /* 0x1F28-0x1F2F */ 
-0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,   /* 0x1F30-0x1F37 */ 
-0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,   /* 0x1F38-0x1F3F */ 
-0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F46, 0x1F47,   /* 0x1F40-0x1F47 */ 
-0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x1F4E, 0x1F4F,   /* 0x1F48-0x1F4F */ 
-0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,   /* 0x1F50-0x1F57 */ 
-0x1F58, 0x1F51, 0x1F5A, 0x1F53, 0x1F5C, 0x1F55, 0x1F5E, 0x1F57,   /* 0x1F58-0x1F5F */ 
-0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,   /* 0x1F60-0x1F67 */ 
-0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,   /* 0x1F68-0x1F6F */ 
-0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,   /* 0x1F70-0x1F77 */ 
-0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x1F7E, 0x1F7F,   /* 0x1F78-0x1F7F */ 
-0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,   /* 0x1F80-0x1F87 */ 
-0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,   /* 0x1F88-0x1F8F */ 
-0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,   /* 0x1F90-0x1F97 */ 
-0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,   /* 0x1F98-0x1F9F */ 
-0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,   /* 0x1FA0-0x1FA7 */ 
-0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,   /* 0x1FA8-0x1FAF */ 
-0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x1FB5, 0x1FB6, 0x1FB7,   /* 0x1FB0-0x1FB7 */ 
-0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FBC, 0x1FBD, 0x1FBE, 0x1FBF,   /* 0x1FB8-0x1FBF */ 
-0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x1FC5, 0x1FC6, 0x1FC7,   /* 0x1FC0-0x1FC7 */ 
-0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,   /* 0x1FC8-0x1FCF */ 
-0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x1FD4, 0x1FD5, 0x1FD6, 0x1FD7,   /* 0x1FD0-0x1FD7 */ 
-0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x1FDC, 0x1FDD, 0x1FDE, 0x1FDF,   /* 0x1FD8-0x1FDF */ 
-0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,   /* 0x1FE0-0x1FE7 */ 
-0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,   /* 0x1FE8-0x1FEF */ 
-0x1FF0, 0x1FF1, 0x1FF2, 0x1FF3, 0x1FF4, 0x1FF5, 0x1FF6, 0x1FF7,   /* 0x1FF0-0x1FF7 */ 
-0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FFC, 0x1FFD, 0x1FFE, 0x1FFF }; /* 0x1FF8-0x1FFF */
-
-static const u_int16_t lowcase_table_5[64] = {
-0x2140, 0x2141, 0x2142, 0x2143, 0x2144, 0x2145, 0x2146, 0x2147,   /* 0x2140-0x2147 */ 
-0x2148, 0x2149, 0x214A, 0x214B, 0x214C, 0x214D, 0x214E, 0x214F,   /* 0x2148-0x214F */ 
-0x2150, 0x2151, 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157,   /* 0x2150-0x2157 */ 
-0x2158, 0x2159, 0x215A, 0x215B, 0x215C, 0x215D, 0x215E, 0x215F,   /* 0x2158-0x215F */ 
-0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,   /* 0x2160-0x2167 */ 
-0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F,   /* 0x2168-0x216F */ 
-0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, 0x2177,   /* 0x2170-0x2177 */ 
-0x2178, 0x2179, 0x217A, 0x217B, 0x217C, 0x217D, 0x217E, 0x217F }; /* 0x2178-0x217F */
-
-static const u_int16_t lowcase_table_6[128] = {
-0x2480, 0x2481, 0x2482, 0x2483, 0x2484, 0x2485, 0x2486, 0x2487,   /* 0x2480-0x2487 */ 
-0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, 0x248E, 0x248F,   /* 0x2488-0x248F */ 
-0x2490, 0x2491, 0x2492, 0x2493, 0x2494, 0x2495, 0x2496, 0x2497,   /* 0x2490-0x2497 */ 
-0x2498, 0x2499, 0x249A, 0x249B, 0x249C, 0x249D, 0x249E, 0x249F,   /* 0x2498-0x249F */ 
-0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, 0x24A7,   /* 0x24A0-0x24A7 */ 
-0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, 0x24AF,   /* 0x24A8-0x24AF */ 
-0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0x24D0, 0x24D1,   /* 0x24B0-0x24B7 */ 
-0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7, 0x24D8, 0x24D9,   /* 0x24B8-0x24BF */ 
-0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF, 0x24E0, 0x24E1,   /* 0x24C0-0x24C7 */ 
-0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7, 0x24E8, 0x24E9,   /* 0x24C8-0x24CF */ 
-0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, 0x24D7,   /* 0x24D0-0x24D7 */ 
-0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, 0x24DF,   /* 0x24D8-0x24DF */ 
-0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, 0x24E7,   /* 0x24E0-0x24E7 */ 
-0x24E8, 0x24E9, 0x24EA, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF,   /* 0x24E8-0x24EF */ 
-0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x24F5, 0x24F6, 0x24F7,   /* 0x24F0-0x24F7 */ 
-0x24F8, 0x24F9, 0x24FA, 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x24FF }; /* 0x24F8-0x24FF */
-
-static const u_int16_t lowcase_table_7[64] = {
-0xFF00, 0xFF01, 0xFF02, 0xFF03, 0xFF04, 0xFF05, 0xFF06, 0xFF07,   /* 0xFF00-0xFF07 */ 
-0xFF08, 0xFF09, 0xFF0A, 0xFF0B, 0xFF0C, 0xFF0D, 0xFF0E, 0xFF0F,   /* 0xFF08-0xFF0F */ 
-0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17,   /* 0xFF10-0xFF17 */ 
-0xFF18, 0xFF19, 0xFF1A, 0xFF1B, 0xFF1C, 0xFF1D, 0xFF1E, 0xFF1F,   /* 0xFF18-0xFF1F */ 
-0xFF20, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47,   /* 0xFF20-0xFF27 */ 
-0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F,   /* 0xFF28-0xFF2F */ 
-0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57,   /* 0xFF30-0xFF37 */ 
-0xFF58, 0xFF59, 0xFF5A, 0xFF3B, 0xFF3C, 0xFF3D, 0xFF3E, 0xFF3F }; /* 0xFF38-0xFF3F */
-
diff --git a/libatalk/unicode/utf16_case.c b/libatalk/unicode/utf16_case.c
new file mode 100644 (file)
index 0000000..5b23ee3
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+DO NOT EDIT BY HAND!!!
+
+This file is generated by
+ contrib/misc/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
+
+UnicodeData.txt is got from
+http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
+*/
+
+#include <netatalk/endian.h>
+#include <atalk/unicode.h>
+#include "utf16_casetable.h"
+
+/*******************************************************************
+ Convert a wide character to upper case.
+*******************************************************************/
+ucs2_t toupper_w(ucs2_t val)
+{
+    if ( val <= 0x02BF)
+        return upper_table_1[val];
+
+    if ( val >= 0x0340 && val <= 0x05BF)
+        return upper_table_2[val-0x0340];
+
+    if ( val >= 0x1D40 && val <= 0x1D7F)
+        return upper_table_3[val-0x1D40];
+
+    if ( val >= 0x1E00 && val <= 0x1FFF)
+        return upper_table_4[val-0x1E00];
+
+    if ( val >= 0x2140 && val <= 0x21BF)
+        return upper_table_5[val-0x2140];
+
+    if ( val >= 0x24C0 && val <= 0x24FF)
+        return upper_table_6[val-0x24C0];
+
+    if ( val >= 0x2C00 && val <= 0x2D3F)
+        return upper_table_7[val-0x2C00];
+
+    if ( val >= 0xA640 && val <= 0xA6BF)
+        return upper_table_8[val-0xA640];
+
+    if ( val >= 0xA700 && val <= 0xA7BF)
+        return upper_table_9[val-0xA700];
+
+    if ( val >= 0xFF40 && val <= 0xFF7F)
+        return upper_table_10[val-0xFF40];
+
+       return (val);
+}
+
+/*******************************************************************
+ Convert a surrogate pair to upper case.
+*******************************************************************/
+u_int32_t toupper_sp(u_int32_t val)
+{
+    if ( val >= 0xD801DC00 && val <= 0xD801DC7F)
+        return upper_table_sp_1[val-0xD801DC00];
+
+       return (val);
+}
+
+/*******************************************************************
+ Convert a wide character to lower case.
+*******************************************************************/
+ucs2_t tolower_w(ucs2_t val)
+{
+    if ( val <= 0x007F)
+        return lower_table_1[val];
+
+    if ( val >= 0x00C0 && val <= 0x027F)
+        return lower_table_2[val-0x00C0];
+
+    if ( val >= 0x0340 && val <= 0x057F)
+        return lower_table_3[val-0x0340];
+
+    if ( val >= 0x1080 && val <= 0x10FF)
+        return lower_table_4[val-0x1080];
+
+    if ( val >= 0x1E00 && val <= 0x1FFF)
+        return lower_table_5[val-0x1E00];
+
+    if ( val >= 0x2100 && val <= 0x21BF)
+        return lower_table_6[val-0x2100];
+
+    if ( val >= 0x2480 && val <= 0x24FF)
+        return lower_table_7[val-0x2480];
+
+    if ( val >= 0x2C00 && val <= 0x2CFF)
+        return lower_table_8[val-0x2C00];
+
+    if ( val >= 0xA640 && val <= 0xA6BF)
+        return lower_table_9[val-0xA640];
+
+    if ( val >= 0xA700 && val <= 0xA7BF)
+        return lower_table_10[val-0xA700];
+
+    if ( val >= 0xFF00 && val <= 0xFF3F)
+        return lower_table_11[val-0xFF00];
+
+       return (val);
+}
+
+/*******************************************************************
+ Convert a surrogate pair to lower case.
+*******************************************************************/
+u_int32_t tolower_sp(u_int32_t val)
+{
+    if ( val >= 0xD801DC00 && val <= 0xD801DC3F)
+        return lower_table_sp_1[val-0xD801DC00];
+
+       return (val);
+}
+
+/* EOF */
diff --git a/libatalk/unicode/utf16_casetable.h b/libatalk/unicode/utf16_casetable.h
new file mode 100644 (file)
index 0000000..9a1366e
--- /dev/null
@@ -0,0 +1,5840 @@
+/*
+DO NOT EDIT BY HAND!!!
+
+This file is generated by
+ contrib/misc/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
+
+UnicodeData.txt is got from
+http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
+*/
+
+static const u_int16_t upper_table_1[704] = {
+  0x0000, /*U+0000*/ /**/
+  0x0001, /*U+0001*/ /**/
+  0x0002, /*U+0002*/ /**/
+  0x0003, /*U+0003*/ /**/
+  0x0004, /*U+0004*/ /**/
+  0x0005, /*U+0005*/ /**/
+  0x0006, /*U+0006*/ /**/
+  0x0007, /*U+0007*/ /**/
+  0x0008, /*U+0008*/ /**/
+  0x0009, /*U+0009*/ /**/
+  0x000A, /*U+000A*/ /**/
+  0x000B, /*U+000B*/ /**/
+  0x000C, /*U+000C*/ /**/
+  0x000D, /*U+000D*/ /**/
+  0x000E, /*U+000E*/ /**/
+  0x000F, /*U+000F*/ /**/
+  0x0010, /*U+0010*/ /**/
+  0x0011, /*U+0011*/ /**/
+  0x0012, /*U+0012*/ /**/
+  0x0013, /*U+0013*/ /**/
+  0x0014, /*U+0014*/ /**/
+  0x0015, /*U+0015*/ /**/
+  0x0016, /*U+0016*/ /**/
+  0x0017, /*U+0017*/ /**/
+  0x0018, /*U+0018*/ /**/
+  0x0019, /*U+0019*/ /**/
+  0x001A, /*U+001A*/ /**/
+  0x001B, /*U+001B*/ /**/
+  0x001C, /*U+001C*/ /**/
+  0x001D, /*U+001D*/ /**/
+  0x001E, /*U+001E*/ /**/
+  0x001F, /*U+001F*/ /**/
+  0x0020, /*U+0020*/ /**/
+  0x0021, /*U+0021*/ /**/
+  0x0022, /*U+0022*/ /**/
+  0x0023, /*U+0023*/ /**/
+  0x0024, /*U+0024*/ /**/
+  0x0025, /*U+0025*/ /**/
+  0x0026, /*U+0026*/ /**/
+  0x0027, /*U+0027*/ /**/
+  0x0028, /*U+0028*/ /**/
+  0x0029, /*U+0029*/ /**/
+  0x002A, /*U+002A*/ /**/
+  0x002B, /*U+002B*/ /**/
+  0x002C, /*U+002C*/ /**/
+  0x002D, /*U+002D*/ /**/
+  0x002E, /*U+002E*/ /**/
+  0x002F, /*U+002F*/ /**/
+  0x0030, /*U+0030*/ /**/
+  0x0031, /*U+0031*/ /**/
+  0x0032, /*U+0032*/ /**/
+  0x0033, /*U+0033*/ /**/
+  0x0034, /*U+0034*/ /**/
+  0x0035, /*U+0035*/ /**/
+  0x0036, /*U+0036*/ /**/
+  0x0037, /*U+0037*/ /**/
+  0x0038, /*U+0038*/ /**/
+  0x0039, /*U+0039*/ /**/
+  0x003A, /*U+003A*/ /**/
+  0x003B, /*U+003B*/ /**/
+  0x003C, /*U+003C*/ /**/
+  0x003D, /*U+003D*/ /**/
+  0x003E, /*U+003E*/ /**/
+  0x003F, /*U+003F*/ /**/
+  0x0040, /*U+0040*/ /**/
+  0x0041, /*U+0041*/ /**/
+  0x0042, /*U+0042*/ /**/
+  0x0043, /*U+0043*/ /**/
+  0x0044, /*U+0044*/ /**/
+  0x0045, /*U+0045*/ /**/
+  0x0046, /*U+0046*/ /**/
+  0x0047, /*U+0047*/ /**/
+  0x0048, /*U+0048*/ /**/
+  0x0049, /*U+0049*/ /**/
+  0x004A, /*U+004A*/ /**/
+  0x004B, /*U+004B*/ /**/
+  0x004C, /*U+004C*/ /**/
+  0x004D, /*U+004D*/ /**/
+  0x004E, /*U+004E*/ /**/
+  0x004F, /*U+004F*/ /**/
+  0x0050, /*U+0050*/ /**/
+  0x0051, /*U+0051*/ /**/
+  0x0052, /*U+0052*/ /**/
+  0x0053, /*U+0053*/ /**/
+  0x0054, /*U+0054*/ /**/
+  0x0055, /*U+0055*/ /**/
+  0x0056, /*U+0056*/ /**/
+  0x0057, /*U+0057*/ /**/
+  0x0058, /*U+0058*/ /**/
+  0x0059, /*U+0059*/ /**/
+  0x005A, /*U+005A*/ /**/
+  0x005B, /*U+005B*/ /**/
+  0x005C, /*U+005C*/ /**/
+  0x005D, /*U+005D*/ /**/
+  0x005E, /*U+005E*/ /**/
+  0x005F, /*U+005F*/ /**/
+  0x0060, /*U+0060*/ /**/
+  0x0041, /*U+0061*/ /*LATIN SMALL LETTER A*/
+  0x0042, /*U+0062*/ /*LATIN SMALL LETTER B*/
+  0x0043, /*U+0063*/ /*LATIN SMALL LETTER C*/
+  0x0044, /*U+0064*/ /*LATIN SMALL LETTER D*/
+  0x0045, /*U+0065*/ /*LATIN SMALL LETTER E*/
+  0x0046, /*U+0066*/ /*LATIN SMALL LETTER F*/
+  0x0047, /*U+0067*/ /*LATIN SMALL LETTER G*/
+  0x0048, /*U+0068*/ /*LATIN SMALL LETTER H*/
+  0x0049, /*U+0069*/ /*LATIN SMALL LETTER I*/
+  0x004A, /*U+006A*/ /*LATIN SMALL LETTER J*/
+  0x004B, /*U+006B*/ /*LATIN SMALL LETTER K*/
+  0x004C, /*U+006C*/ /*LATIN SMALL LETTER L*/
+  0x004D, /*U+006D*/ /*LATIN SMALL LETTER M*/
+  0x004E, /*U+006E*/ /*LATIN SMALL LETTER N*/
+  0x004F, /*U+006F*/ /*LATIN SMALL LETTER O*/
+  0x0050, /*U+0070*/ /*LATIN SMALL LETTER P*/
+  0x0051, /*U+0071*/ /*LATIN SMALL LETTER Q*/
+  0x0052, /*U+0072*/ /*LATIN SMALL LETTER R*/
+  0x0053, /*U+0073*/ /*LATIN SMALL LETTER S*/
+  0x0054, /*U+0074*/ /*LATIN SMALL LETTER T*/
+  0x0055, /*U+0075*/ /*LATIN SMALL LETTER U*/
+  0x0056, /*U+0076*/ /*LATIN SMALL LETTER V*/
+  0x0057, /*U+0077*/ /*LATIN SMALL LETTER W*/
+  0x0058, /*U+0078*/ /*LATIN SMALL LETTER X*/
+  0x0059, /*U+0079*/ /*LATIN SMALL LETTER Y*/
+  0x005A, /*U+007A*/ /*LATIN SMALL LETTER Z*/
+  0x007B, /*U+007B*/ /**/
+  0x007C, /*U+007C*/ /**/
+  0x007D, /*U+007D*/ /**/
+  0x007E, /*U+007E*/ /**/
+  0x007F, /*U+007F*/ /**/
+  0x0080, /*U+0080*/ /**/
+  0x0081, /*U+0081*/ /**/
+  0x0082, /*U+0082*/ /**/
+  0x0083, /*U+0083*/ /**/
+  0x0084, /*U+0084*/ /**/
+  0x0085, /*U+0085*/ /**/
+  0x0086, /*U+0086*/ /**/
+  0x0087, /*U+0087*/ /**/
+  0x0088, /*U+0088*/ /**/
+  0x0089, /*U+0089*/ /**/
+  0x008A, /*U+008A*/ /**/
+  0x008B, /*U+008B*/ /**/
+  0x008C, /*U+008C*/ /**/
+  0x008D, /*U+008D*/ /**/
+  0x008E, /*U+008E*/ /**/
+  0x008F, /*U+008F*/ /**/
+  0x0090, /*U+0090*/ /**/
+  0x0091, /*U+0091*/ /**/
+  0x0092, /*U+0092*/ /**/
+  0x0093, /*U+0093*/ /**/
+  0x0094, /*U+0094*/ /**/
+  0x0095, /*U+0095*/ /**/
+  0x0096, /*U+0096*/ /**/
+  0x0097, /*U+0097*/ /**/
+  0x0098, /*U+0098*/ /**/
+  0x0099, /*U+0099*/ /**/
+  0x009A, /*U+009A*/ /**/
+  0x009B, /*U+009B*/ /**/
+  0x009C, /*U+009C*/ /**/
+  0x009D, /*U+009D*/ /**/
+  0x009E, /*U+009E*/ /**/
+  0x009F, /*U+009F*/ /**/
+  0x00A0, /*U+00A0*/ /**/
+  0x00A1, /*U+00A1*/ /**/
+  0x00A2, /*U+00A2*/ /**/
+  0x00A3, /*U+00A3*/ /**/
+  0x00A4, /*U+00A4*/ /**/
+  0x00A5, /*U+00A5*/ /**/
+  0x00A6, /*U+00A6*/ /**/
+  0x00A7, /*U+00A7*/ /**/
+  0x00A8, /*U+00A8*/ /**/
+  0x00A9, /*U+00A9*/ /**/
+  0x00AA, /*U+00AA*/ /**/
+  0x00AB, /*U+00AB*/ /**/
+  0x00AC, /*U+00AC*/ /**/
+  0x00AD, /*U+00AD*/ /**/
+  0x00AE, /*U+00AE*/ /**/
+  0x00AF, /*U+00AF*/ /**/
+  0x00B0, /*U+00B0*/ /**/
+  0x00B1, /*U+00B1*/ /**/
+  0x00B2, /*U+00B2*/ /**/
+  0x00B3, /*U+00B3*/ /**/
+  0x00B4, /*U+00B4*/ /**/
+  0x039C, /*U+00B5*/ /*MICRO SIGN*/
+  0x00B6, /*U+00B6*/ /**/
+  0x00B7, /*U+00B7*/ /**/
+  0x00B8, /*U+00B8*/ /**/
+  0x00B9, /*U+00B9*/ /**/
+  0x00BA, /*U+00BA*/ /**/
+  0x00BB, /*U+00BB*/ /**/
+  0x00BC, /*U+00BC*/ /**/
+  0x00BD, /*U+00BD*/ /**/
+  0x00BE, /*U+00BE*/ /**/
+  0x00BF, /*U+00BF*/ /**/
+  0x00C0, /*U+00C0*/ /**/
+  0x00C1, /*U+00C1*/ /**/
+  0x00C2, /*U+00C2*/ /**/
+  0x00C3, /*U+00C3*/ /**/
+  0x00C4, /*U+00C4*/ /**/
+  0x00C5, /*U+00C5*/ /**/
+  0x00C6, /*U+00C6*/ /**/
+  0x00C7, /*U+00C7*/ /**/
+  0x00C8, /*U+00C8*/ /**/
+  0x00C9, /*U+00C9*/ /**/
+  0x00CA, /*U+00CA*/ /**/
+  0x00CB, /*U+00CB*/ /**/
+  0x00CC, /*U+00CC*/ /**/
+  0x00CD, /*U+00CD*/ /**/
+  0x00CE, /*U+00CE*/ /**/
+  0x00CF, /*U+00CF*/ /**/
+  0x00D0, /*U+00D0*/ /**/
+  0x00D1, /*U+00D1*/ /**/
+  0x00D2, /*U+00D2*/ /**/
+  0x00D3, /*U+00D3*/ /**/
+  0x00D4, /*U+00D4*/ /**/
+  0x00D5, /*U+00D5*/ /**/
+  0x00D6, /*U+00D6*/ /**/
+  0x00D7, /*U+00D7*/ /**/
+  0x00D8, /*U+00D8*/ /**/
+  0x00D9, /*U+00D9*/ /**/
+  0x00DA, /*U+00DA*/ /**/
+  0x00DB, /*U+00DB*/ /**/
+  0x00DC, /*U+00DC*/ /**/
+  0x00DD, /*U+00DD*/ /**/
+  0x00DE, /*U+00DE*/ /**/
+  0x00DF, /*U+00DF*/ /**/
+  0x00C0, /*U+00E0*/ /*LATIN SMALL LETTER A WITH GRAVE*/
+  0x00C1, /*U+00E1*/ /*LATIN SMALL LETTER A WITH ACUTE*/
+  0x00C2, /*U+00E2*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX*/
+  0x00C3, /*U+00E3*/ /*LATIN SMALL LETTER A WITH TILDE*/
+  0x00C4, /*U+00E4*/ /*LATIN SMALL LETTER A WITH DIAERESIS*/
+  0x00C5, /*U+00E5*/ /*LATIN SMALL LETTER A WITH RING ABOVE*/
+  0x00C6, /*U+00E6*/ /*LATIN SMALL LETTER AE*/
+  0x00C7, /*U+00E7*/ /*LATIN SMALL LETTER C WITH CEDILLA*/
+  0x00C8, /*U+00E8*/ /*LATIN SMALL LETTER E WITH GRAVE*/
+  0x00C9, /*U+00E9*/ /*LATIN SMALL LETTER E WITH ACUTE*/
+  0x00CA, /*U+00EA*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX*/
+  0x00CB, /*U+00EB*/ /*LATIN SMALL LETTER E WITH DIAERESIS*/
+  0x00CC, /*U+00EC*/ /*LATIN SMALL LETTER I WITH GRAVE*/
+  0x00CD, /*U+00ED*/ /*LATIN SMALL LETTER I WITH ACUTE*/
+  0x00CE, /*U+00EE*/ /*LATIN SMALL LETTER I WITH CIRCUMFLEX*/
+  0x00CF, /*U+00EF*/ /*LATIN SMALL LETTER I WITH DIAERESIS*/
+  0x00D0, /*U+00F0*/ /*LATIN SMALL LETTER ETH*/
+  0x00D1, /*U+00F1*/ /*LATIN SMALL LETTER N WITH TILDE*/
+  0x00D2, /*U+00F2*/ /*LATIN SMALL LETTER O WITH GRAVE*/
+  0x00D3, /*U+00F3*/ /*LATIN SMALL LETTER O WITH ACUTE*/
+  0x00D4, /*U+00F4*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX*/
+  0x00D5, /*U+00F5*/ /*LATIN SMALL LETTER O WITH TILDE*/
+  0x00D6, /*U+00F6*/ /*LATIN SMALL LETTER O WITH DIAERESIS*/
+  0x00F7, /*U+00F7*/ /**/
+  0x00D8, /*U+00F8*/ /*LATIN SMALL LETTER O WITH STROKE*/
+  0x00D9, /*U+00F9*/ /*LATIN SMALL LETTER U WITH GRAVE*/
+  0x00DA, /*U+00FA*/ /*LATIN SMALL LETTER U WITH ACUTE*/
+  0x00DB, /*U+00FB*/ /*LATIN SMALL LETTER U WITH CIRCUMFLEX*/
+  0x00DC, /*U+00FC*/ /*LATIN SMALL LETTER U WITH DIAERESIS*/
+  0x00DD, /*U+00FD*/ /*LATIN SMALL LETTER Y WITH ACUTE*/
+  0x00DE, /*U+00FE*/ /*LATIN SMALL LETTER THORN*/
+  0x0178, /*U+00FF*/ /*LATIN SMALL LETTER Y WITH DIAERESIS*/
+  0x0100, /*U+0100*/ /**/
+  0x0100, /*U+0101*/ /*LATIN SMALL LETTER A WITH MACRON*/
+  0x0102, /*U+0102*/ /**/
+  0x0102, /*U+0103*/ /*LATIN SMALL LETTER A WITH BREVE*/
+  0x0104, /*U+0104*/ /**/
+  0x0104, /*U+0105*/ /*LATIN SMALL LETTER A WITH OGONEK*/
+  0x0106, /*U+0106*/ /**/
+  0x0106, /*U+0107*/ /*LATIN SMALL LETTER C WITH ACUTE*/
+  0x0108, /*U+0108*/ /**/
+  0x0108, /*U+0109*/ /*LATIN SMALL LETTER C WITH CIRCUMFLEX*/
+  0x010A, /*U+010A*/ /**/
+  0x010A, /*U+010B*/ /*LATIN SMALL LETTER C WITH DOT ABOVE*/
+  0x010C, /*U+010C*/ /**/
+  0x010C, /*U+010D*/ /*LATIN SMALL LETTER C WITH CARON*/
+  0x010E, /*U+010E*/ /**/
+  0x010E, /*U+010F*/ /*LATIN SMALL LETTER D WITH CARON*/
+  0x0110, /*U+0110*/ /**/
+  0x0110, /*U+0111*/ /*LATIN SMALL LETTER D WITH STROKE*/
+  0x0112, /*U+0112*/ /**/
+  0x0112, /*U+0113*/ /*LATIN SMALL LETTER E WITH MACRON*/
+  0x0114, /*U+0114*/ /**/
+  0x0114, /*U+0115*/ /*LATIN SMALL LETTER E WITH BREVE*/
+  0x0116, /*U+0116*/ /**/
+  0x0116, /*U+0117*/ /*LATIN SMALL LETTER E WITH DOT ABOVE*/
+  0x0118, /*U+0118*/ /**/
+  0x0118, /*U+0119*/ /*LATIN SMALL LETTER E WITH OGONEK*/
+  0x011A, /*U+011A*/ /**/
+  0x011A, /*U+011B*/ /*LATIN SMALL LETTER E WITH CARON*/
+  0x011C, /*U+011C*/ /**/
+  0x011C, /*U+011D*/ /*LATIN SMALL LETTER G WITH CIRCUMFLEX*/
+  0x011E, /*U+011E*/ /**/
+  0x011E, /*U+011F*/ /*LATIN SMALL LETTER G WITH BREVE*/
+  0x0120, /*U+0120*/ /**/
+  0x0120, /*U+0121*/ /*LATIN SMALL LETTER G WITH DOT ABOVE*/
+  0x0122, /*U+0122*/ /**/
+  0x0122, /*U+0123*/ /*LATIN SMALL LETTER G WITH CEDILLA*/
+  0x0124, /*U+0124*/ /**/
+  0x0124, /*U+0125*/ /*LATIN SMALL LETTER H WITH CIRCUMFLEX*/
+  0x0126, /*U+0126*/ /**/
+  0x0126, /*U+0127*/ /*LATIN SMALL LETTER H WITH STROKE*/
+  0x0128, /*U+0128*/ /**/
+  0x0128, /*U+0129*/ /*LATIN SMALL LETTER I WITH TILDE*/
+  0x012A, /*U+012A*/ /**/
+  0x012A, /*U+012B*/ /*LATIN SMALL LETTER I WITH MACRON*/
+  0x012C, /*U+012C*/ /**/
+  0x012C, /*U+012D*/ /*LATIN SMALL LETTER I WITH BREVE*/
+  0x012E, /*U+012E*/ /**/
+  0x012E, /*U+012F*/ /*LATIN SMALL LETTER I WITH OGONEK*/
+  0x0130, /*U+0130*/ /**/
+  0x0049, /*U+0131*/ /*LATIN SMALL LETTER DOTLESS I*/
+  0x0132, /*U+0132*/ /**/
+  0x0132, /*U+0133*/ /*LATIN SMALL LIGATURE IJ*/
+  0x0134, /*U+0134*/ /**/
+  0x0134, /*U+0135*/ /*LATIN SMALL LETTER J WITH CIRCUMFLEX*/
+  0x0136, /*U+0136*/ /**/
+  0x0136, /*U+0137*/ /*LATIN SMALL LETTER K WITH CEDILLA*/
+  0x0138, /*U+0138*/ /**/
+  0x0139, /*U+0139*/ /**/
+  0x0139, /*U+013A*/ /*LATIN SMALL LETTER L WITH ACUTE*/
+  0x013B, /*U+013B*/ /**/
+  0x013B, /*U+013C*/ /*LATIN SMALL LETTER L WITH CEDILLA*/
+  0x013D, /*U+013D*/ /**/
+  0x013D, /*U+013E*/ /*LATIN SMALL LETTER L WITH CARON*/
+  0x013F, /*U+013F*/ /**/
+  0x013F, /*U+0140*/ /*LATIN SMALL LETTER L WITH MIDDLE DOT*/
+  0x0141, /*U+0141*/ /**/
+  0x0141, /*U+0142*/ /*LATIN SMALL LETTER L WITH STROKE*/
+  0x0143, /*U+0143*/ /**/
+  0x0143, /*U+0144*/ /*LATIN SMALL LETTER N WITH ACUTE*/
+  0x0145, /*U+0145*/ /**/
+  0x0145, /*U+0146*/ /*LATIN SMALL LETTER N WITH CEDILLA*/
+  0x0147, /*U+0147*/ /**/
+  0x0147, /*U+0148*/ /*LATIN SMALL LETTER N WITH CARON*/
+  0x0149, /*U+0149*/ /**/
+  0x014A, /*U+014A*/ /**/
+  0x014A, /*U+014B*/ /*LATIN SMALL LETTER ENG*/
+  0x014C, /*U+014C*/ /**/
+  0x014C, /*U+014D*/ /*LATIN SMALL LETTER O WITH MACRON*/
+  0x014E, /*U+014E*/ /**/
+  0x014E, /*U+014F*/ /*LATIN SMALL LETTER O WITH BREVE*/
+  0x0150, /*U+0150*/ /**/
+  0x0150, /*U+0151*/ /*LATIN SMALL LETTER O WITH DOUBLE ACUTE*/
+  0x0152, /*U+0152*/ /**/
+  0x0152, /*U+0153*/ /*LATIN SMALL LIGATURE OE*/
+  0x0154, /*U+0154*/ /**/
+  0x0154, /*U+0155*/ /*LATIN SMALL LETTER R WITH ACUTE*/
+  0x0156, /*U+0156*/ /**/
+  0x0156, /*U+0157*/ /*LATIN SMALL LETTER R WITH CEDILLA*/
+  0x0158, /*U+0158*/ /**/
+  0x0158, /*U+0159*/ /*LATIN SMALL LETTER R WITH CARON*/
+  0x015A, /*U+015A*/ /**/
+  0x015A, /*U+015B*/ /*LATIN SMALL LETTER S WITH ACUTE*/
+  0x015C, /*U+015C*/ /**/
+  0x015C, /*U+015D*/ /*LATIN SMALL LETTER S WITH CIRCUMFLEX*/
+  0x015E, /*U+015E*/ /**/
+  0x015E, /*U+015F*/ /*LATIN SMALL LETTER S WITH CEDILLA*/
+  0x0160, /*U+0160*/ /**/
+  0x0160, /*U+0161*/ /*LATIN SMALL LETTER S WITH CARON*/
+  0x0162, /*U+0162*/ /**/
+  0x0162, /*U+0163*/ /*LATIN SMALL LETTER T WITH CEDILLA*/
+  0x0164, /*U+0164*/ /**/
+  0x0164, /*U+0165*/ /*LATIN SMALL LETTER T WITH CARON*/
+  0x0166, /*U+0166*/ /**/
+  0x0166, /*U+0167*/ /*LATIN SMALL LETTER T WITH STROKE*/
+  0x0168, /*U+0168*/ /**/
+  0x0168, /*U+0169*/ /*LATIN SMALL LETTER U WITH TILDE*/
+  0x016A, /*U+016A*/ /**/
+  0x016A, /*U+016B*/ /*LATIN SMALL LETTER U WITH MACRON*/
+  0x016C, /*U+016C*/ /**/
+  0x016C, /*U+016D*/ /*LATIN SMALL LETTER U WITH BREVE*/
+  0x016E, /*U+016E*/ /**/
+  0x016E, /*U+016F*/ /*LATIN SMALL LETTER U WITH RING ABOVE*/
+  0x0170, /*U+0170*/ /**/
+  0x0170, /*U+0171*/ /*LATIN SMALL LETTER U WITH DOUBLE ACUTE*/
+  0x0172, /*U+0172*/ /**/
+  0x0172, /*U+0173*/ /*LATIN SMALL LETTER U WITH OGONEK*/
+  0x0174, /*U+0174*/ /**/
+  0x0174, /*U+0175*/ /*LATIN SMALL LETTER W WITH CIRCUMFLEX*/
+  0x0176, /*U+0176*/ /**/
+  0x0176, /*U+0177*/ /*LATIN SMALL LETTER Y WITH CIRCUMFLEX*/
+  0x0178, /*U+0178*/ /**/
+  0x0179, /*U+0179*/ /**/
+  0x0179, /*U+017A*/ /*LATIN SMALL LETTER Z WITH ACUTE*/
+  0x017B, /*U+017B*/ /**/
+  0x017B, /*U+017C*/ /*LATIN SMALL LETTER Z WITH DOT ABOVE*/
+  0x017D, /*U+017D*/ /**/
+  0x017D, /*U+017E*/ /*LATIN SMALL LETTER Z WITH CARON*/
+  0x0053, /*U+017F*/ /*LATIN SMALL LETTER LONG S*/
+  0x0243, /*U+0180*/ /*LATIN SMALL LETTER B WITH STROKE*/
+  0x0181, /*U+0181*/ /**/
+  0x0182, /*U+0182*/ /**/
+  0x0182, /*U+0183*/ /*LATIN SMALL LETTER B WITH TOPBAR*/
+  0x0184, /*U+0184*/ /**/
+  0x0184, /*U+0185*/ /*LATIN SMALL LETTER TONE SIX*/
+  0x0186, /*U+0186*/ /**/
+  0x0187, /*U+0187*/ /**/
+  0x0187, /*U+0188*/ /*LATIN SMALL LETTER C WITH HOOK*/
+  0x0189, /*U+0189*/ /**/
+  0x018A, /*U+018A*/ /**/
+  0x018B, /*U+018B*/ /**/
+  0x018B, /*U+018C*/ /*LATIN SMALL LETTER D WITH TOPBAR*/
+  0x018D, /*U+018D*/ /**/
+  0x018E, /*U+018E*/ /**/
+  0x018F, /*U+018F*/ /**/
+  0x0190, /*U+0190*/ /**/
+  0x0191, /*U+0191*/ /**/
+  0x0191, /*U+0192*/ /*LATIN SMALL LETTER F WITH HOOK*/
+  0x0193, /*U+0193*/ /**/
+  0x0194, /*U+0194*/ /**/
+  0x01F6, /*U+0195*/ /*LATIN SMALL LETTER HV*/
+  0x0196, /*U+0196*/ /**/
+  0x0197, /*U+0197*/ /**/
+  0x0198, /*U+0198*/ /**/
+  0x0198, /*U+0199*/ /*LATIN SMALL LETTER K WITH HOOK*/
+  0x023D, /*U+019A*/ /*LATIN SMALL LETTER L WITH BAR*/
+  0x019B, /*U+019B*/ /**/
+  0x019C, /*U+019C*/ /**/
+  0x019D, /*U+019D*/ /**/
+  0x0220, /*U+019E*/ /*LATIN SMALL LETTER N WITH LONG RIGHT LEG*/
+  0x019F, /*U+019F*/ /**/
+  0x01A0, /*U+01A0*/ /**/
+  0x01A0, /*U+01A1*/ /*LATIN SMALL LETTER O WITH HORN*/
+  0x01A2, /*U+01A2*/ /**/
+  0x01A2, /*U+01A3*/ /*LATIN SMALL LETTER OI*/
+  0x01A4, /*U+01A4*/ /**/
+  0x01A4, /*U+01A5*/ /*LATIN SMALL LETTER P WITH HOOK*/
+  0x01A6, /*U+01A6*/ /**/
+  0x01A7, /*U+01A7*/ /**/
+  0x01A7, /*U+01A8*/ /*LATIN SMALL LETTER TONE TWO*/
+  0x01A9, /*U+01A9*/ /**/
+  0x01AA, /*U+01AA*/ /**/
+  0x01AB, /*U+01AB*/ /**/
+  0x01AC, /*U+01AC*/ /**/
+  0x01AC, /*U+01AD*/ /*LATIN SMALL LETTER T WITH HOOK*/
+  0x01AE, /*U+01AE*/ /**/
+  0x01AF, /*U+01AF*/ /**/
+  0x01AF, /*U+01B0*/ /*LATIN SMALL LETTER U WITH HORN*/
+  0x01B1, /*U+01B1*/ /**/
+  0x01B2, /*U+01B2*/ /**/
+  0x01B3, /*U+01B3*/ /**/
+  0x01B3, /*U+01B4*/ /*LATIN SMALL LETTER Y WITH HOOK*/
+  0x01B5, /*U+01B5*/ /**/
+  0x01B5, /*U+01B6*/ /*LATIN SMALL LETTER Z WITH STROKE*/
+  0x01B7, /*U+01B7*/ /**/
+  0x01B8, /*U+01B8*/ /**/
+  0x01B8, /*U+01B9*/ /*LATIN SMALL LETTER EZH REVERSED*/
+  0x01BA, /*U+01BA*/ /**/
+  0x01BB, /*U+01BB*/ /**/
+  0x01BC, /*U+01BC*/ /**/
+  0x01BC, /*U+01BD*/ /*LATIN SMALL LETTER TONE FIVE*/
+  0x01BE, /*U+01BE*/ /**/
+  0x01F7, /*U+01BF*/ /*LATIN LETTER WYNN*/
+  0x01C0, /*U+01C0*/ /**/
+  0x01C1, /*U+01C1*/ /**/
+  0x01C2, /*U+01C2*/ /**/
+  0x01C3, /*U+01C3*/ /**/
+  0x01C4, /*U+01C4*/ /**/
+  0x01C4, /*U+01C5*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON*/
+  0x01C4, /*U+01C6*/ /*LATIN SMALL LETTER DZ WITH CARON*/
+  0x01C7, /*U+01C7*/ /**/
+  0x01C7, /*U+01C8*/ /*LATIN CAPITAL LETTER L WITH SMALL LETTER J*/
+  0x01C7, /*U+01C9*/ /*LATIN SMALL LETTER LJ*/
+  0x01CA, /*U+01CA*/ /**/
+  0x01CA, /*U+01CB*/ /*LATIN CAPITAL LETTER N WITH SMALL LETTER J*/
+  0x01CA, /*U+01CC*/ /*LATIN SMALL LETTER NJ*/
+  0x01CD, /*U+01CD*/ /**/
+  0x01CD, /*U+01CE*/ /*LATIN SMALL LETTER A WITH CARON*/
+  0x01CF, /*U+01CF*/ /**/
+  0x01CF, /*U+01D0*/ /*LATIN SMALL LETTER I WITH CARON*/
+  0x01D1, /*U+01D1*/ /**/
+  0x01D1, /*U+01D2*/ /*LATIN SMALL LETTER O WITH CARON*/
+  0x01D3, /*U+01D3*/ /**/
+  0x01D3, /*U+01D4*/ /*LATIN SMALL LETTER U WITH CARON*/
+  0x01D5, /*U+01D5*/ /**/
+  0x01D5, /*U+01D6*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND MACRON*/
+  0x01D7, /*U+01D7*/ /**/
+  0x01D7, /*U+01D8*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE*/
+  0x01D9, /*U+01D9*/ /**/
+  0x01D9, /*U+01DA*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND CARON*/
+  0x01DB, /*U+01DB*/ /**/
+  0x01DB, /*U+01DC*/ /*LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE*/
+  0x018E, /*U+01DD*/ /*LATIN SMALL LETTER TURNED E*/
+  0x01DE, /*U+01DE*/ /**/
+  0x01DE, /*U+01DF*/ /*LATIN SMALL LETTER A WITH DIAERESIS AND MACRON*/
+  0x01E0, /*U+01E0*/ /**/
+  0x01E0, /*U+01E1*/ /*LATIN SMALL LETTER A WITH DOT ABOVE AND MACRON*/
+  0x01E2, /*U+01E2*/ /**/
+  0x01E2, /*U+01E3*/ /*LATIN SMALL LETTER AE WITH MACRON*/
+  0x01E4, /*U+01E4*/ /**/
+  0x01E4, /*U+01E5*/ /*LATIN SMALL LETTER G WITH STROKE*/
+  0x01E6, /*U+01E6*/ /**/
+  0x01E6, /*U+01E7*/ /*LATIN SMALL LETTER G WITH CARON*/
+  0x01E8, /*U+01E8*/ /**/
+  0x01E8, /*U+01E9*/ /*LATIN SMALL LETTER K WITH CARON*/
+  0x01EA, /*U+01EA*/ /**/
+  0x01EA, /*U+01EB*/ /*LATIN SMALL LETTER O WITH OGONEK*/
+  0x01EC, /*U+01EC*/ /**/
+  0x01EC, /*U+01ED*/ /*LATIN SMALL LETTER O WITH OGONEK AND MACRON*/
+  0x01EE, /*U+01EE*/ /**/
+  0x01EE, /*U+01EF*/ /*LATIN SMALL LETTER EZH WITH CARON*/
+  0x01F0, /*U+01F0*/ /**/
+  0x01F1, /*U+01F1*/ /**/
+  0x01F1, /*U+01F2*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z*/
+  0x01F1, /*U+01F3*/ /*LATIN SMALL LETTER DZ*/
+  0x01F4, /*U+01F4*/ /**/
+  0x01F4, /*U+01F5*/ /*LATIN SMALL LETTER G WITH ACUTE*/
+  0x01F6, /*U+01F6*/ /**/
+  0x01F7, /*U+01F7*/ /**/
+  0x01F8, /*U+01F8*/ /**/
+  0x01F8, /*U+01F9*/ /*LATIN SMALL LETTER N WITH GRAVE*/
+  0x01FA, /*U+01FA*/ /**/
+  0x01FA, /*U+01FB*/ /*LATIN SMALL LETTER A WITH RING ABOVE AND ACUTE*/
+  0x01FC, /*U+01FC*/ /**/
+  0x01FC, /*U+01FD*/ /*LATIN SMALL LETTER AE WITH ACUTE*/
+  0x01FE, /*U+01FE*/ /**/
+  0x01FE, /*U+01FF*/ /*LATIN SMALL LETTER O WITH STROKE AND ACUTE*/
+  0x0200, /*U+0200*/ /**/
+  0x0200, /*U+0201*/ /*LATIN SMALL LETTER A WITH DOUBLE GRAVE*/
+  0x0202, /*U+0202*/ /**/
+  0x0202, /*U+0203*/ /*LATIN SMALL LETTER A WITH INVERTED BREVE*/
+  0x0204, /*U+0204*/ /**/
+  0x0204, /*U+0205*/ /*LATIN SMALL LETTER E WITH DOUBLE GRAVE*/
+  0x0206, /*U+0206*/ /**/
+  0x0206, /*U+0207*/ /*LATIN SMALL LETTER E WITH INVERTED BREVE*/
+  0x0208, /*U+0208*/ /**/
+  0x0208, /*U+0209*/ /*LATIN SMALL LETTER I WITH DOUBLE GRAVE*/
+  0x020A, /*U+020A*/ /**/
+  0x020A, /*U+020B*/ /*LATIN SMALL LETTER I WITH INVERTED BREVE*/
+  0x020C, /*U+020C*/ /**/
+  0x020C, /*U+020D*/ /*LATIN SMALL LETTER O WITH DOUBLE GRAVE*/
+  0x020E, /*U+020E*/ /**/
+  0x020E, /*U+020F*/ /*LATIN SMALL LETTER O WITH INVERTED BREVE*/
+  0x0210, /*U+0210*/ /**/
+  0x0210, /*U+0211*/ /*LATIN SMALL LETTER R WITH DOUBLE GRAVE*/
+  0x0212, /*U+0212*/ /**/
+  0x0212, /*U+0213*/ /*LATIN SMALL LETTER R WITH INVERTED BREVE*/
+  0x0214, /*U+0214*/ /**/
+  0x0214, /*U+0215*/ /*LATIN SMALL LETTER U WITH DOUBLE GRAVE*/
+  0x0216, /*U+0216*/ /**/
+  0x0216, /*U+0217*/ /*LATIN SMALL LETTER U WITH INVERTED BREVE*/
+  0x0218, /*U+0218*/ /**/
+  0x0218, /*U+0219*/ /*LATIN SMALL LETTER S WITH COMMA BELOW*/
+  0x021A, /*U+021A*/ /**/
+  0x021A, /*U+021B*/ /*LATIN SMALL LETTER T WITH COMMA BELOW*/
+  0x021C, /*U+021C*/ /**/
+  0x021C, /*U+021D*/ /*LATIN SMALL LETTER YOGH*/
+  0x021E, /*U+021E*/ /**/
+  0x021E, /*U+021F*/ /*LATIN SMALL LETTER H WITH CARON*/
+  0x0220, /*U+0220*/ /**/
+  0x0221, /*U+0221*/ /**/
+  0x0222, /*U+0222*/ /**/
+  0x0222, /*U+0223*/ /*LATIN SMALL LETTER OU*/
+  0x0224, /*U+0224*/ /**/
+  0x0224, /*U+0225*/ /*LATIN SMALL LETTER Z WITH HOOK*/
+  0x0226, /*U+0226*/ /**/
+  0x0226, /*U+0227*/ /*LATIN SMALL LETTER A WITH DOT ABOVE*/
+  0x0228, /*U+0228*/ /**/
+  0x0228, /*U+0229*/ /*LATIN SMALL LETTER E WITH CEDILLA*/
+  0x022A, /*U+022A*/ /**/
+  0x022A, /*U+022B*/ /*LATIN SMALL LETTER O WITH DIAERESIS AND MACRON*/
+  0x022C, /*U+022C*/ /**/
+  0x022C, /*U+022D*/ /*LATIN SMALL LETTER O WITH TILDE AND MACRON*/
+  0x022E, /*U+022E*/ /**/
+  0x022E, /*U+022F*/ /*LATIN SMALL LETTER O WITH DOT ABOVE*/
+  0x0230, /*U+0230*/ /**/
+  0x0230, /*U+0231*/ /*LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON*/
+  0x0232, /*U+0232*/ /**/
+  0x0232, /*U+0233*/ /*LATIN SMALL LETTER Y WITH MACRON*/
+  0x0234, /*U+0234*/ /**/
+  0x0235, /*U+0235*/ /**/
+  0x0236, /*U+0236*/ /**/
+  0x0237, /*U+0237*/ /**/
+  0x0238, /*U+0238*/ /**/
+  0x0239, /*U+0239*/ /**/
+  0x023A, /*U+023A*/ /**/
+  0x023B, /*U+023B*/ /**/
+  0x023B, /*U+023C*/ /*LATIN SMALL LETTER C WITH STROKE*/
+  0x023D, /*U+023D*/ /**/
+  0x023E, /*U+023E*/ /**/
+  0x2C7E, /*U+023F*/ /*LATIN SMALL LETTER S WITH SWASH TAIL*/
+  0x2C7F, /*U+0240*/ /*LATIN SMALL LETTER Z WITH SWASH TAIL*/
+  0x0241, /*U+0241*/ /**/
+  0x0241, /*U+0242*/ /*LATIN SMALL LETTER GLOTTAL STOP*/
+  0x0243, /*U+0243*/ /**/
+  0x0244, /*U+0244*/ /**/
+  0x0245, /*U+0245*/ /**/
+  0x0246, /*U+0246*/ /**/
+  0x0246, /*U+0247*/ /*LATIN SMALL LETTER E WITH STROKE*/
+  0x0248, /*U+0248*/ /**/
+  0x0248, /*U+0249*/ /*LATIN SMALL LETTER J WITH STROKE*/
+  0x024A, /*U+024A*/ /**/
+  0x024A, /*U+024B*/ /*LATIN SMALL LETTER Q WITH HOOK TAIL*/
+  0x024C, /*U+024C*/ /**/
+  0x024C, /*U+024D*/ /*LATIN SMALL LETTER R WITH STROKE*/
+  0x024E, /*U+024E*/ /**/
+  0x024E, /*U+024F*/ /*LATIN SMALL LETTER Y WITH STROKE*/
+  0x2C6F, /*U+0250*/ /*LATIN SMALL LETTER TURNED A*/
+  0x2C6D, /*U+0251*/ /*LATIN SMALL LETTER ALPHA*/
+  0x2C70, /*U+0252*/ /*LATIN SMALL LETTER TURNED ALPHA*/
+  0x0181, /*U+0253*/ /*LATIN SMALL LETTER B WITH HOOK*/
+  0x0186, /*U+0254*/ /*LATIN SMALL LETTER OPEN O*/
+  0x0255, /*U+0255*/ /**/
+  0x0189, /*U+0256*/ /*LATIN SMALL LETTER D WITH TAIL*/
+  0x018A, /*U+0257*/ /*LATIN SMALL LETTER D WITH HOOK*/
+  0x0258, /*U+0258*/ /**/
+  0x018F, /*U+0259*/ /*LATIN SMALL LETTER SCHWA*/
+  0x025A, /*U+025A*/ /**/
+  0x0190, /*U+025B*/ /*LATIN SMALL LETTER OPEN E*/
+  0x025C, /*U+025C*/ /**/
+  0x025D, /*U+025D*/ /**/
+  0x025E, /*U+025E*/ /**/
+  0x025F, /*U+025F*/ /**/
+  0x0193, /*U+0260*/ /*LATIN SMALL LETTER G WITH HOOK*/
+  0x0261, /*U+0261*/ /**/
+  0x0262, /*U+0262*/ /**/
+  0x0194, /*U+0263*/ /*LATIN SMALL LETTER GAMMA*/
+  0x0264, /*U+0264*/ /**/
+  0xA78D, /*U+0265*/ /*LATIN SMALL LETTER TURNED H*/
+  0x0266, /*U+0266*/ /**/
+  0x0267, /*U+0267*/ /**/
+  0x0197, /*U+0268*/ /*LATIN SMALL LETTER I WITH STROKE*/
+  0x0196, /*U+0269*/ /*LATIN SMALL LETTER IOTA*/
+  0x026A, /*U+026A*/ /**/
+  0x2C62, /*U+026B*/ /*LATIN SMALL LETTER L WITH MIDDLE TILDE*/
+  0x026C, /*U+026C*/ /**/
+  0x026D, /*U+026D*/ /**/
+  0x026E, /*U+026E*/ /**/
+  0x019C, /*U+026F*/ /*LATIN SMALL LETTER TURNED M*/
+  0x0270, /*U+0270*/ /**/
+  0x2C6E, /*U+0271*/ /*LATIN SMALL LETTER M WITH HOOK*/
+  0x019D, /*U+0272*/ /*LATIN SMALL LETTER N WITH LEFT HOOK*/
+  0x0273, /*U+0273*/ /**/
+  0x0274, /*U+0274*/ /**/
+  0x019F, /*U+0275*/ /*LATIN SMALL LETTER BARRED O*/
+  0x0276, /*U+0276*/ /**/
+  0x0277, /*U+0277*/ /**/
+  0x0278, /*U+0278*/ /**/
+  0x0279, /*U+0279*/ /**/
+  0x027A, /*U+027A*/ /**/
+  0x027B, /*U+027B*/ /**/
+  0x027C, /*U+027C*/ /**/
+  0x2C64, /*U+027D*/ /*LATIN SMALL LETTER R WITH TAIL*/
+  0x027E, /*U+027E*/ /**/
+  0x027F, /*U+027F*/ /**/
+  0x01A6, /*U+0280*/ /*LATIN LETTER SMALL CAPITAL R*/
+  0x0281, /*U+0281*/ /**/
+  0x0282, /*U+0282*/ /**/
+  0x01A9, /*U+0283*/ /*LATIN SMALL LETTER ESH*/
+  0x0284, /*U+0284*/ /**/
+  0x0285, /*U+0285*/ /**/
+  0x0286, /*U+0286*/ /**/
+  0x0287, /*U+0287*/ /**/
+  0x01AE, /*U+0288*/ /*LATIN SMALL LETTER T WITH RETROFLEX HOOK*/
+  0x0244, /*U+0289*/ /*LATIN SMALL LETTER U BAR*/
+  0x01B1, /*U+028A*/ /*LATIN SMALL LETTER UPSILON*/
+  0x01B2, /*U+028B*/ /*LATIN SMALL LETTER V WITH HOOK*/
+  0x0245, /*U+028C*/ /*LATIN SMALL LETTER TURNED V*/
+  0x028D, /*U+028D*/ /**/
+  0x028E, /*U+028E*/ /**/
+  0x028F, /*U+028F*/ /**/
+  0x0290, /*U+0290*/ /**/
+  0x0291, /*U+0291*/ /**/
+  0x01B7, /*U+0292*/ /*LATIN SMALL LETTER EZH*/
+  0x0293, /*U+0293*/ /**/
+  0x0294, /*U+0294*/ /**/
+  0x0295, /*U+0295*/ /**/
+  0x0296, /*U+0296*/ /**/
+  0x0297, /*U+0297*/ /**/
+  0x0298, /*U+0298*/ /**/
+  0x0299, /*U+0299*/ /**/
+  0x029A, /*U+029A*/ /**/
+  0x029B, /*U+029B*/ /**/
+  0x029C, /*U+029C*/ /**/
+  0x029D, /*U+029D*/ /**/
+  0x029E, /*U+029E*/ /**/
+  0x029F, /*U+029F*/ /**/
+  0x02A0, /*U+02A0*/ /**/
+  0x02A1, /*U+02A1*/ /**/
+  0x02A2, /*U+02A2*/ /**/
+  0x02A3, /*U+02A3*/ /**/
+  0x02A4, /*U+02A4*/ /**/
+  0x02A5, /*U+02A5*/ /**/
+  0x02A6, /*U+02A6*/ /**/
+  0x02A7, /*U+02A7*/ /**/
+  0x02A8, /*U+02A8*/ /**/
+  0x02A9, /*U+02A9*/ /**/
+  0x02AA, /*U+02AA*/ /**/
+  0x02AB, /*U+02AB*/ /**/
+  0x02AC, /*U+02AC*/ /**/
+  0x02AD, /*U+02AD*/ /**/
+  0x02AE, /*U+02AE*/ /**/
+  0x02AF, /*U+02AF*/ /**/
+  0x02B0, /*U+02B0*/ /**/
+  0x02B1, /*U+02B1*/ /**/
+  0x02B2, /*U+02B2*/ /**/
+  0x02B3, /*U+02B3*/ /**/
+  0x02B4, /*U+02B4*/ /**/
+  0x02B5, /*U+02B5*/ /**/
+  0x02B6, /*U+02B6*/ /**/
+  0x02B7, /*U+02B7*/ /**/
+  0x02B8, /*U+02B8*/ /**/
+  0x02B9, /*U+02B9*/ /**/
+  0x02BA, /*U+02BA*/ /**/
+  0x02BB, /*U+02BB*/ /**/
+  0x02BC, /*U+02BC*/ /**/
+  0x02BD, /*U+02BD*/ /**/
+  0x02BE, /*U+02BE*/ /**/
+  0x02BF, /*U+02BF*/ /**/
+};
+
+static const u_int16_t upper_table_2[640] = {
+  0x0340, /*U+0340*/ /**/
+  0x0341, /*U+0341*/ /**/
+  0x0342, /*U+0342*/ /**/
+  0x0343, /*U+0343*/ /**/
+  0x0344, /*U+0344*/ /**/
+  0x0399, /*U+0345*/ /*COMBINING GREEK YPOGEGRAMMENI*/
+  0x0346, /*U+0346*/ /**/
+  0x0347, /*U+0347*/ /**/
+  0x0348, /*U+0348*/ /**/
+  0x0349, /*U+0349*/ /**/
+  0x034A, /*U+034A*/ /**/
+  0x034B, /*U+034B*/ /**/
+  0x034C, /*U+034C*/ /**/
+  0x034D, /*U+034D*/ /**/
+  0x034E, /*U+034E*/ /**/
+  0x034F, /*U+034F*/ /**/
+  0x0350, /*U+0350*/ /**/
+  0x0351, /*U+0351*/ /**/
+  0x0352, /*U+0352*/ /**/
+  0x0353, /*U+0353*/ /**/
+  0x0354, /*U+0354*/ /**/
+  0x0355, /*U+0355*/ /**/
+  0x0356, /*U+0356*/ /**/
+  0x0357, /*U+0357*/ /**/
+  0x0358, /*U+0358*/ /**/
+  0x0359, /*U+0359*/ /**/
+  0x035A, /*U+035A*/ /**/
+  0x035B, /*U+035B*/ /**/
+  0x035C, /*U+035C*/ /**/
+  0x035D, /*U+035D*/ /**/
+  0x035E, /*U+035E*/ /**/
+  0x035F, /*U+035F*/ /**/
+  0x0360, /*U+0360*/ /**/
+  0x0361, /*U+0361*/ /**/
+  0x0362, /*U+0362*/ /**/
+  0x0363, /*U+0363*/ /**/
+  0x0364, /*U+0364*/ /**/
+  0x0365, /*U+0365*/ /**/
+  0x0366, /*U+0366*/ /**/
+  0x0367, /*U+0367*/ /**/
+  0x0368, /*U+0368*/ /**/
+  0x0369, /*U+0369*/ /**/
+  0x036A, /*U+036A*/ /**/
+  0x036B, /*U+036B*/ /**/
+  0x036C, /*U+036C*/ /**/
+  0x036D, /*U+036D*/ /**/
+  0x036E, /*U+036E*/ /**/
+  0x036F, /*U+036F*/ /**/
+  0x0370, /*U+0370*/ /**/
+  0x0370, /*U+0371*/ /*GREEK SMALL LETTER HETA*/
+  0x0372, /*U+0372*/ /**/
+  0x0372, /*U+0373*/ /*GREEK SMALL LETTER ARCHAIC SAMPI*/
+  0x0374, /*U+0374*/ /**/
+  0x0375, /*U+0375*/ /**/
+  0x0376, /*U+0376*/ /**/
+  0x0376, /*U+0377*/ /*GREEK SMALL LETTER PAMPHYLIAN DIGAMMA*/
+  0x0378, /*U+0378*/ /**/
+  0x0379, /*U+0379*/ /**/
+  0x037A, /*U+037A*/ /**/
+  0x03FD, /*U+037B*/ /*GREEK SMALL REVERSED LUNATE SIGMA SYMBOL*/
+  0x03FE, /*U+037C*/ /*GREEK SMALL DOTTED LUNATE SIGMA SYMBOL*/
+  0x03FF, /*U+037D*/ /*GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL*/
+  0x037E, /*U+037E*/ /**/
+  0x037F, /*U+037F*/ /**/
+  0x0380, /*U+0380*/ /**/
+  0x0381, /*U+0381*/ /**/
+  0x0382, /*U+0382*/ /**/
+  0x0383, /*U+0383*/ /**/
+  0x0384, /*U+0384*/ /**/
+  0x0385, /*U+0385*/ /**/
+  0x0386, /*U+0386*/ /**/
+  0x0387, /*U+0387*/ /**/
+  0x0388, /*U+0388*/ /**/
+  0x0389, /*U+0389*/ /**/
+  0x038A, /*U+038A*/ /**/
+  0x038B, /*U+038B*/ /**/
+  0x038C, /*U+038C*/ /**/
+  0x038D, /*U+038D*/ /**/
+  0x038E, /*U+038E*/ /**/
+  0x038F, /*U+038F*/ /**/
+  0x0390, /*U+0390*/ /**/
+  0x0391, /*U+0391*/ /**/
+  0x0392, /*U+0392*/ /**/
+  0x0393, /*U+0393*/ /**/
+  0x0394, /*U+0394*/ /**/
+  0x0395, /*U+0395*/ /**/
+  0x0396, /*U+0396*/ /**/
+  0x0397, /*U+0397*/ /**/
+  0x0398, /*U+0398*/ /**/
+  0x0399, /*U+0399*/ /**/
+  0x039A, /*U+039A*/ /**/
+  0x039B, /*U+039B*/ /**/
+  0x039C, /*U+039C*/ /**/
+  0x039D, /*U+039D*/ /**/
+  0x039E, /*U+039E*/ /**/
+  0x039F, /*U+039F*/ /**/
+  0x03A0, /*U+03A0*/ /**/
+  0x03A1, /*U+03A1*/ /**/
+  0x03A2, /*U+03A2*/ /**/
+  0x03A3, /*U+03A3*/ /**/
+  0x03A4, /*U+03A4*/ /**/
+  0x03A5, /*U+03A5*/ /**/
+  0x03A6, /*U+03A6*/ /**/
+  0x03A7, /*U+03A7*/ /**/
+  0x03A8, /*U+03A8*/ /**/
+  0x03A9, /*U+03A9*/ /**/
+  0x03AA, /*U+03AA*/ /**/
+  0x03AB, /*U+03AB*/ /**/
+  0x0386, /*U+03AC*/ /*GREEK SMALL LETTER ALPHA WITH TONOS*/
+  0x0388, /*U+03AD*/ /*GREEK SMALL LETTER EPSILON WITH TONOS*/
+  0x0389, /*U+03AE*/ /*GREEK SMALL LETTER ETA WITH TONOS*/
+  0x038A, /*U+03AF*/ /*GREEK SMALL LETTER IOTA WITH TONOS*/
+  0x03B0, /*U+03B0*/ /**/
+  0x0391, /*U+03B1*/ /*GREEK SMALL LETTER ALPHA*/
+  0x0392, /*U+03B2*/ /*GREEK SMALL LETTER BETA*/
+  0x0393, /*U+03B3*/ /*GREEK SMALL LETTER GAMMA*/
+  0x0394, /*U+03B4*/ /*GREEK SMALL LETTER DELTA*/
+  0x0395, /*U+03B5*/ /*GREEK SMALL LETTER EPSILON*/
+  0x0396, /*U+03B6*/ /*GREEK SMALL LETTER ZETA*/
+  0x0397, /*U+03B7*/ /*GREEK SMALL LETTER ETA*/
+  0x0398, /*U+03B8*/ /*GREEK SMALL LETTER THETA*/
+  0x0399, /*U+03B9*/ /*GREEK SMALL LETTER IOTA*/
+  0x039A, /*U+03BA*/ /*GREEK SMALL LETTER KAPPA*/
+  0x039B, /*U+03BB*/ /*GREEK SMALL LETTER LAMDA*/
+  0x039C, /*U+03BC*/ /*GREEK SMALL LETTER MU*/
+  0x039D, /*U+03BD*/ /*GREEK SMALL LETTER NU*/
+  0x039E, /*U+03BE*/ /*GREEK SMALL LETTER XI*/
+  0x039F, /*U+03BF*/ /*GREEK SMALL LETTER OMICRON*/
+  0x03A0, /*U+03C0*/ /*GREEK SMALL LETTER PI*/
+  0x03A1, /*U+03C1*/ /*GREEK SMALL LETTER RHO*/
+  0x03A3, /*U+03C2*/ /*GREEK SMALL LETTER FINAL SIGMA*/
+  0x03A3, /*U+03C3*/ /*GREEK SMALL LETTER SIGMA*/
+  0x03A4, /*U+03C4*/ /*GREEK SMALL LETTER TAU*/
+  0x03A5, /*U+03C5*/ /*GREEK SMALL LETTER UPSILON*/
+  0x03A6, /*U+03C6*/ /*GREEK SMALL LETTER PHI*/
+  0x03A7, /*U+03C7*/ /*GREEK SMALL LETTER CHI*/
+  0x03A8, /*U+03C8*/ /*GREEK SMALL LETTER PSI*/
+  0x03A9, /*U+03C9*/ /*GREEK SMALL LETTER OMEGA*/
+  0x03AA, /*U+03CA*/ /*GREEK SMALL LETTER IOTA WITH DIALYTIKA*/
+  0x03AB, /*U+03CB*/ /*GREEK SMALL LETTER UPSILON WITH DIALYTIKA*/
+  0x038C, /*U+03CC*/ /*GREEK SMALL LETTER OMICRON WITH TONOS*/
+  0x038E, /*U+03CD*/ /*GREEK SMALL LETTER UPSILON WITH TONOS*/
+  0x038F, /*U+03CE*/ /*GREEK SMALL LETTER OMEGA WITH TONOS*/
+  0x03CF, /*U+03CF*/ /**/
+  0x0392, /*U+03D0*/ /*GREEK BETA SYMBOL*/
+  0x0398, /*U+03D1*/ /*GREEK THETA SYMBOL*/
+  0x03D2, /*U+03D2*/ /**/
+  0x03D3, /*U+03D3*/ /**/
+  0x03D4, /*U+03D4*/ /**/
+  0x03A6, /*U+03D5*/ /*GREEK PHI SYMBOL*/
+  0x03A0, /*U+03D6*/ /*GREEK PI SYMBOL*/
+  0x03CF, /*U+03D7*/ /*GREEK KAI SYMBOL*/
+  0x03D8, /*U+03D8*/ /**/
+  0x03D8, /*U+03D9*/ /*GREEK SMALL LETTER ARCHAIC KOPPA*/
+  0x03DA, /*U+03DA*/ /**/
+  0x03DA, /*U+03DB*/ /*GREEK SMALL LETTER STIGMA*/
+  0x03DC, /*U+03DC*/ /**/
+  0x03DC, /*U+03DD*/ /*GREEK SMALL LETTER DIGAMMA*/
+  0x03DE, /*U+03DE*/ /**/
+  0x03DE, /*U+03DF*/ /*GREEK SMALL LETTER KOPPA*/
+  0x03E0, /*U+03E0*/ /**/
+  0x03E0, /*U+03E1*/ /*GREEK SMALL LETTER SAMPI*/
+  0x03E2, /*U+03E2*/ /**/
+  0x03E2, /*U+03E3*/ /*COPTIC SMALL LETTER SHEI*/
+  0x03E4, /*U+03E4*/ /**/
+  0x03E4, /*U+03E5*/ /*COPTIC SMALL LETTER FEI*/
+  0x03E6, /*U+03E6*/ /**/
+  0x03E6, /*U+03E7*/ /*COPTIC SMALL LETTER KHEI*/
+  0x03E8, /*U+03E8*/ /**/
+  0x03E8, /*U+03E9*/ /*COPTIC SMALL LETTER HORI*/
+  0x03EA, /*U+03EA*/ /**/
+  0x03EA, /*U+03EB*/ /*COPTIC SMALL LETTER GANGIA*/
+  0x03EC, /*U+03EC*/ /**/
+  0x03EC, /*U+03ED*/ /*COPTIC SMALL LETTER SHIMA*/
+  0x03EE, /*U+03EE*/ /**/
+  0x03EE, /*U+03EF*/ /*COPTIC SMALL LETTER DEI*/
+  0x039A, /*U+03F0*/ /*GREEK KAPPA SYMBOL*/
+  0x03A1, /*U+03F1*/ /*GREEK RHO SYMBOL*/
+  0x03F9, /*U+03F2*/ /*GREEK LUNATE SIGMA SYMBOL*/
+  0x03F3, /*U+03F3*/ /**/
+  0x03F4, /*U+03F4*/ /**/
+  0x0395, /*U+03F5*/ /*GREEK LUNATE EPSILON SYMBOL*/
+  0x03F6, /*U+03F6*/ /**/
+  0x03F7, /*U+03F7*/ /**/
+  0x03F7, /*U+03F8*/ /*GREEK SMALL LETTER SHO*/
+  0x03F9, /*U+03F9*/ /**/
+  0x03FA, /*U+03FA*/ /**/
+  0x03FA, /*U+03FB*/ /*GREEK SMALL LETTER SAN*/
+  0x03FC, /*U+03FC*/ /**/
+  0x03FD, /*U+03FD*/ /**/
+  0x03FE, /*U+03FE*/ /**/
+  0x03FF, /*U+03FF*/ /**/
+  0x0400, /*U+0400*/ /**/
+  0x0401, /*U+0401*/ /**/
+  0x0402, /*U+0402*/ /**/
+  0x0403, /*U+0403*/ /**/
+  0x0404, /*U+0404*/ /**/
+  0x0405, /*U+0405*/ /**/
+  0x0406, /*U+0406*/ /**/
+  0x0407, /*U+0407*/ /**/
+  0x0408, /*U+0408*/ /**/
+  0x0409, /*U+0409*/ /**/
+  0x040A, /*U+040A*/ /**/
+  0x040B, /*U+040B*/ /**/
+  0x040C, /*U+040C*/ /**/
+  0x040D, /*U+040D*/ /**/
+  0x040E, /*U+040E*/ /**/
+  0x040F, /*U+040F*/ /**/
+  0x0410, /*U+0410*/ /**/
+  0x0411, /*U+0411*/ /**/
+  0x0412, /*U+0412*/ /**/
+  0x0413, /*U+0413*/ /**/
+  0x0414, /*U+0414*/ /**/
+  0x0415, /*U+0415*/ /**/
+  0x0416, /*U+0416*/ /**/
+  0x0417, /*U+0417*/ /**/
+  0x0418, /*U+0418*/ /**/
+  0x0419, /*U+0419*/ /**/
+  0x041A, /*U+041A*/ /**/
+  0x041B, /*U+041B*/ /**/
+  0x041C, /*U+041C*/ /**/
+  0x041D, /*U+041D*/ /**/
+  0x041E, /*U+041E*/ /**/
+  0x041F, /*U+041F*/ /**/
+  0x0420, /*U+0420*/ /**/
+  0x0421, /*U+0421*/ /**/
+  0x0422, /*U+0422*/ /**/
+  0x0423, /*U+0423*/ /**/
+  0x0424, /*U+0424*/ /**/
+  0x0425, /*U+0425*/ /**/
+  0x0426, /*U+0426*/ /**/
+  0x0427, /*U+0427*/ /**/
+  0x0428, /*U+0428*/ /**/
+  0x0429, /*U+0429*/ /**/
+  0x042A, /*U+042A*/ /**/
+  0x042B, /*U+042B*/ /**/
+  0x042C, /*U+042C*/ /**/
+  0x042D, /*U+042D*/ /**/
+  0x042E, /*U+042E*/ /**/
+  0x042F, /*U+042F*/ /**/
+  0x0410, /*U+0430*/ /*CYRILLIC SMALL LETTER A*/
+  0x0411, /*U+0431*/ /*CYRILLIC SMALL LETTER BE*/
+  0x0412, /*U+0432*/ /*CYRILLIC SMALL LETTER VE*/
+  0x0413, /*U+0433*/ /*CYRILLIC SMALL LETTER GHE*/
+  0x0414, /*U+0434*/ /*CYRILLIC SMALL LETTER DE*/
+  0x0415, /*U+0435*/ /*CYRILLIC SMALL LETTER IE*/
+  0x0416, /*U+0436*/ /*CYRILLIC SMALL LETTER ZHE*/
+  0x0417, /*U+0437*/ /*CYRILLIC SMALL LETTER ZE*/
+  0x0418, /*U+0438*/ /*CYRILLIC SMALL LETTER I*/
+  0x0419, /*U+0439*/ /*CYRILLIC SMALL LETTER SHORT I*/
+  0x041A, /*U+043A*/ /*CYRILLIC SMALL LETTER KA*/
+  0x041B, /*U+043B*/ /*CYRILLIC SMALL LETTER EL*/
+  0x041C, /*U+043C*/ /*CYRILLIC SMALL LETTER EM*/
+  0x041D, /*U+043D*/ /*CYRILLIC SMALL LETTER EN*/
+  0x041E, /*U+043E*/ /*CYRILLIC SMALL LETTER O*/
+  0x041F, /*U+043F*/ /*CYRILLIC SMALL LETTER PE*/
+  0x0420, /*U+0440*/ /*CYRILLIC SMALL LETTER ER*/
+  0x0421, /*U+0441*/ /*CYRILLIC SMALL LETTER ES*/
+  0x0422, /*U+0442*/ /*CYRILLIC SMALL LETTER TE*/
+  0x0423, /*U+0443*/ /*CYRILLIC SMALL LETTER U*/
+  0x0424, /*U+0444*/ /*CYRILLIC SMALL LETTER EF*/
+  0x0425, /*U+0445*/ /*CYRILLIC SMALL LETTER HA*/
+  0x0426, /*U+0446*/ /*CYRILLIC SMALL LETTER TSE*/
+  0x0427, /*U+0447*/ /*CYRILLIC SMALL LETTER CHE*/
+  0x0428, /*U+0448*/ /*CYRILLIC SMALL LETTER SHA*/
+  0x0429, /*U+0449*/ /*CYRILLIC SMALL LETTER SHCHA*/
+  0x042A, /*U+044A*/ /*CYRILLIC SMALL LETTER HARD SIGN*/
+  0x042B, /*U+044B*/ /*CYRILLIC SMALL LETTER YERU*/
+  0x042C, /*U+044C*/ /*CYRILLIC SMALL LETTER SOFT SIGN*/
+  0x042D, /*U+044D*/ /*CYRILLIC SMALL LETTER E*/
+  0x042E, /*U+044E*/ /*CYRILLIC SMALL LETTER YU*/
+  0x042F, /*U+044F*/ /*CYRILLIC SMALL LETTER YA*/
+  0x0400, /*U+0450*/ /*CYRILLIC SMALL LETTER IE WITH GRAVE*/
+  0x0401, /*U+0451*/ /*CYRILLIC SMALL LETTER IO*/
+  0x0402, /*U+0452*/ /*CYRILLIC SMALL LETTER DJE*/
+  0x0403, /*U+0453*/ /*CYRILLIC SMALL LETTER GJE*/
+  0x0404, /*U+0454*/ /*CYRILLIC SMALL LETTER UKRAINIAN IE*/
+  0x0405, /*U+0455*/ /*CYRILLIC SMALL LETTER DZE*/
+  0x0406, /*U+0456*/ /*CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I*/
+  0x0407, /*U+0457*/ /*CYRILLIC SMALL LETTER YI*/
+  0x0408, /*U+0458*/ /*CYRILLIC SMALL LETTER JE*/
+  0x0409, /*U+0459*/ /*CYRILLIC SMALL LETTER LJE*/
+  0x040A, /*U+045A*/ /*CYRILLIC SMALL LETTER NJE*/
+  0x040B, /*U+045B*/ /*CYRILLIC SMALL LETTER TSHE*/
+  0x040C, /*U+045C*/ /*CYRILLIC SMALL LETTER KJE*/
+  0x040D, /*U+045D*/ /*CYRILLIC SMALL LETTER I WITH GRAVE*/
+  0x040E, /*U+045E*/ /*CYRILLIC SMALL LETTER SHORT U*/
+  0x040F, /*U+045F*/ /*CYRILLIC SMALL LETTER DZHE*/
+  0x0460, /*U+0460*/ /**/
+  0x0460, /*U+0461*/ /*CYRILLIC SMALL LETTER OMEGA*/
+  0x0462, /*U+0462*/ /**/
+  0x0462, /*U+0463*/ /*CYRILLIC SMALL LETTER YAT*/
+  0x0464, /*U+0464*/ /**/
+  0x0464, /*U+0465*/ /*CYRILLIC SMALL LETTER IOTIFIED E*/
+  0x0466, /*U+0466*/ /**/
+  0x0466, /*U+0467*/ /*CYRILLIC SMALL LETTER LITTLE YUS*/
+  0x0468, /*U+0468*/ /**/
+  0x0468, /*U+0469*/ /*CYRILLIC SMALL LETTER IOTIFIED LITTLE YUS*/
+  0x046A, /*U+046A*/ /**/
+  0x046A, /*U+046B*/ /*CYRILLIC SMALL LETTER BIG YUS*/
+  0x046C, /*U+046C*/ /**/
+  0x046C, /*U+046D*/ /*CYRILLIC SMALL LETTER IOTIFIED BIG YUS*/
+  0x046E, /*U+046E*/ /**/
+  0x046E, /*U+046F*/ /*CYRILLIC SMALL LETTER KSI*/
+  0x0470, /*U+0470*/ /**/
+  0x0470, /*U+0471*/ /*CYRILLIC SMALL LETTER PSI*/
+  0x0472, /*U+0472*/ /**/
+  0x0472, /*U+0473*/ /*CYRILLIC SMALL LETTER FITA*/
+  0x0474, /*U+0474*/ /**/
+  0x0474, /*U+0475*/ /*CYRILLIC SMALL LETTER IZHITSA*/
+  0x0476, /*U+0476*/ /**/
+  0x0476, /*U+0477*/ /*CYRILLIC SMALL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT*/
+  0x0478, /*U+0478*/ /**/
+  0x0478, /*U+0479*/ /*CYRILLIC SMALL LETTER UK*/
+  0x047A, /*U+047A*/ /**/
+  0x047A, /*U+047B*/ /*CYRILLIC SMALL LETTER ROUND OMEGA*/
+  0x047C, /*U+047C*/ /**/
+  0x047C, /*U+047D*/ /*CYRILLIC SMALL LETTER OMEGA WITH TITLO*/
+  0x047E, /*U+047E*/ /**/
+  0x047E, /*U+047F*/ /*CYRILLIC SMALL LETTER OT*/
+  0x0480, /*U+0480*/ /**/
+  0x0480, /*U+0481*/ /*CYRILLIC SMALL LETTER KOPPA*/
+  0x0482, /*U+0482*/ /**/
+  0x0483, /*U+0483*/ /**/
+  0x0484, /*U+0484*/ /**/
+  0x0485, /*U+0485*/ /**/
+  0x0486, /*U+0486*/ /**/
+  0x0487, /*U+0487*/ /**/
+  0x0488, /*U+0488*/ /**/
+  0x0489, /*U+0489*/ /**/
+  0x048A, /*U+048A*/ /**/
+  0x048A, /*U+048B*/ /*CYRILLIC SMALL LETTER SHORT I WITH TAIL*/
+  0x048C, /*U+048C*/ /**/
+  0x048C, /*U+048D*/ /*CYRILLIC SMALL LETTER SEMISOFT SIGN*/
+  0x048E, /*U+048E*/ /**/
+  0x048E, /*U+048F*/ /*CYRILLIC SMALL LETTER ER WITH TICK*/
+  0x0490, /*U+0490*/ /**/
+  0x0490, /*U+0491*/ /*CYRILLIC SMALL LETTER GHE WITH UPTURN*/
+  0x0492, /*U+0492*/ /**/
+  0x0492, /*U+0493*/ /*CYRILLIC SMALL LETTER GHE WITH STROKE*/
+  0x0494, /*U+0494*/ /**/
+  0x0494, /*U+0495*/ /*CYRILLIC SMALL LETTER GHE WITH MIDDLE HOOK*/
+  0x0496, /*U+0496*/ /**/
+  0x0496, /*U+0497*/ /*CYRILLIC SMALL LETTER ZHE WITH DESCENDER*/
+  0x0498, /*U+0498*/ /**/
+  0x0498, /*U+0499*/ /*CYRILLIC SMALL LETTER ZE WITH DESCENDER*/
+  0x049A, /*U+049A*/ /**/
+  0x049A, /*U+049B*/ /*CYRILLIC SMALL LETTER KA WITH DESCENDER*/
+  0x049C, /*U+049C*/ /**/
+  0x049C, /*U+049D*/ /*CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE*/
+  0x049E, /*U+049E*/ /**/
+  0x049E, /*U+049F*/ /*CYRILLIC SMALL LETTER KA WITH STROKE*/
+  0x04A0, /*U+04A0*/ /**/
+  0x04A0, /*U+04A1*/ /*CYRILLIC SMALL LETTER BASHKIR KA*/
+  0x04A2, /*U+04A2*/ /**/
+  0x04A2, /*U+04A3*/ /*CYRILLIC SMALL LETTER EN WITH DESCENDER*/
+  0x04A4, /*U+04A4*/ /**/
+  0x04A4, /*U+04A5*/ /*CYRILLIC SMALL LIGATURE EN GHE*/
+  0x04A6, /*U+04A6*/ /**/
+  0x04A6, /*U+04A7*/ /*CYRILLIC SMALL LETTER PE WITH MIDDLE HOOK*/
+  0x04A8, /*U+04A8*/ /**/
+  0x04A8, /*U+04A9*/ /*CYRILLIC SMALL LETTER ABKHASIAN HA*/
+  0x04AA, /*U+04AA*/ /**/
+  0x04AA, /*U+04AB*/ /*CYRILLIC SMALL LETTER ES WITH DESCENDER*/
+  0x04AC, /*U+04AC*/ /**/
+  0x04AC, /*U+04AD*/ /*CYRILLIC SMALL LETTER TE WITH DESCENDER*/
+  0x04AE, /*U+04AE*/ /**/
+  0x04AE, /*U+04AF*/ /*CYRILLIC SMALL LETTER STRAIGHT U*/
+  0x04B0, /*U+04B0*/ /**/
+  0x04B0, /*U+04B1*/ /*CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE*/
+  0x04B2, /*U+04B2*/ /**/
+  0x04B2, /*U+04B3*/ /*CYRILLIC SMALL LETTER HA WITH DESCENDER*/
+  0x04B4, /*U+04B4*/ /**/
+  0x04B4, /*U+04B5*/ /*CYRILLIC SMALL LIGATURE TE TSE*/
+  0x04B6, /*U+04B6*/ /**/
+  0x04B6, /*U+04B7*/ /*CYRILLIC SMALL LETTER CHE WITH DESCENDER*/
+  0x04B8, /*U+04B8*/ /**/
+  0x04B8, /*U+04B9*/ /*CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE*/
+  0x04BA, /*U+04BA*/ /**/
+  0x04BA, /*U+04BB*/ /*CYRILLIC SMALL LETTER SHHA*/
+  0x04BC, /*U+04BC*/ /**/
+  0x04BC, /*U+04BD*/ /*CYRILLIC SMALL LETTER ABKHASIAN CHE*/
+  0x04BE, /*U+04BE*/ /**/
+  0x04BE, /*U+04BF*/ /*CYRILLIC SMALL LETTER ABKHASIAN CHE WITH DESCENDER*/
+  0x04C0, /*U+04C0*/ /**/
+  0x04C1, /*U+04C1*/ /**/
+  0x04C1, /*U+04C2*/ /*CYRILLIC SMALL LETTER ZHE WITH BREVE*/
+  0x04C3, /*U+04C3*/ /**/
+  0x04C3, /*U+04C4*/ /*CYRILLIC SMALL LETTER KA WITH HOOK*/
+  0x04C5, /*U+04C5*/ /**/
+  0x04C5, /*U+04C6*/ /*CYRILLIC SMALL LETTER EL WITH TAIL*/
+  0x04C7, /*U+04C7*/ /**/
+  0x04C7, /*U+04C8*/ /*CYRILLIC SMALL LETTER EN WITH HOOK*/
+  0x04C9, /*U+04C9*/ /**/
+  0x04C9, /*U+04CA*/ /*CYRILLIC SMALL LETTER EN WITH TAIL*/
+  0x04CB, /*U+04CB*/ /**/
+  0x04CB, /*U+04CC*/ /*CYRILLIC SMALL LETTER KHAKASSIAN CHE*/
+  0x04CD, /*U+04CD*/ /**/
+  0x04CD, /*U+04CE*/ /*CYRILLIC SMALL LETTER EM WITH TAIL*/
+  0x04C0, /*U+04CF*/ /*CYRILLIC SMALL LETTER PALOCHKA*/
+  0x04D0, /*U+04D0*/ /**/
+  0x04D0, /*U+04D1*/ /*CYRILLIC SMALL LETTER A WITH BREVE*/
+  0x04D2, /*U+04D2*/ /**/
+  0x04D2, /*U+04D3*/ /*CYRILLIC SMALL LETTER A WITH DIAERESIS*/
+  0x04D4, /*U+04D4*/ /**/
+  0x04D4, /*U+04D5*/ /*CYRILLIC SMALL LIGATURE A IE*/
+  0x04D6, /*U+04D6*/ /**/
+  0x04D6, /*U+04D7*/ /*CYRILLIC SMALL LETTER IE WITH BREVE*/
+  0x04D8, /*U+04D8*/ /**/
+  0x04D8, /*U+04D9*/ /*CYRILLIC SMALL LETTER SCHWA*/
+  0x04DA, /*U+04DA*/ /**/
+  0x04DA, /*U+04DB*/ /*CYRILLIC SMALL LETTER SCHWA WITH DIAERESIS*/
+  0x04DC, /*U+04DC*/ /**/
+  0x04DC, /*U+04DD*/ /*CYRILLIC SMALL LETTER ZHE WITH DIAERESIS*/
+  0x04DE, /*U+04DE*/ /**/
+  0x04DE, /*U+04DF*/ /*CYRILLIC SMALL LETTER ZE WITH DIAERESIS*/
+  0x04E0, /*U+04E0*/ /**/
+  0x04E0, /*U+04E1*/ /*CYRILLIC SMALL LETTER ABKHASIAN DZE*/
+  0x04E2, /*U+04E2*/ /**/
+  0x04E2, /*U+04E3*/ /*CYRILLIC SMALL LETTER I WITH MACRON*/
+  0x04E4, /*U+04E4*/ /**/
+  0x04E4, /*U+04E5*/ /*CYRILLIC SMALL LETTER I WITH DIAERESIS*/
+  0x04E6, /*U+04E6*/ /**/
+  0x04E6, /*U+04E7*/ /*CYRILLIC SMALL LETTER O WITH DIAERESIS*/
+  0x04E8, /*U+04E8*/ /**/
+  0x04E8, /*U+04E9*/ /*CYRILLIC SMALL LETTER BARRED O*/
+  0x04EA, /*U+04EA*/ /**/
+  0x04EA, /*U+04EB*/ /*CYRILLIC SMALL LETTER BARRED O WITH DIAERESIS*/
+  0x04EC, /*U+04EC*/ /**/
+  0x04EC, /*U+04ED*/ /*CYRILLIC SMALL LETTER E WITH DIAERESIS*/
+  0x04EE, /*U+04EE*/ /**/
+  0x04EE, /*U+04EF*/ /*CYRILLIC SMALL LETTER U WITH MACRON*/
+  0x04F0, /*U+04F0*/ /**/
+  0x04F0, /*U+04F1*/ /*CYRILLIC SMALL LETTER U WITH DIAERESIS*/
+  0x04F2, /*U+04F2*/ /**/
+  0x04F2, /*U+04F3*/ /*CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE*/
+  0x04F4, /*U+04F4*/ /**/
+  0x04F4, /*U+04F5*/ /*CYRILLIC SMALL LETTER CHE WITH DIAERESIS*/
+  0x04F6, /*U+04F6*/ /**/
+  0x04F6, /*U+04F7*/ /*CYRILLIC SMALL LETTER GHE WITH DESCENDER*/
+  0x04F8, /*U+04F8*/ /**/
+  0x04F8, /*U+04F9*/ /*CYRILLIC SMALL LETTER YERU WITH DIAERESIS*/
+  0x04FA, /*U+04FA*/ /**/
+  0x04FA, /*U+04FB*/ /*CYRILLIC SMALL LETTER GHE WITH STROKE AND HOOK*/
+  0x04FC, /*U+04FC*/ /**/
+  0x04FC, /*U+04FD*/ /*CYRILLIC SMALL LETTER HA WITH HOOK*/
+  0x04FE, /*U+04FE*/ /**/
+  0x04FE, /*U+04FF*/ /*CYRILLIC SMALL LETTER HA WITH STROKE*/
+  0x0500, /*U+0500*/ /**/
+  0x0500, /*U+0501*/ /*CYRILLIC SMALL LETTER KOMI DE*/
+  0x0502, /*U+0502*/ /**/
+  0x0502, /*U+0503*/ /*CYRILLIC SMALL LETTER KOMI DJE*/
+  0x0504, /*U+0504*/ /**/
+  0x0504, /*U+0505*/ /*CYRILLIC SMALL LETTER KOMI ZJE*/
+  0x0506, /*U+0506*/ /**/
+  0x0506, /*U+0507*/ /*CYRILLIC SMALL LETTER KOMI DZJE*/
+  0x0508, /*U+0508*/ /**/
+  0x0508, /*U+0509*/ /*CYRILLIC SMALL LETTER KOMI LJE*/
+  0x050A, /*U+050A*/ /**/
+  0x050A, /*U+050B*/ /*CYRILLIC SMALL LETTER KOMI NJE*/
+  0x050C, /*U+050C*/ /**/
+  0x050C, /*U+050D*/ /*CYRILLIC SMALL LETTER KOMI SJE*/
+  0x050E, /*U+050E*/ /**/
+  0x050E, /*U+050F*/ /*CYRILLIC SMALL LETTER KOMI TJE*/
+  0x0510, /*U+0510*/ /**/
+  0x0510, /*U+0511*/ /*CYRILLIC SMALL LETTER REVERSED ZE*/
+  0x0512, /*U+0512*/ /**/
+  0x0512, /*U+0513*/ /*CYRILLIC SMALL LETTER EL WITH HOOK*/
+  0x0514, /*U+0514*/ /**/
+  0x0514, /*U+0515*/ /*CYRILLIC SMALL LETTER LHA*/
+  0x0516, /*U+0516*/ /**/
+  0x0516, /*U+0517*/ /*CYRILLIC SMALL LETTER RHA*/
+  0x0518, /*U+0518*/ /**/
+  0x0518, /*U+0519*/ /*CYRILLIC SMALL LETTER YAE*/
+  0x051A, /*U+051A*/ /**/
+  0x051A, /*U+051B*/ /*CYRILLIC SMALL LETTER QA*/
+  0x051C, /*U+051C*/ /**/
+  0x051C, /*U+051D*/ /*CYRILLIC SMALL LETTER WE*/
+  0x051E, /*U+051E*/ /**/
+  0x051E, /*U+051F*/ /*CYRILLIC SMALL LETTER ALEUT KA*/
+  0x0520, /*U+0520*/ /**/
+  0x0520, /*U+0521*/ /*CYRILLIC SMALL LETTER EL WITH MIDDLE HOOK*/
+  0x0522, /*U+0522*/ /**/
+  0x0522, /*U+0523*/ /*CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK*/
+  0x0524, /*U+0524*/ /**/
+  0x0524, /*U+0525*/ /*CYRILLIC SMALL LETTER PE WITH DESCENDER*/
+  0x0526, /*U+0526*/ /**/
+  0x0526, /*U+0527*/ /*CYRILLIC SMALL LETTER SHHA WITH DESCENDER*/
+  0x0528, /*U+0528*/ /**/
+  0x0529, /*U+0529*/ /**/
+  0x052A, /*U+052A*/ /**/
+  0x052B, /*U+052B*/ /**/
+  0x052C, /*U+052C*/ /**/
+  0x052D, /*U+052D*/ /**/
+  0x052E, /*U+052E*/ /**/
+  0x052F, /*U+052F*/ /**/
+  0x0530, /*U+0530*/ /**/
+  0x0531, /*U+0531*/ /**/
+  0x0532, /*U+0532*/ /**/
+  0x0533, /*U+0533*/ /**/
+  0x0534, /*U+0534*/ /**/
+  0x0535, /*U+0535*/ /**/
+  0x0536, /*U+0536*/ /**/
+  0x0537, /*U+0537*/ /**/
+  0x0538, /*U+0538*/ /**/
+  0x0539, /*U+0539*/ /**/
+  0x053A, /*U+053A*/ /**/
+  0x053B, /*U+053B*/ /**/
+  0x053C, /*U+053C*/ /**/
+  0x053D, /*U+053D*/ /**/
+  0x053E, /*U+053E*/ /**/
+  0x053F, /*U+053F*/ /**/
+  0x0540, /*U+0540*/ /**/
+  0x0541, /*U+0541*/ /**/
+  0x0542, /*U+0542*/ /**/
+  0x0543, /*U+0543*/ /**/
+  0x0544, /*U+0544*/ /**/
+  0x0545, /*U+0545*/ /**/
+  0x0546, /*U+0546*/ /**/
+  0x0547, /*U+0547*/ /**/
+  0x0548, /*U+0548*/ /**/
+  0x0549, /*U+0549*/ /**/
+  0x054A, /*U+054A*/ /**/
+  0x054B, /*U+054B*/ /**/
+  0x054C, /*U+054C*/ /**/
+  0x054D, /*U+054D*/ /**/
+  0x054E, /*U+054E*/ /**/
+  0x054F, /*U+054F*/ /**/
+  0x0550, /*U+0550*/ /**/
+  0x0551, /*U+0551*/ /**/
+  0x0552, /*U+0552*/ /**/
+  0x0553, /*U+0553*/ /**/
+  0x0554, /*U+0554*/ /**/
+  0x0555, /*U+0555*/ /**/
+  0x0556, /*U+0556*/ /**/
+  0x0557, /*U+0557*/ /**/
+  0x0558, /*U+0558*/ /**/
+  0x0559, /*U+0559*/ /**/
+  0x055A, /*U+055A*/ /**/
+  0x055B, /*U+055B*/ /**/
+  0x055C, /*U+055C*/ /**/
+  0x055D, /*U+055D*/ /**/
+  0x055E, /*U+055E*/ /**/
+  0x055F, /*U+055F*/ /**/
+  0x0560, /*U+0560*/ /**/
+  0x0531, /*U+0561*/ /*ARMENIAN SMALL LETTER AYB*/
+  0x0532, /*U+0562*/ /*ARMENIAN SMALL LETTER BEN*/
+  0x0533, /*U+0563*/ /*ARMENIAN SMALL LETTER GIM*/
+  0x0534, /*U+0564*/ /*ARMENIAN SMALL LETTER DA*/
+  0x0535, /*U+0565*/ /*ARMENIAN SMALL LETTER ECH*/
+  0x0536, /*U+0566*/ /*ARMENIAN SMALL LETTER ZA*/
+  0x0537, /*U+0567*/ /*ARMENIAN SMALL LETTER EH*/
+  0x0538, /*U+0568*/ /*ARMENIAN SMALL LETTER ET*/
+  0x0539, /*U+0569*/ /*ARMENIAN SMALL LETTER TO*/
+  0x053A, /*U+056A*/ /*ARMENIAN SMALL LETTER ZHE*/
+  0x053B, /*U+056B*/ /*ARMENIAN SMALL LETTER INI*/
+  0x053C, /*U+056C*/ /*ARMENIAN SMALL LETTER LIWN*/
+  0x053D, /*U+056D*/ /*ARMENIAN SMALL LETTER XEH*/
+  0x053E, /*U+056E*/ /*ARMENIAN SMALL LETTER CA*/
+  0x053F, /*U+056F*/ /*ARMENIAN SMALL LETTER KEN*/
+  0x0540, /*U+0570*/ /*ARMENIAN SMALL LETTER HO*/
+  0x0541, /*U+0571*/ /*ARMENIAN SMALL LETTER JA*/
+  0x0542, /*U+0572*/ /*ARMENIAN SMALL LETTER GHAD*/
+  0x0543, /*U+0573*/ /*ARMENIAN SMALL LETTER CHEH*/
+  0x0544, /*U+0574*/ /*ARMENIAN SMALL LETTER MEN*/
+  0x0545, /*U+0575*/ /*ARMENIAN SMALL LETTER YI*/
+  0x0546, /*U+0576*/ /*ARMENIAN SMALL LETTER NOW*/
+  0x0547, /*U+0577*/ /*ARMENIAN SMALL LETTER SHA*/
+  0x0548, /*U+0578*/ /*ARMENIAN SMALL LETTER VO*/
+  0x0549, /*U+0579*/ /*ARMENIAN SMALL LETTER CHA*/
+  0x054A, /*U+057A*/ /*ARMENIAN SMALL LETTER PEH*/
+  0x054B, /*U+057B*/ /*ARMENIAN SMALL LETTER JHEH*/
+  0x054C, /*U+057C*/ /*ARMENIAN SMALL LETTER RA*/
+  0x054D, /*U+057D*/ /*ARMENIAN SMALL LETTER SEH*/
+  0x054E, /*U+057E*/ /*ARMENIAN SMALL LETTER VEW*/
+  0x054F, /*U+057F*/ /*ARMENIAN SMALL LETTER TIWN*/
+  0x0550, /*U+0580*/ /*ARMENIAN SMALL LETTER REH*/
+  0x0551, /*U+0581*/ /*ARMENIAN SMALL LETTER CO*/
+  0x0552, /*U+0582*/ /*ARMENIAN SMALL LETTER YIWN*/
+  0x0553, /*U+0583*/ /*ARMENIAN SMALL LETTER PIWR*/
+  0x0554, /*U+0584*/ /*ARMENIAN SMALL LETTER KEH*/
+  0x0555, /*U+0585*/ /*ARMENIAN SMALL LETTER OH*/
+  0x0556, /*U+0586*/ /*ARMENIAN SMALL LETTER FEH*/
+  0x0587, /*U+0587*/ /**/
+  0x0588, /*U+0588*/ /**/
+  0x0589, /*U+0589*/ /**/
+  0x058A, /*U+058A*/ /**/
+  0x058B, /*U+058B*/ /**/
+  0x058C, /*U+058C*/ /**/
+  0x058D, /*U+058D*/ /**/
+  0x058E, /*U+058E*/ /**/
+  0x058F, /*U+058F*/ /**/
+  0x0590, /*U+0590*/ /**/
+  0x0591, /*U+0591*/ /**/
+  0x0592, /*U+0592*/ /**/
+  0x0593, /*U+0593*/ /**/
+  0x0594, /*U+0594*/ /**/
+  0x0595, /*U+0595*/ /**/
+  0x0596, /*U+0596*/ /**/
+  0x0597, /*U+0597*/ /**/
+  0x0598, /*U+0598*/ /**/
+  0x0599, /*U+0599*/ /**/
+  0x059A, /*U+059A*/ /**/
+  0x059B, /*U+059B*/ /**/
+  0x059C, /*U+059C*/ /**/
+  0x059D, /*U+059D*/ /**/
+  0x059E, /*U+059E*/ /**/
+  0x059F, /*U+059F*/ /**/
+  0x05A0, /*U+05A0*/ /**/
+  0x05A1, /*U+05A1*/ /**/
+  0x05A2, /*U+05A2*/ /**/
+  0x05A3, /*U+05A3*/ /**/
+  0x05A4, /*U+05A4*/ /**/
+  0x05A5, /*U+05A5*/ /**/
+  0x05A6, /*U+05A6*/ /**/
+  0x05A7, /*U+05A7*/ /**/
+  0x05A8, /*U+05A8*/ /**/
+  0x05A9, /*U+05A9*/ /**/
+  0x05AA, /*U+05AA*/ /**/
+  0x05AB, /*U+05AB*/ /**/
+  0x05AC, /*U+05AC*/ /**/
+  0x05AD, /*U+05AD*/ /**/
+  0x05AE, /*U+05AE*/ /**/
+  0x05AF, /*U+05AF*/ /**/
+  0x05B0, /*U+05B0*/ /**/
+  0x05B1, /*U+05B1*/ /**/
+  0x05B2, /*U+05B2*/ /**/
+  0x05B3, /*U+05B3*/ /**/
+  0x05B4, /*U+05B4*/ /**/
+  0x05B5, /*U+05B5*/ /**/
+  0x05B6, /*U+05B6*/ /**/
+  0x05B7, /*U+05B7*/ /**/
+  0x05B8, /*U+05B8*/ /**/
+  0x05B9, /*U+05B9*/ /**/
+  0x05BA, /*U+05BA*/ /**/
+  0x05BB, /*U+05BB*/ /**/
+  0x05BC, /*U+05BC*/ /**/
+  0x05BD, /*U+05BD*/ /**/
+  0x05BE, /*U+05BE*/ /**/
+  0x05BF, /*U+05BF*/ /**/
+};
+
+static const u_int16_t upper_table_3[64] = {
+  0x1D40, /*U+1D40*/ /**/
+  0x1D41, /*U+1D41*/ /**/
+  0x1D42, /*U+1D42*/ /**/
+  0x1D43, /*U+1D43*/ /**/
+  0x1D44, /*U+1D44*/ /**/
+  0x1D45, /*U+1D45*/ /**/
+  0x1D46, /*U+1D46*/ /**/
+  0x1D47, /*U+1D47*/ /**/
+  0x1D48, /*U+1D48*/ /**/
+  0x1D49, /*U+1D49*/ /**/
+  0x1D4A, /*U+1D4A*/ /**/
+  0x1D4B, /*U+1D4B*/ /**/
+  0x1D4C, /*U+1D4C*/ /**/
+  0x1D4D, /*U+1D4D*/ /**/
+  0x1D4E, /*U+1D4E*/ /**/
+  0x1D4F, /*U+1D4F*/ /**/
+  0x1D50, /*U+1D50*/ /**/
+  0x1D51, /*U+1D51*/ /**/
+  0x1D52, /*U+1D52*/ /**/
+  0x1D53, /*U+1D53*/ /**/
+  0x1D54, /*U+1D54*/ /**/
+  0x1D55, /*U+1D55*/ /**/
+  0x1D56, /*U+1D56*/ /**/
+  0x1D57, /*U+1D57*/ /**/
+  0x1D58, /*U+1D58*/ /**/
+  0x1D59, /*U+1D59*/ /**/
+  0x1D5A, /*U+1D5A*/ /**/
+  0x1D5B, /*U+1D5B*/ /**/
+  0x1D5C, /*U+1D5C*/ /**/
+  0x1D5D, /*U+1D5D*/ /**/
+  0x1D5E, /*U+1D5E*/ /**/
+  0x1D5F, /*U+1D5F*/ /**/
+  0x1D60, /*U+1D60*/ /**/
+  0x1D61, /*U+1D61*/ /**/
+  0x1D62, /*U+1D62*/ /**/
+  0x1D63, /*U+1D63*/ /**/
+  0x1D64, /*U+1D64*/ /**/
+  0x1D65, /*U+1D65*/ /**/
+  0x1D66, /*U+1D66*/ /**/
+  0x1D67, /*U+1D67*/ /**/
+  0x1D68, /*U+1D68*/ /**/
+  0x1D69, /*U+1D69*/ /**/
+  0x1D6A, /*U+1D6A*/ /**/
+  0x1D6B, /*U+1D6B*/ /**/
+  0x1D6C, /*U+1D6C*/ /**/
+  0x1D6D, /*U+1D6D*/ /**/
+  0x1D6E, /*U+1D6E*/ /**/
+  0x1D6F, /*U+1D6F*/ /**/
+  0x1D70, /*U+1D70*/ /**/
+  0x1D71, /*U+1D71*/ /**/
+  0x1D72, /*U+1D72*/ /**/
+  0x1D73, /*U+1D73*/ /**/
+  0x1D74, /*U+1D74*/ /**/
+  0x1D75, /*U+1D75*/ /**/
+  0x1D76, /*U+1D76*/ /**/
+  0x1D77, /*U+1D77*/ /**/
+  0x1D78, /*U+1D78*/ /**/
+  0xA77D, /*U+1D79*/ /*LATIN SMALL LETTER INSULAR G*/
+  0x1D7A, /*U+1D7A*/ /**/
+  0x1D7B, /*U+1D7B*/ /**/
+  0x1D7C, /*U+1D7C*/ /**/
+  0x2C63, /*U+1D7D*/ /*LATIN SMALL LETTER P WITH STROKE*/
+  0x1D7E, /*U+1D7E*/ /**/
+  0x1D7F, /*U+1D7F*/ /**/
+};
+
+static const u_int16_t upper_table_4[512] = {
+  0x1E00, /*U+1E00*/ /**/
+  0x1E00, /*U+1E01*/ /*LATIN SMALL LETTER A WITH RING BELOW*/
+  0x1E02, /*U+1E02*/ /**/
+  0x1E02, /*U+1E03*/ /*LATIN SMALL LETTER B WITH DOT ABOVE*/
+  0x1E04, /*U+1E04*/ /**/
+  0x1E04, /*U+1E05*/ /*LATIN SMALL LETTER B WITH DOT BELOW*/
+  0x1E06, /*U+1E06*/ /**/
+  0x1E06, /*U+1E07*/ /*LATIN SMALL LETTER B WITH LINE BELOW*/
+  0x1E08, /*U+1E08*/ /**/
+  0x1E08, /*U+1E09*/ /*LATIN SMALL LETTER C WITH CEDILLA AND ACUTE*/
+  0x1E0A, /*U+1E0A*/ /**/
+  0x1E0A, /*U+1E0B*/ /*LATIN SMALL LETTER D WITH DOT ABOVE*/
+  0x1E0C, /*U+1E0C*/ /**/
+  0x1E0C, /*U+1E0D*/ /*LATIN SMALL LETTER D WITH DOT BELOW*/
+  0x1E0E, /*U+1E0E*/ /**/
+  0x1E0E, /*U+1E0F*/ /*LATIN SMALL LETTER D WITH LINE BELOW*/
+  0x1E10, /*U+1E10*/ /**/
+  0x1E10, /*U+1E11*/ /*LATIN SMALL LETTER D WITH CEDILLA*/
+  0x1E12, /*U+1E12*/ /**/
+  0x1E12, /*U+1E13*/ /*LATIN SMALL LETTER D WITH CIRCUMFLEX BELOW*/
+  0x1E14, /*U+1E14*/ /**/
+  0x1E14, /*U+1E15*/ /*LATIN SMALL LETTER E WITH MACRON AND GRAVE*/
+  0x1E16, /*U+1E16*/ /**/
+  0x1E16, /*U+1E17*/ /*LATIN SMALL LETTER E WITH MACRON AND ACUTE*/
+  0x1E18, /*U+1E18*/ /**/
+  0x1E18, /*U+1E19*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX BELOW*/
+  0x1E1A, /*U+1E1A*/ /**/
+  0x1E1A, /*U+1E1B*/ /*LATIN SMALL LETTER E WITH TILDE BELOW*/
+  0x1E1C, /*U+1E1C*/ /**/
+  0x1E1C, /*U+1E1D*/ /*LATIN SMALL LETTER E WITH CEDILLA AND BREVE*/
+  0x1E1E, /*U+1E1E*/ /**/
+  0x1E1E, /*U+1E1F*/ /*LATIN SMALL LETTER F WITH DOT ABOVE*/
+  0x1E20, /*U+1E20*/ /**/
+  0x1E20, /*U+1E21*/ /*LATIN SMALL LETTER G WITH MACRON*/
+  0x1E22, /*U+1E22*/ /**/
+  0x1E22, /*U+1E23*/ /*LATIN SMALL LETTER H WITH DOT ABOVE*/
+  0x1E24, /*U+1E24*/ /**/
+  0x1E24, /*U+1E25*/ /*LATIN SMALL LETTER H WITH DOT BELOW*/
+  0x1E26, /*U+1E26*/ /**/
+  0x1E26, /*U+1E27*/ /*LATIN SMALL LETTER H WITH DIAERESIS*/
+  0x1E28, /*U+1E28*/ /**/
+  0x1E28, /*U+1E29*/ /*LATIN SMALL LETTER H WITH CEDILLA*/
+  0x1E2A, /*U+1E2A*/ /**/
+  0x1E2A, /*U+1E2B*/ /*LATIN SMALL LETTER H WITH BREVE BELOW*/
+  0x1E2C, /*U+1E2C*/ /**/
+  0x1E2C, /*U+1E2D*/ /*LATIN SMALL LETTER I WITH TILDE BELOW*/
+  0x1E2E, /*U+1E2E*/ /**/
+  0x1E2E, /*U+1E2F*/ /*LATIN SMALL LETTER I WITH DIAERESIS AND ACUTE*/
+  0x1E30, /*U+1E30*/ /**/
+  0x1E30, /*U+1E31*/ /*LATIN SMALL LETTER K WITH ACUTE*/
+  0x1E32, /*U+1E32*/ /**/
+  0x1E32, /*U+1E33*/ /*LATIN SMALL LETTER K WITH DOT BELOW*/
+  0x1E34, /*U+1E34*/ /**/
+  0x1E34, /*U+1E35*/ /*LATIN SMALL LETTER K WITH LINE BELOW*/
+  0x1E36, /*U+1E36*/ /**/
+  0x1E36, /*U+1E37*/ /*LATIN SMALL LETTER L WITH DOT BELOW*/
+  0x1E38, /*U+1E38*/ /**/
+  0x1E38, /*U+1E39*/ /*LATIN SMALL LETTER L WITH DOT BELOW AND MACRON*/
+  0x1E3A, /*U+1E3A*/ /**/
+  0x1E3A, /*U+1E3B*/ /*LATIN SMALL LETTER L WITH LINE BELOW*/
+  0x1E3C, /*U+1E3C*/ /**/
+  0x1E3C, /*U+1E3D*/ /*LATIN SMALL LETTER L WITH CIRCUMFLEX BELOW*/
+  0x1E3E, /*U+1E3E*/ /**/
+  0x1E3E, /*U+1E3F*/ /*LATIN SMALL LETTER M WITH ACUTE*/
+  0x1E40, /*U+1E40*/ /**/
+  0x1E40, /*U+1E41*/ /*LATIN SMALL LETTER M WITH DOT ABOVE*/
+  0x1E42, /*U+1E42*/ /**/
+  0x1E42, /*U+1E43*/ /*LATIN SMALL LETTER M WITH DOT BELOW*/
+  0x1E44, /*U+1E44*/ /**/
+  0x1E44, /*U+1E45*/ /*LATIN SMALL LETTER N WITH DOT ABOVE*/
+  0x1E46, /*U+1E46*/ /**/
+  0x1E46, /*U+1E47*/ /*LATIN SMALL LETTER N WITH DOT BELOW*/
+  0x1E48, /*U+1E48*/ /**/
+  0x1E48, /*U+1E49*/ /*LATIN SMALL LETTER N WITH LINE BELOW*/
+  0x1E4A, /*U+1E4A*/ /**/
+  0x1E4A, /*U+1E4B*/ /*LATIN SMALL LETTER N WITH CIRCUMFLEX BELOW*/
+  0x1E4C, /*U+1E4C*/ /**/
+  0x1E4C, /*U+1E4D*/ /*LATIN SMALL LETTER O WITH TILDE AND ACUTE*/
+  0x1E4E, /*U+1E4E*/ /**/
+  0x1E4E, /*U+1E4F*/ /*LATIN SMALL LETTER O WITH TILDE AND DIAERESIS*/
+  0x1E50, /*U+1E50*/ /**/
+  0x1E50, /*U+1E51*/ /*LATIN SMALL LETTER O WITH MACRON AND GRAVE*/
+  0x1E52, /*U+1E52*/ /**/
+  0x1E52, /*U+1E53*/ /*LATIN SMALL LETTER O WITH MACRON AND ACUTE*/
+  0x1E54, /*U+1E54*/ /**/
+  0x1E54, /*U+1E55*/ /*LATIN SMALL LETTER P WITH ACUTE*/
+  0x1E56, /*U+1E56*/ /**/
+  0x1E56, /*U+1E57*/ /*LATIN SMALL LETTER P WITH DOT ABOVE*/
+  0x1E58, /*U+1E58*/ /**/
+  0x1E58, /*U+1E59*/ /*LATIN SMALL LETTER R WITH DOT ABOVE*/
+  0x1E5A, /*U+1E5A*/ /**/
+  0x1E5A, /*U+1E5B*/ /*LATIN SMALL LETTER R WITH DOT BELOW*/
+  0x1E5C, /*U+1E5C*/ /**/
+  0x1E5C, /*U+1E5D*/ /*LATIN SMALL LETTER R WITH DOT BELOW AND MACRON*/
+  0x1E5E, /*U+1E5E*/ /**/
+  0x1E5E, /*U+1E5F*/ /*LATIN SMALL LETTER R WITH LINE BELOW*/
+  0x1E60, /*U+1E60*/ /**/
+  0x1E60, /*U+1E61*/ /*LATIN SMALL LETTER S WITH DOT ABOVE*/
+  0x1E62, /*U+1E62*/ /**/
+  0x1E62, /*U+1E63*/ /*LATIN SMALL LETTER S WITH DOT BELOW*/
+  0x1E64, /*U+1E64*/ /**/
+  0x1E64, /*U+1E65*/ /*LATIN SMALL LETTER S WITH ACUTE AND DOT ABOVE*/
+  0x1E66, /*U+1E66*/ /**/
+  0x1E66, /*U+1E67*/ /*LATIN SMALL LETTER S WITH CARON AND DOT ABOVE*/
+  0x1E68, /*U+1E68*/ /**/
+  0x1E68, /*U+1E69*/ /*LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE*/
+  0x1E6A, /*U+1E6A*/ /**/
+  0x1E6A, /*U+1E6B*/ /*LATIN SMALL LETTER T WITH DOT ABOVE*/
+  0x1E6C, /*U+1E6C*/ /**/
+  0x1E6C, /*U+1E6D*/ /*LATIN SMALL LETTER T WITH DOT BELOW*/
+  0x1E6E, /*U+1E6E*/ /**/
+  0x1E6E, /*U+1E6F*/ /*LATIN SMALL LETTER T WITH LINE BELOW*/
+  0x1E70, /*U+1E70*/ /**/
+  0x1E70, /*U+1E71*/ /*LATIN SMALL LETTER T WITH CIRCUMFLEX BELOW*/
+  0x1E72, /*U+1E72*/ /**/
+  0x1E72, /*U+1E73*/ /*LATIN SMALL LETTER U WITH DIAERESIS BELOW*/
+  0x1E74, /*U+1E74*/ /**/
+  0x1E74, /*U+1E75*/ /*LATIN SMALL LETTER U WITH TILDE BELOW*/
+  0x1E76, /*U+1E76*/ /**/
+  0x1E76, /*U+1E77*/ /*LATIN SMALL LETTER U WITH CIRCUMFLEX BELOW*/
+  0x1E78, /*U+1E78*/ /**/
+  0x1E78, /*U+1E79*/ /*LATIN SMALL LETTER U WITH TILDE AND ACUTE*/
+  0x1E7A, /*U+1E7A*/ /**/
+  0x1E7A, /*U+1E7B*/ /*LATIN SMALL LETTER U WITH MACRON AND DIAERESIS*/
+  0x1E7C, /*U+1E7C*/ /**/
+  0x1E7C, /*U+1E7D*/ /*LATIN SMALL LETTER V WITH TILDE*/
+  0x1E7E, /*U+1E7E*/ /**/
+  0x1E7E, /*U+1E7F*/ /*LATIN SMALL LETTER V WITH DOT BELOW*/
+  0x1E80, /*U+1E80*/ /**/
+  0x1E80, /*U+1E81*/ /*LATIN SMALL LETTER W WITH GRAVE*/
+  0x1E82, /*U+1E82*/ /**/
+  0x1E82, /*U+1E83*/ /*LATIN SMALL LETTER W WITH ACUTE*/
+  0x1E84, /*U+1E84*/ /**/
+  0x1E84, /*U+1E85*/ /*LATIN SMALL LETTER W WITH DIAERESIS*/
+  0x1E86, /*U+1E86*/ /**/
+  0x1E86, /*U+1E87*/ /*LATIN SMALL LETTER W WITH DOT ABOVE*/
+  0x1E88, /*U+1E88*/ /**/
+  0x1E88, /*U+1E89*/ /*LATIN SMALL LETTER W WITH DOT BELOW*/
+  0x1E8A, /*U+1E8A*/ /**/
+  0x1E8A, /*U+1E8B*/ /*LATIN SMALL LETTER X WITH DOT ABOVE*/
+  0x1E8C, /*U+1E8C*/ /**/
+  0x1E8C, /*U+1E8D*/ /*LATIN SMALL LETTER X WITH DIAERESIS*/
+  0x1E8E, /*U+1E8E*/ /**/
+  0x1E8E, /*U+1E8F*/ /*LATIN SMALL LETTER Y WITH DOT ABOVE*/
+  0x1E90, /*U+1E90*/ /**/
+  0x1E90, /*U+1E91*/ /*LATIN SMALL LETTER Z WITH CIRCUMFLEX*/
+  0x1E92, /*U+1E92*/ /**/
+  0x1E92, /*U+1E93*/ /*LATIN SMALL LETTER Z WITH DOT BELOW*/
+  0x1E94, /*U+1E94*/ /**/
+  0x1E94, /*U+1E95*/ /*LATIN SMALL LETTER Z WITH LINE BELOW*/
+  0x1E96, /*U+1E96*/ /**/
+  0x1E97, /*U+1E97*/ /**/
+  0x1E98, /*U+1E98*/ /**/
+  0x1E99, /*U+1E99*/ /**/
+  0x1E9A, /*U+1E9A*/ /**/
+  0x1E60, /*U+1E9B*/ /*LATIN SMALL LETTER LONG S WITH DOT ABOVE*/
+  0x1E9C, /*U+1E9C*/ /**/
+  0x1E9D, /*U+1E9D*/ /**/
+  0x1E9E, /*U+1E9E*/ /**/
+  0x1E9F, /*U+1E9F*/ /**/
+  0x1EA0, /*U+1EA0*/ /**/
+  0x1EA0, /*U+1EA1*/ /*LATIN SMALL LETTER A WITH DOT BELOW*/
+  0x1EA2, /*U+1EA2*/ /**/
+  0x1EA2, /*U+1EA3*/ /*LATIN SMALL LETTER A WITH HOOK ABOVE*/
+  0x1EA4, /*U+1EA4*/ /**/
+  0x1EA4, /*U+1EA5*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE*/
+  0x1EA6, /*U+1EA6*/ /**/
+  0x1EA6, /*U+1EA7*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE*/
+  0x1EA8, /*U+1EA8*/ /**/
+  0x1EA8, /*U+1EA9*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1EAA, /*U+1EAA*/ /**/
+  0x1EAA, /*U+1EAB*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE*/
+  0x1EAC, /*U+1EAC*/ /**/
+  0x1EAC, /*U+1EAD*/ /*LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1EAE, /*U+1EAE*/ /**/
+  0x1EAE, /*U+1EAF*/ /*LATIN SMALL LETTER A WITH BREVE AND ACUTE*/
+  0x1EB0, /*U+1EB0*/ /**/
+  0x1EB0, /*U+1EB1*/ /*LATIN SMALL LETTER A WITH BREVE AND GRAVE*/
+  0x1EB2, /*U+1EB2*/ /**/
+  0x1EB2, /*U+1EB3*/ /*LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE*/
+  0x1EB4, /*U+1EB4*/ /**/
+  0x1EB4, /*U+1EB5*/ /*LATIN SMALL LETTER A WITH BREVE AND TILDE*/
+  0x1EB6, /*U+1EB6*/ /**/
+  0x1EB6, /*U+1EB7*/ /*LATIN SMALL LETTER A WITH BREVE AND DOT BELOW*/
+  0x1EB8, /*U+1EB8*/ /**/
+  0x1EB8, /*U+1EB9*/ /*LATIN SMALL LETTER E WITH DOT BELOW*/
+  0x1EBA, /*U+1EBA*/ /**/
+  0x1EBA, /*U+1EBB*/ /*LATIN SMALL LETTER E WITH HOOK ABOVE*/
+  0x1EBC, /*U+1EBC*/ /**/
+  0x1EBC, /*U+1EBD*/ /*LATIN SMALL LETTER E WITH TILDE*/
+  0x1EBE, /*U+1EBE*/ /**/
+  0x1EBE, /*U+1EBF*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE*/
+  0x1EC0, /*U+1EC0*/ /**/
+  0x1EC0, /*U+1EC1*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE*/
+  0x1EC2, /*U+1EC2*/ /**/
+  0x1EC2, /*U+1EC3*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1EC4, /*U+1EC4*/ /**/
+  0x1EC4, /*U+1EC5*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE*/
+  0x1EC6, /*U+1EC6*/ /**/
+  0x1EC6, /*U+1EC7*/ /*LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1EC8, /*U+1EC8*/ /**/
+  0x1EC8, /*U+1EC9*/ /*LATIN SMALL LETTER I WITH HOOK ABOVE*/
+  0x1ECA, /*U+1ECA*/ /**/
+  0x1ECA, /*U+1ECB*/ /*LATIN SMALL LETTER I WITH DOT BELOW*/
+  0x1ECC, /*U+1ECC*/ /**/
+  0x1ECC, /*U+1ECD*/ /*LATIN SMALL LETTER O WITH DOT BELOW*/
+  0x1ECE, /*U+1ECE*/ /**/
+  0x1ECE, /*U+1ECF*/ /*LATIN SMALL LETTER O WITH HOOK ABOVE*/
+  0x1ED0, /*U+1ED0*/ /**/
+  0x1ED0, /*U+1ED1*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE*/
+  0x1ED2, /*U+1ED2*/ /**/
+  0x1ED2, /*U+1ED3*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE*/
+  0x1ED4, /*U+1ED4*/ /**/
+  0x1ED4, /*U+1ED5*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1ED6, /*U+1ED6*/ /**/
+  0x1ED6, /*U+1ED7*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE*/
+  0x1ED8, /*U+1ED8*/ /**/
+  0x1ED8, /*U+1ED9*/ /*LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1EDA, /*U+1EDA*/ /**/
+  0x1EDA, /*U+1EDB*/ /*LATIN SMALL LETTER O WITH HORN AND ACUTE*/
+  0x1EDC, /*U+1EDC*/ /**/
+  0x1EDC, /*U+1EDD*/ /*LATIN SMALL LETTER O WITH HORN AND GRAVE*/
+  0x1EDE, /*U+1EDE*/ /**/
+  0x1EDE, /*U+1EDF*/ /*LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE*/
+  0x1EE0, /*U+1EE0*/ /**/
+  0x1EE0, /*U+1EE1*/ /*LATIN SMALL LETTER O WITH HORN AND TILDE*/
+  0x1EE2, /*U+1EE2*/ /**/
+  0x1EE2, /*U+1EE3*/ /*LATIN SMALL LETTER O WITH HORN AND DOT BELOW*/
+  0x1EE4, /*U+1EE4*/ /**/
+  0x1EE4, /*U+1EE5*/ /*LATIN SMALL LETTER U WITH DOT BELOW*/
+  0x1EE6, /*U+1EE6*/ /**/
+  0x1EE6, /*U+1EE7*/ /*LATIN SMALL LETTER U WITH HOOK ABOVE*/
+  0x1EE8, /*U+1EE8*/ /**/
+  0x1EE8, /*U+1EE9*/ /*LATIN SMALL LETTER U WITH HORN AND ACUTE*/
+  0x1EEA, /*U+1EEA*/ /**/
+  0x1EEA, /*U+1EEB*/ /*LATIN SMALL LETTER U WITH HORN AND GRAVE*/
+  0x1EEC, /*U+1EEC*/ /**/
+  0x1EEC, /*U+1EED*/ /*LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE*/
+  0x1EEE, /*U+1EEE*/ /**/
+  0x1EEE, /*U+1EEF*/ /*LATIN SMALL LETTER U WITH HORN AND TILDE*/
+  0x1EF0, /*U+1EF0*/ /**/
+  0x1EF0, /*U+1EF1*/ /*LATIN SMALL LETTER U WITH HORN AND DOT BELOW*/
+  0x1EF2, /*U+1EF2*/ /**/
+  0x1EF2, /*U+1EF3*/ /*LATIN SMALL LETTER Y WITH GRAVE*/
+  0x1EF4, /*U+1EF4*/ /**/
+  0x1EF4, /*U+1EF5*/ /*LATIN SMALL LETTER Y WITH DOT BELOW*/
+  0x1EF6, /*U+1EF6*/ /**/
+  0x1EF6, /*U+1EF7*/ /*LATIN SMALL LETTER Y WITH HOOK ABOVE*/
+  0x1EF8, /*U+1EF8*/ /**/
+  0x1EF8, /*U+1EF9*/ /*LATIN SMALL LETTER Y WITH TILDE*/
+  0x1EFA, /*U+1EFA*/ /**/
+  0x1EFA, /*U+1EFB*/ /*LATIN SMALL LETTER MIDDLE-WELSH LL*/
+  0x1EFC, /*U+1EFC*/ /**/
+  0x1EFC, /*U+1EFD*/ /*LATIN SMALL LETTER MIDDLE-WELSH V*/
+  0x1EFE, /*U+1EFE*/ /**/
+  0x1EFE, /*U+1EFF*/ /*LATIN SMALL LETTER Y WITH LOOP*/
+  0x1F08, /*U+1F00*/ /*GREEK SMALL LETTER ALPHA WITH PSILI*/
+  0x1F09, /*U+1F01*/ /*GREEK SMALL LETTER ALPHA WITH DASIA*/
+  0x1F0A, /*U+1F02*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA*/
+  0x1F0B, /*U+1F03*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA*/
+  0x1F0C, /*U+1F04*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA*/
+  0x1F0D, /*U+1F05*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA*/
+  0x1F0E, /*U+1F06*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI*/
+  0x1F0F, /*U+1F07*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI*/
+  0x1F08, /*U+1F08*/ /**/
+  0x1F09, /*U+1F09*/ /**/
+  0x1F0A, /*U+1F0A*/ /**/
+  0x1F0B, /*U+1F0B*/ /**/
+  0x1F0C, /*U+1F0C*/ /**/
+  0x1F0D, /*U+1F0D*/ /**/
+  0x1F0E, /*U+1F0E*/ /**/
+  0x1F0F, /*U+1F0F*/ /**/
+  0x1F18, /*U+1F10*/ /*GREEK SMALL LETTER EPSILON WITH PSILI*/
+  0x1F19, /*U+1F11*/ /*GREEK SMALL LETTER EPSILON WITH DASIA*/
+  0x1F1A, /*U+1F12*/ /*GREEK SMALL LETTER EPSILON WITH PSILI AND VARIA*/
+  0x1F1B, /*U+1F13*/ /*GREEK SMALL LETTER EPSILON WITH DASIA AND VARIA*/
+  0x1F1C, /*U+1F14*/ /*GREEK SMALL LETTER EPSILON WITH PSILI AND OXIA*/
+  0x1F1D, /*U+1F15*/ /*GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA*/
+  0x1F16, /*U+1F16*/ /**/
+  0x1F17, /*U+1F17*/ /**/
+  0x1F18, /*U+1F18*/ /**/
+  0x1F19, /*U+1F19*/ /**/
+  0x1F1A, /*U+1F1A*/ /**/
+  0x1F1B, /*U+1F1B*/ /**/
+  0x1F1C, /*U+1F1C*/ /**/
+  0x1F1D, /*U+1F1D*/ /**/
+  0x1F1E, /*U+1F1E*/ /**/
+  0x1F1F, /*U+1F1F*/ /**/
+  0x1F28, /*U+1F20*/ /*GREEK SMALL LETTER ETA WITH PSILI*/
+  0x1F29, /*U+1F21*/ /*GREEK SMALL LETTER ETA WITH DASIA*/
+  0x1F2A, /*U+1F22*/ /*GREEK SMALL LETTER ETA WITH PSILI AND VARIA*/
+  0x1F2B, /*U+1F23*/ /*GREEK SMALL LETTER ETA WITH DASIA AND VARIA*/
+  0x1F2C, /*U+1F24*/ /*GREEK SMALL LETTER ETA WITH PSILI AND OXIA*/
+  0x1F2D, /*U+1F25*/ /*GREEK SMALL LETTER ETA WITH DASIA AND OXIA*/
+  0x1F2E, /*U+1F26*/ /*GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI*/
+  0x1F2F, /*U+1F27*/ /*GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI*/
+  0x1F28, /*U+1F28*/ /**/
+  0x1F29, /*U+1F29*/ /**/
+  0x1F2A, /*U+1F2A*/ /**/
+  0x1F2B, /*U+1F2B*/ /**/
+  0x1F2C, /*U+1F2C*/ /**/
+  0x1F2D, /*U+1F2D*/ /**/
+  0x1F2E, /*U+1F2E*/ /**/
+  0x1F2F, /*U+1F2F*/ /**/
+  0x1F38, /*U+1F30*/ /*GREEK SMALL LETTER IOTA WITH PSILI*/
+  0x1F39, /*U+1F31*/ /*GREEK SMALL LETTER IOTA WITH DASIA*/
+  0x1F3A, /*U+1F32*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND VARIA*/
+  0x1F3B, /*U+1F33*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND VARIA*/
+  0x1F3C, /*U+1F34*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND OXIA*/
+  0x1F3D, /*U+1F35*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND OXIA*/
+  0x1F3E, /*U+1F36*/ /*GREEK SMALL LETTER IOTA WITH PSILI AND PERISPOMENI*/
+  0x1F3F, /*U+1F37*/ /*GREEK SMALL LETTER IOTA WITH DASIA AND PERISPOMENI*/
+  0x1F38, /*U+1F38*/ /**/
+  0x1F39, /*U+1F39*/ /**/
+  0x1F3A, /*U+1F3A*/ /**/
+  0x1F3B, /*U+1F3B*/ /**/
+  0x1F3C, /*U+1F3C*/ /**/
+  0x1F3D, /*U+1F3D*/ /**/
+  0x1F3E, /*U+1F3E*/ /**/
+  0x1F3F, /*U+1F3F*/ /**/
+  0x1F48, /*U+1F40*/ /*GREEK SMALL LETTER OMICRON WITH PSILI*/
+  0x1F49, /*U+1F41*/ /*GREEK SMALL LETTER OMICRON WITH DASIA*/
+  0x1F4A, /*U+1F42*/ /*GREEK SMALL LETTER OMICRON WITH PSILI AND VARIA*/
+  0x1F4B, /*U+1F43*/ /*GREEK SMALL LETTER OMICRON WITH DASIA AND VARIA*/
+  0x1F4C, /*U+1F44*/ /*GREEK SMALL LETTER OMICRON WITH PSILI AND OXIA*/
+  0x1F4D, /*U+1F45*/ /*GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA*/
+  0x1F46, /*U+1F46*/ /**/
+  0x1F47, /*U+1F47*/ /**/
+  0x1F48, /*U+1F48*/ /**/
+  0x1F49, /*U+1F49*/ /**/
+  0x1F4A, /*U+1F4A*/ /**/
+  0x1F4B, /*U+1F4B*/ /**/
+  0x1F4C, /*U+1F4C*/ /**/
+  0x1F4D, /*U+1F4D*/ /**/
+  0x1F4E, /*U+1F4E*/ /**/
+  0x1F4F, /*U+1F4F*/ /**/
+  0x1F50, /*U+1F50*/ /**/
+  0x1F59, /*U+1F51*/ /*GREEK SMALL LETTER UPSILON WITH DASIA*/
+  0x1F52, /*U+1F52*/ /**/
+  0x1F5B, /*U+1F53*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND VARIA*/
+  0x1F54, /*U+1F54*/ /**/
+  0x1F5D, /*U+1F55*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND OXIA*/
+  0x1F56, /*U+1F56*/ /**/
+  0x1F5F, /*U+1F57*/ /*GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI*/
+  0x1F58, /*U+1F58*/ /**/
+  0x1F59, /*U+1F59*/ /**/
+  0x1F5A, /*U+1F5A*/ /**/
+  0x1F5B, /*U+1F5B*/ /**/
+  0x1F5C, /*U+1F5C*/ /**/
+  0x1F5D, /*U+1F5D*/ /**/
+  0x1F5E, /*U+1F5E*/ /**/
+  0x1F5F, /*U+1F5F*/ /**/
+  0x1F68, /*U+1F60*/ /*GREEK SMALL LETTER OMEGA WITH PSILI*/
+  0x1F69, /*U+1F61*/ /*GREEK SMALL LETTER OMEGA WITH DASIA*/
+  0x1F6A, /*U+1F62*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA*/
+  0x1F6B, /*U+1F63*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA*/
+  0x1F6C, /*U+1F64*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA*/
+  0x1F6D, /*U+1F65*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA*/
+  0x1F6E, /*U+1F66*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI*/
+  0x1F6F, /*U+1F67*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI*/
+  0x1F68, /*U+1F68*/ /**/
+  0x1F69, /*U+1F69*/ /**/
+  0x1F6A, /*U+1F6A*/ /**/
+  0x1F6B, /*U+1F6B*/ /**/
+  0x1F6C, /*U+1F6C*/ /**/
+  0x1F6D, /*U+1F6D*/ /**/
+  0x1F6E, /*U+1F6E*/ /**/
+  0x1F6F, /*U+1F6F*/ /**/
+  0x1FBA, /*U+1F70*/ /*GREEK SMALL LETTER ALPHA WITH VARIA*/
+  0x1FBB, /*U+1F71*/ /*GREEK SMALL LETTER ALPHA WITH OXIA*/
+  0x1FC8, /*U+1F72*/ /*GREEK SMALL LETTER EPSILON WITH VARIA*/
+  0x1FC9, /*U+1F73*/ /*GREEK SMALL LETTER EPSILON WITH OXIA*/
+  0x1FCA, /*U+1F74*/ /*GREEK SMALL LETTER ETA WITH VARIA*/
+  0x1FCB, /*U+1F75*/ /*GREEK SMALL LETTER ETA WITH OXIA*/
+  0x1FDA, /*U+1F76*/ /*GREEK SMALL LETTER IOTA WITH VARIA*/
+  0x1FDB, /*U+1F77*/ /*GREEK SMALL LETTER IOTA WITH OXIA*/
+  0x1FF8, /*U+1F78*/ /*GREEK SMALL LETTER OMICRON WITH VARIA*/
+  0x1FF9, /*U+1F79*/ /*GREEK SMALL LETTER OMICRON WITH OXIA*/
+  0x1FEA, /*U+1F7A*/ /*GREEK SMALL LETTER UPSILON WITH VARIA*/
+  0x1FEB, /*U+1F7B*/ /*GREEK SMALL LETTER UPSILON WITH OXIA*/
+  0x1FFA, /*U+1F7C*/ /*GREEK SMALL LETTER OMEGA WITH VARIA*/
+  0x1FFB, /*U+1F7D*/ /*GREEK SMALL LETTER OMEGA WITH OXIA*/
+  0x1F7E, /*U+1F7E*/ /**/
+  0x1F7F, /*U+1F7F*/ /**/
+  0x1F88, /*U+1F80*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI*/
+  0x1F89, /*U+1F81*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI*/
+  0x1F8A, /*U+1F82*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/
+  0x1F8B, /*U+1F83*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/
+  0x1F8C, /*U+1F84*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/
+  0x1F8D, /*U+1F85*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/
+  0x1F8E, /*U+1F86*/ /*GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1F8F, /*U+1F87*/ /*GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1F88, /*U+1F88*/ /**/
+  0x1F89, /*U+1F89*/ /**/
+  0x1F8A, /*U+1F8A*/ /**/
+  0x1F8B, /*U+1F8B*/ /**/
+  0x1F8C, /*U+1F8C*/ /**/
+  0x1F8D, /*U+1F8D*/ /**/
+  0x1F8E, /*U+1F8E*/ /**/
+  0x1F8F, /*U+1F8F*/ /**/
+  0x1F98, /*U+1F90*/ /*GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI*/
+  0x1F99, /*U+1F91*/ /*GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI*/
+  0x1F9A, /*U+1F92*/ /*GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/
+  0x1F9B, /*U+1F93*/ /*GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/
+  0x1F9C, /*U+1F94*/ /*GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/
+  0x1F9D, /*U+1F95*/ /*GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/
+  0x1F9E, /*U+1F96*/ /*GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1F9F, /*U+1F97*/ /*GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1F98, /*U+1F98*/ /**/
+  0x1F99, /*U+1F99*/ /**/
+  0x1F9A, /*U+1F9A*/ /**/
+  0x1F9B, /*U+1F9B*/ /**/
+  0x1F9C, /*U+1F9C*/ /**/
+  0x1F9D, /*U+1F9D*/ /**/
+  0x1F9E, /*U+1F9E*/ /**/
+  0x1F9F, /*U+1F9F*/ /**/
+  0x1FA8, /*U+1FA0*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI*/
+  0x1FA9, /*U+1FA1*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI*/
+  0x1FAA, /*U+1FA2*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI*/
+  0x1FAB, /*U+1FA3*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI*/
+  0x1FAC, /*U+1FA4*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI*/
+  0x1FAD, /*U+1FA5*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI*/
+  0x1FAE, /*U+1FA6*/ /*GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1FAF, /*U+1FA7*/ /*GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI*/
+  0x1FA8, /*U+1FA8*/ /**/
+  0x1FA9, /*U+1FA9*/ /**/
+  0x1FAA, /*U+1FAA*/ /**/
+  0x1FAB, /*U+1FAB*/ /**/
+  0x1FAC, /*U+1FAC*/ /**/
+  0x1FAD, /*U+1FAD*/ /**/
+  0x1FAE, /*U+1FAE*/ /**/
+  0x1FAF, /*U+1FAF*/ /**/
+  0x1FB8, /*U+1FB0*/ /*GREEK SMALL LETTER ALPHA WITH VRACHY*/
+  0x1FB9, /*U+1FB1*/ /*GREEK SMALL LETTER ALPHA WITH MACRON*/
+  0x1FB2, /*U+1FB2*/ /**/
+  0x1FBC, /*U+1FB3*/ /*GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI*/
+  0x1FB4, /*U+1FB4*/ /**/
+  0x1FB5, /*U+1FB5*/ /**/
+  0x1FB6, /*U+1FB6*/ /**/
+  0x1FB7, /*U+1FB7*/ /**/
+  0x1FB8, /*U+1FB8*/ /**/
+  0x1FB9, /*U+1FB9*/ /**/
+  0x1FBA, /*U+1FBA*/ /**/
+  0x1FBB, /*U+1FBB*/ /**/
+  0x1FBC, /*U+1FBC*/ /**/
+  0x1FBD, /*U+1FBD*/ /**/
+  0x0399, /*U+1FBE*/ /*GREEK PROSGEGRAMMENI*/
+  0x1FBF, /*U+1FBF*/ /**/
+  0x1FC0, /*U+1FC0*/ /**/
+  0x1FC1, /*U+1FC1*/ /**/
+  0x1FC2, /*U+1FC2*/ /**/
+  0x1FCC, /*U+1FC3*/ /*GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI*/
+  0x1FC4, /*U+1FC4*/ /**/
+  0x1FC5, /*U+1FC5*/ /**/
+  0x1FC6, /*U+1FC6*/ /**/
+  0x1FC7, /*U+1FC7*/ /**/
+  0x1FC8, /*U+1FC8*/ /**/
+  0x1FC9, /*U+1FC9*/ /**/
+  0x1FCA, /*U+1FCA*/ /**/
+  0x1FCB, /*U+1FCB*/ /**/
+  0x1FCC, /*U+1FCC*/ /**/
+  0x1FCD, /*U+1FCD*/ /**/
+  0x1FCE, /*U+1FCE*/ /**/
+  0x1FCF, /*U+1FCF*/ /**/
+  0x1FD8, /*U+1FD0*/ /*GREEK SMALL LETTER IOTA WITH VRACHY*/
+  0x1FD9, /*U+1FD1*/ /*GREEK SMALL LETTER IOTA WITH MACRON*/
+  0x1FD2, /*U+1FD2*/ /**/
+  0x1FD3, /*U+1FD3*/ /**/
+  0x1FD4, /*U+1FD4*/ /**/
+  0x1FD5, /*U+1FD5*/ /**/
+  0x1FD6, /*U+1FD6*/ /**/
+  0x1FD7, /*U+1FD7*/ /**/
+  0x1FD8, /*U+1FD8*/ /**/
+  0x1FD9, /*U+1FD9*/ /**/
+  0x1FDA, /*U+1FDA*/ /**/
+  0x1FDB, /*U+1FDB*/ /**/
+  0x1FDC, /*U+1FDC*/ /**/
+  0x1FDD, /*U+1FDD*/ /**/
+  0x1FDE, /*U+1FDE*/ /**/
+  0x1FDF, /*U+1FDF*/ /**/
+  0x1FE8, /*U+1FE0*/ /*GREEK SMALL LETTER UPSILON WITH VRACHY*/
+  0x1FE9, /*U+1FE1*/ /*GREEK SMALL LETTER UPSILON WITH MACRON*/
+  0x1FE2, /*U+1FE2*/ /**/
+  0x1FE3, /*U+1FE3*/ /**/
+  0x1FE4, /*U+1FE4*/ /**/
+  0x1FEC, /*U+1FE5*/ /*GREEK SMALL LETTER RHO WITH DASIA*/
+  0x1FE6, /*U+1FE6*/ /**/
+  0x1FE7, /*U+1FE7*/ /**/
+  0x1FE8, /*U+1FE8*/ /**/
+  0x1FE9, /*U+1FE9*/ /**/
+  0x1FEA, /*U+1FEA*/ /**/
+  0x1FEB, /*U+1FEB*/ /**/
+  0x1FEC, /*U+1FEC*/ /**/
+  0x1FED, /*U+1FED*/ /**/
+  0x1FEE, /*U+1FEE*/ /**/
+  0x1FEF, /*U+1FEF*/ /**/
+  0x1FF0, /*U+1FF0*/ /**/
+  0x1FF1, /*U+1FF1*/ /**/
+  0x1FF2, /*U+1FF2*/ /**/
+  0x1FFC, /*U+1FF3*/ /*GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI*/
+  0x1FF4, /*U+1FF4*/ /**/
+  0x1FF5, /*U+1FF5*/ /**/
+  0x1FF6, /*U+1FF6*/ /**/
+  0x1FF7, /*U+1FF7*/ /**/
+  0x1FF8, /*U+1FF8*/ /**/
+  0x1FF9, /*U+1FF9*/ /**/
+  0x1FFA, /*U+1FFA*/ /**/
+  0x1FFB, /*U+1FFB*/ /**/
+  0x1FFC, /*U+1FFC*/ /**/
+  0x1FFD, /*U+1FFD*/ /**/
+  0x1FFE, /*U+1FFE*/ /**/
+  0x1FFF, /*U+1FFF*/ /**/
+};
+
+static const u_int16_t upper_table_5[128] = {
+  0x2140, /*U+2140*/ /**/
+  0x2141, /*U+2141*/ /**/
+  0x2142, /*U+2142*/ /**/
+  0x2143, /*U+2143*/ /**/
+  0x2144, /*U+2144*/ /**/
+  0x2145, /*U+2145*/ /**/
+  0x2146, /*U+2146*/ /**/
+  0x2147, /*U+2147*/ /**/
+  0x2148, /*U+2148*/ /**/
+  0x2149, /*U+2149*/ /**/
+  0x214A, /*U+214A*/ /**/
+  0x214B, /*U+214B*/ /**/
+  0x214C, /*U+214C*/ /**/
+  0x214D, /*U+214D*/ /**/
+  0x2132, /*U+214E*/ /*TURNED SMALL F*/
+  0x214F, /*U+214F*/ /**/
+  0x2150, /*U+2150*/ /**/
+  0x2151, /*U+2151*/ /**/
+  0x2152, /*U+2152*/ /**/
+  0x2153, /*U+2153*/ /**/
+  0x2154, /*U+2154*/ /**/
+  0x2155, /*U+2155*/ /**/
+  0x2156, /*U+2156*/ /**/
+  0x2157, /*U+2157*/ /**/
+  0x2158, /*U+2158*/ /**/
+  0x2159, /*U+2159*/ /**/
+  0x215A, /*U+215A*/ /**/
+  0x215B, /*U+215B*/ /**/
+  0x215C, /*U+215C*/ /**/
+  0x215D, /*U+215D*/ /**/
+  0x215E, /*U+215E*/ /**/
+  0x215F, /*U+215F*/ /**/
+  0x2160, /*U+2160*/ /**/
+  0x2161, /*U+2161*/ /**/
+  0x2162, /*U+2162*/ /**/
+  0x2163, /*U+2163*/ /**/
+  0x2164, /*U+2164*/ /**/
+  0x2165, /*U+2165*/ /**/
+  0x2166, /*U+2166*/ /**/
+  0x2167, /*U+2167*/ /**/
+  0x2168, /*U+2168*/ /**/
+  0x2169, /*U+2169*/ /**/
+  0x216A, /*U+216A*/ /**/
+  0x216B, /*U+216B*/ /**/
+  0x216C, /*U+216C*/ /**/
+  0x216D, /*U+216D*/ /**/
+  0x216E, /*U+216E*/ /**/
+  0x216F, /*U+216F*/ /**/
+  0x2160, /*U+2170*/ /*SMALL ROMAN NUMERAL ONE*/
+  0x2161, /*U+2171*/ /*SMALL ROMAN NUMERAL TWO*/
+  0x2162, /*U+2172*/ /*SMALL ROMAN NUMERAL THREE*/
+  0x2163, /*U+2173*/ /*SMALL ROMAN NUMERAL FOUR*/
+  0x2164, /*U+2174*/ /*SMALL ROMAN NUMERAL FIVE*/
+  0x2165, /*U+2175*/ /*SMALL ROMAN NUMERAL SIX*/
+  0x2166, /*U+2176*/ /*SMALL ROMAN NUMERAL SEVEN*/
+  0x2167, /*U+2177*/ /*SMALL ROMAN NUMERAL EIGHT*/
+  0x2168, /*U+2178*/ /*SMALL ROMAN NUMERAL NINE*/
+  0x2169, /*U+2179*/ /*SMALL ROMAN NUMERAL TEN*/
+  0x216A, /*U+217A*/ /*SMALL ROMAN NUMERAL ELEVEN*/
+  0x216B, /*U+217B*/ /*SMALL ROMAN NUMERAL TWELVE*/
+  0x216C, /*U+217C*/ /*SMALL ROMAN NUMERAL FIFTY*/
+  0x216D, /*U+217D*/ /*SMALL ROMAN NUMERAL ONE HUNDRED*/
+  0x216E, /*U+217E*/ /*SMALL ROMAN NUMERAL FIVE HUNDRED*/
+  0x216F, /*U+217F*/ /*SMALL ROMAN NUMERAL ONE THOUSAND*/
+  0x2180, /*U+2180*/ /**/
+  0x2181, /*U+2181*/ /**/
+  0x2182, /*U+2182*/ /**/
+  0x2183, /*U+2183*/ /**/
+  0x2183, /*U+2184*/ /*LATIN SMALL LETTER REVERSED C*/
+  0x2185, /*U+2185*/ /**/
+  0x2186, /*U+2186*/ /**/
+  0x2187, /*U+2187*/ /**/
+  0x2188, /*U+2188*/ /**/
+  0x2189, /*U+2189*/ /**/
+  0x218A, /*U+218A*/ /**/
+  0x218B, /*U+218B*/ /**/
+  0x218C, /*U+218C*/ /**/
+  0x218D, /*U+218D*/ /**/
+  0x218E, /*U+218E*/ /**/
+  0x218F, /*U+218F*/ /**/
+  0x2190, /*U+2190*/ /**/
+  0x2191, /*U+2191*/ /**/
+  0x2192, /*U+2192*/ /**/
+  0x2193, /*U+2193*/ /**/
+  0x2194, /*U+2194*/ /**/
+  0x2195, /*U+2195*/ /**/
+  0x2196, /*U+2196*/ /**/
+  0x2197, /*U+2197*/ /**/
+  0x2198, /*U+2198*/ /**/
+  0x2199, /*U+2199*/ /**/
+  0x219A, /*U+219A*/ /**/
+  0x219B, /*U+219B*/ /**/
+  0x219C, /*U+219C*/ /**/
+  0x219D, /*U+219D*/ /**/
+  0x219E, /*U+219E*/ /**/
+  0x219F, /*U+219F*/ /**/
+  0x21A0, /*U+21A0*/ /**/
+  0x21A1, /*U+21A1*/ /**/
+  0x21A2, /*U+21A2*/ /**/
+  0x21A3, /*U+21A3*/ /**/
+  0x21A4, /*U+21A4*/ /**/
+  0x21A5, /*U+21A5*/ /**/
+  0x21A6, /*U+21A6*/ /**/
+  0x21A7, /*U+21A7*/ /**/
+  0x21A8, /*U+21A8*/ /**/
+  0x21A9, /*U+21A9*/ /**/
+  0x21AA, /*U+21AA*/ /**/
+  0x21AB, /*U+21AB*/ /**/
+  0x21AC, /*U+21AC*/ /**/
+  0x21AD, /*U+21AD*/ /**/
+  0x21AE, /*U+21AE*/ /**/
+  0x21AF, /*U+21AF*/ /**/
+  0x21B0, /*U+21B0*/ /**/
+  0x21B1, /*U+21B1*/ /**/
+  0x21B2, /*U+21B2*/ /**/
+  0x21B3, /*U+21B3*/ /**/
+  0x21B4, /*U+21B4*/ /**/
+  0x21B5, /*U+21B5*/ /**/
+  0x21B6, /*U+21B6*/ /**/
+  0x21B7, /*U+21B7*/ /**/
+  0x21B8, /*U+21B8*/ /**/
+  0x21B9, /*U+21B9*/ /**/
+  0x21BA, /*U+21BA*/ /**/
+  0x21BB, /*U+21BB*/ /**/
+  0x21BC, /*U+21BC*/ /**/
+  0x21BD, /*U+21BD*/ /**/
+  0x21BE, /*U+21BE*/ /**/
+  0x21BF, /*U+21BF*/ /**/
+};
+
+static const u_int16_t upper_table_6[64] = {
+  0x24C0, /*U+24C0*/ /**/
+  0x24C1, /*U+24C1*/ /**/
+  0x24C2, /*U+24C2*/ /**/
+  0x24C3, /*U+24C3*/ /**/
+  0x24C4, /*U+24C4*/ /**/
+  0x24C5, /*U+24C5*/ /**/
+  0x24C6, /*U+24C6*/ /**/
+  0x24C7, /*U+24C7*/ /**/
+  0x24C8, /*U+24C8*/ /**/
+  0x24C9, /*U+24C9*/ /**/
+  0x24CA, /*U+24CA*/ /**/
+  0x24CB, /*U+24CB*/ /**/
+  0x24CC, /*U+24CC*/ /**/
+  0x24CD, /*U+24CD*/ /**/
+  0x24CE, /*U+24CE*/ /**/
+  0x24CF, /*U+24CF*/ /**/
+  0x24B6, /*U+24D0*/ /*CIRCLED LATIN SMALL LETTER A*/
+  0x24B7, /*U+24D1*/ /*CIRCLED LATIN SMALL LETTER B*/
+  0x24B8, /*U+24D2*/ /*CIRCLED LATIN SMALL LETTER C*/
+  0x24B9, /*U+24D3*/ /*CIRCLED LATIN SMALL LETTER D*/
+  0x24BA, /*U+24D4*/ /*CIRCLED LATIN SMALL LETTER E*/
+  0x24BB, /*U+24D5*/ /*CIRCLED LATIN SMALL LETTER F*/
+  0x24BC, /*U+24D6*/ /*CIRCLED LATIN SMALL LETTER G*/
+  0x24BD, /*U+24D7*/ /*CIRCLED LATIN SMALL LETTER H*/
+  0x24BE, /*U+24D8*/ /*CIRCLED LATIN SMALL LETTER I*/
+  0x24BF, /*U+24D9*/ /*CIRCLED LATIN SMALL LETTER J*/
+  0x24C0, /*U+24DA*/ /*CIRCLED LATIN SMALL LETTER K*/
+  0x24C1, /*U+24DB*/ /*CIRCLED LATIN SMALL LETTER L*/
+  0x24C2, /*U+24DC*/ /*CIRCLED LATIN SMALL LETTER M*/
+  0x24C3, /*U+24DD*/ /*CIRCLED LATIN SMALL LETTER N*/
+  0x24C4, /*U+24DE*/ /*CIRCLED LATIN SMALL LETTER O*/
+  0x24C5, /*U+24DF*/ /*CIRCLED LATIN SMALL LETTER P*/
+  0x24C6, /*U+24E0*/ /*CIRCLED LATIN SMALL LETTER Q*/
+  0x24C7, /*U+24E1*/ /*CIRCLED LATIN SMALL LETTER R*/
+  0x24C8, /*U+24E2*/ /*CIRCLED LATIN SMALL LETTER S*/
+  0x24C9, /*U+24E3*/ /*CIRCLED LATIN SMALL LETTER T*/
+  0x24CA, /*U+24E4*/ /*CIRCLED LATIN SMALL LETTER U*/
+  0x24CB, /*U+24E5*/ /*CIRCLED LATIN SMALL LETTER V*/
+  0x24CC, /*U+24E6*/ /*CIRCLED LATIN SMALL LETTER W*/
+  0x24CD, /*U+24E7*/ /*CIRCLED LATIN SMALL LETTER X*/
+  0x24CE, /*U+24E8*/ /*CIRCLED LATIN SMALL LETTER Y*/
+  0x24CF, /*U+24E9*/ /*CIRCLED LATIN SMALL LETTER Z*/
+  0x24EA, /*U+24EA*/ /**/
+  0x24EB, /*U+24EB*/ /**/
+  0x24EC, /*U+24EC*/ /**/
+  0x24ED, /*U+24ED*/ /**/
+  0x24EE, /*U+24EE*/ /**/
+  0x24EF, /*U+24EF*/ /**/
+  0x24F0, /*U+24F0*/ /**/
+  0x24F1, /*U+24F1*/ /**/
+  0x24F2, /*U+24F2*/ /**/
+  0x24F3, /*U+24F3*/ /**/
+  0x24F4, /*U+24F4*/ /**/
+  0x24F5, /*U+24F5*/ /**/
+  0x24F6, /*U+24F6*/ /**/
+  0x24F7, /*U+24F7*/ /**/
+  0x24F8, /*U+24F8*/ /**/
+  0x24F9, /*U+24F9*/ /**/
+  0x24FA, /*U+24FA*/ /**/
+  0x24FB, /*U+24FB*/ /**/
+  0x24FC, /*U+24FC*/ /**/
+  0x24FD, /*U+24FD*/ /**/
+  0x24FE, /*U+24FE*/ /**/
+  0x24FF, /*U+24FF*/ /**/
+};
+
+static const u_int16_t upper_table_7[320] = {
+  0x2C00, /*U+2C00*/ /**/
+  0x2C01, /*U+2C01*/ /**/
+  0x2C02, /*U+2C02*/ /**/
+  0x2C03, /*U+2C03*/ /**/
+  0x2C04, /*U+2C04*/ /**/
+  0x2C05, /*U+2C05*/ /**/
+  0x2C06, /*U+2C06*/ /**/
+  0x2C07, /*U+2C07*/ /**/
+  0x2C08, /*U+2C08*/ /**/
+  0x2C09, /*U+2C09*/ /**/
+  0x2C0A, /*U+2C0A*/ /**/
+  0x2C0B, /*U+2C0B*/ /**/
+  0x2C0C, /*U+2C0C*/ /**/
+  0x2C0D, /*U+2C0D*/ /**/
+  0x2C0E, /*U+2C0E*/ /**/
+  0x2C0F, /*U+2C0F*/ /**/
+  0x2C10, /*U+2C10*/ /**/
+  0x2C11, /*U+2C11*/ /**/
+  0x2C12, /*U+2C12*/ /**/
+  0x2C13, /*U+2C13*/ /**/
+  0x2C14, /*U+2C14*/ /**/
+  0x2C15, /*U+2C15*/ /**/
+  0x2C16, /*U+2C16*/ /**/
+  0x2C17, /*U+2C17*/ /**/
+  0x2C18, /*U+2C18*/ /**/
+  0x2C19, /*U+2C19*/ /**/
+  0x2C1A, /*U+2C1A*/ /**/
+  0x2C1B, /*U+2C1B*/ /**/
+  0x2C1C, /*U+2C1C*/ /**/
+  0x2C1D, /*U+2C1D*/ /**/
+  0x2C1E, /*U+2C1E*/ /**/
+  0x2C1F, /*U+2C1F*/ /**/
+  0x2C20, /*U+2C20*/ /**/
+  0x2C21, /*U+2C21*/ /**/
+  0x2C22, /*U+2C22*/ /**/
+  0x2C23, /*U+2C23*/ /**/
+  0x2C24, /*U+2C24*/ /**/
+  0x2C25, /*U+2C25*/ /**/
+  0x2C26, /*U+2C26*/ /**/
+  0x2C27, /*U+2C27*/ /**/
+  0x2C28, /*U+2C28*/ /**/
+  0x2C29, /*U+2C29*/ /**/
+  0x2C2A, /*U+2C2A*/ /**/
+  0x2C2B, /*U+2C2B*/ /**/
+  0x2C2C, /*U+2C2C*/ /**/
+  0x2C2D, /*U+2C2D*/ /**/
+  0x2C2E, /*U+2C2E*/ /**/
+  0x2C2F, /*U+2C2F*/ /**/
+  0x2C00, /*U+2C30*/ /*GLAGOLITIC SMALL LETTER AZU*/
+  0x2C01, /*U+2C31*/ /*GLAGOLITIC SMALL LETTER BUKY*/
+  0x2C02, /*U+2C32*/ /*GLAGOLITIC SMALL LETTER VEDE*/
+  0x2C03, /*U+2C33*/ /*GLAGOLITIC SMALL LETTER GLAGOLI*/
+  0x2C04, /*U+2C34*/ /*GLAGOLITIC SMALL LETTER DOBRO*/
+  0x2C05, /*U+2C35*/ /*GLAGOLITIC SMALL LETTER YESTU*/
+  0x2C06, /*U+2C36*/ /*GLAGOLITIC SMALL LETTER ZHIVETE*/
+  0x2C07, /*U+2C37*/ /*GLAGOLITIC SMALL LETTER DZELO*/
+  0x2C08, /*U+2C38*/ /*GLAGOLITIC SMALL LETTER ZEMLJA*/
+  0x2C09, /*U+2C39*/ /*GLAGOLITIC SMALL LETTER IZHE*/
+  0x2C0A, /*U+2C3A*/ /*GLAGOLITIC SMALL LETTER INITIAL IZHE*/
+  0x2C0B, /*U+2C3B*/ /*GLAGOLITIC SMALL LETTER I*/
+  0x2C0C, /*U+2C3C*/ /*GLAGOLITIC SMALL LETTER DJERVI*/
+  0x2C0D, /*U+2C3D*/ /*GLAGOLITIC SMALL LETTER KAKO*/
+  0x2C0E, /*U+2C3E*/ /*GLAGOLITIC SMALL LETTER LJUDIJE*/
+  0x2C0F, /*U+2C3F*/ /*GLAGOLITIC SMALL LETTER MYSLITE*/
+  0x2C10, /*U+2C40*/ /*GLAGOLITIC SMALL LETTER NASHI*/
+  0x2C11, /*U+2C41*/ /*GLAGOLITIC SMALL LETTER ONU*/
+  0x2C12, /*U+2C42*/ /*GLAGOLITIC SMALL LETTER POKOJI*/
+  0x2C13, /*U+2C43*/ /*GLAGOLITIC SMALL LETTER RITSI*/
+  0x2C14, /*U+2C44*/ /*GLAGOLITIC SMALL LETTER SLOVO*/
+  0x2C15, /*U+2C45*/ /*GLAGOLITIC SMALL LETTER TVRIDO*/
+  0x2C16, /*U+2C46*/ /*GLAGOLITIC SMALL LETTER UKU*/
+  0x2C17, /*U+2C47*/ /*GLAGOLITIC SMALL LETTER FRITU*/
+  0x2C18, /*U+2C48*/ /*GLAGOLITIC SMALL LETTER HERU*/
+  0x2C19, /*U+2C49*/ /*GLAGOLITIC SMALL LETTER OTU*/
+  0x2C1A, /*U+2C4A*/ /*GLAGOLITIC SMALL LETTER PE*/
+  0x2C1B, /*U+2C4B*/ /*GLAGOLITIC SMALL LETTER SHTA*/
+  0x2C1C, /*U+2C4C*/ /*GLAGOLITIC SMALL LETTER TSI*/
+  0x2C1D, /*U+2C4D*/ /*GLAGOLITIC SMALL LETTER CHRIVI*/
+  0x2C1E, /*U+2C4E*/ /*GLAGOLITIC SMALL LETTER SHA*/
+  0x2C1F, /*U+2C4F*/ /*GLAGOLITIC SMALL LETTER YERU*/
+  0x2C20, /*U+2C50*/ /*GLAGOLITIC SMALL LETTER YERI*/
+  0x2C21, /*U+2C51*/ /*GLAGOLITIC SMALL LETTER YATI*/
+  0x2C22, /*U+2C52*/ /*GLAGOLITIC SMALL LETTER SPIDERY HA*/
+  0x2C23, /*U+2C53*/ /*GLAGOLITIC SMALL LETTER YU*/
+  0x2C24, /*U+2C54*/ /*GLAGOLITIC SMALL LETTER SMALL YUS*/
+  0x2C25, /*U+2C55*/ /*GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL*/
+  0x2C26, /*U+2C56*/ /*GLAGOLITIC SMALL LETTER YO*/
+  0x2C27, /*U+2C57*/ /*GLAGOLITIC SMALL LETTER IOTATED SMALL YUS*/
+  0x2C28, /*U+2C58*/ /*GLAGOLITIC SMALL LETTER BIG YUS*/
+  0x2C29, /*U+2C59*/ /*GLAGOLITIC SMALL LETTER IOTATED BIG YUS*/
+  0x2C2A, /*U+2C5A*/ /*GLAGOLITIC SMALL LETTER FITA*/
+  0x2C2B, /*U+2C5B*/ /*GLAGOLITIC SMALL LETTER IZHITSA*/
+  0x2C2C, /*U+2C5C*/ /*GLAGOLITIC SMALL LETTER SHTAPIC*/
+  0x2C2D, /*U+2C5D*/ /*GLAGOLITIC SMALL LETTER TROKUTASTI A*/
+  0x2C2E, /*U+2C5E*/ /*GLAGOLITIC SMALL LETTER LATINATE MYSLITE*/
+  0x2C5F, /*U+2C5F*/ /**/
+  0x2C60, /*U+2C60*/ /**/
+  0x2C60, /*U+2C61*/ /*LATIN SMALL LETTER L WITH DOUBLE BAR*/
+  0x2C62, /*U+2C62*/ /**/
+  0x2C63, /*U+2C63*/ /**/
+  0x2C64, /*U+2C64*/ /**/
+  0x023A, /*U+2C65*/ /*LATIN SMALL LETTER A WITH STROKE*/
+  0x023E, /*U+2C66*/ /*LATIN SMALL LETTER T WITH DIAGONAL STROKE*/
+  0x2C67, /*U+2C67*/ /**/
+  0x2C67, /*U+2C68*/ /*LATIN SMALL LETTER H WITH DESCENDER*/
+  0x2C69, /*U+2C69*/ /**/
+  0x2C69, /*U+2C6A*/ /*LATIN SMALL LETTER K WITH DESCENDER*/
+  0x2C6B, /*U+2C6B*/ /**/
+  0x2C6B, /*U+2C6C*/ /*LATIN SMALL LETTER Z WITH DESCENDER*/
+  0x2C6D, /*U+2C6D*/ /**/
+  0x2C6E, /*U+2C6E*/ /**/
+  0x2C6F, /*U+2C6F*/ /**/
+  0x2C70, /*U+2C70*/ /**/
+  0x2C71, /*U+2C71*/ /**/
+  0x2C72, /*U+2C72*/ /**/
+  0x2C72, /*U+2C73*/ /*LATIN SMALL LETTER W WITH HOOK*/
+  0x2C74, /*U+2C74*/ /**/
+  0x2C75, /*U+2C75*/ /**/
+  0x2C75, /*U+2C76*/ /*LATIN SMALL LETTER HALF H*/
+  0x2C77, /*U+2C77*/ /**/
+  0x2C78, /*U+2C78*/ /**/
+  0x2C79, /*U+2C79*/ /**/
+  0x2C7A, /*U+2C7A*/ /**/
+  0x2C7B, /*U+2C7B*/ /**/
+  0x2C7C, /*U+2C7C*/ /**/
+  0x2C7D, /*U+2C7D*/ /**/
+  0x2C7E, /*U+2C7E*/ /**/
+  0x2C7F, /*U+2C7F*/ /**/
+  0x2C80, /*U+2C80*/ /**/
+  0x2C80, /*U+2C81*/ /*COPTIC SMALL LETTER ALFA*/
+  0x2C82, /*U+2C82*/ /**/
+  0x2C82, /*U+2C83*/ /*COPTIC SMALL LETTER VIDA*/
+  0x2C84, /*U+2C84*/ /**/
+  0x2C84, /*U+2C85*/ /*COPTIC SMALL LETTER GAMMA*/
+  0x2C86, /*U+2C86*/ /**/
+  0x2C86, /*U+2C87*/ /*COPTIC SMALL LETTER DALDA*/
+  0x2C88, /*U+2C88*/ /**/
+  0x2C88, /*U+2C89*/ /*COPTIC SMALL LETTER EIE*/
+  0x2C8A, /*U+2C8A*/ /**/
+  0x2C8A, /*U+2C8B*/ /*COPTIC SMALL LETTER SOU*/
+  0x2C8C, /*U+2C8C*/ /**/
+  0x2C8C, /*U+2C8D*/ /*COPTIC SMALL LETTER ZATA*/
+  0x2C8E, /*U+2C8E*/ /**/
+  0x2C8E, /*U+2C8F*/ /*COPTIC SMALL LETTER HATE*/
+  0x2C90, /*U+2C90*/ /**/
+  0x2C90, /*U+2C91*/ /*COPTIC SMALL LETTER THETHE*/
+  0x2C92, /*U+2C92*/ /**/
+  0x2C92, /*U+2C93*/ /*COPTIC SMALL LETTER IAUDA*/
+  0x2C94, /*U+2C94*/ /**/
+  0x2C94, /*U+2C95*/ /*COPTIC SMALL LETTER KAPA*/
+  0x2C96, /*U+2C96*/ /**/
+  0x2C96, /*U+2C97*/ /*COPTIC SMALL LETTER LAULA*/
+  0x2C98, /*U+2C98*/ /**/
+  0x2C98, /*U+2C99*/ /*COPTIC SMALL LETTER MI*/
+  0x2C9A, /*U+2C9A*/ /**/
+  0x2C9A, /*U+2C9B*/ /*COPTIC SMALL LETTER NI*/
+  0x2C9C, /*U+2C9C*/ /**/
+  0x2C9C, /*U+2C9D*/ /*COPTIC SMALL LETTER KSI*/
+  0x2C9E, /*U+2C9E*/ /**/
+  0x2C9E, /*U+2C9F*/ /*COPTIC SMALL LETTER O*/
+  0x2CA0, /*U+2CA0*/ /**/
+  0x2CA0, /*U+2CA1*/ /*COPTIC SMALL LETTER PI*/
+  0x2CA2, /*U+2CA2*/ /**/
+  0x2CA2, /*U+2CA3*/ /*COPTIC SMALL LETTER RO*/
+  0x2CA4, /*U+2CA4*/ /**/
+  0x2CA4, /*U+2CA5*/ /*COPTIC SMALL LETTER SIMA*/
+  0x2CA6, /*U+2CA6*/ /**/
+  0x2CA6, /*U+2CA7*/ /*COPTIC SMALL LETTER TAU*/
+  0x2CA8, /*U+2CA8*/ /**/
+  0x2CA8, /*U+2CA9*/ /*COPTIC SMALL LETTER UA*/
+  0x2CAA, /*U+2CAA*/ /**/
+  0x2CAA, /*U+2CAB*/ /*COPTIC SMALL LETTER FI*/
+  0x2CAC, /*U+2CAC*/ /**/
+  0x2CAC, /*U+2CAD*/ /*COPTIC SMALL LETTER KHI*/
+  0x2CAE, /*U+2CAE*/ /**/
+  0x2CAE, /*U+2CAF*/ /*COPTIC SMALL LETTER PSI*/
+  0x2CB0, /*U+2CB0*/ /**/
+  0x2CB0, /*U+2CB1*/ /*COPTIC SMALL LETTER OOU*/
+  0x2CB2, /*U+2CB2*/ /**/
+  0x2CB2, /*U+2CB3*/ /*COPTIC SMALL LETTER DIALECT-P ALEF*/
+  0x2CB4, /*U+2CB4*/ /**/
+  0x2CB4, /*U+2CB5*/ /*COPTIC SMALL LETTER OLD COPTIC AIN*/
+  0x2CB6, /*U+2CB6*/ /**/
+  0x2CB6, /*U+2CB7*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC EIE*/
+  0x2CB8, /*U+2CB8*/ /**/
+  0x2CB8, /*U+2CB9*/ /*COPTIC SMALL LETTER DIALECT-P KAPA*/
+  0x2CBA, /*U+2CBA*/ /**/
+  0x2CBA, /*U+2CBB*/ /*COPTIC SMALL LETTER DIALECT-P NI*/
+  0x2CBC, /*U+2CBC*/ /**/
+  0x2CBC, /*U+2CBD*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC NI*/
+  0x2CBE, /*U+2CBE*/ /**/
+  0x2CBE, /*U+2CBF*/ /*COPTIC SMALL LETTER OLD COPTIC OOU*/
+  0x2CC0, /*U+2CC0*/ /**/
+  0x2CC0, /*U+2CC1*/ /*COPTIC SMALL LETTER SAMPI*/
+  0x2CC2, /*U+2CC2*/ /**/
+  0x2CC2, /*U+2CC3*/ /*COPTIC SMALL LETTER CROSSED SHEI*/
+  0x2CC4, /*U+2CC4*/ /**/
+  0x2CC4, /*U+2CC5*/ /*COPTIC SMALL LETTER OLD COPTIC SHEI*/
+  0x2CC6, /*U+2CC6*/ /**/
+  0x2CC6, /*U+2CC7*/ /*COPTIC SMALL LETTER OLD COPTIC ESH*/
+  0x2CC8, /*U+2CC8*/ /**/
+  0x2CC8, /*U+2CC9*/ /*COPTIC SMALL LETTER AKHMIMIC KHEI*/
+  0x2CCA, /*U+2CCA*/ /**/
+  0x2CCA, /*U+2CCB*/ /*COPTIC SMALL LETTER DIALECT-P HORI*/
+  0x2CCC, /*U+2CCC*/ /**/
+  0x2CCC, /*U+2CCD*/ /*COPTIC SMALL LETTER OLD COPTIC HORI*/
+  0x2CCE, /*U+2CCE*/ /**/
+  0x2CCE, /*U+2CCF*/ /*COPTIC SMALL LETTER OLD COPTIC HA*/
+  0x2CD0, /*U+2CD0*/ /**/
+  0x2CD0, /*U+2CD1*/ /*COPTIC SMALL LETTER L-SHAPED HA*/
+  0x2CD2, /*U+2CD2*/ /**/
+  0x2CD2, /*U+2CD3*/ /*COPTIC SMALL LETTER OLD COPTIC HEI*/
+  0x2CD4, /*U+2CD4*/ /**/
+  0x2CD4, /*U+2CD5*/ /*COPTIC SMALL LETTER OLD COPTIC HAT*/
+  0x2CD6, /*U+2CD6*/ /**/
+  0x2CD6, /*U+2CD7*/ /*COPTIC SMALL LETTER OLD COPTIC GANGIA*/
+  0x2CD8, /*U+2CD8*/ /**/
+  0x2CD8, /*U+2CD9*/ /*COPTIC SMALL LETTER OLD COPTIC DJA*/
+  0x2CDA, /*U+2CDA*/ /**/
+  0x2CDA, /*U+2CDB*/ /*COPTIC SMALL LETTER OLD COPTIC SHIMA*/
+  0x2CDC, /*U+2CDC*/ /**/
+  0x2CDC, /*U+2CDD*/ /*COPTIC SMALL LETTER OLD NUBIAN SHIMA*/
+  0x2CDE, /*U+2CDE*/ /**/
+  0x2CDE, /*U+2CDF*/ /*COPTIC SMALL LETTER OLD NUBIAN NGI*/
+  0x2CE0, /*U+2CE0*/ /**/
+  0x2CE0, /*U+2CE1*/ /*COPTIC SMALL LETTER OLD NUBIAN NYI*/
+  0x2CE2, /*U+2CE2*/ /**/
+  0x2CE2, /*U+2CE3*/ /*COPTIC SMALL LETTER OLD NUBIAN WAU*/
+  0x2CE4, /*U+2CE4*/ /**/
+  0x2CE5, /*U+2CE5*/ /**/
+  0x2CE6, /*U+2CE6*/ /**/
+  0x2CE7, /*U+2CE7*/ /**/
+  0x2CE8, /*U+2CE8*/ /**/
+  0x2CE9, /*U+2CE9*/ /**/
+  0x2CEA, /*U+2CEA*/ /**/
+  0x2CEB, /*U+2CEB*/ /**/
+  0x2CEB, /*U+2CEC*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC SHEI*/
+  0x2CED, /*U+2CED*/ /**/
+  0x2CED, /*U+2CEE*/ /*COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA*/
+  0x2CEF, /*U+2CEF*/ /**/
+  0x2CF0, /*U+2CF0*/ /**/
+  0x2CF1, /*U+2CF1*/ /**/
+  0x2CF2, /*U+2CF2*/ /**/
+  0x2CF3, /*U+2CF3*/ /**/
+  0x2CF4, /*U+2CF4*/ /**/
+  0x2CF5, /*U+2CF5*/ /**/
+  0x2CF6, /*U+2CF6*/ /**/
+  0x2CF7, /*U+2CF7*/ /**/
+  0x2CF8, /*U+2CF8*/ /**/
+  0x2CF9, /*U+2CF9*/ /**/
+  0x2CFA, /*U+2CFA*/ /**/
+  0x2CFB, /*U+2CFB*/ /**/
+  0x2CFC, /*U+2CFC*/ /**/
+  0x2CFD, /*U+2CFD*/ /**/
+  0x2CFE, /*U+2CFE*/ /**/
+  0x2CFF, /*U+2CFF*/ /**/
+  0x10A0, /*U+2D00*/ /*GEORGIAN SMALL LETTER AN*/
+  0x10A1, /*U+2D01*/ /*GEORGIAN SMALL LETTER BAN*/
+  0x10A2, /*U+2D02*/ /*GEORGIAN SMALL LETTER GAN*/
+  0x10A3, /*U+2D03*/ /*GEORGIAN SMALL LETTER DON*/
+  0x10A4, /*U+2D04*/ /*GEORGIAN SMALL LETTER EN*/
+  0x10A5, /*U+2D05*/ /*GEORGIAN SMALL LETTER VIN*/
+  0x10A6, /*U+2D06*/ /*GEORGIAN SMALL LETTER ZEN*/
+  0x10A7, /*U+2D07*/ /*GEORGIAN SMALL LETTER TAN*/
+  0x10A8, /*U+2D08*/ /*GEORGIAN SMALL LETTER IN*/
+  0x10A9, /*U+2D09*/ /*GEORGIAN SMALL LETTER KAN*/
+  0x10AA, /*U+2D0A*/ /*GEORGIAN SMALL LETTER LAS*/
+  0x10AB, /*U+2D0B*/ /*GEORGIAN SMALL LETTER MAN*/
+  0x10AC, /*U+2D0C*/ /*GEORGIAN SMALL LETTER NAR*/
+  0x10AD, /*U+2D0D*/ /*GEORGIAN SMALL LETTER ON*/
+  0x10AE, /*U+2D0E*/ /*GEORGIAN SMALL LETTER PAR*/
+  0x10AF, /*U+2D0F*/ /*GEORGIAN SMALL LETTER ZHAR*/
+  0x10B0, /*U+2D10*/ /*GEORGIAN SMALL LETTER RAE*/
+  0x10B1, /*U+2D11*/ /*GEORGIAN SMALL LETTER SAN*/
+  0x10B2, /*U+2D12*/ /*GEORGIAN SMALL LETTER TAR*/
+  0x10B3, /*U+2D13*/ /*GEORGIAN SMALL LETTER UN*/
+  0x10B4, /*U+2D14*/ /*GEORGIAN SMALL LETTER PHAR*/
+  0x10B5, /*U+2D15*/ /*GEORGIAN SMALL LETTER KHAR*/
+  0x10B6, /*U+2D16*/ /*GEORGIAN SMALL LETTER GHAN*/
+  0x10B7, /*U+2D17*/ /*GEORGIAN SMALL LETTER QAR*/
+  0x10B8, /*U+2D18*/ /*GEORGIAN SMALL LETTER SHIN*/
+  0x10B9, /*U+2D19*/ /*GEORGIAN SMALL LETTER CHIN*/
+  0x10BA, /*U+2D1A*/ /*GEORGIAN SMALL LETTER CAN*/
+  0x10BB, /*U+2D1B*/ /*GEORGIAN SMALL LETTER JIL*/
+  0x10BC, /*U+2D1C*/ /*GEORGIAN SMALL LETTER CIL*/
+  0x10BD, /*U+2D1D*/ /*GEORGIAN SMALL LETTER CHAR*/
+  0x10BE, /*U+2D1E*/ /*GEORGIAN SMALL LETTER XAN*/
+  0x10BF, /*U+2D1F*/ /*GEORGIAN SMALL LETTER JHAN*/
+  0x10C0, /*U+2D20*/ /*GEORGIAN SMALL LETTER HAE*/
+  0x10C1, /*U+2D21*/ /*GEORGIAN SMALL LETTER HE*/
+  0x10C2, /*U+2D22*/ /*GEORGIAN SMALL LETTER HIE*/
+  0x10C3, /*U+2D23*/ /*GEORGIAN SMALL LETTER WE*/
+  0x10C4, /*U+2D24*/ /*GEORGIAN SMALL LETTER HAR*/
+  0x10C5, /*U+2D25*/ /*GEORGIAN SMALL LETTER HOE*/
+  0x2D26, /*U+2D26*/ /**/
+  0x2D27, /*U+2D27*/ /**/
+  0x2D28, /*U+2D28*/ /**/
+  0x2D29, /*U+2D29*/ /**/
+  0x2D2A, /*U+2D2A*/ /**/
+  0x2D2B, /*U+2D2B*/ /**/
+  0x2D2C, /*U+2D2C*/ /**/
+  0x2D2D, /*U+2D2D*/ /**/
+  0x2D2E, /*U+2D2E*/ /**/
+  0x2D2F, /*U+2D2F*/ /**/
+  0x2D30, /*U+2D30*/ /**/
+  0x2D31, /*U+2D31*/ /**/
+  0x2D32, /*U+2D32*/ /**/
+  0x2D33, /*U+2D33*/ /**/
+  0x2D34, /*U+2D34*/ /**/
+  0x2D35, /*U+2D35*/ /**/
+  0x2D36, /*U+2D36*/ /**/
+  0x2D37, /*U+2D37*/ /**/
+  0x2D38, /*U+2D38*/ /**/
+  0x2D39, /*U+2D39*/ /**/
+  0x2D3A, /*U+2D3A*/ /**/
+  0x2D3B, /*U+2D3B*/ /**/
+  0x2D3C, /*U+2D3C*/ /**/
+  0x2D3D, /*U+2D3D*/ /**/
+  0x2D3E, /*U+2D3E*/ /**/
+  0x2D3F, /*U+2D3F*/ /**/
+};
+
+static const u_int16_t upper_table_8[128] = {
+  0xA640, /*U+A640*/ /**/
+  0xA640, /*U+A641*/ /*CYRILLIC SMALL LETTER ZEMLYA*/
+  0xA642, /*U+A642*/ /**/
+  0xA642, /*U+A643*/ /*CYRILLIC SMALL LETTER DZELO*/
+  0xA644, /*U+A644*/ /**/
+  0xA644, /*U+A645*/ /*CYRILLIC SMALL LETTER REVERSED DZE*/
+  0xA646, /*U+A646*/ /**/
+  0xA646, /*U+A647*/ /*CYRILLIC SMALL LETTER IOTA*/
+  0xA648, /*U+A648*/ /**/
+  0xA648, /*U+A649*/ /*CYRILLIC SMALL LETTER DJERV*/
+  0xA64A, /*U+A64A*/ /**/
+  0xA64A, /*U+A64B*/ /*CYRILLIC SMALL LETTER MONOGRAPH UK*/
+  0xA64C, /*U+A64C*/ /**/
+  0xA64C, /*U+A64D*/ /*CYRILLIC SMALL LETTER BROAD OMEGA*/
+  0xA64E, /*U+A64E*/ /**/
+  0xA64E, /*U+A64F*/ /*CYRILLIC SMALL LETTER NEUTRAL YER*/
+  0xA650, /*U+A650*/ /**/
+  0xA650, /*U+A651*/ /*CYRILLIC SMALL LETTER YERU WITH BACK YER*/
+  0xA652, /*U+A652*/ /**/
+  0xA652, /*U+A653*/ /*CYRILLIC SMALL LETTER IOTIFIED YAT*/
+  0xA654, /*U+A654*/ /**/
+  0xA654, /*U+A655*/ /*CYRILLIC SMALL LETTER REVERSED YU*/
+  0xA656, /*U+A656*/ /**/
+  0xA656, /*U+A657*/ /*CYRILLIC SMALL LETTER IOTIFIED A*/
+  0xA658, /*U+A658*/ /**/
+  0xA658, /*U+A659*/ /*CYRILLIC SMALL LETTER CLOSED LITTLE YUS*/
+  0xA65A, /*U+A65A*/ /**/
+  0xA65A, /*U+A65B*/ /*CYRILLIC SMALL LETTER BLENDED YUS*/
+  0xA65C, /*U+A65C*/ /**/
+  0xA65C, /*U+A65D*/ /*CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS*/
+  0xA65E, /*U+A65E*/ /**/
+  0xA65E, /*U+A65F*/ /*CYRILLIC SMALL LETTER YN*/
+  0xA660, /*U+A660*/ /**/
+  0xA660, /*U+A661*/ /*CYRILLIC SMALL LETTER REVERSED TSE*/
+  0xA662, /*U+A662*/ /**/
+  0xA662, /*U+A663*/ /*CYRILLIC SMALL LETTER SOFT DE*/
+  0xA664, /*U+A664*/ /**/
+  0xA664, /*U+A665*/ /*CYRILLIC SMALL LETTER SOFT EL*/
+  0xA666, /*U+A666*/ /**/
+  0xA666, /*U+A667*/ /*CYRILLIC SMALL LETTER SOFT EM*/
+  0xA668, /*U+A668*/ /**/
+  0xA668, /*U+A669*/ /*CYRILLIC SMALL LETTER MONOCULAR O*/
+  0xA66A, /*U+A66A*/ /**/
+  0xA66A, /*U+A66B*/ /*CYRILLIC SMALL LETTER BINOCULAR O*/
+  0xA66C, /*U+A66C*/ /**/
+  0xA66C, /*U+A66D*/ /*CYRILLIC SMALL LETTER DOUBLE MONOCULAR O*/
+  0xA66E, /*U+A66E*/ /**/
+  0xA66F, /*U+A66F*/ /**/
+  0xA670, /*U+A670*/ /**/
+  0xA671, /*U+A671*/ /**/
+  0xA672, /*U+A672*/ /**/
+  0xA673, /*U+A673*/ /**/
+  0xA674, /*U+A674*/ /**/
+  0xA675, /*U+A675*/ /**/
+  0xA676, /*U+A676*/ /**/
+  0xA677, /*U+A677*/ /**/
+  0xA678, /*U+A678*/ /**/
+  0xA679, /*U+A679*/ /**/
+  0xA67A, /*U+A67A*/ /**/
+  0xA67B, /*U+A67B*/ /**/
+  0xA67C, /*U+A67C*/ /**/
+  0xA67D, /*U+A67D*/ /**/
+  0xA67E, /*U+A67E*/ /**/
+  0xA67F, /*U+A67F*/ /**/
+  0xA680, /*U+A680*/ /**/
+  0xA680, /*U+A681*/ /*CYRILLIC SMALL LETTER DWE*/
+  0xA682, /*U+A682*/ /**/
+  0xA682, /*U+A683*/ /*CYRILLIC SMALL LETTER DZWE*/
+  0xA684, /*U+A684*/ /**/
+  0xA684, /*U+A685*/ /*CYRILLIC SMALL LETTER ZHWE*/
+  0xA686, /*U+A686*/ /**/
+  0xA686, /*U+A687*/ /*CYRILLIC SMALL LETTER CCHE*/
+  0xA688, /*U+A688*/ /**/
+  0xA688, /*U+A689*/ /*CYRILLIC SMALL LETTER DZZE*/
+  0xA68A, /*U+A68A*/ /**/
+  0xA68A, /*U+A68B*/ /*CYRILLIC SMALL LETTER TE WITH MIDDLE HOOK*/
+  0xA68C, /*U+A68C*/ /**/
+  0xA68C, /*U+A68D*/ /*CYRILLIC SMALL LETTER TWE*/
+  0xA68E, /*U+A68E*/ /**/
+  0xA68E, /*U+A68F*/ /*CYRILLIC SMALL LETTER TSWE*/
+  0xA690, /*U+A690*/ /**/
+  0xA690, /*U+A691*/ /*CYRILLIC SMALL LETTER TSSE*/
+  0xA692, /*U+A692*/ /**/
+  0xA692, /*U+A693*/ /*CYRILLIC SMALL LETTER TCHE*/
+  0xA694, /*U+A694*/ /**/
+  0xA694, /*U+A695*/ /*CYRILLIC SMALL LETTER HWE*/
+  0xA696, /*U+A696*/ /**/
+  0xA696, /*U+A697*/ /*CYRILLIC SMALL LETTER SHWE*/
+  0xA698, /*U+A698*/ /**/
+  0xA699, /*U+A699*/ /**/
+  0xA69A, /*U+A69A*/ /**/
+  0xA69B, /*U+A69B*/ /**/
+  0xA69C, /*U+A69C*/ /**/
+  0xA69D, /*U+A69D*/ /**/
+  0xA69E, /*U+A69E*/ /**/
+  0xA69F, /*U+A69F*/ /**/
+  0xA6A0, /*U+A6A0*/ /**/
+  0xA6A1, /*U+A6A1*/ /**/
+  0xA6A2, /*U+A6A2*/ /**/
+  0xA6A3, /*U+A6A3*/ /**/
+  0xA6A4, /*U+A6A4*/ /**/
+  0xA6A5, /*U+A6A5*/ /**/
+  0xA6A6, /*U+A6A6*/ /**/
+  0xA6A7, /*U+A6A7*/ /**/
+  0xA6A8, /*U+A6A8*/ /**/
+  0xA6A9, /*U+A6A9*/ /**/
+  0xA6AA, /*U+A6AA*/ /**/
+  0xA6AB, /*U+A6AB*/ /**/
+  0xA6AC, /*U+A6AC*/ /**/
+  0xA6AD, /*U+A6AD*/ /**/
+  0xA6AE, /*U+A6AE*/ /**/
+  0xA6AF, /*U+A6AF*/ /**/
+  0xA6B0, /*U+A6B0*/ /**/
+  0xA6B1, /*U+A6B1*/ /**/
+  0xA6B2, /*U+A6B2*/ /**/
+  0xA6B3, /*U+A6B3*/ /**/
+  0xA6B4, /*U+A6B4*/ /**/
+  0xA6B5, /*U+A6B5*/ /**/
+  0xA6B6, /*U+A6B6*/ /**/
+  0xA6B7, /*U+A6B7*/ /**/
+  0xA6B8, /*U+A6B8*/ /**/
+  0xA6B9, /*U+A6B9*/ /**/
+  0xA6BA, /*U+A6BA*/ /**/
+  0xA6BB, /*U+A6BB*/ /**/
+  0xA6BC, /*U+A6BC*/ /**/
+  0xA6BD, /*U+A6BD*/ /**/
+  0xA6BE, /*U+A6BE*/ /**/
+  0xA6BF, /*U+A6BF*/ /**/
+};
+
+static const u_int16_t upper_table_9[192] = {
+  0xA700, /*U+A700*/ /**/
+  0xA701, /*U+A701*/ /**/
+  0xA702, /*U+A702*/ /**/
+  0xA703, /*U+A703*/ /**/
+  0xA704, /*U+A704*/ /**/
+  0xA705, /*U+A705*/ /**/
+  0xA706, /*U+A706*/ /**/
+  0xA707, /*U+A707*/ /**/
+  0xA708, /*U+A708*/ /**/
+  0xA709, /*U+A709*/ /**/
+  0xA70A, /*U+A70A*/ /**/
+  0xA70B, /*U+A70B*/ /**/
+  0xA70C, /*U+A70C*/ /**/
+  0xA70D, /*U+A70D*/ /**/
+  0xA70E, /*U+A70E*/ /**/
+  0xA70F, /*U+A70F*/ /**/
+  0xA710, /*U+A710*/ /**/
+  0xA711, /*U+A711*/ /**/
+  0xA712, /*U+A712*/ /**/
+  0xA713, /*U+A713*/ /**/
+  0xA714, /*U+A714*/ /**/
+  0xA715, /*U+A715*/ /**/
+  0xA716, /*U+A716*/ /**/
+  0xA717, /*U+A717*/ /**/
+  0xA718, /*U+A718*/ /**/
+  0xA719, /*U+A719*/ /**/
+  0xA71A, /*U+A71A*/ /**/
+  0xA71B, /*U+A71B*/ /**/
+  0xA71C, /*U+A71C*/ /**/
+  0xA71D, /*U+A71D*/ /**/
+  0xA71E, /*U+A71E*/ /**/
+  0xA71F, /*U+A71F*/ /**/
+  0xA720, /*U+A720*/ /**/
+  0xA721, /*U+A721*/ /**/
+  0xA722, /*U+A722*/ /**/
+  0xA722, /*U+A723*/ /*LATIN SMALL LETTER EGYPTOLOGICAL ALEF*/
+  0xA724, /*U+A724*/ /**/
+  0xA724, /*U+A725*/ /*LATIN SMALL LETTER EGYPTOLOGICAL AIN*/
+  0xA726, /*U+A726*/ /**/
+  0xA726, /*U+A727*/ /*LATIN SMALL LETTER HENG*/
+  0xA728, /*U+A728*/ /**/
+  0xA728, /*U+A729*/ /*LATIN SMALL LETTER TZ*/
+  0xA72A, /*U+A72A*/ /**/
+  0xA72A, /*U+A72B*/ /*LATIN SMALL LETTER TRESILLO*/
+  0xA72C, /*U+A72C*/ /**/
+  0xA72C, /*U+A72D*/ /*LATIN SMALL LETTER CUATRILLO*/
+  0xA72E, /*U+A72E*/ /**/
+  0xA72E, /*U+A72F*/ /*LATIN SMALL LETTER CUATRILLO WITH COMMA*/
+  0xA730, /*U+A730*/ /**/
+  0xA731, /*U+A731*/ /**/
+  0xA732, /*U+A732*/ /**/
+  0xA732, /*U+A733*/ /*LATIN SMALL LETTER AA*/
+  0xA734, /*U+A734*/ /**/
+  0xA734, /*U+A735*/ /*LATIN SMALL LETTER AO*/
+  0xA736, /*U+A736*/ /**/
+  0xA736, /*U+A737*/ /*LATIN SMALL LETTER AU*/
+  0xA738, /*U+A738*/ /**/
+  0xA738, /*U+A739*/ /*LATIN SMALL LETTER AV*/
+  0xA73A, /*U+A73A*/ /**/
+  0xA73A, /*U+A73B*/ /*LATIN SMALL LETTER AV WITH HORIZONTAL BAR*/
+  0xA73C, /*U+A73C*/ /**/
+  0xA73C, /*U+A73D*/ /*LATIN SMALL LETTER AY*/
+  0xA73E, /*U+A73E*/ /**/
+  0xA73E, /*U+A73F*/ /*LATIN SMALL LETTER REVERSED C WITH DOT*/
+  0xA740, /*U+A740*/ /**/
+  0xA740, /*U+A741*/ /*LATIN SMALL LETTER K WITH STROKE*/
+  0xA742, /*U+A742*/ /**/
+  0xA742, /*U+A743*/ /*LATIN SMALL LETTER K WITH DIAGONAL STROKE*/
+  0xA744, /*U+A744*/ /**/
+  0xA744, /*U+A745*/ /*LATIN SMALL LETTER K WITH STROKE AND DIAGONAL STROKE*/
+  0xA746, /*U+A746*/ /**/
+  0xA746, /*U+A747*/ /*LATIN SMALL LETTER BROKEN L*/
+  0xA748, /*U+A748*/ /**/
+  0xA748, /*U+A749*/ /*LATIN SMALL LETTER L WITH HIGH STROKE*/
+  0xA74A, /*U+A74A*/ /**/
+  0xA74A, /*U+A74B*/ /*LATIN SMALL LETTER O WITH LONG STROKE OVERLAY*/
+  0xA74C, /*U+A74C*/ /**/
+  0xA74C, /*U+A74D*/ /*LATIN SMALL LETTER O WITH LOOP*/
+  0xA74E, /*U+A74E*/ /**/
+  0xA74E, /*U+A74F*/ /*LATIN SMALL LETTER OO*/
+  0xA750, /*U+A750*/ /**/
+  0xA750, /*U+A751*/ /*LATIN SMALL LETTER P WITH STROKE THROUGH DESCENDER*/
+  0xA752, /*U+A752*/ /**/
+  0xA752, /*U+A753*/ /*LATIN SMALL LETTER P WITH FLOURISH*/
+  0xA754, /*U+A754*/ /**/
+  0xA754, /*U+A755*/ /*LATIN SMALL LETTER P WITH SQUIRREL TAIL*/
+  0xA756, /*U+A756*/ /**/
+  0xA756, /*U+A757*/ /*LATIN SMALL LETTER Q WITH STROKE THROUGH DESCENDER*/
+  0xA758, /*U+A758*/ /**/
+  0xA758, /*U+A759*/ /*LATIN SMALL LETTER Q WITH DIAGONAL STROKE*/
+  0xA75A, /*U+A75A*/ /**/
+  0xA75A, /*U+A75B*/ /*LATIN SMALL LETTER R ROTUNDA*/
+  0xA75C, /*U+A75C*/ /**/
+  0xA75C, /*U+A75D*/ /*LATIN SMALL LETTER RUM ROTUNDA*/
+  0xA75E, /*U+A75E*/ /**/
+  0xA75E, /*U+A75F*/ /*LATIN SMALL LETTER V WITH DIAGONAL STROKE*/
+  0xA760, /*U+A760*/ /**/
+  0xA760, /*U+A761*/ /*LATIN SMALL LETTER VY*/
+  0xA762, /*U+A762*/ /**/
+  0xA762, /*U+A763*/ /*LATIN SMALL LETTER VISIGOTHIC Z*/
+  0xA764, /*U+A764*/ /**/
+  0xA764, /*U+A765*/ /*LATIN SMALL LETTER THORN WITH STROKE*/
+  0xA766, /*U+A766*/ /**/
+  0xA766, /*U+A767*/ /*LATIN SMALL LETTER THORN WITH STROKE THROUGH DESCENDER*/
+  0xA768, /*U+A768*/ /**/
+  0xA768, /*U+A769*/ /*LATIN SMALL LETTER VEND*/
+  0xA76A, /*U+A76A*/ /**/
+  0xA76A, /*U+A76B*/ /*LATIN SMALL LETTER ET*/
+  0xA76C, /*U+A76C*/ /**/
+  0xA76C, /*U+A76D*/ /*LATIN SMALL LETTER IS*/
+  0xA76E, /*U+A76E*/ /**/
+  0xA76E, /*U+A76F*/ /*LATIN SMALL LETTER CON*/
+  0xA770, /*U+A770*/ /**/
+  0xA771, /*U+A771*/ /**/
+  0xA772, /*U+A772*/ /**/
+  0xA773, /*U+A773*/ /**/
+  0xA774, /*U+A774*/ /**/
+  0xA775, /*U+A775*/ /**/
+  0xA776, /*U+A776*/ /**/
+  0xA777, /*U+A777*/ /**/
+  0xA778, /*U+A778*/ /**/
+  0xA779, /*U+A779*/ /**/
+  0xA779, /*U+A77A*/ /*LATIN SMALL LETTER INSULAR D*/
+  0xA77B, /*U+A77B*/ /**/
+  0xA77B, /*U+A77C*/ /*LATIN SMALL LETTER INSULAR F*/
+  0xA77D, /*U+A77D*/ /**/
+  0xA77E, /*U+A77E*/ /**/
+  0xA77E, /*U+A77F*/ /*LATIN SMALL LETTER TURNED INSULAR G*/
+  0xA780, /*U+A780*/ /**/
+  0xA780, /*U+A781*/ /*LATIN SMALL LETTER TURNED L*/
+  0xA782, /*U+A782*/ /**/
+  0xA782, /*U+A783*/ /*LATIN SMALL LETTER INSULAR R*/
+  0xA784, /*U+A784*/ /**/
+  0xA784, /*U+A785*/ /*LATIN SMALL LETTER INSULAR S*/
+  0xA786, /*U+A786*/ /**/
+  0xA786, /*U+A787*/ /*LATIN SMALL LETTER INSULAR T*/
+  0xA788, /*U+A788*/ /**/
+  0xA789, /*U+A789*/ /**/
+  0xA78A, /*U+A78A*/ /**/
+  0xA78B, /*U+A78B*/ /**/
+  0xA78B, /*U+A78C*/ /*LATIN SMALL LETTER SALTILLO*/
+  0xA78D, /*U+A78D*/ /**/
+  0xA78E, /*U+A78E*/ /**/
+  0xA78F, /*U+A78F*/ /**/
+  0xA790, /*U+A790*/ /**/
+  0xA790, /*U+A791*/ /*LATIN SMALL LETTER N WITH DESCENDER*/
+  0xA792, /*U+A792*/ /**/
+  0xA793, /*U+A793*/ /**/
+  0xA794, /*U+A794*/ /**/
+  0xA795, /*U+A795*/ /**/
+  0xA796, /*U+A796*/ /**/
+  0xA797, /*U+A797*/ /**/
+  0xA798, /*U+A798*/ /**/
+  0xA799, /*U+A799*/ /**/
+  0xA79A, /*U+A79A*/ /**/
+  0xA79B, /*U+A79B*/ /**/
+  0xA79C, /*U+A79C*/ /**/
+  0xA79D, /*U+A79D*/ /**/
+  0xA79E, /*U+A79E*/ /**/
+  0xA79F, /*U+A79F*/ /**/
+  0xA7A0, /*U+A7A0*/ /**/
+  0xA7A0, /*U+A7A1*/ /*LATIN SMALL LETTER G WITH OBLIQUE STROKE*/
+  0xA7A2, /*U+A7A2*/ /**/
+  0xA7A2, /*U+A7A3*/ /*LATIN SMALL LETTER K WITH OBLIQUE STROKE*/
+  0xA7A4, /*U+A7A4*/ /**/
+  0xA7A4, /*U+A7A5*/ /*LATIN SMALL LETTER N WITH OBLIQUE STROKE*/
+  0xA7A6, /*U+A7A6*/ /**/
+  0xA7A6, /*U+A7A7*/ /*LATIN SMALL LETTER R WITH OBLIQUE STROKE*/
+  0xA7A8, /*U+A7A8*/ /**/
+  0xA7A8, /*U+A7A9*/ /*LATIN SMALL LETTER S WITH OBLIQUE STROKE*/
+  0xA7AA, /*U+A7AA*/ /**/
+  0xA7AB, /*U+A7AB*/ /**/
+  0xA7AC, /*U+A7AC*/ /**/
+  0xA7AD, /*U+A7AD*/ /**/
+  0xA7AE, /*U+A7AE*/ /**/
+  0xA7AF, /*U+A7AF*/ /**/
+  0xA7B0, /*U+A7B0*/ /**/
+  0xA7B1, /*U+A7B1*/ /**/
+  0xA7B2, /*U+A7B2*/ /**/
+  0xA7B3, /*U+A7B3*/ /**/
+  0xA7B4, /*U+A7B4*/ /**/
+  0xA7B5, /*U+A7B5*/ /**/
+  0xA7B6, /*U+A7B6*/ /**/
+  0xA7B7, /*U+A7B7*/ /**/
+  0xA7B8, /*U+A7B8*/ /**/
+  0xA7B9, /*U+A7B9*/ /**/
+  0xA7BA, /*U+A7BA*/ /**/
+  0xA7BB, /*U+A7BB*/ /**/
+  0xA7BC, /*U+A7BC*/ /**/
+  0xA7BD, /*U+A7BD*/ /**/
+  0xA7BE, /*U+A7BE*/ /**/
+  0xA7BF, /*U+A7BF*/ /**/
+};
+
+static const u_int16_t upper_table_10[64] = {
+  0xFF40, /*U+FF40*/ /**/
+  0xFF21, /*U+FF41*/ /*FULLWIDTH LATIN SMALL LETTER A*/
+  0xFF22, /*U+FF42*/ /*FULLWIDTH LATIN SMALL LETTER B*/
+  0xFF23, /*U+FF43*/ /*FULLWIDTH LATIN SMALL LETTER C*/
+  0xFF24, /*U+FF44*/ /*FULLWIDTH LATIN SMALL LETTER D*/
+  0xFF25, /*U+FF45*/ /*FULLWIDTH LATIN SMALL LETTER E*/
+  0xFF26, /*U+FF46*/ /*FULLWIDTH LATIN SMALL LETTER F*/
+  0xFF27, /*U+FF47*/ /*FULLWIDTH LATIN SMALL LETTER G*/
+  0xFF28, /*U+FF48*/ /*FULLWIDTH LATIN SMALL LETTER H*/
+  0xFF29, /*U+FF49*/ /*FULLWIDTH LATIN SMALL LETTER I*/
+  0xFF2A, /*U+FF4A*/ /*FULLWIDTH LATIN SMALL LETTER J*/
+  0xFF2B, /*U+FF4B*/ /*FULLWIDTH LATIN SMALL LETTER K*/
+  0xFF2C, /*U+FF4C*/ /*FULLWIDTH LATIN SMALL LETTER L*/
+  0xFF2D, /*U+FF4D*/ /*FULLWIDTH LATIN SMALL LETTER M*/
+  0xFF2E, /*U+FF4E*/ /*FULLWIDTH LATIN SMALL LETTER N*/
+  0xFF2F, /*U+FF4F*/ /*FULLWIDTH LATIN SMALL LETTER O*/
+  0xFF30, /*U+FF50*/ /*FULLWIDTH LATIN SMALL LETTER P*/
+  0xFF31, /*U+FF51*/ /*FULLWIDTH LATIN SMALL LETTER Q*/
+  0xFF32, /*U+FF52*/ /*FULLWIDTH LATIN SMALL LETTER R*/
+  0xFF33, /*U+FF53*/ /*FULLWIDTH LATIN SMALL LETTER S*/
+  0xFF34, /*U+FF54*/ /*FULLWIDTH LATIN SMALL LETTER T*/
+  0xFF35, /*U+FF55*/ /*FULLWIDTH LATIN SMALL LETTER U*/
+  0xFF36, /*U+FF56*/ /*FULLWIDTH LATIN SMALL LETTER V*/
+  0xFF37, /*U+FF57*/ /*FULLWIDTH LATIN SMALL LETTER W*/
+  0xFF38, /*U+FF58*/ /*FULLWIDTH LATIN SMALL LETTER X*/
+  0xFF39, /*U+FF59*/ /*FULLWIDTH LATIN SMALL LETTER Y*/
+  0xFF3A, /*U+FF5A*/ /*FULLWIDTH LATIN SMALL LETTER Z*/
+  0xFF5B, /*U+FF5B*/ /**/
+  0xFF5C, /*U+FF5C*/ /**/
+  0xFF5D, /*U+FF5D*/ /**/
+  0xFF5E, /*U+FF5E*/ /**/
+  0xFF5F, /*U+FF5F*/ /**/
+  0xFF60, /*U+FF60*/ /**/
+  0xFF61, /*U+FF61*/ /**/
+  0xFF62, /*U+FF62*/ /**/
+  0xFF63, /*U+FF63*/ /**/
+  0xFF64, /*U+FF64*/ /**/
+  0xFF65, /*U+FF65*/ /**/
+  0xFF66, /*U+FF66*/ /**/
+  0xFF67, /*U+FF67*/ /**/
+  0xFF68, /*U+FF68*/ /**/
+  0xFF69, /*U+FF69*/ /**/
+  0xFF6A, /*U+FF6A*/ /**/
+  0xFF6B, /*U+FF6B*/ /**/
+  0xFF6C, /*U+FF6C*/ /**/
+  0xFF6D, /*U+FF6D*/ /**/
+  0xFF6E, /*U+FF6E*/ /**/
+  0xFF6F, /*U+FF6F*/ /**/
+  0xFF70, /*U+FF70*/ /**/
+  0xFF71, /*U+FF71*/ /**/
+  0xFF72, /*U+FF72*/ /**/
+  0xFF73, /*U+FF73*/ /**/
+  0xFF74, /*U+FF74*/ /**/
+  0xFF75, /*U+FF75*/ /**/
+  0xFF76, /*U+FF76*/ /**/
+  0xFF77, /*U+FF77*/ /**/
+  0xFF78, /*U+FF78*/ /**/
+  0xFF79, /*U+FF79*/ /**/
+  0xFF7A, /*U+FF7A*/ /**/
+  0xFF7B, /*U+FF7B*/ /**/
+  0xFF7C, /*U+FF7C*/ /**/
+  0xFF7D, /*U+FF7D*/ /**/
+  0xFF7E, /*U+FF7E*/ /**/
+  0xFF7F, /*U+FF7F*/ /**/
+};
+
+static const u_int32_t upper_table_sp_1[128] = {
+  0xD801DC00, /*0xD801DC00*/ /*U+010400*/ /*U+010400*/ /**/
+  0xD801DC01, /*0xD801DC01*/ /*U+010401*/ /*U+010401*/ /**/
+  0xD801DC02, /*0xD801DC02*/ /*U+010402*/ /*U+010402*/ /**/
+  0xD801DC03, /*0xD801DC03*/ /*U+010403*/ /*U+010403*/ /**/
+  0xD801DC04, /*0xD801DC04*/ /*U+010404*/ /*U+010404*/ /**/
+  0xD801DC05, /*0xD801DC05*/ /*U+010405*/ /*U+010405*/ /**/
+  0xD801DC06, /*0xD801DC06*/ /*U+010406*/ /*U+010406*/ /**/
+  0xD801DC07, /*0xD801DC07*/ /*U+010407*/ /*U+010407*/ /**/
+  0xD801DC08, /*0xD801DC08*/ /*U+010408*/ /*U+010408*/ /**/
+  0xD801DC09, /*0xD801DC09*/ /*U+010409*/ /*U+010409*/ /**/
+  0xD801DC0A, /*0xD801DC0A*/ /*U+01040A*/ /*U+01040A*/ /**/
+  0xD801DC0B, /*0xD801DC0B*/ /*U+01040B*/ /*U+01040B*/ /**/
+  0xD801DC0C, /*0xD801DC0C*/ /*U+01040C*/ /*U+01040C*/ /**/
+  0xD801DC0D, /*0xD801DC0D*/ /*U+01040D*/ /*U+01040D*/ /**/
+  0xD801DC0E, /*0xD801DC0E*/ /*U+01040E*/ /*U+01040E*/ /**/
+  0xD801DC0F, /*0xD801DC0F*/ /*U+01040F*/ /*U+01040F*/ /**/
+  0xD801DC10, /*0xD801DC10*/ /*U+010410*/ /*U+010410*/ /**/
+  0xD801DC11, /*0xD801DC11*/ /*U+010411*/ /*U+010411*/ /**/
+  0xD801DC12, /*0xD801DC12*/ /*U+010412*/ /*U+010412*/ /**/
+  0xD801DC13, /*0xD801DC13*/ /*U+010413*/ /*U+010413*/ /**/
+  0xD801DC14, /*0xD801DC14*/ /*U+010414*/ /*U+010414*/ /**/
+  0xD801DC15, /*0xD801DC15*/ /*U+010415*/ /*U+010415*/ /**/
+  0xD801DC16, /*0xD801DC16*/ /*U+010416*/ /*U+010416*/ /**/
+  0xD801DC17, /*0xD801DC17*/ /*U+010417*/ /*U+010417*/ /**/
+  0xD801DC18, /*0xD801DC18*/ /*U+010418*/ /*U+010418*/ /**/
+  0xD801DC19, /*0xD801DC19*/ /*U+010419*/ /*U+010419*/ /**/
+  0xD801DC1A, /*0xD801DC1A*/ /*U+01041A*/ /*U+01041A*/ /**/
+  0xD801DC1B, /*0xD801DC1B*/ /*U+01041B*/ /*U+01041B*/ /**/
+  0xD801DC1C, /*0xD801DC1C*/ /*U+01041C*/ /*U+01041C*/ /**/
+  0xD801DC1D, /*0xD801DC1D*/ /*U+01041D*/ /*U+01041D*/ /**/
+  0xD801DC1E, /*0xD801DC1E*/ /*U+01041E*/ /*U+01041E*/ /**/
+  0xD801DC1F, /*0xD801DC1F*/ /*U+01041F*/ /*U+01041F*/ /**/
+  0xD801DC20, /*0xD801DC20*/ /*U+010420*/ /*U+010420*/ /**/
+  0xD801DC21, /*0xD801DC21*/ /*U+010421*/ /*U+010421*/ /**/
+  0xD801DC22, /*0xD801DC22*/ /*U+010422*/ /*U+010422*/ /**/
+  0xD801DC23, /*0xD801DC23*/ /*U+010423*/ /*U+010423*/ /**/
+  0xD801DC24, /*0xD801DC24*/ /*U+010424*/ /*U+010424*/ /**/
+  0xD801DC25, /*0xD801DC25*/ /*U+010425*/ /*U+010425*/ /**/
+  0xD801DC26, /*0xD801DC26*/ /*U+010426*/ /*U+010426*/ /**/
+  0xD801DC27, /*0xD801DC27*/ /*U+010427*/ /*U+010427*/ /**/
+  0xD801DC00, /*0xD801DC28*/ /*U+010400*/ /*U+010428*/ /*DESERET SMALL LETTER LONG I*/
+  0xD801DC01, /*0xD801DC29*/ /*U+010401*/ /*U+010429*/ /*DESERET SMALL LETTER LONG E*/
+  0xD801DC02, /*0xD801DC2A*/ /*U+010402*/ /*U+01042A*/ /*DESERET SMALL LETTER LONG A*/
+  0xD801DC03, /*0xD801DC2B*/ /*U+010403*/ /*U+01042B*/ /*DESERET SMALL LETTER LONG AH*/
+  0xD801DC04, /*0xD801DC2C*/ /*U+010404*/ /*U+01042C*/ /*DESERET SMALL LETTER LONG O*/
+  0xD801DC05, /*0xD801DC2D*/ /*U+010405*/ /*U+01042D*/ /*DESERET SMALL LETTER LONG OO*/
+  0xD801DC06, /*0xD801DC2E*/ /*U+010406*/ /*U+01042E*/ /*DESERET SMALL LETTER SHORT I*/
+  0xD801DC07, /*0xD801DC2F*/ /*U+010407*/ /*U+01042F*/ /*DESERET SMALL LETTER SHORT E*/
+  0xD801DC08, /*0xD801DC30*/ /*U+010408*/ /*U+010430*/ /*DESERET SMALL LETTER SHORT A*/
+  0xD801DC09, /*0xD801DC31*/ /*U+010409*/ /*U+010431*/ /*DESERET SMALL LETTER SHORT AH*/
+  0xD801DC0A, /*0xD801DC32*/ /*U+01040A*/ /*U+010432*/ /*DESERET SMALL LETTER SHORT O*/
+  0xD801DC0B, /*0xD801DC33*/ /*U+01040B*/ /*U+010433*/ /*DESERET SMALL LETTER SHORT OO*/
+  0xD801DC0C, /*0xD801DC34*/ /*U+01040C*/ /*U+010434*/ /*DESERET SMALL LETTER AY*/
+  0xD801DC0D, /*0xD801DC35*/ /*U+01040D*/ /*U+010435*/ /*DESERET SMALL LETTER OW*/
+  0xD801DC0E, /*0xD801DC36*/ /*U+01040E*/ /*U+010436*/ /*DESERET SMALL LETTER WU*/
+  0xD801DC0F, /*0xD801DC37*/ /*U+01040F*/ /*U+010437*/ /*DESERET SMALL LETTER YEE*/
+  0xD801DC10, /*0xD801DC38*/ /*U+010410*/ /*U+010438*/ /*DESERET SMALL LETTER H*/
+  0xD801DC11, /*0xD801DC39*/ /*U+010411*/ /*U+010439*/ /*DESERET SMALL LETTER PEE*/
+  0xD801DC12, /*0xD801DC3A*/ /*U+010412*/ /*U+01043A*/ /*DESERET SMALL LETTER BEE*/
+  0xD801DC13, /*0xD801DC3B*/ /*U+010413*/ /*U+01043B*/ /*DESERET SMALL LETTER TEE*/
+  0xD801DC14, /*0xD801DC3C*/ /*U+010414*/ /*U+01043C*/ /*DESERET SMALL LETTER DEE*/
+  0xD801DC15, /*0xD801DC3D*/ /*U+010415*/ /*U+01043D*/ /*DESERET SMALL LETTER CHEE*/
+  0xD801DC16, /*0xD801DC3E*/ /*U+010416*/ /*U+01043E*/ /*DESERET SMALL LETTER JEE*/
+  0xD801DC17, /*0xD801DC3F*/ /*U+010417*/ /*U+01043F*/ /*DESERET SMALL LETTER KAY*/
+  0xD801DC18, /*0xD801DC40*/ /*U+010418*/ /*U+010440*/ /*DESERET SMALL LETTER GAY*/
+  0xD801DC19, /*0xD801DC41*/ /*U+010419*/ /*U+010441*/ /*DESERET SMALL LETTER EF*/
+  0xD801DC1A, /*0xD801DC42*/ /*U+01041A*/ /*U+010442*/ /*DESERET SMALL LETTER VEE*/
+  0xD801DC1B, /*0xD801DC43*/ /*U+01041B*/ /*U+010443*/ /*DESERET SMALL LETTER ETH*/
+  0xD801DC1C, /*0xD801DC44*/ /*U+01041C*/ /*U+010444*/ /*DESERET SMALL LETTER THEE*/
+  0xD801DC1D, /*0xD801DC45*/ /*U+01041D*/ /*U+010445*/ /*DESERET SMALL LETTER ES*/
+  0xD801DC1E, /*0xD801DC46*/ /*U+01041E*/ /*U+010446*/ /*DESERET SMALL LETTER ZEE*/
+  0xD801DC1F, /*0xD801DC47*/ /*U+01041F*/ /*U+010447*/ /*DESERET SMALL LETTER ESH*/
+  0xD801DC20, /*0xD801DC48*/ /*U+010420*/ /*U+010448*/ /*DESERET SMALL LETTER ZHEE*/
+  0xD801DC21, /*0xD801DC49*/ /*U+010421*/ /*U+010449*/ /*DESERET SMALL LETTER ER*/
+  0xD801DC22, /*0xD801DC4A*/ /*U+010422*/ /*U+01044A*/ /*DESERET SMALL LETTER EL*/
+  0xD801DC23, /*0xD801DC4B*/ /*U+010423*/ /*U+01044B*/ /*DESERET SMALL LETTER EM*/
+  0xD801DC24, /*0xD801DC4C*/ /*U+010424*/ /*U+01044C*/ /*DESERET SMALL LETTER EN*/
+  0xD801DC25, /*0xD801DC4D*/ /*U+010425*/ /*U+01044D*/ /*DESERET SMALL LETTER ENG*/
+  0xD801DC26, /*0xD801DC4E*/ /*U+010426*/ /*U+01044E*/ /*DESERET SMALL LETTER OI*/
+  0xD801DC27, /*0xD801DC4F*/ /*U+010427*/ /*U+01044F*/ /*DESERET SMALL LETTER EW*/
+  0xD801DC50, /*0xD801DC50*/ /*U+010450*/ /*U+010450*/ /**/
+  0xD801DC51, /*0xD801DC51*/ /*U+010451*/ /*U+010451*/ /**/
+  0xD801DC52, /*0xD801DC52*/ /*U+010452*/ /*U+010452*/ /**/
+  0xD801DC53, /*0xD801DC53*/ /*U+010453*/ /*U+010453*/ /**/
+  0xD801DC54, /*0xD801DC54*/ /*U+010454*/ /*U+010454*/ /**/
+  0xD801DC55, /*0xD801DC55*/ /*U+010455*/ /*U+010455*/ /**/
+  0xD801DC56, /*0xD801DC56*/ /*U+010456*/ /*U+010456*/ /**/
+  0xD801DC57, /*0xD801DC57*/ /*U+010457*/ /*U+010457*/ /**/
+  0xD801DC58, /*0xD801DC58*/ /*U+010458*/ /*U+010458*/ /**/
+  0xD801DC59, /*0xD801DC59*/ /*U+010459*/ /*U+010459*/ /**/
+  0xD801DC5A, /*0xD801DC5A*/ /*U+01045A*/ /*U+01045A*/ /**/
+  0xD801DC5B, /*0xD801DC5B*/ /*U+01045B*/ /*U+01045B*/ /**/
+  0xD801DC5C, /*0xD801DC5C*/ /*U+01045C*/ /*U+01045C*/ /**/
+  0xD801DC5D, /*0xD801DC5D*/ /*U+01045D*/ /*U+01045D*/ /**/
+  0xD801DC5E, /*0xD801DC5E*/ /*U+01045E*/ /*U+01045E*/ /**/
+  0xD801DC5F, /*0xD801DC5F*/ /*U+01045F*/ /*U+01045F*/ /**/
+  0xD801DC60, /*0xD801DC60*/ /*U+010460*/ /*U+010460*/ /**/
+  0xD801DC61, /*0xD801DC61*/ /*U+010461*/ /*U+010461*/ /**/
+  0xD801DC62, /*0xD801DC62*/ /*U+010462*/ /*U+010462*/ /**/
+  0xD801DC63, /*0xD801DC63*/ /*U+010463*/ /*U+010463*/ /**/
+  0xD801DC64, /*0xD801DC64*/ /*U+010464*/ /*U+010464*/ /**/
+  0xD801DC65, /*0xD801DC65*/ /*U+010465*/ /*U+010465*/ /**/
+  0xD801DC66, /*0xD801DC66*/ /*U+010466*/ /*U+010466*/ /**/
+  0xD801DC67, /*0xD801DC67*/ /*U+010467*/ /*U+010467*/ /**/
+  0xD801DC68, /*0xD801DC68*/ /*U+010468*/ /*U+010468*/ /**/
+  0xD801DC69, /*0xD801DC69*/ /*U+010469*/ /*U+010469*/ /**/
+  0xD801DC6A, /*0xD801DC6A*/ /*U+01046A*/ /*U+01046A*/ /**/
+  0xD801DC6B, /*0xD801DC6B*/ /*U+01046B*/ /*U+01046B*/ /**/
+  0xD801DC6C, /*0xD801DC6C*/ /*U+01046C*/ /*U+01046C*/ /**/
+  0xD801DC6D, /*0xD801DC6D*/ /*U+01046D*/ /*U+01046D*/ /**/
+  0xD801DC6E, /*0xD801DC6E*/ /*U+01046E*/ /*U+01046E*/ /**/
+  0xD801DC6F, /*0xD801DC6F*/ /*U+01046F*/ /*U+01046F*/ /**/
+  0xD801DC70, /*0xD801DC70*/ /*U+010470*/ /*U+010470*/ /**/
+  0xD801DC71, /*0xD801DC71*/ /*U+010471*/ /*U+010471*/ /**/
+  0xD801DC72, /*0xD801DC72*/ /*U+010472*/ /*U+010472*/ /**/
+  0xD801DC73, /*0xD801DC73*/ /*U+010473*/ /*U+010473*/ /**/
+  0xD801DC74, /*0xD801DC74*/ /*U+010474*/ /*U+010474*/ /**/
+  0xD801DC75, /*0xD801DC75*/ /*U+010475*/ /*U+010475*/ /**/
+  0xD801DC76, /*0xD801DC76*/ /*U+010476*/ /*U+010476*/ /**/
+  0xD801DC77, /*0xD801DC77*/ /*U+010477*/ /*U+010477*/ /**/
+  0xD801DC78, /*0xD801DC78*/ /*U+010478*/ /*U+010478*/ /**/
+  0xD801DC79, /*0xD801DC79*/ /*U+010479*/ /*U+010479*/ /**/
+  0xD801DC7A, /*0xD801DC7A*/ /*U+01047A*/ /*U+01047A*/ /**/
+  0xD801DC7B, /*0xD801DC7B*/ /*U+01047B*/ /*U+01047B*/ /**/
+  0xD801DC7C, /*0xD801DC7C*/ /*U+01047C*/ /*U+01047C*/ /**/
+  0xD801DC7D, /*0xD801DC7D*/ /*U+01047D*/ /*U+01047D*/ /**/
+  0xD801DC7E, /*0xD801DC7E*/ /*U+01047E*/ /*U+01047E*/ /**/
+  0xD801DC7F, /*0xD801DC7F*/ /*U+01047F*/ /*U+01047F*/ /**/
+};
+
+static const u_int16_t lower_table_1[128] = {
+  0x0000, /*U+0000*/ /**/
+  0x0001, /*U+0001*/ /**/
+  0x0002, /*U+0002*/ /**/
+  0x0003, /*U+0003*/ /**/
+  0x0004, /*U+0004*/ /**/
+  0x0005, /*U+0005*/ /**/
+  0x0006, /*U+0006*/ /**/
+  0x0007, /*U+0007*/ /**/
+  0x0008, /*U+0008*/ /**/
+  0x0009, /*U+0009*/ /**/
+  0x000A, /*U+000A*/ /**/
+  0x000B, /*U+000B*/ /**/
+  0x000C, /*U+000C*/ /**/
+  0x000D, /*U+000D*/ /**/
+  0x000E, /*U+000E*/ /**/
+  0x000F, /*U+000F*/ /**/
+  0x0010, /*U+0010*/ /**/
+  0x0011, /*U+0011*/ /**/
+  0x0012, /*U+0012*/ /**/
+  0x0013, /*U+0013*/ /**/
+  0x0014, /*U+0014*/ /**/
+  0x0015, /*U+0015*/ /**/
+  0x0016, /*U+0016*/ /**/
+  0x0017, /*U+0017*/ /**/
+  0x0018, /*U+0018*/ /**/
+  0x0019, /*U+0019*/ /**/
+  0x001A, /*U+001A*/ /**/
+  0x001B, /*U+001B*/ /**/
+  0x001C, /*U+001C*/ /**/
+  0x001D, /*U+001D*/ /**/
+  0x001E, /*U+001E*/ /**/
+  0x001F, /*U+001F*/ /**/
+  0x0020, /*U+0020*/ /**/
+  0x0021, /*U+0021*/ /**/
+  0x0022, /*U+0022*/ /**/
+  0x0023, /*U+0023*/ /**/
+  0x0024, /*U+0024*/ /**/
+  0x0025, /*U+0025*/ /**/
+  0x0026, /*U+0026*/ /**/
+  0x0027, /*U+0027*/ /**/
+  0x0028, /*U+0028*/ /**/
+  0x0029, /*U+0029*/ /**/
+  0x002A, /*U+002A*/ /**/
+  0x002B, /*U+002B*/ /**/
+  0x002C, /*U+002C*/ /**/
+  0x002D, /*U+002D*/ /**/
+  0x002E, /*U+002E*/ /**/
+  0x002F, /*U+002F*/ /**/
+  0x0030, /*U+0030*/ /**/
+  0x0031, /*U+0031*/ /**/
+  0x0032, /*U+0032*/ /**/
+  0x0033, /*U+0033*/ /**/
+  0x0034, /*U+0034*/ /**/
+  0x0035, /*U+0035*/ /**/
+  0x0036, /*U+0036*/ /**/
+  0x0037, /*U+0037*/ /**/
+  0x0038, /*U+0038*/ /**/
+  0x0039, /*U+0039*/ /**/
+  0x003A, /*U+003A*/ /**/
+  0x003B, /*U+003B*/ /**/
+  0x003C, /*U+003C*/ /**/
+  0x003D, /*U+003D*/ /**/
+  0x003E, /*U+003E*/ /**/
+  0x003F, /*U+003F*/ /**/
+  0x0040, /*U+0040*/ /**/
+  0x0061, /*U+0041*/ /*LATIN CAPITAL LETTER A*/
+  0x0062, /*U+0042*/ /*LATIN CAPITAL LETTER B*/
+  0x0063, /*U+0043*/ /*LATIN CAPITAL LETTER C*/
+  0x0064, /*U+0044*/ /*LATIN CAPITAL LETTER D*/
+  0x0065, /*U+0045*/ /*LATIN CAPITAL LETTER E*/
+  0x0066, /*U+0046*/ /*LATIN CAPITAL LETTER F*/
+  0x0067, /*U+0047*/ /*LATIN CAPITAL LETTER G*/
+  0x0068, /*U+0048*/ /*LATIN CAPITAL LETTER H*/
+  0x0069, /*U+0049*/ /*LATIN CAPITAL LETTER I*/
+  0x006A, /*U+004A*/ /*LATIN CAPITAL LETTER J*/
+  0x006B, /*U+004B*/ /*LATIN CAPITAL LETTER K*/
+  0x006C, /*U+004C*/ /*LATIN CAPITAL LETTER L*/
+  0x006D, /*U+004D*/ /*LATIN CAPITAL LETTER M*/
+  0x006E, /*U+004E*/ /*LATIN CAPITAL LETTER N*/
+  0x006F, /*U+004F*/ /*LATIN CAPITAL LETTER O*/
+  0x0070, /*U+0050*/ /*LATIN CAPITAL LETTER P*/
+  0x0071, /*U+0051*/ /*LATIN CAPITAL LETTER Q*/
+  0x0072, /*U+0052*/ /*LATIN CAPITAL LETTER R*/
+  0x0073, /*U+0053*/ /*LATIN CAPITAL LETTER S*/
+  0x0074, /*U+0054*/ /*LATIN CAPITAL LETTER T*/
+  0x0075, /*U+0055*/ /*LATIN CAPITAL LETTER U*/
+  0x0076, /*U+0056*/ /*LATIN CAPITAL LETTER V*/
+  0x0077, /*U+0057*/ /*LATIN CAPITAL LETTER W*/
+  0x0078, /*U+0058*/ /*LATIN CAPITAL LETTER X*/
+  0x0079, /*U+0059*/ /*LATIN CAPITAL LETTER Y*/
+  0x007A, /*U+005A*/ /*LATIN CAPITAL LETTER Z*/
+  0x005B, /*U+005B*/ /**/
+  0x005C, /*U+005C*/ /**/
+  0x005D, /*U+005D*/ /**/
+  0x005E, /*U+005E*/ /**/
+  0x005F, /*U+005F*/ /**/
+  0x0060, /*U+0060*/ /**/
+  0x0061, /*U+0061*/ /**/
+  0x0062, /*U+0062*/ /**/
+  0x0063, /*U+0063*/ /**/
+  0x0064, /*U+0064*/ /**/
+  0x0065, /*U+0065*/ /**/
+  0x0066, /*U+0066*/ /**/
+  0x0067, /*U+0067*/ /**/
+  0x0068, /*U+0068*/ /**/
+  0x0069, /*U+0069*/ /**/
+  0x006A, /*U+006A*/ /**/
+  0x006B, /*U+006B*/ /**/
+  0x006C, /*U+006C*/ /**/
+  0x006D, /*U+006D*/ /**/
+  0x006E, /*U+006E*/ /**/
+  0x006F, /*U+006F*/ /**/
+  0x0070, /*U+0070*/ /**/
+  0x0071, /*U+0071*/ /**/
+  0x0072, /*U+0072*/ /**/
+  0x0073, /*U+0073*/ /**/
+  0x0074, /*U+0074*/ /**/
+  0x0075, /*U+0075*/ /**/
+  0x0076, /*U+0076*/ /**/
+  0x0077, /*U+0077*/ /**/
+  0x0078, /*U+0078*/ /**/
+  0x0079, /*U+0079*/ /**/
+  0x007A, /*U+007A*/ /**/
+  0x007B, /*U+007B*/ /**/
+  0x007C, /*U+007C*/ /**/
+  0x007D, /*U+007D*/ /**/
+  0x007E, /*U+007E*/ /**/
+  0x007F, /*U+007F*/ /**/
+};
+
+static const u_int16_t lower_table_2[448] = {
+  0x00E0, /*U+00C0*/ /*LATIN CAPITAL LETTER A WITH GRAVE*/
+  0x00E1, /*U+00C1*/ /*LATIN CAPITAL LETTER A WITH ACUTE*/
+  0x00E2, /*U+00C2*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX*/
+  0x00E3, /*U+00C3*/ /*LATIN CAPITAL LETTER A WITH TILDE*/
+  0x00E4, /*U+00C4*/ /*LATIN CAPITAL LETTER A WITH DIAERESIS*/
+  0x00E5, /*U+00C5*/ /*LATIN CAPITAL LETTER A WITH RING ABOVE*/
+  0x00E6, /*U+00C6*/ /*LATIN CAPITAL LETTER AE*/
+  0x00E7, /*U+00C7*/ /*LATIN CAPITAL LETTER C WITH CEDILLA*/
+  0x00E8, /*U+00C8*/ /*LATIN CAPITAL LETTER E WITH GRAVE*/
+  0x00E9, /*U+00C9*/ /*LATIN CAPITAL LETTER E WITH ACUTE*/
+  0x00EA, /*U+00CA*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX*/
+  0x00EB, /*U+00CB*/ /*LATIN CAPITAL LETTER E WITH DIAERESIS*/
+  0x00EC, /*U+00CC*/ /*LATIN CAPITAL LETTER I WITH GRAVE*/
+  0x00ED, /*U+00CD*/ /*LATIN CAPITAL LETTER I WITH ACUTE*/
+  0x00EE, /*U+00CE*/ /*LATIN CAPITAL LETTER I WITH CIRCUMFLEX*/
+  0x00EF, /*U+00CF*/ /*LATIN CAPITAL LETTER I WITH DIAERESIS*/
+  0x00F0, /*U+00D0*/ /*LATIN CAPITAL LETTER ETH*/
+  0x00F1, /*U+00D1*/ /*LATIN CAPITAL LETTER N WITH TILDE*/
+  0x00F2, /*U+00D2*/ /*LATIN CAPITAL LETTER O WITH GRAVE*/
+  0x00F3, /*U+00D3*/ /*LATIN CAPITAL LETTER O WITH ACUTE*/
+  0x00F4, /*U+00D4*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX*/
+  0x00F5, /*U+00D5*/ /*LATIN CAPITAL LETTER O WITH TILDE*/
+  0x00F6, /*U+00D6*/ /*LATIN CAPITAL LETTER O WITH DIAERESIS*/
+  0x00D7, /*U+00D7*/ /**/
+  0x00F8, /*U+00D8*/ /*LATIN CAPITAL LETTER O WITH STROKE*/
+  0x00F9, /*U+00D9*/ /*LATIN CAPITAL LETTER U WITH GRAVE*/
+  0x00FA, /*U+00DA*/ /*LATIN CAPITAL LETTER U WITH ACUTE*/
+  0x00FB, /*U+00DB*/ /*LATIN CAPITAL LETTER U WITH CIRCUMFLEX*/
+  0x00FC, /*U+00DC*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS*/
+  0x00FD, /*U+00DD*/ /*LATIN CAPITAL LETTER Y WITH ACUTE*/
+  0x00FE, /*U+00DE*/ /*LATIN CAPITAL LETTER THORN*/
+  0x00DF, /*U+00DF*/ /**/
+  0x00E0, /*U+00E0*/ /**/
+  0x00E1, /*U+00E1*/ /**/
+  0x00E2, /*U+00E2*/ /**/
+  0x00E3, /*U+00E3*/ /**/
+  0x00E4, /*U+00E4*/ /**/
+  0x00E5, /*U+00E5*/ /**/
+  0x00E6, /*U+00E6*/ /**/
+  0x00E7, /*U+00E7*/ /**/
+  0x00E8, /*U+00E8*/ /**/
+  0x00E9, /*U+00E9*/ /**/
+  0x00EA, /*U+00EA*/ /**/
+  0x00EB, /*U+00EB*/ /**/
+  0x00EC, /*U+00EC*/ /**/
+  0x00ED, /*U+00ED*/ /**/
+  0x00EE, /*U+00EE*/ /**/
+  0x00EF, /*U+00EF*/ /**/
+  0x00F0, /*U+00F0*/ /**/
+  0x00F1, /*U+00F1*/ /**/
+  0x00F2, /*U+00F2*/ /**/
+  0x00F3, /*U+00F3*/ /**/
+  0x00F4, /*U+00F4*/ /**/
+  0x00F5, /*U+00F5*/ /**/
+  0x00F6, /*U+00F6*/ /**/
+  0x00F7, /*U+00F7*/ /**/
+  0x00F8, /*U+00F8*/ /**/
+  0x00F9, /*U+00F9*/ /**/
+  0x00FA, /*U+00FA*/ /**/
+  0x00FB, /*U+00FB*/ /**/
+  0x00FC, /*U+00FC*/ /**/
+  0x00FD, /*U+00FD*/ /**/
+  0x00FE, /*U+00FE*/ /**/
+  0x00FF, /*U+00FF*/ /**/
+  0x0101, /*U+0100*/ /*LATIN CAPITAL LETTER A WITH MACRON*/
+  0x0101, /*U+0101*/ /**/
+  0x0103, /*U+0102*/ /*LATIN CAPITAL LETTER A WITH BREVE*/
+  0x0103, /*U+0103*/ /**/
+  0x0105, /*U+0104*/ /*LATIN CAPITAL LETTER A WITH OGONEK*/
+  0x0105, /*U+0105*/ /**/
+  0x0107, /*U+0106*/ /*LATIN CAPITAL LETTER C WITH ACUTE*/
+  0x0107, /*U+0107*/ /**/
+  0x0109, /*U+0108*/ /*LATIN CAPITAL LETTER C WITH CIRCUMFLEX*/
+  0x0109, /*U+0109*/ /**/
+  0x010B, /*U+010A*/ /*LATIN CAPITAL LETTER C WITH DOT ABOVE*/
+  0x010B, /*U+010B*/ /**/
+  0x010D, /*U+010C*/ /*LATIN CAPITAL LETTER C WITH CARON*/
+  0x010D, /*U+010D*/ /**/
+  0x010F, /*U+010E*/ /*LATIN CAPITAL LETTER D WITH CARON*/
+  0x010F, /*U+010F*/ /**/
+  0x0111, /*U+0110*/ /*LATIN CAPITAL LETTER D WITH STROKE*/
+  0x0111, /*U+0111*/ /**/
+  0x0113, /*U+0112*/ /*LATIN CAPITAL LETTER E WITH MACRON*/
+  0x0113, /*U+0113*/ /**/
+  0x0115, /*U+0114*/ /*LATIN CAPITAL LETTER E WITH BREVE*/
+  0x0115, /*U+0115*/ /**/
+  0x0117, /*U+0116*/ /*LATIN CAPITAL LETTER E WITH DOT ABOVE*/
+  0x0117, /*U+0117*/ /**/
+  0x0119, /*U+0118*/ /*LATIN CAPITAL LETTER E WITH OGONEK*/
+  0x0119, /*U+0119*/ /**/
+  0x011B, /*U+011A*/ /*LATIN CAPITAL LETTER E WITH CARON*/
+  0x011B, /*U+011B*/ /**/
+  0x011D, /*U+011C*/ /*LATIN CAPITAL LETTER G WITH CIRCUMFLEX*/
+  0x011D, /*U+011D*/ /**/
+  0x011F, /*U+011E*/ /*LATIN CAPITAL LETTER G WITH BREVE*/
+  0x011F, /*U+011F*/ /**/
+  0x0121, /*U+0120*/ /*LATIN CAPITAL LETTER G WITH DOT ABOVE*/
+  0x0121, /*U+0121*/ /**/
+  0x0123, /*U+0122*/ /*LATIN CAPITAL LETTER G WITH CEDILLA*/
+  0x0123, /*U+0123*/ /**/
+  0x0125, /*U+0124*/ /*LATIN CAPITAL LETTER H WITH CIRCUMFLEX*/
+  0x0125, /*U+0125*/ /**/
+  0x0127, /*U+0126*/ /*LATIN CAPITAL LETTER H WITH STROKE*/
+  0x0127, /*U+0127*/ /**/
+  0x0129, /*U+0128*/ /*LATIN CAPITAL LETTER I WITH TILDE*/
+  0x0129, /*U+0129*/ /**/
+  0x012B, /*U+012A*/ /*LATIN CAPITAL LETTER I WITH MACRON*/
+  0x012B, /*U+012B*/ /**/
+  0x012D, /*U+012C*/ /*LATIN CAPITAL LETTER I WITH BREVE*/
+  0x012D, /*U+012D*/ /**/
+  0x012F, /*U+012E*/ /*LATIN CAPITAL LETTER I WITH OGONEK*/
+  0x012F, /*U+012F*/ /**/
+  0x0069, /*U+0130*/ /*LATIN CAPITAL LETTER I WITH DOT ABOVE*/
+  0x0131, /*U+0131*/ /**/
+  0x0133, /*U+0132*/ /*LATIN CAPITAL LIGATURE IJ*/
+  0x0133, /*U+0133*/ /**/
+  0x0135, /*U+0134*/ /*LATIN CAPITAL LETTER J WITH CIRCUMFLEX*/
+  0x0135, /*U+0135*/ /**/
+  0x0137, /*U+0136*/ /*LATIN CAPITAL LETTER K WITH CEDILLA*/
+  0x0137, /*U+0137*/ /**/
+  0x0138, /*U+0138*/ /**/
+  0x013A, /*U+0139*/ /*LATIN CAPITAL LETTER L WITH ACUTE*/
+  0x013A, /*U+013A*/ /**/
+  0x013C, /*U+013B*/ /*LATIN CAPITAL LETTER L WITH CEDILLA*/
+  0x013C, /*U+013C*/ /**/
+  0x013E, /*U+013D*/ /*LATIN CAPITAL LETTER L WITH CARON*/
+  0x013E, /*U+013E*/ /**/
+  0x0140, /*U+013F*/ /*LATIN CAPITAL LETTER L WITH MIDDLE DOT*/
+  0x0140, /*U+0140*/ /**/
+  0x0142, /*U+0141*/ /*LATIN CAPITAL LETTER L WITH STROKE*/
+  0x0142, /*U+0142*/ /**/
+  0x0144, /*U+0143*/ /*LATIN CAPITAL LETTER N WITH ACUTE*/
+  0x0144, /*U+0144*/ /**/
+  0x0146, /*U+0145*/ /*LATIN CAPITAL LETTER N WITH CEDILLA*/
+  0x0146, /*U+0146*/ /**/
+  0x0148, /*U+0147*/ /*LATIN CAPITAL LETTER N WITH CARON*/
+  0x0148, /*U+0148*/ /**/
+  0x0149, /*U+0149*/ /**/
+  0x014B, /*U+014A*/ /*LATIN CAPITAL LETTER ENG*/
+  0x014B, /*U+014B*/ /**/
+  0x014D, /*U+014C*/ /*LATIN CAPITAL LETTER O WITH MACRON*/
+  0x014D, /*U+014D*/ /**/
+  0x014F, /*U+014E*/ /*LATIN CAPITAL LETTER O WITH BREVE*/
+  0x014F, /*U+014F*/ /**/
+  0x0151, /*U+0150*/ /*LATIN CAPITAL LETTER O WITH DOUBLE ACUTE*/
+  0x0151, /*U+0151*/ /**/
+  0x0153, /*U+0152*/ /*LATIN CAPITAL LIGATURE OE*/
+  0x0153, /*U+0153*/ /**/
+  0x0155, /*U+0154*/ /*LATIN CAPITAL LETTER R WITH ACUTE*/
+  0x0155, /*U+0155*/ /**/
+  0x0157, /*U+0156*/ /*LATIN CAPITAL LETTER R WITH CEDILLA*/
+  0x0157, /*U+0157*/ /**/
+  0x0159, /*U+0158*/ /*LATIN CAPITAL LETTER R WITH CARON*/
+  0x0159, /*U+0159*/ /**/
+  0x015B, /*U+015A*/ /*LATIN CAPITAL LETTER S WITH ACUTE*/
+  0x015B, /*U+015B*/ /**/
+  0x015D, /*U+015C*/ /*LATIN CAPITAL LETTER S WITH CIRCUMFLEX*/
+  0x015D, /*U+015D*/ /**/
+  0x015F, /*U+015E*/ /*LATIN CAPITAL LETTER S WITH CEDILLA*/
+  0x015F, /*U+015F*/ /**/
+  0x0161, /*U+0160*/ /*LATIN CAPITAL LETTER S WITH CARON*/
+  0x0161, /*U+0161*/ /**/
+  0x0163, /*U+0162*/ /*LATIN CAPITAL LETTER T WITH CEDILLA*/
+  0x0163, /*U+0163*/ /**/
+  0x0165, /*U+0164*/ /*LATIN CAPITAL LETTER T WITH CARON*/
+  0x0165, /*U+0165*/ /**/
+  0x0167, /*U+0166*/ /*LATIN CAPITAL LETTER T WITH STROKE*/
+  0x0167, /*U+0167*/ /**/
+  0x0169, /*U+0168*/ /*LATIN CAPITAL LETTER U WITH TILDE*/
+  0x0169, /*U+0169*/ /**/
+  0x016B, /*U+016A*/ /*LATIN CAPITAL LETTER U WITH MACRON*/
+  0x016B, /*U+016B*/ /**/
+  0x016D, /*U+016C*/ /*LATIN CAPITAL LETTER U WITH BREVE*/
+  0x016D, /*U+016D*/ /**/
+  0x016F, /*U+016E*/ /*LATIN CAPITAL LETTER U WITH RING ABOVE*/
+  0x016F, /*U+016F*/ /**/
+  0x0171, /*U+0170*/ /*LATIN CAPITAL LETTER U WITH DOUBLE ACUTE*/
+  0x0171, /*U+0171*/ /**/
+  0x0173, /*U+0172*/ /*LATIN CAPITAL LETTER U WITH OGONEK*/
+  0x0173, /*U+0173*/ /**/
+  0x0175, /*U+0174*/ /*LATIN CAPITAL LETTER W WITH CIRCUMFLEX*/
+  0x0175, /*U+0175*/ /**/
+  0x0177, /*U+0176*/ /*LATIN CAPITAL LETTER Y WITH CIRCUMFLEX*/
+  0x0177, /*U+0177*/ /**/
+  0x00FF, /*U+0178*/ /*LATIN CAPITAL LETTER Y WITH DIAERESIS*/
+  0x017A, /*U+0179*/ /*LATIN CAPITAL LETTER Z WITH ACUTE*/
+  0x017A, /*U+017A*/ /**/
+  0x017C, /*U+017B*/ /*LATIN CAPITAL LETTER Z WITH DOT ABOVE*/
+  0x017C, /*U+017C*/ /**/
+  0x017E, /*U+017D*/ /*LATIN CAPITAL LETTER Z WITH CARON*/
+  0x017E, /*U+017E*/ /**/
+  0x017F, /*U+017F*/ /**/
+  0x0180, /*U+0180*/ /**/
+  0x0253, /*U+0181*/ /*LATIN CAPITAL LETTER B WITH HOOK*/
+  0x0183, /*U+0182*/ /*LATIN CAPITAL LETTER B WITH TOPBAR*/
+  0x0183, /*U+0183*/ /**/
+  0x0185, /*U+0184*/ /*LATIN CAPITAL LETTER TONE SIX*/
+  0x0185, /*U+0185*/ /**/
+  0x0254, /*U+0186*/ /*LATIN CAPITAL LETTER OPEN O*/
+  0x0188, /*U+0187*/ /*LATIN CAPITAL LETTER C WITH HOOK*/
+  0x0188, /*U+0188*/ /**/
+  0x0256, /*U+0189*/ /*LATIN CAPITAL LETTER AFRICAN D*/
+  0x0257, /*U+018A*/ /*LATIN CAPITAL LETTER D WITH HOOK*/
+  0x018C, /*U+018B*/ /*LATIN CAPITAL LETTER D WITH TOPBAR*/
+  0x018C, /*U+018C*/ /**/
+  0x018D, /*U+018D*/ /**/
+  0x01DD, /*U+018E*/ /*LATIN CAPITAL LETTER REVERSED E*/
+  0x0259, /*U+018F*/ /*LATIN CAPITAL LETTER SCHWA*/
+  0x025B, /*U+0190*/ /*LATIN CAPITAL LETTER OPEN E*/
+  0x0192, /*U+0191*/ /*LATIN CAPITAL LETTER F WITH HOOK*/
+  0x0192, /*U+0192*/ /**/
+  0x0260, /*U+0193*/ /*LATIN CAPITAL LETTER G WITH HOOK*/
+  0x0263, /*U+0194*/ /*LATIN CAPITAL LETTER GAMMA*/
+  0x0195, /*U+0195*/ /**/
+  0x0269, /*U+0196*/ /*LATIN CAPITAL LETTER IOTA*/
+  0x0268, /*U+0197*/ /*LATIN CAPITAL LETTER I WITH STROKE*/
+  0x0199, /*U+0198*/ /*LATIN CAPITAL LETTER K WITH HOOK*/
+  0x0199, /*U+0199*/ /**/
+  0x019A, /*U+019A*/ /**/
+  0x019B, /*U+019B*/ /**/
+  0x026F, /*U+019C*/ /*LATIN CAPITAL LETTER TURNED M*/
+  0x0272, /*U+019D*/ /*LATIN CAPITAL LETTER N WITH LEFT HOOK*/
+  0x019E, /*U+019E*/ /**/
+  0x0275, /*U+019F*/ /*LATIN CAPITAL LETTER O WITH MIDDLE TILDE*/
+  0x01A1, /*U+01A0*/ /*LATIN CAPITAL LETTER O WITH HORN*/
+  0x01A1, /*U+01A1*/ /**/
+  0x01A3, /*U+01A2*/ /*LATIN CAPITAL LETTER OI*/
+  0x01A3, /*U+01A3*/ /**/
+  0x01A5, /*U+01A4*/ /*LATIN CAPITAL LETTER P WITH HOOK*/
+  0x01A5, /*U+01A5*/ /**/
+  0x0280, /*U+01A6*/ /*LATIN LETTER YR*/
+  0x01A8, /*U+01A7*/ /*LATIN CAPITAL LETTER TONE TWO*/
+  0x01A8, /*U+01A8*/ /**/
+  0x0283, /*U+01A9*/ /*LATIN CAPITAL LETTER ESH*/
+  0x01AA, /*U+01AA*/ /**/
+  0x01AB, /*U+01AB*/ /**/
+  0x01AD, /*U+01AC*/ /*LATIN CAPITAL LETTER T WITH HOOK*/
+  0x01AD, /*U+01AD*/ /**/
+  0x0288, /*U+01AE*/ /*LATIN CAPITAL LETTER T WITH RETROFLEX HOOK*/
+  0x01B0, /*U+01AF*/ /*LATIN CAPITAL LETTER U WITH HORN*/
+  0x01B0, /*U+01B0*/ /**/
+  0x028A, /*U+01B1*/ /*LATIN CAPITAL LETTER UPSILON*/
+  0x028B, /*U+01B2*/ /*LATIN CAPITAL LETTER V WITH HOOK*/
+  0x01B4, /*U+01B3*/ /*LATIN CAPITAL LETTER Y WITH HOOK*/
+  0x01B4, /*U+01B4*/ /**/
+  0x01B6, /*U+01B5*/ /*LATIN CAPITAL LETTER Z WITH STROKE*/
+  0x01B6, /*U+01B6*/ /**/
+  0x0292, /*U+01B7*/ /*LATIN CAPITAL LETTER EZH*/
+  0x01B9, /*U+01B8*/ /*LATIN CAPITAL LETTER EZH REVERSED*/
+  0x01B9, /*U+01B9*/ /**/
+  0x01BA, /*U+01BA*/ /**/
+  0x01BB, /*U+01BB*/ /**/
+  0x01BD, /*U+01BC*/ /*LATIN CAPITAL LETTER TONE FIVE*/
+  0x01BD, /*U+01BD*/ /**/
+  0x01BE, /*U+01BE*/ /**/
+  0x01BF, /*U+01BF*/ /**/
+  0x01C0, /*U+01C0*/ /**/
+  0x01C1, /*U+01C1*/ /**/
+  0x01C2, /*U+01C2*/ /**/
+  0x01C3, /*U+01C3*/ /**/
+  0x01C6, /*U+01C4*/ /*LATIN CAPITAL LETTER DZ WITH CARON*/
+  0x01C6, /*U+01C5*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON*/
+  0x01C6, /*U+01C6*/ /**/
+  0x01C9, /*U+01C7*/ /*LATIN CAPITAL LETTER LJ*/
+  0x01C9, /*U+01C8*/ /*LATIN CAPITAL LETTER L WITH SMALL LETTER J*/
+  0x01C9, /*U+01C9*/ /**/
+  0x01CC, /*U+01CA*/ /*LATIN CAPITAL LETTER NJ*/
+  0x01CC, /*U+01CB*/ /*LATIN CAPITAL LETTER N WITH SMALL LETTER J*/
+  0x01CC, /*U+01CC*/ /**/
+  0x01CE, /*U+01CD*/ /*LATIN CAPITAL LETTER A WITH CARON*/
+  0x01CE, /*U+01CE*/ /**/
+  0x01D0, /*U+01CF*/ /*LATIN CAPITAL LETTER I WITH CARON*/
+  0x01D0, /*U+01D0*/ /**/
+  0x01D2, /*U+01D1*/ /*LATIN CAPITAL LETTER O WITH CARON*/
+  0x01D2, /*U+01D2*/ /**/
+  0x01D4, /*U+01D3*/ /*LATIN CAPITAL LETTER U WITH CARON*/
+  0x01D4, /*U+01D4*/ /**/
+  0x01D6, /*U+01D5*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON*/
+  0x01D6, /*U+01D6*/ /**/
+  0x01D8, /*U+01D7*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE*/
+  0x01D8, /*U+01D8*/ /**/
+  0x01DA, /*U+01D9*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON*/
+  0x01DA, /*U+01DA*/ /**/
+  0x01DC, /*U+01DB*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE*/
+  0x01DC, /*U+01DC*/ /**/
+  0x01DD, /*U+01DD*/ /**/
+  0x01DF, /*U+01DE*/ /*LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON*/
+  0x01DF, /*U+01DF*/ /**/
+  0x01E1, /*U+01E0*/ /*LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON*/
+  0x01E1, /*U+01E1*/ /**/
+  0x01E3, /*U+01E2*/ /*LATIN CAPITAL LETTER AE WITH MACRON*/
+  0x01E3, /*U+01E3*/ /**/
+  0x01E5, /*U+01E4*/ /*LATIN CAPITAL LETTER G WITH STROKE*/
+  0x01E5, /*U+01E5*/ /**/
+  0x01E7, /*U+01E6*/ /*LATIN CAPITAL LETTER G WITH CARON*/
+  0x01E7, /*U+01E7*/ /**/
+  0x01E9, /*U+01E8*/ /*LATIN CAPITAL LETTER K WITH CARON*/
+  0x01E9, /*U+01E9*/ /**/
+  0x01EB, /*U+01EA*/ /*LATIN CAPITAL LETTER O WITH OGONEK*/
+  0x01EB, /*U+01EB*/ /**/
+  0x01ED, /*U+01EC*/ /*LATIN CAPITAL LETTER O WITH OGONEK AND MACRON*/
+  0x01ED, /*U+01ED*/ /**/
+  0x01EF, /*U+01EE*/ /*LATIN CAPITAL LETTER EZH WITH CARON*/
+  0x01EF, /*U+01EF*/ /**/
+  0x01F0, /*U+01F0*/ /**/
+  0x01F3, /*U+01F1*/ /*LATIN CAPITAL LETTER DZ*/
+  0x01F3, /*U+01F2*/ /*LATIN CAPITAL LETTER D WITH SMALL LETTER Z*/
+  0x01F3, /*U+01F3*/ /**/
+  0x01F5, /*U+01F4*/ /*LATIN CAPITAL LETTER G WITH ACUTE*/
+  0x01F5, /*U+01F5*/ /**/
+  0x0195, /*U+01F6*/ /*LATIN CAPITAL LETTER HWAIR*/
+  0x01BF, /*U+01F7*/ /*LATIN CAPITAL LETTER WYNN*/
+  0x01F9, /*U+01F8*/ /*LATIN CAPITAL LETTER N WITH GRAVE*/
+  0x01F9, /*U+01F9*/ /**/
+  0x01FB, /*U+01FA*/ /*LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE*/
+  0x01FB, /*U+01FB*/ /**/
+  0x01FD, /*U+01FC*/ /*LATIN CAPITAL LETTER AE WITH ACUTE*/
+  0x01FD, /*U+01FD*/ /**/
+  0x01FF, /*U+01FE*/ /*LATIN CAPITAL LETTER O WITH STROKE AND ACUTE*/
+  0x01FF, /*U+01FF*/ /**/
+  0x0201, /*U+0200*/ /*LATIN CAPITAL LETTER A WITH DOUBLE GRAVE*/
+  0x0201, /*U+0201*/ /**/
+  0x0203, /*U+0202*/ /*LATIN CAPITAL LETTER A WITH INVERTED BREVE*/
+  0x0203, /*U+0203*/ /**/
+  0x0205, /*U+0204*/ /*LATIN CAPITAL LETTER E WITH DOUBLE GRAVE*/
+  0x0205, /*U+0205*/ /**/
+  0x0207, /*U+0206*/ /*LATIN CAPITAL LETTER E WITH INVERTED BREVE*/
+  0x0207, /*U+0207*/ /**/
+  0x0209, /*U+0208*/ /*LATIN CAPITAL LETTER I WITH DOUBLE GRAVE*/
+  0x0209, /*U+0209*/ /**/
+  0x020B, /*U+020A*/ /*LATIN CAPITAL LETTER I WITH INVERTED BREVE*/
+  0x020B, /*U+020B*/ /**/
+  0x020D, /*U+020C*/ /*LATIN CAPITAL LETTER O WITH DOUBLE GRAVE*/
+  0x020D, /*U+020D*/ /**/
+  0x020F, /*U+020E*/ /*LATIN CAPITAL LETTER O WITH INVERTED BREVE*/
+  0x020F, /*U+020F*/ /**/
+  0x0211, /*U+0210*/ /*LATIN CAPITAL LETTER R WITH DOUBLE GRAVE*/
+  0x0211, /*U+0211*/ /**/
+  0x0213, /*U+0212*/ /*LATIN CAPITAL LETTER R WITH INVERTED BREVE*/
+  0x0213, /*U+0213*/ /**/
+  0x0215, /*U+0214*/ /*LATIN CAPITAL LETTER U WITH DOUBLE GRAVE*/
+  0x0215, /*U+0215*/ /**/
+  0x0217, /*U+0216*/ /*LATIN CAPITAL LETTER U WITH INVERTED BREVE*/
+  0x0217, /*U+0217*/ /**/
+  0x0219, /*U+0218*/ /*LATIN CAPITAL LETTER S WITH COMMA BELOW*/
+  0x0219, /*U+0219*/ /**/
+  0x021B, /*U+021A*/ /*LATIN CAPITAL LETTER T WITH COMMA BELOW*/
+  0x021B, /*U+021B*/ /**/
+  0x021D, /*U+021C*/ /*LATIN CAPITAL LETTER YOGH*/
+  0x021D, /*U+021D*/ /**/
+  0x021F, /*U+021E*/ /*LATIN CAPITAL LETTER H WITH CARON*/
+  0x021F, /*U+021F*/ /**/
+  0x019E, /*U+0220*/ /*LATIN CAPITAL LETTER N WITH LONG RIGHT LEG*/
+  0x0221, /*U+0221*/ /**/
+  0x0223, /*U+0222*/ /*LATIN CAPITAL LETTER OU*/
+  0x0223, /*U+0223*/ /**/
+  0x0225, /*U+0224*/ /*LATIN CAPITAL LETTER Z WITH HOOK*/
+  0x0225, /*U+0225*/ /**/
+  0x0227, /*U+0226*/ /*LATIN CAPITAL LETTER A WITH DOT ABOVE*/
+  0x0227, /*U+0227*/ /**/
+  0x0229, /*U+0228*/ /*LATIN CAPITAL LETTER E WITH CEDILLA*/
+  0x0229, /*U+0229*/ /**/
+  0x022B, /*U+022A*/ /*LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON*/
+  0x022B, /*U+022B*/ /**/
+  0x022D, /*U+022C*/ /*LATIN CAPITAL LETTER O WITH TILDE AND MACRON*/
+  0x022D, /*U+022D*/ /**/
+  0x022F, /*U+022E*/ /*LATIN CAPITAL LETTER O WITH DOT ABOVE*/
+  0x022F, /*U+022F*/ /**/
+  0x0231, /*U+0230*/ /*LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON*/
+  0x0231, /*U+0231*/ /**/
+  0x0233, /*U+0232*/ /*LATIN CAPITAL LETTER Y WITH MACRON*/
+  0x0233, /*U+0233*/ /**/
+  0x0234, /*U+0234*/ /**/
+  0x0235, /*U+0235*/ /**/
+  0x0236, /*U+0236*/ /**/
+  0x0237, /*U+0237*/ /**/
+  0x0238, /*U+0238*/ /**/
+  0x0239, /*U+0239*/ /**/
+  0x2C65, /*U+023A*/ /*LATIN CAPITAL LETTER A WITH STROKE*/
+  0x023C, /*U+023B*/ /*LATIN CAPITAL LETTER C WITH STROKE*/
+  0x023C, /*U+023C*/ /**/
+  0x019A, /*U+023D*/ /*LATIN CAPITAL LETTER L WITH BAR*/
+  0x2C66, /*U+023E*/ /*LATIN CAPITAL LETTER T WITH DIAGONAL STROKE*/
+  0x023F, /*U+023F*/ /**/
+  0x0240, /*U+0240*/ /**/
+  0x0242, /*U+0241*/ /*LATIN CAPITAL LETTER GLOTTAL STOP*/
+  0x0242, /*U+0242*/ /**/
+  0x0180, /*U+0243*/ /*LATIN CAPITAL LETTER B WITH STROKE*/
+  0x0289, /*U+0244*/ /*LATIN CAPITAL LETTER U BAR*/
+  0x028C, /*U+0245*/ /*LATIN CAPITAL LETTER TURNED V*/
+  0x0247, /*U+0246*/ /*LATIN CAPITAL LETTER E WITH STROKE*/
+  0x0247, /*U+0247*/ /**/
+  0x0249, /*U+0248*/ /*LATIN CAPITAL LETTER J WITH STROKE*/
+  0x0249, /*U+0249*/ /**/
+  0x024B, /*U+024A*/ /*LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL*/
+  0x024B, /*U+024B*/ /**/
+  0x024D, /*U+024C*/ /*LATIN CAPITAL LETTER R WITH STROKE*/
+  0x024D, /*U+024D*/ /**/
+  0x024F, /*U+024E*/ /*LATIN CAPITAL LETTER Y WITH STROKE*/
+  0x024F, /*U+024F*/ /**/
+  0x0250, /*U+0250*/ /**/
+  0x0251, /*U+0251*/ /**/
+  0x0252, /*U+0252*/ /**/
+  0x0253, /*U+0253*/ /**/
+  0x0254, /*U+0254*/ /**/
+  0x0255, /*U+0255*/ /**/
+  0x0256, /*U+0256*/ /**/
+  0x0257, /*U+0257*/ /**/
+  0x0258, /*U+0258*/ /**/
+  0x0259, /*U+0259*/ /**/
+  0x025A, /*U+025A*/ /**/
+  0x025B, /*U+025B*/ /**/
+  0x025C, /*U+025C*/ /**/
+  0x025D, /*U+025D*/ /**/
+  0x025E, /*U+025E*/ /**/
+  0x025F, /*U+025F*/ /**/
+  0x0260, /*U+0260*/ /**/
+  0x0261, /*U+0261*/ /**/
+  0x0262, /*U+0262*/ /**/
+  0x0263, /*U+0263*/ /**/
+  0x0264, /*U+0264*/ /**/
+  0x0265, /*U+0265*/ /**/
+  0x0266, /*U+0266*/ /**/
+  0x0267, /*U+0267*/ /**/
+  0x0268, /*U+0268*/ /**/
+  0x0269, /*U+0269*/ /**/
+  0x026A, /*U+026A*/ /**/
+  0x026B, /*U+026B*/ /**/
+  0x026C, /*U+026C*/ /**/
+  0x026D, /*U+026D*/ /**/
+  0x026E, /*U+026E*/ /**/
+  0x026F, /*U+026F*/ /**/
+  0x0270, /*U+0270*/ /**/
+  0x0271, /*U+0271*/ /**/
+  0x0272, /*U+0272*/ /**/
+  0x0273, /*U+0273*/ /**/
+  0x0274, /*U+0274*/ /**/
+  0x0275, /*U+0275*/ /**/
+  0x0276, /*U+0276*/ /**/
+  0x0277, /*U+0277*/ /**/
+  0x0278, /*U+0278*/ /**/
+  0x0279, /*U+0279*/ /**/
+  0x027A, /*U+027A*/ /**/
+  0x027B, /*U+027B*/ /**/
+  0x027C, /*U+027C*/ /**/
+  0x027D, /*U+027D*/ /**/
+  0x027E, /*U+027E*/ /**/
+  0x027F, /*U+027F*/ /**/
+};
+
+static const u_int16_t lower_table_3[576] = {
+  0x0340, /*U+0340*/ /**/
+  0x0341, /*U+0341*/ /**/
+  0x0342, /*U+0342*/ /**/
+  0x0343, /*U+0343*/ /**/
+  0x0344, /*U+0344*/ /**/
+  0x0345, /*U+0345*/ /**/
+  0x0346, /*U+0346*/ /**/
+  0x0347, /*U+0347*/ /**/
+  0x0348, /*U+0348*/ /**/
+  0x0349, /*U+0349*/ /**/
+  0x034A, /*U+034A*/ /**/
+  0x034B, /*U+034B*/ /**/
+  0x034C, /*U+034C*/ /**/
+  0x034D, /*U+034D*/ /**/
+  0x034E, /*U+034E*/ /**/
+  0x034F, /*U+034F*/ /**/
+  0x0350, /*U+0350*/ /**/
+  0x0351, /*U+0351*/ /**/
+  0x0352, /*U+0352*/ /**/
+  0x0353, /*U+0353*/ /**/
+  0x0354, /*U+0354*/ /**/
+  0x0355, /*U+0355*/ /**/
+  0x0356, /*U+0356*/ /**/
+  0x0357, /*U+0357*/ /**/
+  0x0358, /*U+0358*/ /**/
+  0x0359, /*U+0359*/ /**/
+  0x035A, /*U+035A*/ /**/
+  0x035B, /*U+035B*/ /**/
+  0x035C, /*U+035C*/ /**/
+  0x035D, /*U+035D*/ /**/
+  0x035E, /*U+035E*/ /**/
+  0x035F, /*U+035F*/ /**/
+  0x0360, /*U+0360*/ /**/
+  0x0361, /*U+0361*/ /**/
+  0x0362, /*U+0362*/ /**/
+  0x0363, /*U+0363*/ /**/
+  0x0364, /*U+0364*/ /**/
+  0x0365, /*U+0365*/ /**/
+  0x0366, /*U+0366*/ /**/
+  0x0367, /*U+0367*/ /**/
+  0x0368, /*U+0368*/ /**/
+  0x0369, /*U+0369*/ /**/
+  0x036A, /*U+036A*/ /**/
+  0x036B, /*U+036B*/ /**/
+  0x036C, /*U+036C*/ /**/
+  0x036D, /*U+036D*/ /**/
+  0x036E, /*U+036E*/ /**/
+  0x036F, /*U+036F*/ /**/
+  0x0371, /*U+0370*/ /*GREEK CAPITAL LETTER HETA*/
+  0x0371, /*U+0371*/ /**/
+  0x0373, /*U+0372*/ /*GREEK CAPITAL LETTER ARCHAIC SAMPI*/
+  0x0373, /*U+0373*/ /**/
+  0x0374, /*U+0374*/ /**/
+  0x0375, /*U+0375*/ /**/
+  0x0377, /*U+0376*/ /*GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA*/
+  0x0377, /*U+0377*/ /**/
+  0x0378, /*U+0378*/ /**/
+  0x0379, /*U+0379*/ /**/
+  0x037A, /*U+037A*/ /**/
+  0x037B, /*U+037B*/ /**/
+  0x037C, /*U+037C*/ /**/
+  0x037D, /*U+037D*/ /**/
+  0x037E, /*U+037E*/ /**/
+  0x037F, /*U+037F*/ /**/
+  0x0380, /*U+0380*/ /**/
+  0x0381, /*U+0381*/ /**/
+  0x0382, /*U+0382*/ /**/
+  0x0383, /*U+0383*/ /**/
+  0x0384, /*U+0384*/ /**/
+  0x0385, /*U+0385*/ /**/
+  0x03AC, /*U+0386*/ /*GREEK CAPITAL LETTER ALPHA WITH TONOS*/
+  0x0387, /*U+0387*/ /**/
+  0x03AD, /*U+0388*/ /*GREEK CAPITAL LETTER EPSILON WITH TONOS*/
+  0x03AE, /*U+0389*/ /*GREEK CAPITAL LETTER ETA WITH TONOS*/
+  0x03AF, /*U+038A*/ /*GREEK CAPITAL LETTER IOTA WITH TONOS*/
+  0x038B, /*U+038B*/ /**/
+  0x03CC, /*U+038C*/ /*GREEK CAPITAL LETTER OMICRON WITH TONOS*/
+  0x038D, /*U+038D*/ /**/
+  0x03CD, /*U+038E*/ /*GREEK CAPITAL LETTER UPSILON WITH TONOS*/
+  0x03CE, /*U+038F*/ /*GREEK CAPITAL LETTER OMEGA WITH TONOS*/
+  0x0390, /*U+0390*/ /**/
+  0x03B1, /*U+0391*/ /*GREEK CAPITAL LETTER ALPHA*/
+  0x03B2, /*U+0392*/ /*GREEK CAPITAL LETTER BETA*/
+  0x03B3, /*U+0393*/ /*GREEK CAPITAL LETTER GAMMA*/
+  0x03B4, /*U+0394*/ /*GREEK CAPITAL LETTER DELTA*/
+  0x03B5, /*U+0395*/ /*GREEK CAPITAL LETTER EPSILON*/
+  0x03B6, /*U+0396*/ /*GREEK CAPITAL LETTER ZETA*/
+  0x03B7, /*U+0397*/ /*GREEK CAPITAL LETTER ETA*/
+  0x03B8, /*U+0398*/ /*GREEK CAPITAL LETTER THETA*/
+  0x03B9, /*U+0399*/ /*GREEK CAPITAL LETTER IOTA*/
+  0x03BA, /*U+039A*/ /*GREEK CAPITAL LETTER KAPPA*/
+  0x03BB, /*U+039B*/ /*GREEK CAPITAL LETTER LAMDA*/
+  0x03BC, /*U+039C*/ /*GREEK CAPITAL LETTER MU*/
+  0x03BD, /*U+039D*/ /*GREEK CAPITAL LETTER NU*/
+  0x03BE, /*U+039E*/ /*GREEK CAPITAL LETTER XI*/
+  0x03BF, /*U+039F*/ /*GREEK CAPITAL LETTER OMICRON*/
+  0x03C0, /*U+03A0*/ /*GREEK CAPITAL LETTER PI*/
+  0x03C1, /*U+03A1*/ /*GREEK CAPITAL LETTER RHO*/
+  0x03A2, /*U+03A2*/ /**/
+  0x03C3, /*U+03A3*/ /*GREEK CAPITAL LETTER SIGMA*/
+  0x03C4, /*U+03A4*/ /*GREEK CAPITAL LETTER TAU*/
+  0x03C5, /*U+03A5*/ /*GREEK CAPITAL LETTER UPSILON*/
+  0x03C6, /*U+03A6*/ /*GREEK CAPITAL LETTER PHI*/
+  0x03C7, /*U+03A7*/ /*GREEK CAPITAL LETTER CHI*/
+  0x03C8, /*U+03A8*/ /*GREEK CAPITAL LETTER PSI*/
+  0x03C9, /*U+03A9*/ /*GREEK CAPITAL LETTER OMEGA*/
+  0x03CA, /*U+03AA*/ /*GREEK CAPITAL LETTER IOTA WITH DIALYTIKA*/
+  0x03CB, /*U+03AB*/ /*GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA*/
+  0x03AC, /*U+03AC*/ /**/
+  0x03AD, /*U+03AD*/ /**/
+  0x03AE, /*U+03AE*/ /**/
+  0x03AF, /*U+03AF*/ /**/
+  0x03B0, /*U+03B0*/ /**/
+  0x03B1, /*U+03B1*/ /**/
+  0x03B2, /*U+03B2*/ /**/
+  0x03B3, /*U+03B3*/ /**/
+  0x03B4, /*U+03B4*/ /**/
+  0x03B5, /*U+03B5*/ /**/
+  0x03B6, /*U+03B6*/ /**/
+  0x03B7, /*U+03B7*/ /**/
+  0x03B8, /*U+03B8*/ /**/
+  0x03B9, /*U+03B9*/ /**/
+  0x03BA, /*U+03BA*/ /**/
+  0x03BB, /*U+03BB*/ /**/
+  0x03BC, /*U+03BC*/ /**/
+  0x03BD, /*U+03BD*/ /**/
+  0x03BE, /*U+03BE*/ /**/
+  0x03BF, /*U+03BF*/ /**/
+  0x03C0, /*U+03C0*/ /**/
+  0x03C1, /*U+03C1*/ /**/
+  0x03C2, /*U+03C2*/ /**/
+  0x03C3, /*U+03C3*/ /**/
+  0x03C4, /*U+03C4*/ /**/
+  0x03C5, /*U+03C5*/ /**/
+  0x03C6, /*U+03C6*/ /**/
+  0x03C7, /*U+03C7*/ /**/
+  0x03C8, /*U+03C8*/ /**/
+  0x03C9, /*U+03C9*/ /**/
+  0x03CA, /*U+03CA*/ /**/
+  0x03CB, /*U+03CB*/ /**/
+  0x03CC, /*U+03CC*/ /**/
+  0x03CD, /*U+03CD*/ /**/
+  0x03CE, /*U+03CE*/ /**/
+  0x03D7, /*U+03CF*/ /*GREEK CAPITAL KAI SYMBOL*/
+  0x03D0, /*U+03D0*/ /**/
+  0x03D1, /*U+03D1*/ /**/
+  0x03D2, /*U+03D2*/ /**/
+  0x03D3, /*U+03D3*/ /**/
+  0x03D4, /*U+03D4*/ /**/
+  0x03D5, /*U+03D5*/ /**/
+  0x03D6, /*U+03D6*/ /**/
+  0x03D7, /*U+03D7*/ /**/
+  0x03D9, /*U+03D8*/ /*GREEK LETTER ARCHAIC KOPPA*/
+  0x03D9, /*U+03D9*/ /**/
+  0x03DB, /*U+03DA*/ /*GREEK LETTER STIGMA*/
+  0x03DB, /*U+03DB*/ /**/
+  0x03DD, /*U+03DC*/ /*GREEK LETTER DIGAMMA*/
+  0x03DD, /*U+03DD*/ /**/
+  0x03DF, /*U+03DE*/ /*GREEK LETTER KOPPA*/
+  0x03DF, /*U+03DF*/ /**/
+  0x03E1, /*U+03E0*/ /*GREEK LETTER SAMPI*/
+  0x03E1, /*U+03E1*/ /**/
+  0x03E3, /*U+03E2*/ /*COPTIC CAPITAL LETTER SHEI*/
+  0x03E3, /*U+03E3*/ /**/
+  0x03E5, /*U+03E4*/ /*COPTIC CAPITAL LETTER FEI*/
+  0x03E5, /*U+03E5*/ /**/
+  0x03E7, /*U+03E6*/ /*COPTIC CAPITAL LETTER KHEI*/
+  0x03E7, /*U+03E7*/ /**/
+  0x03E9, /*U+03E8*/ /*COPTIC CAPITAL LETTER HORI*/
+  0x03E9, /*U+03E9*/ /**/
+  0x03EB, /*U+03EA*/ /*COPTIC CAPITAL LETTER GANGIA*/
+  0x03EB, /*U+03EB*/ /**/
+  0x03ED, /*U+03EC*/ /*COPTIC CAPITAL LETTER SHIMA*/
+  0x03ED, /*U+03ED*/ /**/
+  0x03EF, /*U+03EE*/ /*COPTIC CAPITAL LETTER DEI*/
+  0x03EF, /*U+03EF*/ /**/
+  0x03F0, /*U+03F0*/ /**/
+  0x03F1, /*U+03F1*/ /**/
+  0x03F2, /*U+03F2*/ /**/
+  0x03F3, /*U+03F3*/ /**/
+  0x03B8, /*U+03F4*/ /*GREEK CAPITAL THETA SYMBOL*/
+  0x03F5, /*U+03F5*/ /**/
+  0x03F6, /*U+03F6*/ /**/
+  0x03F8, /*U+03F7*/ /*GREEK CAPITAL LETTER SHO*/
+  0x03F8, /*U+03F8*/ /**/
+  0x03F2, /*U+03F9*/ /*GREEK CAPITAL LUNATE SIGMA SYMBOL*/
+  0x03FB, /*U+03FA*/ /*GREEK CAPITAL LETTER SAN*/
+  0x03FB, /*U+03FB*/ /**/
+  0x03FC, /*U+03FC*/ /**/
+  0x037B, /*U+03FD*/ /*GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL*/
+  0x037C, /*U+03FE*/ /*GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL*/
+  0x037D, /*U+03FF*/ /*GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL*/
+  0x0450, /*U+0400*/ /*CYRILLIC CAPITAL LETTER IE WITH GRAVE*/
+  0x0451, /*U+0401*/ /*CYRILLIC CAPITAL LETTER IO*/
+  0x0452, /*U+0402*/ /*CYRILLIC CAPITAL LETTER DJE*/
+  0x0453, /*U+0403*/ /*CYRILLIC CAPITAL LETTER GJE*/
+  0x0454, /*U+0404*/ /*CYRILLIC CAPITAL LETTER UKRAINIAN IE*/
+  0x0455, /*U+0405*/ /*CYRILLIC CAPITAL LETTER DZE*/
+  0x0456, /*U+0406*/ /*CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I*/
+  0x0457, /*U+0407*/ /*CYRILLIC CAPITAL LETTER YI*/
+  0x0458, /*U+0408*/ /*CYRILLIC CAPITAL LETTER JE*/
+  0x0459, /*U+0409*/ /*CYRILLIC CAPITAL LETTER LJE*/
+  0x045A, /*U+040A*/ /*CYRILLIC CAPITAL LETTER NJE*/
+  0x045B, /*U+040B*/ /*CYRILLIC CAPITAL LETTER TSHE*/
+  0x045C, /*U+040C*/ /*CYRILLIC CAPITAL LETTER KJE*/
+  0x045D, /*U+040D*/ /*CYRILLIC CAPITAL LETTER I WITH GRAVE*/
+  0x045E, /*U+040E*/ /*CYRILLIC CAPITAL LETTER SHORT U*/
+  0x045F, /*U+040F*/ /*CYRILLIC CAPITAL LETTER DZHE*/
+  0x0430, /*U+0410*/ /*CYRILLIC CAPITAL LETTER A*/
+  0x0431, /*U+0411*/ /*CYRILLIC CAPITAL LETTER BE*/
+  0x0432, /*U+0412*/ /*CYRILLIC CAPITAL LETTER VE*/
+  0x0433, /*U+0413*/ /*CYRILLIC CAPITAL LETTER GHE*/
+  0x0434, /*U+0414*/ /*CYRILLIC CAPITAL LETTER DE*/
+  0x0435, /*U+0415*/ /*CYRILLIC CAPITAL LETTER IE*/
+  0x0436, /*U+0416*/ /*CYRILLIC CAPITAL LETTER ZHE*/
+  0x0437, /*U+0417*/ /*CYRILLIC CAPITAL LETTER ZE*/
+  0x0438, /*U+0418*/ /*CYRILLIC CAPITAL LETTER I*/
+  0x0439, /*U+0419*/ /*CYRILLIC CAPITAL LETTER SHORT I*/
+  0x043A, /*U+041A*/ /*CYRILLIC CAPITAL LETTER KA*/
+  0x043B, /*U+041B*/ /*CYRILLIC CAPITAL LETTER EL*/
+  0x043C, /*U+041C*/ /*CYRILLIC CAPITAL LETTER EM*/
+  0x043D, /*U+041D*/ /*CYRILLIC CAPITAL LETTER EN*/
+  0x043E, /*U+041E*/ /*CYRILLIC CAPITAL LETTER O*/
+  0x043F, /*U+041F*/ /*CYRILLIC CAPITAL LETTER PE*/
+  0x0440, /*U+0420*/ /*CYRILLIC CAPITAL LETTER ER*/
+  0x0441, /*U+0421*/ /*CYRILLIC CAPITAL LETTER ES*/
+  0x0442, /*U+0422*/ /*CYRILLIC CAPITAL LETTER TE*/
+  0x0443, /*U+0423*/ /*CYRILLIC CAPITAL LETTER U*/
+  0x0444, /*U+0424*/ /*CYRILLIC CAPITAL LETTER EF*/
+  0x0445, /*U+0425*/ /*CYRILLIC CAPITAL LETTER HA*/
+  0x0446, /*U+0426*/ /*CYRILLIC CAPITAL LETTER TSE*/
+  0x0447, /*U+0427*/ /*CYRILLIC CAPITAL LETTER CHE*/
+  0x0448, /*U+0428*/ /*CYRILLIC CAPITAL LETTER SHA*/
+  0x0449, /*U+0429*/ /*CYRILLIC CAPITAL LETTER SHCHA*/
+  0x044A, /*U+042A*/ /*CYRILLIC CAPITAL LETTER HARD SIGN*/
+  0x044B, /*U+042B*/ /*CYRILLIC CAPITAL LETTER YERU*/
+  0x044C, /*U+042C*/ /*CYRILLIC CAPITAL LETTER SOFT SIGN*/
+  0x044D, /*U+042D*/ /*CYRILLIC CAPITAL LETTER E*/
+  0x044E, /*U+042E*/ /*CYRILLIC CAPITAL LETTER YU*/
+  0x044F, /*U+042F*/ /*CYRILLIC CAPITAL LETTER YA*/
+  0x0430, /*U+0430*/ /**/
+  0x0431, /*U+0431*/ /**/
+  0x0432, /*U+0432*/ /**/
+  0x0433, /*U+0433*/ /**/
+  0x0434, /*U+0434*/ /**/
+  0x0435, /*U+0435*/ /**/
+  0x0436, /*U+0436*/ /**/
+  0x0437, /*U+0437*/ /**/
+  0x0438, /*U+0438*/ /**/
+  0x0439, /*U+0439*/ /**/
+  0x043A, /*U+043A*/ /**/
+  0x043B, /*U+043B*/ /**/
+  0x043C, /*U+043C*/ /**/
+  0x043D, /*U+043D*/ /**/
+  0x043E, /*U+043E*/ /**/
+  0x043F, /*U+043F*/ /**/
+  0x0440, /*U+0440*/ /**/
+  0x0441, /*U+0441*/ /**/
+  0x0442, /*U+0442*/ /**/
+  0x0443, /*U+0443*/ /**/
+  0x0444, /*U+0444*/ /**/
+  0x0445, /*U+0445*/ /**/
+  0x0446, /*U+0446*/ /**/
+  0x0447, /*U+0447*/ /**/
+  0x0448, /*U+0448*/ /**/
+  0x0449, /*U+0449*/ /**/
+  0x044A, /*U+044A*/ /**/
+  0x044B, /*U+044B*/ /**/
+  0x044C, /*U+044C*/ /**/
+  0x044D, /*U+044D*/ /**/
+  0x044E, /*U+044E*/ /**/
+  0x044F, /*U+044F*/ /**/
+  0x0450, /*U+0450*/ /**/
+  0x0451, /*U+0451*/ /**/
+  0x0452, /*U+0452*/ /**/
+  0x0453, /*U+0453*/ /**/
+  0x0454, /*U+0454*/ /**/
+  0x0455, /*U+0455*/ /**/
+  0x0456, /*U+0456*/ /**/
+  0x0457, /*U+0457*/ /**/
+  0x0458, /*U+0458*/ /**/
+  0x0459, /*U+0459*/ /**/
+  0x045A, /*U+045A*/ /**/
+  0x045B, /*U+045B*/ /**/
+  0x045C, /*U+045C*/ /**/
+  0x045D, /*U+045D*/ /**/
+  0x045E, /*U+045E*/ /**/
+  0x045F, /*U+045F*/ /**/
+  0x0461, /*U+0460*/ /*CYRILLIC CAPITAL LETTER OMEGA*/
+  0x0461, /*U+0461*/ /**/
+  0x0463, /*U+0462*/ /*CYRILLIC CAPITAL LETTER YAT*/
+  0x0463, /*U+0463*/ /**/
+  0x0465, /*U+0464*/ /*CYRILLIC CAPITAL LETTER IOTIFIED E*/
+  0x0465, /*U+0465*/ /**/
+  0x0467, /*U+0466*/ /*CYRILLIC CAPITAL LETTER LITTLE YUS*/
+  0x0467, /*U+0467*/ /**/
+  0x0469, /*U+0468*/ /*CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS*/
+  0x0469, /*U+0469*/ /**/
+  0x046B, /*U+046A*/ /*CYRILLIC CAPITAL LETTER BIG YUS*/
+  0x046B, /*U+046B*/ /**/
+  0x046D, /*U+046C*/ /*CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS*/
+  0x046D, /*U+046D*/ /**/
+  0x046F, /*U+046E*/ /*CYRILLIC CAPITAL LETTER KSI*/
+  0x046F, /*U+046F*/ /**/
+  0x0471, /*U+0470*/ /*CYRILLIC CAPITAL LETTER PSI*/
+  0x0471, /*U+0471*/ /**/
+  0x0473, /*U+0472*/ /*CYRILLIC CAPITAL LETTER FITA*/
+  0x0473, /*U+0473*/ /**/
+  0x0475, /*U+0474*/ /*CYRILLIC CAPITAL LETTER IZHITSA*/
+  0x0475, /*U+0475*/ /**/
+  0x0477, /*U+0476*/ /*CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT*/
+  0x0477, /*U+0477*/ /**/
+  0x0479, /*U+0478*/ /*CYRILLIC CAPITAL LETTER UK*/
+  0x0479, /*U+0479*/ /**/
+  0x047B, /*U+047A*/ /*CYRILLIC CAPITAL LETTER ROUND OMEGA*/
+  0x047B, /*U+047B*/ /**/
+  0x047D, /*U+047C*/ /*CYRILLIC CAPITAL LETTER OMEGA WITH TITLO*/
+  0x047D, /*U+047D*/ /**/
+  0x047F, /*U+047E*/ /*CYRILLIC CAPITAL LETTER OT*/
+  0x047F, /*U+047F*/ /**/
+  0x0481, /*U+0480*/ /*CYRILLIC CAPITAL LETTER KOPPA*/
+  0x0481, /*U+0481*/ /**/
+  0x0482, /*U+0482*/ /**/
+  0x0483, /*U+0483*/ /**/
+  0x0484, /*U+0484*/ /**/
+  0x0485, /*U+0485*/ /**/
+  0x0486, /*U+0486*/ /**/
+  0x0487, /*U+0487*/ /**/
+  0x0488, /*U+0488*/ /**/
+  0x0489, /*U+0489*/ /**/
+  0x048B, /*U+048A*/ /*CYRILLIC CAPITAL LETTER SHORT I WITH TAIL*/
+  0x048B, /*U+048B*/ /**/
+  0x048D, /*U+048C*/ /*CYRILLIC CAPITAL LETTER SEMISOFT SIGN*/
+  0x048D, /*U+048D*/ /**/
+  0x048F, /*U+048E*/ /*CYRILLIC CAPITAL LETTER ER WITH TICK*/
+  0x048F, /*U+048F*/ /**/
+  0x0491, /*U+0490*/ /*CYRILLIC CAPITAL LETTER GHE WITH UPTURN*/
+  0x0491, /*U+0491*/ /**/
+  0x0493, /*U+0492*/ /*CYRILLIC CAPITAL LETTER GHE WITH STROKE*/
+  0x0493, /*U+0493*/ /**/
+  0x0495, /*U+0494*/ /*CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK*/
+  0x0495, /*U+0495*/ /**/
+  0x0497, /*U+0496*/ /*CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER*/
+  0x0497, /*U+0497*/ /**/
+  0x0499, /*U+0498*/ /*CYRILLIC CAPITAL LETTER ZE WITH DESCENDER*/
+  0x0499, /*U+0499*/ /**/
+  0x049B, /*U+049A*/ /*CYRILLIC CAPITAL LETTER KA WITH DESCENDER*/
+  0x049B, /*U+049B*/ /**/
+  0x049D, /*U+049C*/ /*CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE*/
+  0x049D, /*U+049D*/ /**/
+  0x049F, /*U+049E*/ /*CYRILLIC CAPITAL LETTER KA WITH STROKE*/
+  0x049F, /*U+049F*/ /**/
+  0x04A1, /*U+04A0*/ /*CYRILLIC CAPITAL LETTER BASHKIR KA*/
+  0x04A1, /*U+04A1*/ /**/
+  0x04A3, /*U+04A2*/ /*CYRILLIC CAPITAL LETTER EN WITH DESCENDER*/
+  0x04A3, /*U+04A3*/ /**/
+  0x04A5, /*U+04A4*/ /*CYRILLIC CAPITAL LIGATURE EN GHE*/
+  0x04A5, /*U+04A5*/ /**/
+  0x04A7, /*U+04A6*/ /*CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK*/
+  0x04A7, /*U+04A7*/ /**/
+  0x04A9, /*U+04A8*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN HA*/
+  0x04A9, /*U+04A9*/ /**/
+  0x04AB, /*U+04AA*/ /*CYRILLIC CAPITAL LETTER ES WITH DESCENDER*/
+  0x04AB, /*U+04AB*/ /**/
+  0x04AD, /*U+04AC*/ /*CYRILLIC CAPITAL LETTER TE WITH DESCENDER*/
+  0x04AD, /*U+04AD*/ /**/
+  0x04AF, /*U+04AE*/ /*CYRILLIC CAPITAL LETTER STRAIGHT U*/
+  0x04AF, /*U+04AF*/ /**/
+  0x04B1, /*U+04B0*/ /*CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE*/
+  0x04B1, /*U+04B1*/ /**/
+  0x04B3, /*U+04B2*/ /*CYRILLIC CAPITAL LETTER HA WITH DESCENDER*/
+  0x04B3, /*U+04B3*/ /**/
+  0x04B5, /*U+04B4*/ /*CYRILLIC CAPITAL LIGATURE TE TSE*/
+  0x04B5, /*U+04B5*/ /**/
+  0x04B7, /*U+04B6*/ /*CYRILLIC CAPITAL LETTER CHE WITH DESCENDER*/
+  0x04B7, /*U+04B7*/ /**/
+  0x04B9, /*U+04B8*/ /*CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE*/
+  0x04B9, /*U+04B9*/ /**/
+  0x04BB, /*U+04BA*/ /*CYRILLIC CAPITAL LETTER SHHA*/
+  0x04BB, /*U+04BB*/ /**/
+  0x04BD, /*U+04BC*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN CHE*/
+  0x04BD, /*U+04BD*/ /**/
+  0x04BF, /*U+04BE*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER*/
+  0x04BF, /*U+04BF*/ /**/
+  0x04CF, /*U+04C0*/ /*CYRILLIC LETTER PALOCHKA*/
+  0x04C2, /*U+04C1*/ /*CYRILLIC CAPITAL LETTER ZHE WITH BREVE*/
+  0x04C2, /*U+04C2*/ /**/
+  0x04C4, /*U+04C3*/ /*CYRILLIC CAPITAL LETTER KA WITH HOOK*/
+  0x04C4, /*U+04C4*/ /**/
+  0x04C6, /*U+04C5*/ /*CYRILLIC CAPITAL LETTER EL WITH TAIL*/
+  0x04C6, /*U+04C6*/ /**/
+  0x04C8, /*U+04C7*/ /*CYRILLIC CAPITAL LETTER EN WITH HOOK*/
+  0x04C8, /*U+04C8*/ /**/
+  0x04CA, /*U+04C9*/ /*CYRILLIC CAPITAL LETTER EN WITH TAIL*/
+  0x04CA, /*U+04CA*/ /**/
+  0x04CC, /*U+04CB*/ /*CYRILLIC CAPITAL LETTER KHAKASSIAN CHE*/
+  0x04CC, /*U+04CC*/ /**/
+  0x04CE, /*U+04CD*/ /*CYRILLIC CAPITAL LETTER EM WITH TAIL*/
+  0x04CE, /*U+04CE*/ /**/
+  0x04CF, /*U+04CF*/ /**/
+  0x04D1, /*U+04D0*/ /*CYRILLIC CAPITAL LETTER A WITH BREVE*/
+  0x04D1, /*U+04D1*/ /**/
+  0x04D3, /*U+04D2*/ /*CYRILLIC CAPITAL LETTER A WITH DIAERESIS*/
+  0x04D3, /*U+04D3*/ /**/
+  0x04D5, /*U+04D4*/ /*CYRILLIC CAPITAL LIGATURE A IE*/
+  0x04D5, /*U+04D5*/ /**/
+  0x04D7, /*U+04D6*/ /*CYRILLIC CAPITAL LETTER IE WITH BREVE*/
+  0x04D7, /*U+04D7*/ /**/
+  0x04D9, /*U+04D8*/ /*CYRILLIC CAPITAL LETTER SCHWA*/
+  0x04D9, /*U+04D9*/ /**/
+  0x04DB, /*U+04DA*/ /*CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS*/
+  0x04DB, /*U+04DB*/ /**/
+  0x04DD, /*U+04DC*/ /*CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS*/
+  0x04DD, /*U+04DD*/ /**/
+  0x04DF, /*U+04DE*/ /*CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS*/
+  0x04DF, /*U+04DF*/ /**/
+  0x04E1, /*U+04E0*/ /*CYRILLIC CAPITAL LETTER ABKHASIAN DZE*/
+  0x04E1, /*U+04E1*/ /**/
+  0x04E3, /*U+04E2*/ /*CYRILLIC CAPITAL LETTER I WITH MACRON*/
+  0x04E3, /*U+04E3*/ /**/
+  0x04E5, /*U+04E4*/ /*CYRILLIC CAPITAL LETTER I WITH DIAERESIS*/
+  0x04E5, /*U+04E5*/ /**/
+  0x04E7, /*U+04E6*/ /*CYRILLIC CAPITAL LETTER O WITH DIAERESIS*/
+  0x04E7, /*U+04E7*/ /**/
+  0x04E9, /*U+04E8*/ /*CYRILLIC CAPITAL LETTER BARRED O*/
+  0x04E9, /*U+04E9*/ /**/
+  0x04EB, /*U+04EA*/ /*CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS*/
+  0x04EB, /*U+04EB*/ /**/
+  0x04ED, /*U+04EC*/ /*CYRILLIC CAPITAL LETTER E WITH DIAERESIS*/
+  0x04ED, /*U+04ED*/ /**/
+  0x04EF, /*U+04EE*/ /*CYRILLIC CAPITAL LETTER U WITH MACRON*/
+  0x04EF, /*U+04EF*/ /**/
+  0x04F1, /*U+04F0*/ /*CYRILLIC CAPITAL LETTER U WITH DIAERESIS*/
+  0x04F1, /*U+04F1*/ /**/
+  0x04F3, /*U+04F2*/ /*CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE*/
+  0x04F3, /*U+04F3*/ /**/
+  0x04F5, /*U+04F4*/ /*CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS*/
+  0x04F5, /*U+04F5*/ /**/
+  0x04F7, /*U+04F6*/ /*CYRILLIC CAPITAL LETTER GHE WITH DESCENDER*/
+  0x04F7, /*U+04F7*/ /**/
+  0x04F9, /*U+04F8*/ /*CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS*/
+  0x04F9, /*U+04F9*/ /**/
+  0x04FB, /*U+04FA*/ /*CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK*/
+  0x04FB, /*U+04FB*/ /**/
+  0x04FD, /*U+04FC*/ /*CYRILLIC CAPITAL LETTER HA WITH HOOK*/
+  0x04FD, /*U+04FD*/ /**/
+  0x04FF, /*U+04FE*/ /*CYRILLIC CAPITAL LETTER HA WITH STROKE*/
+  0x04FF, /*U+04FF*/ /**/
+  0x0501, /*U+0500*/ /*CYRILLIC CAPITAL LETTER KOMI DE*/
+  0x0501, /*U+0501*/ /**/
+  0x0503, /*U+0502*/ /*CYRILLIC CAPITAL LETTER KOMI DJE*/
+  0x0503, /*U+0503*/ /**/
+  0x0505, /*U+0504*/ /*CYRILLIC CAPITAL LETTER KOMI ZJE*/
+  0x0505, /*U+0505*/ /**/
+  0x0507, /*U+0506*/ /*CYRILLIC CAPITAL LETTER KOMI DZJE*/
+  0x0507, /*U+0507*/ /**/
+  0x0509, /*U+0508*/ /*CYRILLIC CAPITAL LETTER KOMI LJE*/
+  0x0509, /*U+0509*/ /**/
+  0x050B, /*U+050A*/ /*CYRILLIC CAPITAL LETTER KOMI NJE*/
+  0x050B, /*U+050B*/ /**/
+  0x050D, /*U+050C*/ /*CYRILLIC CAPITAL LETTER KOMI SJE*/
+  0x050D, /*U+050D*/ /**/
+  0x050F, /*U+050E*/ /*CYRILLIC CAPITAL LETTER KOMI TJE*/
+  0x050F, /*U+050F*/ /**/
+  0x0511, /*U+0510*/ /*CYRILLIC CAPITAL LETTER REVERSED ZE*/
+  0x0511, /*U+0511*/ /**/
+  0x0513, /*U+0512*/ /*CYRILLIC CAPITAL LETTER EL WITH HOOK*/
+  0x0513, /*U+0513*/ /**/
+  0x0515, /*U+0514*/ /*CYRILLIC CAPITAL LETTER LHA*/
+  0x0515, /*U+0515*/ /**/
+  0x0517, /*U+0516*/ /*CYRILLIC CAPITAL LETTER RHA*/
+  0x0517, /*U+0517*/ /**/
+  0x0519, /*U+0518*/ /*CYRILLIC CAPITAL LETTER YAE*/
+  0x0519, /*U+0519*/ /**/
+  0x051B, /*U+051A*/ /*CYRILLIC CAPITAL LETTER QA*/
+  0x051B, /*U+051B*/ /**/
+  0x051D, /*U+051C*/ /*CYRILLIC CAPITAL LETTER WE*/
+  0x051D, /*U+051D*/ /**/
+  0x051F, /*U+051E*/ /*CYRILLIC CAPITAL LETTER ALEUT KA*/
+  0x051F, /*U+051F*/ /**/
+  0x0521, /*U+0520*/ /*CYRILLIC CAPITAL LETTER EL WITH MIDDLE HOOK*/
+  0x0521, /*U+0521*/ /**/
+  0x0523, /*U+0522*/ /*CYRILLIC CAPITAL LETTER EN WITH MIDDLE HOOK*/
+  0x0523, /*U+0523*/ /**/
+  0x0525, /*U+0524*/ /*CYRILLIC CAPITAL LETTER PE WITH DESCENDER*/
+  0x0525, /*U+0525*/ /**/
+  0x0527, /*U+0526*/ /*CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER*/
+  0x0527, /*U+0527*/ /**/
+  0x0528, /*U+0528*/ /**/
+  0x0529, /*U+0529*/ /**/
+  0x052A, /*U+052A*/ /**/
+  0x052B, /*U+052B*/ /**/
+  0x052C, /*U+052C*/ /**/
+  0x052D, /*U+052D*/ /**/
+  0x052E, /*U+052E*/ /**/
+  0x052F, /*U+052F*/ /**/
+  0x0530, /*U+0530*/ /**/
+  0x0561, /*U+0531*/ /*ARMENIAN CAPITAL LETTER AYB*/
+  0x0562, /*U+0532*/ /*ARMENIAN CAPITAL LETTER BEN*/
+  0x0563, /*U+0533*/ /*ARMENIAN CAPITAL LETTER GIM*/
+  0x0564, /*U+0534*/ /*ARMENIAN CAPITAL LETTER DA*/
+  0x0565, /*U+0535*/ /*ARMENIAN CAPITAL LETTER ECH*/
+  0x0566, /*U+0536*/ /*ARMENIAN CAPITAL LETTER ZA*/
+  0x0567, /*U+0537*/ /*ARMENIAN CAPITAL LETTER EH*/
+  0x0568, /*U+0538*/ /*ARMENIAN CAPITAL LETTER ET*/
+  0x0569, /*U+0539*/ /*ARMENIAN CAPITAL LETTER TO*/
+  0x056A, /*U+053A*/ /*ARMENIAN CAPITAL LETTER ZHE*/
+  0x056B, /*U+053B*/ /*ARMENIAN CAPITAL LETTER INI*/
+  0x056C, /*U+053C*/ /*ARMENIAN CAPITAL LETTER LIWN*/
+  0x056D, /*U+053D*/ /*ARMENIAN CAPITAL LETTER XEH*/
+  0x056E, /*U+053E*/ /*ARMENIAN CAPITAL LETTER CA*/
+  0x056F, /*U+053F*/ /*ARMENIAN CAPITAL LETTER KEN*/
+  0x0570, /*U+0540*/ /*ARMENIAN CAPITAL LETTER HO*/
+  0x0571, /*U+0541*/ /*ARMENIAN CAPITAL LETTER JA*/
+  0x0572, /*U+0542*/ /*ARMENIAN CAPITAL LETTER GHAD*/
+  0x0573, /*U+0543*/ /*ARMENIAN CAPITAL LETTER CHEH*/
+  0x0574, /*U+0544*/ /*ARMENIAN CAPITAL LETTER MEN*/
+  0x0575, /*U+0545*/ /*ARMENIAN CAPITAL LETTER YI*/
+  0x0576, /*U+0546*/ /*ARMENIAN CAPITAL LETTER NOW*/
+  0x0577, /*U+0547*/ /*ARMENIAN CAPITAL LETTER SHA*/
+  0x0578, /*U+0548*/ /*ARMENIAN CAPITAL LETTER VO*/
+  0x0579, /*U+0549*/ /*ARMENIAN CAPITAL LETTER CHA*/
+  0x057A, /*U+054A*/ /*ARMENIAN CAPITAL LETTER PEH*/
+  0x057B, /*U+054B*/ /*ARMENIAN CAPITAL LETTER JHEH*/
+  0x057C, /*U+054C*/ /*ARMENIAN CAPITAL LETTER RA*/
+  0x057D, /*U+054D*/ /*ARMENIAN CAPITAL LETTER SEH*/
+  0x057E, /*U+054E*/ /*ARMENIAN CAPITAL LETTER VEW*/
+  0x057F, /*U+054F*/ /*ARMENIAN CAPITAL LETTER TIWN*/
+  0x0580, /*U+0550*/ /*ARMENIAN CAPITAL LETTER REH*/
+  0x0581, /*U+0551*/ /*ARMENIAN CAPITAL LETTER CO*/
+  0x0582, /*U+0552*/ /*ARMENIAN CAPITAL LETTER YIWN*/
+  0x0583, /*U+0553*/ /*ARMENIAN CAPITAL LETTER PIWR*/
+  0x0584, /*U+0554*/ /*ARMENIAN CAPITAL LETTER KEH*/
+  0x0585, /*U+0555*/ /*ARMENIAN CAPITAL LETTER OH*/
+  0x0586, /*U+0556*/ /*ARMENIAN CAPITAL LETTER FEH*/
+  0x0557, /*U+0557*/ /**/
+  0x0558, /*U+0558*/ /**/
+  0x0559, /*U+0559*/ /**/
+  0x055A, /*U+055A*/ /**/
+  0x055B, /*U+055B*/ /**/
+  0x055C, /*U+055C*/ /**/
+  0x055D, /*U+055D*/ /**/
+  0x055E, /*U+055E*/ /**/
+  0x055F, /*U+055F*/ /**/
+  0x0560, /*U+0560*/ /**/
+  0x0561, /*U+0561*/ /**/
+  0x0562, /*U+0562*/ /**/
+  0x0563, /*U+0563*/ /**/
+  0x0564, /*U+0564*/ /**/
+  0x0565, /*U+0565*/ /**/
+  0x0566, /*U+0566*/ /**/
+  0x0567, /*U+0567*/ /**/
+  0x0568, /*U+0568*/ /**/
+  0x0569, /*U+0569*/ /**/
+  0x056A, /*U+056A*/ /**/
+  0x056B, /*U+056B*/ /**/
+  0x056C, /*U+056C*/ /**/
+  0x056D, /*U+056D*/ /**/
+  0x056E, /*U+056E*/ /**/
+  0x056F, /*U+056F*/ /**/
+  0x0570, /*U+0570*/ /**/
+  0x0571, /*U+0571*/ /**/
+  0x0572, /*U+0572*/ /**/
+  0x0573, /*U+0573*/ /**/
+  0x0574, /*U+0574*/ /**/
+  0x0575, /*U+0575*/ /**/
+  0x0576, /*U+0576*/ /**/
+  0x0577, /*U+0577*/ /**/
+  0x0578, /*U+0578*/ /**/
+  0x0579, /*U+0579*/ /**/
+  0x057A, /*U+057A*/ /**/
+  0x057B, /*U+057B*/ /**/
+  0x057C, /*U+057C*/ /**/
+  0x057D, /*U+057D*/ /**/
+  0x057E, /*U+057E*/ /**/
+  0x057F, /*U+057F*/ /**/
+};
+
+static const u_int16_t lower_table_4[128] = {
+  0x1080, /*U+1080*/ /**/
+  0x1081, /*U+1081*/ /**/
+  0x1082, /*U+1082*/ /**/
+  0x1083, /*U+1083*/ /**/
+  0x1084, /*U+1084*/ /**/
+  0x1085, /*U+1085*/ /**/
+  0x1086, /*U+1086*/ /**/
+  0x1087, /*U+1087*/ /**/
+  0x1088, /*U+1088*/ /**/
+  0x1089, /*U+1089*/ /**/
+  0x108A, /*U+108A*/ /**/
+  0x108B, /*U+108B*/ /**/
+  0x108C, /*U+108C*/ /**/
+  0x108D, /*U+108D*/ /**/
+  0x108E, /*U+108E*/ /**/
+  0x108F, /*U+108F*/ /**/
+  0x1090, /*U+1090*/ /**/
+  0x1091, /*U+1091*/ /**/
+  0x1092, /*U+1092*/ /**/
+  0x1093, /*U+1093*/ /**/
+  0x1094, /*U+1094*/ /**/
+  0x1095, /*U+1095*/ /**/
+  0x1096, /*U+1096*/ /**/
+  0x1097, /*U+1097*/ /**/
+  0x1098, /*U+1098*/ /**/
+  0x1099, /*U+1099*/ /**/
+  0x109A, /*U+109A*/ /**/
+  0x109B, /*U+109B*/ /**/
+  0x109C, /*U+109C*/ /**/
+  0x109D, /*U+109D*/ /**/
+  0x109E, /*U+109E*/ /**/
+  0x109F, /*U+109F*/ /**/
+  0x2D00, /*U+10A0*/ /*GEORGIAN CAPITAL LETTER AN*/
+  0x2D01, /*U+10A1*/ /*GEORGIAN CAPITAL LETTER BAN*/
+  0x2D02, /*U+10A2*/ /*GEORGIAN CAPITAL LETTER GAN*/
+  0x2D03, /*U+10A3*/ /*GEORGIAN CAPITAL LETTER DON*/
+  0x2D04, /*U+10A4*/ /*GEORGIAN CAPITAL LETTER EN*/
+  0x2D05, /*U+10A5*/ /*GEORGIAN CAPITAL LETTER VIN*/
+  0x2D06, /*U+10A6*/ /*GEORGIAN CAPITAL LETTER ZEN*/
+  0x2D07, /*U+10A7*/ /*GEORGIAN CAPITAL LETTER TAN*/
+  0x2D08, /*U+10A8*/ /*GEORGIAN CAPITAL LETTER IN*/
+  0x2D09, /*U+10A9*/ /*GEORGIAN CAPITAL LETTER KAN*/
+  0x2D0A, /*U+10AA*/ /*GEORGIAN CAPITAL LETTER LAS*/
+  0x2D0B, /*U+10AB*/ /*GEORGIAN CAPITAL LETTER MAN*/
+  0x2D0C, /*U+10AC*/ /*GEORGIAN CAPITAL LETTER NAR*/
+  0x2D0D, /*U+10AD*/ /*GEORGIAN CAPITAL LETTER ON*/
+  0x2D0E, /*U+10AE*/ /*GEORGIAN CAPITAL LETTER PAR*/
+  0x2D0F, /*U+10AF*/ /*GEORGIAN CAPITAL LETTER ZHAR*/
+  0x2D10, /*U+10B0*/ /*GEORGIAN CAPITAL LETTER RAE*/
+  0x2D11, /*U+10B1*/ /*GEORGIAN CAPITAL LETTER SAN*/
+  0x2D12, /*U+10B2*/ /*GEORGIAN CAPITAL LETTER TAR*/
+  0x2D13, /*U+10B3*/ /*GEORGIAN CAPITAL LETTER UN*/
+  0x2D14, /*U+10B4*/ /*GEORGIAN CAPITAL LETTER PHAR*/
+  0x2D15, /*U+10B5*/ /*GEORGIAN CAPITAL LETTER KHAR*/
+  0x2D16, /*U+10B6*/ /*GEORGIAN CAPITAL LETTER GHAN*/
+  0x2D17, /*U+10B7*/ /*GEORGIAN CAPITAL LETTER QAR*/
+  0x2D18, /*U+10B8*/ /*GEORGIAN CAPITAL LETTER SHIN*/
+  0x2D19, /*U+10B9*/ /*GEORGIAN CAPITAL LETTER CHIN*/
+  0x2D1A, /*U+10BA*/ /*GEORGIAN CAPITAL LETTER CAN*/
+  0x2D1B, /*U+10BB*/ /*GEORGIAN CAPITAL LETTER JIL*/
+  0x2D1C, /*U+10BC*/ /*GEORGIAN CAPITAL LETTER CIL*/
+  0x2D1D, /*U+10BD*/ /*GEORGIAN CAPITAL LETTER CHAR*/
+  0x2D1E, /*U+10BE*/ /*GEORGIAN CAPITAL LETTER XAN*/
+  0x2D1F, /*U+10BF*/ /*GEORGIAN CAPITAL LETTER JHAN*/
+  0x2D20, /*U+10C0*/ /*GEORGIAN CAPITAL LETTER HAE*/
+  0x2D21, /*U+10C1*/ /*GEORGIAN CAPITAL LETTER HE*/
+  0x2D22, /*U+10C2*/ /*GEORGIAN CAPITAL LETTER HIE*/
+  0x2D23, /*U+10C3*/ /*GEORGIAN CAPITAL LETTER WE*/
+  0x2D24, /*U+10C4*/ /*GEORGIAN CAPITAL LETTER HAR*/
+  0x2D25, /*U+10C5*/ /*GEORGIAN CAPITAL LETTER HOE*/
+  0x10C6, /*U+10C6*/ /**/
+  0x10C7, /*U+10C7*/ /**/
+  0x10C8, /*U+10C8*/ /**/
+  0x10C9, /*U+10C9*/ /**/
+  0x10CA, /*U+10CA*/ /**/
+  0x10CB, /*U+10CB*/ /**/
+  0x10CC, /*U+10CC*/ /**/
+  0x10CD, /*U+10CD*/ /**/
+  0x10CE, /*U+10CE*/ /**/
+  0x10CF, /*U+10CF*/ /**/
+  0x10D0, /*U+10D0*/ /**/
+  0x10D1, /*U+10D1*/ /**/
+  0x10D2, /*U+10D2*/ /**/
+  0x10D3, /*U+10D3*/ /**/
+  0x10D4, /*U+10D4*/ /**/
+  0x10D5, /*U+10D5*/ /**/
+  0x10D6, /*U+10D6*/ /**/
+  0x10D7, /*U+10D7*/ /**/
+  0x10D8, /*U+10D8*/ /**/
+  0x10D9, /*U+10D9*/ /**/
+  0x10DA, /*U+10DA*/ /**/
+  0x10DB, /*U+10DB*/ /**/
+  0x10DC, /*U+10DC*/ /**/
+  0x10DD, /*U+10DD*/ /**/
+  0x10DE, /*U+10DE*/ /**/
+  0x10DF, /*U+10DF*/ /**/
+  0x10E0, /*U+10E0*/ /**/
+  0x10E1, /*U+10E1*/ /**/
+  0x10E2, /*U+10E2*/ /**/
+  0x10E3, /*U+10E3*/ /**/
+  0x10E4, /*U+10E4*/ /**/
+  0x10E5, /*U+10E5*/ /**/
+  0x10E6, /*U+10E6*/ /**/
+  0x10E7, /*U+10E7*/ /**/
+  0x10E8, /*U+10E8*/ /**/
+  0x10E9, /*U+10E9*/ /**/
+  0x10EA, /*U+10EA*/ /**/
+  0x10EB, /*U+10EB*/ /**/
+  0x10EC, /*U+10EC*/ /**/
+  0x10ED, /*U+10ED*/ /**/
+  0x10EE, /*U+10EE*/ /**/
+  0x10EF, /*U+10EF*/ /**/
+  0x10F0, /*U+10F0*/ /**/
+  0x10F1, /*U+10F1*/ /**/
+  0x10F2, /*U+10F2*/ /**/
+  0x10F3, /*U+10F3*/ /**/
+  0x10F4, /*U+10F4*/ /**/
+  0x10F5, /*U+10F5*/ /**/
+  0x10F6, /*U+10F6*/ /**/
+  0x10F7, /*U+10F7*/ /**/
+  0x10F8, /*U+10F8*/ /**/
+  0x10F9, /*U+10F9*/ /**/
+  0x10FA, /*U+10FA*/ /**/
+  0x10FB, /*U+10FB*/ /**/
+  0x10FC, /*U+10FC*/ /**/
+  0x10FD, /*U+10FD*/ /**/
+  0x10FE, /*U+10FE*/ /**/
+  0x10FF, /*U+10FF*/ /**/
+};
+
+static const u_int16_t lower_table_5[512] = {
+  0x1E01, /*U+1E00*/ /*LATIN CAPITAL LETTER A WITH RING BELOW*/
+  0x1E01, /*U+1E01*/ /**/
+  0x1E03, /*U+1E02*/ /*LATIN CAPITAL LETTER B WITH DOT ABOVE*/
+  0x1E03, /*U+1E03*/ /**/
+  0x1E05, /*U+1E04*/ /*LATIN CAPITAL LETTER B WITH DOT BELOW*/
+  0x1E05, /*U+1E05*/ /**/
+  0x1E07, /*U+1E06*/ /*LATIN CAPITAL LETTER B WITH LINE BELOW*/
+  0x1E07, /*U+1E07*/ /**/
+  0x1E09, /*U+1E08*/ /*LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE*/
+  0x1E09, /*U+1E09*/ /**/
+  0x1E0B, /*U+1E0A*/ /*LATIN CAPITAL LETTER D WITH DOT ABOVE*/
+  0x1E0B, /*U+1E0B*/ /**/
+  0x1E0D, /*U+1E0C*/ /*LATIN CAPITAL LETTER D WITH DOT BELOW*/
+  0x1E0D, /*U+1E0D*/ /**/
+  0x1E0F, /*U+1E0E*/ /*LATIN CAPITAL LETTER D WITH LINE BELOW*/
+  0x1E0F, /*U+1E0F*/ /**/
+  0x1E11, /*U+1E10*/ /*LATIN CAPITAL LETTER D WITH CEDILLA*/
+  0x1E11, /*U+1E11*/ /**/
+  0x1E13, /*U+1E12*/ /*LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW*/
+  0x1E13, /*U+1E13*/ /**/
+  0x1E15, /*U+1E14*/ /*LATIN CAPITAL LETTER E WITH MACRON AND GRAVE*/
+  0x1E15, /*U+1E15*/ /**/
+  0x1E17, /*U+1E16*/ /*LATIN CAPITAL LETTER E WITH MACRON AND ACUTE*/
+  0x1E17, /*U+1E17*/ /**/
+  0x1E19, /*U+1E18*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW*/
+  0x1E19, /*U+1E19*/ /**/
+  0x1E1B, /*U+1E1A*/ /*LATIN CAPITAL LETTER E WITH TILDE BELOW*/
+  0x1E1B, /*U+1E1B*/ /**/
+  0x1E1D, /*U+1E1C*/ /*LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE*/
+  0x1E1D, /*U+1E1D*/ /**/
+  0x1E1F, /*U+1E1E*/ /*LATIN CAPITAL LETTER F WITH DOT ABOVE*/
+  0x1E1F, /*U+1E1F*/ /**/
+  0x1E21, /*U+1E20*/ /*LATIN CAPITAL LETTER G WITH MACRON*/
+  0x1E21, /*U+1E21*/ /**/
+  0x1E23, /*U+1E22*/ /*LATIN CAPITAL LETTER H WITH DOT ABOVE*/
+  0x1E23, /*U+1E23*/ /**/
+  0x1E25, /*U+1E24*/ /*LATIN CAPITAL LETTER H WITH DOT BELOW*/
+  0x1E25, /*U+1E25*/ /**/
+  0x1E27, /*U+1E26*/ /*LATIN CAPITAL LETTER H WITH DIAERESIS*/
+  0x1E27, /*U+1E27*/ /**/
+  0x1E29, /*U+1E28*/ /*LATIN CAPITAL LETTER H WITH CEDILLA*/
+  0x1E29, /*U+1E29*/ /**/
+  0x1E2B, /*U+1E2A*/ /*LATIN CAPITAL LETTER H WITH BREVE BELOW*/
+  0x1E2B, /*U+1E2B*/ /**/
+  0x1E2D, /*U+1E2C*/ /*LATIN CAPITAL LETTER I WITH TILDE BELOW*/
+  0x1E2D, /*U+1E2D*/ /**/
+  0x1E2F, /*U+1E2E*/ /*LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE*/
+  0x1E2F, /*U+1E2F*/ /**/
+  0x1E31, /*U+1E30*/ /*LATIN CAPITAL LETTER K WITH ACUTE*/
+  0x1E31, /*U+1E31*/ /**/
+  0x1E33, /*U+1E32*/ /*LATIN CAPITAL LETTER K WITH DOT BELOW*/
+  0x1E33, /*U+1E33*/ /**/
+  0x1E35, /*U+1E34*/ /*LATIN CAPITAL LETTER K WITH LINE BELOW*/
+  0x1E35, /*U+1E35*/ /**/
+  0x1E37, /*U+1E36*/ /*LATIN CAPITAL LETTER L WITH DOT BELOW*/
+  0x1E37, /*U+1E37*/ /**/
+  0x1E39, /*U+1E38*/ /*LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON*/
+  0x1E39, /*U+1E39*/ /**/
+  0x1E3B, /*U+1E3A*/ /*LATIN CAPITAL LETTER L WITH LINE BELOW*/
+  0x1E3B, /*U+1E3B*/ /**/
+  0x1E3D, /*U+1E3C*/ /*LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW*/
+  0x1E3D, /*U+1E3D*/ /**/
+  0x1E3F, /*U+1E3E*/ /*LATIN CAPITAL LETTER M WITH ACUTE*/
+  0x1E3F, /*U+1E3F*/ /**/
+  0x1E41, /*U+1E40*/ /*LATIN CAPITAL LETTER M WITH DOT ABOVE*/
+  0x1E41, /*U+1E41*/ /**/
+  0x1E43, /*U+1E42*/ /*LATIN CAPITAL LETTER M WITH DOT BELOW*/
+  0x1E43, /*U+1E43*/ /**/
+  0x1E45, /*U+1E44*/ /*LATIN CAPITAL LETTER N WITH DOT ABOVE*/
+  0x1E45, /*U+1E45*/ /**/
+  0x1E47, /*U+1E46*/ /*LATIN CAPITAL LETTER N WITH DOT BELOW*/
+  0x1E47, /*U+1E47*/ /**/
+  0x1E49, /*U+1E48*/ /*LATIN CAPITAL LETTER N WITH LINE BELOW*/
+  0x1E49, /*U+1E49*/ /**/
+  0x1E4B, /*U+1E4A*/ /*LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW*/
+  0x1E4B, /*U+1E4B*/ /**/
+  0x1E4D, /*U+1E4C*/ /*LATIN CAPITAL LETTER O WITH TILDE AND ACUTE*/
+  0x1E4D, /*U+1E4D*/ /**/
+  0x1E4F, /*U+1E4E*/ /*LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS*/
+  0x1E4F, /*U+1E4F*/ /**/
+  0x1E51, /*U+1E50*/ /*LATIN CAPITAL LETTER O WITH MACRON AND GRAVE*/
+  0x1E51, /*U+1E51*/ /**/
+  0x1E53, /*U+1E52*/ /*LATIN CAPITAL LETTER O WITH MACRON AND ACUTE*/
+  0x1E53, /*U+1E53*/ /**/
+  0x1E55, /*U+1E54*/ /*LATIN CAPITAL LETTER P WITH ACUTE*/
+  0x1E55, /*U+1E55*/ /**/
+  0x1E57, /*U+1E56*/ /*LATIN CAPITAL LETTER P WITH DOT ABOVE*/
+  0x1E57, /*U+1E57*/ /**/
+  0x1E59, /*U+1E58*/ /*LATIN CAPITAL LETTER R WITH DOT ABOVE*/
+  0x1E59, /*U+1E59*/ /**/
+  0x1E5B, /*U+1E5A*/ /*LATIN CAPITAL LETTER R WITH DOT BELOW*/
+  0x1E5B, /*U+1E5B*/ /**/
+  0x1E5D, /*U+1E5C*/ /*LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON*/
+  0x1E5D, /*U+1E5D*/ /**/
+  0x1E5F, /*U+1E5E*/ /*LATIN CAPITAL LETTER R WITH LINE BELOW*/
+  0x1E5F, /*U+1E5F*/ /**/
+  0x1E61, /*U+1E60*/ /*LATIN CAPITAL LETTER S WITH DOT ABOVE*/
+  0x1E61, /*U+1E61*/ /**/
+  0x1E63, /*U+1E62*/ /*LATIN CAPITAL LETTER S WITH DOT BELOW*/
+  0x1E63, /*U+1E63*/ /**/
+  0x1E65, /*U+1E64*/ /*LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE*/
+  0x1E65, /*U+1E65*/ /**/
+  0x1E67, /*U+1E66*/ /*LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE*/
+  0x1E67, /*U+1E67*/ /**/
+  0x1E69, /*U+1E68*/ /*LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE*/
+  0x1E69, /*U+1E69*/ /**/
+  0x1E6B, /*U+1E6A*/ /*LATIN CAPITAL LETTER T WITH DOT ABOVE*/
+  0x1E6B, /*U+1E6B*/ /**/
+  0x1E6D, /*U+1E6C*/ /*LATIN CAPITAL LETTER T WITH DOT BELOW*/
+  0x1E6D, /*U+1E6D*/ /**/
+  0x1E6F, /*U+1E6E*/ /*LATIN CAPITAL LETTER T WITH LINE BELOW*/
+  0x1E6F, /*U+1E6F*/ /**/
+  0x1E71, /*U+1E70*/ /*LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW*/
+  0x1E71, /*U+1E71*/ /**/
+  0x1E73, /*U+1E72*/ /*LATIN CAPITAL LETTER U WITH DIAERESIS BELOW*/
+  0x1E73, /*U+1E73*/ /**/
+  0x1E75, /*U+1E74*/ /*LATIN CAPITAL LETTER U WITH TILDE BELOW*/
+  0x1E75, /*U+1E75*/ /**/
+  0x1E77, /*U+1E76*/ /*LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW*/
+  0x1E77, /*U+1E77*/ /**/
+  0x1E79, /*U+1E78*/ /*LATIN CAPITAL LETTER U WITH TILDE AND ACUTE*/
+  0x1E79, /*U+1E79*/ /**/
+  0x1E7B, /*U+1E7A*/ /*LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS*/
+  0x1E7B, /*U+1E7B*/ /**/
+  0x1E7D, /*U+1E7C*/ /*LATIN CAPITAL LETTER V WITH TILDE*/
+  0x1E7D, /*U+1E7D*/ /**/
+  0x1E7F, /*U+1E7E*/ /*LATIN CAPITAL LETTER V WITH DOT BELOW*/
+  0x1E7F, /*U+1E7F*/ /**/
+  0x1E81, /*U+1E80*/ /*LATIN CAPITAL LETTER W WITH GRAVE*/
+  0x1E81, /*U+1E81*/ /**/
+  0x1E83, /*U+1E82*/ /*LATIN CAPITAL LETTER W WITH ACUTE*/
+  0x1E83, /*U+1E83*/ /**/
+  0x1E85, /*U+1E84*/ /*LATIN CAPITAL LETTER W WITH DIAERESIS*/
+  0x1E85, /*U+1E85*/ /**/
+  0x1E87, /*U+1E86*/ /*LATIN CAPITAL LETTER W WITH DOT ABOVE*/
+  0x1E87, /*U+1E87*/ /**/
+  0x1E89, /*U+1E88*/ /*LATIN CAPITAL LETTER W WITH DOT BELOW*/
+  0x1E89, /*U+1E89*/ /**/
+  0x1E8B, /*U+1E8A*/ /*LATIN CAPITAL LETTER X WITH DOT ABOVE*/
+  0x1E8B, /*U+1E8B*/ /**/
+  0x1E8D, /*U+1E8C*/ /*LATIN CAPITAL LETTER X WITH DIAERESIS*/
+  0x1E8D, /*U+1E8D*/ /**/
+  0x1E8F, /*U+1E8E*/ /*LATIN CAPITAL LETTER Y WITH DOT ABOVE*/
+  0x1E8F, /*U+1E8F*/ /**/
+  0x1E91, /*U+1E90*/ /*LATIN CAPITAL LETTER Z WITH CIRCUMFLEX*/
+  0x1E91, /*U+1E91*/ /**/
+  0x1E93, /*U+1E92*/ /*LATIN CAPITAL LETTER Z WITH DOT BELOW*/
+  0x1E93, /*U+1E93*/ /**/
+  0x1E95, /*U+1E94*/ /*LATIN CAPITAL LETTER Z WITH LINE BELOW*/
+  0x1E95, /*U+1E95*/ /**/
+  0x1E96, /*U+1E96*/ /**/
+  0x1E97, /*U+1E97*/ /**/
+  0x1E98, /*U+1E98*/ /**/
+  0x1E99, /*U+1E99*/ /**/
+  0x1E9A, /*U+1E9A*/ /**/
+  0x1E9B, /*U+1E9B*/ /**/
+  0x1E9C, /*U+1E9C*/ /**/
+  0x1E9D, /*U+1E9D*/ /**/
+  0x00DF, /*U+1E9E*/ /*LATIN CAPITAL LETTER SHARP S*/
+  0x1E9F, /*U+1E9F*/ /**/
+  0x1EA1, /*U+1EA0*/ /*LATIN CAPITAL LETTER A WITH DOT BELOW*/
+  0x1EA1, /*U+1EA1*/ /**/
+  0x1EA3, /*U+1EA2*/ /*LATIN CAPITAL LETTER A WITH HOOK ABOVE*/
+  0x1EA3, /*U+1EA3*/ /**/
+  0x1EA5, /*U+1EA4*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE*/
+  0x1EA5, /*U+1EA5*/ /**/
+  0x1EA7, /*U+1EA6*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE*/
+  0x1EA7, /*U+1EA7*/ /**/
+  0x1EA9, /*U+1EA8*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1EA9, /*U+1EA9*/ /**/
+  0x1EAB, /*U+1EAA*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE*/
+  0x1EAB, /*U+1EAB*/ /**/
+  0x1EAD, /*U+1EAC*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1EAD, /*U+1EAD*/ /**/
+  0x1EAF, /*U+1EAE*/ /*LATIN CAPITAL LETTER A WITH BREVE AND ACUTE*/
+  0x1EAF, /*U+1EAF*/ /**/
+  0x1EB1, /*U+1EB0*/ /*LATIN CAPITAL LETTER A WITH BREVE AND GRAVE*/
+  0x1EB1, /*U+1EB1*/ /**/
+  0x1EB3, /*U+1EB2*/ /*LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE*/
+  0x1EB3, /*U+1EB3*/ /**/
+  0x1EB5, /*U+1EB4*/ /*LATIN CAPITAL LETTER A WITH BREVE AND TILDE*/
+  0x1EB5, /*U+1EB5*/ /**/
+  0x1EB7, /*U+1EB6*/ /*LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW*/
+  0x1EB7, /*U+1EB7*/ /**/
+  0x1EB9, /*U+1EB8*/ /*LATIN CAPITAL LETTER E WITH DOT BELOW*/
+  0x1EB9, /*U+1EB9*/ /**/
+  0x1EBB, /*U+1EBA*/ /*LATIN CAPITAL LETTER E WITH HOOK ABOVE*/
+  0x1EBB, /*U+1EBB*/ /**/
+  0x1EBD, /*U+1EBC*/ /*LATIN CAPITAL LETTER E WITH TILDE*/
+  0x1EBD, /*U+1EBD*/ /**/
+  0x1EBF, /*U+1EBE*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE*/
+  0x1EBF, /*U+1EBF*/ /**/
+  0x1EC1, /*U+1EC0*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE*/
+  0x1EC1, /*U+1EC1*/ /**/
+  0x1EC3, /*U+1EC2*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1EC3, /*U+1EC3*/ /**/
+  0x1EC5, /*U+1EC4*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE*/
+  0x1EC5, /*U+1EC5*/ /**/
+  0x1EC7, /*U+1EC6*/ /*LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1EC7, /*U+1EC7*/ /**/
+  0x1EC9, /*U+1EC8*/ /*LATIN CAPITAL LETTER I WITH HOOK ABOVE*/
+  0x1EC9, /*U+1EC9*/ /**/
+  0x1ECB, /*U+1ECA*/ /*LATIN CAPITAL LETTER I WITH DOT BELOW*/
+  0x1ECB, /*U+1ECB*/ /**/
+  0x1ECD, /*U+1ECC*/ /*LATIN CAPITAL LETTER O WITH DOT BELOW*/
+  0x1ECD, /*U+1ECD*/ /**/
+  0x1ECF, /*U+1ECE*/ /*LATIN CAPITAL LETTER O WITH HOOK ABOVE*/
+  0x1ECF, /*U+1ECF*/ /**/
+  0x1ED1, /*U+1ED0*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE*/
+  0x1ED1, /*U+1ED1*/ /**/
+  0x1ED3, /*U+1ED2*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE*/
+  0x1ED3, /*U+1ED3*/ /**/
+  0x1ED5, /*U+1ED4*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE*/
+  0x1ED5, /*U+1ED5*/ /**/
+  0x1ED7, /*U+1ED6*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE*/
+  0x1ED7, /*U+1ED7*/ /**/
+  0x1ED9, /*U+1ED8*/ /*LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW*/
+  0x1ED9, /*U+1ED9*/ /**/
+  0x1EDB, /*U+1EDA*/ /*LATIN CAPITAL LETTER O WITH HORN AND ACUTE*/
+  0x1EDB, /*U+1EDB*/ /**/
+  0x1EDD, /*U+1EDC*/ /*LATIN CAPITAL LETTER O WITH HORN AND GRAVE*/
+  0x1EDD, /*U+1EDD*/ /**/
+  0x1EDF, /*U+1EDE*/ /*LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE*/
+  0x1EDF, /*U+1EDF*/ /**/
+  0x1EE1, /*U+1EE0*/ /*LATIN CAPITAL LETTER O WITH HORN AND TILDE*/
+  0x1EE1, /*U+1EE1*/ /**/
+  0x1EE3, /*U+1EE2*/ /*LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW*/
+  0x1EE3, /*U+1EE3*/ /**/
+  0x1EE5, /*U+1EE4*/ /*LATIN CAPITAL LETTER U WITH DOT BELOW*/
+  0x1EE5, /*U+1EE5*/ /**/
+  0x1EE7, /*U+1EE6*/ /*LATIN CAPITAL LETTER U WITH HOOK ABOVE*/
+  0x1EE7, /*U+1EE7*/ /**/
+  0x1EE9, /*U+1EE8*/ /*LATIN CAPITAL LETTER U WITH HORN AND ACUTE*/
+  0x1EE9, /*U+1EE9*/ /**/
+  0x1EEB, /*U+1EEA*/ /*LATIN CAPITAL LETTER U WITH HORN AND GRAVE*/
+  0x1EEB, /*U+1EEB*/ /**/
+  0x1EED, /*U+1EEC*/ /*LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE*/
+  0x1EED, /*U+1EED*/ /**/
+  0x1EEF, /*U+1EEE*/ /*LATIN CAPITAL LETTER U WITH HORN AND TILDE*/
+  0x1EEF, /*U+1EEF*/ /**/
+  0x1EF1, /*U+1EF0*/ /*LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW*/
+  0x1EF1, /*U+1EF1*/ /**/
+  0x1EF3, /*U+1EF2*/ /*LATIN CAPITAL LETTER Y WITH GRAVE*/
+  0x1EF3, /*U+1EF3*/ /**/
+  0x1EF5, /*U+1EF4*/ /*LATIN CAPITAL LETTER Y WITH DOT BELOW*/
+  0x1EF5, /*U+1EF5*/ /**/
+  0x1EF7, /*U+1EF6*/ /*LATIN CAPITAL LETTER Y WITH HOOK ABOVE*/
+  0x1EF7, /*U+1EF7*/ /**/
+  0x1EF9, /*U+1EF8*/ /*LATIN CAPITAL LETTER Y WITH TILDE*/
+  0x1EF9, /*U+1EF9*/ /**/
+  0x1EFB, /*U+1EFA*/ /*LATIN CAPITAL LETTER MIDDLE-WELSH LL*/
+  0x1EFB, /*U+1EFB*/ /**/
+  0x1EFD, /*U+1EFC*/ /*LATIN CAPITAL LETTER MIDDLE-WELSH V*/
+  0x1EFD, /*U+1EFD*/ /**/
+  0x1EFF, /*U+1EFE*/ /*LATIN CAPITAL LETTER Y WITH LOOP*/
+  0x1EFF, /*U+1EFF*/ /**/
+  0x1F00, /*U+1F00*/ /**/
+  0x1F01, /*U+1F01*/ /**/
+  0x1F02, /*U+1F02*/ /**/
+  0x1F03, /*U+1F03*/ /**/
+  0x1F04, /*U+1F04*/ /**/
+  0x1F05, /*U+1F05*/ /**/
+  0x1F06, /*U+1F06*/ /**/
+  0x1F07, /*U+1F07*/ /**/
+  0x1F00, /*U+1F08*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI*/
+  0x1F01, /*U+1F09*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA*/
+  0x1F02, /*U+1F0A*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA*/
+  0x1F03, /*U+1F0B*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA*/
+  0x1F04, /*U+1F0C*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA*/
+  0x1F05, /*U+1F0D*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA*/
+  0x1F06, /*U+1F0E*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI*/
+  0x1F07, /*U+1F0F*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI*/
+  0x1F10, /*U+1F10*/ /**/
+  0x1F11, /*U+1F11*/ /**/
+  0x1F12, /*U+1F12*/ /**/
+  0x1F13, /*U+1F13*/ /**/
+  0x1F14, /*U+1F14*/ /**/
+  0x1F15, /*U+1F15*/ /**/
+  0x1F16, /*U+1F16*/ /**/
+  0x1F17, /*U+1F17*/ /**/
+  0x1F10, /*U+1F18*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI*/
+  0x1F11, /*U+1F19*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA*/
+  0x1F12, /*U+1F1A*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA*/
+  0x1F13, /*U+1F1B*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA*/
+  0x1F14, /*U+1F1C*/ /*GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA*/
+  0x1F15, /*U+1F1D*/ /*GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA*/
+  0x1F1E, /*U+1F1E*/ /**/
+  0x1F1F, /*U+1F1F*/ /**/
+  0x1F20, /*U+1F20*/ /**/
+  0x1F21, /*U+1F21*/ /**/
+  0x1F22, /*U+1F22*/ /**/
+  0x1F23, /*U+1F23*/ /**/
+  0x1F24, /*U+1F24*/ /**/
+  0x1F25, /*U+1F25*/ /**/
+  0x1F26, /*U+1F26*/ /**/
+  0x1F27, /*U+1F27*/ /**/
+  0x1F20, /*U+1F28*/ /*GREEK CAPITAL LETTER ETA WITH PSILI*/
+  0x1F21, /*U+1F29*/ /*GREEK CAPITAL LETTER ETA WITH DASIA*/
+  0x1F22, /*U+1F2A*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA*/
+  0x1F23, /*U+1F2B*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA*/
+  0x1F24, /*U+1F2C*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA*/
+  0x1F25, /*U+1F2D*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA*/
+  0x1F26, /*U+1F2E*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI*/
+  0x1F27, /*U+1F2F*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI*/
+  0x1F30, /*U+1F30*/ /**/
+  0x1F31, /*U+1F31*/ /**/
+  0x1F32, /*U+1F32*/ /**/
+  0x1F33, /*U+1F33*/ /**/
+  0x1F34, /*U+1F34*/ /**/
+  0x1F35, /*U+1F35*/ /**/
+  0x1F36, /*U+1F36*/ /**/
+  0x1F37, /*U+1F37*/ /**/
+  0x1F30, /*U+1F38*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI*/
+  0x1F31, /*U+1F39*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA*/
+  0x1F32, /*U+1F3A*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA*/
+  0x1F33, /*U+1F3B*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA*/
+  0x1F34, /*U+1F3C*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA*/
+  0x1F35, /*U+1F3D*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA*/
+  0x1F36, /*U+1F3E*/ /*GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI*/
+  0x1F37, /*U+1F3F*/ /*GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI*/
+  0x1F40, /*U+1F40*/ /**/
+  0x1F41, /*U+1F41*/ /**/
+  0x1F42, /*U+1F42*/ /**/
+  0x1F43, /*U+1F43*/ /**/
+  0x1F44, /*U+1F44*/ /**/
+  0x1F45, /*U+1F45*/ /**/
+  0x1F46, /*U+1F46*/ /**/
+  0x1F47, /*U+1F47*/ /**/
+  0x1F40, /*U+1F48*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI*/
+  0x1F41, /*U+1F49*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA*/
+  0x1F42, /*U+1F4A*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA*/
+  0x1F43, /*U+1F4B*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA*/
+  0x1F44, /*U+1F4C*/ /*GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA*/
+  0x1F45, /*U+1F4D*/ /*GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA*/
+  0x1F4E, /*U+1F4E*/ /**/
+  0x1F4F, /*U+1F4F*/ /**/
+  0x1F50, /*U+1F50*/ /**/
+  0x1F51, /*U+1F51*/ /**/
+  0x1F52, /*U+1F52*/ /**/
+  0x1F53, /*U+1F53*/ /**/
+  0x1F54, /*U+1F54*/ /**/
+  0x1F55, /*U+1F55*/ /**/
+  0x1F56, /*U+1F56*/ /**/
+  0x1F57, /*U+1F57*/ /**/
+  0x1F58, /*U+1F58*/ /**/
+  0x1F51, /*U+1F59*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA*/
+  0x1F5A, /*U+1F5A*/ /**/
+  0x1F53, /*U+1F5B*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA*/
+  0x1F5C, /*U+1F5C*/ /**/
+  0x1F55, /*U+1F5D*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA*/
+  0x1F5E, /*U+1F5E*/ /**/
+  0x1F57, /*U+1F5F*/ /*GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI*/
+  0x1F60, /*U+1F60*/ /**/
+  0x1F61, /*U+1F61*/ /**/
+  0x1F62, /*U+1F62*/ /**/
+  0x1F63, /*U+1F63*/ /**/
+  0x1F64, /*U+1F64*/ /**/
+  0x1F65, /*U+1F65*/ /**/
+  0x1F66, /*U+1F66*/ /**/
+  0x1F67, /*U+1F67*/ /**/
+  0x1F60, /*U+1F68*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI*/
+  0x1F61, /*U+1F69*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA*/
+  0x1F62, /*U+1F6A*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA*/
+  0x1F63, /*U+1F6B*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA*/
+  0x1F64, /*U+1F6C*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA*/
+  0x1F65, /*U+1F6D*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA*/
+  0x1F66, /*U+1F6E*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI*/
+  0x1F67, /*U+1F6F*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI*/
+  0x1F70, /*U+1F70*/ /**/
+  0x1F71, /*U+1F71*/ /**/
+  0x1F72, /*U+1F72*/ /**/
+  0x1F73, /*U+1F73*/ /**/
+  0x1F74, /*U+1F74*/ /**/
+  0x1F75, /*U+1F75*/ /**/
+  0x1F76, /*U+1F76*/ /**/
+  0x1F77, /*U+1F77*/ /**/
+  0x1F78, /*U+1F78*/ /**/
+  0x1F79, /*U+1F79*/ /**/
+  0x1F7A, /*U+1F7A*/ /**/
+  0x1F7B, /*U+1F7B*/ /**/
+  0x1F7C, /*U+1F7C*/ /**/
+  0x1F7D, /*U+1F7D*/ /**/
+  0x1F7E, /*U+1F7E*/ /**/
+  0x1F7F, /*U+1F7F*/ /**/
+  0x1F80, /*U+1F80*/ /**/
+  0x1F81, /*U+1F81*/ /**/
+  0x1F82, /*U+1F82*/ /**/
+  0x1F83, /*U+1F83*/ /**/
+  0x1F84, /*U+1F84*/ /**/
+  0x1F85, /*U+1F85*/ /**/
+  0x1F86, /*U+1F86*/ /**/
+  0x1F87, /*U+1F87*/ /**/
+  0x1F80, /*U+1F88*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI*/
+  0x1F81, /*U+1F89*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI*/
+  0x1F82, /*U+1F8A*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/
+  0x1F83, /*U+1F8B*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/
+  0x1F84, /*U+1F8C*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/
+  0x1F85, /*U+1F8D*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/
+  0x1F86, /*U+1F8E*/ /*GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1F87, /*U+1F8F*/ /*GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1F90, /*U+1F90*/ /**/
+  0x1F91, /*U+1F91*/ /**/
+  0x1F92, /*U+1F92*/ /**/
+  0x1F93, /*U+1F93*/ /**/
+  0x1F94, /*U+1F94*/ /**/
+  0x1F95, /*U+1F95*/ /**/
+  0x1F96, /*U+1F96*/ /**/
+  0x1F97, /*U+1F97*/ /**/
+  0x1F90, /*U+1F98*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI*/
+  0x1F91, /*U+1F99*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI*/
+  0x1F92, /*U+1F9A*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/
+  0x1F93, /*U+1F9B*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/
+  0x1F94, /*U+1F9C*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/
+  0x1F95, /*U+1F9D*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/
+  0x1F96, /*U+1F9E*/ /*GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1F97, /*U+1F9F*/ /*GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1FA0, /*U+1FA0*/ /**/
+  0x1FA1, /*U+1FA1*/ /**/
+  0x1FA2, /*U+1FA2*/ /**/
+  0x1FA3, /*U+1FA3*/ /**/
+  0x1FA4, /*U+1FA4*/ /**/
+  0x1FA5, /*U+1FA5*/ /**/
+  0x1FA6, /*U+1FA6*/ /**/
+  0x1FA7, /*U+1FA7*/ /**/
+  0x1FA0, /*U+1FA8*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI*/
+  0x1FA1, /*U+1FA9*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI*/
+  0x1FA2, /*U+1FAA*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI*/
+  0x1FA3, /*U+1FAB*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI*/
+  0x1FA4, /*U+1FAC*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI*/
+  0x1FA5, /*U+1FAD*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI*/
+  0x1FA6, /*U+1FAE*/ /*GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1FA7, /*U+1FAF*/ /*GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI*/
+  0x1FB0, /*U+1FB0*/ /**/
+  0x1FB1, /*U+1FB1*/ /**/
+  0x1FB2, /*U+1FB2*/ /**/
+  0x1FB3, /*U+1FB3*/ /**/
+  0x1FB4, /*U+1FB4*/ /**/
+  0x1FB5, /*U+1FB5*/ /**/
+  0x1FB6, /*U+1FB6*/ /**/
+  0x1FB7, /*U+1FB7*/ /**/
+  0x1FB0, /*U+1FB8*/ /*GREEK CAPITAL LETTER ALPHA WITH VRACHY*/
+  0x1FB1, /*U+1FB9*/ /*GREEK CAPITAL LETTER ALPHA WITH MACRON*/
+  0x1F70, /*U+1FBA*/ /*GREEK CAPITAL LETTER ALPHA WITH VARIA*/
+  0x1F71, /*U+1FBB*/ /*GREEK CAPITAL LETTER ALPHA WITH OXIA*/
+  0x1FB3, /*U+1FBC*/ /*GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI*/
+  0x1FBD, /*U+1FBD*/ /**/
+  0x1FBE, /*U+1FBE*/ /**/
+  0x1FBF, /*U+1FBF*/ /**/
+  0x1FC0, /*U+1FC0*/ /**/
+  0x1FC1, /*U+1FC1*/ /**/
+  0x1FC2, /*U+1FC2*/ /**/
+  0x1FC3, /*U+1FC3*/ /**/
+  0x1FC4, /*U+1FC4*/ /**/
+  0x1FC5, /*U+1FC5*/ /**/
+  0x1FC6, /*U+1FC6*/ /**/
+  0x1FC7, /*U+1FC7*/ /**/
+  0x1F72, /*U+1FC8*/ /*GREEK CAPITAL LETTER EPSILON WITH VARIA*/
+  0x1F73, /*U+1FC9*/ /*GREEK CAPITAL LETTER EPSILON WITH OXIA*/
+  0x1F74, /*U+1FCA*/ /*GREEK CAPITAL LETTER ETA WITH VARIA*/
+  0x1F75, /*U+1FCB*/ /*GREEK CAPITAL LETTER ETA WITH OXIA*/
+  0x1FC3, /*U+1FCC*/ /*GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI*/
+  0x1FCD, /*U+1FCD*/ /**/
+  0x1FCE, /*U+1FCE*/ /**/
+  0x1FCF, /*U+1FCF*/ /**/
+  0x1FD0, /*U+1FD0*/ /**/
+  0x1FD1, /*U+1FD1*/ /**/
+  0x1FD2, /*U+1FD2*/ /**/
+  0x1FD3, /*U+1FD3*/ /**/
+  0x1FD4, /*U+1FD4*/ /**/
+  0x1FD5, /*U+1FD5*/ /**/
+  0x1FD6, /*U+1FD6*/ /**/
+  0x1FD7, /*U+1FD7*/ /**/
+  0x1FD0, /*U+1FD8*/ /*GREEK CAPITAL LETTER IOTA WITH VRACHY*/
+  0x1FD1, /*U+1FD9*/ /*GREEK CAPITAL LETTER IOTA WITH MACRON*/
+  0x1F76, /*U+1FDA*/ /*GREEK CAPITAL LETTER IOTA WITH VARIA*/
+  0x1F77, /*U+1FDB*/ /*GREEK CAPITAL LETTER IOTA WITH OXIA*/
+  0x1FDC, /*U+1FDC*/ /**/
+  0x1FDD, /*U+1FDD*/ /**/
+  0x1FDE, /*U+1FDE*/ /**/
+  0x1FDF, /*U+1FDF*/ /**/
+  0x1FE0, /*U+1FE0*/ /**/
+  0x1FE1, /*U+1FE1*/ /**/
+  0x1FE2, /*U+1FE2*/ /**/
+  0x1FE3, /*U+1FE3*/ /**/
+  0x1FE4, /*U+1FE4*/ /**/
+  0x1FE5, /*U+1FE5*/ /**/
+  0x1FE6, /*U+1FE6*/ /**/
+  0x1FE7, /*U+1FE7*/ /**/
+  0x1FE0, /*U+1FE8*/ /*GREEK CAPITAL LETTER UPSILON WITH VRACHY*/
+  0x1FE1, /*U+1FE9*/ /*GREEK CAPITAL LETTER UPSILON WITH MACRON*/
+  0x1F7A, /*U+1FEA*/ /*GREEK CAPITAL LETTER UPSILON WITH VARIA*/
+  0x1F7B, /*U+1FEB*/ /*GREEK CAPITAL LETTER UPSILON WITH OXIA*/
+  0x1FE5, /*U+1FEC*/ /*GREEK CAPITAL LETTER RHO WITH DASIA*/
+  0x1FED, /*U+1FED*/ /**/
+  0x1FEE, /*U+1FEE*/ /**/
+  0x1FEF, /*U+1FEF*/ /**/
+  0x1FF0, /*U+1FF0*/ /**/
+  0x1FF1, /*U+1FF1*/ /**/
+  0x1FF2, /*U+1FF2*/ /**/
+  0x1FF3, /*U+1FF3*/ /**/
+  0x1FF4, /*U+1FF4*/ /**/
+  0x1FF5, /*U+1FF5*/ /**/
+  0x1FF6, /*U+1FF6*/ /**/
+  0x1FF7, /*U+1FF7*/ /**/
+  0x1F78, /*U+1FF8*/ /*GREEK CAPITAL LETTER OMICRON WITH VARIA*/
+  0x1F79, /*U+1FF9*/ /*GREEK CAPITAL LETTER OMICRON WITH OXIA*/
+  0x1F7C, /*U+1FFA*/ /*GREEK CAPITAL LETTER OMEGA WITH VARIA*/
+  0x1F7D, /*U+1FFB*/ /*GREEK CAPITAL LETTER OMEGA WITH OXIA*/
+  0x1FF3, /*U+1FFC*/ /*GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI*/
+  0x1FFD, /*U+1FFD*/ /**/
+  0x1FFE, /*U+1FFE*/ /**/
+  0x1FFF, /*U+1FFF*/ /**/
+};
+
+static const u_int16_t lower_table_6[192] = {
+  0x2100, /*U+2100*/ /**/
+  0x2101, /*U+2101*/ /**/
+  0x2102, /*U+2102*/ /**/
+  0x2103, /*U+2103*/ /**/
+  0x2104, /*U+2104*/ /**/
+  0x2105, /*U+2105*/ /**/
+  0x2106, /*U+2106*/ /**/
+  0x2107, /*U+2107*/ /**/
+  0x2108, /*U+2108*/ /**/
+  0x2109, /*U+2109*/ /**/
+  0x210A, /*U+210A*/ /**/
+  0x210B, /*U+210B*/ /**/
+  0x210C, /*U+210C*/ /**/
+  0x210D, /*U+210D*/ /**/
+  0x210E, /*U+210E*/ /**/
+  0x210F, /*U+210F*/ /**/
+  0x2110, /*U+2110*/ /**/
+  0x2111, /*U+2111*/ /**/
+  0x2112, /*U+2112*/ /**/
+  0x2113, /*U+2113*/ /**/
+  0x2114, /*U+2114*/ /**/
+  0x2115, /*U+2115*/ /**/
+  0x2116, /*U+2116*/ /**/
+  0x2117, /*U+2117*/ /**/
+  0x2118, /*U+2118*/ /**/
+  0x2119, /*U+2119*/ /**/
+  0x211A, /*U+211A*/ /**/
+  0x211B, /*U+211B*/ /**/
+  0x211C, /*U+211C*/ /**/
+  0x211D, /*U+211D*/ /**/
+  0x211E, /*U+211E*/ /**/
+  0x211F, /*U+211F*/ /**/
+  0x2120, /*U+2120*/ /**/
+  0x2121, /*U+2121*/ /**/
+  0x2122, /*U+2122*/ /**/
+  0x2123, /*U+2123*/ /**/
+  0x2124, /*U+2124*/ /**/
+  0x2125, /*U+2125*/ /**/
+  0x03C9, /*U+2126*/ /*OHM SIGN*/
+  0x2127, /*U+2127*/ /**/
+  0x2128, /*U+2128*/ /**/
+  0x2129, /*U+2129*/ /**/
+  0x006B, /*U+212A*/ /*KELVIN SIGN*/
+  0x00E5, /*U+212B*/ /*ANGSTROM SIGN*/
+  0x212C, /*U+212C*/ /**/
+  0x212D, /*U+212D*/ /**/
+  0x212E, /*U+212E*/ /**/
+  0x212F, /*U+212F*/ /**/
+  0x2130, /*U+2130*/ /**/
+  0x2131, /*U+2131*/ /**/
+  0x214E, /*U+2132*/ /*TURNED CAPITAL F*/
+  0x2133, /*U+2133*/ /**/
+  0x2134, /*U+2134*/ /**/
+  0x2135, /*U+2135*/ /**/
+  0x2136, /*U+2136*/ /**/
+  0x2137, /*U+2137*/ /**/
+  0x2138, /*U+2138*/ /**/
+  0x2139, /*U+2139*/ /**/
+  0x213A, /*U+213A*/ /**/
+  0x213B, /*U+213B*/ /**/
+  0x213C, /*U+213C*/ /**/
+  0x213D, /*U+213D*/ /**/
+  0x213E, /*U+213E*/ /**/
+  0x213F, /*U+213F*/ /**/
+  0x2140, /*U+2140*/ /**/
+  0x2141, /*U+2141*/ /**/
+  0x2142, /*U+2142*/ /**/
+  0x2143, /*U+2143*/ /**/
+  0x2144, /*U+2144*/ /**/
+  0x2145, /*U+2145*/ /**/
+  0x2146, /*U+2146*/ /**/
+  0x2147, /*U+2147*/ /**/
+  0x2148, /*U+2148*/ /**/
+  0x2149, /*U+2149*/ /**/
+  0x214A, /*U+214A*/ /**/
+  0x214B, /*U+214B*/ /**/
+  0x214C, /*U+214C*/ /**/
+  0x214D, /*U+214D*/ /**/
+  0x214E, /*U+214E*/ /**/
+  0x214F, /*U+214F*/ /**/
+  0x2150, /*U+2150*/ /**/
+  0x2151, /*U+2151*/ /**/
+  0x2152, /*U+2152*/ /**/
+  0x2153, /*U+2153*/ /**/
+  0x2154, /*U+2154*/ /**/
+  0x2155, /*U+2155*/ /**/
+  0x2156, /*U+2156*/ /**/
+  0x2157, /*U+2157*/ /**/
+  0x2158, /*U+2158*/ /**/
+  0x2159, /*U+2159*/ /**/
+  0x215A, /*U+215A*/ /**/
+  0x215B, /*U+215B*/ /**/
+  0x215C, /*U+215C*/ /**/
+  0x215D, /*U+215D*/ /**/
+  0x215E, /*U+215E*/ /**/
+  0x215F, /*U+215F*/ /**/
+  0x2170, /*U+2160*/ /*ROMAN NUMERAL ONE*/
+  0x2171, /*U+2161*/ /*ROMAN NUMERAL TWO*/
+  0x2172, /*U+2162*/ /*ROMAN NUMERAL THREE*/
+  0x2173, /*U+2163*/ /*ROMAN NUMERAL FOUR*/
+  0x2174, /*U+2164*/ /*ROMAN NUMERAL FIVE*/
+  0x2175, /*U+2165*/ /*ROMAN NUMERAL SIX*/
+  0x2176, /*U+2166*/ /*ROMAN NUMERAL SEVEN*/
+  0x2177, /*U+2167*/ /*ROMAN NUMERAL EIGHT*/
+  0x2178, /*U+2168*/ /*ROMAN NUMERAL NINE*/
+  0x2179, /*U+2169*/ /*ROMAN NUMERAL TEN*/
+  0x217A, /*U+216A*/ /*ROMAN NUMERAL ELEVEN*/
+  0x217B, /*U+216B*/ /*ROMAN NUMERAL TWELVE*/
+  0x217C, /*U+216C*/ /*ROMAN NUMERAL FIFTY*/
+  0x217D, /*U+216D*/ /*ROMAN NUMERAL ONE HUNDRED*/
+  0x217E, /*U+216E*/ /*ROMAN NUMERAL FIVE HUNDRED*/
+  0x217F, /*U+216F*/ /*ROMAN NUMERAL ONE THOUSAND*/
+  0x2170, /*U+2170*/ /**/
+  0x2171, /*U+2171*/ /**/
+  0x2172, /*U+2172*/ /**/
+  0x2173, /*U+2173*/ /**/
+  0x2174, /*U+2174*/ /**/
+  0x2175, /*U+2175*/ /**/
+  0x2176, /*U+2176*/ /**/
+  0x2177, /*U+2177*/ /**/
+  0x2178, /*U+2178*/ /**/
+  0x2179, /*U+2179*/ /**/
+  0x217A, /*U+217A*/ /**/
+  0x217B, /*U+217B*/ /**/
+  0x217C, /*U+217C*/ /**/
+  0x217D, /*U+217D*/ /**/
+  0x217E, /*U+217E*/ /**/
+  0x217F, /*U+217F*/ /**/
+  0x2180, /*U+2180*/ /**/
+  0x2181, /*U+2181*/ /**/
+  0x2182, /*U+2182*/ /**/
+  0x2184, /*U+2183*/ /*ROMAN NUMERAL REVERSED ONE HUNDRED*/
+  0x2184, /*U+2184*/ /**/
+  0x2185, /*U+2185*/ /**/
+  0x2186, /*U+2186*/ /**/
+  0x2187, /*U+2187*/ /**/
+  0x2188, /*U+2188*/ /**/
+  0x2189, /*U+2189*/ /**/
+  0x218A, /*U+218A*/ /**/
+  0x218B, /*U+218B*/ /**/
+  0x218C, /*U+218C*/ /**/
+  0x218D, /*U+218D*/ /**/
+  0x218E, /*U+218E*/ /**/
+  0x218F, /*U+218F*/ /**/
+  0x2190, /*U+2190*/ /**/
+  0x2191, /*U+2191*/ /**/
+  0x2192, /*U+2192*/ /**/
+  0x2193, /*U+2193*/ /**/
+  0x2194, /*U+2194*/ /**/
+  0x2195, /*U+2195*/ /**/
+  0x2196, /*U+2196*/ /**/
+  0x2197, /*U+2197*/ /**/
+  0x2198, /*U+2198*/ /**/
+  0x2199, /*U+2199*/ /**/
+  0x219A, /*U+219A*/ /**/
+  0x219B, /*U+219B*/ /**/
+  0x219C, /*U+219C*/ /**/
+  0x219D, /*U+219D*/ /**/
+  0x219E, /*U+219E*/ /**/
+  0x219F, /*U+219F*/ /**/
+  0x21A0, /*U+21A0*/ /**/
+  0x21A1, /*U+21A1*/ /**/
+  0x21A2, /*U+21A2*/ /**/
+  0x21A3, /*U+21A3*/ /**/
+  0x21A4, /*U+21A4*/ /**/
+  0x21A5, /*U+21A5*/ /**/
+  0x21A6, /*U+21A6*/ /**/
+  0x21A7, /*U+21A7*/ /**/
+  0x21A8, /*U+21A8*/ /**/
+  0x21A9, /*U+21A9*/ /**/
+  0x21AA, /*U+21AA*/ /**/
+  0x21AB, /*U+21AB*/ /**/
+  0x21AC, /*U+21AC*/ /**/
+  0x21AD, /*U+21AD*/ /**/
+  0x21AE, /*U+21AE*/ /**/
+  0x21AF, /*U+21AF*/ /**/
+  0x21B0, /*U+21B0*/ /**/
+  0x21B1, /*U+21B1*/ /**/
+  0x21B2, /*U+21B2*/ /**/
+  0x21B3, /*U+21B3*/ /**/
+  0x21B4, /*U+21B4*/ /**/
+  0x21B5, /*U+21B5*/ /**/
+  0x21B6, /*U+21B6*/ /**/
+  0x21B7, /*U+21B7*/ /**/
+  0x21B8, /*U+21B8*/ /**/
+  0x21B9, /*U+21B9*/ /**/
+  0x21BA, /*U+21BA*/ /**/
+  0x21BB, /*U+21BB*/ /**/
+  0x21BC, /*U+21BC*/ /**/
+  0x21BD, /*U+21BD*/ /**/
+  0x21BE, /*U+21BE*/ /**/
+  0x21BF, /*U+21BF*/ /**/
+};
+
+static const u_int16_t lower_table_7[128] = {
+  0x2480, /*U+2480*/ /**/
+  0x2481, /*U+2481*/ /**/
+  0x2482, /*U+2482*/ /**/
+  0x2483, /*U+2483*/ /**/
+  0x2484, /*U+2484*/ /**/
+  0x2485, /*U+2485*/ /**/
+  0x2486, /*U+2486*/ /**/
+  0x2487, /*U+2487*/ /**/
+  0x2488, /*U+2488*/ /**/
+  0x2489, /*U+2489*/ /**/
+  0x248A, /*U+248A*/ /**/
+  0x248B, /*U+248B*/ /**/
+  0x248C, /*U+248C*/ /**/
+  0x248D, /*U+248D*/ /**/
+  0x248E, /*U+248E*/ /**/
+  0x248F, /*U+248F*/ /**/
+  0x2490, /*U+2490*/ /**/
+  0x2491, /*U+2491*/ /**/
+  0x2492, /*U+2492*/ /**/
+  0x2493, /*U+2493*/ /**/
+  0x2494, /*U+2494*/ /**/
+  0x2495, /*U+2495*/ /**/
+  0x2496, /*U+2496*/ /**/
+  0x2497, /*U+2497*/ /**/
+  0x2498, /*U+2498*/ /**/
+  0x2499, /*U+2499*/ /**/
+  0x249A, /*U+249A*/ /**/
+  0x249B, /*U+249B*/ /**/
+  0x249C, /*U+249C*/ /**/
+  0x249D, /*U+249D*/ /**/
+  0x249E, /*U+249E*/ /**/
+  0x249F, /*U+249F*/ /**/
+  0x24A0, /*U+24A0*/ /**/
+  0x24A1, /*U+24A1*/ /**/
+  0x24A2, /*U+24A2*/ /**/
+  0x24A3, /*U+24A3*/ /**/
+  0x24A4, /*U+24A4*/ /**/
+  0x24A5, /*U+24A5*/ /**/
+  0x24A6, /*U+24A6*/ /**/
+  0x24A7, /*U+24A7*/ /**/
+  0x24A8, /*U+24A8*/ /**/
+  0x24A9, /*U+24A9*/ /**/
+  0x24AA, /*U+24AA*/ /**/
+  0x24AB, /*U+24AB*/ /**/
+  0x24AC, /*U+24AC*/ /**/
+  0x24AD, /*U+24AD*/ /**/
+  0x24AE, /*U+24AE*/ /**/
+  0x24AF, /*U+24AF*/ /**/
+  0x24B0, /*U+24B0*/ /**/
+  0x24B1, /*U+24B1*/ /**/
+  0x24B2, /*U+24B2*/ /**/
+  0x24B3, /*U+24B3*/ /**/
+  0x24B4, /*U+24B4*/ /**/
+  0x24B5, /*U+24B5*/ /**/
+  0x24D0, /*U+24B6*/ /*CIRCLED LATIN CAPITAL LETTER A*/
+  0x24D1, /*U+24B7*/ /*CIRCLED LATIN CAPITAL LETTER B*/
+  0x24D2, /*U+24B8*/ /*CIRCLED LATIN CAPITAL LETTER C*/
+  0x24D3, /*U+24B9*/ /*CIRCLED LATIN CAPITAL LETTER D*/
+  0x24D4, /*U+24BA*/ /*CIRCLED LATIN CAPITAL LETTER E*/
+  0x24D5, /*U+24BB*/ /*CIRCLED LATIN CAPITAL LETTER F*/
+  0x24D6, /*U+24BC*/ /*CIRCLED LATIN CAPITAL LETTER G*/
+  0x24D7, /*U+24BD*/ /*CIRCLED LATIN CAPITAL LETTER H*/
+  0x24D8, /*U+24BE*/ /*CIRCLED LATIN CAPITAL LETTER I*/
+  0x24D9, /*U+24BF*/ /*CIRCLED LATIN CAPITAL LETTER J*/
+  0x24DA, /*U+24C0*/ /*CIRCLED LATIN CAPITAL LETTER K*/
+  0x24DB, /*U+24C1*/ /*CIRCLED LATIN CAPITAL LETTER L*/
+  0x24DC, /*U+24C2*/ /*CIRCLED LATIN CAPITAL LETTER M*/
+  0x24DD, /*U+24C3*/ /*CIRCLED LATIN CAPITAL LETTER N*/
+  0x24DE, /*U+24C4*/ /*CIRCLED LATIN CAPITAL LETTER O*/
+  0x24DF, /*U+24C5*/ /*CIRCLED LATIN CAPITAL LETTER P*/
+  0x24E0, /*U+24C6*/ /*CIRCLED LATIN CAPITAL LETTER Q*/
+  0x24E1, /*U+24C7*/ /*CIRCLED LATIN CAPITAL LETTER R*/
+  0x24E2, /*U+24C8*/ /*CIRCLED LATIN CAPITAL LETTER S*/
+  0x24E3, /*U+24C9*/ /*CIRCLED LATIN CAPITAL LETTER T*/
+  0x24E4, /*U+24CA*/ /*CIRCLED LATIN CAPITAL LETTER U*/
+  0x24E5, /*U+24CB*/ /*CIRCLED LATIN CAPITAL LETTER V*/
+  0x24E6, /*U+24CC*/ /*CIRCLED LATIN CAPITAL LETTER W*/
+  0x24E7, /*U+24CD*/ /*CIRCLED LATIN CAPITAL LETTER X*/
+  0x24E8, /*U+24CE*/ /*CIRCLED LATIN CAPITAL LETTER Y*/
+  0x24E9, /*U+24CF*/ /*CIRCLED LATIN CAPITAL LETTER Z*/
+  0x24D0, /*U+24D0*/ /**/
+  0x24D1, /*U+24D1*/ /**/
+  0x24D2, /*U+24D2*/ /**/
+  0x24D3, /*U+24D3*/ /**/
+  0x24D4, /*U+24D4*/ /**/
+  0x24D5, /*U+24D5*/ /**/
+  0x24D6, /*U+24D6*/ /**/
+  0x24D7, /*U+24D7*/ /**/
+  0x24D8, /*U+24D8*/ /**/
+  0x24D9, /*U+24D9*/ /**/
+  0x24DA, /*U+24DA*/ /**/
+  0x24DB, /*U+24DB*/ /**/
+  0x24DC, /*U+24DC*/ /**/
+  0x24DD, /*U+24DD*/ /**/
+  0x24DE, /*U+24DE*/ /**/
+  0x24DF, /*U+24DF*/ /**/
+  0x24E0, /*U+24E0*/ /**/
+  0x24E1, /*U+24E1*/ /**/
+  0x24E2, /*U+24E2*/ /**/
+  0x24E3, /*U+24E3*/ /**/
+  0x24E4, /*U+24E4*/ /**/
+  0x24E5, /*U+24E5*/ /**/
+  0x24E6, /*U+24E6*/ /**/
+  0x24E7, /*U+24E7*/ /**/
+  0x24E8, /*U+24E8*/ /**/
+  0x24E9, /*U+24E9*/ /**/
+  0x24EA, /*U+24EA*/ /**/
+  0x24EB, /*U+24EB*/ /**/
+  0x24EC, /*U+24EC*/ /**/
+  0x24ED, /*U+24ED*/ /**/
+  0x24EE, /*U+24EE*/ /**/
+  0x24EF, /*U+24EF*/ /**/
+  0x24F0, /*U+24F0*/ /**/
+  0x24F1, /*U+24F1*/ /**/
+  0x24F2, /*U+24F2*/ /**/
+  0x24F3, /*U+24F3*/ /**/
+  0x24F4, /*U+24F4*/ /**/
+  0x24F5, /*U+24F5*/ /**/
+  0x24F6, /*U+24F6*/ /**/
+  0x24F7, /*U+24F7*/ /**/
+  0x24F8, /*U+24F8*/ /**/
+  0x24F9, /*U+24F9*/ /**/
+  0x24FA, /*U+24FA*/ /**/
+  0x24FB, /*U+24FB*/ /**/
+  0x24FC, /*U+24FC*/ /**/
+  0x24FD, /*U+24FD*/ /**/
+  0x24FE, /*U+24FE*/ /**/
+  0x24FF, /*U+24FF*/ /**/
+};
+
+static const u_int16_t lower_table_8[256] = {
+  0x2C30, /*U+2C00*/ /*GLAGOLITIC CAPITAL LETTER AZU*/
+  0x2C31, /*U+2C01*/ /*GLAGOLITIC CAPITAL LETTER BUKY*/
+  0x2C32, /*U+2C02*/ /*GLAGOLITIC CAPITAL LETTER VEDE*/
+  0x2C33, /*U+2C03*/ /*GLAGOLITIC CAPITAL LETTER GLAGOLI*/
+  0x2C34, /*U+2C04*/ /*GLAGOLITIC CAPITAL LETTER DOBRO*/
+  0x2C35, /*U+2C05*/ /*GLAGOLITIC CAPITAL LETTER YESTU*/
+  0x2C36, /*U+2C06*/ /*GLAGOLITIC CAPITAL LETTER ZHIVETE*/
+  0x2C37, /*U+2C07*/ /*GLAGOLITIC CAPITAL LETTER DZELO*/
+  0x2C38, /*U+2C08*/ /*GLAGOLITIC CAPITAL LETTER ZEMLJA*/
+  0x2C39, /*U+2C09*/ /*GLAGOLITIC CAPITAL LETTER IZHE*/
+  0x2C3A, /*U+2C0A*/ /*GLAGOLITIC CAPITAL LETTER INITIAL IZHE*/
+  0x2C3B, /*U+2C0B*/ /*GLAGOLITIC CAPITAL LETTER I*/
+  0x2C3C, /*U+2C0C*/ /*GLAGOLITIC CAPITAL LETTER DJERVI*/
+  0x2C3D, /*U+2C0D*/ /*GLAGOLITIC CAPITAL LETTER KAKO*/
+  0x2C3E, /*U+2C0E*/ /*GLAGOLITIC CAPITAL LETTER LJUDIJE*/
+  0x2C3F, /*U+2C0F*/ /*GLAGOLITIC CAPITAL LETTER MYSLITE*/
+  0x2C40, /*U+2C10*/ /*GLAGOLITIC CAPITAL LETTER NASHI*/
+  0x2C41, /*U+2C11*/ /*GLAGOLITIC CAPITAL LETTER ONU*/
+  0x2C42, /*U+2C12*/ /*GLAGOLITIC CAPITAL LETTER POKOJI*/
+  0x2C43, /*U+2C13*/ /*GLAGOLITIC CAPITAL LETTER RITSI*/
+  0x2C44, /*U+2C14*/ /*GLAGOLITIC CAPITAL LETTER SLOVO*/
+  0x2C45, /*U+2C15*/ /*GLAGOLITIC CAPITAL LETTER TVRIDO*/
+  0x2C46, /*U+2C16*/ /*GLAGOLITIC CAPITAL LETTER UKU*/
+  0x2C47, /*U+2C17*/ /*GLAGOLITIC CAPITAL LETTER FRITU*/
+  0x2C48, /*U+2C18*/ /*GLAGOLITIC CAPITAL LETTER HERU*/
+  0x2C49, /*U+2C19*/ /*GLAGOLITIC CAPITAL LETTER OTU*/
+  0x2C4A, /*U+2C1A*/ /*GLAGOLITIC CAPITAL LETTER PE*/
+  0x2C4B, /*U+2C1B*/ /*GLAGOLITIC CAPITAL LETTER SHTA*/
+  0x2C4C, /*U+2C1C*/ /*GLAGOLITIC CAPITAL LETTER TSI*/
+  0x2C4D, /*U+2C1D*/ /*GLAGOLITIC CAPITAL LETTER CHRIVI*/
+  0x2C4E, /*U+2C1E*/ /*GLAGOLITIC CAPITAL LETTER SHA*/
+  0x2C4F, /*U+2C1F*/ /*GLAGOLITIC CAPITAL LETTER YERU*/
+  0x2C50, /*U+2C20*/ /*GLAGOLITIC CAPITAL LETTER YERI*/
+  0x2C51, /*U+2C21*/ /*GLAGOLITIC CAPITAL LETTER YATI*/
+  0x2C52, /*U+2C22*/ /*GLAGOLITIC CAPITAL LETTER SPIDERY HA*/
+  0x2C53, /*U+2C23*/ /*GLAGOLITIC CAPITAL LETTER YU*/
+  0x2C54, /*U+2C24*/ /*GLAGOLITIC CAPITAL LETTER SMALL YUS*/
+  0x2C55, /*U+2C25*/ /*GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL*/
+  0x2C56, /*U+2C26*/ /*GLAGOLITIC CAPITAL LETTER YO*/
+  0x2C57, /*U+2C27*/ /*GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS*/
+  0x2C58, /*U+2C28*/ /*GLAGOLITIC CAPITAL LETTER BIG YUS*/
+  0x2C59, /*U+2C29*/ /*GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS*/
+  0x2C5A, /*U+2C2A*/ /*GLAGOLITIC CAPITAL LETTER FITA*/
+  0x2C5B, /*U+2C2B*/ /*GLAGOLITIC CAPITAL LETTER IZHITSA*/
+  0x2C5C, /*U+2C2C*/ /*GLAGOLITIC CAPITAL LETTER SHTAPIC*/
+  0x2C5D, /*U+2C2D*/ /*GLAGOLITIC CAPITAL LETTER TROKUTASTI A*/
+  0x2C5E, /*U+2C2E*/ /*GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE*/
+  0x2C2F, /*U+2C2F*/ /**/
+  0x2C30, /*U+2C30*/ /**/
+  0x2C31, /*U+2C31*/ /**/
+  0x2C32, /*U+2C32*/ /**/
+  0x2C33, /*U+2C33*/ /**/
+  0x2C34, /*U+2C34*/ /**/
+  0x2C35, /*U+2C35*/ /**/
+  0x2C36, /*U+2C36*/ /**/
+  0x2C37, /*U+2C37*/ /**/
+  0x2C38, /*U+2C38*/ /**/
+  0x2C39, /*U+2C39*/ /**/
+  0x2C3A, /*U+2C3A*/ /**/
+  0x2C3B, /*U+2C3B*/ /**/
+  0x2C3C, /*U+2C3C*/ /**/
+  0x2C3D, /*U+2C3D*/ /**/
+  0x2C3E, /*U+2C3E*/ /**/
+  0x2C3F, /*U+2C3F*/ /**/
+  0x2C40, /*U+2C40*/ /**/
+  0x2C41, /*U+2C41*/ /**/
+  0x2C42, /*U+2C42*/ /**/
+  0x2C43, /*U+2C43*/ /**/
+  0x2C44, /*U+2C44*/ /**/
+  0x2C45, /*U+2C45*/ /**/
+  0x2C46, /*U+2C46*/ /**/
+  0x2C47, /*U+2C47*/ /**/
+  0x2C48, /*U+2C48*/ /**/
+  0x2C49, /*U+2C49*/ /**/
+  0x2C4A, /*U+2C4A*/ /**/
+  0x2C4B, /*U+2C4B*/ /**/
+  0x2C4C, /*U+2C4C*/ /**/
+  0x2C4D, /*U+2C4D*/ /**/
+  0x2C4E, /*U+2C4E*/ /**/
+  0x2C4F, /*U+2C4F*/ /**/
+  0x2C50, /*U+2C50*/ /**/
+  0x2C51, /*U+2C51*/ /**/
+  0x2C52, /*U+2C52*/ /**/
+  0x2C53, /*U+2C53*/ /**/
+  0x2C54, /*U+2C54*/ /**/
+  0x2C55, /*U+2C55*/ /**/
+  0x2C56, /*U+2C56*/ /**/
+  0x2C57, /*U+2C57*/ /**/
+  0x2C58, /*U+2C58*/ /**/
+  0x2C59, /*U+2C59*/ /**/
+  0x2C5A, /*U+2C5A*/ /**/
+  0x2C5B, /*U+2C5B*/ /**/
+  0x2C5C, /*U+2C5C*/ /**/
+  0x2C5D, /*U+2C5D*/ /**/
+  0x2C5E, /*U+2C5E*/ /**/
+  0x2C5F, /*U+2C5F*/ /**/
+  0x2C61, /*U+2C60*/ /*LATIN CAPITAL LETTER L WITH DOUBLE BAR*/
+  0x2C61, /*U+2C61*/ /**/
+  0x026B, /*U+2C62*/ /*LATIN CAPITAL LETTER L WITH MIDDLE TILDE*/
+  0x1D7D, /*U+2C63*/ /*LATIN CAPITAL LETTER P WITH STROKE*/
+  0x027D, /*U+2C64*/ /*LATIN CAPITAL LETTER R WITH TAIL*/
+  0x2C65, /*U+2C65*/ /**/
+  0x2C66, /*U+2C66*/ /**/
+  0x2C68, /*U+2C67*/ /*LATIN CAPITAL LETTER H WITH DESCENDER*/
+  0x2C68, /*U+2C68*/ /**/
+  0x2C6A, /*U+2C69*/ /*LATIN CAPITAL LETTER K WITH DESCENDER*/
+  0x2C6A, /*U+2C6A*/ /**/
+  0x2C6C, /*U+2C6B*/ /*LATIN CAPITAL LETTER Z WITH DESCENDER*/
+  0x2C6C, /*U+2C6C*/ /**/
+  0x0251, /*U+2C6D*/ /*LATIN CAPITAL LETTER ALPHA*/
+  0x0271, /*U+2C6E*/ /*LATIN CAPITAL LETTER M WITH HOOK*/
+  0x0250, /*U+2C6F*/ /*LATIN CAPITAL LETTER TURNED A*/
+  0x0252, /*U+2C70*/ /*LATIN CAPITAL LETTER TURNED ALPHA*/
+  0x2C71, /*U+2C71*/ /**/
+  0x2C73, /*U+2C72*/ /*LATIN CAPITAL LETTER W WITH HOOK*/
+  0x2C73, /*U+2C73*/ /**/
+  0x2C74, /*U+2C74*/ /**/
+  0x2C76, /*U+2C75*/ /*LATIN CAPITAL LETTER HALF H*/
+  0x2C76, /*U+2C76*/ /**/
+  0x2C77, /*U+2C77*/ /**/
+  0x2C78, /*U+2C78*/ /**/
+  0x2C79, /*U+2C79*/ /**/
+  0x2C7A, /*U+2C7A*/ /**/
+  0x2C7B, /*U+2C7B*/ /**/
+  0x2C7C, /*U+2C7C*/ /**/
+  0x2C7D, /*U+2C7D*/ /**/
+  0x023F, /*U+2C7E*/ /*LATIN CAPITAL LETTER S WITH SWASH TAIL*/
+  0x0240, /*U+2C7F*/ /*LATIN CAPITAL LETTER Z WITH SWASH TAIL*/
+  0x2C81, /*U+2C80*/ /*COPTIC CAPITAL LETTER ALFA*/
+  0x2C81, /*U+2C81*/ /**/
+  0x2C83, /*U+2C82*/ /*COPTIC CAPITAL LETTER VIDA*/
+  0x2C83, /*U+2C83*/ /**/
+  0x2C85, /*U+2C84*/ /*COPTIC CAPITAL LETTER GAMMA*/
+  0x2C85, /*U+2C85*/ /**/
+  0x2C87, /*U+2C86*/ /*COPTIC CAPITAL LETTER DALDA*/
+  0x2C87, /*U+2C87*/ /**/
+  0x2C89, /*U+2C88*/ /*COPTIC CAPITAL LETTER EIE*/
+  0x2C89, /*U+2C89*/ /**/
+  0x2C8B, /*U+2C8A*/ /*COPTIC CAPITAL LETTER SOU*/
+  0x2C8B, /*U+2C8B*/ /**/
+  0x2C8D, /*U+2C8C*/ /*COPTIC CAPITAL LETTER ZATA*/
+  0x2C8D, /*U+2C8D*/ /**/
+  0x2C8F, /*U+2C8E*/ /*COPTIC CAPITAL LETTER HATE*/
+  0x2C8F, /*U+2C8F*/ /**/
+  0x2C91, /*U+2C90*/ /*COPTIC CAPITAL LETTER THETHE*/
+  0x2C91, /*U+2C91*/ /**/
+  0x2C93, /*U+2C92*/ /*COPTIC CAPITAL LETTER IAUDA*/
+  0x2C93, /*U+2C93*/ /**/
+  0x2C95, /*U+2C94*/ /*COPTIC CAPITAL LETTER KAPA*/
+  0x2C95, /*U+2C95*/ /**/
+  0x2C97, /*U+2C96*/ /*COPTIC CAPITAL LETTER LAULA*/
+  0x2C97, /*U+2C97*/ /**/
+  0x2C99, /*U+2C98*/ /*COPTIC CAPITAL LETTER MI*/
+  0x2C99, /*U+2C99*/ /**/
+  0x2C9B, /*U+2C9A*/ /*COPTIC CAPITAL LETTER NI*/
+  0x2C9B, /*U+2C9B*/ /**/
+  0x2C9D, /*U+2C9C*/ /*COPTIC CAPITAL LETTER KSI*/
+  0x2C9D, /*U+2C9D*/ /**/
+  0x2C9F, /*U+2C9E*/ /*COPTIC CAPITAL LETTER O*/
+  0x2C9F, /*U+2C9F*/ /**/
+  0x2CA1, /*U+2CA0*/ /*COPTIC CAPITAL LETTER PI*/
+  0x2CA1, /*U+2CA1*/ /**/
+  0x2CA3, /*U+2CA2*/ /*COPTIC CAPITAL LETTER RO*/
+  0x2CA3, /*U+2CA3*/ /**/
+  0x2CA5, /*U+2CA4*/ /*COPTIC CAPITAL LETTER SIMA*/
+  0x2CA5, /*U+2CA5*/ /**/
+  0x2CA7, /*U+2CA6*/ /*COPTIC CAPITAL LETTER TAU*/
+  0x2CA7, /*U+2CA7*/ /**/
+  0x2CA9, /*U+2CA8*/ /*COPTIC CAPITAL LETTER UA*/
+  0x2CA9, /*U+2CA9*/ /**/
+  0x2CAB, /*U+2CAA*/ /*COPTIC CAPITAL LETTER FI*/
+  0x2CAB, /*U+2CAB*/ /**/
+  0x2CAD, /*U+2CAC*/ /*COPTIC CAPITAL LETTER KHI*/
+  0x2CAD, /*U+2CAD*/ /**/
+  0x2CAF, /*U+2CAE*/ /*COPTIC CAPITAL LETTER PSI*/
+  0x2CAF, /*U+2CAF*/ /**/
+  0x2CB1, /*U+2CB0*/ /*COPTIC CAPITAL LETTER OOU*/
+  0x2CB1, /*U+2CB1*/ /**/
+  0x2CB3, /*U+2CB2*/ /*COPTIC CAPITAL LETTER DIALECT-P ALEF*/
+  0x2CB3, /*U+2CB3*/ /**/
+  0x2CB5, /*U+2CB4*/ /*COPTIC CAPITAL LETTER OLD COPTIC AIN*/
+  0x2CB5, /*U+2CB5*/ /**/
+  0x2CB7, /*U+2CB6*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE*/
+  0x2CB7, /*U+2CB7*/ /**/
+  0x2CB9, /*U+2CB8*/ /*COPTIC CAPITAL LETTER DIALECT-P KAPA*/
+  0x2CB9, /*U+2CB9*/ /**/
+  0x2CBB, /*U+2CBA*/ /*COPTIC CAPITAL LETTER DIALECT-P NI*/
+  0x2CBB, /*U+2CBB*/ /**/
+  0x2CBD, /*U+2CBC*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI*/
+  0x2CBD, /*U+2CBD*/ /**/
+  0x2CBF, /*U+2CBE*/ /*COPTIC CAPITAL LETTER OLD COPTIC OOU*/
+  0x2CBF, /*U+2CBF*/ /**/
+  0x2CC1, /*U+2CC0*/ /*COPTIC CAPITAL LETTER SAMPI*/
+  0x2CC1, /*U+2CC1*/ /**/
+  0x2CC3, /*U+2CC2*/ /*COPTIC CAPITAL LETTER CROSSED SHEI*/
+  0x2CC3, /*U+2CC3*/ /**/
+  0x2CC5, /*U+2CC4*/ /*COPTIC CAPITAL LETTER OLD COPTIC SHEI*/
+  0x2CC5, /*U+2CC5*/ /**/
+  0x2CC7, /*U+2CC6*/ /*COPTIC CAPITAL LETTER OLD COPTIC ESH*/
+  0x2CC7, /*U+2CC7*/ /**/
+  0x2CC9, /*U+2CC8*/ /*COPTIC CAPITAL LETTER AKHMIMIC KHEI*/
+  0x2CC9, /*U+2CC9*/ /**/
+  0x2CCB, /*U+2CCA*/ /*COPTIC CAPITAL LETTER DIALECT-P HORI*/
+  0x2CCB, /*U+2CCB*/ /**/
+  0x2CCD, /*U+2CCC*/ /*COPTIC CAPITAL LETTER OLD COPTIC HORI*/
+  0x2CCD, /*U+2CCD*/ /**/
+  0x2CCF, /*U+2CCE*/ /*COPTIC CAPITAL LETTER OLD COPTIC HA*/
+  0x2CCF, /*U+2CCF*/ /**/
+  0x2CD1, /*U+2CD0*/ /*COPTIC CAPITAL LETTER L-SHAPED HA*/
+  0x2CD1, /*U+2CD1*/ /**/
+  0x2CD3, /*U+2CD2*/ /*COPTIC CAPITAL LETTER OLD COPTIC HEI*/
+  0x2CD3, /*U+2CD3*/ /**/
+  0x2CD5, /*U+2CD4*/ /*COPTIC CAPITAL LETTER OLD COPTIC HAT*/
+  0x2CD5, /*U+2CD5*/ /**/
+  0x2CD7, /*U+2CD6*/ /*COPTIC CAPITAL LETTER OLD COPTIC GANGIA*/
+  0x2CD7, /*U+2CD7*/ /**/
+  0x2CD9, /*U+2CD8*/ /*COPTIC CAPITAL LETTER OLD COPTIC DJA*/
+  0x2CD9, /*U+2CD9*/ /**/
+  0x2CDB, /*U+2CDA*/ /*COPTIC CAPITAL LETTER OLD COPTIC SHIMA*/
+  0x2CDB, /*U+2CDB*/ /**/
+  0x2CDD, /*U+2CDC*/ /*COPTIC CAPITAL LETTER OLD NUBIAN SHIMA*/
+  0x2CDD, /*U+2CDD*/ /**/
+  0x2CDF, /*U+2CDE*/ /*COPTIC CAPITAL LETTER OLD NUBIAN NGI*/
+  0x2CDF, /*U+2CDF*/ /**/
+  0x2CE1, /*U+2CE0*/ /*COPTIC CAPITAL LETTER OLD NUBIAN NYI*/
+  0x2CE1, /*U+2CE1*/ /**/
+  0x2CE3, /*U+2CE2*/ /*COPTIC CAPITAL LETTER OLD NUBIAN WAU*/
+  0x2CE3, /*U+2CE3*/ /**/
+  0x2CE4, /*U+2CE4*/ /**/
+  0x2CE5, /*U+2CE5*/ /**/
+  0x2CE6, /*U+2CE6*/ /**/
+  0x2CE7, /*U+2CE7*/ /**/
+  0x2CE8, /*U+2CE8*/ /**/
+  0x2CE9, /*U+2CE9*/ /**/
+  0x2CEA, /*U+2CEA*/ /**/
+  0x2CEC, /*U+2CEB*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI*/
+  0x2CEC, /*U+2CEC*/ /**/
+  0x2CEE, /*U+2CED*/ /*COPTIC CAPITAL LETTER CRYPTOGRAMMIC GANGIA*/
+  0x2CEE, /*U+2CEE*/ /**/
+  0x2CEF, /*U+2CEF*/ /**/
+  0x2CF0, /*U+2CF0*/ /**/
+  0x2CF1, /*U+2CF1*/ /**/
+  0x2CF2, /*U+2CF2*/ /**/
+  0x2CF3, /*U+2CF3*/ /**/
+  0x2CF4, /*U+2CF4*/ /**/
+  0x2CF5, /*U+2CF5*/ /**/
+  0x2CF6, /*U+2CF6*/ /**/
+  0x2CF7, /*U+2CF7*/ /**/
+  0x2CF8, /*U+2CF8*/ /**/
+  0x2CF9, /*U+2CF9*/ /**/
+  0x2CFA, /*U+2CFA*/ /**/
+  0x2CFB, /*U+2CFB*/ /**/
+  0x2CFC, /*U+2CFC*/ /**/
+  0x2CFD, /*U+2CFD*/ /**/
+  0x2CFE, /*U+2CFE*/ /**/
+  0x2CFF, /*U+2CFF*/ /**/
+};
+
+static const u_int16_t lower_table_9[128] = {
+  0xA641, /*U+A640*/ /*CYRILLIC CAPITAL LETTER ZEMLYA*/
+  0xA641, /*U+A641*/ /**/
+  0xA643, /*U+A642*/ /*CYRILLIC CAPITAL LETTER DZELO*/
+  0xA643, /*U+A643*/ /**/
+  0xA645, /*U+A644*/ /*CYRILLIC CAPITAL LETTER REVERSED DZE*/
+  0xA645, /*U+A645*/ /**/
+  0xA647, /*U+A646*/ /*CYRILLIC CAPITAL LETTER IOTA*/
+  0xA647, /*U+A647*/ /**/
+  0xA649, /*U+A648*/ /*CYRILLIC CAPITAL LETTER DJERV*/
+  0xA649, /*U+A649*/ /**/
+  0xA64B, /*U+A64A*/ /*CYRILLIC CAPITAL LETTER MONOGRAPH UK*/
+  0xA64B, /*U+A64B*/ /**/
+  0xA64D, /*U+A64C*/ /*CYRILLIC CAPITAL LETTER BROAD OMEGA*/
+  0xA64D, /*U+A64D*/ /**/
+  0xA64F, /*U+A64E*/ /*CYRILLIC CAPITAL LETTER NEUTRAL YER*/
+  0xA64F, /*U+A64F*/ /**/
+  0xA651, /*U+A650*/ /*CYRILLIC CAPITAL LETTER YERU WITH BACK YER*/
+  0xA651, /*U+A651*/ /**/
+  0xA653, /*U+A652*/ /*CYRILLIC CAPITAL LETTER IOTIFIED YAT*/
+  0xA653, /*U+A653*/ /**/
+  0xA655, /*U+A654*/ /*CYRILLIC CAPITAL LETTER REVERSED YU*/
+  0xA655, /*U+A655*/ /**/
+  0xA657, /*U+A656*/ /*CYRILLIC CAPITAL LETTER IOTIFIED A*/
+  0xA657, /*U+A657*/ /**/
+  0xA659, /*U+A658*/ /*CYRILLIC CAPITAL LETTER CLOSED LITTLE YUS*/
+  0xA659, /*U+A659*/ /**/
+  0xA65B, /*U+A65A*/ /*CYRILLIC CAPITAL LETTER BLENDED YUS*/
+  0xA65B, /*U+A65B*/ /**/
+  0xA65D, /*U+A65C*/ /*CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS*/
+  0xA65D, /*U+A65D*/ /**/
+  0xA65F, /*U+A65E*/ /*CYRILLIC CAPITAL LETTER YN*/
+  0xA65F, /*U+A65F*/ /**/
+  0xA661, /*U+A660*/ /*CYRILLIC CAPITAL LETTER REVERSED TSE*/
+  0xA661, /*U+A661*/ /**/
+  0xA663, /*U+A662*/ /*CYRILLIC CAPITAL LETTER SOFT DE*/
+  0xA663, /*U+A663*/ /**/
+  0xA665, /*U+A664*/ /*CYRILLIC CAPITAL LETTER SOFT EL*/
+  0xA665, /*U+A665*/ /**/
+  0xA667, /*U+A666*/ /*CYRILLIC CAPITAL LETTER SOFT EM*/
+  0xA667, /*U+A667*/ /**/
+  0xA669, /*U+A668*/ /*CYRILLIC CAPITAL LETTER MONOCULAR O*/
+  0xA669, /*U+A669*/ /**/
+  0xA66B, /*U+A66A*/ /*CYRILLIC CAPITAL LETTER BINOCULAR O*/
+  0xA66B, /*U+A66B*/ /**/
+  0xA66D, /*U+A66C*/ /*CYRILLIC CAPITAL LETTER DOUBLE MONOCULAR O*/
+  0xA66D, /*U+A66D*/ /**/
+  0xA66E, /*U+A66E*/ /**/
+  0xA66F, /*U+A66F*/ /**/
+  0xA670, /*U+A670*/ /**/
+  0xA671, /*U+A671*/ /**/
+  0xA672, /*U+A672*/ /**/
+  0xA673, /*U+A673*/ /**/
+  0xA674, /*U+A674*/ /**/
+  0xA675, /*U+A675*/ /**/
+  0xA676, /*U+A676*/ /**/
+  0xA677, /*U+A677*/ /**/
+  0xA678, /*U+A678*/ /**/
+  0xA679, /*U+A679*/ /**/
+  0xA67A, /*U+A67A*/ /**/
+  0xA67B, /*U+A67B*/ /**/
+  0xA67C, /*U+A67C*/ /**/
+  0xA67D, /*U+A67D*/ /**/
+  0xA67E, /*U+A67E*/ /**/
+  0xA67F, /*U+A67F*/ /**/
+  0xA681, /*U+A680*/ /*CYRILLIC CAPITAL LETTER DWE*/
+  0xA681, /*U+A681*/ /**/
+  0xA683, /*U+A682*/ /*CYRILLIC CAPITAL LETTER DZWE*/
+  0xA683, /*U+A683*/ /**/
+  0xA685, /*U+A684*/ /*CYRILLIC CAPITAL LETTER ZHWE*/
+  0xA685, /*U+A685*/ /**/
+  0xA687, /*U+A686*/ /*CYRILLIC CAPITAL LETTER CCHE*/
+  0xA687, /*U+A687*/ /**/
+  0xA689, /*U+A688*/ /*CYRILLIC CAPITAL LETTER DZZE*/
+  0xA689, /*U+A689*/ /**/
+  0xA68B, /*U+A68A*/ /*CYRILLIC CAPITAL LETTER TE WITH MIDDLE HOOK*/
+  0xA68B, /*U+A68B*/ /**/
+  0xA68D, /*U+A68C*/ /*CYRILLIC CAPITAL LETTER TWE*/
+  0xA68D, /*U+A68D*/ /**/
+  0xA68F, /*U+A68E*/ /*CYRILLIC CAPITAL LETTER TSWE*/
+  0xA68F, /*U+A68F*/ /**/
+  0xA691, /*U+A690*/ /*CYRILLIC CAPITAL LETTER TSSE*/
+  0xA691, /*U+A691*/ /**/
+  0xA693, /*U+A692*/ /*CYRILLIC CAPITAL LETTER TCHE*/
+  0xA693, /*U+A693*/ /**/
+  0xA695, /*U+A694*/ /*CYRILLIC CAPITAL LETTER HWE*/
+  0xA695, /*U+A695*/ /**/
+  0xA697, /*U+A696*/ /*CYRILLIC CAPITAL LETTER SHWE*/
+  0xA697, /*U+A697*/ /**/
+  0xA698, /*U+A698*/ /**/
+  0xA699, /*U+A699*/ /**/
+  0xA69A, /*U+A69A*/ /**/
+  0xA69B, /*U+A69B*/ /**/
+  0xA69C, /*U+A69C*/ /**/
+  0xA69D, /*U+A69D*/ /**/
+  0xA69E, /*U+A69E*/ /**/
+  0xA69F, /*U+A69F*/ /**/
+  0xA6A0, /*U+A6A0*/ /**/
+  0xA6A1, /*U+A6A1*/ /**/
+  0xA6A2, /*U+A6A2*/ /**/
+  0xA6A3, /*U+A6A3*/ /**/
+  0xA6A4, /*U+A6A4*/ /**/
+  0xA6A5, /*U+A6A5*/ /**/
+  0xA6A6, /*U+A6A6*/ /**/
+  0xA6A7, /*U+A6A7*/ /**/
+  0xA6A8, /*U+A6A8*/ /**/
+  0xA6A9, /*U+A6A9*/ /**/
+  0xA6AA, /*U+A6AA*/ /**/
+  0xA6AB, /*U+A6AB*/ /**/
+  0xA6AC, /*U+A6AC*/ /**/
+  0xA6AD, /*U+A6AD*/ /**/
+  0xA6AE, /*U+A6AE*/ /**/
+  0xA6AF, /*U+A6AF*/ /**/
+  0xA6B0, /*U+A6B0*/ /**/
+  0xA6B1, /*U+A6B1*/ /**/
+  0xA6B2, /*U+A6B2*/ /**/
+  0xA6B3, /*U+A6B3*/ /**/
+  0xA6B4, /*U+A6B4*/ /**/
+  0xA6B5, /*U+A6B5*/ /**/
+  0xA6B6, /*U+A6B6*/ /**/
+  0xA6B7, /*U+A6B7*/ /**/
+  0xA6B8, /*U+A6B8*/ /**/
+  0xA6B9, /*U+A6B9*/ /**/
+  0xA6BA, /*U+A6BA*/ /**/
+  0xA6BB, /*U+A6BB*/ /**/
+  0xA6BC, /*U+A6BC*/ /**/
+  0xA6BD, /*U+A6BD*/ /**/
+  0xA6BE, /*U+A6BE*/ /**/
+  0xA6BF, /*U+A6BF*/ /**/
+};
+
+static const u_int16_t lower_table_10[192] = {
+  0xA700, /*U+A700*/ /**/
+  0xA701, /*U+A701*/ /**/
+  0xA702, /*U+A702*/ /**/
+  0xA703, /*U+A703*/ /**/
+  0xA704, /*U+A704*/ /**/
+  0xA705, /*U+A705*/ /**/
+  0xA706, /*U+A706*/ /**/
+  0xA707, /*U+A707*/ /**/
+  0xA708, /*U+A708*/ /**/
+  0xA709, /*U+A709*/ /**/
+  0xA70A, /*U+A70A*/ /**/
+  0xA70B, /*U+A70B*/ /**/
+  0xA70C, /*U+A70C*/ /**/
+  0xA70D, /*U+A70D*/ /**/
+  0xA70E, /*U+A70E*/ /**/
+  0xA70F, /*U+A70F*/ /**/
+  0xA710, /*U+A710*/ /**/
+  0xA711, /*U+A711*/ /**/
+  0xA712, /*U+A712*/ /**/
+  0xA713, /*U+A713*/ /**/
+  0xA714, /*U+A714*/ /**/
+  0xA715, /*U+A715*/ /**/
+  0xA716, /*U+A716*/ /**/
+  0xA717, /*U+A717*/ /**/
+  0xA718, /*U+A718*/ /**/
+  0xA719, /*U+A719*/ /**/
+  0xA71A, /*U+A71A*/ /**/
+  0xA71B, /*U+A71B*/ /**/
+  0xA71C, /*U+A71C*/ /**/
+  0xA71D, /*U+A71D*/ /**/
+  0xA71E, /*U+A71E*/ /**/
+  0xA71F, /*U+A71F*/ /**/
+  0xA720, /*U+A720*/ /**/
+  0xA721, /*U+A721*/ /**/
+  0xA723, /*U+A722*/ /*LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF*/
+  0xA723, /*U+A723*/ /**/
+  0xA725, /*U+A724*/ /*LATIN CAPITAL LETTER EGYPTOLOGICAL AIN*/
+  0xA725, /*U+A725*/ /**/
+  0xA727, /*U+A726*/ /*LATIN CAPITAL LETTER HENG*/
+  0xA727, /*U+A727*/ /**/
+  0xA729, /*U+A728*/ /*LATIN CAPITAL LETTER TZ*/
+  0xA729, /*U+A729*/ /**/
+  0xA72B, /*U+A72A*/ /*LATIN CAPITAL LETTER TRESILLO*/
+  0xA72B, /*U+A72B*/ /**/
+  0xA72D, /*U+A72C*/ /*LATIN CAPITAL LETTER CUATRILLO*/
+  0xA72D, /*U+A72D*/ /**/
+  0xA72F, /*U+A72E*/ /*LATIN CAPITAL LETTER CUATRILLO WITH COMMA*/
+  0xA72F, /*U+A72F*/ /**/
+  0xA730, /*U+A730*/ /**/
+  0xA731, /*U+A731*/ /**/
+  0xA733, /*U+A732*/ /*LATIN CAPITAL LETTER AA*/
+  0xA733, /*U+A733*/ /**/
+  0xA735, /*U+A734*/ /*LATIN CAPITAL LETTER AO*/
+  0xA735, /*U+A735*/ /**/
+  0xA737, /*U+A736*/ /*LATIN CAPITAL LETTER AU*/
+  0xA737, /*U+A737*/ /**/
+  0xA739, /*U+A738*/ /*LATIN CAPITAL LETTER AV*/
+  0xA739, /*U+A739*/ /**/
+  0xA73B, /*U+A73A*/ /*LATIN CAPITAL LETTER AV WITH HORIZONTAL BAR*/
+  0xA73B, /*U+A73B*/ /**/
+  0xA73D, /*U+A73C*/ /*LATIN CAPITAL LETTER AY*/
+  0xA73D, /*U+A73D*/ /**/
+  0xA73F, /*U+A73E*/ /*LATIN CAPITAL LETTER REVERSED C WITH DOT*/
+  0xA73F, /*U+A73F*/ /**/
+  0xA741, /*U+A740*/ /*LATIN CAPITAL LETTER K WITH STROKE*/
+  0xA741, /*U+A741*/ /**/
+  0xA743, /*U+A742*/ /*LATIN CAPITAL LETTER K WITH DIAGONAL STROKE*/
+  0xA743, /*U+A743*/ /**/
+  0xA745, /*U+A744*/ /*LATIN CAPITAL LETTER K WITH STROKE AND DIAGONAL STROKE*/
+  0xA745, /*U+A745*/ /**/
+  0xA747, /*U+A746*/ /*LATIN CAPITAL LETTER BROKEN L*/
+  0xA747, /*U+A747*/ /**/
+  0xA749, /*U+A748*/ /*LATIN CAPITAL LETTER L WITH HIGH STROKE*/
+  0xA749, /*U+A749*/ /**/
+  0xA74B, /*U+A74A*/ /*LATIN CAPITAL LETTER O WITH LONG STROKE OVERLAY*/
+  0xA74B, /*U+A74B*/ /**/
+  0xA74D, /*U+A74C*/ /*LATIN CAPITAL LETTER O WITH LOOP*/
+  0xA74D, /*U+A74D*/ /**/
+  0xA74F, /*U+A74E*/ /*LATIN CAPITAL LETTER OO*/
+  0xA74F, /*U+A74F*/ /**/
+  0xA751, /*U+A750*/ /*LATIN CAPITAL LETTER P WITH STROKE THROUGH DESCENDER*/
+  0xA751, /*U+A751*/ /**/
+  0xA753, /*U+A752*/ /*LATIN CAPITAL LETTER P WITH FLOURISH*/
+  0xA753, /*U+A753*/ /**/
+  0xA755, /*U+A754*/ /*LATIN CAPITAL LETTER P WITH SQUIRREL TAIL*/
+  0xA755, /*U+A755*/ /**/
+  0xA757, /*U+A756*/ /*LATIN CAPITAL LETTER Q WITH STROKE THROUGH DESCENDER*/
+  0xA757, /*U+A757*/ /**/
+  0xA759, /*U+A758*/ /*LATIN CAPITAL LETTER Q WITH DIAGONAL STROKE*/
+  0xA759, /*U+A759*/ /**/
+  0xA75B, /*U+A75A*/ /*LATIN CAPITAL LETTER R ROTUNDA*/
+  0xA75B, /*U+A75B*/ /**/
+  0xA75D, /*U+A75C*/ /*LATIN CAPITAL LETTER RUM ROTUNDA*/
+  0xA75D, /*U+A75D*/ /**/
+  0xA75F, /*U+A75E*/ /*LATIN CAPITAL LETTER V WITH DIAGONAL STROKE*/
+  0xA75F, /*U+A75F*/ /**/
+  0xA761, /*U+A760*/ /*LATIN CAPITAL LETTER VY*/
+  0xA761, /*U+A761*/ /**/
+  0xA763, /*U+A762*/ /*LATIN CAPITAL LETTER VISIGOTHIC Z*/
+  0xA763, /*U+A763*/ /**/
+  0xA765, /*U+A764*/ /*LATIN CAPITAL LETTER THORN WITH STROKE*/
+  0xA765, /*U+A765*/ /**/
+  0xA767, /*U+A766*/ /*LATIN CAPITAL LETTER THORN WITH STROKE THROUGH DESCENDER*/
+  0xA767, /*U+A767*/ /**/
+  0xA769, /*U+A768*/ /*LATIN CAPITAL LETTER VEND*/
+  0xA769, /*U+A769*/ /**/
+  0xA76B, /*U+A76A*/ /*LATIN CAPITAL LETTER ET*/
+  0xA76B, /*U+A76B*/ /**/
+  0xA76D, /*U+A76C*/ /*LATIN CAPITAL LETTER IS*/
+  0xA76D, /*U+A76D*/ /**/
+  0xA76F, /*U+A76E*/ /*LATIN CAPITAL LETTER CON*/
+  0xA76F, /*U+A76F*/ /**/
+  0xA770, /*U+A770*/ /**/
+  0xA771, /*U+A771*/ /**/
+  0xA772, /*U+A772*/ /**/
+  0xA773, /*U+A773*/ /**/
+  0xA774, /*U+A774*/ /**/
+  0xA775, /*U+A775*/ /**/
+  0xA776, /*U+A776*/ /**/
+  0xA777, /*U+A777*/ /**/
+  0xA778, /*U+A778*/ /**/
+  0xA77A, /*U+A779*/ /*LATIN CAPITAL LETTER INSULAR D*/
+  0xA77A, /*U+A77A*/ /**/
+  0xA77C, /*U+A77B*/ /*LATIN CAPITAL LETTER INSULAR F*/
+  0xA77C, /*U+A77C*/ /**/
+  0x1D79, /*U+A77D*/ /*LATIN CAPITAL LETTER INSULAR G*/
+  0xA77F, /*U+A77E*/ /*LATIN CAPITAL LETTER TURNED INSULAR G*/
+  0xA77F, /*U+A77F*/ /**/
+  0xA781, /*U+A780*/ /*LATIN CAPITAL LETTER TURNED L*/
+  0xA781, /*U+A781*/ /**/
+  0xA783, /*U+A782*/ /*LATIN CAPITAL LETTER INSULAR R*/
+  0xA783, /*U+A783*/ /**/
+  0xA785, /*U+A784*/ /*LATIN CAPITAL LETTER INSULAR S*/
+  0xA785, /*U+A785*/ /**/
+  0xA787, /*U+A786*/ /*LATIN CAPITAL LETTER INSULAR T*/
+  0xA787, /*U+A787*/ /**/
+  0xA788, /*U+A788*/ /**/
+  0xA789, /*U+A789*/ /**/
+  0xA78A, /*U+A78A*/ /**/
+  0xA78C, /*U+A78B*/ /*LATIN CAPITAL LETTER SALTILLO*/
+  0xA78C, /*U+A78C*/ /**/
+  0x0265, /*U+A78D*/ /*LATIN CAPITAL LETTER TURNED H*/
+  0xA78E, /*U+A78E*/ /**/
+  0xA78F, /*U+A78F*/ /**/
+  0xA791, /*U+A790*/ /*LATIN CAPITAL LETTER N WITH DESCENDER*/
+  0xA791, /*U+A791*/ /**/
+  0xA792, /*U+A792*/ /**/
+  0xA793, /*U+A793*/ /**/
+  0xA794, /*U+A794*/ /**/
+  0xA795, /*U+A795*/ /**/
+  0xA796, /*U+A796*/ /**/
+  0xA797, /*U+A797*/ /**/
+  0xA798, /*U+A798*/ /**/
+  0xA799, /*U+A799*/ /**/
+  0xA79A, /*U+A79A*/ /**/
+  0xA79B, /*U+A79B*/ /**/
+  0xA79C, /*U+A79C*/ /**/
+  0xA79D, /*U+A79D*/ /**/
+  0xA79E, /*U+A79E*/ /**/
+  0xA79F, /*U+A79F*/ /**/
+  0xA7A1, /*U+A7A0*/ /*LATIN CAPITAL LETTER G WITH OBLIQUE STROKE*/
+  0xA7A1, /*U+A7A1*/ /**/
+  0xA7A3, /*U+A7A2*/ /*LATIN CAPITAL LETTER K WITH OBLIQUE STROKE*/
+  0xA7A3, /*U+A7A3*/ /**/
+  0xA7A5, /*U+A7A4*/ /*LATIN CAPITAL LETTER N WITH OBLIQUE STROKE*/
+  0xA7A5, /*U+A7A5*/ /**/
+  0xA7A7, /*U+A7A6*/ /*LATIN CAPITAL LETTER R WITH OBLIQUE STROKE*/
+  0xA7A7, /*U+A7A7*/ /**/
+  0xA7A9, /*U+A7A8*/ /*LATIN CAPITAL LETTER S WITH OBLIQUE STROKE*/
+  0xA7A9, /*U+A7A9*/ /**/
+  0xA7AA, /*U+A7AA*/ /**/
+  0xA7AB, /*U+A7AB*/ /**/
+  0xA7AC, /*U+A7AC*/ /**/
+  0xA7AD, /*U+A7AD*/ /**/
+  0xA7AE, /*U+A7AE*/ /**/
+  0xA7AF, /*U+A7AF*/ /**/
+  0xA7B0, /*U+A7B0*/ /**/
+  0xA7B1, /*U+A7B1*/ /**/
+  0xA7B2, /*U+A7B2*/ /**/
+  0xA7B3, /*U+A7B3*/ /**/
+  0xA7B4, /*U+A7B4*/ /**/
+  0xA7B5, /*U+A7B5*/ /**/
+  0xA7B6, /*U+A7B6*/ /**/
+  0xA7B7, /*U+A7B7*/ /**/
+  0xA7B8, /*U+A7B8*/ /**/
+  0xA7B9, /*U+A7B9*/ /**/
+  0xA7BA, /*U+A7BA*/ /**/
+  0xA7BB, /*U+A7BB*/ /**/
+  0xA7BC, /*U+A7BC*/ /**/
+  0xA7BD, /*U+A7BD*/ /**/
+  0xA7BE, /*U+A7BE*/ /**/
+  0xA7BF, /*U+A7BF*/ /**/
+};
+
+static const u_int16_t lower_table_11[64] = {
+  0xFF00, /*U+FF00*/ /**/
+  0xFF01, /*U+FF01*/ /**/
+  0xFF02, /*U+FF02*/ /**/
+  0xFF03, /*U+FF03*/ /**/
+  0xFF04, /*U+FF04*/ /**/
+  0xFF05, /*U+FF05*/ /**/
+  0xFF06, /*U+FF06*/ /**/
+  0xFF07, /*U+FF07*/ /**/
+  0xFF08, /*U+FF08*/ /**/
+  0xFF09, /*U+FF09*/ /**/
+  0xFF0A, /*U+FF0A*/ /**/
+  0xFF0B, /*U+FF0B*/ /**/
+  0xFF0C, /*U+FF0C*/ /**/
+  0xFF0D, /*U+FF0D*/ /**/
+  0xFF0E, /*U+FF0E*/ /**/
+  0xFF0F, /*U+FF0F*/ /**/
+  0xFF10, /*U+FF10*/ /**/
+  0xFF11, /*U+FF11*/ /**/
+  0xFF12, /*U+FF12*/ /**/
+  0xFF13, /*U+FF13*/ /**/
+  0xFF14, /*U+FF14*/ /**/
+  0xFF15, /*U+FF15*/ /**/
+  0xFF16, /*U+FF16*/ /**/
+  0xFF17, /*U+FF17*/ /**/
+  0xFF18, /*U+FF18*/ /**/
+  0xFF19, /*U+FF19*/ /**/
+  0xFF1A, /*U+FF1A*/ /**/
+  0xFF1B, /*U+FF1B*/ /**/
+  0xFF1C, /*U+FF1C*/ /**/
+  0xFF1D, /*U+FF1D*/ /**/
+  0xFF1E, /*U+FF1E*/ /**/
+  0xFF1F, /*U+FF1F*/ /**/
+  0xFF20, /*U+FF20*/ /**/
+  0xFF41, /*U+FF21*/ /*FULLWIDTH LATIN CAPITAL LETTER A*/
+  0xFF42, /*U+FF22*/ /*FULLWIDTH LATIN CAPITAL LETTER B*/
+  0xFF43, /*U+FF23*/ /*FULLWIDTH LATIN CAPITAL LETTER C*/
+  0xFF44, /*U+FF24*/ /*FULLWIDTH LATIN CAPITAL LETTER D*/
+  0xFF45, /*U+FF25*/ /*FULLWIDTH LATIN CAPITAL LETTER E*/
+  0xFF46, /*U+FF26*/ /*FULLWIDTH LATIN CAPITAL LETTER F*/
+  0xFF47, /*U+FF27*/ /*FULLWIDTH LATIN CAPITAL LETTER G*/
+  0xFF48, /*U+FF28*/ /*FULLWIDTH LATIN CAPITAL LETTER H*/
+  0xFF49, /*U+FF29*/ /*FULLWIDTH LATIN CAPITAL LETTER I*/
+  0xFF4A, /*U+FF2A*/ /*FULLWIDTH LATIN CAPITAL LETTER J*/
+  0xFF4B, /*U+FF2B*/ /*FULLWIDTH LATIN CAPITAL LETTER K*/
+  0xFF4C, /*U+FF2C*/ /*FULLWIDTH LATIN CAPITAL LETTER L*/
+  0xFF4D, /*U+FF2D*/ /*FULLWIDTH LATIN CAPITAL LETTER M*/
+  0xFF4E, /*U+FF2E*/ /*FULLWIDTH LATIN CAPITAL LETTER N*/
+  0xFF4F, /*U+FF2F*/ /*FULLWIDTH LATIN CAPITAL LETTER O*/
+  0xFF50, /*U+FF30*/ /*FULLWIDTH LATIN CAPITAL LETTER P*/
+  0xFF51, /*U+FF31*/ /*FULLWIDTH LATIN CAPITAL LETTER Q*/
+  0xFF52, /*U+FF32*/ /*FULLWIDTH LATIN CAPITAL LETTER R*/
+  0xFF53, /*U+FF33*/ /*FULLWIDTH LATIN CAPITAL LETTER S*/
+  0xFF54, /*U+FF34*/ /*FULLWIDTH LATIN CAPITAL LETTER T*/
+  0xFF55, /*U+FF35*/ /*FULLWIDTH LATIN CAPITAL LETTER U*/
+  0xFF56, /*U+FF36*/ /*FULLWIDTH LATIN CAPITAL LETTER V*/
+  0xFF57, /*U+FF37*/ /*FULLWIDTH LATIN CAPITAL LETTER W*/
+  0xFF58, /*U+FF38*/ /*FULLWIDTH LATIN CAPITAL LETTER X*/
+  0xFF59, /*U+FF39*/ /*FULLWIDTH LATIN CAPITAL LETTER Y*/
+  0xFF5A, /*U+FF3A*/ /*FULLWIDTH LATIN CAPITAL LETTER Z*/
+  0xFF3B, /*U+FF3B*/ /**/
+  0xFF3C, /*U+FF3C*/ /**/
+  0xFF3D, /*U+FF3D*/ /**/
+  0xFF3E, /*U+FF3E*/ /**/
+  0xFF3F, /*U+FF3F*/ /**/
+};
+
+static const u_int32_t lower_table_sp_1[64] = {
+  0xD801DC28, /*0xD801DC00*/ /*U+010428*/ /*U+010400*/ /*DESERET CAPITAL LETTER LONG I*/
+  0xD801DC29, /*0xD801DC01*/ /*U+010429*/ /*U+010401*/ /*DESERET CAPITAL LETTER LONG E*/
+  0xD801DC2A, /*0xD801DC02*/ /*U+01042A*/ /*U+010402*/ /*DESERET CAPITAL LETTER LONG A*/
+  0xD801DC2B, /*0xD801DC03*/ /*U+01042B*/ /*U+010403*/ /*DESERET CAPITAL LETTER LONG AH*/
+  0xD801DC2C, /*0xD801DC04*/ /*U+01042C*/ /*U+010404*/ /*DESERET CAPITAL LETTER LONG O*/
+  0xD801DC2D, /*0xD801DC05*/ /*U+01042D*/ /*U+010405*/ /*DESERET CAPITAL LETTER LONG OO*/
+  0xD801DC2E, /*0xD801DC06*/ /*U+01042E*/ /*U+010406*/ /*DESERET CAPITAL LETTER SHORT I*/
+  0xD801DC2F, /*0xD801DC07*/ /*U+01042F*/ /*U+010407*/ /*DESERET CAPITAL LETTER SHORT E*/
+  0xD801DC30, /*0xD801DC08*/ /*U+010430*/ /*U+010408*/ /*DESERET CAPITAL LETTER SHORT A*/
+  0xD801DC31, /*0xD801DC09*/ /*U+010431*/ /*U+010409*/ /*DESERET CAPITAL LETTER SHORT AH*/
+  0xD801DC32, /*0xD801DC0A*/ /*U+010432*/ /*U+01040A*/ /*DESERET CAPITAL LETTER SHORT O*/
+  0xD801DC33, /*0xD801DC0B*/ /*U+010433*/ /*U+01040B*/ /*DESERET CAPITAL LETTER SHORT OO*/
+  0xD801DC34, /*0xD801DC0C*/ /*U+010434*/ /*U+01040C*/ /*DESERET CAPITAL LETTER AY*/
+  0xD801DC35, /*0xD801DC0D*/ /*U+010435*/ /*U+01040D*/ /*DESERET CAPITAL LETTER OW*/
+  0xD801DC36, /*0xD801DC0E*/ /*U+010436*/ /*U+01040E*/ /*DESERET CAPITAL LETTER WU*/
+  0xD801DC37, /*0xD801DC0F*/ /*U+010437*/ /*U+01040F*/ /*DESERET CAPITAL LETTER YEE*/
+  0xD801DC38, /*0xD801DC10*/ /*U+010438*/ /*U+010410*/ /*DESERET CAPITAL LETTER H*/
+  0xD801DC39, /*0xD801DC11*/ /*U+010439*/ /*U+010411*/ /*DESERET CAPITAL LETTER PEE*/
+  0xD801DC3A, /*0xD801DC12*/ /*U+01043A*/ /*U+010412*/ /*DESERET CAPITAL LETTER BEE*/
+  0xD801DC3B, /*0xD801DC13*/ /*U+01043B*/ /*U+010413*/ /*DESERET CAPITAL LETTER TEE*/
+  0xD801DC3C, /*0xD801DC14*/ /*U+01043C*/ /*U+010414*/ /*DESERET CAPITAL LETTER DEE*/
+  0xD801DC3D, /*0xD801DC15*/ /*U+01043D*/ /*U+010415*/ /*DESERET CAPITAL LETTER CHEE*/
+  0xD801DC3E, /*0xD801DC16*/ /*U+01043E*/ /*U+010416*/ /*DESERET CAPITAL LETTER JEE*/
+  0xD801DC3F, /*0xD801DC17*/ /*U+01043F*/ /*U+010417*/ /*DESERET CAPITAL LETTER KAY*/
+  0xD801DC40, /*0xD801DC18*/ /*U+010440*/ /*U+010418*/ /*DESERET CAPITAL LETTER GAY*/
+  0xD801DC41, /*0xD801DC19*/ /*U+010441*/ /*U+010419*/ /*DESERET CAPITAL LETTER EF*/
+  0xD801DC42, /*0xD801DC1A*/ /*U+010442*/ /*U+01041A*/ /*DESERET CAPITAL LETTER VEE*/
+  0xD801DC43, /*0xD801DC1B*/ /*U+010443*/ /*U+01041B*/ /*DESERET CAPITAL LETTER ETH*/
+  0xD801DC44, /*0xD801DC1C*/ /*U+010444*/ /*U+01041C*/ /*DESERET CAPITAL LETTER THEE*/
+  0xD801DC45, /*0xD801DC1D*/ /*U+010445*/ /*U+01041D*/ /*DESERET CAPITAL LETTER ES*/
+  0xD801DC46, /*0xD801DC1E*/ /*U+010446*/ /*U+01041E*/ /*DESERET CAPITAL LETTER ZEE*/
+  0xD801DC47, /*0xD801DC1F*/ /*U+010447*/ /*U+01041F*/ /*DESERET CAPITAL LETTER ESH*/
+  0xD801DC48, /*0xD801DC20*/ /*U+010448*/ /*U+010420*/ /*DESERET CAPITAL LETTER ZHEE*/
+  0xD801DC49, /*0xD801DC21*/ /*U+010449*/ /*U+010421*/ /*DESERET CAPITAL LETTER ER*/
+  0xD801DC4A, /*0xD801DC22*/ /*U+01044A*/ /*U+010422*/ /*DESERET CAPITAL LETTER EL*/
+  0xD801DC4B, /*0xD801DC23*/ /*U+01044B*/ /*U+010423*/ /*DESERET CAPITAL LETTER EM*/
+  0xD801DC4C, /*0xD801DC24*/ /*U+01044C*/ /*U+010424*/ /*DESERET CAPITAL LETTER EN*/
+  0xD801DC4D, /*0xD801DC25*/ /*U+01044D*/ /*U+010425*/ /*DESERET CAPITAL LETTER ENG*/
+  0xD801DC4E, /*0xD801DC26*/ /*U+01044E*/ /*U+010426*/ /*DESERET CAPITAL LETTER OI*/
+  0xD801DC4F, /*0xD801DC27*/ /*U+01044F*/ /*U+010427*/ /*DESERET CAPITAL LETTER EW*/
+  0xD801DC28, /*0xD801DC28*/ /*U+010428*/ /*U+010428*/ /**/
+  0xD801DC29, /*0xD801DC29*/ /*U+010429*/ /*U+010429*/ /**/
+  0xD801DC2A, /*0xD801DC2A*/ /*U+01042A*/ /*U+01042A*/ /**/
+  0xD801DC2B, /*0xD801DC2B*/ /*U+01042B*/ /*U+01042B*/ /**/
+  0xD801DC2C, /*0xD801DC2C*/ /*U+01042C*/ /*U+01042C*/ /**/
+  0xD801DC2D, /*0xD801DC2D*/ /*U+01042D*/ /*U+01042D*/ /**/
+  0xD801DC2E, /*0xD801DC2E*/ /*U+01042E*/ /*U+01042E*/ /**/
+  0xD801DC2F, /*0xD801DC2F*/ /*U+01042F*/ /*U+01042F*/ /**/
+  0xD801DC30, /*0xD801DC30*/ /*U+010430*/ /*U+010430*/ /**/
+  0xD801DC31, /*0xD801DC31*/ /*U+010431*/ /*U+010431*/ /**/
+  0xD801DC32, /*0xD801DC32*/ /*U+010432*/ /*U+010432*/ /**/
+  0xD801DC33, /*0xD801DC33*/ /*U+010433*/ /*U+010433*/ /**/
+  0xD801DC34, /*0xD801DC34*/ /*U+010434*/ /*U+010434*/ /**/
+  0xD801DC35, /*0xD801DC35*/ /*U+010435*/ /*U+010435*/ /**/
+  0xD801DC36, /*0xD801DC36*/ /*U+010436*/ /*U+010436*/ /**/
+  0xD801DC37, /*0xD801DC37*/ /*U+010437*/ /*U+010437*/ /**/
+  0xD801DC38, /*0xD801DC38*/ /*U+010438*/ /*U+010438*/ /**/
+  0xD801DC39, /*0xD801DC39*/ /*U+010439*/ /*U+010439*/ /**/
+  0xD801DC3A, /*0xD801DC3A*/ /*U+01043A*/ /*U+01043A*/ /**/
+  0xD801DC3B, /*0xD801DC3B*/ /*U+01043B*/ /*U+01043B*/ /**/
+  0xD801DC3C, /*0xD801DC3C*/ /*U+01043C*/ /*U+01043C*/ /**/
+  0xD801DC3D, /*0xD801DC3D*/ /*U+01043D*/ /*U+01043D*/ /**/
+  0xD801DC3E, /*0xD801DC3E*/ /*U+01043E*/ /*U+01043E*/ /**/
+  0xD801DC3F, /*0xD801DC3F*/ /*U+01043F*/ /*U+01043F*/ /**/
+};
+
+/* EOF */
index da61a4371cc6968e84915e1bb2ba7eab0bc353ff..5e4ae8597a42e1b2f73c1fccd0b3f8cd6b3fc249 100644 (file)
 #include <arpa/inet.h>
 
 #include <atalk/unicode.h>
-#include "ucs2_casetable.h"
 #include "precompose.h"
 #include "byteorder.h"
 
-/*******************************************************************
- Convert a wide character to upper/lower case.
-********************************************************************/
-ucs2_t toupper_w(ucs2_t val)
-{
-       if ( val >= 0x0040 && val <= 0x007F)
-               return upcase_table_1[val-0x0040];
-       if ( val >= 0x00C0 && val <= 0x02BF)
-               return upcase_table_2[val-0x00C0];
-       if ( val >= 0x0380 && val <= 0x04FF)
-               return upcase_table_3[val-0x0380];
-       if ( val >= 0x0540 && val <= 0x05BF)
-               return upcase_table_4[val-0x0540];
-       if ( val >= 0x1E00 && val <= 0x1FFF)
-               return upcase_table_5[val-0x1E00];
-       if ( val >= 0x2140 && val <= 0x217F)
-               return upcase_table_6[val-0x2140];
-       if ( val >= 0x24C0 && val <= 0x24FF)
-               return upcase_table_7[val-0x24C0];
-       if ( val >= 0xFF40 && val <= 0xFF7F)
-               return upcase_table_8[val-0xFF40];
-
-       return (val);
-}
-
-
-ucs2_t tolower_w(ucs2_t val)
-{
-       if ( val >= 0x0040 && val <= 0x007F)
-               return lowcase_table_1[val-0x0040];
-       if ( val >= 0x00C0 && val <= 0x023F)
-               return lowcase_table_2[val-0x00C0];
-       if ( val >= 0x0380 && val <= 0x057F)
-               return lowcase_table_3[val-0x0380];
-       if ( val >= 0x1E00 && val <= 0x1FFF)
-               return lowcase_table_4[val-0x1E00];
-       if ( val >= 0x2140 && val <= 0x217F)
-               return lowcase_table_5[val-0x2140];
-       if ( val >= 0x2480 && val <= 0x24FF)
-               return lowcase_table_6[val-0x2480];
-       if ( val >= 0xFF00 && val <= 0xFF3F)
-               return lowcase_table_7[val-0xFF00];
-
-       return (val);
-}
-
 /*******************************************************************
  Convert a string to lower case.
  return True if any char is converted
index 957bf527c14dc72e24ccb752667bbec558bb122f..17ae747cb9ac45c278996965d57d697f8df91a65 100644 (file)
@@ -6,8 +6,8 @@ noinst_LTLIBRARIES = libutil.la
 
 libutil_la_SOURCES = \
        bprint.c        \
+       cnid.c          \
        fault.c         \
-       ftw.c           \
        getiface.c      \
        locking.c   \
        logger.c        \
@@ -21,4 +21,8 @@ libutil_la_SOURCES = \
        volinfo.c       \
        unix.c
 
-libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\"
\ No newline at end of file
+libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\"
+
+if HAVE_ATFUNCS
+libutil_la_SOURCES += ftw.c
+endif
diff --git a/libatalk/util/cnid.c b/libatalk/util/cnid.c
new file mode 100644 (file)
index 0000000..3753090
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <atalk/util.h>
+#include <atalk/cnid.h>
+#include <atalk/volinfo.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/logger.h>
+#include <atalk/errchk.h>
+#include <atalk/unicode.h>
+
+/*!
+ * Build path relativ to volume root
+ *
+ * path might be:
+ * (a) relative:
+ *     "dir/subdir" with cwd: "/afp_volume/topdir"
+ * (b) absolute:
+ *     "/afp_volume/dir/subdir"
+ *
+ * @param path     (r) path relative to cwd() or absolute
+ * @param volpath  (r) volume path that path is a subdir of (has been computed in volinfo funcs)
+ *
+ * @returns relative path in new bstring, caller must bdestroy it
+ */
+bstring rel_path_in_vol(const char *path, const char *volpath)
+{
+    EC_INIT;
+    int cwd = -1;
+    bstring fpath = NULL;
+    char *dname = NULL;
+    struct stat st;
+
+    if (path == NULL || volpath == NULL)
+        return NULL;
+
+    EC_NEG1_LOG(cwd = open(".", O_RDONLY));
+
+    EC_ZERO_LOGSTR(lstat(path, &st), "lstat(%s): %s", path, strerror(errno));
+
+    if (path[0] == '/') {
+        EC_NULL(fpath = bfromcstr(path));
+    } else {
+        switch (S_IFMT & st.st_mode) {
+        case S_IFREG:
+        case S_IFLNK:
+            EC_NULL_LOG(dname = strdup(path));
+            EC_ZERO_LOGSTR(chdir(dirname(dname)), "chdir(%s): %s", dirname, strerror(errno));
+            free(dname);
+            dname = NULL;
+            EC_NULL(fpath = bfromcstr(getcwdpath()));
+            BSTRING_STRIP_SLASH(fpath);
+            EC_ZERO(bcatcstr(fpath, "/"));
+            EC_NULL_LOG(dname = strdup(path));
+            EC_ZERO(bcatcstr(fpath, basename(dname)));
+            break;
+
+        case S_IFDIR:
+            EC_ZERO_LOGSTR(chdir(path), "chdir(%s): %s", path, strerror(errno));
+            EC_NULL(fpath = bfromcstr(getcwdpath()));
+            break;
+
+        default:
+            EC_FAIL;
+        }
+    }
+
+    BSTRING_STRIP_SLASH(fpath);
+
+    /*
+     * Now we have eg:
+     *   fpath:   /Volume/netatalk/dir/bla
+     *   volpath: /Volume/netatalk/
+     * we want: "dir/bla"
+     */
+    int len = strlen(volpath);
+    if (volpath[len-1] != '/')
+        /* in case volpath has no trailing slash */
+        len ++;
+    EC_ZERO(bdelete(fpath, 0, len));
+
+EC_CLEANUP:
+    if (dname) free(dname);
+    if (cwd != -1) {
+        fchdir(cwd);
+        close(cwd);
+    }
+    if (ret != 0)
+        return NULL;
+    return fpath;
+}
index 5f1c4a727ee33233cd82a75f439b0cd20efc5a29..eb98f45b290d5817461b90498a399bfb5034bbf0 100644 (file)
@@ -539,6 +539,9 @@ void make_log_entry(enum loglevels loglevel, enum logtypes logtype,
         temp_buffer[len+1] = 0;
     }
 
+    if (type_configs[logtype].level >= log_debug)
+        goto log; /* bypass flooding checks */
+
     /* Prevent flooding: hash the message and check if we got the same one recently */
     int hash = hash_message(temp_buffer) + log_src_linenumber;
 
index e8ed4d4d956382d06330ff02767f0efbf2afe18e..47e9baa2549bee28b42cbf1695f855e534476d89 100644 (file)
@@ -331,9 +331,9 @@ void server_child_kill_one_by_id(server_child *children, int forkid, pid_t pid,
                                 "Session with different pid[%u]", child->pid);
                         }
                     } else {
-                        kill_child(child);
-                        LOG(log_note, logtype_default,
-                            "Terminated disconnected session[%u]", child->pid);
+                        /* One client with multiple sessions */
+                        LOG(log_debug, logtype_default,
+                            "Found another session[%u] for client[%u]", child->pid, pid);
                     }
                 }
             } else {
@@ -341,7 +341,7 @@ void server_child_kill_one_by_id(server_child *children, int forkid, pid_t pid,
                 child->time = boottime;
                 if (child->clientid)
                     free(child->clientid);
-                LOG(log_debug, logtype_default, "Setting client ID for %d", child->pid);
+                LOG(log_debug, logtype_default, "Setting client ID for %u", child->pid);
                 child->uid = uid;
                 child->valid = 1;
                 child->idlen = idlen;
index 9edeb6c55c0cf34f380c121b77826a43d7c71972..528b2646bcfe2885bd2c0450b61b4429825f1082 100644 (file)
@@ -87,7 +87,7 @@ int setnonblock(int fd, int cmd)
  *                             io mode for the socket
  * @param timeout         (r)  number of seconds to try reading
  *
- * @returns number of bytes actually read or -1 on fatal error
+ * @returns number of bytes actually read or -1 on timeout or error
  */
 ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, int timeout)
 {
@@ -97,6 +97,8 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
     fd_set rfds;
     int ret;
 
+    FD_ZERO(&rfds);
+
     if (setnonblocking) {
         if (setnonblock(socket, 1) != 0)
             return -1;
@@ -114,7 +116,6 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
             case EINTR:
                 continue;
             case EAGAIN:
-                FD_ZERO(&rfds);
                 FD_SET(socket, &rfds);
                 tv.tv_usec = 0;
                 tv.tv_sec  = timeout;
@@ -122,7 +123,8 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                 while ((ret = select(socket + 1, &rfds, NULL, NULL, &tv)) < 1) {
                     switch (ret) {
                     case 0:
-                        LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+                        LOG(log_debug, logtype_afpd, "select timeout %d s", timeout);
+                        errno = EAGAIN;
                         goto exit;
 
                     default: /* -1 */
@@ -139,7 +141,6 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                                 tv.tv_usec = end.tv_usec - now.tv_usec;
                                 tv.tv_sec  = end.tv_sec - now.tv_sec;
                             }
-                            FD_ZERO(&rfds);
                             FD_SET(socket, &rfds);
                             continue;
                         }
index a4fa75b5c97291f3a88d56665b27b68c4c8d1553..5b210d81de9042d9227bbd793d7dce0de9e07eb1 100644 (file)
@@ -309,15 +309,20 @@ int sys_set_ea(VFS_FUNC_ARGS_EA_SET)
         switch(errno) {
         case OPEN_NOFOLLOW_ERRNO:
             /* its a symlink and client requested O_NOFOLLOW  */
-            LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): encountered symlink with kXAttrNoFollow",
-                uname, attruname);
+            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): encountered symlink with kXAttrNoFollow",
+                getcwdpath(), uname, attruname);
             return AFP_OK;
         case EEXIST:
-            LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): EA already exists",
-                uname, attruname);
+            LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists",
+                getcwdpath(), uname, attruname);
             return AFPERR_EXIST;
         default:
-            LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
+            LOG(log_error, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s",
+                getcwdpath(), uname, attruname, attrsize, 
+                oflag & O_CREAT ? "XATTR_CREATE" : "-",
+                oflag & O_TRUNC ? "XATTR_REPLACE" : "-",
+                oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-",
+                strerror(errno));
             return AFPERR_MISC;
         }
     }
index 0115c1534bca209cb9b43e82ed2ba32a8a93695b..bdae873e6c05ef3682a9db708167addd890ddf0c 100644 (file)
@@ -825,7 +825,7 @@ static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
        }
 
        if (closedir(dirp) == -1) {
-               LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno));
+               LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno));
                return -1;
        }
        return len;
@@ -843,8 +843,9 @@ static int solaris_attropen(const char *path, const char *attrpath, int oflag, m
 {
        int filedes = attropen(path, attrpath, oflag, mode);
        if (filedes == -1) {
-               LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s",
-            path, attrpath, strerror(errno));
+        if (errno != ENOENT)
+            LOG(log_error, logtype_default, "attropen(\"%s\", ea:'%s'): %s",
+                path, attrpath, strerror(errno));
         errno = ENOATTR;
        }
        return filedes;
@@ -854,8 +855,8 @@ static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
 {
        int filedes = openat(fildes, path, oflag, mode);
        if (filedes == -1) {
-               LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %d, path: %s, errno: %s",
-            filedes, path, strerror(errno));
+               LOG(log_error, logtype_default, "openat(\"%s\"): %s",
+            path, strerror(errno));
        }
        return filedes;
 }
@@ -865,7 +866,8 @@ static int solaris_write_xattr(int attrfd, const char *value, size_t size)
        if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
                return 0;
        } else {
-               LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!");
+               LOG(log_error, logtype_default, "solaris_write_xattr: %s",
+            strerror(errno));
                return -1;
        }
 }
index 83c6016903e42e8615fe4232b2b4118b755ea4ce..5e0588dfd171bf54e9b6b7410c292639aaeabb1b 100644 (file)
@@ -79,15 +79,15 @@ int setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
 /*
  * @brief system rmdir with afp error code.
  *
- * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this.
+ * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this.
  */
 int netatalk_rmdir_all_errors(int dirfd, const char *name)
 {
     int err;
 
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (dirfd == -1)
-        dirfd = ATFD_CWD;
+        dirfd = AT_FDCWD;
     err = unlinkat(dirfd, name, AT_REMOVEDIR);
 #else
     err = rmdir(name);
@@ -114,7 +114,7 @@ int netatalk_rmdir_all_errors(int dirfd, const char *name)
 /*
  * @brief System rmdir with afp error code, but ENOENT is not an error.
  *
- * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this.
+ * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this.
  */
 int netatalk_rmdir(int dirfd, const char *name)
 {
@@ -166,7 +166,7 @@ char *fullpathname(const char *name)
  **************************************************************************/
 
 /* 
- * Supports *at semantics if HAVE_RENAMEAT, pass dirfd=-1 to ignore this
+ * Supports *at semantics if HAVE_ATFUNCS, pass dirfd=-1 to ignore this
  */
 int copy_file(int dirfd, const char *src, const char *dst, mode_t mode)
 {
@@ -177,9 +177,9 @@ int copy_file(int dirfd, const char *src, const char *dst, mode_t mode)
     size_t  buflen;
     char   filebuf[8192];
 
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (dirfd == -1)
-        dirfd = ATFD_CWD;
+        dirfd = AT_FDCWD;
     sfd = openat(dirfd, src, O_RDONLY);
 #else
     sfd = open(src, O_RDONLY);
@@ -245,7 +245,7 @@ exit:
  */
 int netatalk_unlinkat(int dirfd, const char *name)
 {
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (dirfd == -1)
         dirfd = AT_FDCWD;
 
@@ -274,17 +274,17 @@ int netatalk_unlinkat(int dirfd, const char *name)
 /*
  * @brief This is equivalent of unix rename()
  *
- * unix_rename mulitplexes rename and renameat. If we dont HAVE_RENAMEAT, sfd and dfd
+ * unix_rename mulitplexes rename and renameat. If we dont HAVE_ATFUNCS, sfd and dfd
  * are ignored.
  *
- * @param sfd        (r) if we HAVE_RENAMEAT, -1 gives AT_FDCWD
+ * @param sfd        (r) if we HAVE_ATFUNCS, -1 gives AT_FDCWD
  * @param oldpath    (r) guess what
  * @param dfd        (r) same as sfd
  * @param newpath    (r) guess what
  */
 int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath)
 {
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (sfd == -1)
         sfd = AT_FDCWD;
     if (dfd == -1)
@@ -295,7 +295,7 @@ int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath)
 #else
     if (rename(oldpath, newpath) < 0)
         return -1;
-#endif  /* HAVE_RENAMEAT */
+#endif  /* HAVE_ATFUNCS */
 
     return 0;
 }
@@ -303,15 +303,15 @@ int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath)
 /* 
  * @brief stat/fsstatat multiplexer
  *
- * statat mulitplexes stat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored.
+ * statat mulitplexes stat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
  *
- * @param dirfd   (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD
+ * @param dirfd   (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
  * @param path    (r) pathname
  * @param st      (rw) pointer to struct stat
  */
 int statat(int dirfd, const char *path, struct stat *st)
 {
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (dirfd == -1)
         dirfd = AT_FDCWD;
     return (fstatat(dirfd, path, st, 0));
@@ -326,15 +326,15 @@ int statat(int dirfd, const char *path, struct stat *st)
 /* 
  * @brief lstat/fsstatat multiplexer
  *
- * lstatat mulitplexes lstat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored.
+ * lstatat mulitplexes lstat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
  *
- * @param dirfd   (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD
+ * @param dirfd   (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
  * @param path    (r) pathname
  * @param st      (rw) pointer to struct stat
  */
 int lstatat(int dirfd, const char *path, struct stat *st)
 {
-#ifdef HAVE_RENAMEAT
+#ifdef HAVE_ATFUNCS
     if (dirfd == -1)
         dirfd = AT_FDCWD;
     return (fstatat(dirfd, path, st, AT_SYMLINK_NOFOLLOW));
index 6fae6187205b69d4542ace1016e7de16b6901e96..902220befa3581e0a1d6a9dea9bc4a850e4ea599 100644 (file)
@@ -87,7 +87,7 @@ if test "x$bdb_required" = "xyes"; then
     trybdbdir=""
     dobdbsearch=yes
     bdb_search_dirs="/usr/local /usr"
-    search_subdirs="/ /db5 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
+    search_subdirs="/ /db5 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
 
     bdbfound=no
     savedcflags="$CFLAGS"
index b646244e5cc4aa571b7b480dd1b8e113376ced95..c767a967abd49b2fcfcba5f0d80066eb03c9b2a1 100644 (file)
@@ -5,6 +5,7 @@ apple_dump.1
 apple_mv.1
 apple_rm.1
 asip-status.pl.1
+afpldaptest.1
 uniconv.1
 .gitignore
 *.o
index ef56aadbbee9384ffb11b4207797bd42cc782483..52564afb6b3916de3408767103322e32e2a10ca5 100644 (file)
@@ -12,8 +12,8 @@ SUFFIXES= .tmpl .
            -e s@:DEFAULT_CNID_SCHEME:@${DEFAULT_CNID_SCHEME}@ \
            <$< >$@
 
-GENERATED_MANS = uniconv.1 asip-status.pl.1
-TEMPLATE_FILES = uniconv.1.tmpl asip-status.pl.1.tmpl
+GENERATED_MANS = uniconv.1 asip-status.pl.1 afpldaptest.1
+TEMPLATE_FILES = uniconv.1.tmpl asip-status.pl.1.tmpl afpldaptest.1.tmpl
 
 NONGENERATED_MANS      =       ad.1 \
                                afppasswd.1 \
index c0c3817a7d258e3278604fb6059e82aab5b1aaa5..b42b79b1a2b063b8b43350dac4daf1ba3de19225 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: ad
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 12 Oct 2010
+.\"      Date: 30 Mar 2011
 .\"    Manual: Netatalk 2.2
 .\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AD" "1" "12 Oct 2010" "Netatalk 2.2" "Netatalk 2.2"
+.TH "AD" "1" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -234,4 +234,5 @@ Be verbose when deleting files, showing them as they are removed\&.
 Report bugs to the Netatalk\-devel list <netatalk\-devel@lists\&.sourceforge\&.net>\&.
 .SH "SEE ALSO"
 .PP
-\fBdbd\fR(1)\&.
+\fBdbd\fR(1),
+\fBapple_dump\fR(1)\&.
diff --git a/man/man1/afpldaptest.1.tmpl b/man/man1/afpldaptest.1.tmpl
new file mode 100644 (file)
index 0000000..2ea753c
--- /dev/null
@@ -0,0 +1,58 @@
+'\" t
+.\"     Title: afpldaptest
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\"      Date: 30 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
+.\"  Language: English
+.\"
+.TH "AFPLDAPTEST" "1" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+afpldaptest \- Syntactically check an afp_ldap\&.conf
+.SH "SYNOPSIS"
+.HP \w'\fBafpldaptest\fR\fB\fR\fBafpldaptest\fR\fB\fR\ 'u
+\fBafpldaptest\fR\fB\fR {\-u\ \fIUSER\fR | \-g\ \fIGROUP\fR | \-i\ \fIUUID\fR}
+.br
+\fBafpldaptest\fR\fB\fR {\-h | \-? | \-:}
+.SH "DESCRIPTION"
+.PP
+\fBafpldaptest\fR
+is a simple command to syntactically check :ETCDIR:/afp_ldap\&.conf\&.
+.SH "OPTIONS"
+.PP
+\fB\-u\fR \fIUSER\fR
+.RS 4
+Show uuid for
+\fIUSER\fR\&.
+.RE
+.PP
+\fB\-g\fR \fIGROUP\fR
+.RS 4
+Show uuid for
+\fIGROUP\fR\&.
+.RE
+.PP
+\fB\-i\fR \fIUUID\fR
+.RS 4
+Show user, group or local\-uuid for
+\fIUUID\fR\&.
+.RE
+.PP
+\fB\-h, \-?, \-:\fR
+.RS 4
+Show the help and exit\&.
+.RE
+.SH "SEE ALSO"
+.PP
+\fBafp_ldap.conf\fR(5)
index 0fea6807c4a7c5692da2ec65e0760767a7388e91..8d72f85c5477fdae3cabb6584fd0c55ebd59077a 100644 (file)
@@ -3,11 +3,11 @@
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: 22 Aug 2004
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AFPPASSWD" "1" "22 Aug 2004" "Netatalk 2.1" "Netatalk 2.1"
+.TH "AFPPASSWD" "1" "22 Aug 2004" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
index d915cd8cdfe43db2884537e0f2068587e189225c..7df7c0998e78149223351b869f213a6948d94002 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: apple_dump
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 31 Mar 2010
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 30 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "APPLE_DUMP" "1" "31 Mar 2010" "Netatalk 2.1" "Netatalk 2.1"
+.TH "APPLE_DUMP" "1" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -74,4 +74,4 @@ There is no way to detect whether FinderInfo is FileInfo or DirInfo\&. By defaul
 If setting option \-f or \-d, assume FinderInfo and doesn\'t look for another file\&.
 .SH "SEE ALSO"
 .PP
-\fBafile\fR(1)
+\fBad\fR(1)
index f5c2d64afcd35a286af6a1774819a3a2104dbc31..2bf64bdc7ddb3bc111e5bd5f106e6e364e7524b3 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: asip-status.pl
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 22 Aug 2004
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 10 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "ASIP\-STATUS\&.PL" "1" "22 Aug 2004" "Netatalk 2.1" "Netatalk 2.1"
+.TH "ASIP\-STATUS\&.PL" "1" "10 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
 .SH "NAME"
 asip-status.pl \- Queries AFP servers for their capabilities
 .SH "SYNOPSIS"
-.PP
-\fB:BINDIR:/asip\-status\&.pl\fR\fB\fR
-ADDRESS\fI:PORT\fR\&.\&.\&.
+.HP \w'\fBasip\-status\&.pl\fR\fB\fR\ 'u
+\fBasip\-status\&.pl\fR\fB\fR [\-d] [\-i] [\-x] HOSTNAME[:PORT]
 .SH "DESCRIPTION"
 .PP
 \fBasip\-status\&.pl\fR
-is a perl script that sends a FPGetSrvrInfo request to an AFP server at ADDRESS:PORT and displays the results, namely "Machine type", the server\'s name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
+is a perl script that sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and displays the results, namely "Machine type", the server\'s name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
 .PP
 When you don\'t supply :PORT, then the default AFP port, 548, will be used\&.
+.SH "OPTIONS"
+.PP
+\fB\-d\fR
+.RS 4
+Enable debug output\&.
+.RE
+.PP
+\fB\-i\fR
+.RS 4
+Show icon if it exists\&.
+.RE
+.PP
+\fB\-x\fR
+.RS 4
+Enable hex dump output\&.
+.RE
 .SH "EXAMPLES"
 .PP
 .if n \{\
 .RS 4
 .\}
 .nf
-\fB:BINDIR:/asip\-status\&.pl\fR 192\&.168\&.21\&.2
+\fBasip\-status\&.pl\fR 192\&.168\&.21\&.2
 AFP reply from 192\&.168\&.21\&.2:548
 Flags: 1  Cmd: 3  ID: 57005
 Reply: DSIGetStatus
@@ -61,8 +76,8 @@ Network address: 10\&.20 (ddp address)
 .RS 4
 .\}
 .nf
-\fB:BINDIR:/asip\-status\&.pl\fR 192\&.168\&.21\&.1:10548
-AFP reply from 192\&.168\&.21\&.1:10548
+\fBasip\-status\&.pl\fR myserver:10548
+AFP reply from myserver:10548
 Flags: 1  Cmd: 3  ID: 57005
 Reply: DSIGetStatus
 Request ID: 57005
index b665673ec0ee3cffd67cfd2fc71c7b2c27c287c6..7b55c76fee304c12dbde5e500ef3ca3135eee5b1 100644 (file)
@@ -3,11 +3,11 @@
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: 8 Jan 1992
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "MEGATRON" "1" "8 Jan 1992" "Netatalk 2.1" "Netatalk 2.1"
+.TH "MEGATRON" "1" "8 Jan 1992" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
index 3ceecbcefefc6cfdb99b2354ebbad4a35b39fe13..3d4d9a8b8905b7a53f8485e4ecb35a76b635b1dc 100644 (file)
@@ -4,10 +4,10 @@
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: 09 June 2001
 .\"    Manual: The Netatalk Project
-.\"    Source: Netatalk 2.1
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "NETATALK\-CONFIG" "1" "09 June 2001" "Netatalk 2.1" "The Netatalk Project"
+.TH "NETATALK\-CONFIG" "1" "09 June 2001" "Netatalk 2.2" "The Netatalk Project"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
index 1d49c30b170a21a0e18d942e97468002f7d601d9..9e314b52749147e0509c41281a0b75724d156bc9 100644 (file)
@@ -3,11 +3,11 @@
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: 24 Jun 2004
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "UNICONV" "1" "24 Jun 2004" "Netatalk 2.1" "Netatalk 2.1"
+.TH "UNICONV" "1" "24 Jun 2004" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
index c754aeea017bcca0ebdc4564e69f9d9b4b7cae8b..c6a1255bb7908c0ffd6885c5914dd2807ab4f7a8 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: AppleVolumes.default
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 07 Dec 2010
+.\"      Date: 30 Mar 2011
 .\"    Manual: Netatalk 2.2
 .\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "APPLEVOLUMES\&.DEFAU" "5" "07 Dec 2010" "Netatalk 2.2" "Netatalk 2.2"
+.TH "APPLEVOLUMES\&.DEFAU" "5" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -353,11 +353,9 @@ rwlist:\fI[users/groups]\fR
 Allows certain users and groups to have read/write access to a share\&. This follows the allow option format\&.
 .RE
 .PP
-veto:\fI[vetoed name]\fR
+veto:\fI[vetoed names]\fR
 .RS 4
-hide files and directories,where the path matches one of the \'/\' delimited vetoed names\&. Matches are partial, e\&.g\&. path is
-/abc/def/file
-and veto:/abc/ will hide the file\&.
+hide files and directories,where the path matches one of the \'/\' delimited vetoed names\&. The veto string must always be terminated with a \'/\', eg\&. "veto1/", "veto1/veto2/"\&.
 .RE
 .PP
 volcharset:\fI[charset]\fR
@@ -724,5 +722,4 @@ Provides compatibility with Apple II clients\&. (legacy)
 .PP
 \fBafpd.conf\fR(5),
 \fBafpd\fR(8),
-\fBafp_ldap.conf\fR(5),
-\fBafp_acls\fR(8)
+\fBcnid_metad\fR(8)
index 84dd7b9cff6c90dfaa0cd54ea46447ea9cc6cf17..2f7ec5b6cc091822761943fd771a8a71d2714f61 100644 (file)
@@ -17,13 +17,15 @@ GENERATED_MANS = AppleVolumes.default.5 \
        afpd.conf.5 \
        netatalk.conf.5 \
        afp_ldap.conf.5 \
-       afp_signature.conf.5
+       afp_signature.conf.5 \
+       afp_voluuid.conf.5
 
 TEMPLATE_FILES = AppleVolumes.default.5.tmpl \
        afpd.conf.5.tmpl \
        netatalk.conf.5.tmpl \
        afp_ldap.conf.5.tmpl \
-       afp_signature.conf.5.tmpl
+       afp_signature.conf.5.tmpl \
+       afp_voluuid.conf.5.tmpl
 
 NONGENERATED_MANS = AppleVolumes.5 AppleVolumes.system.5
 
index 0b909e330338867f9df634309bd7ad12adad6539..8ad13027b1a48aa084bab7b1f9253823f503d66f 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: afp_ldap.conf
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 28 November 2009
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 30 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AFP_LDAP\&.CONF" "5" "28 November 2009" "Netatalk 2.1" "Netatalk 2.1"
+.TH "AFP_LDAP\&.CONF" "5" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -160,4 +160,5 @@ ldap_group_attr  = cn
 .SH "SEE ALSO"
 .PP
 \fBafpd\fR(8),
-\fBAppleVolumes.default\fR(5),\fBafpldaptest\fR(1)
+\fBAppleVolumes.default\fR(5),
+\fBafpldaptest\fR(1)
index 59de330138122c603f06814f902e7bfc32a97ed0..592b8fbb0171c2e3b54057a85ff37e5d3168a44f 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: afp_signature.conf
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 29 March 2010
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 08 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AFP_SIGNATURE\&.CONF" "5" "29 March 2010" "Netatalk 2.1" "Netatalk 2.1"
+.TH "AFP_SIGNATURE\&.CONF" "5" "08 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -25,7 +25,7 @@ afp_signature.conf \- Configuration file used by afpd(8) to specify server signa
 :ETCDIR:/afp_signature\&.conf
 is the configuration file used by
 \fBafpd\fR
-to specify server signature automatically\&. The configuration lines are composed like:
+to specify server signature automagically\&. The configuration lines are composed like:
 .PP
 \fI"server name"\fR
 \fIhexa\-string\fR
@@ -50,7 +50,7 @@ Server Signature is unique 16\-bytes identifier used to prevent logging on to th
 .PP
 Netatalk 2\&.0 and earlier generated server signature by using gethostid()\&. There was a problem that another servers have the same signature because the hostid is not unique enough\&.
 .PP
-Netatalk 2\&.1 generates the signature from random numbers and saves it into afp_signature\&.conf\&. When starting next time, it is read from this file\&.
+Current netatalk generates the signature from random numbers and saves it into afp_signature\&.conf\&. When starting next time, it is read from this file\&.
 .PP
 This file should not be thoughtlessly edited and be copied onto another server\&. If it wants to set the signature intentionally, use the option "\-signature user:xxxx" in afpd\&.conf\&. In this case, afp_signature\&.conf is not used\&.
 .sp .5v
diff --git a/man/man5/afp_voluuid.conf.5.tmpl b/man/man5/afp_voluuid.conf.5.tmpl
new file mode 100644 (file)
index 0000000..c36a112
--- /dev/null
@@ -0,0 +1,77 @@
+'\" t
+.\"     Title: afp_voluuid.conf
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\"      Date: 8 March 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
+.\"  Language: English
+.\"
+.TH "AFP_VOLUUID\&.CONF" "5" "8 March 2011" "Netatalk 2.2" "Netatalk 2.2"
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+afp_voluuid.conf \- Configuration file used by afpd(8) to specify UUID for Time Machine volume
+.SH "DESCRIPTION"
+.PP
+:ETCDIR:/afp_voluuid\&.conf
+is the configuration file used by
+\fBafpd\fR
+to specify UUID of Time Machine volume automagically\&. The configuration lines are composed like:
+.PP
+\fI"volume name"\fR
+\fIuuid\-string\fR
+.PP
+The first field is volume name\&. Volume names must be quoted if they contain spaces\&. The second field is the 36 character hexadecimal ASCII string representation of a UUID\&.
+.PP
+The leading spaces and tabs are ignored\&. Blank lines are ignored\&. The lines prefixed with # are ignored\&. The illegal lines are ignored\&.
+.if n \{\
+.sp
+.\}
+.RS 4
+.it 1 an-trap
+.nr an-no-space-flag 1
+.nr an-break-flag 1
+.br
+.ps +1
+\fBNote\fR
+.ps -1
+.br
+.PP
+This UUID is advertised by Zeroconf in order to provide robust disambiguation of Time Machine volume\&.
+.PP
+The afpd generates the UUID from random numbers and saves it into afp_voluuid\&.conf, only when setting "tm" option in AppleVolumes file\&.
+.PP
+This file should not be thoughtlessly edited and be copied onto another server\&.
+.sp .5v
+.RE
+.PP
+.SH "EXAMPLES"
+.PP
+\fBExample.\ \&afp_voluuid.conf three TM volumes on one netatalk\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# This is a comment\&.
+"Backup for John Smith" 1573974F\-0ABD\-69CC\-C40A\-8519B681A0E1
+"bob" 39A487F4\-55AA\-8240\-E584\-69AA01800FE9
+mary 6331E2D1\-446C\-B68C\-3066\-D685AADBE911
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SEE ALSO"
+.PP
+\fBafpd\fR(8),
+\fBAppleVolumes.default\fR(5),
+\fBavahi-daemon\fR(8)
index f06130409ecd0ce05e126c4851f7fe6cecae906e..b3f099ff1641d7680581c5cecb5c7a7aa5045b2c 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: afpd.conf
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 1 November 2010
+.\"      Date: 30 Mar 2011
 .\"    Manual: Netatalk 2.2
 .\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AFPD\&.CONF" "5" "1 November 2010" "Netatalk 2.2" "Netatalk 2.2"
+.TH "AFPD\&.CONF" "5" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -46,7 +46,7 @@ is used instead of a server name, the default server is specified\&. Server name
 .PP
 Each server has to be configured on a
 \fBsingle\fR
-line\&. Though newline escaping is supported\&.
+line\&. Though, using "\e" character, newline escaping is supported\&.
 .sp .5v
 .RE
 The possible options and their meanings are:
@@ -90,7 +90,7 @@ allows guest logins
 .PP
 uams_clrtxt\&.so
 .RS 4
-(uams_pam\&.so or uams_passwd\&.so) Allow logins with passwords transmitted in the clear\&.
+(uams_pam\&.so or uams_passwd\&.so) Allow logins with passwords transmitted in the clear\&. (legacy)
 .RE
 .PP
 uams_randum\&.so
@@ -98,7 +98,7 @@ uams_randum\&.so
 allows Random Number and Two\-Way Random Number Exchange for authentication (requires a separate file containing the passwords, either :ETCDIR:/afppasswd file or the one specified via
 \fB\-passwdfile\fR\&. See
 \fBafppasswd\fR(1)
-for details
+for details\&. (legacy)
 .RE
 .PP
 uams_dhx\&.so
@@ -256,24 +256,24 @@ listens to\&. The default is advertise the first IP address of the system, but t
 when used together with the
 \fB\-proxy\fR
 option\&.
-.PP \fBExample.\ \&IP/hostname example configuration\fR fluxxus \fB\-hostname\fR afp\&.apple\&.com \fB\-ipaddr\fR 127\&.0\&.0\&.1 \fB\-fqdn\fR www\&.microsoft\&.comResult:.TS
-allbox tab(:);
-l
-l
-l.
-T{
-(UTF8) Server name: fluxxus
-T}
-T{
-Listening and advertised network address:
-                    127\&.0\&.0\&.1
-T}
-T{
-Advertised network address:
-                    www\&.microsoft\&.com
-T}
-.TE
-.sp 1
+.PP
+\fBExample.\ \&afpd.conf onfiguration line\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+              fluxxus \-hostname afp\&.example\&.org \-ipaddr 192\&.168\&.0\&.1 \-fqdn www\&.example\&.com
+            
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+
+\fBResult\fR
+.sp
+(UTF8) Server name: fluxxus, Listening and advertised network address: 192\&.168\&.0\&.1, Advertised network address: www\&.example\&.com, hostname is not used\&.
 .RE
 .PP
 \-port \fI[port number]\fR
@@ -293,6 +293,28 @@ server as well, set
 This specifies the DSI server quantum\&. The default value is 303840\&. The maximum value is 0xFFFFFFFFF, the minimum is 32000\&. If you specify a value that is out of range, the default value will be set\&. Do not change this value unless you\'re absolutely sure, what you\'re doing
 .RE
 .PP
+\-dsireadbuf \fI[number]\fR
+.RS 4
+Scale factor that determines the size of the DSI/TCP readahead buffer, default is 12\&. This is multiplies with the DSI server quantum (default ~300k) to give the size of the buffer\&. Increasing this value might increase throughput in fast local networks for volume to volume copies\&.
+\fINote\fR: This buffer is allocated per afpd child process, so specifying large values will eat up large amount of memory (buffer size * number of clients)\&.
+.RE
+.PP
+\-tcprcvbuf \fI[number]\fR
+.RS 4
+Try to set TCP receive buffer using setsockpt()\&. Often OSes impose restrictions on the applications ability to set this value\&.
+.RE
+.PP
+\-tcpsndbuf \fI[number]\fR
+.RS 4
+Try to set TCP send buffer using setsockpt()\&. Often OSes impose restrictions on the applications ability to set this value\&.
+.RE
+.PP
+\-nozeroconf
+.RS 4
+Disable automatic Zeroconf
+service registration if support was compiled in\&.
+.RE
+.PP
 \-slp
 .RS 4
 Register this server using the Service Location Protocol (if SLP
@@ -371,7 +393,7 @@ Specifies the user that guests should use (default is "nobody")\&. The name shou
 .PP
 \-[no]icon
 .RS 4
-[Dont\'t] Use the platform\-specific icon\&. Recent Mac OS don\'t display it any longer\&.
+[Don\'t] Use the platform\-specific icon\&. Recent Mac OS don\'t display it any longer\&.
 .RE
 .PP
 \-loginmesg \fI[message]\fR
@@ -427,7 +449,6 @@ Max length of UTF8\-MAC volume name for Mac OS X\&. Note that Hangul is especial
 .nf
 73:  limit of Mac OS X 10\&.1
 80:  limit for Mac OS X 10\&.4/10\&.5 (default)
-123: limit for Mac OS X 10\&.6
 255: limit of spec
 .fi
 .if n \{\
@@ -482,7 +503,7 @@ The config is case\-ignoring
 .RS 4
 .\}
 .nf
-\-setuplog "default log_info /var/log/afpd\&.log"
+\- \-setuplog "default log_info /var/log/afpd\&.log"
 .fi
 .if n \{\
 .RE
@@ -494,7 +515,7 @@ The config is case\-ignoring
 .RS 4
 .\}
 .nf
-\-setuplog "default log_maxdebug /var/log/afpd\&.log"
+\- \-setuplog "default log_maxdebug /var/log/afpd\&.log"
 .fi
 .if n \{\
 .RE
@@ -506,7 +527,7 @@ The config is case\-ignoring
 .RS 4
 .\}
 .nf
-\-setuplog "default log_info /var/log/afpd\&.log"
+\- \-setuplog "default log_info /var/log/afpd\&.log" \e
 \-setuplog "UAMSDaemon log_maxdebug /var/log/uams\&.log"
 .fi
 .if n \{\
@@ -526,7 +547,7 @@ specifying any string as filename is sufficient for the config parser to disting
 .RS 4
 .\}
 .nf
-\-unsetuplog "default \-"
+\- \-unsetuplog "default \-"
 .fi
 .if n \{\
 .RE
@@ -553,7 +574,7 @@ Specify the number of tickles to send before timing out a connection\&. The defa
 .RS 4
 .\}
 .nf
-\- \-transall \-uamlist uams_dhx\&.so,uams_dhx2\&.so
+\- \-tcp \-noddp \-uamlist uams_dhx\&.so,uams_dhx2\&.so \-nosavepassword
 .fi
 .if n \{\
 .RE
@@ -565,7 +586,7 @@ Specify the number of tickles to send before timing out a connection\&. The defa
 .RS 4
 .\}
 .nf
-\- \-transall \-maccodepage mac_cyrillic \-unixcodepage utf8
+\- \-maccodepage mac_cyrillic \-unixcodepage utf8
 .fi
 .if n \{\
 .RE
@@ -577,7 +598,7 @@ Specify the number of tickles to send before timing out a connection\&. The defa
 .RS 4
 .\}
 .nf
-\- \-transall \-uamlist uams_dhx\&.so,uams_dhx2\&.so,uams_guest\&.so,uams_gss\&.so \e 
+\- \-uamlist uams_dhx\&.so,uams_dhx2\&.so,uams_guest\&.so,uams_gss\&.so \e 
 \-k5service afpserver \-k5keytab /path/to/afpserver\&.keytab \e 
 \-k5realm YOUR\&.REALM \-fqdn your\&.fqdn\&.namel:548
 .fi
@@ -593,7 +614,7 @@ Specify the number of tickles to send before timing out a connection\&. The defa
 .nf
 "Guest Server" \-uamlist uams_guest\&.so \-loginmesg "Welcome guest!"
 "User Server" \-uamlist uams_dhx2\&.so \-port 12000
-"special" \-notcp \-defaultvol <path> \-systemvol <path>
+"special" \-ddp \-notcp \-defaultvol <path> \-systemvol <path>
 .fi
 .if n \{\
 .RE
@@ -603,4 +624,5 @@ Specify the number of tickles to send before timing out a connection\&. The defa
 \fBafpd\fR(8),
 \fBafppasswd\fR(1),
 \fBAppleVolumes.default\fR(5),
-\fBafp_signature.conf\fR(5)
+\fBafp_signature.conf\fR(5),
+\fBcnid_metad\fR(8)
index 8adcb66c5484ea948f11d6b8bcf3073832b956a6..6c9b4b748f05dda4fccd91fc92ebfc9863e9194f 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: netatalk.conf
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 26 Sep 2010
+.\"      Date: 30 Mar 2011
 .\"    Manual: Netatalk 2.2
 .\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "NETATALK\&.CONF" "5" "26 Sep 2010" "Netatalk 2.2" "Netatalk 2.2"
+.TH "NETATALK\&.CONF" "5" "30 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -19,7 +19,7 @@
 .\" * MAIN CONTENT STARTS HERE *
 .\" -----------------------------------------------------------------
 .SH "NAME"
-netatalk.conf \- Configuration file used by netatalk(8) to determine its general configuration
+netatalk.conf \- Configuration file used by Netatalk to determine its general configuration
 .SH "SYNOPSIS"
 .HP \w'\fB:ETCDIR:/netatalk\&.conf\fR\fB\fR\fB:DESTDIR:/etc/default/netatalk\fR\fB\fR\ 'u
 \fB:ETCDIR:/netatalk\&.conf\fR\fB\fR
@@ -115,5 +115,8 @@ Set the Unix codepage, used by atalkd and papd to convert extended characters fr
 .RE
 .SH "SEE ALSO"
 .PP
+\fBafpd\fR(8),
+\fBafpd.conf\fR(5),
+\fBcnid_metad\fR(8),
 \fBatalkd\fR(8),
 \fBatalkd.conf\fR(5)
index 1995473a7ae58170221b20a9ff88ae092eb14111..9fc6dd3739e148722266333b3145fe3c89bc6dc8 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: afpd
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 21 Apr 2010
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 08 Mar 2011
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "AFPD" "8" "21 Apr 2010" "Netatalk 2.1" "Netatalk 2.1"
+.TH "AFPD" "8" "08 Mar 2011" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -278,7 +278,17 @@ user\'s list of volumes to mount
 list of server signature
 .RE
 .PP
-:ETCDIR:/netatalk/msg/message\&.pid
+:ETCDIR:/afp_voluuid\&.conf
+.RS 4
+list of UUID for Time Machine volume
+.RE
+.PP
+:ETCDIR:/afp_ldap\&.conf
+.RS 4
+configuration file for LDAP and ACL support
+.RE
+.PP
+:ETCDIR:/msg/message\&.pid
 .RS 4
 contains messages to be sent to users\&.
 .RE
@@ -290,4 +300,6 @@ contains messages to be sent to users\&.
 \fBafpd.conf\fR(5),
 \fBAppleVolumes.default\fR(5),
 \fBafp_signature.conf\fR(5),
+\fBafp_voluuid.conf\fR(5),
+\fBafp_ldap.conf\fR(5),
 \fBdbd\fR(1)\&.
index 1698faab2fc51bb0d837230fd78c82f6ab1e83cc..2822e2f098968bb8e3623fe473dbf675af9e686d 100644 (file)
@@ -3,11 +3,11 @@
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
 .\"      Date: 23 Dec 2009
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "CNID_METAD" "8" "23 Dec 2009" "Netatalk 2.1" "Netatalk 2.1"
+.TH "CNID_METAD" "8" "23 Dec 2009" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
index 7049a7c7d17d06026fa406958396f1a24308e56a..6e76a18ce8dae3c3b71694ff8621924ac31b75a5 100644 (file)
@@ -1,5 +1,4 @@
 /*
-  $Id: subtests.c,v 1.1.2.1 2010-02-01 10:56:08 franklahm Exp $
   Copyright (c) 2010 Frank Lahm <franklahm@gmail.com>
 
   This program is free software; you can redistribute it and/or modify
@@ -51,7 +50,7 @@ int test001_add_x_dirs(const struct vol *vol, cnid_t start, cnid_t end)
         dir = dir_new(dirname, dirname, vol, DIRDID_ROOT, htonl(start), bfromcstr(vol->v_path), 0);
         if (dir == NULL)
             return -1;
-        if (dircache_add(dir) != 0)
+        if (dircache_add(vol, dir) != 0)
             return -1;
     }