]> granicus.if.org Git - pgbouncer/commitdiff
Add SASL and SCRAM support
authorPeter Eisentraut <peter@eisentraut.org>
Sun, 18 Aug 2019 04:56:14 +0000 (06:56 +0200)
committerPeter Eisentraut <peter@eisentraut.org>
Fri, 23 Aug 2019 07:44:31 +0000 (09:44 +0200)
Add support for SASL/SCRAM-SHA-256 authentication for clients and servers.

Import a few files from PostgreSQL core (commit REL_11_5) to support
SCRAM.

resolves #208

33 files changed:
Makefile
doc/config.md
etc/import-common.sh [new file with mode: 0644]
include/bouncer.h
include/common/base64.h [new file with mode: 0644]
include/common/pg_wchar.h [new file with mode: 0644]
include/common/postgres_compat.h [new file with mode: 0644]
include/common/saslprep.h [new file with mode: 0644]
include/common/scram-common.h [new file with mode: 0644]
include/common/unicode_norm.h [new file with mode: 0644]
include/common/unicode_norm_table.h [new file with mode: 0644]
include/pktbuf.h
include/scram.h [new file with mode: 0644]
include/server.h
include/util.h
src/client.c
src/common/base64.c [new file with mode: 0644]
src/common/saslprep.c [new file with mode: 0644]
src/common/scram-common.c [new file with mode: 0644]
src/common/unicode_norm.c [new file with mode: 0644]
src/common/wchar.c [new file with mode: 0644]
src/hba.c
src/main.c
src/objects.c
src/proto.c
src/scram.c [new file with mode: 0644]
src/server.c
test/hba_test.c
test/hba_test.eval
test/hba_test.rules
test/test.ini
test/test.sh
test/userlist.txt

index 0663ed0cf19fdb548e49b974349e816efe87f160..badfd0f6c5eab963799135ffb75fc4b8d88716a5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,12 +17,18 @@ pgbouncer_SOURCES = \
        src/pooler.c \
        src/proto.c \
        src/sbuf.c \
+       src/scram.c \
        src/server.c \
        src/stats.c \
        src/system.c \
        src/takeover.c \
        src/util.c \
        src/varcache.c \
+       src/common/base64.c \
+       src/common/saslprep.c \
+       src/common/scram-common.c \
+       src/common/unicode_norm.c \
+       src/common/wchar.c \
        include/admin.h \
        include/bouncer.h \
        include/client.h \
@@ -37,12 +43,20 @@ pgbouncer_SOURCES = \
        include/pooler.h \
        include/proto.h \
        include/sbuf.h \
+       include/scram.h \
        include/server.h \
        include/stats.h \
        include/system.h \
        include/takeover.h \
        include/util.h \
-       include/varcache.h
+       include/varcache.h \
+       include/common/base64.h \
+       include/common/pg_wchar.h \
+       include/common/postgres_compat.h \
+       include/common/saslprep.h \
+       include/common/scram-common.h \
+       include/common/unicode_norm.h \
+       include/common/unicode_norm_table.h
 
 pgbouncer_CPPFLAGS = -Iinclude $(CARES_CFLAGS) $(TLS_CPPFLAGS)
 
index 534723b3989ec0bf8d29e8d7b12378f45067ce49..03a29fdbaef9b517d9b696c8e08a824c4355fc87 100644 (file)
@@ -104,8 +104,17 @@ cert
     Username is then taken from CommonName field from certificate.
 
 md5
-:   Use MD5-based password check. `auth_file` may contain both MD5-encrypted
-    or plain-text passwords.  This is the default authentication method.
+:   Use MD5-based password check.  This is the default authentication
+    method.  `auth_file` may contain both MD5-encrypted or plain-text
+    passwords.  If `md5` is configured and a user has a SCRAM secret,
+    then SCRAM authentication is used automatically instead.
+
+scram-sha-256
+:   Use password check with SCRAM-SHA-256.  `auth_file` has to contain
+    SCRAM secrets or plain-text passwords.  Note that SCRAM secrets
+    can only be used for verifying the password of a client but not
+    for logging into a server.  To be able to use SCRAM on server
+    connections, use plain-text passwords.
 
 plain
 :   Clear-text password is sent over wire.  Deprecated.
@@ -806,7 +815,7 @@ username, meaning that there will be one pool per user.
 
 ### password
 
-The length for `password` is limited to 128 characters maximum.
+The length for `password` is limited to 160 characters maximum.
 
 If no password is specified here, the password from the `auth_file` or
 `auth_query` will be used.
@@ -892,10 +901,11 @@ file in following format:
 
     "username1" "password" ...
     "username2" "md5abcdef012342345" ...
+    "username2" "SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>"
 
 There should be at least 2 fields, surrounded by double quotes. The first
-field is the username and the second is either a plain-text or a MD5-hidden
-password.  PgBouncer ignores the rest of the line.
+field is the username and the second is either a plain-text, a MD5-hidden
+password, or a SCRAM secret.  PgBouncer ignores the rest of the line.
 
 PostgreSQL MD5-hidden password format:
 
@@ -904,6 +914,12 @@ PostgreSQL MD5-hidden password format:
 So user `admin` with password `1234` will have MD5-hidden password
 `md545f2603610af569b6155c45067268c6b`.
 
+PostgreSQL SCRAM secret format:
+
+    SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
+
+See the PostgreSQL documentation and RFC 5803 for details on this.
+
 The authentication file can be written by hand, but it's also useful
 to generate it from some other list of users and passwords.  See
 `./etc/mkauth.py` for a sample script to generate the authentication
diff --git a/etc/import-common.sh b/etc/import-common.sh
new file mode 100644 (file)
index 0000000..67fa7dc
--- /dev/null
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+set -eu
+
+# Script to import common files from PostgreSQL source tree for SCRAM
+# support.  Run this from time to time, ideally against the latest
+# tagged and released stable minor version of PostgreSQL.
+#
+# The files are not taken verbatim.  Especially the header file
+# includes are adjusted.  So go through the changes with "git app -p"
+# or similar after this.
+
+pgsrcdir=$1
+
+common_include='
+src/include/common/base64.h
+src/include/mb/pg_wchar.h
+src/include/common/saslprep.h
+src/include/common/scram-common.h
+src/include/common/unicode_norm.h
+src/include/common/unicode_norm_table.h
+'
+
+common_src='
+src/common/base64.c
+src/common/saslprep.c
+src/common/scram-common.c
+src/common/unicode_norm.c
+src/backend/utils/mb/wchar.c
+'
+
+for file in $common_include; do cp -v $pgsrcdir/$file include/common/; done
+for file in $common_src; do cp -v $pgsrcdir/$file src/common; done
index 6485fef0da56a4f682e6dfdedd53b9bf29065e90..149a0967930babda98adfdb2c47c3b86fb1cee69 100644 (file)
@@ -84,6 +84,7 @@ typedef struct PgStats PgStats;
 typedef union PgAddr PgAddr;
 typedef enum SocketState SocketState;
 typedef struct PktHdr PktHdr;
+typedef struct ScramState ScramState;
 
 extern int cf_sbuf_len;
 
@@ -110,7 +111,8 @@ extern int cf_sbuf_len;
 /* to avoid allocations will use static buffers */
 #define MAX_DBNAME     64
 #define MAX_USERNAME   64
-#define MAX_PASSWORD   128
+/* typical SCRAM-SHA-256 verifier takes at least 133 bytes */
+#define MAX_PASSWORD   160
 
 /*
  * AUTH_* symbols are used for both protocol handling and
@@ -133,9 +135,9 @@ extern int cf_sbuf_len;
 #define AUTH_GSS       7       /* not supported */
 #define AUTH_GSS_CONT  8       /* not supported */
 #define AUTH_SSPI      9       /* not supported */
-#define AUTH_SASL      10      /* not supported */
-#define AUTH_SASL_CONT 11      /* not supported */
-#define AUTH_SASL_FIN  12      /* not supported */
+#define AUTH_SASL      10
+#define AUTH_SASL_CONT 11
+#define AUTH_SASL_FIN  12
 
 /* internal codes */
 #define AUTH_CERT      107
@@ -143,6 +145,7 @@ extern int cf_sbuf_len;
 #define AUTH_HBA       109
 #define AUTH_REJECT    110
 #define AUTH_PAM       111
+#define AUTH_SCRAM_SHA_256     112
 
 /* type codes for weird pkts */
 #define PKT_STARTUP_V2  0x20000
@@ -387,6 +390,19 @@ struct PgSocket {
                PgDatabase *db;                 /* cache db while doing auth query */
        };
 
+       struct ScramState {
+               char *client_nonce;
+               char *client_first_message_bare;
+               char *client_final_message_without_proof;
+               char *server_nonce;
+               char *server_first_message;
+               uint8_t *SaltedPassword;
+               int iterations;
+               char *salt;     /* base64-encoded */
+               uint8_t StoredKey[32];  /* SHA256_DIGEST_LENGTH */
+               uint8_t ServerKey[32];
+       } scram_state;
+
        VarCache vars;          /* state of interesting server parameters */
 
        SBuf sbuf;              /* stream buffer, must be last */
diff --git a/include/common/base64.h b/include/common/base64.h
new file mode 100644 (file)
index 0000000..32cec4b
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * base64.h
+ *       Encoding and decoding routines for base64 without whitespace
+ *       support.
+ *
+ * Portions Copyright (c) 2001-2018, PostgreSQL Global Development Group
+ *
+ * src/include/common/base64.h
+ */
+#ifndef BASE64_H
+#define BASE64_H
+
+/* base 64 */
+extern int     pg_b64_encode(const char *src, int len, char *dst);
+extern int     pg_b64_decode(const char *src, int len, char *dst);
+extern int     pg_b64_enc_len(int srclen);
+extern int     pg_b64_dec_len(int srclen);
+
+#endif                                                 /* BASE64_H */
diff --git a/include/common/pg_wchar.h b/include/common/pg_wchar.h
new file mode 100644 (file)
index 0000000..748db5b
--- /dev/null
@@ -0,0 +1,636 @@
+/*-------------------------------------------------------------------------
+ *
+ * pg_wchar.h
+ *       multibyte-character support
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/mb/pg_wchar.h
+ *
+ *     NOTES
+ *             This is used both by the backend and by libpq, but should not be
+ *             included by libpq client programs.  In particular, a libpq client
+ *             should not assume that the encoding IDs used by the version of libpq
+ *             it's linked to match up with the IDs declared here.
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef PG_WCHAR_H
+#define PG_WCHAR_H
+
+/*
+ * The pg_wchar type
+ */
+typedef unsigned int pg_wchar;
+
+/*
+ * Maximum byte length of multibyte characters in any backend encoding
+ */
+#define MAX_MULTIBYTE_CHAR_LEN 4
+
+/*
+ * various definitions for EUC
+ */
+#define SS2 0x8e                               /* single shift 2 (JIS0201) */
+#define SS3 0x8f                               /* single shift 3 (JIS0212) */
+
+/*
+ * SJIS validation macros
+ */
+#define ISSJISHEAD(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xfc))
+#define ISSJISTAIL(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
+
+/*----------------------------------------------------
+ * MULE Internal Encoding (MIC)
+ *
+ * This encoding follows the design used within XEmacs; it is meant to
+ * subsume many externally-defined character sets.  Each character includes
+ * identification of the character set it belongs to, so the encoding is
+ * general but somewhat bulky.
+ *
+ * Currently PostgreSQL supports 5 types of MULE character sets:
+ *
+ * 1) 1-byte ASCII characters.  Each byte is below 0x80.
+ *
+ * 2) "Official" single byte charsets such as ISO-8859-1 (Latin1).
+ *       Each MULE character consists of 2 bytes: LC1 + C1, where LC1 is
+ *       an identifier for the charset (in the range 0x81 to 0x8d) and C1
+ *       is the character code (in the range 0xa0 to 0xff).
+ *
+ * 3) "Private" single byte charsets such as SISHENG.  Each MULE
+ *       character consists of 3 bytes: LCPRV1 + LC12 + C1, where LCPRV1
+ *       is a private-charset flag, LC12 is an identifier for the charset,
+ *       and C1 is the character code (in the range 0xa0 to 0xff).
+ *       LCPRV1 is either 0x9a (if LC12 is in the range 0xa0 to 0xdf)
+ *       or 0x9b (if LC12 is in the range 0xe0 to 0xef).
+ *
+ * 4) "Official" multibyte charsets such as JIS X0208.  Each MULE
+ *       character consists of 3 bytes: LC2 + C1 + C2, where LC2 is
+ *       an identifier for the charset (in the range 0x90 to 0x99) and C1
+ *       and C2 form the character code (each in the range 0xa0 to 0xff).
+ *
+ * 5) "Private" multibyte charsets such as CNS 11643-1992 Plane 3.
+ *       Each MULE character consists of 4 bytes: LCPRV2 + LC22 + C1 + C2,
+ *       where LCPRV2 is a private-charset flag, LC22 is an identifier for
+ *       the charset, and C1 and C2 form the character code (each in the range
+ *       0xa0 to 0xff).  LCPRV2 is either 0x9c (if LC22 is in the range 0xf0
+ *       to 0xf4) or 0x9d (if LC22 is in the range 0xf5 to 0xfe).
+ *
+ * "Official" encodings are those that have been assigned code numbers by
+ * the XEmacs project; "private" encodings have Postgres-specific charset
+ * identifiers.
+ *
+ * See the "XEmacs Internals Manual", available at http://www.xemacs.org,
+ * for more details.  Note that for historical reasons, Postgres'
+ * private-charset flag values do not match what XEmacs says they should be,
+ * so this isn't really exactly MULE (not that private charsets would be
+ * interoperable anyway).
+ *
+ * Note that XEmacs's implementation is different from what emacs does.
+ * We follow emacs's implementation, rather than XEmacs's.
+ *----------------------------------------------------
+ */
+
+/*
+ * Charset identifiers (also called "leading bytes" in the MULE documentation)
+ */
+
+/*
+ * Charset IDs for official single byte encodings (0x81-0x8e)
+ */
+#define LC_ISO8859_1           0x81    /* ISO8859 Latin 1 */
+#define LC_ISO8859_2           0x82    /* ISO8859 Latin 2 */
+#define LC_ISO8859_3           0x83    /* ISO8859 Latin 3 */
+#define LC_ISO8859_4           0x84    /* ISO8859 Latin 4 */
+#define LC_TIS620                      0x85    /* Thai (not supported yet) */
+#define LC_ISO8859_7           0x86    /* Greek (not supported yet) */
+#define LC_ISO8859_6           0x87    /* Arabic (not supported yet) */
+#define LC_ISO8859_8           0x88    /* Hebrew (not supported yet) */
+#define LC_JISX0201K           0x89    /* Japanese 1 byte kana */
+#define LC_JISX0201R           0x8a    /* Japanese 1 byte Roman */
+/* Note that 0x8b seems to be unused as of Emacs 20.7.
+ * However, there might be a chance that 0x8b could be used
+ * in later versions of Emacs.
+ */
+#define LC_KOI8_R                      0x8b    /* Cyrillic KOI8-R */
+#define LC_ISO8859_5           0x8c    /* ISO8859 Cyrillic */
+#define LC_ISO8859_9           0x8d    /* ISO8859 Latin 5 (not supported yet) */
+#define LC_ISO8859_15          0x8e    /* ISO8859 Latin 15 (not supported yet) */
+/* #define CONTROL_1           0x8f    control characters (unused) */
+
+/* Is a leading byte for "official" single byte encodings? */
+#define IS_LC1(c)      ((unsigned char)(c) >= 0x81 && (unsigned char)(c) <= 0x8d)
+
+/*
+ * Charset IDs for official multibyte encodings (0x90-0x99)
+ * 0x9a-0x9d are free. 0x9e and 0x9f are reserved.
+ */
+#define LC_JISX0208_1978       0x90    /* Japanese Kanji, old JIS (not supported) */
+#define LC_GB2312_80           0x91    /* Chinese */
+#define LC_JISX0208                    0x92    /* Japanese Kanji (JIS X 0208) */
+#define LC_KS5601                      0x93    /* Korean */
+#define LC_JISX0212                    0x94    /* Japanese Kanji (JIS X 0212) */
+#define LC_CNS11643_1          0x95    /* CNS 11643-1992 Plane 1 */
+#define LC_CNS11643_2          0x96    /* CNS 11643-1992 Plane 2 */
+#define LC_JISX0213_1          0x97    /* Japanese Kanji (JIS X 0213 Plane 1)
+                                                                        * (not supported) */
+#define LC_BIG5_1                      0x98    /* Plane 1 Chinese traditional (not
+                                                                        * supported) */
+#define LC_BIG5_2                      0x99    /* Plane 1 Chinese traditional (not
+                                                                        * supported) */
+
+/* Is a leading byte for "official" multibyte encodings? */
+#define IS_LC2(c)      ((unsigned char)(c) >= 0x90 && (unsigned char)(c) <= 0x99)
+
+/*
+ * Postgres-specific prefix bytes for "private" single byte encodings
+ * (According to the MULE docs, we should be using 0x9e for this)
+ */
+#define LCPRV1_A               0x9a
+#define LCPRV1_B               0x9b
+#define IS_LCPRV1(c)   ((unsigned char)(c) == LCPRV1_A || (unsigned char)(c) == LCPRV1_B)
+#define IS_LCPRV1_A_RANGE(c)   \
+       ((unsigned char)(c) >= 0xa0 && (unsigned char)(c) <= 0xdf)
+#define IS_LCPRV1_B_RANGE(c)   \
+       ((unsigned char)(c) >= 0xe0 && (unsigned char)(c) <= 0xef)
+
+/*
+ * Postgres-specific prefix bytes for "private" multibyte encodings
+ * (According to the MULE docs, we should be using 0x9f for this)
+ */
+#define LCPRV2_A               0x9c
+#define LCPRV2_B               0x9d
+#define IS_LCPRV2(c)   ((unsigned char)(c) == LCPRV2_A || (unsigned char)(c) == LCPRV2_B)
+#define IS_LCPRV2_A_RANGE(c)   \
+       ((unsigned char)(c) >= 0xf0 && (unsigned char)(c) <= 0xf4)
+#define IS_LCPRV2_B_RANGE(c)   \
+       ((unsigned char)(c) >= 0xf5 && (unsigned char)(c) <= 0xfe)
+
+/*
+ * Charset IDs for private single byte encodings (0xa0-0xef)
+ */
+#define LC_SISHENG                     0xa0    /* Chinese SiSheng characters for
+                                                                        * PinYin/ZhuYin (not supported) */
+#define LC_IPA                         0xa1    /* IPA (International Phonetic
+                                                                        * Association) (not supported) */
+#define LC_VISCII_LOWER                0xa2    /* Vietnamese VISCII1.1 lower-case (not
+                                                                        * supported) */
+#define LC_VISCII_UPPER                0xa3    /* Vietnamese VISCII1.1 upper-case (not
+                                                                        * supported) */
+#define LC_ARABIC_DIGIT                0xa4    /* Arabic digit (not supported) */
+#define LC_ARABIC_1_COLUMN     0xa5    /* Arabic 1-column (not supported) */
+#define LC_ASCII_RIGHT_TO_LEFT 0xa6    /* ASCII (left half of ISO8859-1) with
+                                                                                * right-to-left direction (not
+                                                                                * supported) */
+#define LC_LAO                         0xa7    /* Lao characters (ISO10646 0E80..0EDF)
+                                                                        * (not supported) */
+#define LC_ARABIC_2_COLUMN     0xa8    /* Arabic 1-column (not supported) */
+
+/*
+ * Charset IDs for private multibyte encodings (0xf0-0xff)
+ */
+#define LC_INDIAN_1_COLUMN     0xf0    /* Indian charset for 1-column width
+                                                                        * glyphs (not supported) */
+#define LC_TIBETAN_1_COLUMN 0xf1       /* Tibetan 1-column width glyphs (not
+                                                                        * supported) */
+#define LC_UNICODE_SUBSET_2 0xf2       /* Unicode characters of the range
+                                                                        * U+2500..U+33FF. (not supported) */
+#define LC_UNICODE_SUBSET_3 0xf3       /* Unicode characters of the range
+                                                                        * U+E000..U+FFFF. (not supported) */
+#define LC_UNICODE_SUBSET      0xf4    /* Unicode characters of the range
+                                                                        * U+0100..U+24FF. (not supported) */
+#define LC_ETHIOPIC                    0xf5    /* Ethiopic characters (not supported) */
+#define LC_CNS11643_3          0xf6    /* CNS 11643-1992 Plane 3 */
+#define LC_CNS11643_4          0xf7    /* CNS 11643-1992 Plane 4 */
+#define LC_CNS11643_5          0xf8    /* CNS 11643-1992 Plane 5 */
+#define LC_CNS11643_6          0xf9    /* CNS 11643-1992 Plane 6 */
+#define LC_CNS11643_7          0xfa    /* CNS 11643-1992 Plane 7 */
+#define LC_INDIAN_2_COLUMN     0xfb    /* Indian charset for 2-column width
+                                                                        * glyphs (not supported) */
+#define LC_TIBETAN                     0xfc    /* Tibetan (not supported) */
+/* #define FREE                                0xfd    free (unused) */
+/* #define FREE                                0xfe    free (unused) */
+/* #define FREE                                0xff    free (unused) */
+
+/*----------------------------------------------------
+ * end of MULE stuff
+ *----------------------------------------------------
+ */
+
+/*
+ * PostgreSQL encoding identifiers
+ *
+ * WARNING: the order of this enum must be same as order of entries
+ *                     in the pg_enc2name_tbl[] array (in mb/encnames.c), and
+ *                     in the pg_wchar_table[] array (in mb/wchar.c)!
+ *
+ *                     If you add some encoding don't forget to check
+ *                     PG_ENCODING_BE_LAST macro.
+ *
+ * PG_SQL_ASCII is default encoding and must be = 0.
+ *
+ * XXX We must avoid renumbering any backend encoding until libpq's major
+ * version number is increased beyond 5; it turns out that the backend
+ * encoding IDs are effectively part of libpq's ABI as far as 8.2 initdb and
+ * psql are concerned.
+ */
+typedef enum pg_enc
+{
+       PG_SQL_ASCII = 0,                       /* SQL/ASCII */
+       PG_EUC_JP,                                      /* EUC for Japanese */
+       PG_EUC_CN,                                      /* EUC for Chinese */
+       PG_EUC_KR,                                      /* EUC for Korean */
+       PG_EUC_TW,                                      /* EUC for Taiwan */
+       PG_EUC_JIS_2004,                        /* EUC-JIS-2004 */
+       PG_UTF8,                                        /* Unicode UTF8 */
+       PG_MULE_INTERNAL,                       /* Mule internal code */
+       PG_LATIN1,                                      /* ISO-8859-1 Latin 1 */
+       PG_LATIN2,                                      /* ISO-8859-2 Latin 2 */
+       PG_LATIN3,                                      /* ISO-8859-3 Latin 3 */
+       PG_LATIN4,                                      /* ISO-8859-4 Latin 4 */
+       PG_LATIN5,                                      /* ISO-8859-9 Latin 5 */
+       PG_LATIN6,                                      /* ISO-8859-10 Latin6 */
+       PG_LATIN7,                                      /* ISO-8859-13 Latin7 */
+       PG_LATIN8,                                      /* ISO-8859-14 Latin8 */
+       PG_LATIN9,                                      /* ISO-8859-15 Latin9 */
+       PG_LATIN10,                                     /* ISO-8859-16 Latin10 */
+       PG_WIN1256,                                     /* windows-1256 */
+       PG_WIN1258,                                     /* Windows-1258 */
+       PG_WIN866,                                      /* (MS-DOS CP866) */
+       PG_WIN874,                                      /* windows-874 */
+       PG_KOI8R,                                       /* KOI8-R */
+       PG_WIN1251,                                     /* windows-1251 */
+       PG_WIN1252,                                     /* windows-1252 */
+       PG_ISO_8859_5,                          /* ISO-8859-5 */
+       PG_ISO_8859_6,                          /* ISO-8859-6 */
+       PG_ISO_8859_7,                          /* ISO-8859-7 */
+       PG_ISO_8859_8,                          /* ISO-8859-8 */
+       PG_WIN1250,                                     /* windows-1250 */
+       PG_WIN1253,                                     /* windows-1253 */
+       PG_WIN1254,                                     /* windows-1254 */
+       PG_WIN1255,                                     /* windows-1255 */
+       PG_WIN1257,                                     /* windows-1257 */
+       PG_KOI8U,                                       /* KOI8-U */
+       /* PG_ENCODING_BE_LAST points to the above entry */
+
+       /* followings are for client encoding only */
+       PG_SJIS,                                        /* Shift JIS (Windows-932) */
+       PG_BIG5,                                        /* Big5 (Windows-950) */
+       PG_GBK,                                         /* GBK (Windows-936) */
+       PG_UHC,                                         /* UHC (Windows-949) */
+       PG_GB18030,                                     /* GB18030 */
+       PG_JOHAB,                                       /* EUC for Korean JOHAB */
+       PG_SHIFT_JIS_2004,                      /* Shift-JIS-2004 */
+       _PG_LAST_ENCODING_                      /* mark only */
+
+} pg_enc;
+
+#define PG_ENCODING_BE_LAST PG_KOI8U
+
+/*
+ * Please use these tests before access to pg_encconv_tbl[]
+ * or to other places...
+ */
+#define PG_VALID_BE_ENCODING(_enc) \
+               ((_enc) >= 0 && (_enc) <= PG_ENCODING_BE_LAST)
+
+#define PG_ENCODING_IS_CLIENT_ONLY(_enc) \
+               ((_enc) > PG_ENCODING_BE_LAST && (_enc) < _PG_LAST_ENCODING_)
+
+#define PG_VALID_ENCODING(_enc) \
+               ((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_)
+
+/* On FE are possible all encodings */
+#define PG_VALID_FE_ENCODING(_enc)     PG_VALID_ENCODING(_enc)
+
+/*
+ * When converting strings between different encodings, we assume that space
+ * for converted result is 4-to-1 growth in the worst case. The rate for
+ * currently supported encoding pairs are within 3 (SJIS JIS X0201 half width
+ * kanna -> UTF8 is the worst case).  So "4" should be enough for the moment.
+ *
+ * Note that this is not the same as the maximum character width in any
+ * particular encoding.
+ */
+#define MAX_CONVERSION_GROWTH  4
+
+/*
+ * Table for mapping an encoding number to official encoding name and
+ * possibly other subsidiary data.  Be careful to check encoding number
+ * before accessing a table entry!
+ *
+ * if (PG_VALID_ENCODING(encoding))
+ *             pg_enc2name_tbl[ encoding ];
+ */
+typedef struct pg_enc2name
+{
+       const char *name;
+       pg_enc          encoding;
+#ifdef WIN32
+       unsigned        codepage;               /* codepage for WIN32 */
+#endif
+} pg_enc2name;
+
+extern const pg_enc2name pg_enc2name_tbl[];
+
+/*
+ * Encoding names for gettext
+ */
+typedef struct pg_enc2gettext
+{
+       pg_enc          encoding;
+       const char *name;
+} pg_enc2gettext;
+
+extern const pg_enc2gettext pg_enc2gettext_tbl[];
+
+/*
+ * Encoding names for ICU
+ */
+extern bool is_encoding_supported_by_icu(int encoding);
+extern const char *get_encoding_name_for_icu(int encoding);
+
+/*
+ * pg_wchar stuff
+ */
+typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
+                                                                                       pg_wchar *to,
+                                                                                       int len);
+
+typedef int (*wchar2mb_with_len_converter) (const pg_wchar *from,
+                                                                                       unsigned char *to,
+                                                                                       int len);
+
+typedef int (*mblen_converter) (const unsigned char *mbstr);
+
+typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr);
+
+typedef bool (*mbcharacter_incrementer) (unsigned char *mbstr, int len);
+
+typedef int (*mbverifier) (const unsigned char *mbstr, int len);
+
+typedef struct
+{
+       mb2wchar_with_len_converter mb2wchar_with_len;  /* convert a multibyte
+                                                                                                        * string to a wchar */
+       wchar2mb_with_len_converter wchar2mb_with_len;  /* convert a wchar string
+                                                                                                        * to a multibyte */
+       mblen_converter mblen;          /* get byte length of a char */
+       mbdisplaylen_converter dsplen;  /* get display width of a char */
+       mbverifier      mbverify;               /* verify multibyte sequence */
+       int                     maxmblen;               /* max bytes for a char in this encoding */
+} pg_wchar_tbl;
+
+extern const pg_wchar_tbl pg_wchar_table[];
+
+/*
+ * Data structures for conversions between UTF-8 and other encodings
+ * (UtfToLocal() and LocalToUtf()).  In these data structures, characters of
+ * either encoding are represented by uint32 words; hence we can only support
+ * characters up to 4 bytes long.  For example, the byte sequence 0xC2 0x89
+ * would be represented by 0x0000C289, and 0xE8 0xA2 0xB4 by 0x00E8A2B4.
+ *
+ * There are three possible ways a character can be mapped:
+ *
+ * 1. Using a radix tree, from source to destination code.
+ * 2. Using a sorted array of source -> destination code pairs. This
+ *       method is used for "combining" characters. There are so few of
+ *       them that building a radix tree would be wasteful.
+ * 3. Using a conversion function.
+ */
+
+/*
+ * Radix tree for character conversion.
+ *
+ * Logically, this is actually four different radix trees, for 1-byte,
+ * 2-byte, 3-byte and 4-byte inputs. The 1-byte tree is a simple lookup
+ * table from source to target code. The 2-byte tree consists of two levels:
+ * one lookup table for the first byte, where the value in the lookup table
+ * points to a lookup table for the second byte. And so on.
+ *
+ * Physically, all the trees are stored in one big array, in 'chars16' or
+ * 'chars32', depending on the maximum value that needs to be represented. For
+ * each level in each tree, we also store lower and upper bound of allowed
+ * values - values outside those bounds are considered invalid, and are left
+ * out of the tables.
+ *
+ * In the intermediate levels of the trees, the values stored are offsets
+ * into the chars[16|32] array.
+ *
+ * In the beginning of the chars[16|32] array, there is always a number of
+ * zeros, so that you safely follow an index from an intermediate table
+ * without explicitly checking for a zero. Following a zero any number of
+ * times will always bring you to the dummy, all-zeros table in the
+ * beginning. This helps to shave some cycles when looking up values.
+ */
+typedef struct
+{
+       /*
+        * Array containing all the values. Only one of chars16 or chars32 is
+        * used, depending on how wide the values we need to represent are.
+        */
+       const uint16 *chars16;
+       const uint32 *chars32;
+
+       /* Radix tree for 1-byte inputs */
+       uint32          b1root;                 /* offset of table in the chars[16|32] array */
+       uint8           b1_lower;               /* min allowed value for a single byte input */
+       uint8           b1_upper;               /* max allowed value for a single byte input */
+
+       /* Radix tree for 2-byte inputs */
+       uint32          b2root;                 /* offset of 1st byte's table */
+       uint8           b2_1_lower;             /* min/max allowed value for 1st input byte */
+       uint8           b2_1_upper;
+       uint8           b2_2_lower;             /* min/max allowed value for 2nd input byte */
+       uint8           b2_2_upper;
+
+       /* Radix tree for 3-byte inputs */
+       uint32          b3root;                 /* offset of 1st byte's table */
+       uint8           b3_1_lower;             /* min/max allowed value for 1st input byte */
+       uint8           b3_1_upper;
+       uint8           b3_2_lower;             /* min/max allowed value for 2nd input byte */
+       uint8           b3_2_upper;
+       uint8           b3_3_lower;             /* min/max allowed value for 3rd input byte */
+       uint8           b3_3_upper;
+
+       /* Radix tree for 4-byte inputs */
+       uint32          b4root;                 /* offset of 1st byte's table */
+       uint8           b4_1_lower;             /* min/max allowed value for 1st input byte */
+       uint8           b4_1_upper;
+       uint8           b4_2_lower;             /* min/max allowed value for 2nd input byte */
+       uint8           b4_2_upper;
+       uint8           b4_3_lower;             /* min/max allowed value for 3rd input byte */
+       uint8           b4_3_upper;
+       uint8           b4_4_lower;             /* min/max allowed value for 4th input byte */
+       uint8           b4_4_upper;
+
+} pg_mb_radix_tree;
+
+/*
+ * UTF-8 to local code conversion map (for combined characters)
+ */
+typedef struct
+{
+       uint32          utf1;                   /* UTF-8 code 1 */
+       uint32          utf2;                   /* UTF-8 code 2 */
+       uint32          code;                   /* local code */
+} pg_utf_to_local_combined;
+
+/*
+ * local code to UTF-8 conversion map (for combined characters)
+ */
+typedef struct
+{
+       uint32          code;                   /* local code */
+       uint32          utf1;                   /* UTF-8 code 1 */
+       uint32          utf2;                   /* UTF-8 code 2 */
+} pg_local_to_utf_combined;
+
+/*
+ * callback function for algorithmic encoding conversions (in either direction)
+ *
+ * if function returns zero, it does not know how to convert the code
+ */
+typedef uint32 (*utf_local_conversion_func) (uint32 code);
+
+/*
+ * Support macro for encoding conversion functions to validate their
+ * arguments.  (This could be made more compact if we included fmgr.h
+ * here, but we don't want to do that because this header file is also
+ * used by frontends.)
+ */
+#define CHECK_ENCODING_CONVERSION_ARGS(srcencoding,destencoding) \
+       check_encoding_conversion_args(PG_GETARG_INT32(0), \
+                                                                  PG_GETARG_INT32(1), \
+                                                                  PG_GETARG_INT32(4), \
+                                                                  (srcencoding), \
+                                                                  (destencoding))
+
+
+/*
+ * These functions are considered part of libpq's exported API and
+ * are also declared in libpq-fe.h.
+ */
+extern int     pg_char_to_encoding(const char *name);
+extern const char *pg_encoding_to_char(int encoding);
+extern int     pg_valid_server_encoding_id(int encoding);
+
+/*
+ * Remaining functions are not considered part of libpq's API, though many
+ * of them do exist inside libpq.
+ */
+extern int     pg_mb2wchar(const char *from, pg_wchar *to);
+extern int     pg_mb2wchar_with_len(const char *from, pg_wchar *to, int len);
+extern int pg_encoding_mb2wchar_with_len(int encoding,
+                                                         const char *from, pg_wchar *to, int len);
+extern int     pg_wchar2mb(const pg_wchar *from, char *to);
+extern int     pg_wchar2mb_with_len(const pg_wchar *from, char *to, int len);
+extern int pg_encoding_wchar2mb_with_len(int encoding,
+                                                         const pg_wchar *from, char *to, int len);
+extern int     pg_char_and_wchar_strcmp(const char *s1, const pg_wchar *s2);
+extern int     pg_wchar_strncmp(const pg_wchar *s1, const pg_wchar *s2, size_t n);
+extern int     pg_char_and_wchar_strncmp(const char *s1, const pg_wchar *s2, size_t n);
+extern size_t pg_wchar_strlen(const pg_wchar *wstr);
+extern int     pg_mblen(const char *mbstr);
+extern int     pg_dsplen(const char *mbstr);
+extern int     pg_encoding_mblen(int encoding, const char *mbstr);
+extern int     pg_encoding_dsplen(int encoding, const char *mbstr);
+extern int     pg_encoding_verifymb(int encoding, const char *mbstr, int len);
+extern int     pg_mule_mblen(const unsigned char *mbstr);
+extern int     pg_mic_mblen(const unsigned char *mbstr);
+extern int     pg_mbstrlen(const char *mbstr);
+extern int     pg_mbstrlen_with_len(const char *mbstr, int len);
+extern int     pg_mbcliplen(const char *mbstr, int len, int limit);
+extern int pg_encoding_mbcliplen(int encoding, const char *mbstr,
+                                         int len, int limit);
+extern int     pg_mbcharcliplen(const char *mbstr, int len, int imit);
+extern int     pg_encoding_max_length(int encoding);
+extern int     pg_database_encoding_max_length(void);
+extern mbcharacter_incrementer pg_database_encoding_character_incrementer(void);
+
+extern int     PrepareClientEncoding(int encoding);
+extern int     SetClientEncoding(int encoding);
+extern void InitializeClientEncoding(void);
+extern int     pg_get_client_encoding(void);
+extern const char *pg_get_client_encoding_name(void);
+
+extern void SetDatabaseEncoding(int encoding);
+extern int     GetDatabaseEncoding(void);
+extern const char *GetDatabaseEncodingName(void);
+extern void SetMessageEncoding(int encoding);
+extern int     GetMessageEncoding(void);
+
+#ifdef ENABLE_NLS
+extern int     pg_bind_textdomain_codeset(const char *domainname);
+#endif
+
+extern int     pg_valid_client_encoding(const char *name);
+extern int     pg_valid_server_encoding(const char *name);
+
+extern unsigned char *unicode_to_utf8(pg_wchar c, unsigned char *utf8string);
+extern pg_wchar utf8_to_unicode(const unsigned char *c);
+extern int     pg_utf_mblen(const unsigned char *);
+extern unsigned char *pg_do_encoding_conversion(unsigned char *src, int len,
+                                                 int src_encoding,
+                                                 int dest_encoding);
+
+extern char *pg_client_to_server(const char *s, int len);
+extern char *pg_server_to_client(const char *s, int len);
+extern char *pg_any_to_server(const char *s, int len, int encoding);
+extern char *pg_server_to_any(const char *s, int len, int encoding);
+
+extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc);
+extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc);
+
+extern void UtfToLocal(const unsigned char *utf, int len,
+                  unsigned char *iso,
+                  const pg_mb_radix_tree *map,
+                  const pg_utf_to_local_combined *cmap, int cmapsize,
+                  utf_local_conversion_func conv_func,
+                  int encoding);
+extern void LocalToUtf(const unsigned char *iso, int len,
+                  unsigned char *utf,
+                  const pg_mb_radix_tree *map,
+                  const pg_local_to_utf_combined *cmap, int cmapsize,
+                  utf_local_conversion_func conv_func,
+                  int encoding);
+
+extern bool pg_verifymbstr(const char *mbstr, int len, bool noError);
+extern bool pg_verify_mbstr(int encoding, const char *mbstr, int len,
+                               bool noError);
+extern int pg_verify_mbstr_len(int encoding, const char *mbstr, int len,
+                                       bool noError);
+
+extern void check_encoding_conversion_args(int src_encoding,
+                                                          int dest_encoding,
+                                                          int len,
+                                                          int expected_src_encoding,
+                                                          int expected_dest_encoding);
+
+extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn();
+extern void report_untranslatable_char(int src_encoding, int dest_encoding,
+                                                  const char *mbstr, int len) pg_attribute_noreturn();
+
+extern void local2local(const unsigned char *l, unsigned char *p, int len,
+                       int src_encoding, int dest_encoding, const unsigned char *tab);
+extern void pg_ascii2mic(const unsigned char *l, unsigned char *p, int len);
+extern void pg_mic2ascii(const unsigned char *mic, unsigned char *p, int len);
+extern void latin2mic(const unsigned char *l, unsigned char *p, int len,
+                 int lc, int encoding);
+extern void mic2latin(const unsigned char *mic, unsigned char *p, int len,
+                 int lc, int encoding);
+extern void latin2mic_with_table(const unsigned char *l, unsigned char *p,
+                                        int len, int lc, int encoding,
+                                        const unsigned char *tab);
+extern void mic2latin_with_table(const unsigned char *mic, unsigned char *p,
+                                        int len, int lc, int encoding,
+                                        const unsigned char *tab);
+
+extern bool pg_utf8_islegal(const unsigned char *source, int length);
+
+#ifdef WIN32
+extern WCHAR *pgwin32_message_to_UTF16(const char *str, int len, int *utf16len);
+#endif
+
+#endif                                                 /* PG_WCHAR_H */
diff --git a/include/common/postgres_compat.h b/include/common/postgres_compat.h
new file mode 100644 (file)
index 0000000..71afe25
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Various things to allow source files from postgresql code to be
+ * used in pgbouncer.  pgbouncer's system.h needs to be included
+ * before this.
+ */
+
+/* from c.h */
+
+#include <string.h>
+
+#define int8 int8_t
+#define uint8 uint8_t
+#define uint16 uint16_t
+#define uint32 uint32_t
+
+#define lengthof(array) (sizeof (array) / sizeof ((array)[0]))
+#define pg_hton32(x) htobe32(x)
+
+#define pg_attribute_noreturn() _NORETURN
+
+#define HIGHBIT                                        (0x80)
+#define IS_HIGHBIT_SET(ch)             ((unsigned char)(ch) & HIGHBIT)
+
+
+/* sha2.h compat */
+#define pg_sha256_ctx struct sha256_ctx
+#define PG_SHA256_BLOCK_LENGTH SHA256_BLOCK_SIZE
+#define PG_SHA256_DIGEST_LENGTH SHA256_DIGEST_LENGTH
+#define pg_sha256_init(ctx) sha256_reset(ctx)
+#define pg_sha256_update(ctx, data, len) sha256_update(ctx, data, len)
+#define pg_sha256_final(ctx, dst) sha256_final(ctx, dst)
+
+
+/* define this to use non-server code paths */
+#define FRONTEND
diff --git a/include/common/saslprep.h b/include/common/saslprep.h
new file mode 100644 (file)
index 0000000..dc1af15
--- /dev/null
@@ -0,0 +1,30 @@
+/*-------------------------------------------------------------------------
+ *
+ * saslprep.h
+ *       SASLprep normalization, for SCRAM authentication
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2018, PostgreSQL Global Development Group
+ *
+ * src/include/common/saslprep.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SASLPREP_H
+#define SASLPREP_H
+
+/*
+ * Return codes for pg_saslprep() function.
+ */
+typedef enum
+{
+       SASLPREP_SUCCESS = 0,
+       SASLPREP_OOM = -1,                      /* out of memory (only in frontend) */
+       SASLPREP_INVALID_UTF8 = -2, /* input is not a valid UTF-8 string */
+       SASLPREP_PROHIBITED = -3        /* output would contain prohibited characters */
+} pg_saslprep_rc;
+
+extern pg_saslprep_rc pg_saslprep(const char *input, char **output);
+
+#endif                                                 /* SASLPREP_H */
diff --git a/include/common/scram-common.h b/include/common/scram-common.h
new file mode 100644 (file)
index 0000000..196b2e7
--- /dev/null
@@ -0,0 +1,72 @@
+/*-------------------------------------------------------------------------
+ *
+ * scram-common.h
+ *             Declarations for helper functions used for SCRAM authentication
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/scram-common.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef SCRAM_COMMON_H
+#define SCRAM_COMMON_H
+
+#include "common/postgres_compat.h"
+//#include "common/sha2.h"
+#include "usual/crypto/sha256.h"
+
+/* Name of SCRAM mechanisms per IANA */
+#define SCRAM_SHA_256_NAME "SCRAM-SHA-256"
+#define SCRAM_SHA_256_PLUS_NAME "SCRAM-SHA-256-PLUS"   /* with channel binding */
+
+/* Length of SCRAM keys (client and server) */
+#define SCRAM_KEY_LEN                          PG_SHA256_DIGEST_LENGTH
+
+/* length of HMAC */
+#define SHA256_HMAC_B                          PG_SHA256_BLOCK_LENGTH
+
+/*
+ * Size of random nonce generated in the authentication exchange.  This
+ * is in "raw" number of bytes, the actual nonces sent over the wire are
+ * encoded using only ASCII-printable characters.
+ */
+#define SCRAM_RAW_NONCE_LEN                    18
+
+/*
+ * Length of salt when generating new verifiers, in bytes.  (It will be stored
+ * and sent over the wire encoded in Base64.)  16 bytes is what the example in
+ * RFC 7677 uses.
+ */
+#define SCRAM_DEFAULT_SALT_LEN         16
+
+/*
+ * Default number of iterations when generating verifier.  Should be at least
+ * 4096 per RFC 7677.
+ */
+#define SCRAM_DEFAULT_ITERATIONS       4096
+
+/*
+ * Context data for HMAC used in SCRAM authentication.
+ */
+typedef struct
+{
+       pg_sha256_ctx sha256ctx;
+       uint8           k_opad[SHA256_HMAC_B];
+} scram_HMAC_ctx;
+
+extern void scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen);
+extern void scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen);
+extern void scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx);
+
+extern void scram_SaltedPassword(const char *password, const char *salt,
+                                        int saltlen, int iterations, uint8 *result);
+extern void scram_H(const uint8 *str, int len, uint8 *result);
+extern void scram_ClientKey(const uint8 *salted_password, uint8 *result);
+extern void scram_ServerKey(const uint8 *salted_password, uint8 *result);
+
+extern char *scram_build_verifier(const char *salt, int saltlen, int iterations,
+                                        const char *password);
+
+#endif                                                 /* SCRAM_COMMON_H */
diff --git a/include/common/unicode_norm.h b/include/common/unicode_norm.h
new file mode 100644 (file)
index 0000000..85e8be5
--- /dev/null
@@ -0,0 +1,22 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm.h
+ *       Routines for normalizing Unicode strings
+ *
+ * These definitions are used by both frontend and backend code.
+ *
+ * Copyright (c) 2017-2018, PostgreSQL Global Development Group
+ *
+ * src/include/common/unicode_norm.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef UNICODE_NORM_H
+#define UNICODE_NORM_H
+
+#include "common/postgres_compat.h"
+#include "common/pg_wchar.h"
+
+extern pg_wchar *unicode_normalize_kc(const pg_wchar *input);
+
+#endif                                                 /* UNICODE_NORM_H */
diff --git a/include/common/unicode_norm_table.h b/include/common/unicode_norm_table.h
new file mode 100644 (file)
index 0000000..3444bc8
--- /dev/null
@@ -0,0 +1,8860 @@
+/*-------------------------------------------------------------------------
+ *
+ * unicode_norm_table.h
+ *       Composition table used for Unicode normalization
+ *
+ * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/common/unicode_norm_table.h
+ *
+ *-------------------------------------------------------------------------
+ */
+
+/*
+ * File auto-generated by src/common/unicode/generate-unicode_norm_table.pl,
+ * do not edit. There is deliberately not an #ifndef PG_UNICODE_NORM_TABLE_H
+ * here.
+ */
+typedef struct
+{
+       uint32          codepoint;              /* Unicode codepoint */
+       uint8           comb_class;             /* combining class of character */
+       uint8           dec_size_flags; /* size and flags of decomposition code list */
+       uint16          dec_index;              /* index into UnicodeDecomp_codepoints, or the
+                                                                * decomposition itself if DECOMP_INLINE */
+} pg_unicode_decomposition;
+
+#define DECOMP_NO_COMPOSE      0x80    /* don't use for re-composition */
+#define DECOMP_INLINE          0x40    /* decomposition is stored inline in
+                                                                        * dec_index */
+
+#define DECOMPOSITION_SIZE(x) ((x)->dec_size_flags & 0x3F)
+#define DECOMPOSITION_NO_COMPOSE(x) (((x)->dec_size_flags & DECOMP_NO_COMPOSE) != 0)
+#define DECOMPOSITION_IS_INLINE(x) (((x)->dec_size_flags & DECOMP_INLINE) != 0)
+
+/* Table of Unicode codepoints and their decompositions */
+static const pg_unicode_decomposition UnicodeDecompMain[6532] =
+{
+       {0x00A0, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x00A8, 0, 2 | DECOMP_NO_COMPOSE, 0},  /* compatibility mapping */
+       {0x00AA, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x00AF, 0, 2 | DECOMP_NO_COMPOSE, 2},  /* compatibility mapping */
+       {0x00B2, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x00B3, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x00B4, 0, 2 | DECOMP_NO_COMPOSE, 4},  /* compatibility mapping */
+       {0x00B5, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x00B8, 0, 2 | DECOMP_NO_COMPOSE, 6},  /* compatibility mapping */
+       {0x00B9, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x00BA, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x00BC, 0, 3, 8},
+       {0x00BD, 0, 3, 11},
+       {0x00BE, 0, 3, 14},
+       {0x00C0, 0, 2, 17},
+       {0x00C1, 0, 2, 19},
+       {0x00C2, 0, 2, 21},
+       {0x00C3, 0, 2, 23},
+       {0x00C4, 0, 2, 25},
+       {0x00C5, 0, 2, 27},
+       {0x00C7, 0, 2, 29},
+       {0x00C8, 0, 2, 31},
+       {0x00C9, 0, 2, 33},
+       {0x00CA, 0, 2, 35},
+       {0x00CB, 0, 2, 37},
+       {0x00CC, 0, 2, 39},
+       {0x00CD, 0, 2, 41},
+       {0x00CE, 0, 2, 43},
+       {0x00CF, 0, 2, 45},
+       {0x00D1, 0, 2, 47},
+       {0x00D2, 0, 2, 49},
+       {0x00D3, 0, 2, 51},
+       {0x00D4, 0, 2, 53},
+       {0x00D5, 0, 2, 55},
+       {0x00D6, 0, 2, 57},
+       {0x00D9, 0, 2, 59},
+       {0x00DA, 0, 2, 61},
+       {0x00DB, 0, 2, 63},
+       {0x00DC, 0, 2, 65},
+       {0x00DD, 0, 2, 67},
+       {0x00E0, 0, 2, 69},
+       {0x00E1, 0, 2, 71},
+       {0x00E2, 0, 2, 73},
+       {0x00E3, 0, 2, 75},
+       {0x00E4, 0, 2, 77},
+       {0x00E5, 0, 2, 79},
+       {0x00E7, 0, 2, 81},
+       {0x00E8, 0, 2, 83},
+       {0x00E9, 0, 2, 85},
+       {0x00EA, 0, 2, 87},
+       {0x00EB, 0, 2, 89},
+       {0x00EC, 0, 2, 91},
+       {0x00ED, 0, 2, 93},
+       {0x00EE, 0, 2, 95},
+       {0x00EF, 0, 2, 97},
+       {0x00F1, 0, 2, 99},
+       {0x00F2, 0, 2, 101},
+       {0x00F3, 0, 2, 103},
+       {0x00F4, 0, 2, 105},
+       {0x00F5, 0, 2, 107},
+       {0x00F6, 0, 2, 109},
+       {0x00F9, 0, 2, 111},
+       {0x00FA, 0, 2, 113},
+       {0x00FB, 0, 2, 115},
+       {0x00FC, 0, 2, 117},
+       {0x00FD, 0, 2, 119},
+       {0x00FF, 0, 2, 121},
+       {0x0100, 0, 2, 123},
+       {0x0101, 0, 2, 125},
+       {0x0102, 0, 2, 127},
+       {0x0103, 0, 2, 129},
+       {0x0104, 0, 2, 131},
+       {0x0105, 0, 2, 133},
+       {0x0106, 0, 2, 135},
+       {0x0107, 0, 2, 137},
+       {0x0108, 0, 2, 139},
+       {0x0109, 0, 2, 141},
+       {0x010A, 0, 2, 143},
+       {0x010B, 0, 2, 145},
+       {0x010C, 0, 2, 147},
+       {0x010D, 0, 2, 149},
+       {0x010E, 0, 2, 151},
+       {0x010F, 0, 2, 153},
+       {0x0112, 0, 2, 155},
+       {0x0113, 0, 2, 157},
+       {0x0114, 0, 2, 159},
+       {0x0115, 0, 2, 161},
+       {0x0116, 0, 2, 163},
+       {0x0117, 0, 2, 165},
+       {0x0118, 0, 2, 167},
+       {0x0119, 0, 2, 169},
+       {0x011A, 0, 2, 171},
+       {0x011B, 0, 2, 173},
+       {0x011C, 0, 2, 175},
+       {0x011D, 0, 2, 177},
+       {0x011E, 0, 2, 179},
+       {0x011F, 0, 2, 181},
+       {0x0120, 0, 2, 183},
+       {0x0121, 0, 2, 185},
+       {0x0122, 0, 2, 187},
+       {0x0123, 0, 2, 189},
+       {0x0124, 0, 2, 191},
+       {0x0125, 0, 2, 193},
+       {0x0128, 0, 2, 195},
+       {0x0129, 0, 2, 197},
+       {0x012A, 0, 2, 199},
+       {0x012B, 0, 2, 201},
+       {0x012C, 0, 2, 203},
+       {0x012D, 0, 2, 205},
+       {0x012E, 0, 2, 207},
+       {0x012F, 0, 2, 209},
+       {0x0130, 0, 2, 211},
+       {0x0132, 0, 2 | DECOMP_NO_COMPOSE, 213},        /* compatibility mapping */
+       {0x0133, 0, 2 | DECOMP_NO_COMPOSE, 215},        /* compatibility mapping */
+       {0x0134, 0, 2, 217},
+       {0x0135, 0, 2, 219},
+       {0x0136, 0, 2, 221},
+       {0x0137, 0, 2, 223},
+       {0x0139, 0, 2, 225},
+       {0x013A, 0, 2, 227},
+       {0x013B, 0, 2, 229},
+       {0x013C, 0, 2, 231},
+       {0x013D, 0, 2, 233},
+       {0x013E, 0, 2, 235},
+       {0x013F, 0, 2 | DECOMP_NO_COMPOSE, 237},        /* compatibility mapping */
+       {0x0140, 0, 2 | DECOMP_NO_COMPOSE, 239},        /* compatibility mapping */
+       {0x0143, 0, 2, 241},
+       {0x0144, 0, 2, 243},
+       {0x0145, 0, 2, 245},
+       {0x0146, 0, 2, 247},
+       {0x0147, 0, 2, 249},
+       {0x0148, 0, 2, 251},
+       {0x0149, 0, 2 | DECOMP_NO_COMPOSE, 253},        /* compatibility mapping */
+       {0x014C, 0, 2, 255},
+       {0x014D, 0, 2, 257},
+       {0x014E, 0, 2, 259},
+       {0x014F, 0, 2, 261},
+       {0x0150, 0, 2, 263},
+       {0x0151, 0, 2, 265},
+       {0x0154, 0, 2, 267},
+       {0x0155, 0, 2, 269},
+       {0x0156, 0, 2, 271},
+       {0x0157, 0, 2, 273},
+       {0x0158, 0, 2, 275},
+       {0x0159, 0, 2, 277},
+       {0x015A, 0, 2, 279},
+       {0x015B, 0, 2, 281},
+       {0x015C, 0, 2, 283},
+       {0x015D, 0, 2, 285},
+       {0x015E, 0, 2, 287},
+       {0x015F, 0, 2, 289},
+       {0x0160, 0, 2, 291},
+       {0x0161, 0, 2, 293},
+       {0x0162, 0, 2, 295},
+       {0x0163, 0, 2, 297},
+       {0x0164, 0, 2, 299},
+       {0x0165, 0, 2, 301},
+       {0x0168, 0, 2, 303},
+       {0x0169, 0, 2, 305},
+       {0x016A, 0, 2, 307},
+       {0x016B, 0, 2, 309},
+       {0x016C, 0, 2, 311},
+       {0x016D, 0, 2, 313},
+       {0x016E, 0, 2, 315},
+       {0x016F, 0, 2, 317},
+       {0x0170, 0, 2, 319},
+       {0x0171, 0, 2, 321},
+       {0x0172, 0, 2, 323},
+       {0x0173, 0, 2, 325},
+       {0x0174, 0, 2, 327},
+       {0x0175, 0, 2, 329},
+       {0x0176, 0, 2, 331},
+       {0x0177, 0, 2, 333},
+       {0x0178, 0, 2, 335},
+       {0x0179, 0, 2, 337},
+       {0x017A, 0, 2, 339},
+       {0x017B, 0, 2, 341},
+       {0x017C, 0, 2, 343},
+       {0x017D, 0, 2, 345},
+       {0x017E, 0, 2, 347},
+       {0x017F, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x01A0, 0, 2, 349},
+       {0x01A1, 0, 2, 351},
+       {0x01AF, 0, 2, 353},
+       {0x01B0, 0, 2, 355},
+       {0x01C4, 0, 2 | DECOMP_NO_COMPOSE, 357},        /* compatibility mapping */
+       {0x01C5, 0, 2 | DECOMP_NO_COMPOSE, 359},        /* compatibility mapping */
+       {0x01C6, 0, 2 | DECOMP_NO_COMPOSE, 361},        /* compatibility mapping */
+       {0x01C7, 0, 2 | DECOMP_NO_COMPOSE, 363},        /* compatibility mapping */
+       {0x01C8, 0, 2 | DECOMP_NO_COMPOSE, 365},        /* compatibility mapping */
+       {0x01C9, 0, 2 | DECOMP_NO_COMPOSE, 367},        /* compatibility mapping */
+       {0x01CA, 0, 2 | DECOMP_NO_COMPOSE, 369},        /* compatibility mapping */
+       {0x01CB, 0, 2 | DECOMP_NO_COMPOSE, 371},        /* compatibility mapping */
+       {0x01CC, 0, 2 | DECOMP_NO_COMPOSE, 373},        /* compatibility mapping */
+       {0x01CD, 0, 2, 375},
+       {0x01CE, 0, 2, 377},
+       {0x01CF, 0, 2, 379},
+       {0x01D0, 0, 2, 381},
+       {0x01D1, 0, 2, 383},
+       {0x01D2, 0, 2, 385},
+       {0x01D3, 0, 2, 387},
+       {0x01D4, 0, 2, 389},
+       {0x01D5, 0, 2, 391},
+       {0x01D6, 0, 2, 393},
+       {0x01D7, 0, 2, 395},
+       {0x01D8, 0, 2, 397},
+       {0x01D9, 0, 2, 399},
+       {0x01DA, 0, 2, 401},
+       {0x01DB, 0, 2, 403},
+       {0x01DC, 0, 2, 405},
+       {0x01DE, 0, 2, 407},
+       {0x01DF, 0, 2, 409},
+       {0x01E0, 0, 2, 411},
+       {0x01E1, 0, 2, 413},
+       {0x01E2, 0, 2, 415},
+       {0x01E3, 0, 2, 417},
+       {0x01E6, 0, 2, 419},
+       {0x01E7, 0, 2, 421},
+       {0x01E8, 0, 2, 423},
+       {0x01E9, 0, 2, 425},
+       {0x01EA, 0, 2, 427},
+       {0x01EB, 0, 2, 429},
+       {0x01EC, 0, 2, 431},
+       {0x01ED, 0, 2, 433},
+       {0x01EE, 0, 2, 435},
+       {0x01EF, 0, 2, 437},
+       {0x01F0, 0, 2, 439},
+       {0x01F1, 0, 2 | DECOMP_NO_COMPOSE, 441},        /* compatibility mapping */
+       {0x01F2, 0, 2 | DECOMP_NO_COMPOSE, 443},        /* compatibility mapping */
+       {0x01F3, 0, 2 | DECOMP_NO_COMPOSE, 445},        /* compatibility mapping */
+       {0x01F4, 0, 2, 447},
+       {0x01F5, 0, 2, 449},
+       {0x01F8, 0, 2, 451},
+       {0x01F9, 0, 2, 453},
+       {0x01FA, 0, 2, 455},
+       {0x01FB, 0, 2, 457},
+       {0x01FC, 0, 2, 459},
+       {0x01FD, 0, 2, 461},
+       {0x01FE, 0, 2, 463},
+       {0x01FF, 0, 2, 465},
+       {0x0200, 0, 2, 467},
+       {0x0201, 0, 2, 469},
+       {0x0202, 0, 2, 471},
+       {0x0203, 0, 2, 473},
+       {0x0204, 0, 2, 475},
+       {0x0205, 0, 2, 477},
+       {0x0206, 0, 2, 479},
+       {0x0207, 0, 2, 481},
+       {0x0208, 0, 2, 483},
+       {0x0209, 0, 2, 485},
+       {0x020A, 0, 2, 487},
+       {0x020B, 0, 2, 489},
+       {0x020C, 0, 2, 491},
+       {0x020D, 0, 2, 493},
+       {0x020E, 0, 2, 495},
+       {0x020F, 0, 2, 497},
+       {0x0210, 0, 2, 499},
+       {0x0211, 0, 2, 501},
+       {0x0212, 0, 2, 503},
+       {0x0213, 0, 2, 505},
+       {0x0214, 0, 2, 507},
+       {0x0215, 0, 2, 509},
+       {0x0216, 0, 2, 511},
+       {0x0217, 0, 2, 513},
+       {0x0218, 0, 2, 515},
+       {0x0219, 0, 2, 517},
+       {0x021A, 0, 2, 519},
+       {0x021B, 0, 2, 521},
+       {0x021E, 0, 2, 523},
+       {0x021F, 0, 2, 525},
+       {0x0226, 0, 2, 527},
+       {0x0227, 0, 2, 529},
+       {0x0228, 0, 2, 531},
+       {0x0229, 0, 2, 533},
+       {0x022A, 0, 2, 535},
+       {0x022B, 0, 2, 537},
+       {0x022C, 0, 2, 539},
+       {0x022D, 0, 2, 541},
+       {0x022E, 0, 2, 543},
+       {0x022F, 0, 2, 545},
+       {0x0230, 0, 2, 547},
+       {0x0231, 0, 2, 549},
+       {0x0232, 0, 2, 551},
+       {0x0233, 0, 2, 553},
+       {0x02B0, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x02B1, 0, 1 | DECOMP_INLINE, 0x0266},
+       {0x02B2, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x02B3, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x02B4, 0, 1 | DECOMP_INLINE, 0x0279},
+       {0x02B5, 0, 1 | DECOMP_INLINE, 0x027B},
+       {0x02B6, 0, 1 | DECOMP_INLINE, 0x0281},
+       {0x02B7, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x02B8, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x02D8, 0, 2 | DECOMP_NO_COMPOSE, 555},        /* compatibility mapping */
+       {0x02D9, 0, 2 | DECOMP_NO_COMPOSE, 557},        /* compatibility mapping */
+       {0x02DA, 0, 2 | DECOMP_NO_COMPOSE, 559},        /* compatibility mapping */
+       {0x02DB, 0, 2 | DECOMP_NO_COMPOSE, 561},        /* compatibility mapping */
+       {0x02DC, 0, 2 | DECOMP_NO_COMPOSE, 563},        /* compatibility mapping */
+       {0x02DD, 0, 2 | DECOMP_NO_COMPOSE, 565},        /* compatibility mapping */
+       {0x02E0, 0, 1 | DECOMP_INLINE, 0x0263},
+       {0x02E1, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x02E2, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x02E3, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x02E4, 0, 1 | DECOMP_INLINE, 0x0295},
+       {0x0300, 230, 0, 0},
+       {0x0301, 230, 0, 0},
+       {0x0302, 230, 0, 0},
+       {0x0303, 230, 0, 0},
+       {0x0304, 230, 0, 0},
+       {0x0305, 230, 0, 0},
+       {0x0306, 230, 0, 0},
+       {0x0307, 230, 0, 0},
+       {0x0308, 230, 0, 0},
+       {0x0309, 230, 0, 0},
+       {0x030A, 230, 0, 0},
+       {0x030B, 230, 0, 0},
+       {0x030C, 230, 0, 0},
+       {0x030D, 230, 0, 0},
+       {0x030E, 230, 0, 0},
+       {0x030F, 230, 0, 0},
+       {0x0310, 230, 0, 0},
+       {0x0311, 230, 0, 0},
+       {0x0312, 230, 0, 0},
+       {0x0313, 230, 0, 0},
+       {0x0314, 230, 0, 0},
+       {0x0315, 232, 0, 0},
+       {0x0316, 220, 0, 0},
+       {0x0317, 220, 0, 0},
+       {0x0318, 220, 0, 0},
+       {0x0319, 220, 0, 0},
+       {0x031A, 232, 0, 0},
+       {0x031B, 216, 0, 0},
+       {0x031C, 220, 0, 0},
+       {0x031D, 220, 0, 0},
+       {0x031E, 220, 0, 0},
+       {0x031F, 220, 0, 0},
+       {0x0320, 220, 0, 0},
+       {0x0321, 202, 0, 0},
+       {0x0322, 202, 0, 0},
+       {0x0323, 220, 0, 0},
+       {0x0324, 220, 0, 0},
+       {0x0325, 220, 0, 0},
+       {0x0326, 220, 0, 0},
+       {0x0327, 202, 0, 0},
+       {0x0328, 202, 0, 0},
+       {0x0329, 220, 0, 0},
+       {0x032A, 220, 0, 0},
+       {0x032B, 220, 0, 0},
+       {0x032C, 220, 0, 0},
+       {0x032D, 220, 0, 0},
+       {0x032E, 220, 0, 0},
+       {0x032F, 220, 0, 0},
+       {0x0330, 220, 0, 0},
+       {0x0331, 220, 0, 0},
+       {0x0332, 220, 0, 0},
+       {0x0333, 220, 0, 0},
+       {0x0334, 1, 0, 0},
+       {0x0335, 1, 0, 0},
+       {0x0336, 1, 0, 0},
+       {0x0337, 1, 0, 0},
+       {0x0338, 1, 0, 0},
+       {0x0339, 220, 0, 0},
+       {0x033A, 220, 0, 0},
+       {0x033B, 220, 0, 0},
+       {0x033C, 220, 0, 0},
+       {0x033D, 230, 0, 0},
+       {0x033E, 230, 0, 0},
+       {0x033F, 230, 0, 0},
+       {0x0340, 230, 1 | DECOMP_INLINE, 0x0300},
+       {0x0341, 230, 1 | DECOMP_INLINE, 0x0301},
+       {0x0342, 230, 0, 0},
+       {0x0343, 230, 1 | DECOMP_INLINE, 0x0313},
+       {0x0344, 230, 2 | DECOMP_NO_COMPOSE, 567},      /* non-starter decomposition */
+       {0x0345, 240, 0, 0},
+       {0x0346, 230, 0, 0},
+       {0x0347, 220, 0, 0},
+       {0x0348, 220, 0, 0},
+       {0x0349, 220, 0, 0},
+       {0x034A, 230, 0, 0},
+       {0x034B, 230, 0, 0},
+       {0x034C, 230, 0, 0},
+       {0x034D, 220, 0, 0},
+       {0x034E, 220, 0, 0},
+       {0x0350, 230, 0, 0},
+       {0x0351, 230, 0, 0},
+       {0x0352, 230, 0, 0},
+       {0x0353, 220, 0, 0},
+       {0x0354, 220, 0, 0},
+       {0x0355, 220, 0, 0},
+       {0x0356, 220, 0, 0},
+       {0x0357, 230, 0, 0},
+       {0x0358, 232, 0, 0},
+       {0x0359, 220, 0, 0},
+       {0x035A, 220, 0, 0},
+       {0x035B, 230, 0, 0},
+       {0x035C, 233, 0, 0},
+       {0x035D, 234, 0, 0},
+       {0x035E, 234, 0, 0},
+       {0x035F, 233, 0, 0},
+       {0x0360, 234, 0, 0},
+       {0x0361, 234, 0, 0},
+       {0x0362, 233, 0, 0},
+       {0x0363, 230, 0, 0},
+       {0x0364, 230, 0, 0},
+       {0x0365, 230, 0, 0},
+       {0x0366, 230, 0, 0},
+       {0x0367, 230, 0, 0},
+       {0x0368, 230, 0, 0},
+       {0x0369, 230, 0, 0},
+       {0x036A, 230, 0, 0},
+       {0x036B, 230, 0, 0},
+       {0x036C, 230, 0, 0},
+       {0x036D, 230, 0, 0},
+       {0x036E, 230, 0, 0},
+       {0x036F, 230, 0, 0},
+       {0x0374, 0, 1 | DECOMP_INLINE, 0x02B9},
+       {0x037A, 0, 2 | DECOMP_NO_COMPOSE, 569},        /* compatibility mapping */
+       {0x037E, 0, 1 | DECOMP_INLINE, 0x003B},
+       {0x0384, 0, 2 | DECOMP_NO_COMPOSE, 571},        /* compatibility mapping */
+       {0x0385, 0, 2, 573},
+       {0x0386, 0, 2, 575},
+       {0x0387, 0, 1 | DECOMP_INLINE, 0x00B7},
+       {0x0388, 0, 2, 577},
+       {0x0389, 0, 2, 579},
+       {0x038A, 0, 2, 581},
+       {0x038C, 0, 2, 583},
+       {0x038E, 0, 2, 585},
+       {0x038F, 0, 2, 587},
+       {0x0390, 0, 2, 589},
+       {0x03AA, 0, 2, 591},
+       {0x03AB, 0, 2, 593},
+       {0x03AC, 0, 2, 595},
+       {0x03AD, 0, 2, 597},
+       {0x03AE, 0, 2, 599},
+       {0x03AF, 0, 2, 601},
+       {0x03B0, 0, 2, 603},
+       {0x03CA, 0, 2, 605},
+       {0x03CB, 0, 2, 607},
+       {0x03CC, 0, 2, 609},
+       {0x03CD, 0, 2, 611},
+       {0x03CE, 0, 2, 613},
+       {0x03D0, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x03D1, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x03D2, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x03D3, 0, 2, 615},
+       {0x03D4, 0, 2, 617},
+       {0x03D5, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x03D6, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x03F0, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x03F1, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x03F2, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x03F4, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x03F5, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x03F9, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x0400, 0, 2, 619},
+       {0x0401, 0, 2, 621},
+       {0x0403, 0, 2, 623},
+       {0x0407, 0, 2, 625},
+       {0x040C, 0, 2, 627},
+       {0x040D, 0, 2, 629},
+       {0x040E, 0, 2, 631},
+       {0x0419, 0, 2, 633},
+       {0x0439, 0, 2, 635},
+       {0x0450, 0, 2, 637},
+       {0x0451, 0, 2, 639},
+       {0x0453, 0, 2, 641},
+       {0x0457, 0, 2, 643},
+       {0x045C, 0, 2, 645},
+       {0x045D, 0, 2, 647},
+       {0x045E, 0, 2, 649},
+       {0x0476, 0, 2, 651},
+       {0x0477, 0, 2, 653},
+       {0x0483, 230, 0, 0},
+       {0x0484, 230, 0, 0},
+       {0x0485, 230, 0, 0},
+       {0x0486, 230, 0, 0},
+       {0x0487, 230, 0, 0},
+       {0x04C1, 0, 2, 655},
+       {0x04C2, 0, 2, 657},
+       {0x04D0, 0, 2, 659},
+       {0x04D1, 0, 2, 661},
+       {0x04D2, 0, 2, 663},
+       {0x04D3, 0, 2, 665},
+       {0x04D6, 0, 2, 667},
+       {0x04D7, 0, 2, 669},
+       {0x04DA, 0, 2, 671},
+       {0x04DB, 0, 2, 673},
+       {0x04DC, 0, 2, 675},
+       {0x04DD, 0, 2, 677},
+       {0x04DE, 0, 2, 679},
+       {0x04DF, 0, 2, 681},
+       {0x04E2, 0, 2, 683},
+       {0x04E3, 0, 2, 685},
+       {0x04E4, 0, 2, 687},
+       {0x04E5, 0, 2, 689},
+       {0x04E6, 0, 2, 691},
+       {0x04E7, 0, 2, 693},
+       {0x04EA, 0, 2, 695},
+       {0x04EB, 0, 2, 697},
+       {0x04EC, 0, 2, 699},
+       {0x04ED, 0, 2, 701},
+       {0x04EE, 0, 2, 703},
+       {0x04EF, 0, 2, 705},
+       {0x04F0, 0, 2, 707},
+       {0x04F1, 0, 2, 709},
+       {0x04F2, 0, 2, 711},
+       {0x04F3, 0, 2, 713},
+       {0x04F4, 0, 2, 715},
+       {0x04F5, 0, 2, 717},
+       {0x04F8, 0, 2, 719},
+       {0x04F9, 0, 2, 721},
+       {0x0587, 0, 2 | DECOMP_NO_COMPOSE, 723},        /* compatibility mapping */
+       {0x0591, 220, 0, 0},
+       {0x0592, 230, 0, 0},
+       {0x0593, 230, 0, 0},
+       {0x0594, 230, 0, 0},
+       {0x0595, 230, 0, 0},
+       {0x0596, 220, 0, 0},
+       {0x0597, 230, 0, 0},
+       {0x0598, 230, 0, 0},
+       {0x0599, 230, 0, 0},
+       {0x059A, 222, 0, 0},
+       {0x059B, 220, 0, 0},
+       {0x059C, 230, 0, 0},
+       {0x059D, 230, 0, 0},
+       {0x059E, 230, 0, 0},
+       {0x059F, 230, 0, 0},
+       {0x05A0, 230, 0, 0},
+       {0x05A1, 230, 0, 0},
+       {0x05A2, 220, 0, 0},
+       {0x05A3, 220, 0, 0},
+       {0x05A4, 220, 0, 0},
+       {0x05A5, 220, 0, 0},
+       {0x05A6, 220, 0, 0},
+       {0x05A7, 220, 0, 0},
+       {0x05A8, 230, 0, 0},
+       {0x05A9, 230, 0, 0},
+       {0x05AA, 220, 0, 0},
+       {0x05AB, 230, 0, 0},
+       {0x05AC, 230, 0, 0},
+       {0x05AD, 222, 0, 0},
+       {0x05AE, 228, 0, 0},
+       {0x05AF, 230, 0, 0},
+       {0x05B0, 10, 0, 0},
+       {0x05B1, 11, 0, 0},
+       {0x05B2, 12, 0, 0},
+       {0x05B3, 13, 0, 0},
+       {0x05B4, 14, 0, 0},
+       {0x05B5, 15, 0, 0},
+       {0x05B6, 16, 0, 0},
+       {0x05B7, 17, 0, 0},
+       {0x05B8, 18, 0, 0},
+       {0x05B9, 19, 0, 0},
+       {0x05BA, 19, 0, 0},
+       {0x05BB, 20, 0, 0},
+       {0x05BC, 21, 0, 0},
+       {0x05BD, 22, 0, 0},
+       {0x05BF, 23, 0, 0},
+       {0x05C1, 24, 0, 0},
+       {0x05C2, 25, 0, 0},
+       {0x05C4, 230, 0, 0},
+       {0x05C5, 220, 0, 0},
+       {0x05C7, 18, 0, 0},
+       {0x0610, 230, 0, 0},
+       {0x0611, 230, 0, 0},
+       {0x0612, 230, 0, 0},
+       {0x0613, 230, 0, 0},
+       {0x0614, 230, 0, 0},
+       {0x0615, 230, 0, 0},
+       {0x0616, 230, 0, 0},
+       {0x0617, 230, 0, 0},
+       {0x0618, 30, 0, 0},
+       {0x0619, 31, 0, 0},
+       {0x061A, 32, 0, 0},
+       {0x0622, 0, 2, 725},
+       {0x0623, 0, 2, 727},
+       {0x0624, 0, 2, 729},
+       {0x0625, 0, 2, 731},
+       {0x0626, 0, 2, 733},
+       {0x064B, 27, 0, 0},
+       {0x064C, 28, 0, 0},
+       {0x064D, 29, 0, 0},
+       {0x064E, 30, 0, 0},
+       {0x064F, 31, 0, 0},
+       {0x0650, 32, 0, 0},
+       {0x0651, 33, 0, 0},
+       {0x0652, 34, 0, 0},
+       {0x0653, 230, 0, 0},
+       {0x0654, 230, 0, 0},
+       {0x0655, 220, 0, 0},
+       {0x0656, 220, 0, 0},
+       {0x0657, 230, 0, 0},
+       {0x0658, 230, 0, 0},
+       {0x0659, 230, 0, 0},
+       {0x065A, 230, 0, 0},
+       {0x065B, 230, 0, 0},
+       {0x065C, 220, 0, 0},
+       {0x065D, 230, 0, 0},
+       {0x065E, 230, 0, 0},
+       {0x065F, 220, 0, 0},
+       {0x0670, 35, 0, 0},
+       {0x0675, 0, 2 | DECOMP_NO_COMPOSE, 735},        /* compatibility mapping */
+       {0x0676, 0, 2 | DECOMP_NO_COMPOSE, 737},        /* compatibility mapping */
+       {0x0677, 0, 2 | DECOMP_NO_COMPOSE, 739},        /* compatibility mapping */
+       {0x0678, 0, 2 | DECOMP_NO_COMPOSE, 741},        /* compatibility mapping */
+       {0x06C0, 0, 2, 743},
+       {0x06C2, 0, 2, 745},
+       {0x06D3, 0, 2, 747},
+       {0x06D6, 230, 0, 0},
+       {0x06D7, 230, 0, 0},
+       {0x06D8, 230, 0, 0},
+       {0x06D9, 230, 0, 0},
+       {0x06DA, 230, 0, 0},
+       {0x06DB, 230, 0, 0},
+       {0x06DC, 230, 0, 0},
+       {0x06DF, 230, 0, 0},
+       {0x06E0, 230, 0, 0},
+       {0x06E1, 230, 0, 0},
+       {0x06E2, 230, 0, 0},
+       {0x06E3, 220, 0, 0},
+       {0x06E4, 230, 0, 0},
+       {0x06E7, 230, 0, 0},
+       {0x06E8, 230, 0, 0},
+       {0x06EA, 220, 0, 0},
+       {0x06EB, 230, 0, 0},
+       {0x06EC, 230, 0, 0},
+       {0x06ED, 220, 0, 0},
+       {0x0711, 36, 0, 0},
+       {0x0730, 230, 0, 0},
+       {0x0731, 220, 0, 0},
+       {0x0732, 230, 0, 0},
+       {0x0733, 230, 0, 0},
+       {0x0734, 220, 0, 0},
+       {0x0735, 230, 0, 0},
+       {0x0736, 230, 0, 0},
+       {0x0737, 220, 0, 0},
+       {0x0738, 220, 0, 0},
+       {0x0739, 220, 0, 0},
+       {0x073A, 230, 0, 0},
+       {0x073B, 220, 0, 0},
+       {0x073C, 220, 0, 0},
+       {0x073D, 230, 0, 0},
+       {0x073E, 220, 0, 0},
+       {0x073F, 230, 0, 0},
+       {0x0740, 230, 0, 0},
+       {0x0741, 230, 0, 0},
+       {0x0742, 220, 0, 0},
+       {0x0743, 230, 0, 0},
+       {0x0744, 220, 0, 0},
+       {0x0745, 230, 0, 0},
+       {0x0746, 220, 0, 0},
+       {0x0747, 230, 0, 0},
+       {0x0748, 220, 0, 0},
+       {0x0749, 230, 0, 0},
+       {0x074A, 230, 0, 0},
+       {0x07EB, 230, 0, 0},
+       {0x07EC, 230, 0, 0},
+       {0x07ED, 230, 0, 0},
+       {0x07EE, 230, 0, 0},
+       {0x07EF, 230, 0, 0},
+       {0x07F0, 230, 0, 0},
+       {0x07F1, 230, 0, 0},
+       {0x07F2, 220, 0, 0},
+       {0x07F3, 230, 0, 0},
+       {0x0816, 230, 0, 0},
+       {0x0817, 230, 0, 0},
+       {0x0818, 230, 0, 0},
+       {0x0819, 230, 0, 0},
+       {0x081B, 230, 0, 0},
+       {0x081C, 230, 0, 0},
+       {0x081D, 230, 0, 0},
+       {0x081E, 230, 0, 0},
+       {0x081F, 230, 0, 0},
+       {0x0820, 230, 0, 0},
+       {0x0821, 230, 0, 0},
+       {0x0822, 230, 0, 0},
+       {0x0823, 230, 0, 0},
+       {0x0825, 230, 0, 0},
+       {0x0826, 230, 0, 0},
+       {0x0827, 230, 0, 0},
+       {0x0829, 230, 0, 0},
+       {0x082A, 230, 0, 0},
+       {0x082B, 230, 0, 0},
+       {0x082C, 230, 0, 0},
+       {0x082D, 230, 0, 0},
+       {0x0859, 220, 0, 0},
+       {0x085A, 220, 0, 0},
+       {0x085B, 220, 0, 0},
+       {0x08D4, 230, 0, 0},
+       {0x08D5, 230, 0, 0},
+       {0x08D6, 230, 0, 0},
+       {0x08D7, 230, 0, 0},
+       {0x08D8, 230, 0, 0},
+       {0x08D9, 230, 0, 0},
+       {0x08DA, 230, 0, 0},
+       {0x08DB, 230, 0, 0},
+       {0x08DC, 230, 0, 0},
+       {0x08DD, 230, 0, 0},
+       {0x08DE, 230, 0, 0},
+       {0x08DF, 230, 0, 0},
+       {0x08E0, 230, 0, 0},
+       {0x08E1, 230, 0, 0},
+       {0x08E3, 220, 0, 0},
+       {0x08E4, 230, 0, 0},
+       {0x08E5, 230, 0, 0},
+       {0x08E6, 220, 0, 0},
+       {0x08E7, 230, 0, 0},
+       {0x08E8, 230, 0, 0},
+       {0x08E9, 220, 0, 0},
+       {0x08EA, 230, 0, 0},
+       {0x08EB, 230, 0, 0},
+       {0x08EC, 230, 0, 0},
+       {0x08ED, 220, 0, 0},
+       {0x08EE, 220, 0, 0},
+       {0x08EF, 220, 0, 0},
+       {0x08F0, 27, 0, 0},
+       {0x08F1, 28, 0, 0},
+       {0x08F2, 29, 0, 0},
+       {0x08F3, 230, 0, 0},
+       {0x08F4, 230, 0, 0},
+       {0x08F5, 230, 0, 0},
+       {0x08F6, 220, 0, 0},
+       {0x08F7, 230, 0, 0},
+       {0x08F8, 230, 0, 0},
+       {0x08F9, 220, 0, 0},
+       {0x08FA, 220, 0, 0},
+       {0x08FB, 230, 0, 0},
+       {0x08FC, 230, 0, 0},
+       {0x08FD, 230, 0, 0},
+       {0x08FE, 230, 0, 0},
+       {0x08FF, 230, 0, 0},
+       {0x0929, 0, 2, 749},
+       {0x0931, 0, 2, 751},
+       {0x0934, 0, 2, 753},
+       {0x093C, 7, 0, 0},
+       {0x094D, 9, 0, 0},
+       {0x0951, 230, 0, 0},
+       {0x0952, 220, 0, 0},
+       {0x0953, 230, 0, 0},
+       {0x0954, 230, 0, 0},
+       {0x0958, 0, 2 | DECOMP_NO_COMPOSE, 755},        /* in exclusion list */
+       {0x0959, 0, 2 | DECOMP_NO_COMPOSE, 757},        /* in exclusion list */
+       {0x095A, 0, 2 | DECOMP_NO_COMPOSE, 759},        /* in exclusion list */
+       {0x095B, 0, 2 | DECOMP_NO_COMPOSE, 761},        /* in exclusion list */
+       {0x095C, 0, 2 | DECOMP_NO_COMPOSE, 763},        /* in exclusion list */
+       {0x095D, 0, 2 | DECOMP_NO_COMPOSE, 765},        /* in exclusion list */
+       {0x095E, 0, 2 | DECOMP_NO_COMPOSE, 767},        /* in exclusion list */
+       {0x095F, 0, 2 | DECOMP_NO_COMPOSE, 769},        /* in exclusion list */
+       {0x09BC, 7, 0, 0},
+       {0x09CB, 0, 2, 771},
+       {0x09CC, 0, 2, 773},
+       {0x09CD, 9, 0, 0},
+       {0x09DC, 0, 2 | DECOMP_NO_COMPOSE, 775},        /* in exclusion list */
+       {0x09DD, 0, 2 | DECOMP_NO_COMPOSE, 777},        /* in exclusion list */
+       {0x09DF, 0, 2 | DECOMP_NO_COMPOSE, 779},        /* in exclusion list */
+       {0x0A33, 0, 2 | DECOMP_NO_COMPOSE, 781},        /* in exclusion list */
+       {0x0A36, 0, 2 | DECOMP_NO_COMPOSE, 783},        /* in exclusion list */
+       {0x0A3C, 7, 0, 0},
+       {0x0A4D, 9, 0, 0},
+       {0x0A59, 0, 2 | DECOMP_NO_COMPOSE, 785},        /* in exclusion list */
+       {0x0A5A, 0, 2 | DECOMP_NO_COMPOSE, 787},        /* in exclusion list */
+       {0x0A5B, 0, 2 | DECOMP_NO_COMPOSE, 789},        /* in exclusion list */
+       {0x0A5E, 0, 2 | DECOMP_NO_COMPOSE, 791},        /* in exclusion list */
+       {0x0ABC, 7, 0, 0},
+       {0x0ACD, 9, 0, 0},
+       {0x0B3C, 7, 0, 0},
+       {0x0B48, 0, 2, 793},
+       {0x0B4B, 0, 2, 795},
+       {0x0B4C, 0, 2, 797},
+       {0x0B4D, 9, 0, 0},
+       {0x0B5C, 0, 2 | DECOMP_NO_COMPOSE, 799},        /* in exclusion list */
+       {0x0B5D, 0, 2 | DECOMP_NO_COMPOSE, 801},        /* in exclusion list */
+       {0x0B94, 0, 2, 803},
+       {0x0BCA, 0, 2, 805},
+       {0x0BCB, 0, 2, 807},
+       {0x0BCC, 0, 2, 809},
+       {0x0BCD, 9, 0, 0},
+       {0x0C48, 0, 2, 811},
+       {0x0C4D, 9, 0, 0},
+       {0x0C55, 84, 0, 0},
+       {0x0C56, 91, 0, 0},
+       {0x0CBC, 7, 0, 0},
+       {0x0CC0, 0, 2, 813},
+       {0x0CC7, 0, 2, 815},
+       {0x0CC8, 0, 2, 817},
+       {0x0CCA, 0, 2, 819},
+       {0x0CCB, 0, 2, 821},
+       {0x0CCD, 9, 0, 0},
+       {0x0D4A, 0, 2, 823},
+       {0x0D4B, 0, 2, 825},
+       {0x0D4C, 0, 2, 827},
+       {0x0D4D, 9, 0, 0},
+       {0x0DCA, 9, 0, 0},
+       {0x0DDA, 0, 2, 829},
+       {0x0DDC, 0, 2, 831},
+       {0x0DDD, 0, 2, 833},
+       {0x0DDE, 0, 2, 835},
+       {0x0E33, 0, 2 | DECOMP_NO_COMPOSE, 837},        /* compatibility mapping */
+       {0x0E38, 103, 0, 0},
+       {0x0E39, 103, 0, 0},
+       {0x0E3A, 9, 0, 0},
+       {0x0E48, 107, 0, 0},
+       {0x0E49, 107, 0, 0},
+       {0x0E4A, 107, 0, 0},
+       {0x0E4B, 107, 0, 0},
+       {0x0EB3, 0, 2 | DECOMP_NO_COMPOSE, 839},        /* compatibility mapping */
+       {0x0EB8, 118, 0, 0},
+       {0x0EB9, 118, 0, 0},
+       {0x0EC8, 122, 0, 0},
+       {0x0EC9, 122, 0, 0},
+       {0x0ECA, 122, 0, 0},
+       {0x0ECB, 122, 0, 0},
+       {0x0EDC, 0, 2 | DECOMP_NO_COMPOSE, 841},        /* compatibility mapping */
+       {0x0EDD, 0, 2 | DECOMP_NO_COMPOSE, 843},        /* compatibility mapping */
+       {0x0F0C, 0, 1 | DECOMP_INLINE, 0x0F0B},
+       {0x0F18, 220, 0, 0},
+       {0x0F19, 220, 0, 0},
+       {0x0F35, 220, 0, 0},
+       {0x0F37, 220, 0, 0},
+       {0x0F39, 216, 0, 0},
+       {0x0F43, 0, 2 | DECOMP_NO_COMPOSE, 845},        /* in exclusion list */
+       {0x0F4D, 0, 2 | DECOMP_NO_COMPOSE, 847},        /* in exclusion list */
+       {0x0F52, 0, 2 | DECOMP_NO_COMPOSE, 849},        /* in exclusion list */
+       {0x0F57, 0, 2 | DECOMP_NO_COMPOSE, 851},        /* in exclusion list */
+       {0x0F5C, 0, 2 | DECOMP_NO_COMPOSE, 853},        /* in exclusion list */
+       {0x0F69, 0, 2 | DECOMP_NO_COMPOSE, 855},        /* in exclusion list */
+       {0x0F71, 129, 0, 0},
+       {0x0F72, 130, 0, 0},
+       {0x0F73, 0, 2 | DECOMP_NO_COMPOSE, 857},        /* non-starter decomposition */
+       {0x0F74, 132, 0, 0},
+       {0x0F75, 0, 2 | DECOMP_NO_COMPOSE, 859},        /* non-starter decomposition */
+       {0x0F76, 0, 2 | DECOMP_NO_COMPOSE, 861},        /* in exclusion list */
+       {0x0F77, 0, 2 | DECOMP_NO_COMPOSE, 863},        /* compatibility mapping */
+       {0x0F78, 0, 2 | DECOMP_NO_COMPOSE, 865},        /* in exclusion list */
+       {0x0F79, 0, 2 | DECOMP_NO_COMPOSE, 867},        /* compatibility mapping */
+       {0x0F7A, 130, 0, 0},
+       {0x0F7B, 130, 0, 0},
+       {0x0F7C, 130, 0, 0},
+       {0x0F7D, 130, 0, 0},
+       {0x0F80, 130, 0, 0},
+       {0x0F81, 0, 2 | DECOMP_NO_COMPOSE, 869},        /* non-starter decomposition */
+       {0x0F82, 230, 0, 0},
+       {0x0F83, 230, 0, 0},
+       {0x0F84, 9, 0, 0},
+       {0x0F86, 230, 0, 0},
+       {0x0F87, 230, 0, 0},
+       {0x0F93, 0, 2 | DECOMP_NO_COMPOSE, 871},        /* in exclusion list */
+       {0x0F9D, 0, 2 | DECOMP_NO_COMPOSE, 873},        /* in exclusion list */
+       {0x0FA2, 0, 2 | DECOMP_NO_COMPOSE, 875},        /* in exclusion list */
+       {0x0FA7, 0, 2 | DECOMP_NO_COMPOSE, 877},        /* in exclusion list */
+       {0x0FAC, 0, 2 | DECOMP_NO_COMPOSE, 879},        /* in exclusion list */
+       {0x0FB9, 0, 2 | DECOMP_NO_COMPOSE, 881},        /* in exclusion list */
+       {0x0FC6, 220, 0, 0},
+       {0x1026, 0, 2, 883},
+       {0x1037, 7, 0, 0},
+       {0x1039, 9, 0, 0},
+       {0x103A, 9, 0, 0},
+       {0x108D, 220, 0, 0},
+       {0x10FC, 0, 1 | DECOMP_INLINE, 0x10DC},
+       {0x135D, 230, 0, 0},
+       {0x135E, 230, 0, 0},
+       {0x135F, 230, 0, 0},
+       {0x1714, 9, 0, 0},
+       {0x1734, 9, 0, 0},
+       {0x17D2, 9, 0, 0},
+       {0x17DD, 230, 0, 0},
+       {0x18A9, 228, 0, 0},
+       {0x1939, 222, 0, 0},
+       {0x193A, 230, 0, 0},
+       {0x193B, 220, 0, 0},
+       {0x1A17, 230, 0, 0},
+       {0x1A18, 220, 0, 0},
+       {0x1A60, 9, 0, 0},
+       {0x1A75, 230, 0, 0},
+       {0x1A76, 230, 0, 0},
+       {0x1A77, 230, 0, 0},
+       {0x1A78, 230, 0, 0},
+       {0x1A79, 230, 0, 0},
+       {0x1A7A, 230, 0, 0},
+       {0x1A7B, 230, 0, 0},
+       {0x1A7C, 230, 0, 0},
+       {0x1A7F, 220, 0, 0},
+       {0x1AB0, 230, 0, 0},
+       {0x1AB1, 230, 0, 0},
+       {0x1AB2, 230, 0, 0},
+       {0x1AB3, 230, 0, 0},
+       {0x1AB4, 230, 0, 0},
+       {0x1AB5, 220, 0, 0},
+       {0x1AB6, 220, 0, 0},
+       {0x1AB7, 220, 0, 0},
+       {0x1AB8, 220, 0, 0},
+       {0x1AB9, 220, 0, 0},
+       {0x1ABA, 220, 0, 0},
+       {0x1ABB, 230, 0, 0},
+       {0x1ABC, 230, 0, 0},
+       {0x1ABD, 220, 0, 0},
+       {0x1B06, 0, 2, 885},
+       {0x1B08, 0, 2, 887},
+       {0x1B0A, 0, 2, 889},
+       {0x1B0C, 0, 2, 891},
+       {0x1B0E, 0, 2, 893},
+       {0x1B12, 0, 2, 895},
+       {0x1B34, 7, 0, 0},
+       {0x1B3B, 0, 2, 897},
+       {0x1B3D, 0, 2, 899},
+       {0x1B40, 0, 2, 901},
+       {0x1B41, 0, 2, 903},
+       {0x1B43, 0, 2, 905},
+       {0x1B44, 9, 0, 0},
+       {0x1B6B, 230, 0, 0},
+       {0x1B6C, 220, 0, 0},
+       {0x1B6D, 230, 0, 0},
+       {0x1B6E, 230, 0, 0},
+       {0x1B6F, 230, 0, 0},
+       {0x1B70, 230, 0, 0},
+       {0x1B71, 230, 0, 0},
+       {0x1B72, 230, 0, 0},
+       {0x1B73, 230, 0, 0},
+       {0x1BAA, 9, 0, 0},
+       {0x1BAB, 9, 0, 0},
+       {0x1BE6, 7, 0, 0},
+       {0x1BF2, 9, 0, 0},
+       {0x1BF3, 9, 0, 0},
+       {0x1C37, 7, 0, 0},
+       {0x1CD0, 230, 0, 0},
+       {0x1CD1, 230, 0, 0},
+       {0x1CD2, 230, 0, 0},
+       {0x1CD4, 1, 0, 0},
+       {0x1CD5, 220, 0, 0},
+       {0x1CD6, 220, 0, 0},
+       {0x1CD7, 220, 0, 0},
+       {0x1CD8, 220, 0, 0},
+       {0x1CD9, 220, 0, 0},
+       {0x1CDA, 230, 0, 0},
+       {0x1CDB, 230, 0, 0},
+       {0x1CDC, 220, 0, 0},
+       {0x1CDD, 220, 0, 0},
+       {0x1CDE, 220, 0, 0},
+       {0x1CDF, 220, 0, 0},
+       {0x1CE0, 230, 0, 0},
+       {0x1CE2, 1, 0, 0},
+       {0x1CE3, 1, 0, 0},
+       {0x1CE4, 1, 0, 0},
+       {0x1CE5, 1, 0, 0},
+       {0x1CE6, 1, 0, 0},
+       {0x1CE7, 1, 0, 0},
+       {0x1CE8, 1, 0, 0},
+       {0x1CED, 220, 0, 0},
+       {0x1CF4, 230, 0, 0},
+       {0x1CF8, 230, 0, 0},
+       {0x1CF9, 230, 0, 0},
+       {0x1D2C, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D2D, 0, 1 | DECOMP_INLINE, 0x00C6},
+       {0x1D2E, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D30, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D31, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D32, 0, 1 | DECOMP_INLINE, 0x018E},
+       {0x1D33, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D34, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D35, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D36, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D37, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D38, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D39, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D3A, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D3C, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D3D, 0, 1 | DECOMP_INLINE, 0x0222},
+       {0x1D3E, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D3F, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D40, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D41, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D42, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D43, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D44, 0, 1 | DECOMP_INLINE, 0x0250},
+       {0x1D45, 0, 1 | DECOMP_INLINE, 0x0251},
+       {0x1D46, 0, 1 | DECOMP_INLINE, 0x1D02},
+       {0x1D47, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D48, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D49, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D4A, 0, 1 | DECOMP_INLINE, 0x0259},
+       {0x1D4B, 0, 1 | DECOMP_INLINE, 0x025B},
+       {0x1D4C, 0, 1 | DECOMP_INLINE, 0x025C},
+       {0x1D4D, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D4F, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D50, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D51, 0, 1 | DECOMP_INLINE, 0x014B},
+       {0x1D52, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D53, 0, 1 | DECOMP_INLINE, 0x0254},
+       {0x1D54, 0, 1 | DECOMP_INLINE, 0x1D16},
+       {0x1D55, 0, 1 | DECOMP_INLINE, 0x1D17},
+       {0x1D56, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D57, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D58, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D59, 0, 1 | DECOMP_INLINE, 0x1D1D},
+       {0x1D5A, 0, 1 | DECOMP_INLINE, 0x026F},
+       {0x1D5B, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D5C, 0, 1 | DECOMP_INLINE, 0x1D25},
+       {0x1D5D, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D5E, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D5F, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D60, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D61, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D62, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D63, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D64, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D65, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D66, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D67, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D68, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D69, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D6A, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D78, 0, 1 | DECOMP_INLINE, 0x043D},
+       {0x1D9B, 0, 1 | DECOMP_INLINE, 0x0252},
+       {0x1D9C, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D9D, 0, 1 | DECOMP_INLINE, 0x0255},
+       {0x1D9E, 0, 1 | DECOMP_INLINE, 0x00F0},
+       {0x1D9F, 0, 1 | DECOMP_INLINE, 0x025C},
+       {0x1DA0, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1DA1, 0, 1 | DECOMP_INLINE, 0x025F},
+       {0x1DA2, 0, 1 | DECOMP_INLINE, 0x0261},
+       {0x1DA3, 0, 1 | DECOMP_INLINE, 0x0265},
+       {0x1DA4, 0, 1 | DECOMP_INLINE, 0x0268},
+       {0x1DA5, 0, 1 | DECOMP_INLINE, 0x0269},
+       {0x1DA6, 0, 1 | DECOMP_INLINE, 0x026A},
+       {0x1DA7, 0, 1 | DECOMP_INLINE, 0x1D7B},
+       {0x1DA8, 0, 1 | DECOMP_INLINE, 0x029D},
+       {0x1DA9, 0, 1 | DECOMP_INLINE, 0x026D},
+       {0x1DAA, 0, 1 | DECOMP_INLINE, 0x1D85},
+       {0x1DAB, 0, 1 | DECOMP_INLINE, 0x029F},
+       {0x1DAC, 0, 1 | DECOMP_INLINE, 0x0271},
+       {0x1DAD, 0, 1 | DECOMP_INLINE, 0x0270},
+       {0x1DAE, 0, 1 | DECOMP_INLINE, 0x0272},
+       {0x1DAF, 0, 1 | DECOMP_INLINE, 0x0273},
+       {0x1DB0, 0, 1 | DECOMP_INLINE, 0x0274},
+       {0x1DB1, 0, 1 | DECOMP_INLINE, 0x0275},
+       {0x1DB2, 0, 1 | DECOMP_INLINE, 0x0278},
+       {0x1DB3, 0, 1 | DECOMP_INLINE, 0x0282},
+       {0x1DB4, 0, 1 | DECOMP_INLINE, 0x0283},
+       {0x1DB5, 0, 1 | DECOMP_INLINE, 0x01AB},
+       {0x1DB6, 0, 1 | DECOMP_INLINE, 0x0289},
+       {0x1DB7, 0, 1 | DECOMP_INLINE, 0x028A},
+       {0x1DB8, 0, 1 | DECOMP_INLINE, 0x1D1C},
+       {0x1DB9, 0, 1 | DECOMP_INLINE, 0x028B},
+       {0x1DBA, 0, 1 | DECOMP_INLINE, 0x028C},
+       {0x1DBB, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1DBC, 0, 1 | DECOMP_INLINE, 0x0290},
+       {0x1DBD, 0, 1 | DECOMP_INLINE, 0x0291},
+       {0x1DBE, 0, 1 | DECOMP_INLINE, 0x0292},
+       {0x1DBF, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1DC0, 230, 0, 0},
+       {0x1DC1, 230, 0, 0},
+       {0x1DC2, 220, 0, 0},
+       {0x1DC3, 230, 0, 0},
+       {0x1DC4, 230, 0, 0},
+       {0x1DC5, 230, 0, 0},
+       {0x1DC6, 230, 0, 0},
+       {0x1DC7, 230, 0, 0},
+       {0x1DC8, 230, 0, 0},
+       {0x1DC9, 230, 0, 0},
+       {0x1DCA, 220, 0, 0},
+       {0x1DCB, 230, 0, 0},
+       {0x1DCC, 230, 0, 0},
+       {0x1DCD, 234, 0, 0},
+       {0x1DCE, 214, 0, 0},
+       {0x1DCF, 220, 0, 0},
+       {0x1DD0, 202, 0, 0},
+       {0x1DD1, 230, 0, 0},
+       {0x1DD2, 230, 0, 0},
+       {0x1DD3, 230, 0, 0},
+       {0x1DD4, 230, 0, 0},
+       {0x1DD5, 230, 0, 0},
+       {0x1DD6, 230, 0, 0},
+       {0x1DD7, 230, 0, 0},
+       {0x1DD8, 230, 0, 0},
+       {0x1DD9, 230, 0, 0},
+       {0x1DDA, 230, 0, 0},
+       {0x1DDB, 230, 0, 0},
+       {0x1DDC, 230, 0, 0},
+       {0x1DDD, 230, 0, 0},
+       {0x1DDE, 230, 0, 0},
+       {0x1DDF, 230, 0, 0},
+       {0x1DE0, 230, 0, 0},
+       {0x1DE1, 230, 0, 0},
+       {0x1DE2, 230, 0, 0},
+       {0x1DE3, 230, 0, 0},
+       {0x1DE4, 230, 0, 0},
+       {0x1DE5, 230, 0, 0},
+       {0x1DE6, 230, 0, 0},
+       {0x1DE7, 230, 0, 0},
+       {0x1DE8, 230, 0, 0},
+       {0x1DE9, 230, 0, 0},
+       {0x1DEA, 230, 0, 0},
+       {0x1DEB, 230, 0, 0},
+       {0x1DEC, 230, 0, 0},
+       {0x1DED, 230, 0, 0},
+       {0x1DEE, 230, 0, 0},
+       {0x1DEF, 230, 0, 0},
+       {0x1DF0, 230, 0, 0},
+       {0x1DF1, 230, 0, 0},
+       {0x1DF2, 230, 0, 0},
+       {0x1DF3, 230, 0, 0},
+       {0x1DF4, 230, 0, 0},
+       {0x1DF5, 230, 0, 0},
+       {0x1DFB, 230, 0, 0},
+       {0x1DFC, 233, 0, 0},
+       {0x1DFD, 220, 0, 0},
+       {0x1DFE, 230, 0, 0},
+       {0x1DFF, 220, 0, 0},
+       {0x1E00, 0, 2, 907},
+       {0x1E01, 0, 2, 909},
+       {0x1E02, 0, 2, 911},
+       {0x1E03, 0, 2, 913},
+       {0x1E04, 0, 2, 915},
+       {0x1E05, 0, 2, 917},
+       {0x1E06, 0, 2, 919},
+       {0x1E07, 0, 2, 921},
+       {0x1E08, 0, 2, 923},
+       {0x1E09, 0, 2, 925},
+       {0x1E0A, 0, 2, 927},
+       {0x1E0B, 0, 2, 929},
+       {0x1E0C, 0, 2, 931},
+       {0x1E0D, 0, 2, 933},
+       {0x1E0E, 0, 2, 935},
+       {0x1E0F, 0, 2, 937},
+       {0x1E10, 0, 2, 939},
+       {0x1E11, 0, 2, 941},
+       {0x1E12, 0, 2, 943},
+       {0x1E13, 0, 2, 945},
+       {0x1E14, 0, 2, 947},
+       {0x1E15, 0, 2, 949},
+       {0x1E16, 0, 2, 951},
+       {0x1E17, 0, 2, 953},
+       {0x1E18, 0, 2, 955},
+       {0x1E19, 0, 2, 957},
+       {0x1E1A, 0, 2, 959},
+       {0x1E1B, 0, 2, 961},
+       {0x1E1C, 0, 2, 963},
+       {0x1E1D, 0, 2, 965},
+       {0x1E1E, 0, 2, 967},
+       {0x1E1F, 0, 2, 969},
+       {0x1E20, 0, 2, 971},
+       {0x1E21, 0, 2, 973},
+       {0x1E22, 0, 2, 975},
+       {0x1E23, 0, 2, 977},
+       {0x1E24, 0, 2, 979},
+       {0x1E25, 0, 2, 981},
+       {0x1E26, 0, 2, 983},
+       {0x1E27, 0, 2, 985},
+       {0x1E28, 0, 2, 987},
+       {0x1E29, 0, 2, 989},
+       {0x1E2A, 0, 2, 991},
+       {0x1E2B, 0, 2, 993},
+       {0x1E2C, 0, 2, 995},
+       {0x1E2D, 0, 2, 997},
+       {0x1E2E, 0, 2, 999},
+       {0x1E2F, 0, 2, 1001},
+       {0x1E30, 0, 2, 1003},
+       {0x1E31, 0, 2, 1005},
+       {0x1E32, 0, 2, 1007},
+       {0x1E33, 0, 2, 1009},
+       {0x1E34, 0, 2, 1011},
+       {0x1E35, 0, 2, 1013},
+       {0x1E36, 0, 2, 1015},
+       {0x1E37, 0, 2, 1017},
+       {0x1E38, 0, 2, 1019},
+       {0x1E39, 0, 2, 1021},
+       {0x1E3A, 0, 2, 1023},
+       {0x1E3B, 0, 2, 1025},
+       {0x1E3C, 0, 2, 1027},
+       {0x1E3D, 0, 2, 1029},
+       {0x1E3E, 0, 2, 1031},
+       {0x1E3F, 0, 2, 1033},
+       {0x1E40, 0, 2, 1035},
+       {0x1E41, 0, 2, 1037},
+       {0x1E42, 0, 2, 1039},
+       {0x1E43, 0, 2, 1041},
+       {0x1E44, 0, 2, 1043},
+       {0x1E45, 0, 2, 1045},
+       {0x1E46, 0, 2, 1047},
+       {0x1E47, 0, 2, 1049},
+       {0x1E48, 0, 2, 1051},
+       {0x1E49, 0, 2, 1053},
+       {0x1E4A, 0, 2, 1055},
+       {0x1E4B, 0, 2, 1057},
+       {0x1E4C, 0, 2, 1059},
+       {0x1E4D, 0, 2, 1061},
+       {0x1E4E, 0, 2, 1063},
+       {0x1E4F, 0, 2, 1065},
+       {0x1E50, 0, 2, 1067},
+       {0x1E51, 0, 2, 1069},
+       {0x1E52, 0, 2, 1071},
+       {0x1E53, 0, 2, 1073},
+       {0x1E54, 0, 2, 1075},
+       {0x1E55, 0, 2, 1077},
+       {0x1E56, 0, 2, 1079},
+       {0x1E57, 0, 2, 1081},
+       {0x1E58, 0, 2, 1083},
+       {0x1E59, 0, 2, 1085},
+       {0x1E5A, 0, 2, 1087},
+       {0x1E5B, 0, 2, 1089},
+       {0x1E5C, 0, 2, 1091},
+       {0x1E5D, 0, 2, 1093},
+       {0x1E5E, 0, 2, 1095},
+       {0x1E5F, 0, 2, 1097},
+       {0x1E60, 0, 2, 1099},
+       {0x1E61, 0, 2, 1101},
+       {0x1E62, 0, 2, 1103},
+       {0x1E63, 0, 2, 1105},
+       {0x1E64, 0, 2, 1107},
+       {0x1E65, 0, 2, 1109},
+       {0x1E66, 0, 2, 1111},
+       {0x1E67, 0, 2, 1113},
+       {0x1E68, 0, 2, 1115},
+       {0x1E69, 0, 2, 1117},
+       {0x1E6A, 0, 2, 1119},
+       {0x1E6B, 0, 2, 1121},
+       {0x1E6C, 0, 2, 1123},
+       {0x1E6D, 0, 2, 1125},
+       {0x1E6E, 0, 2, 1127},
+       {0x1E6F, 0, 2, 1129},
+       {0x1E70, 0, 2, 1131},
+       {0x1E71, 0, 2, 1133},
+       {0x1E72, 0, 2, 1135},
+       {0x1E73, 0, 2, 1137},
+       {0x1E74, 0, 2, 1139},
+       {0x1E75, 0, 2, 1141},
+       {0x1E76, 0, 2, 1143},
+       {0x1E77, 0, 2, 1145},
+       {0x1E78, 0, 2, 1147},
+       {0x1E79, 0, 2, 1149},
+       {0x1E7A, 0, 2, 1151},
+       {0x1E7B, 0, 2, 1153},
+       {0x1E7C, 0, 2, 1155},
+       {0x1E7D, 0, 2, 1157},
+       {0x1E7E, 0, 2, 1159},
+       {0x1E7F, 0, 2, 1161},
+       {0x1E80, 0, 2, 1163},
+       {0x1E81, 0, 2, 1165},
+       {0x1E82, 0, 2, 1167},
+       {0x1E83, 0, 2, 1169},
+       {0x1E84, 0, 2, 1171},
+       {0x1E85, 0, 2, 1173},
+       {0x1E86, 0, 2, 1175},
+       {0x1E87, 0, 2, 1177},
+       {0x1E88, 0, 2, 1179},
+       {0x1E89, 0, 2, 1181},
+       {0x1E8A, 0, 2, 1183},
+       {0x1E8B, 0, 2, 1185},
+       {0x1E8C, 0, 2, 1187},
+       {0x1E8D, 0, 2, 1189},
+       {0x1E8E, 0, 2, 1191},
+       {0x1E8F, 0, 2, 1193},
+       {0x1E90, 0, 2, 1195},
+       {0x1E91, 0, 2, 1197},
+       {0x1E92, 0, 2, 1199},
+       {0x1E93, 0, 2, 1201},
+       {0x1E94, 0, 2, 1203},
+       {0x1E95, 0, 2, 1205},
+       {0x1E96, 0, 2, 1207},
+       {0x1E97, 0, 2, 1209},
+       {0x1E98, 0, 2, 1211},
+       {0x1E99, 0, 2, 1213},
+       {0x1E9A, 0, 2 | DECOMP_NO_COMPOSE, 1215},       /* compatibility mapping */
+       {0x1E9B, 0, 2, 1217},
+       {0x1EA0, 0, 2, 1219},
+       {0x1EA1, 0, 2, 1221},
+       {0x1EA2, 0, 2, 1223},
+       {0x1EA3, 0, 2, 1225},
+       {0x1EA4, 0, 2, 1227},
+       {0x1EA5, 0, 2, 1229},
+       {0x1EA6, 0, 2, 1231},
+       {0x1EA7, 0, 2, 1233},
+       {0x1EA8, 0, 2, 1235},
+       {0x1EA9, 0, 2, 1237},
+       {0x1EAA, 0, 2, 1239},
+       {0x1EAB, 0, 2, 1241},
+       {0x1EAC, 0, 2, 1243},
+       {0x1EAD, 0, 2, 1245},
+       {0x1EAE, 0, 2, 1247},
+       {0x1EAF, 0, 2, 1249},
+       {0x1EB0, 0, 2, 1251},
+       {0x1EB1, 0, 2, 1253},
+       {0x1EB2, 0, 2, 1255},
+       {0x1EB3, 0, 2, 1257},
+       {0x1EB4, 0, 2, 1259},
+       {0x1EB5, 0, 2, 1261},
+       {0x1EB6, 0, 2, 1263},
+       {0x1EB7, 0, 2, 1265},
+       {0x1EB8, 0, 2, 1267},
+       {0x1EB9, 0, 2, 1269},
+       {0x1EBA, 0, 2, 1271},
+       {0x1EBB, 0, 2, 1273},
+       {0x1EBC, 0, 2, 1275},
+       {0x1EBD, 0, 2, 1277},
+       {0x1EBE, 0, 2, 1279},
+       {0x1EBF, 0, 2, 1281},
+       {0x1EC0, 0, 2, 1283},
+       {0x1EC1, 0, 2, 1285},
+       {0x1EC2, 0, 2, 1287},
+       {0x1EC3, 0, 2, 1289},
+       {0x1EC4, 0, 2, 1291},
+       {0x1EC5, 0, 2, 1293},
+       {0x1EC6, 0, 2, 1295},
+       {0x1EC7, 0, 2, 1297},
+       {0x1EC8, 0, 2, 1299},
+       {0x1EC9, 0, 2, 1301},
+       {0x1ECA, 0, 2, 1303},
+       {0x1ECB, 0, 2, 1305},
+       {0x1ECC, 0, 2, 1307},
+       {0x1ECD, 0, 2, 1309},
+       {0x1ECE, 0, 2, 1311},
+       {0x1ECF, 0, 2, 1313},
+       {0x1ED0, 0, 2, 1315},
+       {0x1ED1, 0, 2, 1317},
+       {0x1ED2, 0, 2, 1319},
+       {0x1ED3, 0, 2, 1321},
+       {0x1ED4, 0, 2, 1323},
+       {0x1ED5, 0, 2, 1325},
+       {0x1ED6, 0, 2, 1327},
+       {0x1ED7, 0, 2, 1329},
+       {0x1ED8, 0, 2, 1331},
+       {0x1ED9, 0, 2, 1333},
+       {0x1EDA, 0, 2, 1335},
+       {0x1EDB, 0, 2, 1337},
+       {0x1EDC, 0, 2, 1339},
+       {0x1EDD, 0, 2, 1341},
+       {0x1EDE, 0, 2, 1343},
+       {0x1EDF, 0, 2, 1345},
+       {0x1EE0, 0, 2, 1347},
+       {0x1EE1, 0, 2, 1349},
+       {0x1EE2, 0, 2, 1351},
+       {0x1EE3, 0, 2, 1353},
+       {0x1EE4, 0, 2, 1355},
+       {0x1EE5, 0, 2, 1357},
+       {0x1EE6, 0, 2, 1359},
+       {0x1EE7, 0, 2, 1361},
+       {0x1EE8, 0, 2, 1363},
+       {0x1EE9, 0, 2, 1365},
+       {0x1EEA, 0, 2, 1367},
+       {0x1EEB, 0, 2, 1369},
+       {0x1EEC, 0, 2, 1371},
+       {0x1EED, 0, 2, 1373},
+       {0x1EEE, 0, 2, 1375},
+       {0x1EEF, 0, 2, 1377},
+       {0x1EF0, 0, 2, 1379},
+       {0x1EF1, 0, 2, 1381},
+       {0x1EF2, 0, 2, 1383},
+       {0x1EF3, 0, 2, 1385},
+       {0x1EF4, 0, 2, 1387},
+       {0x1EF5, 0, 2, 1389},
+       {0x1EF6, 0, 2, 1391},
+       {0x1EF7, 0, 2, 1393},
+       {0x1EF8, 0, 2, 1395},
+       {0x1EF9, 0, 2, 1397},
+       {0x1F00, 0, 2, 1399},
+       {0x1F01, 0, 2, 1401},
+       {0x1F02, 0, 2, 1403},
+       {0x1F03, 0, 2, 1405},
+       {0x1F04, 0, 2, 1407},
+       {0x1F05, 0, 2, 1409},
+       {0x1F06, 0, 2, 1411},
+       {0x1F07, 0, 2, 1413},
+       {0x1F08, 0, 2, 1415},
+       {0x1F09, 0, 2, 1417},
+       {0x1F0A, 0, 2, 1419},
+       {0x1F0B, 0, 2, 1421},
+       {0x1F0C, 0, 2, 1423},
+       {0x1F0D, 0, 2, 1425},
+       {0x1F0E, 0, 2, 1427},
+       {0x1F0F, 0, 2, 1429},
+       {0x1F10, 0, 2, 1431},
+       {0x1F11, 0, 2, 1433},
+       {0x1F12, 0, 2, 1435},
+       {0x1F13, 0, 2, 1437},
+       {0x1F14, 0, 2, 1439},
+       {0x1F15, 0, 2, 1441},
+       {0x1F18, 0, 2, 1443},
+       {0x1F19, 0, 2, 1445},
+       {0x1F1A, 0, 2, 1447},
+       {0x1F1B, 0, 2, 1449},
+       {0x1F1C, 0, 2, 1451},
+       {0x1F1D, 0, 2, 1453},
+       {0x1F20, 0, 2, 1455},
+       {0x1F21, 0, 2, 1457},
+       {0x1F22, 0, 2, 1459},
+       {0x1F23, 0, 2, 1461},
+       {0x1F24, 0, 2, 1463},
+       {0x1F25, 0, 2, 1465},
+       {0x1F26, 0, 2, 1467},
+       {0x1F27, 0, 2, 1469},
+       {0x1F28, 0, 2, 1471},
+       {0x1F29, 0, 2, 1473},
+       {0x1F2A, 0, 2, 1475},
+       {0x1F2B, 0, 2, 1477},
+       {0x1F2C, 0, 2, 1479},
+       {0x1F2D, 0, 2, 1481},
+       {0x1F2E, 0, 2, 1483},
+       {0x1F2F, 0, 2, 1485},
+       {0x1F30, 0, 2, 1487},
+       {0x1F31, 0, 2, 1489},
+       {0x1F32, 0, 2, 1491},
+       {0x1F33, 0, 2, 1493},
+       {0x1F34, 0, 2, 1495},
+       {0x1F35, 0, 2, 1497},
+       {0x1F36, 0, 2, 1499},
+       {0x1F37, 0, 2, 1501},
+       {0x1F38, 0, 2, 1503},
+       {0x1F39, 0, 2, 1505},
+       {0x1F3A, 0, 2, 1507},
+       {0x1F3B, 0, 2, 1509},
+       {0x1F3C, 0, 2, 1511},
+       {0x1F3D, 0, 2, 1513},
+       {0x1F3E, 0, 2, 1515},
+       {0x1F3F, 0, 2, 1517},
+       {0x1F40, 0, 2, 1519},
+       {0x1F41, 0, 2, 1521},
+       {0x1F42, 0, 2, 1523},
+       {0x1F43, 0, 2, 1525},
+       {0x1F44, 0, 2, 1527},
+       {0x1F45, 0, 2, 1529},
+       {0x1F48, 0, 2, 1531},
+       {0x1F49, 0, 2, 1533},
+       {0x1F4A, 0, 2, 1535},
+       {0x1F4B, 0, 2, 1537},
+       {0x1F4C, 0, 2, 1539},
+       {0x1F4D, 0, 2, 1541},
+       {0x1F50, 0, 2, 1543},
+       {0x1F51, 0, 2, 1545},
+       {0x1F52, 0, 2, 1547},
+       {0x1F53, 0, 2, 1549},
+       {0x1F54, 0, 2, 1551},
+       {0x1F55, 0, 2, 1553},
+       {0x1F56, 0, 2, 1555},
+       {0x1F57, 0, 2, 1557},
+       {0x1F59, 0, 2, 1559},
+       {0x1F5B, 0, 2, 1561},
+       {0x1F5D, 0, 2, 1563},
+       {0x1F5F, 0, 2, 1565},
+       {0x1F60, 0, 2, 1567},
+       {0x1F61, 0, 2, 1569},
+       {0x1F62, 0, 2, 1571},
+       {0x1F63, 0, 2, 1573},
+       {0x1F64, 0, 2, 1575},
+       {0x1F65, 0, 2, 1577},
+       {0x1F66, 0, 2, 1579},
+       {0x1F67, 0, 2, 1581},
+       {0x1F68, 0, 2, 1583},
+       {0x1F69, 0, 2, 1585},
+       {0x1F6A, 0, 2, 1587},
+       {0x1F6B, 0, 2, 1589},
+       {0x1F6C, 0, 2, 1591},
+       {0x1F6D, 0, 2, 1593},
+       {0x1F6E, 0, 2, 1595},
+       {0x1F6F, 0, 2, 1597},
+       {0x1F70, 0, 2, 1599},
+       {0x1F71, 0, 1 | DECOMP_INLINE, 0x03AC},
+       {0x1F72, 0, 2, 1601},
+       {0x1F73, 0, 1 | DECOMP_INLINE, 0x03AD},
+       {0x1F74, 0, 2, 1603},
+       {0x1F75, 0, 1 | DECOMP_INLINE, 0x03AE},
+       {0x1F76, 0, 2, 1605},
+       {0x1F77, 0, 1 | DECOMP_INLINE, 0x03AF},
+       {0x1F78, 0, 2, 1607},
+       {0x1F79, 0, 1 | DECOMP_INLINE, 0x03CC},
+       {0x1F7A, 0, 2, 1609},
+       {0x1F7B, 0, 1 | DECOMP_INLINE, 0x03CD},
+       {0x1F7C, 0, 2, 1611},
+       {0x1F7D, 0, 1 | DECOMP_INLINE, 0x03CE},
+       {0x1F80, 0, 2, 1613},
+       {0x1F81, 0, 2, 1615},
+       {0x1F82, 0, 2, 1617},
+       {0x1F83, 0, 2, 1619},
+       {0x1F84, 0, 2, 1621},
+       {0x1F85, 0, 2, 1623},
+       {0x1F86, 0, 2, 1625},
+       {0x1F87, 0, 2, 1627},
+       {0x1F88, 0, 2, 1629},
+       {0x1F89, 0, 2, 1631},
+       {0x1F8A, 0, 2, 1633},
+       {0x1F8B, 0, 2, 1635},
+       {0x1F8C, 0, 2, 1637},
+       {0x1F8D, 0, 2, 1639},
+       {0x1F8E, 0, 2, 1641},
+       {0x1F8F, 0, 2, 1643},
+       {0x1F90, 0, 2, 1645},
+       {0x1F91, 0, 2, 1647},
+       {0x1F92, 0, 2, 1649},
+       {0x1F93, 0, 2, 1651},
+       {0x1F94, 0, 2, 1653},
+       {0x1F95, 0, 2, 1655},
+       {0x1F96, 0, 2, 1657},
+       {0x1F97, 0, 2, 1659},
+       {0x1F98, 0, 2, 1661},
+       {0x1F99, 0, 2, 1663},
+       {0x1F9A, 0, 2, 1665},
+       {0x1F9B, 0, 2, 1667},
+       {0x1F9C, 0, 2, 1669},
+       {0x1F9D, 0, 2, 1671},
+       {0x1F9E, 0, 2, 1673},
+       {0x1F9F, 0, 2, 1675},
+       {0x1FA0, 0, 2, 1677},
+       {0x1FA1, 0, 2, 1679},
+       {0x1FA2, 0, 2, 1681},
+       {0x1FA3, 0, 2, 1683},
+       {0x1FA4, 0, 2, 1685},
+       {0x1FA5, 0, 2, 1687},
+       {0x1FA6, 0, 2, 1689},
+       {0x1FA7, 0, 2, 1691},
+       {0x1FA8, 0, 2, 1693},
+       {0x1FA9, 0, 2, 1695},
+       {0x1FAA, 0, 2, 1697},
+       {0x1FAB, 0, 2, 1699},
+       {0x1FAC, 0, 2, 1701},
+       {0x1FAD, 0, 2, 1703},
+       {0x1FAE, 0, 2, 1705},
+       {0x1FAF, 0, 2, 1707},
+       {0x1FB0, 0, 2, 1709},
+       {0x1FB1, 0, 2, 1711},
+       {0x1FB2, 0, 2, 1713},
+       {0x1FB3, 0, 2, 1715},
+       {0x1FB4, 0, 2, 1717},
+       {0x1FB6, 0, 2, 1719},
+       {0x1FB7, 0, 2, 1721},
+       {0x1FB8, 0, 2, 1723},
+       {0x1FB9, 0, 2, 1725},
+       {0x1FBA, 0, 2, 1727},
+       {0x1FBB, 0, 1 | DECOMP_INLINE, 0x0386},
+       {0x1FBC, 0, 2, 1729},
+       {0x1FBD, 0, 2 | DECOMP_NO_COMPOSE, 1731},       /* compatibility mapping */
+       {0x1FBE, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1FBF, 0, 2 | DECOMP_NO_COMPOSE, 1733},       /* compatibility mapping */
+       {0x1FC0, 0, 2 | DECOMP_NO_COMPOSE, 1735},       /* compatibility mapping */
+       {0x1FC1, 0, 2, 1737},
+       {0x1FC2, 0, 2, 1739},
+       {0x1FC3, 0, 2, 1741},
+       {0x1FC4, 0, 2, 1743},
+       {0x1FC6, 0, 2, 1745},
+       {0x1FC7, 0, 2, 1747},
+       {0x1FC8, 0, 2, 1749},
+       {0x1FC9, 0, 1 | DECOMP_INLINE, 0x0388},
+       {0x1FCA, 0, 2, 1751},
+       {0x1FCB, 0, 1 | DECOMP_INLINE, 0x0389},
+       {0x1FCC, 0, 2, 1753},
+       {0x1FCD, 0, 2, 1755},
+       {0x1FCE, 0, 2, 1757},
+       {0x1FCF, 0, 2, 1759},
+       {0x1FD0, 0, 2, 1761},
+       {0x1FD1, 0, 2, 1763},
+       {0x1FD2, 0, 2, 1765},
+       {0x1FD3, 0, 1 | DECOMP_INLINE, 0x0390},
+       {0x1FD6, 0, 2, 1767},
+       {0x1FD7, 0, 2, 1769},
+       {0x1FD8, 0, 2, 1771},
+       {0x1FD9, 0, 2, 1773},
+       {0x1FDA, 0, 2, 1775},
+       {0x1FDB, 0, 1 | DECOMP_INLINE, 0x038A},
+       {0x1FDD, 0, 2, 1777},
+       {0x1FDE, 0, 2, 1779},
+       {0x1FDF, 0, 2, 1781},
+       {0x1FE0, 0, 2, 1783},
+       {0x1FE1, 0, 2, 1785},
+       {0x1FE2, 0, 2, 1787},
+       {0x1FE3, 0, 1 | DECOMP_INLINE, 0x03B0},
+       {0x1FE4, 0, 2, 1789},
+       {0x1FE5, 0, 2, 1791},
+       {0x1FE6, 0, 2, 1793},
+       {0x1FE7, 0, 2, 1795},
+       {0x1FE8, 0, 2, 1797},
+       {0x1FE9, 0, 2, 1799},
+       {0x1FEA, 0, 2, 1801},
+       {0x1FEB, 0, 1 | DECOMP_INLINE, 0x038E},
+       {0x1FEC, 0, 2, 1803},
+       {0x1FED, 0, 2, 1805},
+       {0x1FEE, 0, 1 | DECOMP_INLINE, 0x0385},
+       {0x1FEF, 0, 1 | DECOMP_INLINE, 0x0060},
+       {0x1FF2, 0, 2, 1807},
+       {0x1FF3, 0, 2, 1809},
+       {0x1FF4, 0, 2, 1811},
+       {0x1FF6, 0, 2, 1813},
+       {0x1FF7, 0, 2, 1815},
+       {0x1FF8, 0, 2, 1817},
+       {0x1FF9, 0, 1 | DECOMP_INLINE, 0x038C},
+       {0x1FFA, 0, 2, 1819},
+       {0x1FFB, 0, 1 | DECOMP_INLINE, 0x038F},
+       {0x1FFC, 0, 2, 1821},
+       {0x1FFD, 0, 1 | DECOMP_INLINE, 0x00B4},
+       {0x1FFE, 0, 2 | DECOMP_NO_COMPOSE, 1823},       /* compatibility mapping */
+       {0x2000, 0, 1 | DECOMP_INLINE, 0x2002},
+       {0x2001, 0, 1 | DECOMP_INLINE, 0x2003},
+       {0x2002, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2003, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2004, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2005, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2006, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2007, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2008, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2009, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x200A, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2011, 0, 1 | DECOMP_INLINE, 0x2010},
+       {0x2017, 0, 2 | DECOMP_NO_COMPOSE, 1825},       /* compatibility mapping */
+       {0x2024, 0, 1 | DECOMP_INLINE, 0x002E},
+       {0x2025, 0, 2 | DECOMP_NO_COMPOSE, 1827},       /* compatibility mapping */
+       {0x2026, 0, 3, 1829},
+       {0x202F, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2033, 0, 2 | DECOMP_NO_COMPOSE, 1832},       /* compatibility mapping */
+       {0x2034, 0, 3, 1834},
+       {0x2036, 0, 2 | DECOMP_NO_COMPOSE, 1837},       /* compatibility mapping */
+       {0x2037, 0, 3, 1839},
+       {0x203C, 0, 2 | DECOMP_NO_COMPOSE, 1842},       /* compatibility mapping */
+       {0x203E, 0, 2 | DECOMP_NO_COMPOSE, 1844},       /* compatibility mapping */
+       {0x2047, 0, 2 | DECOMP_NO_COMPOSE, 1846},       /* compatibility mapping */
+       {0x2048, 0, 2 | DECOMP_NO_COMPOSE, 1848},       /* compatibility mapping */
+       {0x2049, 0, 2 | DECOMP_NO_COMPOSE, 1850},       /* compatibility mapping */
+       {0x2057, 0, 4, 1852},
+       {0x205F, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x2070, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x2071, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x2074, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x2075, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x2076, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x2077, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x2078, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x2079, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x207A, 0, 1 | DECOMP_INLINE, 0x002B},
+       {0x207B, 0, 1 | DECOMP_INLINE, 0x2212},
+       {0x207C, 0, 1 | DECOMP_INLINE, 0x003D},
+       {0x207D, 0, 1 | DECOMP_INLINE, 0x0028},
+       {0x207E, 0, 1 | DECOMP_INLINE, 0x0029},
+       {0x207F, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x2080, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x2081, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x2082, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x2083, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x2084, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x2085, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x2086, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x2087, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x2088, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x2089, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x208A, 0, 1 | DECOMP_INLINE, 0x002B},
+       {0x208B, 0, 1 | DECOMP_INLINE, 0x2212},
+       {0x208C, 0, 1 | DECOMP_INLINE, 0x003D},
+       {0x208D, 0, 1 | DECOMP_INLINE, 0x0028},
+       {0x208E, 0, 1 | DECOMP_INLINE, 0x0029},
+       {0x2090, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x2091, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x2092, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x2093, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x2094, 0, 1 | DECOMP_INLINE, 0x0259},
+       {0x2095, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x2096, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x2097, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x2098, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x2099, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x209A, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x209B, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x209C, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x20A8, 0, 2 | DECOMP_NO_COMPOSE, 1856},       /* compatibility mapping */
+       {0x20D0, 230, 0, 0},
+       {0x20D1, 230, 0, 0},
+       {0x20D2, 1, 0, 0},
+       {0x20D3, 1, 0, 0},
+       {0x20D4, 230, 0, 0},
+       {0x20D5, 230, 0, 0},
+       {0x20D6, 230, 0, 0},
+       {0x20D7, 230, 0, 0},
+       {0x20D8, 1, 0, 0},
+       {0x20D9, 1, 0, 0},
+       {0x20DA, 1, 0, 0},
+       {0x20DB, 230, 0, 0},
+       {0x20DC, 230, 0, 0},
+       {0x20E1, 230, 0, 0},
+       {0x20E5, 1, 0, 0},
+       {0x20E6, 1, 0, 0},
+       {0x20E7, 230, 0, 0},
+       {0x20E8, 220, 0, 0},
+       {0x20E9, 230, 0, 0},
+       {0x20EA, 1, 0, 0},
+       {0x20EB, 1, 0, 0},
+       {0x20EC, 220, 0, 0},
+       {0x20ED, 220, 0, 0},
+       {0x20EE, 220, 0, 0},
+       {0x20EF, 220, 0, 0},
+       {0x20F0, 230, 0, 0},
+       {0x2100, 0, 3, 1858},
+       {0x2101, 0, 3, 1861},
+       {0x2102, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x2103, 0, 2 | DECOMP_NO_COMPOSE, 1864},       /* compatibility mapping */
+       {0x2105, 0, 3, 1866},
+       {0x2106, 0, 3, 1869},
+       {0x2107, 0, 1 | DECOMP_INLINE, 0x0190},
+       {0x2109, 0, 2 | DECOMP_NO_COMPOSE, 1872},       /* compatibility mapping */
+       {0x210A, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x210B, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x210C, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x210D, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x210E, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x210F, 0, 1 | DECOMP_INLINE, 0x0127},
+       {0x2110, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x2111, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x2112, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x2113, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x2115, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x2116, 0, 2 | DECOMP_NO_COMPOSE, 1874},       /* compatibility mapping */
+       {0x2119, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x211A, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x211B, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x211C, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x211D, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x2120, 0, 2 | DECOMP_NO_COMPOSE, 1876},       /* compatibility mapping */
+       {0x2121, 0, 3, 1878},
+       {0x2122, 0, 2 | DECOMP_NO_COMPOSE, 1881},       /* compatibility mapping */
+       {0x2124, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x2126, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x2128, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x212A, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x212B, 0, 1 | DECOMP_INLINE, 0x00C5},
+       {0x212C, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x212D, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x212F, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x2130, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x2131, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x2133, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x2134, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x2135, 0, 1 | DECOMP_INLINE, 0x05D0},
+       {0x2136, 0, 1 | DECOMP_INLINE, 0x05D1},
+       {0x2137, 0, 1 | DECOMP_INLINE, 0x05D2},
+       {0x2138, 0, 1 | DECOMP_INLINE, 0x05D3},
+       {0x2139, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x213B, 0, 3, 1883},
+       {0x213C, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x213D, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x213E, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x213F, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x2140, 0, 1 | DECOMP_INLINE, 0x2211},
+       {0x2145, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x2146, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x2147, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x2148, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x2149, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x2150, 0, 3, 1886},
+       {0x2151, 0, 3, 1889},
+       {0x2152, 0, 4, 1892},
+       {0x2153, 0, 3, 1896},
+       {0x2154, 0, 3, 1899},
+       {0x2155, 0, 3, 1902},
+       {0x2156, 0, 3, 1905},
+       {0x2157, 0, 3, 1908},
+       {0x2158, 0, 3, 1911},
+       {0x2159, 0, 3, 1914},
+       {0x215A, 0, 3, 1917},
+       {0x215B, 0, 3, 1920},
+       {0x215C, 0, 3, 1923},
+       {0x215D, 0, 3, 1926},
+       {0x215E, 0, 3, 1929},
+       {0x215F, 0, 2 | DECOMP_NO_COMPOSE, 1932},       /* compatibility mapping */
+       {0x2160, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x2161, 0, 2 | DECOMP_NO_COMPOSE, 1934},       /* compatibility mapping */
+       {0x2162, 0, 3, 1936},
+       {0x2163, 0, 2 | DECOMP_NO_COMPOSE, 1939},       /* compatibility mapping */
+       {0x2164, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x2165, 0, 2 | DECOMP_NO_COMPOSE, 1941},       /* compatibility mapping */
+       {0x2166, 0, 3, 1943},
+       {0x2167, 0, 4, 1946},
+       {0x2168, 0, 2 | DECOMP_NO_COMPOSE, 1950},       /* compatibility mapping */
+       {0x2169, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x216A, 0, 2 | DECOMP_NO_COMPOSE, 1952},       /* compatibility mapping */
+       {0x216B, 0, 3, 1954},
+       {0x216C, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x216D, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x216E, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x216F, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x2170, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x2171, 0, 2 | DECOMP_NO_COMPOSE, 1957},       /* compatibility mapping */
+       {0x2172, 0, 3, 1959},
+       {0x2173, 0, 2 | DECOMP_NO_COMPOSE, 1962},       /* compatibility mapping */
+       {0x2174, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x2175, 0, 2 | DECOMP_NO_COMPOSE, 1964},       /* compatibility mapping */
+       {0x2176, 0, 3, 1966},
+       {0x2177, 0, 4, 1969},
+       {0x2178, 0, 2 | DECOMP_NO_COMPOSE, 1973},       /* compatibility mapping */
+       {0x2179, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x217A, 0, 2 | DECOMP_NO_COMPOSE, 1975},       /* compatibility mapping */
+       {0x217B, 0, 3, 1977},
+       {0x217C, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x217D, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x217E, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x217F, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x2189, 0, 3, 1980},
+       {0x219A, 0, 2, 1983},
+       {0x219B, 0, 2, 1985},
+       {0x21AE, 0, 2, 1987},
+       {0x21CD, 0, 2, 1989},
+       {0x21CE, 0, 2, 1991},
+       {0x21CF, 0, 2, 1993},
+       {0x2204, 0, 2, 1995},
+       {0x2209, 0, 2, 1997},
+       {0x220C, 0, 2, 1999},
+       {0x2224, 0, 2, 2001},
+       {0x2226, 0, 2, 2003},
+       {0x222C, 0, 2 | DECOMP_NO_COMPOSE, 2005},       /* compatibility mapping */
+       {0x222D, 0, 3, 2007},
+       {0x222F, 0, 2 | DECOMP_NO_COMPOSE, 2010},       /* compatibility mapping */
+       {0x2230, 0, 3, 2012},
+       {0x2241, 0, 2, 2015},
+       {0x2244, 0, 2, 2017},
+       {0x2247, 0, 2, 2019},
+       {0x2249, 0, 2, 2021},
+       {0x2260, 0, 2, 2023},
+       {0x2262, 0, 2, 2025},
+       {0x226D, 0, 2, 2027},
+       {0x226E, 0, 2, 2029},
+       {0x226F, 0, 2, 2031},
+       {0x2270, 0, 2, 2033},
+       {0x2271, 0, 2, 2035},
+       {0x2274, 0, 2, 2037},
+       {0x2275, 0, 2, 2039},
+       {0x2278, 0, 2, 2041},
+       {0x2279, 0, 2, 2043},
+       {0x2280, 0, 2, 2045},
+       {0x2281, 0, 2, 2047},
+       {0x2284, 0, 2, 2049},
+       {0x2285, 0, 2, 2051},
+       {0x2288, 0, 2, 2053},
+       {0x2289, 0, 2, 2055},
+       {0x22AC, 0, 2, 2057},
+       {0x22AD, 0, 2, 2059},
+       {0x22AE, 0, 2, 2061},
+       {0x22AF, 0, 2, 2063},
+       {0x22E0, 0, 2, 2065},
+       {0x22E1, 0, 2, 2067},
+       {0x22E2, 0, 2, 2069},
+       {0x22E3, 0, 2, 2071},
+       {0x22EA, 0, 2, 2073},
+       {0x22EB, 0, 2, 2075},
+       {0x22EC, 0, 2, 2077},
+       {0x22ED, 0, 2, 2079},
+       {0x2329, 0, 1 | DECOMP_INLINE, 0x3008},
+       {0x232A, 0, 1 | DECOMP_INLINE, 0x3009},
+       {0x2460, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x2461, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x2462, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x2463, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x2464, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x2465, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x2466, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x2467, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x2468, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x2469, 0, 2 | DECOMP_NO_COMPOSE, 2081},       /* compatibility mapping */
+       {0x246A, 0, 2 | DECOMP_NO_COMPOSE, 2083},       /* compatibility mapping */
+       {0x246B, 0, 2 | DECOMP_NO_COMPOSE, 2085},       /* compatibility mapping */
+       {0x246C, 0, 2 | DECOMP_NO_COMPOSE, 2087},       /* compatibility mapping */
+       {0x246D, 0, 2 | DECOMP_NO_COMPOSE, 2089},       /* compatibility mapping */
+       {0x246E, 0, 2 | DECOMP_NO_COMPOSE, 2091},       /* compatibility mapping */
+       {0x246F, 0, 2 | DECOMP_NO_COMPOSE, 2093},       /* compatibility mapping */
+       {0x2470, 0, 2 | DECOMP_NO_COMPOSE, 2095},       /* compatibility mapping */
+       {0x2471, 0, 2 | DECOMP_NO_COMPOSE, 2097},       /* compatibility mapping */
+       {0x2472, 0, 2 | DECOMP_NO_COMPOSE, 2099},       /* compatibility mapping */
+       {0x2473, 0, 2 | DECOMP_NO_COMPOSE, 2101},       /* compatibility mapping */
+       {0x2474, 0, 3, 2103},
+       {0x2475, 0, 3, 2106},
+       {0x2476, 0, 3, 2109},
+       {0x2477, 0, 3, 2112},
+       {0x2478, 0, 3, 2115},
+       {0x2479, 0, 3, 2118},
+       {0x247A, 0, 3, 2121},
+       {0x247B, 0, 3, 2124},
+       {0x247C, 0, 3, 2127},
+       {0x247D, 0, 4, 2130},
+       {0x247E, 0, 4, 2134},
+       {0x247F, 0, 4, 2138},
+       {0x2480, 0, 4, 2142},
+       {0x2481, 0, 4, 2146},
+       {0x2482, 0, 4, 2150},
+       {0x2483, 0, 4, 2154},
+       {0x2484, 0, 4, 2158},
+       {0x2485, 0, 4, 2162},
+       {0x2486, 0, 4, 2166},
+       {0x2487, 0, 4, 2170},
+       {0x2488, 0, 2 | DECOMP_NO_COMPOSE, 2174},       /* compatibility mapping */
+       {0x2489, 0, 2 | DECOMP_NO_COMPOSE, 2176},       /* compatibility mapping */
+       {0x248A, 0, 2 | DECOMP_NO_COMPOSE, 2178},       /* compatibility mapping */
+       {0x248B, 0, 2 | DECOMP_NO_COMPOSE, 2180},       /* compatibility mapping */
+       {0x248C, 0, 2 | DECOMP_NO_COMPOSE, 2182},       /* compatibility mapping */
+       {0x248D, 0, 2 | DECOMP_NO_COMPOSE, 2184},       /* compatibility mapping */
+       {0x248E, 0, 2 | DECOMP_NO_COMPOSE, 2186},       /* compatibility mapping */
+       {0x248F, 0, 2 | DECOMP_NO_COMPOSE, 2188},       /* compatibility mapping */
+       {0x2490, 0, 2 | DECOMP_NO_COMPOSE, 2190},       /* compatibility mapping */
+       {0x2491, 0, 3, 2192},
+       {0x2492, 0, 3, 2195},
+       {0x2493, 0, 3, 2198},
+       {0x2494, 0, 3, 2201},
+       {0x2495, 0, 3, 2204},
+       {0x2496, 0, 3, 2207},
+       {0x2497, 0, 3, 2210},
+       {0x2498, 0, 3, 2213},
+       {0x2499, 0, 3, 2216},
+       {0x249A, 0, 3, 2219},
+       {0x249B, 0, 3, 2222},
+       {0x249C, 0, 3, 2225},
+       {0x249D, 0, 3, 2228},
+       {0x249E, 0, 3, 2231},
+       {0x249F, 0, 3, 2234},
+       {0x24A0, 0, 3, 2237},
+       {0x24A1, 0, 3, 2240},
+       {0x24A2, 0, 3, 2243},
+       {0x24A3, 0, 3, 2246},
+       {0x24A4, 0, 3, 2249},
+       {0x24A5, 0, 3, 2252},
+       {0x24A6, 0, 3, 2255},
+       {0x24A7, 0, 3, 2258},
+       {0x24A8, 0, 3, 2261},
+       {0x24A9, 0, 3, 2264},
+       {0x24AA, 0, 3, 2267},
+       {0x24AB, 0, 3, 2270},
+       {0x24AC, 0, 3, 2273},
+       {0x24AD, 0, 3, 2276},
+       {0x24AE, 0, 3, 2279},
+       {0x24AF, 0, 3, 2282},
+       {0x24B0, 0, 3, 2285},
+       {0x24B1, 0, 3, 2288},
+       {0x24B2, 0, 3, 2291},
+       {0x24B3, 0, 3, 2294},
+       {0x24B4, 0, 3, 2297},
+       {0x24B5, 0, 3, 2300},
+       {0x24B6, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x24B7, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x24B8, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x24B9, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x24BA, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x24BB, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x24BC, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x24BD, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x24BE, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x24BF, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x24C0, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x24C1, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x24C2, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x24C3, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x24C4, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x24C5, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x24C6, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x24C7, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x24C8, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x24C9, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x24CA, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x24CB, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x24CC, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x24CD, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x24CE, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x24CF, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x24D0, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x24D1, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x24D2, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x24D3, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x24D4, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x24D5, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x24D6, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x24D7, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x24D8, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x24D9, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x24DA, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x24DB, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x24DC, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x24DD, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x24DE, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x24DF, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x24E0, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x24E1, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x24E2, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x24E3, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x24E4, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x24E5, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x24E6, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x24E7, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x24E8, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x24E9, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x24EA, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x2A0C, 0, 4, 2303},
+       {0x2A74, 0, 3, 2307},
+       {0x2A75, 0, 2 | DECOMP_NO_COMPOSE, 2310},       /* compatibility mapping */
+       {0x2A76, 0, 3, 2312},
+       {0x2ADC, 0, 2 | DECOMP_NO_COMPOSE, 2315},       /* in exclusion list */
+       {0x2C7C, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x2C7D, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x2CEF, 230, 0, 0},
+       {0x2CF0, 230, 0, 0},
+       {0x2CF1, 230, 0, 0},
+       {0x2D6F, 0, 1 | DECOMP_INLINE, 0x2D61},
+       {0x2D7F, 9, 0, 0},
+       {0x2DE0, 230, 0, 0},
+       {0x2DE1, 230, 0, 0},
+       {0x2DE2, 230, 0, 0},
+       {0x2DE3, 230, 0, 0},
+       {0x2DE4, 230, 0, 0},
+       {0x2DE5, 230, 0, 0},
+       {0x2DE6, 230, 0, 0},
+       {0x2DE7, 230, 0, 0},
+       {0x2DE8, 230, 0, 0},
+       {0x2DE9, 230, 0, 0},
+       {0x2DEA, 230, 0, 0},
+       {0x2DEB, 230, 0, 0},
+       {0x2DEC, 230, 0, 0},
+       {0x2DED, 230, 0, 0},
+       {0x2DEE, 230, 0, 0},
+       {0x2DEF, 230, 0, 0},
+       {0x2DF0, 230, 0, 0},
+       {0x2DF1, 230, 0, 0},
+       {0x2DF2, 230, 0, 0},
+       {0x2DF3, 230, 0, 0},
+       {0x2DF4, 230, 0, 0},
+       {0x2DF5, 230, 0, 0},
+       {0x2DF6, 230, 0, 0},
+       {0x2DF7, 230, 0, 0},
+       {0x2DF8, 230, 0, 0},
+       {0x2DF9, 230, 0, 0},
+       {0x2DFA, 230, 0, 0},
+       {0x2DFB, 230, 0, 0},
+       {0x2DFC, 230, 0, 0},
+       {0x2DFD, 230, 0, 0},
+       {0x2DFE, 230, 0, 0},
+       {0x2DFF, 230, 0, 0},
+       {0x2E9F, 0, 1 | DECOMP_INLINE, 0x6BCD},
+       {0x2EF3, 0, 1 | DECOMP_INLINE, 0x9F9F},
+       {0x2F00, 0, 1 | DECOMP_INLINE, 0x4E00},
+       {0x2F01, 0, 1 | DECOMP_INLINE, 0x4E28},
+       {0x2F02, 0, 1 | DECOMP_INLINE, 0x4E36},
+       {0x2F03, 0, 1 | DECOMP_INLINE, 0x4E3F},
+       {0x2F04, 0, 1 | DECOMP_INLINE, 0x4E59},
+       {0x2F05, 0, 1 | DECOMP_INLINE, 0x4E85},
+       {0x2F06, 0, 1 | DECOMP_INLINE, 0x4E8C},
+       {0x2F07, 0, 1 | DECOMP_INLINE, 0x4EA0},
+       {0x2F08, 0, 1 | DECOMP_INLINE, 0x4EBA},
+       {0x2F09, 0, 1 | DECOMP_INLINE, 0x513F},
+       {0x2F0A, 0, 1 | DECOMP_INLINE, 0x5165},
+       {0x2F0B, 0, 1 | DECOMP_INLINE, 0x516B},
+       {0x2F0C, 0, 1 | DECOMP_INLINE, 0x5182},
+       {0x2F0D, 0, 1 | DECOMP_INLINE, 0x5196},
+       {0x2F0E, 0, 1 | DECOMP_INLINE, 0x51AB},
+       {0x2F0F, 0, 1 | DECOMP_INLINE, 0x51E0},
+       {0x2F10, 0, 1 | DECOMP_INLINE, 0x51F5},
+       {0x2F11, 0, 1 | DECOMP_INLINE, 0x5200},
+       {0x2F12, 0, 1 | DECOMP_INLINE, 0x529B},
+       {0x2F13, 0, 1 | DECOMP_INLINE, 0x52F9},
+       {0x2F14, 0, 1 | DECOMP_INLINE, 0x5315},
+       {0x2F15, 0, 1 | DECOMP_INLINE, 0x531A},
+       {0x2F16, 0, 1 | DECOMP_INLINE, 0x5338},
+       {0x2F17, 0, 1 | DECOMP_INLINE, 0x5341},
+       {0x2F18, 0, 1 | DECOMP_INLINE, 0x535C},
+       {0x2F19, 0, 1 | DECOMP_INLINE, 0x5369},
+       {0x2F1A, 0, 1 | DECOMP_INLINE, 0x5382},
+       {0x2F1B, 0, 1 | DECOMP_INLINE, 0x53B6},
+       {0x2F1C, 0, 1 | DECOMP_INLINE, 0x53C8},
+       {0x2F1D, 0, 1 | DECOMP_INLINE, 0x53E3},
+       {0x2F1E, 0, 1 | DECOMP_INLINE, 0x56D7},
+       {0x2F1F, 0, 1 | DECOMP_INLINE, 0x571F},
+       {0x2F20, 0, 1 | DECOMP_INLINE, 0x58EB},
+       {0x2F21, 0, 1 | DECOMP_INLINE, 0x5902},
+       {0x2F22, 0, 1 | DECOMP_INLINE, 0x590A},
+       {0x2F23, 0, 1 | DECOMP_INLINE, 0x5915},
+       {0x2F24, 0, 1 | DECOMP_INLINE, 0x5927},
+       {0x2F25, 0, 1 | DECOMP_INLINE, 0x5973},
+       {0x2F26, 0, 1 | DECOMP_INLINE, 0x5B50},
+       {0x2F27, 0, 1 | DECOMP_INLINE, 0x5B80},
+       {0x2F28, 0, 1 | DECOMP_INLINE, 0x5BF8},
+       {0x2F29, 0, 1 | DECOMP_INLINE, 0x5C0F},
+       {0x2F2A, 0, 1 | DECOMP_INLINE, 0x5C22},
+       {0x2F2B, 0, 1 | DECOMP_INLINE, 0x5C38},
+       {0x2F2C, 0, 1 | DECOMP_INLINE, 0x5C6E},
+       {0x2F2D, 0, 1 | DECOMP_INLINE, 0x5C71},
+       {0x2F2E, 0, 1 | DECOMP_INLINE, 0x5DDB},
+       {0x2F2F, 0, 1 | DECOMP_INLINE, 0x5DE5},
+       {0x2F30, 0, 1 | DECOMP_INLINE, 0x5DF1},
+       {0x2F31, 0, 1 | DECOMP_INLINE, 0x5DFE},
+       {0x2F32, 0, 1 | DECOMP_INLINE, 0x5E72},
+       {0x2F33, 0, 1 | DECOMP_INLINE, 0x5E7A},
+       {0x2F34, 0, 1 | DECOMP_INLINE, 0x5E7F},
+       {0x2F35, 0, 1 | DECOMP_INLINE, 0x5EF4},
+       {0x2F36, 0, 1 | DECOMP_INLINE, 0x5EFE},
+       {0x2F37, 0, 1 | DECOMP_INLINE, 0x5F0B},
+       {0x2F38, 0, 1 | DECOMP_INLINE, 0x5F13},
+       {0x2F39, 0, 1 | DECOMP_INLINE, 0x5F50},
+       {0x2F3A, 0, 1 | DECOMP_INLINE, 0x5F61},
+       {0x2F3B, 0, 1 | DECOMP_INLINE, 0x5F73},
+       {0x2F3C, 0, 1 | DECOMP_INLINE, 0x5FC3},
+       {0x2F3D, 0, 1 | DECOMP_INLINE, 0x6208},
+       {0x2F3E, 0, 1 | DECOMP_INLINE, 0x6236},
+       {0x2F3F, 0, 1 | DECOMP_INLINE, 0x624B},
+       {0x2F40, 0, 1 | DECOMP_INLINE, 0x652F},
+       {0x2F41, 0, 1 | DECOMP_INLINE, 0x6534},
+       {0x2F42, 0, 1 | DECOMP_INLINE, 0x6587},
+       {0x2F43, 0, 1 | DECOMP_INLINE, 0x6597},
+       {0x2F44, 0, 1 | DECOMP_INLINE, 0x65A4},
+       {0x2F45, 0, 1 | DECOMP_INLINE, 0x65B9},
+       {0x2F46, 0, 1 | DECOMP_INLINE, 0x65E0},
+       {0x2F47, 0, 1 | DECOMP_INLINE, 0x65E5},
+       {0x2F48, 0, 1 | DECOMP_INLINE, 0x66F0},
+       {0x2F49, 0, 1 | DECOMP_INLINE, 0x6708},
+       {0x2F4A, 0, 1 | DECOMP_INLINE, 0x6728},
+       {0x2F4B, 0, 1 | DECOMP_INLINE, 0x6B20},
+       {0x2F4C, 0, 1 | DECOMP_INLINE, 0x6B62},
+       {0x2F4D, 0, 1 | DECOMP_INLINE, 0x6B79},
+       {0x2F4E, 0, 1 | DECOMP_INLINE, 0x6BB3},
+       {0x2F4F, 0, 1 | DECOMP_INLINE, 0x6BCB},
+       {0x2F50, 0, 1 | DECOMP_INLINE, 0x6BD4},
+       {0x2F51, 0, 1 | DECOMP_INLINE, 0x6BDB},
+       {0x2F52, 0, 1 | DECOMP_INLINE, 0x6C0F},
+       {0x2F53, 0, 1 | DECOMP_INLINE, 0x6C14},
+       {0x2F54, 0, 1 | DECOMP_INLINE, 0x6C34},
+       {0x2F55, 0, 1 | DECOMP_INLINE, 0x706B},
+       {0x2F56, 0, 1 | DECOMP_INLINE, 0x722A},
+       {0x2F57, 0, 1 | DECOMP_INLINE, 0x7236},
+       {0x2F58, 0, 1 | DECOMP_INLINE, 0x723B},
+       {0x2F59, 0, 1 | DECOMP_INLINE, 0x723F},
+       {0x2F5A, 0, 1 | DECOMP_INLINE, 0x7247},
+       {0x2F5B, 0, 1 | DECOMP_INLINE, 0x7259},
+       {0x2F5C, 0, 1 | DECOMP_INLINE, 0x725B},
+       {0x2F5D, 0, 1 | DECOMP_INLINE, 0x72AC},
+       {0x2F5E, 0, 1 | DECOMP_INLINE, 0x7384},
+       {0x2F5F, 0, 1 | DECOMP_INLINE, 0x7389},
+       {0x2F60, 0, 1 | DECOMP_INLINE, 0x74DC},
+       {0x2F61, 0, 1 | DECOMP_INLINE, 0x74E6},
+       {0x2F62, 0, 1 | DECOMP_INLINE, 0x7518},
+       {0x2F63, 0, 1 | DECOMP_INLINE, 0x751F},
+       {0x2F64, 0, 1 | DECOMP_INLINE, 0x7528},
+       {0x2F65, 0, 1 | DECOMP_INLINE, 0x7530},
+       {0x2F66, 0, 1 | DECOMP_INLINE, 0x758B},
+       {0x2F67, 0, 1 | DECOMP_INLINE, 0x7592},
+       {0x2F68, 0, 1 | DECOMP_INLINE, 0x7676},
+       {0x2F69, 0, 1 | DECOMP_INLINE, 0x767D},
+       {0x2F6A, 0, 1 | DECOMP_INLINE, 0x76AE},
+       {0x2F6B, 0, 1 | DECOMP_INLINE, 0x76BF},
+       {0x2F6C, 0, 1 | DECOMP_INLINE, 0x76EE},
+       {0x2F6D, 0, 1 | DECOMP_INLINE, 0x77DB},
+       {0x2F6E, 0, 1 | DECOMP_INLINE, 0x77E2},
+       {0x2F6F, 0, 1 | DECOMP_INLINE, 0x77F3},
+       {0x2F70, 0, 1 | DECOMP_INLINE, 0x793A},
+       {0x2F71, 0, 1 | DECOMP_INLINE, 0x79B8},
+       {0x2F72, 0, 1 | DECOMP_INLINE, 0x79BE},
+       {0x2F73, 0, 1 | DECOMP_INLINE, 0x7A74},
+       {0x2F74, 0, 1 | DECOMP_INLINE, 0x7ACB},
+       {0x2F75, 0, 1 | DECOMP_INLINE, 0x7AF9},
+       {0x2F76, 0, 1 | DECOMP_INLINE, 0x7C73},
+       {0x2F77, 0, 1 | DECOMP_INLINE, 0x7CF8},
+       {0x2F78, 0, 1 | DECOMP_INLINE, 0x7F36},
+       {0x2F79, 0, 1 | DECOMP_INLINE, 0x7F51},
+       {0x2F7A, 0, 1 | DECOMP_INLINE, 0x7F8A},
+       {0x2F7B, 0, 1 | DECOMP_INLINE, 0x7FBD},
+       {0x2F7C, 0, 1 | DECOMP_INLINE, 0x8001},
+       {0x2F7D, 0, 1 | DECOMP_INLINE, 0x800C},
+       {0x2F7E, 0, 1 | DECOMP_INLINE, 0x8012},
+       {0x2F7F, 0, 1 | DECOMP_INLINE, 0x8033},
+       {0x2F80, 0, 1 | DECOMP_INLINE, 0x807F},
+       {0x2F81, 0, 1 | DECOMP_INLINE, 0x8089},
+       {0x2F82, 0, 1 | DECOMP_INLINE, 0x81E3},
+       {0x2F83, 0, 1 | DECOMP_INLINE, 0x81EA},
+       {0x2F84, 0, 1 | DECOMP_INLINE, 0x81F3},
+       {0x2F85, 0, 1 | DECOMP_INLINE, 0x81FC},
+       {0x2F86, 0, 1 | DECOMP_INLINE, 0x820C},
+       {0x2F87, 0, 1 | DECOMP_INLINE, 0x821B},
+       {0x2F88, 0, 1 | DECOMP_INLINE, 0x821F},
+       {0x2F89, 0, 1 | DECOMP_INLINE, 0x826E},
+       {0x2F8A, 0, 1 | DECOMP_INLINE, 0x8272},
+       {0x2F8B, 0, 1 | DECOMP_INLINE, 0x8278},
+       {0x2F8C, 0, 1 | DECOMP_INLINE, 0x864D},
+       {0x2F8D, 0, 1 | DECOMP_INLINE, 0x866B},
+       {0x2F8E, 0, 1 | DECOMP_INLINE, 0x8840},
+       {0x2F8F, 0, 1 | DECOMP_INLINE, 0x884C},
+       {0x2F90, 0, 1 | DECOMP_INLINE, 0x8863},
+       {0x2F91, 0, 1 | DECOMP_INLINE, 0x897E},
+       {0x2F92, 0, 1 | DECOMP_INLINE, 0x898B},
+       {0x2F93, 0, 1 | DECOMP_INLINE, 0x89D2},
+       {0x2F94, 0, 1 | DECOMP_INLINE, 0x8A00},
+       {0x2F95, 0, 1 | DECOMP_INLINE, 0x8C37},
+       {0x2F96, 0, 1 | DECOMP_INLINE, 0x8C46},
+       {0x2F97, 0, 1 | DECOMP_INLINE, 0x8C55},
+       {0x2F98, 0, 1 | DECOMP_INLINE, 0x8C78},
+       {0x2F99, 0, 1 | DECOMP_INLINE, 0x8C9D},
+       {0x2F9A, 0, 1 | DECOMP_INLINE, 0x8D64},
+       {0x2F9B, 0, 1 | DECOMP_INLINE, 0x8D70},
+       {0x2F9C, 0, 1 | DECOMP_INLINE, 0x8DB3},
+       {0x2F9D, 0, 1 | DECOMP_INLINE, 0x8EAB},
+       {0x2F9E, 0, 1 | DECOMP_INLINE, 0x8ECA},
+       {0x2F9F, 0, 1 | DECOMP_INLINE, 0x8F9B},
+       {0x2FA0, 0, 1 | DECOMP_INLINE, 0x8FB0},
+       {0x2FA1, 0, 1 | DECOMP_INLINE, 0x8FB5},
+       {0x2FA2, 0, 1 | DECOMP_INLINE, 0x9091},
+       {0x2FA3, 0, 1 | DECOMP_INLINE, 0x9149},
+       {0x2FA4, 0, 1 | DECOMP_INLINE, 0x91C6},
+       {0x2FA5, 0, 1 | DECOMP_INLINE, 0x91CC},
+       {0x2FA6, 0, 1 | DECOMP_INLINE, 0x91D1},
+       {0x2FA7, 0, 1 | DECOMP_INLINE, 0x9577},
+       {0x2FA8, 0, 1 | DECOMP_INLINE, 0x9580},
+       {0x2FA9, 0, 1 | DECOMP_INLINE, 0x961C},
+       {0x2FAA, 0, 1 | DECOMP_INLINE, 0x96B6},
+       {0x2FAB, 0, 1 | DECOMP_INLINE, 0x96B9},
+       {0x2FAC, 0, 1 | DECOMP_INLINE, 0x96E8},
+       {0x2FAD, 0, 1 | DECOMP_INLINE, 0x9751},
+       {0x2FAE, 0, 1 | DECOMP_INLINE, 0x975E},
+       {0x2FAF, 0, 1 | DECOMP_INLINE, 0x9762},
+       {0x2FB0, 0, 1 | DECOMP_INLINE, 0x9769},
+       {0x2FB1, 0, 1 | DECOMP_INLINE, 0x97CB},
+       {0x2FB2, 0, 1 | DECOMP_INLINE, 0x97ED},
+       {0x2FB3, 0, 1 | DECOMP_INLINE, 0x97F3},
+       {0x2FB4, 0, 1 | DECOMP_INLINE, 0x9801},
+       {0x2FB5, 0, 1 | DECOMP_INLINE, 0x98A8},
+       {0x2FB6, 0, 1 | DECOMP_INLINE, 0x98DB},
+       {0x2FB7, 0, 1 | DECOMP_INLINE, 0x98DF},
+       {0x2FB8, 0, 1 | DECOMP_INLINE, 0x9996},
+       {0x2FB9, 0, 1 | DECOMP_INLINE, 0x9999},
+       {0x2FBA, 0, 1 | DECOMP_INLINE, 0x99AC},
+       {0x2FBB, 0, 1 | DECOMP_INLINE, 0x9AA8},
+       {0x2FBC, 0, 1 | DECOMP_INLINE, 0x9AD8},
+       {0x2FBD, 0, 1 | DECOMP_INLINE, 0x9ADF},
+       {0x2FBE, 0, 1 | DECOMP_INLINE, 0x9B25},
+       {0x2FBF, 0, 1 | DECOMP_INLINE, 0x9B2F},
+       {0x2FC0, 0, 1 | DECOMP_INLINE, 0x9B32},
+       {0x2FC1, 0, 1 | DECOMP_INLINE, 0x9B3C},
+       {0x2FC2, 0, 1 | DECOMP_INLINE, 0x9B5A},
+       {0x2FC3, 0, 1 | DECOMP_INLINE, 0x9CE5},
+       {0x2FC4, 0, 1 | DECOMP_INLINE, 0x9E75},
+       {0x2FC5, 0, 1 | DECOMP_INLINE, 0x9E7F},
+       {0x2FC6, 0, 1 | DECOMP_INLINE, 0x9EA5},
+       {0x2FC7, 0, 1 | DECOMP_INLINE, 0x9EBB},
+       {0x2FC8, 0, 1 | DECOMP_INLINE, 0x9EC3},
+       {0x2FC9, 0, 1 | DECOMP_INLINE, 0x9ECD},
+       {0x2FCA, 0, 1 | DECOMP_INLINE, 0x9ED1},
+       {0x2FCB, 0, 1 | DECOMP_INLINE, 0x9EF9},
+       {0x2FCC, 0, 1 | DECOMP_INLINE, 0x9EFD},
+       {0x2FCD, 0, 1 | DECOMP_INLINE, 0x9F0E},
+       {0x2FCE, 0, 1 | DECOMP_INLINE, 0x9F13},
+       {0x2FCF, 0, 1 | DECOMP_INLINE, 0x9F20},
+       {0x2FD0, 0, 1 | DECOMP_INLINE, 0x9F3B},
+       {0x2FD1, 0, 1 | DECOMP_INLINE, 0x9F4A},
+       {0x2FD2, 0, 1 | DECOMP_INLINE, 0x9F52},
+       {0x2FD3, 0, 1 | DECOMP_INLINE, 0x9F8D},
+       {0x2FD4, 0, 1 | DECOMP_INLINE, 0x9F9C},
+       {0x2FD5, 0, 1 | DECOMP_INLINE, 0x9FA0},
+       {0x3000, 0, 1 | DECOMP_INLINE, 0x0020},
+       {0x302A, 218, 0, 0},
+       {0x302B, 228, 0, 0},
+       {0x302C, 232, 0, 0},
+       {0x302D, 222, 0, 0},
+       {0x302E, 224, 0, 0},
+       {0x302F, 224, 0, 0},
+       {0x3036, 0, 1 | DECOMP_INLINE, 0x3012},
+       {0x3038, 0, 1 | DECOMP_INLINE, 0x5341},
+       {0x3039, 0, 1 | DECOMP_INLINE, 0x5344},
+       {0x303A, 0, 1 | DECOMP_INLINE, 0x5345},
+       {0x304C, 0, 2, 2317},
+       {0x304E, 0, 2, 2319},
+       {0x3050, 0, 2, 2321},
+       {0x3052, 0, 2, 2323},
+       {0x3054, 0, 2, 2325},
+       {0x3056, 0, 2, 2327},
+       {0x3058, 0, 2, 2329},
+       {0x305A, 0, 2, 2331},
+       {0x305C, 0, 2, 2333},
+       {0x305E, 0, 2, 2335},
+       {0x3060, 0, 2, 2337},
+       {0x3062, 0, 2, 2339},
+       {0x3065, 0, 2, 2341},
+       {0x3067, 0, 2, 2343},
+       {0x3069, 0, 2, 2345},
+       {0x3070, 0, 2, 2347},
+       {0x3071, 0, 2, 2349},
+       {0x3073, 0, 2, 2351},
+       {0x3074, 0, 2, 2353},
+       {0x3076, 0, 2, 2355},
+       {0x3077, 0, 2, 2357},
+       {0x3079, 0, 2, 2359},
+       {0x307A, 0, 2, 2361},
+       {0x307C, 0, 2, 2363},
+       {0x307D, 0, 2, 2365},
+       {0x3094, 0, 2, 2367},
+       {0x3099, 8, 0, 0},
+       {0x309A, 8, 0, 0},
+       {0x309B, 0, 2 | DECOMP_NO_COMPOSE, 2369},       /* compatibility mapping */
+       {0x309C, 0, 2 | DECOMP_NO_COMPOSE, 2371},       /* compatibility mapping */
+       {0x309E, 0, 2, 2373},
+       {0x309F, 0, 2 | DECOMP_NO_COMPOSE, 2375},       /* compatibility mapping */
+       {0x30AC, 0, 2, 2377},
+       {0x30AE, 0, 2, 2379},
+       {0x30B0, 0, 2, 2381},
+       {0x30B2, 0, 2, 2383},
+       {0x30B4, 0, 2, 2385},
+       {0x30B6, 0, 2, 2387},
+       {0x30B8, 0, 2, 2389},
+       {0x30BA, 0, 2, 2391},
+       {0x30BC, 0, 2, 2393},
+       {0x30BE, 0, 2, 2395},
+       {0x30C0, 0, 2, 2397},
+       {0x30C2, 0, 2, 2399},
+       {0x30C5, 0, 2, 2401},
+       {0x30C7, 0, 2, 2403},
+       {0x30C9, 0, 2, 2405},
+       {0x30D0, 0, 2, 2407},
+       {0x30D1, 0, 2, 2409},
+       {0x30D3, 0, 2, 2411},
+       {0x30D4, 0, 2, 2413},
+       {0x30D6, 0, 2, 2415},
+       {0x30D7, 0, 2, 2417},
+       {0x30D9, 0, 2, 2419},
+       {0x30DA, 0, 2, 2421},
+       {0x30DC, 0, 2, 2423},
+       {0x30DD, 0, 2, 2425},
+       {0x30F4, 0, 2, 2427},
+       {0x30F7, 0, 2, 2429},
+       {0x30F8, 0, 2, 2431},
+       {0x30F9, 0, 2, 2433},
+       {0x30FA, 0, 2, 2435},
+       {0x30FE, 0, 2, 2437},
+       {0x30FF, 0, 2 | DECOMP_NO_COMPOSE, 2439},       /* compatibility mapping */
+       {0x3131, 0, 1 | DECOMP_INLINE, 0x1100},
+       {0x3132, 0, 1 | DECOMP_INLINE, 0x1101},
+       {0x3133, 0, 1 | DECOMP_INLINE, 0x11AA},
+       {0x3134, 0, 1 | DECOMP_INLINE, 0x1102},
+       {0x3135, 0, 1 | DECOMP_INLINE, 0x11AC},
+       {0x3136, 0, 1 | DECOMP_INLINE, 0x11AD},
+       {0x3137, 0, 1 | DECOMP_INLINE, 0x1103},
+       {0x3138, 0, 1 | DECOMP_INLINE, 0x1104},
+       {0x3139, 0, 1 | DECOMP_INLINE, 0x1105},
+       {0x313A, 0, 1 | DECOMP_INLINE, 0x11B0},
+       {0x313B, 0, 1 | DECOMP_INLINE, 0x11B1},
+       {0x313C, 0, 1 | DECOMP_INLINE, 0x11B2},
+       {0x313D, 0, 1 | DECOMP_INLINE, 0x11B3},
+       {0x313E, 0, 1 | DECOMP_INLINE, 0x11B4},
+       {0x313F, 0, 1 | DECOMP_INLINE, 0x11B5},
+       {0x3140, 0, 1 | DECOMP_INLINE, 0x111A},
+       {0x3141, 0, 1 | DECOMP_INLINE, 0x1106},
+       {0x3142, 0, 1 | DECOMP_INLINE, 0x1107},
+       {0x3143, 0, 1 | DECOMP_INLINE, 0x1108},
+       {0x3144, 0, 1 | DECOMP_INLINE, 0x1121},
+       {0x3145, 0, 1 | DECOMP_INLINE, 0x1109},
+       {0x3146, 0, 1 | DECOMP_INLINE, 0x110A},
+       {0x3147, 0, 1 | DECOMP_INLINE, 0x110B},
+       {0x3148, 0, 1 | DECOMP_INLINE, 0x110C},
+       {0x3149, 0, 1 | DECOMP_INLINE, 0x110D},
+       {0x314A, 0, 1 | DECOMP_INLINE, 0x110E},
+       {0x314B, 0, 1 | DECOMP_INLINE, 0x110F},
+       {0x314C, 0, 1 | DECOMP_INLINE, 0x1110},
+       {0x314D, 0, 1 | DECOMP_INLINE, 0x1111},
+       {0x314E, 0, 1 | DECOMP_INLINE, 0x1112},
+       {0x314F, 0, 1 | DECOMP_INLINE, 0x1161},
+       {0x3150, 0, 1 | DECOMP_INLINE, 0x1162},
+       {0x3151, 0, 1 | DECOMP_INLINE, 0x1163},
+       {0x3152, 0, 1 | DECOMP_INLINE, 0x1164},
+       {0x3153, 0, 1 | DECOMP_INLINE, 0x1165},
+       {0x3154, 0, 1 | DECOMP_INLINE, 0x1166},
+       {0x3155, 0, 1 | DECOMP_INLINE, 0x1167},
+       {0x3156, 0, 1 | DECOMP_INLINE, 0x1168},
+       {0x3157, 0, 1 | DECOMP_INLINE, 0x1169},
+       {0x3158, 0, 1 | DECOMP_INLINE, 0x116A},
+       {0x3159, 0, 1 | DECOMP_INLINE, 0x116B},
+       {0x315A, 0, 1 | DECOMP_INLINE, 0x116C},
+       {0x315B, 0, 1 | DECOMP_INLINE, 0x116D},
+       {0x315C, 0, 1 | DECOMP_INLINE, 0x116E},
+       {0x315D, 0, 1 | DECOMP_INLINE, 0x116F},
+       {0x315E, 0, 1 | DECOMP_INLINE, 0x1170},
+       {0x315F, 0, 1 | DECOMP_INLINE, 0x1171},
+       {0x3160, 0, 1 | DECOMP_INLINE, 0x1172},
+       {0x3161, 0, 1 | DECOMP_INLINE, 0x1173},
+       {0x3162, 0, 1 | DECOMP_INLINE, 0x1174},
+       {0x3163, 0, 1 | DECOMP_INLINE, 0x1175},
+       {0x3164, 0, 1 | DECOMP_INLINE, 0x1160},
+       {0x3165, 0, 1 | DECOMP_INLINE, 0x1114},
+       {0x3166, 0, 1 | DECOMP_INLINE, 0x1115},
+       {0x3167, 0, 1 | DECOMP_INLINE, 0x11C7},
+       {0x3168, 0, 1 | DECOMP_INLINE, 0x11C8},
+       {0x3169, 0, 1 | DECOMP_INLINE, 0x11CC},
+       {0x316A, 0, 1 | DECOMP_INLINE, 0x11CE},
+       {0x316B, 0, 1 | DECOMP_INLINE, 0x11D3},
+       {0x316C, 0, 1 | DECOMP_INLINE, 0x11D7},
+       {0x316D, 0, 1 | DECOMP_INLINE, 0x11D9},
+       {0x316E, 0, 1 | DECOMP_INLINE, 0x111C},
+       {0x316F, 0, 1 | DECOMP_INLINE, 0x11DD},
+       {0x3170, 0, 1 | DECOMP_INLINE, 0x11DF},
+       {0x3171, 0, 1 | DECOMP_INLINE, 0x111D},
+       {0x3172, 0, 1 | DECOMP_INLINE, 0x111E},
+       {0x3173, 0, 1 | DECOMP_INLINE, 0x1120},
+       {0x3174, 0, 1 | DECOMP_INLINE, 0x1122},
+       {0x3175, 0, 1 | DECOMP_INLINE, 0x1123},
+       {0x3176, 0, 1 | DECOMP_INLINE, 0x1127},
+       {0x3177, 0, 1 | DECOMP_INLINE, 0x1129},
+       {0x3178, 0, 1 | DECOMP_INLINE, 0x112B},
+       {0x3179, 0, 1 | DECOMP_INLINE, 0x112C},
+       {0x317A, 0, 1 | DECOMP_INLINE, 0x112D},
+       {0x317B, 0, 1 | DECOMP_INLINE, 0x112E},
+       {0x317C, 0, 1 | DECOMP_INLINE, 0x112F},
+       {0x317D, 0, 1 | DECOMP_INLINE, 0x1132},
+       {0x317E, 0, 1 | DECOMP_INLINE, 0x1136},
+       {0x317F, 0, 1 | DECOMP_INLINE, 0x1140},
+       {0x3180, 0, 1 | DECOMP_INLINE, 0x1147},
+       {0x3181, 0, 1 | DECOMP_INLINE, 0x114C},
+       {0x3182, 0, 1 | DECOMP_INLINE, 0x11F1},
+       {0x3183, 0, 1 | DECOMP_INLINE, 0x11F2},
+       {0x3184, 0, 1 | DECOMP_INLINE, 0x1157},
+       {0x3185, 0, 1 | DECOMP_INLINE, 0x1158},
+       {0x3186, 0, 1 | DECOMP_INLINE, 0x1159},
+       {0x3187, 0, 1 | DECOMP_INLINE, 0x1184},
+       {0x3188, 0, 1 | DECOMP_INLINE, 0x1185},
+       {0x3189, 0, 1 | DECOMP_INLINE, 0x1188},
+       {0x318A, 0, 1 | DECOMP_INLINE, 0x1191},
+       {0x318B, 0, 1 | DECOMP_INLINE, 0x1192},
+       {0x318C, 0, 1 | DECOMP_INLINE, 0x1194},
+       {0x318D, 0, 1 | DECOMP_INLINE, 0x119E},
+       {0x318E, 0, 1 | DECOMP_INLINE, 0x11A1},
+       {0x3192, 0, 1 | DECOMP_INLINE, 0x4E00},
+       {0x3193, 0, 1 | DECOMP_INLINE, 0x4E8C},
+       {0x3194, 0, 1 | DECOMP_INLINE, 0x4E09},
+       {0x3195, 0, 1 | DECOMP_INLINE, 0x56DB},
+       {0x3196, 0, 1 | DECOMP_INLINE, 0x4E0A},
+       {0x3197, 0, 1 | DECOMP_INLINE, 0x4E2D},
+       {0x3198, 0, 1 | DECOMP_INLINE, 0x4E0B},
+       {0x3199, 0, 1 | DECOMP_INLINE, 0x7532},
+       {0x319A, 0, 1 | DECOMP_INLINE, 0x4E59},
+       {0x319B, 0, 1 | DECOMP_INLINE, 0x4E19},
+       {0x319C, 0, 1 | DECOMP_INLINE, 0x4E01},
+       {0x319D, 0, 1 | DECOMP_INLINE, 0x5929},
+       {0x319E, 0, 1 | DECOMP_INLINE, 0x5730},
+       {0x319F, 0, 1 | DECOMP_INLINE, 0x4EBA},
+       {0x3200, 0, 3, 2441},
+       {0x3201, 0, 3, 2444},
+       {0x3202, 0, 3, 2447},
+       {0x3203, 0, 3, 2450},
+       {0x3204, 0, 3, 2453},
+       {0x3205, 0, 3, 2456},
+       {0x3206, 0, 3, 2459},
+       {0x3207, 0, 3, 2462},
+       {0x3208, 0, 3, 2465},
+       {0x3209, 0, 3, 2468},
+       {0x320A, 0, 3, 2471},
+       {0x320B, 0, 3, 2474},
+       {0x320C, 0, 3, 2477},
+       {0x320D, 0, 3, 2480},
+       {0x320E, 0, 4, 2483},
+       {0x320F, 0, 4, 2487},
+       {0x3210, 0, 4, 2491},
+       {0x3211, 0, 4, 2495},
+       {0x3212, 0, 4, 2499},
+       {0x3213, 0, 4, 2503},
+       {0x3214, 0, 4, 2507},
+       {0x3215, 0, 4, 2511},
+       {0x3216, 0, 4, 2515},
+       {0x3217, 0, 4, 2519},
+       {0x3218, 0, 4, 2523},
+       {0x3219, 0, 4, 2527},
+       {0x321A, 0, 4, 2531},
+       {0x321B, 0, 4, 2535},
+       {0x321C, 0, 4, 2539},
+       {0x321D, 0, 7, 2543},
+       {0x321E, 0, 6, 2550},
+       {0x3220, 0, 3, 2556},
+       {0x3221, 0, 3, 2559},
+       {0x3222, 0, 3, 2562},
+       {0x3223, 0, 3, 2565},
+       {0x3224, 0, 3, 2568},
+       {0x3225, 0, 3, 2571},
+       {0x3226, 0, 3, 2574},
+       {0x3227, 0, 3, 2577},
+       {0x3228, 0, 3, 2580},
+       {0x3229, 0, 3, 2583},
+       {0x322A, 0, 3, 2586},
+       {0x322B, 0, 3, 2589},
+       {0x322C, 0, 3, 2592},
+       {0x322D, 0, 3, 2595},
+       {0x322E, 0, 3, 2598},
+       {0x322F, 0, 3, 2601},
+       {0x3230, 0, 3, 2604},
+       {0x3231, 0, 3, 2607},
+       {0x3232, 0, 3, 2610},
+       {0x3233, 0, 3, 2613},
+       {0x3234, 0, 3, 2616},
+       {0x3235, 0, 3, 2619},
+       {0x3236, 0, 3, 2622},
+       {0x3237, 0, 3, 2625},
+       {0x3238, 0, 3, 2628},
+       {0x3239, 0, 3, 2631},
+       {0x323A, 0, 3, 2634},
+       {0x323B, 0, 3, 2637},
+       {0x323C, 0, 3, 2640},
+       {0x323D, 0, 3, 2643},
+       {0x323E, 0, 3, 2646},
+       {0x323F, 0, 3, 2649},
+       {0x3240, 0, 3, 2652},
+       {0x3241, 0, 3, 2655},
+       {0x3242, 0, 3, 2658},
+       {0x3243, 0, 3, 2661},
+       {0x3244, 0, 1 | DECOMP_INLINE, 0x554F},
+       {0x3245, 0, 1 | DECOMP_INLINE, 0x5E7C},
+       {0x3246, 0, 1 | DECOMP_INLINE, 0x6587},
+       {0x3247, 0, 1 | DECOMP_INLINE, 0x7B8F},
+       {0x3250, 0, 3, 2664},
+       {0x3251, 0, 2 | DECOMP_NO_COMPOSE, 2667},       /* compatibility mapping */
+       {0x3252, 0, 2 | DECOMP_NO_COMPOSE, 2669},       /* compatibility mapping */
+       {0x3253, 0, 2 | DECOMP_NO_COMPOSE, 2671},       /* compatibility mapping */
+       {0x3254, 0, 2 | DECOMP_NO_COMPOSE, 2673},       /* compatibility mapping */
+       {0x3255, 0, 2 | DECOMP_NO_COMPOSE, 2675},       /* compatibility mapping */
+       {0x3256, 0, 2 | DECOMP_NO_COMPOSE, 2677},       /* compatibility mapping */
+       {0x3257, 0, 2 | DECOMP_NO_COMPOSE, 2679},       /* compatibility mapping */
+       {0x3258, 0, 2 | DECOMP_NO_COMPOSE, 2681},       /* compatibility mapping */
+       {0x3259, 0, 2 | DECOMP_NO_COMPOSE, 2683},       /* compatibility mapping */
+       {0x325A, 0, 2 | DECOMP_NO_COMPOSE, 2685},       /* compatibility mapping */
+       {0x325B, 0, 2 | DECOMP_NO_COMPOSE, 2687},       /* compatibility mapping */
+       {0x325C, 0, 2 | DECOMP_NO_COMPOSE, 2689},       /* compatibility mapping */
+       {0x325D, 0, 2 | DECOMP_NO_COMPOSE, 2691},       /* compatibility mapping */
+       {0x325E, 0, 2 | DECOMP_NO_COMPOSE, 2693},       /* compatibility mapping */
+       {0x325F, 0, 2 | DECOMP_NO_COMPOSE, 2695},       /* compatibility mapping */
+       {0x3260, 0, 1 | DECOMP_INLINE, 0x1100},
+       {0x3261, 0, 1 | DECOMP_INLINE, 0x1102},
+       {0x3262, 0, 1 | DECOMP_INLINE, 0x1103},
+       {0x3263, 0, 1 | DECOMP_INLINE, 0x1105},
+       {0x3264, 0, 1 | DECOMP_INLINE, 0x1106},
+       {0x3265, 0, 1 | DECOMP_INLINE, 0x1107},
+       {0x3266, 0, 1 | DECOMP_INLINE, 0x1109},
+       {0x3267, 0, 1 | DECOMP_INLINE, 0x110B},
+       {0x3268, 0, 1 | DECOMP_INLINE, 0x110C},
+       {0x3269, 0, 1 | DECOMP_INLINE, 0x110E},
+       {0x326A, 0, 1 | DECOMP_INLINE, 0x110F},
+       {0x326B, 0, 1 | DECOMP_INLINE, 0x1110},
+       {0x326C, 0, 1 | DECOMP_INLINE, 0x1111},
+       {0x326D, 0, 1 | DECOMP_INLINE, 0x1112},
+       {0x326E, 0, 2 | DECOMP_NO_COMPOSE, 2697},       /* compatibility mapping */
+       {0x326F, 0, 2 | DECOMP_NO_COMPOSE, 2699},       /* compatibility mapping */
+       {0x3270, 0, 2 | DECOMP_NO_COMPOSE, 2701},       /* compatibility mapping */
+       {0x3271, 0, 2 | DECOMP_NO_COMPOSE, 2703},       /* compatibility mapping */
+       {0x3272, 0, 2 | DECOMP_NO_COMPOSE, 2705},       /* compatibility mapping */
+       {0x3273, 0, 2 | DECOMP_NO_COMPOSE, 2707},       /* compatibility mapping */
+       {0x3274, 0, 2 | DECOMP_NO_COMPOSE, 2709},       /* compatibility mapping */
+       {0x3275, 0, 2 | DECOMP_NO_COMPOSE, 2711},       /* compatibility mapping */
+       {0x3276, 0, 2 | DECOMP_NO_COMPOSE, 2713},       /* compatibility mapping */
+       {0x3277, 0, 2 | DECOMP_NO_COMPOSE, 2715},       /* compatibility mapping */
+       {0x3278, 0, 2 | DECOMP_NO_COMPOSE, 2717},       /* compatibility mapping */
+       {0x3279, 0, 2 | DECOMP_NO_COMPOSE, 2719},       /* compatibility mapping */
+       {0x327A, 0, 2 | DECOMP_NO_COMPOSE, 2721},       /* compatibility mapping */
+       {0x327B, 0, 2 | DECOMP_NO_COMPOSE, 2723},       /* compatibility mapping */
+       {0x327C, 0, 5, 2725},
+       {0x327D, 0, 4, 2730},
+       {0x327E, 0, 2 | DECOMP_NO_COMPOSE, 2734},       /* compatibility mapping */
+       {0x3280, 0, 1 | DECOMP_INLINE, 0x4E00},
+       {0x3281, 0, 1 | DECOMP_INLINE, 0x4E8C},
+       {0x3282, 0, 1 | DECOMP_INLINE, 0x4E09},
+       {0x3283, 0, 1 | DECOMP_INLINE, 0x56DB},
+       {0x3284, 0, 1 | DECOMP_INLINE, 0x4E94},
+       {0x3285, 0, 1 | DECOMP_INLINE, 0x516D},
+       {0x3286, 0, 1 | DECOMP_INLINE, 0x4E03},
+       {0x3287, 0, 1 | DECOMP_INLINE, 0x516B},
+       {0x3288, 0, 1 | DECOMP_INLINE, 0x4E5D},
+       {0x3289, 0, 1 | DECOMP_INLINE, 0x5341},
+       {0x328A, 0, 1 | DECOMP_INLINE, 0x6708},
+       {0x328B, 0, 1 | DECOMP_INLINE, 0x706B},
+       {0x328C, 0, 1 | DECOMP_INLINE, 0x6C34},
+       {0x328D, 0, 1 | DECOMP_INLINE, 0x6728},
+       {0x328E, 0, 1 | DECOMP_INLINE, 0x91D1},
+       {0x328F, 0, 1 | DECOMP_INLINE, 0x571F},
+       {0x3290, 0, 1 | DECOMP_INLINE, 0x65E5},
+       {0x3291, 0, 1 | DECOMP_INLINE, 0x682A},
+       {0x3292, 0, 1 | DECOMP_INLINE, 0x6709},
+       {0x3293, 0, 1 | DECOMP_INLINE, 0x793E},
+       {0x3294, 0, 1 | DECOMP_INLINE, 0x540D},
+       {0x3295, 0, 1 | DECOMP_INLINE, 0x7279},
+       {0x3296, 0, 1 | DECOMP_INLINE, 0x8CA1},
+       {0x3297, 0, 1 | DECOMP_INLINE, 0x795D},
+       {0x3298, 0, 1 | DECOMP_INLINE, 0x52B4},
+       {0x3299, 0, 1 | DECOMP_INLINE, 0x79D8},
+       {0x329A, 0, 1 | DECOMP_INLINE, 0x7537},
+       {0x329B, 0, 1 | DECOMP_INLINE, 0x5973},
+       {0x329C, 0, 1 | DECOMP_INLINE, 0x9069},
+       {0x329D, 0, 1 | DECOMP_INLINE, 0x512A},
+       {0x329E, 0, 1 | DECOMP_INLINE, 0x5370},
+       {0x329F, 0, 1 | DECOMP_INLINE, 0x6CE8},
+       {0x32A0, 0, 1 | DECOMP_INLINE, 0x9805},
+       {0x32A1, 0, 1 | DECOMP_INLINE, 0x4F11},
+       {0x32A2, 0, 1 | DECOMP_INLINE, 0x5199},
+       {0x32A3, 0, 1 | DECOMP_INLINE, 0x6B63},
+       {0x32A4, 0, 1 | DECOMP_INLINE, 0x4E0A},
+       {0x32A5, 0, 1 | DECOMP_INLINE, 0x4E2D},
+       {0x32A6, 0, 1 | DECOMP_INLINE, 0x4E0B},
+       {0x32A7, 0, 1 | DECOMP_INLINE, 0x5DE6},
+       {0x32A8, 0, 1 | DECOMP_INLINE, 0x53F3},
+       {0x32A9, 0, 1 | DECOMP_INLINE, 0x533B},
+       {0x32AA, 0, 1 | DECOMP_INLINE, 0x5B97},
+       {0x32AB, 0, 1 | DECOMP_INLINE, 0x5B66},
+       {0x32AC, 0, 1 | DECOMP_INLINE, 0x76E3},
+       {0x32AD, 0, 1 | DECOMP_INLINE, 0x4F01},
+       {0x32AE, 0, 1 | DECOMP_INLINE, 0x8CC7},
+       {0x32AF, 0, 1 | DECOMP_INLINE, 0x5354},
+       {0x32B0, 0, 1 | DECOMP_INLINE, 0x591C},
+       {0x32B1, 0, 2 | DECOMP_NO_COMPOSE, 2736},       /* compatibility mapping */
+       {0x32B2, 0, 2 | DECOMP_NO_COMPOSE, 2738},       /* compatibility mapping */
+       {0x32B3, 0, 2 | DECOMP_NO_COMPOSE, 2740},       /* compatibility mapping */
+       {0x32B4, 0, 2 | DECOMP_NO_COMPOSE, 2742},       /* compatibility mapping */
+       {0x32B5, 0, 2 | DECOMP_NO_COMPOSE, 2744},       /* compatibility mapping */
+       {0x32B6, 0, 2 | DECOMP_NO_COMPOSE, 2746},       /* compatibility mapping */
+       {0x32B7, 0, 2 | DECOMP_NO_COMPOSE, 2748},       /* compatibility mapping */
+       {0x32B8, 0, 2 | DECOMP_NO_COMPOSE, 2750},       /* compatibility mapping */
+       {0x32B9, 0, 2 | DECOMP_NO_COMPOSE, 2752},       /* compatibility mapping */
+       {0x32BA, 0, 2 | DECOMP_NO_COMPOSE, 2754},       /* compatibility mapping */
+       {0x32BB, 0, 2 | DECOMP_NO_COMPOSE, 2756},       /* compatibility mapping */
+       {0x32BC, 0, 2 | DECOMP_NO_COMPOSE, 2758},       /* compatibility mapping */
+       {0x32BD, 0, 2 | DECOMP_NO_COMPOSE, 2760},       /* compatibility mapping */
+       {0x32BE, 0, 2 | DECOMP_NO_COMPOSE, 2762},       /* compatibility mapping */
+       {0x32BF, 0, 2 | DECOMP_NO_COMPOSE, 2764},       /* compatibility mapping */
+       {0x32C0, 0, 2 | DECOMP_NO_COMPOSE, 2766},       /* compatibility mapping */
+       {0x32C1, 0, 2 | DECOMP_NO_COMPOSE, 2768},       /* compatibility mapping */
+       {0x32C2, 0, 2 | DECOMP_NO_COMPOSE, 2770},       /* compatibility mapping */
+       {0x32C3, 0, 2 | DECOMP_NO_COMPOSE, 2772},       /* compatibility mapping */
+       {0x32C4, 0, 2 | DECOMP_NO_COMPOSE, 2774},       /* compatibility mapping */
+       {0x32C5, 0, 2 | DECOMP_NO_COMPOSE, 2776},       /* compatibility mapping */
+       {0x32C6, 0, 2 | DECOMP_NO_COMPOSE, 2778},       /* compatibility mapping */
+       {0x32C7, 0, 2 | DECOMP_NO_COMPOSE, 2780},       /* compatibility mapping */
+       {0x32C8, 0, 2 | DECOMP_NO_COMPOSE, 2782},       /* compatibility mapping */
+       {0x32C9, 0, 3, 2784},
+       {0x32CA, 0, 3, 2787},
+       {0x32CB, 0, 3, 2790},
+       {0x32CC, 0, 2 | DECOMP_NO_COMPOSE, 2793},       /* compatibility mapping */
+       {0x32CD, 0, 3, 2795},
+       {0x32CE, 0, 2 | DECOMP_NO_COMPOSE, 2798},       /* compatibility mapping */
+       {0x32CF, 0, 3, 2800},
+       {0x32D0, 0, 1 | DECOMP_INLINE, 0x30A2},
+       {0x32D1, 0, 1 | DECOMP_INLINE, 0x30A4},
+       {0x32D2, 0, 1 | DECOMP_INLINE, 0x30A6},
+       {0x32D3, 0, 1 | DECOMP_INLINE, 0x30A8},
+       {0x32D4, 0, 1 | DECOMP_INLINE, 0x30AA},
+       {0x32D5, 0, 1 | DECOMP_INLINE, 0x30AB},
+       {0x32D6, 0, 1 | DECOMP_INLINE, 0x30AD},
+       {0x32D7, 0, 1 | DECOMP_INLINE, 0x30AF},
+       {0x32D8, 0, 1 | DECOMP_INLINE, 0x30B1},
+       {0x32D9, 0, 1 | DECOMP_INLINE, 0x30B3},
+       {0x32DA, 0, 1 | DECOMP_INLINE, 0x30B5},
+       {0x32DB, 0, 1 | DECOMP_INLINE, 0x30B7},
+       {0x32DC, 0, 1 | DECOMP_INLINE, 0x30B9},
+       {0x32DD, 0, 1 | DECOMP_INLINE, 0x30BB},
+       {0x32DE, 0, 1 | DECOMP_INLINE, 0x30BD},
+       {0x32DF, 0, 1 | DECOMP_INLINE, 0x30BF},
+       {0x32E0, 0, 1 | DECOMP_INLINE, 0x30C1},
+       {0x32E1, 0, 1 | DECOMP_INLINE, 0x30C4},
+       {0x32E2, 0, 1 | DECOMP_INLINE, 0x30C6},
+       {0x32E3, 0, 1 | DECOMP_INLINE, 0x30C8},
+       {0x32E4, 0, 1 | DECOMP_INLINE, 0x30CA},
+       {0x32E5, 0, 1 | DECOMP_INLINE, 0x30CB},
+       {0x32E6, 0, 1 | DECOMP_INLINE, 0x30CC},
+       {0x32E7, 0, 1 | DECOMP_INLINE, 0x30CD},
+       {0x32E8, 0, 1 | DECOMP_INLINE, 0x30CE},
+       {0x32E9, 0, 1 | DECOMP_INLINE, 0x30CF},
+       {0x32EA, 0, 1 | DECOMP_INLINE, 0x30D2},
+       {0x32EB, 0, 1 | DECOMP_INLINE, 0x30D5},
+       {0x32EC, 0, 1 | DECOMP_INLINE, 0x30D8},
+       {0x32ED, 0, 1 | DECOMP_INLINE, 0x30DB},
+       {0x32EE, 0, 1 | DECOMP_INLINE, 0x30DE},
+       {0x32EF, 0, 1 | DECOMP_INLINE, 0x30DF},
+       {0x32F0, 0, 1 | DECOMP_INLINE, 0x30E0},
+       {0x32F1, 0, 1 | DECOMP_INLINE, 0x30E1},
+       {0x32F2, 0, 1 | DECOMP_INLINE, 0x30E2},
+       {0x32F3, 0, 1 | DECOMP_INLINE, 0x30E4},
+       {0x32F4, 0, 1 | DECOMP_INLINE, 0x30E6},
+       {0x32F5, 0, 1 | DECOMP_INLINE, 0x30E8},
+       {0x32F6, 0, 1 | DECOMP_INLINE, 0x30E9},
+       {0x32F7, 0, 1 | DECOMP_INLINE, 0x30EA},
+       {0x32F8, 0, 1 | DECOMP_INLINE, 0x30EB},
+       {0x32F9, 0, 1 | DECOMP_INLINE, 0x30EC},
+       {0x32FA, 0, 1 | DECOMP_INLINE, 0x30ED},
+       {0x32FB, 0, 1 | DECOMP_INLINE, 0x30EF},
+       {0x32FC, 0, 1 | DECOMP_INLINE, 0x30F0},
+       {0x32FD, 0, 1 | DECOMP_INLINE, 0x30F1},
+       {0x32FE, 0, 1 | DECOMP_INLINE, 0x30F2},
+       {0x3300, 0, 4, 2803},
+       {0x3301, 0, 4, 2807},
+       {0x3302, 0, 4, 2811},
+       {0x3303, 0, 3, 2815},
+       {0x3304, 0, 4, 2818},
+       {0x3305, 0, 3, 2822},
+       {0x3306, 0, 3, 2825},
+       {0x3307, 0, 5, 2828},
+       {0x3308, 0, 4, 2833},
+       {0x3309, 0, 3, 2837},
+       {0x330A, 0, 3, 2840},
+       {0x330B, 0, 3, 2843},
+       {0x330C, 0, 4, 2846},
+       {0x330D, 0, 4, 2850},
+       {0x330E, 0, 3, 2854},
+       {0x330F, 0, 3, 2857},
+       {0x3310, 0, 2 | DECOMP_NO_COMPOSE, 2860},       /* compatibility mapping */
+       {0x3311, 0, 3, 2862},
+       {0x3312, 0, 4, 2865},
+       {0x3313, 0, 4, 2869},
+       {0x3314, 0, 2 | DECOMP_NO_COMPOSE, 2873},       /* compatibility mapping */
+       {0x3315, 0, 5, 2875},
+       {0x3316, 0, 6, 2880},
+       {0x3317, 0, 5, 2886},
+       {0x3318, 0, 3, 2891},
+       {0x3319, 0, 5, 2894},
+       {0x331A, 0, 5, 2899},
+       {0x331B, 0, 4, 2904},
+       {0x331C, 0, 3, 2908},
+       {0x331D, 0, 3, 2911},
+       {0x331E, 0, 3, 2914},
+       {0x331F, 0, 4, 2917},
+       {0x3320, 0, 5, 2921},
+       {0x3321, 0, 4, 2926},
+       {0x3322, 0, 3, 2930},
+       {0x3323, 0, 3, 2933},
+       {0x3324, 0, 3, 2936},
+       {0x3325, 0, 2 | DECOMP_NO_COMPOSE, 2939},       /* compatibility mapping */
+       {0x3326, 0, 2 | DECOMP_NO_COMPOSE, 2941},       /* compatibility mapping */
+       {0x3327, 0, 2 | DECOMP_NO_COMPOSE, 2943},       /* compatibility mapping */
+       {0x3328, 0, 2 | DECOMP_NO_COMPOSE, 2945},       /* compatibility mapping */
+       {0x3329, 0, 3, 2947},
+       {0x332A, 0, 3, 2950},
+       {0x332B, 0, 5, 2953},
+       {0x332C, 0, 3, 2958},
+       {0x332D, 0, 4, 2961},
+       {0x332E, 0, 5, 2965},
+       {0x332F, 0, 3, 2970},
+       {0x3330, 0, 2 | DECOMP_NO_COMPOSE, 2973},       /* compatibility mapping */
+       {0x3331, 0, 2 | DECOMP_NO_COMPOSE, 2975},       /* compatibility mapping */
+       {0x3332, 0, 5, 2977},
+       {0x3333, 0, 4, 2982},
+       {0x3334, 0, 5, 2986},
+       {0x3335, 0, 3, 2991},
+       {0x3336, 0, 5, 2994},
+       {0x3337, 0, 2 | DECOMP_NO_COMPOSE, 2999},       /* compatibility mapping */
+       {0x3338, 0, 3, 3001},
+       {0x3339, 0, 3, 3004},
+       {0x333A, 0, 3, 3007},
+       {0x333B, 0, 3, 3010},
+       {0x333C, 0, 3, 3013},
+       {0x333D, 0, 4, 3016},
+       {0x333E, 0, 3, 3020},
+       {0x333F, 0, 2 | DECOMP_NO_COMPOSE, 3023},       /* compatibility mapping */
+       {0x3340, 0, 3, 3025},
+       {0x3341, 0, 3, 3028},
+       {0x3342, 0, 3, 3031},
+       {0x3343, 0, 4, 3034},
+       {0x3344, 0, 3, 3038},
+       {0x3345, 0, 3, 3041},
+       {0x3346, 0, 3, 3044},
+       {0x3347, 0, 5, 3047},
+       {0x3348, 0, 4, 3052},
+       {0x3349, 0, 2 | DECOMP_NO_COMPOSE, 3056},       /* compatibility mapping */
+       {0x334A, 0, 5, 3058},
+       {0x334B, 0, 2 | DECOMP_NO_COMPOSE, 3063},       /* compatibility mapping */
+       {0x334C, 0, 4, 3065},
+       {0x334D, 0, 4, 3069},
+       {0x334E, 0, 3, 3073},
+       {0x334F, 0, 3, 3076},
+       {0x3350, 0, 3, 3079},
+       {0x3351, 0, 4, 3082},
+       {0x3352, 0, 2 | DECOMP_NO_COMPOSE, 3086},       /* compatibility mapping */
+       {0x3353, 0, 3, 3088},
+       {0x3354, 0, 4, 3091},
+       {0x3355, 0, 2 | DECOMP_NO_COMPOSE, 3095},       /* compatibility mapping */
+       {0x3356, 0, 5, 3097},
+       {0x3357, 0, 3, 3102},
+       {0x3358, 0, 2 | DECOMP_NO_COMPOSE, 3105},       /* compatibility mapping */
+       {0x3359, 0, 2 | DECOMP_NO_COMPOSE, 3107},       /* compatibility mapping */
+       {0x335A, 0, 2 | DECOMP_NO_COMPOSE, 3109},       /* compatibility mapping */
+       {0x335B, 0, 2 | DECOMP_NO_COMPOSE, 3111},       /* compatibility mapping */
+       {0x335C, 0, 2 | DECOMP_NO_COMPOSE, 3113},       /* compatibility mapping */
+       {0x335D, 0, 2 | DECOMP_NO_COMPOSE, 3115},       /* compatibility mapping */
+       {0x335E, 0, 2 | DECOMP_NO_COMPOSE, 3117},       /* compatibility mapping */
+       {0x335F, 0, 2 | DECOMP_NO_COMPOSE, 3119},       /* compatibility mapping */
+       {0x3360, 0, 2 | DECOMP_NO_COMPOSE, 3121},       /* compatibility mapping */
+       {0x3361, 0, 2 | DECOMP_NO_COMPOSE, 3123},       /* compatibility mapping */
+       {0x3362, 0, 3, 3125},
+       {0x3363, 0, 3, 3128},
+       {0x3364, 0, 3, 3131},
+       {0x3365, 0, 3, 3134},
+       {0x3366, 0, 3, 3137},
+       {0x3367, 0, 3, 3140},
+       {0x3368, 0, 3, 3143},
+       {0x3369, 0, 3, 3146},
+       {0x336A, 0, 3, 3149},
+       {0x336B, 0, 3, 3152},
+       {0x336C, 0, 3, 3155},
+       {0x336D, 0, 3, 3158},
+       {0x336E, 0, 3, 3161},
+       {0x336F, 0, 3, 3164},
+       {0x3370, 0, 3, 3167},
+       {0x3371, 0, 3, 3170},
+       {0x3372, 0, 2 | DECOMP_NO_COMPOSE, 3173},       /* compatibility mapping */
+       {0x3373, 0, 2 | DECOMP_NO_COMPOSE, 3175},       /* compatibility mapping */
+       {0x3374, 0, 3, 3177},
+       {0x3375, 0, 2 | DECOMP_NO_COMPOSE, 3180},       /* compatibility mapping */
+       {0x3376, 0, 2 | DECOMP_NO_COMPOSE, 3182},       /* compatibility mapping */
+       {0x3377, 0, 2 | DECOMP_NO_COMPOSE, 3184},       /* compatibility mapping */
+       {0x3378, 0, 3, 3186},
+       {0x3379, 0, 3, 3189},
+       {0x337A, 0, 2 | DECOMP_NO_COMPOSE, 3192},       /* compatibility mapping */
+       {0x337B, 0, 2 | DECOMP_NO_COMPOSE, 3194},       /* compatibility mapping */
+       {0x337C, 0, 2 | DECOMP_NO_COMPOSE, 3196},       /* compatibility mapping */
+       {0x337D, 0, 2 | DECOMP_NO_COMPOSE, 3198},       /* compatibility mapping */
+       {0x337E, 0, 2 | DECOMP_NO_COMPOSE, 3200},       /* compatibility mapping */
+       {0x337F, 0, 4, 3202},
+       {0x3380, 0, 2 | DECOMP_NO_COMPOSE, 3206},       /* compatibility mapping */
+       {0x3381, 0, 2 | DECOMP_NO_COMPOSE, 3208},       /* compatibility mapping */
+       {0x3382, 0, 2 | DECOMP_NO_COMPOSE, 3210},       /* compatibility mapping */
+       {0x3383, 0, 2 | DECOMP_NO_COMPOSE, 3212},       /* compatibility mapping */
+       {0x3384, 0, 2 | DECOMP_NO_COMPOSE, 3214},       /* compatibility mapping */
+       {0x3385, 0, 2 | DECOMP_NO_COMPOSE, 3216},       /* compatibility mapping */
+       {0x3386, 0, 2 | DECOMP_NO_COMPOSE, 3218},       /* compatibility mapping */
+       {0x3387, 0, 2 | DECOMP_NO_COMPOSE, 3220},       /* compatibility mapping */
+       {0x3388, 0, 3, 3222},
+       {0x3389, 0, 4, 3225},
+       {0x338A, 0, 2 | DECOMP_NO_COMPOSE, 3229},       /* compatibility mapping */
+       {0x338B, 0, 2 | DECOMP_NO_COMPOSE, 3231},       /* compatibility mapping */
+       {0x338C, 0, 2 | DECOMP_NO_COMPOSE, 3233},       /* compatibility mapping */
+       {0x338D, 0, 2 | DECOMP_NO_COMPOSE, 3235},       /* compatibility mapping */
+       {0x338E, 0, 2 | DECOMP_NO_COMPOSE, 3237},       /* compatibility mapping */
+       {0x338F, 0, 2 | DECOMP_NO_COMPOSE, 3239},       /* compatibility mapping */
+       {0x3390, 0, 2 | DECOMP_NO_COMPOSE, 3241},       /* compatibility mapping */
+       {0x3391, 0, 3, 3243},
+       {0x3392, 0, 3, 3246},
+       {0x3393, 0, 3, 3249},
+       {0x3394, 0, 3, 3252},
+       {0x3395, 0, 2 | DECOMP_NO_COMPOSE, 3255},       /* compatibility mapping */
+       {0x3396, 0, 2 | DECOMP_NO_COMPOSE, 3257},       /* compatibility mapping */
+       {0x3397, 0, 2 | DECOMP_NO_COMPOSE, 3259},       /* compatibility mapping */
+       {0x3398, 0, 2 | DECOMP_NO_COMPOSE, 3261},       /* compatibility mapping */
+       {0x3399, 0, 2 | DECOMP_NO_COMPOSE, 3263},       /* compatibility mapping */
+       {0x339A, 0, 2 | DECOMP_NO_COMPOSE, 3265},       /* compatibility mapping */
+       {0x339B, 0, 2 | DECOMP_NO_COMPOSE, 3267},       /* compatibility mapping */
+       {0x339C, 0, 2 | DECOMP_NO_COMPOSE, 3269},       /* compatibility mapping */
+       {0x339D, 0, 2 | DECOMP_NO_COMPOSE, 3271},       /* compatibility mapping */
+       {0x339E, 0, 2 | DECOMP_NO_COMPOSE, 3273},       /* compatibility mapping */
+       {0x339F, 0, 3, 3275},
+       {0x33A0, 0, 3, 3278},
+       {0x33A1, 0, 2 | DECOMP_NO_COMPOSE, 3281},       /* compatibility mapping */
+       {0x33A2, 0, 3, 3283},
+       {0x33A3, 0, 3, 3286},
+       {0x33A4, 0, 3, 3289},
+       {0x33A5, 0, 2 | DECOMP_NO_COMPOSE, 3292},       /* compatibility mapping */
+       {0x33A6, 0, 3, 3294},
+       {0x33A7, 0, 3, 3297},
+       {0x33A8, 0, 4, 3300},
+       {0x33A9, 0, 2 | DECOMP_NO_COMPOSE, 3304},       /* compatibility mapping */
+       {0x33AA, 0, 3, 3306},
+       {0x33AB, 0, 3, 3309},
+       {0x33AC, 0, 3, 3312},
+       {0x33AD, 0, 3, 3315},
+       {0x33AE, 0, 5, 3318},
+       {0x33AF, 0, 6, 3323},
+       {0x33B0, 0, 2 | DECOMP_NO_COMPOSE, 3329},       /* compatibility mapping */
+       {0x33B1, 0, 2 | DECOMP_NO_COMPOSE, 3331},       /* compatibility mapping */
+       {0x33B2, 0, 2 | DECOMP_NO_COMPOSE, 3333},       /* compatibility mapping */
+       {0x33B3, 0, 2 | DECOMP_NO_COMPOSE, 3335},       /* compatibility mapping */
+       {0x33B4, 0, 2 | DECOMP_NO_COMPOSE, 3337},       /* compatibility mapping */
+       {0x33B5, 0, 2 | DECOMP_NO_COMPOSE, 3339},       /* compatibility mapping */
+       {0x33B6, 0, 2 | DECOMP_NO_COMPOSE, 3341},       /* compatibility mapping */
+       {0x33B7, 0, 2 | DECOMP_NO_COMPOSE, 3343},       /* compatibility mapping */
+       {0x33B8, 0, 2 | DECOMP_NO_COMPOSE, 3345},       /* compatibility mapping */
+       {0x33B9, 0, 2 | DECOMP_NO_COMPOSE, 3347},       /* compatibility mapping */
+       {0x33BA, 0, 2 | DECOMP_NO_COMPOSE, 3349},       /* compatibility mapping */
+       {0x33BB, 0, 2 | DECOMP_NO_COMPOSE, 3351},       /* compatibility mapping */
+       {0x33BC, 0, 2 | DECOMP_NO_COMPOSE, 3353},       /* compatibility mapping */
+       {0x33BD, 0, 2 | DECOMP_NO_COMPOSE, 3355},       /* compatibility mapping */
+       {0x33BE, 0, 2 | DECOMP_NO_COMPOSE, 3357},       /* compatibility mapping */
+       {0x33BF, 0, 2 | DECOMP_NO_COMPOSE, 3359},       /* compatibility mapping */
+       {0x33C0, 0, 2 | DECOMP_NO_COMPOSE, 3361},       /* compatibility mapping */
+       {0x33C1, 0, 2 | DECOMP_NO_COMPOSE, 3363},       /* compatibility mapping */
+       {0x33C2, 0, 4, 3365},
+       {0x33C3, 0, 2 | DECOMP_NO_COMPOSE, 3369},       /* compatibility mapping */
+       {0x33C4, 0, 2 | DECOMP_NO_COMPOSE, 3371},       /* compatibility mapping */
+       {0x33C5, 0, 2 | DECOMP_NO_COMPOSE, 3373},       /* compatibility mapping */
+       {0x33C6, 0, 4, 3375},
+       {0x33C7, 0, 3, 3379},
+       {0x33C8, 0, 2 | DECOMP_NO_COMPOSE, 3382},       /* compatibility mapping */
+       {0x33C9, 0, 2 | DECOMP_NO_COMPOSE, 3384},       /* compatibility mapping */
+       {0x33CA, 0, 2 | DECOMP_NO_COMPOSE, 3386},       /* compatibility mapping */
+       {0x33CB, 0, 2 | DECOMP_NO_COMPOSE, 3388},       /* compatibility mapping */
+       {0x33CC, 0, 2 | DECOMP_NO_COMPOSE, 3390},       /* compatibility mapping */
+       {0x33CD, 0, 2 | DECOMP_NO_COMPOSE, 3392},       /* compatibility mapping */
+       {0x33CE, 0, 2 | DECOMP_NO_COMPOSE, 3394},       /* compatibility mapping */
+       {0x33CF, 0, 2 | DECOMP_NO_COMPOSE, 3396},       /* compatibility mapping */
+       {0x33D0, 0, 2 | DECOMP_NO_COMPOSE, 3398},       /* compatibility mapping */
+       {0x33D1, 0, 2 | DECOMP_NO_COMPOSE, 3400},       /* compatibility mapping */
+       {0x33D2, 0, 3, 3402},
+       {0x33D3, 0, 2 | DECOMP_NO_COMPOSE, 3405},       /* compatibility mapping */
+       {0x33D4, 0, 2 | DECOMP_NO_COMPOSE, 3407},       /* compatibility mapping */
+       {0x33D5, 0, 3, 3409},
+       {0x33D6, 0, 3, 3412},
+       {0x33D7, 0, 2 | DECOMP_NO_COMPOSE, 3415},       /* compatibility mapping */
+       {0x33D8, 0, 4, 3417},
+       {0x33D9, 0, 3, 3421},
+       {0x33DA, 0, 2 | DECOMP_NO_COMPOSE, 3424},       /* compatibility mapping */
+       {0x33DB, 0, 2 | DECOMP_NO_COMPOSE, 3426},       /* compatibility mapping */
+       {0x33DC, 0, 2 | DECOMP_NO_COMPOSE, 3428},       /* compatibility mapping */
+       {0x33DD, 0, 2 | DECOMP_NO_COMPOSE, 3430},       /* compatibility mapping */
+       {0x33DE, 0, 3, 3432},
+       {0x33DF, 0, 3, 3435},
+       {0x33E0, 0, 2 | DECOMP_NO_COMPOSE, 3438},       /* compatibility mapping */
+       {0x33E1, 0, 2 | DECOMP_NO_COMPOSE, 3440},       /* compatibility mapping */
+       {0x33E2, 0, 2 | DECOMP_NO_COMPOSE, 3442},       /* compatibility mapping */
+       {0x33E3, 0, 2 | DECOMP_NO_COMPOSE, 3444},       /* compatibility mapping */
+       {0x33E4, 0, 2 | DECOMP_NO_COMPOSE, 3446},       /* compatibility mapping */
+       {0x33E5, 0, 2 | DECOMP_NO_COMPOSE, 3448},       /* compatibility mapping */
+       {0x33E6, 0, 2 | DECOMP_NO_COMPOSE, 3450},       /* compatibility mapping */
+       {0x33E7, 0, 2 | DECOMP_NO_COMPOSE, 3452},       /* compatibility mapping */
+       {0x33E8, 0, 2 | DECOMP_NO_COMPOSE, 3454},       /* compatibility mapping */
+       {0x33E9, 0, 3, 3456},
+       {0x33EA, 0, 3, 3459},
+       {0x33EB, 0, 3, 3462},
+       {0x33EC, 0, 3, 3465},
+       {0x33ED, 0, 3, 3468},
+       {0x33EE, 0, 3, 3471},
+       {0x33EF, 0, 3, 3474},
+       {0x33F0, 0, 3, 3477},
+       {0x33F1, 0, 3, 3480},
+       {0x33F2, 0, 3, 3483},
+       {0x33F3, 0, 3, 3486},
+       {0x33F4, 0, 3, 3489},
+       {0x33F5, 0, 3, 3492},
+       {0x33F6, 0, 3, 3495},
+       {0x33F7, 0, 3, 3498},
+       {0x33F8, 0, 3, 3501},
+       {0x33F9, 0, 3, 3504},
+       {0x33FA, 0, 3, 3507},
+       {0x33FB, 0, 3, 3510},
+       {0x33FC, 0, 3, 3513},
+       {0x33FD, 0, 3, 3516},
+       {0x33FE, 0, 3, 3519},
+       {0x33FF, 0, 3, 3522},
+       {0xA66F, 230, 0, 0},
+       {0xA674, 230, 0, 0},
+       {0xA675, 230, 0, 0},
+       {0xA676, 230, 0, 0},
+       {0xA677, 230, 0, 0},
+       {0xA678, 230, 0, 0},
+       {0xA679, 230, 0, 0},
+       {0xA67A, 230, 0, 0},
+       {0xA67B, 230, 0, 0},
+       {0xA67C, 230, 0, 0},
+       {0xA67D, 230, 0, 0},
+       {0xA69C, 0, 1 | DECOMP_INLINE, 0x044A},
+       {0xA69D, 0, 1 | DECOMP_INLINE, 0x044C},
+       {0xA69E, 230, 0, 0},
+       {0xA69F, 230, 0, 0},
+       {0xA6F0, 230, 0, 0},
+       {0xA6F1, 230, 0, 0},
+       {0xA770, 0, 1 | DECOMP_INLINE, 0xA76F},
+       {0xA7F8, 0, 1 | DECOMP_INLINE, 0x0126},
+       {0xA7F9, 0, 1 | DECOMP_INLINE, 0x0153},
+       {0xA806, 9, 0, 0},
+       {0xA8C4, 9, 0, 0},
+       {0xA8E0, 230, 0, 0},
+       {0xA8E1, 230, 0, 0},
+       {0xA8E2, 230, 0, 0},
+       {0xA8E3, 230, 0, 0},
+       {0xA8E4, 230, 0, 0},
+       {0xA8E5, 230, 0, 0},
+       {0xA8E6, 230, 0, 0},
+       {0xA8E7, 230, 0, 0},
+       {0xA8E8, 230, 0, 0},
+       {0xA8E9, 230, 0, 0},
+       {0xA8EA, 230, 0, 0},
+       {0xA8EB, 230, 0, 0},
+       {0xA8EC, 230, 0, 0},
+       {0xA8ED, 230, 0, 0},
+       {0xA8EE, 230, 0, 0},
+       {0xA8EF, 230, 0, 0},
+       {0xA8F0, 230, 0, 0},
+       {0xA8F1, 230, 0, 0},
+       {0xA92B, 220, 0, 0},
+       {0xA92C, 220, 0, 0},
+       {0xA92D, 220, 0, 0},
+       {0xA953, 9, 0, 0},
+       {0xA9B3, 7, 0, 0},
+       {0xA9C0, 9, 0, 0},
+       {0xAAB0, 230, 0, 0},
+       {0xAAB2, 230, 0, 0},
+       {0xAAB3, 230, 0, 0},
+       {0xAAB4, 220, 0, 0},
+       {0xAAB7, 230, 0, 0},
+       {0xAAB8, 230, 0, 0},
+       {0xAABE, 230, 0, 0},
+       {0xAABF, 230, 0, 0},
+       {0xAAC1, 230, 0, 0},
+       {0xAAF6, 9, 0, 0},
+       {0xAB5C, 0, 1 | DECOMP_INLINE, 0xA727},
+       {0xAB5D, 0, 1 | DECOMP_INLINE, 0xAB37},
+       {0xAB5E, 0, 1 | DECOMP_INLINE, 0x026B},
+       {0xAB5F, 0, 1 | DECOMP_INLINE, 0xAB52},
+       {0xABED, 9, 0, 0},
+       {0xF900, 0, 1 | DECOMP_INLINE, 0x8C48},
+       {0xF901, 0, 1 | DECOMP_INLINE, 0x66F4},
+       {0xF902, 0, 1 | DECOMP_INLINE, 0x8ECA},
+       {0xF903, 0, 1 | DECOMP_INLINE, 0x8CC8},
+       {0xF904, 0, 1 | DECOMP_INLINE, 0x6ED1},
+       {0xF905, 0, 1 | DECOMP_INLINE, 0x4E32},
+       {0xF906, 0, 1 | DECOMP_INLINE, 0x53E5},
+       {0xF907, 0, 1 | DECOMP_INLINE, 0x9F9C},
+       {0xF908, 0, 1 | DECOMP_INLINE, 0x9F9C},
+       {0xF909, 0, 1 | DECOMP_INLINE, 0x5951},
+       {0xF90A, 0, 1 | DECOMP_INLINE, 0x91D1},
+       {0xF90B, 0, 1 | DECOMP_INLINE, 0x5587},
+       {0xF90C, 0, 1 | DECOMP_INLINE, 0x5948},
+       {0xF90D, 0, 1 | DECOMP_INLINE, 0x61F6},
+       {0xF90E, 0, 1 | DECOMP_INLINE, 0x7669},
+       {0xF90F, 0, 1 | DECOMP_INLINE, 0x7F85},
+       {0xF910, 0, 1 | DECOMP_INLINE, 0x863F},
+       {0xF911, 0, 1 | DECOMP_INLINE, 0x87BA},
+       {0xF912, 0, 1 | DECOMP_INLINE, 0x88F8},
+       {0xF913, 0, 1 | DECOMP_INLINE, 0x908F},
+       {0xF914, 0, 1 | DECOMP_INLINE, 0x6A02},
+       {0xF915, 0, 1 | DECOMP_INLINE, 0x6D1B},
+       {0xF916, 0, 1 | DECOMP_INLINE, 0x70D9},
+       {0xF917, 0, 1 | DECOMP_INLINE, 0x73DE},
+       {0xF918, 0, 1 | DECOMP_INLINE, 0x843D},
+       {0xF919, 0, 1 | DECOMP_INLINE, 0x916A},
+       {0xF91A, 0, 1 | DECOMP_INLINE, 0x99F1},
+       {0xF91B, 0, 1 | DECOMP_INLINE, 0x4E82},
+       {0xF91C, 0, 1 | DECOMP_INLINE, 0x5375},
+       {0xF91D, 0, 1 | DECOMP_INLINE, 0x6B04},
+       {0xF91E, 0, 1 | DECOMP_INLINE, 0x721B},
+       {0xF91F, 0, 1 | DECOMP_INLINE, 0x862D},
+       {0xF920, 0, 1 | DECOMP_INLINE, 0x9E1E},
+       {0xF921, 0, 1 | DECOMP_INLINE, 0x5D50},
+       {0xF922, 0, 1 | DECOMP_INLINE, 0x6FEB},
+       {0xF923, 0, 1 | DECOMP_INLINE, 0x85CD},
+       {0xF924, 0, 1 | DECOMP_INLINE, 0x8964},
+       {0xF925, 0, 1 | DECOMP_INLINE, 0x62C9},
+       {0xF926, 0, 1 | DECOMP_INLINE, 0x81D8},
+       {0xF927, 0, 1 | DECOMP_INLINE, 0x881F},
+       {0xF928, 0, 1 | DECOMP_INLINE, 0x5ECA},
+       {0xF929, 0, 1 | DECOMP_INLINE, 0x6717},
+       {0xF92A, 0, 1 | DECOMP_INLINE, 0x6D6A},
+       {0xF92B, 0, 1 | DECOMP_INLINE, 0x72FC},
+       {0xF92C, 0, 1 | DECOMP_INLINE, 0x90CE},
+       {0xF92D, 0, 1 | DECOMP_INLINE, 0x4F86},
+       {0xF92E, 0, 1 | DECOMP_INLINE, 0x51B7},
+       {0xF92F, 0, 1 | DECOMP_INLINE, 0x52DE},
+       {0xF930, 0, 1 | DECOMP_INLINE, 0x64C4},
+       {0xF931, 0, 1 | DECOMP_INLINE, 0x6AD3},
+       {0xF932, 0, 1 | DECOMP_INLINE, 0x7210},
+       {0xF933, 0, 1 | DECOMP_INLINE, 0x76E7},
+       {0xF934, 0, 1 | DECOMP_INLINE, 0x8001},
+       {0xF935, 0, 1 | DECOMP_INLINE, 0x8606},
+       {0xF936, 0, 1 | DECOMP_INLINE, 0x865C},
+       {0xF937, 0, 1 | DECOMP_INLINE, 0x8DEF},
+       {0xF938, 0, 1 | DECOMP_INLINE, 0x9732},
+       {0xF939, 0, 1 | DECOMP_INLINE, 0x9B6F},
+       {0xF93A, 0, 1 | DECOMP_INLINE, 0x9DFA},
+       {0xF93B, 0, 1 | DECOMP_INLINE, 0x788C},
+       {0xF93C, 0, 1 | DECOMP_INLINE, 0x797F},
+       {0xF93D, 0, 1 | DECOMP_INLINE, 0x7DA0},
+       {0xF93E, 0, 1 | DECOMP_INLINE, 0x83C9},
+       {0xF93F, 0, 1 | DECOMP_INLINE, 0x9304},
+       {0xF940, 0, 1 | DECOMP_INLINE, 0x9E7F},
+       {0xF941, 0, 1 | DECOMP_INLINE, 0x8AD6},
+       {0xF942, 0, 1 | DECOMP_INLINE, 0x58DF},
+       {0xF943, 0, 1 | DECOMP_INLINE, 0x5F04},
+       {0xF944, 0, 1 | DECOMP_INLINE, 0x7C60},
+       {0xF945, 0, 1 | DECOMP_INLINE, 0x807E},
+       {0xF946, 0, 1 | DECOMP_INLINE, 0x7262},
+       {0xF947, 0, 1 | DECOMP_INLINE, 0x78CA},
+       {0xF948, 0, 1 | DECOMP_INLINE, 0x8CC2},
+       {0xF949, 0, 1 | DECOMP_INLINE, 0x96F7},
+       {0xF94A, 0, 1 | DECOMP_INLINE, 0x58D8},
+       {0xF94B, 0, 1 | DECOMP_INLINE, 0x5C62},
+       {0xF94C, 0, 1 | DECOMP_INLINE, 0x6A13},
+       {0xF94D, 0, 1 | DECOMP_INLINE, 0x6DDA},
+       {0xF94E, 0, 1 | DECOMP_INLINE, 0x6F0F},
+       {0xF94F, 0, 1 | DECOMP_INLINE, 0x7D2F},
+       {0xF950, 0, 1 | DECOMP_INLINE, 0x7E37},
+       {0xF951, 0, 1 | DECOMP_INLINE, 0x964B},
+       {0xF952, 0, 1 | DECOMP_INLINE, 0x52D2},
+       {0xF953, 0, 1 | DECOMP_INLINE, 0x808B},
+       {0xF954, 0, 1 | DECOMP_INLINE, 0x51DC},
+       {0xF955, 0, 1 | DECOMP_INLINE, 0x51CC},
+       {0xF956, 0, 1 | DECOMP_INLINE, 0x7A1C},
+       {0xF957, 0, 1 | DECOMP_INLINE, 0x7DBE},
+       {0xF958, 0, 1 | DECOMP_INLINE, 0x83F1},
+       {0xF959, 0, 1 | DECOMP_INLINE, 0x9675},
+       {0xF95A, 0, 1 | DECOMP_INLINE, 0x8B80},
+       {0xF95B, 0, 1 | DECOMP_INLINE, 0x62CF},
+       {0xF95C, 0, 1 | DECOMP_INLINE, 0x6A02},
+       {0xF95D, 0, 1 | DECOMP_INLINE, 0x8AFE},
+       {0xF95E, 0, 1 | DECOMP_INLINE, 0x4E39},
+       {0xF95F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+       {0xF960, 0, 1 | DECOMP_INLINE, 0x6012},
+       {0xF961, 0, 1 | DECOMP_INLINE, 0x7387},
+       {0xF962, 0, 1 | DECOMP_INLINE, 0x7570},
+       {0xF963, 0, 1 | DECOMP_INLINE, 0x5317},
+       {0xF964, 0, 1 | DECOMP_INLINE, 0x78FB},
+       {0xF965, 0, 1 | DECOMP_INLINE, 0x4FBF},
+       {0xF966, 0, 1 | DECOMP_INLINE, 0x5FA9},
+       {0xF967, 0, 1 | DECOMP_INLINE, 0x4E0D},
+       {0xF968, 0, 1 | DECOMP_INLINE, 0x6CCC},
+       {0xF969, 0, 1 | DECOMP_INLINE, 0x6578},
+       {0xF96A, 0, 1 | DECOMP_INLINE, 0x7D22},
+       {0xF96B, 0, 1 | DECOMP_INLINE, 0x53C3},
+       {0xF96C, 0, 1 | DECOMP_INLINE, 0x585E},
+       {0xF96D, 0, 1 | DECOMP_INLINE, 0x7701},
+       {0xF96E, 0, 1 | DECOMP_INLINE, 0x8449},
+       {0xF96F, 0, 1 | DECOMP_INLINE, 0x8AAA},
+       {0xF970, 0, 1 | DECOMP_INLINE, 0x6BBA},
+       {0xF971, 0, 1 | DECOMP_INLINE, 0x8FB0},
+       {0xF972, 0, 1 | DECOMP_INLINE, 0x6C88},
+       {0xF973, 0, 1 | DECOMP_INLINE, 0x62FE},
+       {0xF974, 0, 1 | DECOMP_INLINE, 0x82E5},
+       {0xF975, 0, 1 | DECOMP_INLINE, 0x63A0},
+       {0xF976, 0, 1 | DECOMP_INLINE, 0x7565},
+       {0xF977, 0, 1 | DECOMP_INLINE, 0x4EAE},
+       {0xF978, 0, 1 | DECOMP_INLINE, 0x5169},
+       {0xF979, 0, 1 | DECOMP_INLINE, 0x51C9},
+       {0xF97A, 0, 1 | DECOMP_INLINE, 0x6881},
+       {0xF97B, 0, 1 | DECOMP_INLINE, 0x7CE7},
+       {0xF97C, 0, 1 | DECOMP_INLINE, 0x826F},
+       {0xF97D, 0, 1 | DECOMP_INLINE, 0x8AD2},
+       {0xF97E, 0, 1 | DECOMP_INLINE, 0x91CF},
+       {0xF97F, 0, 1 | DECOMP_INLINE, 0x52F5},
+       {0xF980, 0, 1 | DECOMP_INLINE, 0x5442},
+       {0xF981, 0, 1 | DECOMP_INLINE, 0x5973},
+       {0xF982, 0, 1 | DECOMP_INLINE, 0x5EEC},
+       {0xF983, 0, 1 | DECOMP_INLINE, 0x65C5},
+       {0xF984, 0, 1 | DECOMP_INLINE, 0x6FFE},
+       {0xF985, 0, 1 | DECOMP_INLINE, 0x792A},
+       {0xF986, 0, 1 | DECOMP_INLINE, 0x95AD},
+       {0xF987, 0, 1 | DECOMP_INLINE, 0x9A6A},
+       {0xF988, 0, 1 | DECOMP_INLINE, 0x9E97},
+       {0xF989, 0, 1 | DECOMP_INLINE, 0x9ECE},
+       {0xF98A, 0, 1 | DECOMP_INLINE, 0x529B},
+       {0xF98B, 0, 1 | DECOMP_INLINE, 0x66C6},
+       {0xF98C, 0, 1 | DECOMP_INLINE, 0x6B77},
+       {0xF98D, 0, 1 | DECOMP_INLINE, 0x8F62},
+       {0xF98E, 0, 1 | DECOMP_INLINE, 0x5E74},
+       {0xF98F, 0, 1 | DECOMP_INLINE, 0x6190},
+       {0xF990, 0, 1 | DECOMP_INLINE, 0x6200},
+       {0xF991, 0, 1 | DECOMP_INLINE, 0x649A},
+       {0xF992, 0, 1 | DECOMP_INLINE, 0x6F23},
+       {0xF993, 0, 1 | DECOMP_INLINE, 0x7149},
+       {0xF994, 0, 1 | DECOMP_INLINE, 0x7489},
+       {0xF995, 0, 1 | DECOMP_INLINE, 0x79CA},
+       {0xF996, 0, 1 | DECOMP_INLINE, 0x7DF4},
+       {0xF997, 0, 1 | DECOMP_INLINE, 0x806F},
+       {0xF998, 0, 1 | DECOMP_INLINE, 0x8F26},
+       {0xF999, 0, 1 | DECOMP_INLINE, 0x84EE},
+       {0xF99A, 0, 1 | DECOMP_INLINE, 0x9023},
+       {0xF99B, 0, 1 | DECOMP_INLINE, 0x934A},
+       {0xF99C, 0, 1 | DECOMP_INLINE, 0x5217},
+       {0xF99D, 0, 1 | DECOMP_INLINE, 0x52A3},
+       {0xF99E, 0, 1 | DECOMP_INLINE, 0x54BD},
+       {0xF99F, 0, 1 | DECOMP_INLINE, 0x70C8},
+       {0xF9A0, 0, 1 | DECOMP_INLINE, 0x88C2},
+       {0xF9A1, 0, 1 | DECOMP_INLINE, 0x8AAA},
+       {0xF9A2, 0, 1 | DECOMP_INLINE, 0x5EC9},
+       {0xF9A3, 0, 1 | DECOMP_INLINE, 0x5FF5},
+       {0xF9A4, 0, 1 | DECOMP_INLINE, 0x637B},
+       {0xF9A5, 0, 1 | DECOMP_INLINE, 0x6BAE},
+       {0xF9A6, 0, 1 | DECOMP_INLINE, 0x7C3E},
+       {0xF9A7, 0, 1 | DECOMP_INLINE, 0x7375},
+       {0xF9A8, 0, 1 | DECOMP_INLINE, 0x4EE4},
+       {0xF9A9, 0, 1 | DECOMP_INLINE, 0x56F9},
+       {0xF9AA, 0, 1 | DECOMP_INLINE, 0x5BE7},
+       {0xF9AB, 0, 1 | DECOMP_INLINE, 0x5DBA},
+       {0xF9AC, 0, 1 | DECOMP_INLINE, 0x601C},
+       {0xF9AD, 0, 1 | DECOMP_INLINE, 0x73B2},
+       {0xF9AE, 0, 1 | DECOMP_INLINE, 0x7469},
+       {0xF9AF, 0, 1 | DECOMP_INLINE, 0x7F9A},
+       {0xF9B0, 0, 1 | DECOMP_INLINE, 0x8046},
+       {0xF9B1, 0, 1 | DECOMP_INLINE, 0x9234},
+       {0xF9B2, 0, 1 | DECOMP_INLINE, 0x96F6},
+       {0xF9B3, 0, 1 | DECOMP_INLINE, 0x9748},
+       {0xF9B4, 0, 1 | DECOMP_INLINE, 0x9818},
+       {0xF9B5, 0, 1 | DECOMP_INLINE, 0x4F8B},
+       {0xF9B6, 0, 1 | DECOMP_INLINE, 0x79AE},
+       {0xF9B7, 0, 1 | DECOMP_INLINE, 0x91B4},
+       {0xF9B8, 0, 1 | DECOMP_INLINE, 0x96B8},
+       {0xF9B9, 0, 1 | DECOMP_INLINE, 0x60E1},
+       {0xF9BA, 0, 1 | DECOMP_INLINE, 0x4E86},
+       {0xF9BB, 0, 1 | DECOMP_INLINE, 0x50DA},
+       {0xF9BC, 0, 1 | DECOMP_INLINE, 0x5BEE},
+       {0xF9BD, 0, 1 | DECOMP_INLINE, 0x5C3F},
+       {0xF9BE, 0, 1 | DECOMP_INLINE, 0x6599},
+       {0xF9BF, 0, 1 | DECOMP_INLINE, 0x6A02},
+       {0xF9C0, 0, 1 | DECOMP_INLINE, 0x71CE},
+       {0xF9C1, 0, 1 | DECOMP_INLINE, 0x7642},
+       {0xF9C2, 0, 1 | DECOMP_INLINE, 0x84FC},
+       {0xF9C3, 0, 1 | DECOMP_INLINE, 0x907C},
+       {0xF9C4, 0, 1 | DECOMP_INLINE, 0x9F8D},
+       {0xF9C5, 0, 1 | DECOMP_INLINE, 0x6688},
+       {0xF9C6, 0, 1 | DECOMP_INLINE, 0x962E},
+       {0xF9C7, 0, 1 | DECOMP_INLINE, 0x5289},
+       {0xF9C8, 0, 1 | DECOMP_INLINE, 0x677B},
+       {0xF9C9, 0, 1 | DECOMP_INLINE, 0x67F3},
+       {0xF9CA, 0, 1 | DECOMP_INLINE, 0x6D41},
+       {0xF9CB, 0, 1 | DECOMP_INLINE, 0x6E9C},
+       {0xF9CC, 0, 1 | DECOMP_INLINE, 0x7409},
+       {0xF9CD, 0, 1 | DECOMP_INLINE, 0x7559},
+       {0xF9CE, 0, 1 | DECOMP_INLINE, 0x786B},
+       {0xF9CF, 0, 1 | DECOMP_INLINE, 0x7D10},
+       {0xF9D0, 0, 1 | DECOMP_INLINE, 0x985E},
+       {0xF9D1, 0, 1 | DECOMP_INLINE, 0x516D},
+       {0xF9D2, 0, 1 | DECOMP_INLINE, 0x622E},
+       {0xF9D3, 0, 1 | DECOMP_INLINE, 0x9678},
+       {0xF9D4, 0, 1 | DECOMP_INLINE, 0x502B},
+       {0xF9D5, 0, 1 | DECOMP_INLINE, 0x5D19},
+       {0xF9D6, 0, 1 | DECOMP_INLINE, 0x6DEA},
+       {0xF9D7, 0, 1 | DECOMP_INLINE, 0x8F2A},
+       {0xF9D8, 0, 1 | DECOMP_INLINE, 0x5F8B},
+       {0xF9D9, 0, 1 | DECOMP_INLINE, 0x6144},
+       {0xF9DA, 0, 1 | DECOMP_INLINE, 0x6817},
+       {0xF9DB, 0, 1 | DECOMP_INLINE, 0x7387},
+       {0xF9DC, 0, 1 | DECOMP_INLINE, 0x9686},
+       {0xF9DD, 0, 1 | DECOMP_INLINE, 0x5229},
+       {0xF9DE, 0, 1 | DECOMP_INLINE, 0x540F},
+       {0xF9DF, 0, 1 | DECOMP_INLINE, 0x5C65},
+       {0xF9E0, 0, 1 | DECOMP_INLINE, 0x6613},
+       {0xF9E1, 0, 1 | DECOMP_INLINE, 0x674E},
+       {0xF9E2, 0, 1 | DECOMP_INLINE, 0x68A8},
+       {0xF9E3, 0, 1 | DECOMP_INLINE, 0x6CE5},
+       {0xF9E4, 0, 1 | DECOMP_INLINE, 0x7406},
+       {0xF9E5, 0, 1 | DECOMP_INLINE, 0x75E2},
+       {0xF9E6, 0, 1 | DECOMP_INLINE, 0x7F79},
+       {0xF9E7, 0, 1 | DECOMP_INLINE, 0x88CF},
+       {0xF9E8, 0, 1 | DECOMP_INLINE, 0x88E1},
+       {0xF9E9, 0, 1 | DECOMP_INLINE, 0x91CC},
+       {0xF9EA, 0, 1 | DECOMP_INLINE, 0x96E2},
+       {0xF9EB, 0, 1 | DECOMP_INLINE, 0x533F},
+       {0xF9EC, 0, 1 | DECOMP_INLINE, 0x6EBA},
+       {0xF9ED, 0, 1 | DECOMP_INLINE, 0x541D},
+       {0xF9EE, 0, 1 | DECOMP_INLINE, 0x71D0},
+       {0xF9EF, 0, 1 | DECOMP_INLINE, 0x7498},
+       {0xF9F0, 0, 1 | DECOMP_INLINE, 0x85FA},
+       {0xF9F1, 0, 1 | DECOMP_INLINE, 0x96A3},
+       {0xF9F2, 0, 1 | DECOMP_INLINE, 0x9C57},
+       {0xF9F3, 0, 1 | DECOMP_INLINE, 0x9E9F},
+       {0xF9F4, 0, 1 | DECOMP_INLINE, 0x6797},
+       {0xF9F5, 0, 1 | DECOMP_INLINE, 0x6DCB},
+       {0xF9F6, 0, 1 | DECOMP_INLINE, 0x81E8},
+       {0xF9F7, 0, 1 | DECOMP_INLINE, 0x7ACB},
+       {0xF9F8, 0, 1 | DECOMP_INLINE, 0x7B20},
+       {0xF9F9, 0, 1 | DECOMP_INLINE, 0x7C92},
+       {0xF9FA, 0, 1 | DECOMP_INLINE, 0x72C0},
+       {0xF9FB, 0, 1 | DECOMP_INLINE, 0x7099},
+       {0xF9FC, 0, 1 | DECOMP_INLINE, 0x8B58},
+       {0xF9FD, 0, 1 | DECOMP_INLINE, 0x4EC0},
+       {0xF9FE, 0, 1 | DECOMP_INLINE, 0x8336},
+       {0xF9FF, 0, 1 | DECOMP_INLINE, 0x523A},
+       {0xFA00, 0, 1 | DECOMP_INLINE, 0x5207},
+       {0xFA01, 0, 1 | DECOMP_INLINE, 0x5EA6},
+       {0xFA02, 0, 1 | DECOMP_INLINE, 0x62D3},
+       {0xFA03, 0, 1 | DECOMP_INLINE, 0x7CD6},
+       {0xFA04, 0, 1 | DECOMP_INLINE, 0x5B85},
+       {0xFA05, 0, 1 | DECOMP_INLINE, 0x6D1E},
+       {0xFA06, 0, 1 | DECOMP_INLINE, 0x66B4},
+       {0xFA07, 0, 1 | DECOMP_INLINE, 0x8F3B},
+       {0xFA08, 0, 1 | DECOMP_INLINE, 0x884C},
+       {0xFA09, 0, 1 | DECOMP_INLINE, 0x964D},
+       {0xFA0A, 0, 1 | DECOMP_INLINE, 0x898B},
+       {0xFA0B, 0, 1 | DECOMP_INLINE, 0x5ED3},
+       {0xFA0C, 0, 1 | DECOMP_INLINE, 0x5140},
+       {0xFA0D, 0, 1 | DECOMP_INLINE, 0x55C0},
+       {0xFA10, 0, 1 | DECOMP_INLINE, 0x585A},
+       {0xFA12, 0, 1 | DECOMP_INLINE, 0x6674},
+       {0xFA15, 0, 1 | DECOMP_INLINE, 0x51DE},
+       {0xFA16, 0, 1 | DECOMP_INLINE, 0x732A},
+       {0xFA17, 0, 1 | DECOMP_INLINE, 0x76CA},
+       {0xFA18, 0, 1 | DECOMP_INLINE, 0x793C},
+       {0xFA19, 0, 1 | DECOMP_INLINE, 0x795E},
+       {0xFA1A, 0, 1 | DECOMP_INLINE, 0x7965},
+       {0xFA1B, 0, 1 | DECOMP_INLINE, 0x798F},
+       {0xFA1C, 0, 1 | DECOMP_INLINE, 0x9756},
+       {0xFA1D, 0, 1 | DECOMP_INLINE, 0x7CBE},
+       {0xFA1E, 0, 1 | DECOMP_INLINE, 0x7FBD},
+       {0xFA20, 0, 1 | DECOMP_INLINE, 0x8612},
+       {0xFA22, 0, 1 | DECOMP_INLINE, 0x8AF8},
+       {0xFA25, 0, 1 | DECOMP_INLINE, 0x9038},
+       {0xFA26, 0, 1 | DECOMP_INLINE, 0x90FD},
+       {0xFA2A, 0, 1 | DECOMP_INLINE, 0x98EF},
+       {0xFA2B, 0, 1 | DECOMP_INLINE, 0x98FC},
+       {0xFA2C, 0, 1 | DECOMP_INLINE, 0x9928},
+       {0xFA2D, 0, 1 | DECOMP_INLINE, 0x9DB4},
+       {0xFA2E, 0, 1 | DECOMP_INLINE, 0x90DE},
+       {0xFA2F, 0, 1 | DECOMP_INLINE, 0x96B7},
+       {0xFA30, 0, 1 | DECOMP_INLINE, 0x4FAE},
+       {0xFA31, 0, 1 | DECOMP_INLINE, 0x50E7},
+       {0xFA32, 0, 1 | DECOMP_INLINE, 0x514D},
+       {0xFA33, 0, 1 | DECOMP_INLINE, 0x52C9},
+       {0xFA34, 0, 1 | DECOMP_INLINE, 0x52E4},
+       {0xFA35, 0, 1 | DECOMP_INLINE, 0x5351},
+       {0xFA36, 0, 1 | DECOMP_INLINE, 0x559D},
+       {0xFA37, 0, 1 | DECOMP_INLINE, 0x5606},
+       {0xFA38, 0, 1 | DECOMP_INLINE, 0x5668},
+       {0xFA39, 0, 1 | DECOMP_INLINE, 0x5840},
+       {0xFA3A, 0, 1 | DECOMP_INLINE, 0x58A8},
+       {0xFA3B, 0, 1 | DECOMP_INLINE, 0x5C64},
+       {0xFA3C, 0, 1 | DECOMP_INLINE, 0x5C6E},
+       {0xFA3D, 0, 1 | DECOMP_INLINE, 0x6094},
+       {0xFA3E, 0, 1 | DECOMP_INLINE, 0x6168},
+       {0xFA3F, 0, 1 | DECOMP_INLINE, 0x618E},
+       {0xFA40, 0, 1 | DECOMP_INLINE, 0x61F2},
+       {0xFA41, 0, 1 | DECOMP_INLINE, 0x654F},
+       {0xFA42, 0, 1 | DECOMP_INLINE, 0x65E2},
+       {0xFA43, 0, 1 | DECOMP_INLINE, 0x6691},
+       {0xFA44, 0, 1 | DECOMP_INLINE, 0x6885},
+       {0xFA45, 0, 1 | DECOMP_INLINE, 0x6D77},
+       {0xFA46, 0, 1 | DECOMP_INLINE, 0x6E1A},
+       {0xFA47, 0, 1 | DECOMP_INLINE, 0x6F22},
+       {0xFA48, 0, 1 | DECOMP_INLINE, 0x716E},
+       {0xFA49, 0, 1 | DECOMP_INLINE, 0x722B},
+       {0xFA4A, 0, 1 | DECOMP_INLINE, 0x7422},
+       {0xFA4B, 0, 1 | DECOMP_INLINE, 0x7891},
+       {0xFA4C, 0, 1 | DECOMP_INLINE, 0x793E},
+       {0xFA4D, 0, 1 | DECOMP_INLINE, 0x7949},
+       {0xFA4E, 0, 1 | DECOMP_INLINE, 0x7948},
+       {0xFA4F, 0, 1 | DECOMP_INLINE, 0x7950},
+       {0xFA50, 0, 1 | DECOMP_INLINE, 0x7956},
+       {0xFA51, 0, 1 | DECOMP_INLINE, 0x795D},
+       {0xFA52, 0, 1 | DECOMP_INLINE, 0x798D},
+       {0xFA53, 0, 1 | DECOMP_INLINE, 0x798E},
+       {0xFA54, 0, 1 | DECOMP_INLINE, 0x7A40},
+       {0xFA55, 0, 1 | DECOMP_INLINE, 0x7A81},
+       {0xFA56, 0, 1 | DECOMP_INLINE, 0x7BC0},
+       {0xFA57, 0, 1 | DECOMP_INLINE, 0x7DF4},
+       {0xFA58, 0, 1 | DECOMP_INLINE, 0x7E09},
+       {0xFA59, 0, 1 | DECOMP_INLINE, 0x7E41},
+       {0xFA5A, 0, 1 | DECOMP_INLINE, 0x7F72},
+       {0xFA5B, 0, 1 | DECOMP_INLINE, 0x8005},
+       {0xFA5C, 0, 1 | DECOMP_INLINE, 0x81ED},
+       {0xFA5D, 0, 1 | DECOMP_INLINE, 0x8279},
+       {0xFA5E, 0, 1 | DECOMP_INLINE, 0x8279},
+       {0xFA5F, 0, 1 | DECOMP_INLINE, 0x8457},
+       {0xFA60, 0, 1 | DECOMP_INLINE, 0x8910},
+       {0xFA61, 0, 1 | DECOMP_INLINE, 0x8996},
+       {0xFA62, 0, 1 | DECOMP_INLINE, 0x8B01},
+       {0xFA63, 0, 1 | DECOMP_INLINE, 0x8B39},
+       {0xFA64, 0, 1 | DECOMP_INLINE, 0x8CD3},
+       {0xFA65, 0, 1 | DECOMP_INLINE, 0x8D08},
+       {0xFA66, 0, 1 | DECOMP_INLINE, 0x8FB6},
+       {0xFA67, 0, 1 | DECOMP_INLINE, 0x9038},
+       {0xFA68, 0, 1 | DECOMP_INLINE, 0x96E3},
+       {0xFA69, 0, 1 | DECOMP_INLINE, 0x97FF},
+       {0xFA6A, 0, 1 | DECOMP_INLINE, 0x983B},
+       {0xFA6B, 0, 1 | DECOMP_INLINE, 0x6075},
+       {0xFA6C, 0, 1, 3525},
+       {0xFA6D, 0, 1 | DECOMP_INLINE, 0x8218},
+       {0xFA70, 0, 1 | DECOMP_INLINE, 0x4E26},
+       {0xFA71, 0, 1 | DECOMP_INLINE, 0x51B5},
+       {0xFA72, 0, 1 | DECOMP_INLINE, 0x5168},
+       {0xFA73, 0, 1 | DECOMP_INLINE, 0x4F80},
+       {0xFA74, 0, 1 | DECOMP_INLINE, 0x5145},
+       {0xFA75, 0, 1 | DECOMP_INLINE, 0x5180},
+       {0xFA76, 0, 1 | DECOMP_INLINE, 0x52C7},
+       {0xFA77, 0, 1 | DECOMP_INLINE, 0x52FA},
+       {0xFA78, 0, 1 | DECOMP_INLINE, 0x559D},
+       {0xFA79, 0, 1 | DECOMP_INLINE, 0x5555},
+       {0xFA7A, 0, 1 | DECOMP_INLINE, 0x5599},
+       {0xFA7B, 0, 1 | DECOMP_INLINE, 0x55E2},
+       {0xFA7C, 0, 1 | DECOMP_INLINE, 0x585A},
+       {0xFA7D, 0, 1 | DECOMP_INLINE, 0x58B3},
+       {0xFA7E, 0, 1 | DECOMP_INLINE, 0x5944},
+       {0xFA7F, 0, 1 | DECOMP_INLINE, 0x5954},
+       {0xFA80, 0, 1 | DECOMP_INLINE, 0x5A62},
+       {0xFA81, 0, 1 | DECOMP_INLINE, 0x5B28},
+       {0xFA82, 0, 1 | DECOMP_INLINE, 0x5ED2},
+       {0xFA83, 0, 1 | DECOMP_INLINE, 0x5ED9},
+       {0xFA84, 0, 1 | DECOMP_INLINE, 0x5F69},
+       {0xFA85, 0, 1 | DECOMP_INLINE, 0x5FAD},
+       {0xFA86, 0, 1 | DECOMP_INLINE, 0x60D8},
+       {0xFA87, 0, 1 | DECOMP_INLINE, 0x614E},
+       {0xFA88, 0, 1 | DECOMP_INLINE, 0x6108},
+       {0xFA89, 0, 1 | DECOMP_INLINE, 0x618E},
+       {0xFA8A, 0, 1 | DECOMP_INLINE, 0x6160},
+       {0xFA8B, 0, 1 | DECOMP_INLINE, 0x61F2},
+       {0xFA8C, 0, 1 | DECOMP_INLINE, 0x6234},
+       {0xFA8D, 0, 1 | DECOMP_INLINE, 0x63C4},
+       {0xFA8E, 0, 1 | DECOMP_INLINE, 0x641C},
+       {0xFA8F, 0, 1 | DECOMP_INLINE, 0x6452},
+       {0xFA90, 0, 1 | DECOMP_INLINE, 0x6556},
+       {0xFA91, 0, 1 | DECOMP_INLINE, 0x6674},
+       {0xFA92, 0, 1 | DECOMP_INLINE, 0x6717},
+       {0xFA93, 0, 1 | DECOMP_INLINE, 0x671B},
+       {0xFA94, 0, 1 | DECOMP_INLINE, 0x6756},
+       {0xFA95, 0, 1 | DECOMP_INLINE, 0x6B79},
+       {0xFA96, 0, 1 | DECOMP_INLINE, 0x6BBA},
+       {0xFA97, 0, 1 | DECOMP_INLINE, 0x6D41},
+       {0xFA98, 0, 1 | DECOMP_INLINE, 0x6EDB},
+       {0xFA99, 0, 1 | DECOMP_INLINE, 0x6ECB},
+       {0xFA9A, 0, 1 | DECOMP_INLINE, 0x6F22},
+       {0xFA9B, 0, 1 | DECOMP_INLINE, 0x701E},
+       {0xFA9C, 0, 1 | DECOMP_INLINE, 0x716E},
+       {0xFA9D, 0, 1 | DECOMP_INLINE, 0x77A7},
+       {0xFA9E, 0, 1 | DECOMP_INLINE, 0x7235},
+       {0xFA9F, 0, 1 | DECOMP_INLINE, 0x72AF},
+       {0xFAA0, 0, 1 | DECOMP_INLINE, 0x732A},
+       {0xFAA1, 0, 1 | DECOMP_INLINE, 0x7471},
+       {0xFAA2, 0, 1 | DECOMP_INLINE, 0x7506},
+       {0xFAA3, 0, 1 | DECOMP_INLINE, 0x753B},
+       {0xFAA4, 0, 1 | DECOMP_INLINE, 0x761D},
+       {0xFAA5, 0, 1 | DECOMP_INLINE, 0x761F},
+       {0xFAA6, 0, 1 | DECOMP_INLINE, 0x76CA},
+       {0xFAA7, 0, 1 | DECOMP_INLINE, 0x76DB},
+       {0xFAA8, 0, 1 | DECOMP_INLINE, 0x76F4},
+       {0xFAA9, 0, 1 | DECOMP_INLINE, 0x774A},
+       {0xFAAA, 0, 1 | DECOMP_INLINE, 0x7740},
+       {0xFAAB, 0, 1 | DECOMP_INLINE, 0x78CC},
+       {0xFAAC, 0, 1 | DECOMP_INLINE, 0x7AB1},
+       {0xFAAD, 0, 1 | DECOMP_INLINE, 0x7BC0},
+       {0xFAAE, 0, 1 | DECOMP_INLINE, 0x7C7B},
+       {0xFAAF, 0, 1 | DECOMP_INLINE, 0x7D5B},
+       {0xFAB0, 0, 1 | DECOMP_INLINE, 0x7DF4},
+       {0xFAB1, 0, 1 | DECOMP_INLINE, 0x7F3E},
+       {0xFAB2, 0, 1 | DECOMP_INLINE, 0x8005},
+       {0xFAB3, 0, 1 | DECOMP_INLINE, 0x8352},
+       {0xFAB4, 0, 1 | DECOMP_INLINE, 0x83EF},
+       {0xFAB5, 0, 1 | DECOMP_INLINE, 0x8779},
+       {0xFAB6, 0, 1 | DECOMP_INLINE, 0x8941},
+       {0xFAB7, 0, 1 | DECOMP_INLINE, 0x8986},
+       {0xFAB8, 0, 1 | DECOMP_INLINE, 0x8996},
+       {0xFAB9, 0, 1 | DECOMP_INLINE, 0x8ABF},
+       {0xFABA, 0, 1 | DECOMP_INLINE, 0x8AF8},
+       {0xFABB, 0, 1 | DECOMP_INLINE, 0x8ACB},
+       {0xFABC, 0, 1 | DECOMP_INLINE, 0x8B01},
+       {0xFABD, 0, 1 | DECOMP_INLINE, 0x8AFE},
+       {0xFABE, 0, 1 | DECOMP_INLINE, 0x8AED},
+       {0xFABF, 0, 1 | DECOMP_INLINE, 0x8B39},
+       {0xFAC0, 0, 1 | DECOMP_INLINE, 0x8B8A},
+       {0xFAC1, 0, 1 | DECOMP_INLINE, 0x8D08},
+       {0xFAC2, 0, 1 | DECOMP_INLINE, 0x8F38},
+       {0xFAC3, 0, 1 | DECOMP_INLINE, 0x9072},
+       {0xFAC4, 0, 1 | DECOMP_INLINE, 0x9199},
+       {0xFAC5, 0, 1 | DECOMP_INLINE, 0x9276},
+       {0xFAC6, 0, 1 | DECOMP_INLINE, 0x967C},
+       {0xFAC7, 0, 1 | DECOMP_INLINE, 0x96E3},
+       {0xFAC8, 0, 1 | DECOMP_INLINE, 0x9756},
+       {0xFAC9, 0, 1 | DECOMP_INLINE, 0x97DB},
+       {0xFACA, 0, 1 | DECOMP_INLINE, 0x97FF},
+       {0xFACB, 0, 1 | DECOMP_INLINE, 0x980B},
+       {0xFACC, 0, 1 | DECOMP_INLINE, 0x983B},
+       {0xFACD, 0, 1 | DECOMP_INLINE, 0x9B12},
+       {0xFACE, 0, 1 | DECOMP_INLINE, 0x9F9C},
+       {0xFACF, 0, 1, 3526},
+       {0xFAD0, 0, 1, 3527},
+       {0xFAD1, 0, 1, 3528},
+       {0xFAD2, 0, 1 | DECOMP_INLINE, 0x3B9D},
+       {0xFAD3, 0, 1 | DECOMP_INLINE, 0x4018},
+       {0xFAD4, 0, 1 | DECOMP_INLINE, 0x4039},
+       {0xFAD5, 0, 1, 3529},
+       {0xFAD6, 0, 1, 3530},
+       {0xFAD7, 0, 1, 3531},
+       {0xFAD8, 0, 1 | DECOMP_INLINE, 0x9F43},
+       {0xFAD9, 0, 1 | DECOMP_INLINE, 0x9F8E},
+       {0xFB00, 0, 2 | DECOMP_NO_COMPOSE, 3532},       /* compatibility mapping */
+       {0xFB01, 0, 2 | DECOMP_NO_COMPOSE, 3534},       /* compatibility mapping */
+       {0xFB02, 0, 2 | DECOMP_NO_COMPOSE, 3536},       /* compatibility mapping */
+       {0xFB03, 0, 3, 3538},
+       {0xFB04, 0, 3, 3541},
+       {0xFB05, 0, 2 | DECOMP_NO_COMPOSE, 3544},       /* compatibility mapping */
+       {0xFB06, 0, 2 | DECOMP_NO_COMPOSE, 3546},       /* compatibility mapping */
+       {0xFB13, 0, 2 | DECOMP_NO_COMPOSE, 3548},       /* compatibility mapping */
+       {0xFB14, 0, 2 | DECOMP_NO_COMPOSE, 3550},       /* compatibility mapping */
+       {0xFB15, 0, 2 | DECOMP_NO_COMPOSE, 3552},       /* compatibility mapping */
+       {0xFB16, 0, 2 | DECOMP_NO_COMPOSE, 3554},       /* compatibility mapping */
+       {0xFB17, 0, 2 | DECOMP_NO_COMPOSE, 3556},       /* compatibility mapping */
+       {0xFB1D, 0, 2 | DECOMP_NO_COMPOSE, 3558},       /* in exclusion list */
+       {0xFB1E, 26, 0, 0},
+       {0xFB1F, 0, 2 | DECOMP_NO_COMPOSE, 3560},       /* in exclusion list */
+       {0xFB20, 0, 1 | DECOMP_INLINE, 0x05E2},
+       {0xFB21, 0, 1 | DECOMP_INLINE, 0x05D0},
+       {0xFB22, 0, 1 | DECOMP_INLINE, 0x05D3},
+       {0xFB23, 0, 1 | DECOMP_INLINE, 0x05D4},
+       {0xFB24, 0, 1 | DECOMP_INLINE, 0x05DB},
+       {0xFB25, 0, 1 | DECOMP_INLINE, 0x05DC},
+       {0xFB26, 0, 1 | DECOMP_INLINE, 0x05DD},
+       {0xFB27, 0, 1 | DECOMP_INLINE, 0x05E8},
+       {0xFB28, 0, 1 | DECOMP_INLINE, 0x05EA},
+       {0xFB29, 0, 1 | DECOMP_INLINE, 0x002B},
+       {0xFB2A, 0, 2 | DECOMP_NO_COMPOSE, 3562},       /* in exclusion list */
+       {0xFB2B, 0, 2 | DECOMP_NO_COMPOSE, 3564},       /* in exclusion list */
+       {0xFB2C, 0, 2 | DECOMP_NO_COMPOSE, 3566},       /* in exclusion list */
+       {0xFB2D, 0, 2 | DECOMP_NO_COMPOSE, 3568},       /* in exclusion list */
+       {0xFB2E, 0, 2 | DECOMP_NO_COMPOSE, 3570},       /* in exclusion list */
+       {0xFB2F, 0, 2 | DECOMP_NO_COMPOSE, 3572},       /* in exclusion list */
+       {0xFB30, 0, 2 | DECOMP_NO_COMPOSE, 3574},       /* in exclusion list */
+       {0xFB31, 0, 2 | DECOMP_NO_COMPOSE, 3576},       /* in exclusion list */
+       {0xFB32, 0, 2 | DECOMP_NO_COMPOSE, 3578},       /* in exclusion list */
+       {0xFB33, 0, 2 | DECOMP_NO_COMPOSE, 3580},       /* in exclusion list */
+       {0xFB34, 0, 2 | DECOMP_NO_COMPOSE, 3582},       /* in exclusion list */
+       {0xFB35, 0, 2 | DECOMP_NO_COMPOSE, 3584},       /* in exclusion list */
+       {0xFB36, 0, 2 | DECOMP_NO_COMPOSE, 3586},       /* in exclusion list */
+       {0xFB38, 0, 2 | DECOMP_NO_COMPOSE, 3588},       /* in exclusion list */
+       {0xFB39, 0, 2 | DECOMP_NO_COMPOSE, 3590},       /* in exclusion list */
+       {0xFB3A, 0, 2 | DECOMP_NO_COMPOSE, 3592},       /* in exclusion list */
+       {0xFB3B, 0, 2 | DECOMP_NO_COMPOSE, 3594},       /* in exclusion list */
+       {0xFB3C, 0, 2 | DECOMP_NO_COMPOSE, 3596},       /* in exclusion list */
+       {0xFB3E, 0, 2 | DECOMP_NO_COMPOSE, 3598},       /* in exclusion list */
+       {0xFB40, 0, 2 | DECOMP_NO_COMPOSE, 3600},       /* in exclusion list */
+       {0xFB41, 0, 2 | DECOMP_NO_COMPOSE, 3602},       /* in exclusion list */
+       {0xFB43, 0, 2 | DECOMP_NO_COMPOSE, 3604},       /* in exclusion list */
+       {0xFB44, 0, 2 | DECOMP_NO_COMPOSE, 3606},       /* in exclusion list */
+       {0xFB46, 0, 2 | DECOMP_NO_COMPOSE, 3608},       /* in exclusion list */
+       {0xFB47, 0, 2 | DECOMP_NO_COMPOSE, 3610},       /* in exclusion list */
+       {0xFB48, 0, 2 | DECOMP_NO_COMPOSE, 3612},       /* in exclusion list */
+       {0xFB49, 0, 2 | DECOMP_NO_COMPOSE, 3614},       /* in exclusion list */
+       {0xFB4A, 0, 2 | DECOMP_NO_COMPOSE, 3616},       /* in exclusion list */
+       {0xFB4B, 0, 2 | DECOMP_NO_COMPOSE, 3618},       /* in exclusion list */
+       {0xFB4C, 0, 2 | DECOMP_NO_COMPOSE, 3620},       /* in exclusion list */
+       {0xFB4D, 0, 2 | DECOMP_NO_COMPOSE, 3622},       /* in exclusion list */
+       {0xFB4E, 0, 2 | DECOMP_NO_COMPOSE, 3624},       /* in exclusion list */
+       {0xFB4F, 0, 2 | DECOMP_NO_COMPOSE, 3626},       /* compatibility mapping */
+       {0xFB50, 0, 1 | DECOMP_INLINE, 0x0671},
+       {0xFB51, 0, 1 | DECOMP_INLINE, 0x0671},
+       {0xFB52, 0, 1 | DECOMP_INLINE, 0x067B},
+       {0xFB53, 0, 1 | DECOMP_INLINE, 0x067B},
+       {0xFB54, 0, 1 | DECOMP_INLINE, 0x067B},
+       {0xFB55, 0, 1 | DECOMP_INLINE, 0x067B},
+       {0xFB56, 0, 1 | DECOMP_INLINE, 0x067E},
+       {0xFB57, 0, 1 | DECOMP_INLINE, 0x067E},
+       {0xFB58, 0, 1 | DECOMP_INLINE, 0x067E},
+       {0xFB59, 0, 1 | DECOMP_INLINE, 0x067E},
+       {0xFB5A, 0, 1 | DECOMP_INLINE, 0x0680},
+       {0xFB5B, 0, 1 | DECOMP_INLINE, 0x0680},
+       {0xFB5C, 0, 1 | DECOMP_INLINE, 0x0680},
+       {0xFB5D, 0, 1 | DECOMP_INLINE, 0x0680},
+       {0xFB5E, 0, 1 | DECOMP_INLINE, 0x067A},
+       {0xFB5F, 0, 1 | DECOMP_INLINE, 0x067A},
+       {0xFB60, 0, 1 | DECOMP_INLINE, 0x067A},
+       {0xFB61, 0, 1 | DECOMP_INLINE, 0x067A},
+       {0xFB62, 0, 1 | DECOMP_INLINE, 0x067F},
+       {0xFB63, 0, 1 | DECOMP_INLINE, 0x067F},
+       {0xFB64, 0, 1 | DECOMP_INLINE, 0x067F},
+       {0xFB65, 0, 1 | DECOMP_INLINE, 0x067F},
+       {0xFB66, 0, 1 | DECOMP_INLINE, 0x0679},
+       {0xFB67, 0, 1 | DECOMP_INLINE, 0x0679},
+       {0xFB68, 0, 1 | DECOMP_INLINE, 0x0679},
+       {0xFB69, 0, 1 | DECOMP_INLINE, 0x0679},
+       {0xFB6A, 0, 1 | DECOMP_INLINE, 0x06A4},
+       {0xFB6B, 0, 1 | DECOMP_INLINE, 0x06A4},
+       {0xFB6C, 0, 1 | DECOMP_INLINE, 0x06A4},
+       {0xFB6D, 0, 1 | DECOMP_INLINE, 0x06A4},
+       {0xFB6E, 0, 1 | DECOMP_INLINE, 0x06A6},
+       {0xFB6F, 0, 1 | DECOMP_INLINE, 0x06A6},
+       {0xFB70, 0, 1 | DECOMP_INLINE, 0x06A6},
+       {0xFB71, 0, 1 | DECOMP_INLINE, 0x06A6},
+       {0xFB72, 0, 1 | DECOMP_INLINE, 0x0684},
+       {0xFB73, 0, 1 | DECOMP_INLINE, 0x0684},
+       {0xFB74, 0, 1 | DECOMP_INLINE, 0x0684},
+       {0xFB75, 0, 1 | DECOMP_INLINE, 0x0684},
+       {0xFB76, 0, 1 | DECOMP_INLINE, 0x0683},
+       {0xFB77, 0, 1 | DECOMP_INLINE, 0x0683},
+       {0xFB78, 0, 1 | DECOMP_INLINE, 0x0683},
+       {0xFB79, 0, 1 | DECOMP_INLINE, 0x0683},
+       {0xFB7A, 0, 1 | DECOMP_INLINE, 0x0686},
+       {0xFB7B, 0, 1 | DECOMP_INLINE, 0x0686},
+       {0xFB7C, 0, 1 | DECOMP_INLINE, 0x0686},
+       {0xFB7D, 0, 1 | DECOMP_INLINE, 0x0686},
+       {0xFB7E, 0, 1 | DECOMP_INLINE, 0x0687},
+       {0xFB7F, 0, 1 | DECOMP_INLINE, 0x0687},
+       {0xFB80, 0, 1 | DECOMP_INLINE, 0x0687},
+       {0xFB81, 0, 1 | DECOMP_INLINE, 0x0687},
+       {0xFB82, 0, 1 | DECOMP_INLINE, 0x068D},
+       {0xFB83, 0, 1 | DECOMP_INLINE, 0x068D},
+       {0xFB84, 0, 1 | DECOMP_INLINE, 0x068C},
+       {0xFB85, 0, 1 | DECOMP_INLINE, 0x068C},
+       {0xFB86, 0, 1 | DECOMP_INLINE, 0x068E},
+       {0xFB87, 0, 1 | DECOMP_INLINE, 0x068E},
+       {0xFB88, 0, 1 | DECOMP_INLINE, 0x0688},
+       {0xFB89, 0, 1 | DECOMP_INLINE, 0x0688},
+       {0xFB8A, 0, 1 | DECOMP_INLINE, 0x0698},
+       {0xFB8B, 0, 1 | DECOMP_INLINE, 0x0698},
+       {0xFB8C, 0, 1 | DECOMP_INLINE, 0x0691},
+       {0xFB8D, 0, 1 | DECOMP_INLINE, 0x0691},
+       {0xFB8E, 0, 1 | DECOMP_INLINE, 0x06A9},
+       {0xFB8F, 0, 1 | DECOMP_INLINE, 0x06A9},
+       {0xFB90, 0, 1 | DECOMP_INLINE, 0x06A9},
+       {0xFB91, 0, 1 | DECOMP_INLINE, 0x06A9},
+       {0xFB92, 0, 1 | DECOMP_INLINE, 0x06AF},
+       {0xFB93, 0, 1 | DECOMP_INLINE, 0x06AF},
+       {0xFB94, 0, 1 | DECOMP_INLINE, 0x06AF},
+       {0xFB95, 0, 1 | DECOMP_INLINE, 0x06AF},
+       {0xFB96, 0, 1 | DECOMP_INLINE, 0x06B3},
+       {0xFB97, 0, 1 | DECOMP_INLINE, 0x06B3},
+       {0xFB98, 0, 1 | DECOMP_INLINE, 0x06B3},
+       {0xFB99, 0, 1 | DECOMP_INLINE, 0x06B3},
+       {0xFB9A, 0, 1 | DECOMP_INLINE, 0x06B1},
+       {0xFB9B, 0, 1 | DECOMP_INLINE, 0x06B1},
+       {0xFB9C, 0, 1 | DECOMP_INLINE, 0x06B1},
+       {0xFB9D, 0, 1 | DECOMP_INLINE, 0x06B1},
+       {0xFB9E, 0, 1 | DECOMP_INLINE, 0x06BA},
+       {0xFB9F, 0, 1 | DECOMP_INLINE, 0x06BA},
+       {0xFBA0, 0, 1 | DECOMP_INLINE, 0x06BB},
+       {0xFBA1, 0, 1 | DECOMP_INLINE, 0x06BB},
+       {0xFBA2, 0, 1 | DECOMP_INLINE, 0x06BB},
+       {0xFBA3, 0, 1 | DECOMP_INLINE, 0x06BB},
+       {0xFBA4, 0, 1 | DECOMP_INLINE, 0x06C0},
+       {0xFBA5, 0, 1 | DECOMP_INLINE, 0x06C0},
+       {0xFBA6, 0, 1 | DECOMP_INLINE, 0x06C1},
+       {0xFBA7, 0, 1 | DECOMP_INLINE, 0x06C1},
+       {0xFBA8, 0, 1 | DECOMP_INLINE, 0x06C1},
+       {0xFBA9, 0, 1 | DECOMP_INLINE, 0x06C1},
+       {0xFBAA, 0, 1 | DECOMP_INLINE, 0x06BE},
+       {0xFBAB, 0, 1 | DECOMP_INLINE, 0x06BE},
+       {0xFBAC, 0, 1 | DECOMP_INLINE, 0x06BE},
+       {0xFBAD, 0, 1 | DECOMP_INLINE, 0x06BE},
+       {0xFBAE, 0, 1 | DECOMP_INLINE, 0x06D2},
+       {0xFBAF, 0, 1 | DECOMP_INLINE, 0x06D2},
+       {0xFBB0, 0, 1 | DECOMP_INLINE, 0x06D3},
+       {0xFBB1, 0, 1 | DECOMP_INLINE, 0x06D3},
+       {0xFBD3, 0, 1 | DECOMP_INLINE, 0x06AD},
+       {0xFBD4, 0, 1 | DECOMP_INLINE, 0x06AD},
+       {0xFBD5, 0, 1 | DECOMP_INLINE, 0x06AD},
+       {0xFBD6, 0, 1 | DECOMP_INLINE, 0x06AD},
+       {0xFBD7, 0, 1 | DECOMP_INLINE, 0x06C7},
+       {0xFBD8, 0, 1 | DECOMP_INLINE, 0x06C7},
+       {0xFBD9, 0, 1 | DECOMP_INLINE, 0x06C6},
+       {0xFBDA, 0, 1 | DECOMP_INLINE, 0x06C6},
+       {0xFBDB, 0, 1 | DECOMP_INLINE, 0x06C8},
+       {0xFBDC, 0, 1 | DECOMP_INLINE, 0x06C8},
+       {0xFBDD, 0, 1 | DECOMP_INLINE, 0x0677},
+       {0xFBDE, 0, 1 | DECOMP_INLINE, 0x06CB},
+       {0xFBDF, 0, 1 | DECOMP_INLINE, 0x06CB},
+       {0xFBE0, 0, 1 | DECOMP_INLINE, 0x06C5},
+       {0xFBE1, 0, 1 | DECOMP_INLINE, 0x06C5},
+       {0xFBE2, 0, 1 | DECOMP_INLINE, 0x06C9},
+       {0xFBE3, 0, 1 | DECOMP_INLINE, 0x06C9},
+       {0xFBE4, 0, 1 | DECOMP_INLINE, 0x06D0},
+       {0xFBE5, 0, 1 | DECOMP_INLINE, 0x06D0},
+       {0xFBE6, 0, 1 | DECOMP_INLINE, 0x06D0},
+       {0xFBE7, 0, 1 | DECOMP_INLINE, 0x06D0},
+       {0xFBE8, 0, 1 | DECOMP_INLINE, 0x0649},
+       {0xFBE9, 0, 1 | DECOMP_INLINE, 0x0649},
+       {0xFBEA, 0, 2 | DECOMP_NO_COMPOSE, 3628},       /* compatibility mapping */
+       {0xFBEB, 0, 2 | DECOMP_NO_COMPOSE, 3630},       /* compatibility mapping */
+       {0xFBEC, 0, 2 | DECOMP_NO_COMPOSE, 3632},       /* compatibility mapping */
+       {0xFBED, 0, 2 | DECOMP_NO_COMPOSE, 3634},       /* compatibility mapping */
+       {0xFBEE, 0, 2 | DECOMP_NO_COMPOSE, 3636},       /* compatibility mapping */
+       {0xFBEF, 0, 2 | DECOMP_NO_COMPOSE, 3638},       /* compatibility mapping */
+       {0xFBF0, 0, 2 | DECOMP_NO_COMPOSE, 3640},       /* compatibility mapping */
+       {0xFBF1, 0, 2 | DECOMP_NO_COMPOSE, 3642},       /* compatibility mapping */
+       {0xFBF2, 0, 2 | DECOMP_NO_COMPOSE, 3644},       /* compatibility mapping */
+       {0xFBF3, 0, 2 | DECOMP_NO_COMPOSE, 3646},       /* compatibility mapping */
+       {0xFBF4, 0, 2 | DECOMP_NO_COMPOSE, 3648},       /* compatibility mapping */
+       {0xFBF5, 0, 2 | DECOMP_NO_COMPOSE, 3650},       /* compatibility mapping */
+       {0xFBF6, 0, 2 | DECOMP_NO_COMPOSE, 3652},       /* compatibility mapping */
+       {0xFBF7, 0, 2 | DECOMP_NO_COMPOSE, 3654},       /* compatibility mapping */
+       {0xFBF8, 0, 2 | DECOMP_NO_COMPOSE, 3656},       /* compatibility mapping */
+       {0xFBF9, 0, 2 | DECOMP_NO_COMPOSE, 3658},       /* compatibility mapping */
+       {0xFBFA, 0, 2 | DECOMP_NO_COMPOSE, 3660},       /* compatibility mapping */
+       {0xFBFB, 0, 2 | DECOMP_NO_COMPOSE, 3662},       /* compatibility mapping */
+       {0xFBFC, 0, 1 | DECOMP_INLINE, 0x06CC},
+       {0xFBFD, 0, 1 | DECOMP_INLINE, 0x06CC},
+       {0xFBFE, 0, 1 | DECOMP_INLINE, 0x06CC},
+       {0xFBFF, 0, 1 | DECOMP_INLINE, 0x06CC},
+       {0xFC00, 0, 2 | DECOMP_NO_COMPOSE, 3664},       /* compatibility mapping */
+       {0xFC01, 0, 2 | DECOMP_NO_COMPOSE, 3666},       /* compatibility mapping */
+       {0xFC02, 0, 2 | DECOMP_NO_COMPOSE, 3668},       /* compatibility mapping */
+       {0xFC03, 0, 2 | DECOMP_NO_COMPOSE, 3670},       /* compatibility mapping */
+       {0xFC04, 0, 2 | DECOMP_NO_COMPOSE, 3672},       /* compatibility mapping */
+       {0xFC05, 0, 2 | DECOMP_NO_COMPOSE, 3674},       /* compatibility mapping */
+       {0xFC06, 0, 2 | DECOMP_NO_COMPOSE, 3676},       /* compatibility mapping */
+       {0xFC07, 0, 2 | DECOMP_NO_COMPOSE, 3678},       /* compatibility mapping */
+       {0xFC08, 0, 2 | DECOMP_NO_COMPOSE, 3680},       /* compatibility mapping */
+       {0xFC09, 0, 2 | DECOMP_NO_COMPOSE, 3682},       /* compatibility mapping */
+       {0xFC0A, 0, 2 | DECOMP_NO_COMPOSE, 3684},       /* compatibility mapping */
+       {0xFC0B, 0, 2 | DECOMP_NO_COMPOSE, 3686},       /* compatibility mapping */
+       {0xFC0C, 0, 2 | DECOMP_NO_COMPOSE, 3688},       /* compatibility mapping */
+       {0xFC0D, 0, 2 | DECOMP_NO_COMPOSE, 3690},       /* compatibility mapping */
+       {0xFC0E, 0, 2 | DECOMP_NO_COMPOSE, 3692},       /* compatibility mapping */
+       {0xFC0F, 0, 2 | DECOMP_NO_COMPOSE, 3694},       /* compatibility mapping */
+       {0xFC10, 0, 2 | DECOMP_NO_COMPOSE, 3696},       /* compatibility mapping */
+       {0xFC11, 0, 2 | DECOMP_NO_COMPOSE, 3698},       /* compatibility mapping */
+       {0xFC12, 0, 2 | DECOMP_NO_COMPOSE, 3700},       /* compatibility mapping */
+       {0xFC13, 0, 2 | DECOMP_NO_COMPOSE, 3702},       /* compatibility mapping */
+       {0xFC14, 0, 2 | DECOMP_NO_COMPOSE, 3704},       /* compatibility mapping */
+       {0xFC15, 0, 2 | DECOMP_NO_COMPOSE, 3706},       /* compatibility mapping */
+       {0xFC16, 0, 2 | DECOMP_NO_COMPOSE, 3708},       /* compatibility mapping */
+       {0xFC17, 0, 2 | DECOMP_NO_COMPOSE, 3710},       /* compatibility mapping */
+       {0xFC18, 0, 2 | DECOMP_NO_COMPOSE, 3712},       /* compatibility mapping */
+       {0xFC19, 0, 2 | DECOMP_NO_COMPOSE, 3714},       /* compatibility mapping */
+       {0xFC1A, 0, 2 | DECOMP_NO_COMPOSE, 3716},       /* compatibility mapping */
+       {0xFC1B, 0, 2 | DECOMP_NO_COMPOSE, 3718},       /* compatibility mapping */
+       {0xFC1C, 0, 2 | DECOMP_NO_COMPOSE, 3720},       /* compatibility mapping */
+       {0xFC1D, 0, 2 | DECOMP_NO_COMPOSE, 3722},       /* compatibility mapping */
+       {0xFC1E, 0, 2 | DECOMP_NO_COMPOSE, 3724},       /* compatibility mapping */
+       {0xFC1F, 0, 2 | DECOMP_NO_COMPOSE, 3726},       /* compatibility mapping */
+       {0xFC20, 0, 2 | DECOMP_NO_COMPOSE, 3728},       /* compatibility mapping */
+       {0xFC21, 0, 2 | DECOMP_NO_COMPOSE, 3730},       /* compatibility mapping */
+       {0xFC22, 0, 2 | DECOMP_NO_COMPOSE, 3732},       /* compatibility mapping */
+       {0xFC23, 0, 2 | DECOMP_NO_COMPOSE, 3734},       /* compatibility mapping */
+       {0xFC24, 0, 2 | DECOMP_NO_COMPOSE, 3736},       /* compatibility mapping */
+       {0xFC25, 0, 2 | DECOMP_NO_COMPOSE, 3738},       /* compatibility mapping */
+       {0xFC26, 0, 2 | DECOMP_NO_COMPOSE, 3740},       /* compatibility mapping */
+       {0xFC27, 0, 2 | DECOMP_NO_COMPOSE, 3742},       /* compatibility mapping */
+       {0xFC28, 0, 2 | DECOMP_NO_COMPOSE, 3744},       /* compatibility mapping */
+       {0xFC29, 0, 2 | DECOMP_NO_COMPOSE, 3746},       /* compatibility mapping */
+       {0xFC2A, 0, 2 | DECOMP_NO_COMPOSE, 3748},       /* compatibility mapping */
+       {0xFC2B, 0, 2 | DECOMP_NO_COMPOSE, 3750},       /* compatibility mapping */
+       {0xFC2C, 0, 2 | DECOMP_NO_COMPOSE, 3752},       /* compatibility mapping */
+       {0xFC2D, 0, 2 | DECOMP_NO_COMPOSE, 3754},       /* compatibility mapping */
+       {0xFC2E, 0, 2 | DECOMP_NO_COMPOSE, 3756},       /* compatibility mapping */
+       {0xFC2F, 0, 2 | DECOMP_NO_COMPOSE, 3758},       /* compatibility mapping */
+       {0xFC30, 0, 2 | DECOMP_NO_COMPOSE, 3760},       /* compatibility mapping */
+       {0xFC31, 0, 2 | DECOMP_NO_COMPOSE, 3762},       /* compatibility mapping */
+       {0xFC32, 0, 2 | DECOMP_NO_COMPOSE, 3764},       /* compatibility mapping */
+       {0xFC33, 0, 2 | DECOMP_NO_COMPOSE, 3766},       /* compatibility mapping */
+       {0xFC34, 0, 2 | DECOMP_NO_COMPOSE, 3768},       /* compatibility mapping */
+       {0xFC35, 0, 2 | DECOMP_NO_COMPOSE, 3770},       /* compatibility mapping */
+       {0xFC36, 0, 2 | DECOMP_NO_COMPOSE, 3772},       /* compatibility mapping */
+       {0xFC37, 0, 2 | DECOMP_NO_COMPOSE, 3774},       /* compatibility mapping */
+       {0xFC38, 0, 2 | DECOMP_NO_COMPOSE, 3776},       /* compatibility mapping */
+       {0xFC39, 0, 2 | DECOMP_NO_COMPOSE, 3778},       /* compatibility mapping */
+       {0xFC3A, 0, 2 | DECOMP_NO_COMPOSE, 3780},       /* compatibility mapping */
+       {0xFC3B, 0, 2 | DECOMP_NO_COMPOSE, 3782},       /* compatibility mapping */
+       {0xFC3C, 0, 2 | DECOMP_NO_COMPOSE, 3784},       /* compatibility mapping */
+       {0xFC3D, 0, 2 | DECOMP_NO_COMPOSE, 3786},       /* compatibility mapping */
+       {0xFC3E, 0, 2 | DECOMP_NO_COMPOSE, 3788},       /* compatibility mapping */
+       {0xFC3F, 0, 2 | DECOMP_NO_COMPOSE, 3790},       /* compatibility mapping */
+       {0xFC40, 0, 2 | DECOMP_NO_COMPOSE, 3792},       /* compatibility mapping */
+       {0xFC41, 0, 2 | DECOMP_NO_COMPOSE, 3794},       /* compatibility mapping */
+       {0xFC42, 0, 2 | DECOMP_NO_COMPOSE, 3796},       /* compatibility mapping */
+       {0xFC43, 0, 2 | DECOMP_NO_COMPOSE, 3798},       /* compatibility mapping */
+       {0xFC44, 0, 2 | DECOMP_NO_COMPOSE, 3800},       /* compatibility mapping */
+       {0xFC45, 0, 2 | DECOMP_NO_COMPOSE, 3802},       /* compatibility mapping */
+       {0xFC46, 0, 2 | DECOMP_NO_COMPOSE, 3804},       /* compatibility mapping */
+       {0xFC47, 0, 2 | DECOMP_NO_COMPOSE, 3806},       /* compatibility mapping */
+       {0xFC48, 0, 2 | DECOMP_NO_COMPOSE, 3808},       /* compatibility mapping */
+       {0xFC49, 0, 2 | DECOMP_NO_COMPOSE, 3810},       /* compatibility mapping */
+       {0xFC4A, 0, 2 | DECOMP_NO_COMPOSE, 3812},       /* compatibility mapping */
+       {0xFC4B, 0, 2 | DECOMP_NO_COMPOSE, 3814},       /* compatibility mapping */
+       {0xFC4C, 0, 2 | DECOMP_NO_COMPOSE, 3816},       /* compatibility mapping */
+       {0xFC4D, 0, 2 | DECOMP_NO_COMPOSE, 3818},       /* compatibility mapping */
+       {0xFC4E, 0, 2 | DECOMP_NO_COMPOSE, 3820},       /* compatibility mapping */
+       {0xFC4F, 0, 2 | DECOMP_NO_COMPOSE, 3822},       /* compatibility mapping */
+       {0xFC50, 0, 2 | DECOMP_NO_COMPOSE, 3824},       /* compatibility mapping */
+       {0xFC51, 0, 2 | DECOMP_NO_COMPOSE, 3826},       /* compatibility mapping */
+       {0xFC52, 0, 2 | DECOMP_NO_COMPOSE, 3828},       /* compatibility mapping */
+       {0xFC53, 0, 2 | DECOMP_NO_COMPOSE, 3830},       /* compatibility mapping */
+       {0xFC54, 0, 2 | DECOMP_NO_COMPOSE, 3832},       /* compatibility mapping */
+       {0xFC55, 0, 2 | DECOMP_NO_COMPOSE, 3834},       /* compatibility mapping */
+       {0xFC56, 0, 2 | DECOMP_NO_COMPOSE, 3836},       /* compatibility mapping */
+       {0xFC57, 0, 2 | DECOMP_NO_COMPOSE, 3838},       /* compatibility mapping */
+       {0xFC58, 0, 2 | DECOMP_NO_COMPOSE, 3840},       /* compatibility mapping */
+       {0xFC59, 0, 2 | DECOMP_NO_COMPOSE, 3842},       /* compatibility mapping */
+       {0xFC5A, 0, 2 | DECOMP_NO_COMPOSE, 3844},       /* compatibility mapping */
+       {0xFC5B, 0, 2 | DECOMP_NO_COMPOSE, 3846},       /* compatibility mapping */
+       {0xFC5C, 0, 2 | DECOMP_NO_COMPOSE, 3848},       /* compatibility mapping */
+       {0xFC5D, 0, 2 | DECOMP_NO_COMPOSE, 3850},       /* compatibility mapping */
+       {0xFC5E, 0, 3, 3852},
+       {0xFC5F, 0, 3, 3855},
+       {0xFC60, 0, 3, 3858},
+       {0xFC61, 0, 3, 3861},
+       {0xFC62, 0, 3, 3864},
+       {0xFC63, 0, 3, 3867},
+       {0xFC64, 0, 2 | DECOMP_NO_COMPOSE, 3870},       /* compatibility mapping */
+       {0xFC65, 0, 2 | DECOMP_NO_COMPOSE, 3872},       /* compatibility mapping */
+       {0xFC66, 0, 2 | DECOMP_NO_COMPOSE, 3874},       /* compatibility mapping */
+       {0xFC67, 0, 2 | DECOMP_NO_COMPOSE, 3876},       /* compatibility mapping */
+       {0xFC68, 0, 2 | DECOMP_NO_COMPOSE, 3878},       /* compatibility mapping */
+       {0xFC69, 0, 2 | DECOMP_NO_COMPOSE, 3880},       /* compatibility mapping */
+       {0xFC6A, 0, 2 | DECOMP_NO_COMPOSE, 3882},       /* compatibility mapping */
+       {0xFC6B, 0, 2 | DECOMP_NO_COMPOSE, 3884},       /* compatibility mapping */
+       {0xFC6C, 0, 2 | DECOMP_NO_COMPOSE, 3886},       /* compatibility mapping */
+       {0xFC6D, 0, 2 | DECOMP_NO_COMPOSE, 3888},       /* compatibility mapping */
+       {0xFC6E, 0, 2 | DECOMP_NO_COMPOSE, 3890},       /* compatibility mapping */
+       {0xFC6F, 0, 2 | DECOMP_NO_COMPOSE, 3892},       /* compatibility mapping */
+       {0xFC70, 0, 2 | DECOMP_NO_COMPOSE, 3894},       /* compatibility mapping */
+       {0xFC71, 0, 2 | DECOMP_NO_COMPOSE, 3896},       /* compatibility mapping */
+       {0xFC72, 0, 2 | DECOMP_NO_COMPOSE, 3898},       /* compatibility mapping */
+       {0xFC73, 0, 2 | DECOMP_NO_COMPOSE, 3900},       /* compatibility mapping */
+       {0xFC74, 0, 2 | DECOMP_NO_COMPOSE, 3902},       /* compatibility mapping */
+       {0xFC75, 0, 2 | DECOMP_NO_COMPOSE, 3904},       /* compatibility mapping */
+       {0xFC76, 0, 2 | DECOMP_NO_COMPOSE, 3906},       /* compatibility mapping */
+       {0xFC77, 0, 2 | DECOMP_NO_COMPOSE, 3908},       /* compatibility mapping */
+       {0xFC78, 0, 2 | DECOMP_NO_COMPOSE, 3910},       /* compatibility mapping */
+       {0xFC79, 0, 2 | DECOMP_NO_COMPOSE, 3912},       /* compatibility mapping */
+       {0xFC7A, 0, 2 | DECOMP_NO_COMPOSE, 3914},       /* compatibility mapping */
+       {0xFC7B, 0, 2 | DECOMP_NO_COMPOSE, 3916},       /* compatibility mapping */
+       {0xFC7C, 0, 2 | DECOMP_NO_COMPOSE, 3918},       /* compatibility mapping */
+       {0xFC7D, 0, 2 | DECOMP_NO_COMPOSE, 3920},       /* compatibility mapping */
+       {0xFC7E, 0, 2 | DECOMP_NO_COMPOSE, 3922},       /* compatibility mapping */
+       {0xFC7F, 0, 2 | DECOMP_NO_COMPOSE, 3924},       /* compatibility mapping */
+       {0xFC80, 0, 2 | DECOMP_NO_COMPOSE, 3926},       /* compatibility mapping */
+       {0xFC81, 0, 2 | DECOMP_NO_COMPOSE, 3928},       /* compatibility mapping */
+       {0xFC82, 0, 2 | DECOMP_NO_COMPOSE, 3930},       /* compatibility mapping */
+       {0xFC83, 0, 2 | DECOMP_NO_COMPOSE, 3932},       /* compatibility mapping */
+       {0xFC84, 0, 2 | DECOMP_NO_COMPOSE, 3934},       /* compatibility mapping */
+       {0xFC85, 0, 2 | DECOMP_NO_COMPOSE, 3936},       /* compatibility mapping */
+       {0xFC86, 0, 2 | DECOMP_NO_COMPOSE, 3938},       /* compatibility mapping */
+       {0xFC87, 0, 2 | DECOMP_NO_COMPOSE, 3940},       /* compatibility mapping */
+       {0xFC88, 0, 2 | DECOMP_NO_COMPOSE, 3942},       /* compatibility mapping */
+       {0xFC89, 0, 2 | DECOMP_NO_COMPOSE, 3944},       /* compatibility mapping */
+       {0xFC8A, 0, 2 | DECOMP_NO_COMPOSE, 3946},       /* compatibility mapping */
+       {0xFC8B, 0, 2 | DECOMP_NO_COMPOSE, 3948},       /* compatibility mapping */
+       {0xFC8C, 0, 2 | DECOMP_NO_COMPOSE, 3950},       /* compatibility mapping */
+       {0xFC8D, 0, 2 | DECOMP_NO_COMPOSE, 3952},       /* compatibility mapping */
+       {0xFC8E, 0, 2 | DECOMP_NO_COMPOSE, 3954},       /* compatibility mapping */
+       {0xFC8F, 0, 2 | DECOMP_NO_COMPOSE, 3956},       /* compatibility mapping */
+       {0xFC90, 0, 2 | DECOMP_NO_COMPOSE, 3958},       /* compatibility mapping */
+       {0xFC91, 0, 2 | DECOMP_NO_COMPOSE, 3960},       /* compatibility mapping */
+       {0xFC92, 0, 2 | DECOMP_NO_COMPOSE, 3962},       /* compatibility mapping */
+       {0xFC93, 0, 2 | DECOMP_NO_COMPOSE, 3964},       /* compatibility mapping */
+       {0xFC94, 0, 2 | DECOMP_NO_COMPOSE, 3966},       /* compatibility mapping */
+       {0xFC95, 0, 2 | DECOMP_NO_COMPOSE, 3968},       /* compatibility mapping */
+       {0xFC96, 0, 2 | DECOMP_NO_COMPOSE, 3970},       /* compatibility mapping */
+       {0xFC97, 0, 2 | DECOMP_NO_COMPOSE, 3972},       /* compatibility mapping */
+       {0xFC98, 0, 2 | DECOMP_NO_COMPOSE, 3974},       /* compatibility mapping */
+       {0xFC99, 0, 2 | DECOMP_NO_COMPOSE, 3976},       /* compatibility mapping */
+       {0xFC9A, 0, 2 | DECOMP_NO_COMPOSE, 3978},       /* compatibility mapping */
+       {0xFC9B, 0, 2 | DECOMP_NO_COMPOSE, 3980},       /* compatibility mapping */
+       {0xFC9C, 0, 2 | DECOMP_NO_COMPOSE, 3982},       /* compatibility mapping */
+       {0xFC9D, 0, 2 | DECOMP_NO_COMPOSE, 3984},       /* compatibility mapping */
+       {0xFC9E, 0, 2 | DECOMP_NO_COMPOSE, 3986},       /* compatibility mapping */
+       {0xFC9F, 0, 2 | DECOMP_NO_COMPOSE, 3988},       /* compatibility mapping */
+       {0xFCA0, 0, 2 | DECOMP_NO_COMPOSE, 3990},       /* compatibility mapping */
+       {0xFCA1, 0, 2 | DECOMP_NO_COMPOSE, 3992},       /* compatibility mapping */
+       {0xFCA2, 0, 2 | DECOMP_NO_COMPOSE, 3994},       /* compatibility mapping */
+       {0xFCA3, 0, 2 | DECOMP_NO_COMPOSE, 3996},       /* compatibility mapping */
+       {0xFCA4, 0, 2 | DECOMP_NO_COMPOSE, 3998},       /* compatibility mapping */
+       {0xFCA5, 0, 2 | DECOMP_NO_COMPOSE, 4000},       /* compatibility mapping */
+       {0xFCA6, 0, 2 | DECOMP_NO_COMPOSE, 4002},       /* compatibility mapping */
+       {0xFCA7, 0, 2 | DECOMP_NO_COMPOSE, 4004},       /* compatibility mapping */
+       {0xFCA8, 0, 2 | DECOMP_NO_COMPOSE, 4006},       /* compatibility mapping */
+       {0xFCA9, 0, 2 | DECOMP_NO_COMPOSE, 4008},       /* compatibility mapping */
+       {0xFCAA, 0, 2 | DECOMP_NO_COMPOSE, 4010},       /* compatibility mapping */
+       {0xFCAB, 0, 2 | DECOMP_NO_COMPOSE, 4012},       /* compatibility mapping */
+       {0xFCAC, 0, 2 | DECOMP_NO_COMPOSE, 4014},       /* compatibility mapping */
+       {0xFCAD, 0, 2 | DECOMP_NO_COMPOSE, 4016},       /* compatibility mapping */
+       {0xFCAE, 0, 2 | DECOMP_NO_COMPOSE, 4018},       /* compatibility mapping */
+       {0xFCAF, 0, 2 | DECOMP_NO_COMPOSE, 4020},       /* compatibility mapping */
+       {0xFCB0, 0, 2 | DECOMP_NO_COMPOSE, 4022},       /* compatibility mapping */
+       {0xFCB1, 0, 2 | DECOMP_NO_COMPOSE, 4024},       /* compatibility mapping */
+       {0xFCB2, 0, 2 | DECOMP_NO_COMPOSE, 4026},       /* compatibility mapping */
+       {0xFCB3, 0, 2 | DECOMP_NO_COMPOSE, 4028},       /* compatibility mapping */
+       {0xFCB4, 0, 2 | DECOMP_NO_COMPOSE, 4030},       /* compatibility mapping */
+       {0xFCB5, 0, 2 | DECOMP_NO_COMPOSE, 4032},       /* compatibility mapping */
+       {0xFCB6, 0, 2 | DECOMP_NO_COMPOSE, 4034},       /* compatibility mapping */
+       {0xFCB7, 0, 2 | DECOMP_NO_COMPOSE, 4036},       /* compatibility mapping */
+       {0xFCB8, 0, 2 | DECOMP_NO_COMPOSE, 4038},       /* compatibility mapping */
+       {0xFCB9, 0, 2 | DECOMP_NO_COMPOSE, 4040},       /* compatibility mapping */
+       {0xFCBA, 0, 2 | DECOMP_NO_COMPOSE, 4042},       /* compatibility mapping */
+       {0xFCBB, 0, 2 | DECOMP_NO_COMPOSE, 4044},       /* compatibility mapping */
+       {0xFCBC, 0, 2 | DECOMP_NO_COMPOSE, 4046},       /* compatibility mapping */
+       {0xFCBD, 0, 2 | DECOMP_NO_COMPOSE, 4048},       /* compatibility mapping */
+       {0xFCBE, 0, 2 | DECOMP_NO_COMPOSE, 4050},       /* compatibility mapping */
+       {0xFCBF, 0, 2 | DECOMP_NO_COMPOSE, 4052},       /* compatibility mapping */
+       {0xFCC0, 0, 2 | DECOMP_NO_COMPOSE, 4054},       /* compatibility mapping */
+       {0xFCC1, 0, 2 | DECOMP_NO_COMPOSE, 4056},       /* compatibility mapping */
+       {0xFCC2, 0, 2 | DECOMP_NO_COMPOSE, 4058},       /* compatibility mapping */
+       {0xFCC3, 0, 2 | DECOMP_NO_COMPOSE, 4060},       /* compatibility mapping */
+       {0xFCC4, 0, 2 | DECOMP_NO_COMPOSE, 4062},       /* compatibility mapping */
+       {0xFCC5, 0, 2 | DECOMP_NO_COMPOSE, 4064},       /* compatibility mapping */
+       {0xFCC6, 0, 2 | DECOMP_NO_COMPOSE, 4066},       /* compatibility mapping */
+       {0xFCC7, 0, 2 | DECOMP_NO_COMPOSE, 4068},       /* compatibility mapping */
+       {0xFCC8, 0, 2 | DECOMP_NO_COMPOSE, 4070},       /* compatibility mapping */
+       {0xFCC9, 0, 2 | DECOMP_NO_COMPOSE, 4072},       /* compatibility mapping */
+       {0xFCCA, 0, 2 | DECOMP_NO_COMPOSE, 4074},       /* compatibility mapping */
+       {0xFCCB, 0, 2 | DECOMP_NO_COMPOSE, 4076},       /* compatibility mapping */
+       {0xFCCC, 0, 2 | DECOMP_NO_COMPOSE, 4078},       /* compatibility mapping */
+       {0xFCCD, 0, 2 | DECOMP_NO_COMPOSE, 4080},       /* compatibility mapping */
+       {0xFCCE, 0, 2 | DECOMP_NO_COMPOSE, 4082},       /* compatibility mapping */
+       {0xFCCF, 0, 2 | DECOMP_NO_COMPOSE, 4084},       /* compatibility mapping */
+       {0xFCD0, 0, 2 | DECOMP_NO_COMPOSE, 4086},       /* compatibility mapping */
+       {0xFCD1, 0, 2 | DECOMP_NO_COMPOSE, 4088},       /* compatibility mapping */
+       {0xFCD2, 0, 2 | DECOMP_NO_COMPOSE, 4090},       /* compatibility mapping */
+       {0xFCD3, 0, 2 | DECOMP_NO_COMPOSE, 4092},       /* compatibility mapping */
+       {0xFCD4, 0, 2 | DECOMP_NO_COMPOSE, 4094},       /* compatibility mapping */
+       {0xFCD5, 0, 2 | DECOMP_NO_COMPOSE, 4096},       /* compatibility mapping */
+       {0xFCD6, 0, 2 | DECOMP_NO_COMPOSE, 4098},       /* compatibility mapping */
+       {0xFCD7, 0, 2 | DECOMP_NO_COMPOSE, 4100},       /* compatibility mapping */
+       {0xFCD8, 0, 2 | DECOMP_NO_COMPOSE, 4102},       /* compatibility mapping */
+       {0xFCD9, 0, 2 | DECOMP_NO_COMPOSE, 4104},       /* compatibility mapping */
+       {0xFCDA, 0, 2 | DECOMP_NO_COMPOSE, 4106},       /* compatibility mapping */
+       {0xFCDB, 0, 2 | DECOMP_NO_COMPOSE, 4108},       /* compatibility mapping */
+       {0xFCDC, 0, 2 | DECOMP_NO_COMPOSE, 4110},       /* compatibility mapping */
+       {0xFCDD, 0, 2 | DECOMP_NO_COMPOSE, 4112},       /* compatibility mapping */
+       {0xFCDE, 0, 2 | DECOMP_NO_COMPOSE, 4114},       /* compatibility mapping */
+       {0xFCDF, 0, 2 | DECOMP_NO_COMPOSE, 4116},       /* compatibility mapping */
+       {0xFCE0, 0, 2 | DECOMP_NO_COMPOSE, 4118},       /* compatibility mapping */
+       {0xFCE1, 0, 2 | DECOMP_NO_COMPOSE, 4120},       /* compatibility mapping */
+       {0xFCE2, 0, 2 | DECOMP_NO_COMPOSE, 4122},       /* compatibility mapping */
+       {0xFCE3, 0, 2 | DECOMP_NO_COMPOSE, 4124},       /* compatibility mapping */
+       {0xFCE4, 0, 2 | DECOMP_NO_COMPOSE, 4126},       /* compatibility mapping */
+       {0xFCE5, 0, 2 | DECOMP_NO_COMPOSE, 4128},       /* compatibility mapping */
+       {0xFCE6, 0, 2 | DECOMP_NO_COMPOSE, 4130},       /* compatibility mapping */
+       {0xFCE7, 0, 2 | DECOMP_NO_COMPOSE, 4132},       /* compatibility mapping */
+       {0xFCE8, 0, 2 | DECOMP_NO_COMPOSE, 4134},       /* compatibility mapping */
+       {0xFCE9, 0, 2 | DECOMP_NO_COMPOSE, 4136},       /* compatibility mapping */
+       {0xFCEA, 0, 2 | DECOMP_NO_COMPOSE, 4138},       /* compatibility mapping */
+       {0xFCEB, 0, 2 | DECOMP_NO_COMPOSE, 4140},       /* compatibility mapping */
+       {0xFCEC, 0, 2 | DECOMP_NO_COMPOSE, 4142},       /* compatibility mapping */
+       {0xFCED, 0, 2 | DECOMP_NO_COMPOSE, 4144},       /* compatibility mapping */
+       {0xFCEE, 0, 2 | DECOMP_NO_COMPOSE, 4146},       /* compatibility mapping */
+       {0xFCEF, 0, 2 | DECOMP_NO_COMPOSE, 4148},       /* compatibility mapping */
+       {0xFCF0, 0, 2 | DECOMP_NO_COMPOSE, 4150},       /* compatibility mapping */
+       {0xFCF1, 0, 2 | DECOMP_NO_COMPOSE, 4152},       /* compatibility mapping */
+       {0xFCF2, 0, 3, 4154},
+       {0xFCF3, 0, 3, 4157},
+       {0xFCF4, 0, 3, 4160},
+       {0xFCF5, 0, 2 | DECOMP_NO_COMPOSE, 4163},       /* compatibility mapping */
+       {0xFCF6, 0, 2 | DECOMP_NO_COMPOSE, 4165},       /* compatibility mapping */
+       {0xFCF7, 0, 2 | DECOMP_NO_COMPOSE, 4167},       /* compatibility mapping */
+       {0xFCF8, 0, 2 | DECOMP_NO_COMPOSE, 4169},       /* compatibility mapping */
+       {0xFCF9, 0, 2 | DECOMP_NO_COMPOSE, 4171},       /* compatibility mapping */
+       {0xFCFA, 0, 2 | DECOMP_NO_COMPOSE, 4173},       /* compatibility mapping */
+       {0xFCFB, 0, 2 | DECOMP_NO_COMPOSE, 4175},       /* compatibility mapping */
+       {0xFCFC, 0, 2 | DECOMP_NO_COMPOSE, 4177},       /* compatibility mapping */
+       {0xFCFD, 0, 2 | DECOMP_NO_COMPOSE, 4179},       /* compatibility mapping */
+       {0xFCFE, 0, 2 | DECOMP_NO_COMPOSE, 4181},       /* compatibility mapping */
+       {0xFCFF, 0, 2 | DECOMP_NO_COMPOSE, 4183},       /* compatibility mapping */
+       {0xFD00, 0, 2 | DECOMP_NO_COMPOSE, 4185},       /* compatibility mapping */
+       {0xFD01, 0, 2 | DECOMP_NO_COMPOSE, 4187},       /* compatibility mapping */
+       {0xFD02, 0, 2 | DECOMP_NO_COMPOSE, 4189},       /* compatibility mapping */
+       {0xFD03, 0, 2 | DECOMP_NO_COMPOSE, 4191},       /* compatibility mapping */
+       {0xFD04, 0, 2 | DECOMP_NO_COMPOSE, 4193},       /* compatibility mapping */
+       {0xFD05, 0, 2 | DECOMP_NO_COMPOSE, 4195},       /* compatibility mapping */
+       {0xFD06, 0, 2 | DECOMP_NO_COMPOSE, 4197},       /* compatibility mapping */
+       {0xFD07, 0, 2 | DECOMP_NO_COMPOSE, 4199},       /* compatibility mapping */
+       {0xFD08, 0, 2 | DECOMP_NO_COMPOSE, 4201},       /* compatibility mapping */
+       {0xFD09, 0, 2 | DECOMP_NO_COMPOSE, 4203},       /* compatibility mapping */
+       {0xFD0A, 0, 2 | DECOMP_NO_COMPOSE, 4205},       /* compatibility mapping */
+       {0xFD0B, 0, 2 | DECOMP_NO_COMPOSE, 4207},       /* compatibility mapping */
+       {0xFD0C, 0, 2 | DECOMP_NO_COMPOSE, 4209},       /* compatibility mapping */
+       {0xFD0D, 0, 2 | DECOMP_NO_COMPOSE, 4211},       /* compatibility mapping */
+       {0xFD0E, 0, 2 | DECOMP_NO_COMPOSE, 4213},       /* compatibility mapping */
+       {0xFD0F, 0, 2 | DECOMP_NO_COMPOSE, 4215},       /* compatibility mapping */
+       {0xFD10, 0, 2 | DECOMP_NO_COMPOSE, 4217},       /* compatibility mapping */
+       {0xFD11, 0, 2 | DECOMP_NO_COMPOSE, 4219},       /* compatibility mapping */
+       {0xFD12, 0, 2 | DECOMP_NO_COMPOSE, 4221},       /* compatibility mapping */
+       {0xFD13, 0, 2 | DECOMP_NO_COMPOSE, 4223},       /* compatibility mapping */
+       {0xFD14, 0, 2 | DECOMP_NO_COMPOSE, 4225},       /* compatibility mapping */
+       {0xFD15, 0, 2 | DECOMP_NO_COMPOSE, 4227},       /* compatibility mapping */
+       {0xFD16, 0, 2 | DECOMP_NO_COMPOSE, 4229},       /* compatibility mapping */
+       {0xFD17, 0, 2 | DECOMP_NO_COMPOSE, 4231},       /* compatibility mapping */
+       {0xFD18, 0, 2 | DECOMP_NO_COMPOSE, 4233},       /* compatibility mapping */
+       {0xFD19, 0, 2 | DECOMP_NO_COMPOSE, 4235},       /* compatibility mapping */
+       {0xFD1A, 0, 2 | DECOMP_NO_COMPOSE, 4237},       /* compatibility mapping */
+       {0xFD1B, 0, 2 | DECOMP_NO_COMPOSE, 4239},       /* compatibility mapping */
+       {0xFD1C, 0, 2 | DECOMP_NO_COMPOSE, 4241},       /* compatibility mapping */
+       {0xFD1D, 0, 2 | DECOMP_NO_COMPOSE, 4243},       /* compatibility mapping */
+       {0xFD1E, 0, 2 | DECOMP_NO_COMPOSE, 4245},       /* compatibility mapping */
+       {0xFD1F, 0, 2 | DECOMP_NO_COMPOSE, 4247},       /* compatibility mapping */
+       {0xFD20, 0, 2 | DECOMP_NO_COMPOSE, 4249},       /* compatibility mapping */
+       {0xFD21, 0, 2 | DECOMP_NO_COMPOSE, 4251},       /* compatibility mapping */
+       {0xFD22, 0, 2 | DECOMP_NO_COMPOSE, 4253},       /* compatibility mapping */
+       {0xFD23, 0, 2 | DECOMP_NO_COMPOSE, 4255},       /* compatibility mapping */
+       {0xFD24, 0, 2 | DECOMP_NO_COMPOSE, 4257},       /* compatibility mapping */
+       {0xFD25, 0, 2 | DECOMP_NO_COMPOSE, 4259},       /* compatibility mapping */
+       {0xFD26, 0, 2 | DECOMP_NO_COMPOSE, 4261},       /* compatibility mapping */
+       {0xFD27, 0, 2 | DECOMP_NO_COMPOSE, 4263},       /* compatibility mapping */
+       {0xFD28, 0, 2 | DECOMP_NO_COMPOSE, 4265},       /* compatibility mapping */
+       {0xFD29, 0, 2 | DECOMP_NO_COMPOSE, 4267},       /* compatibility mapping */
+       {0xFD2A, 0, 2 | DECOMP_NO_COMPOSE, 4269},       /* compatibility mapping */
+       {0xFD2B, 0, 2 | DECOMP_NO_COMPOSE, 4271},       /* compatibility mapping */
+       {0xFD2C, 0, 2 | DECOMP_NO_COMPOSE, 4273},       /* compatibility mapping */
+       {0xFD2D, 0, 2 | DECOMP_NO_COMPOSE, 4275},       /* compatibility mapping */
+       {0xFD2E, 0, 2 | DECOMP_NO_COMPOSE, 4277},       /* compatibility mapping */
+       {0xFD2F, 0, 2 | DECOMP_NO_COMPOSE, 4279},       /* compatibility mapping */
+       {0xFD30, 0, 2 | DECOMP_NO_COMPOSE, 4281},       /* compatibility mapping */
+       {0xFD31, 0, 2 | DECOMP_NO_COMPOSE, 4283},       /* compatibility mapping */
+       {0xFD32, 0, 2 | DECOMP_NO_COMPOSE, 4285},       /* compatibility mapping */
+       {0xFD33, 0, 2 | DECOMP_NO_COMPOSE, 4287},       /* compatibility mapping */
+       {0xFD34, 0, 2 | DECOMP_NO_COMPOSE, 4289},       /* compatibility mapping */
+       {0xFD35, 0, 2 | DECOMP_NO_COMPOSE, 4291},       /* compatibility mapping */
+       {0xFD36, 0, 2 | DECOMP_NO_COMPOSE, 4293},       /* compatibility mapping */
+       {0xFD37, 0, 2 | DECOMP_NO_COMPOSE, 4295},       /* compatibility mapping */
+       {0xFD38, 0, 2 | DECOMP_NO_COMPOSE, 4297},       /* compatibility mapping */
+       {0xFD39, 0, 2 | DECOMP_NO_COMPOSE, 4299},       /* compatibility mapping */
+       {0xFD3A, 0, 2 | DECOMP_NO_COMPOSE, 4301},       /* compatibility mapping */
+       {0xFD3B, 0, 2 | DECOMP_NO_COMPOSE, 4303},       /* compatibility mapping */
+       {0xFD3C, 0, 2 | DECOMP_NO_COMPOSE, 4305},       /* compatibility mapping */
+       {0xFD3D, 0, 2 | DECOMP_NO_COMPOSE, 4307},       /* compatibility mapping */
+       {0xFD50, 0, 3, 4309},
+       {0xFD51, 0, 3, 4312},
+       {0xFD52, 0, 3, 4315},
+       {0xFD53, 0, 3, 4318},
+       {0xFD54, 0, 3, 4321},
+       {0xFD55, 0, 3, 4324},
+       {0xFD56, 0, 3, 4327},
+       {0xFD57, 0, 3, 4330},
+       {0xFD58, 0, 3, 4333},
+       {0xFD59, 0, 3, 4336},
+       {0xFD5A, 0, 3, 4339},
+       {0xFD5B, 0, 3, 4342},
+       {0xFD5C, 0, 3, 4345},
+       {0xFD5D, 0, 3, 4348},
+       {0xFD5E, 0, 3, 4351},
+       {0xFD5F, 0, 3, 4354},
+       {0xFD60, 0, 3, 4357},
+       {0xFD61, 0, 3, 4360},
+       {0xFD62, 0, 3, 4363},
+       {0xFD63, 0, 3, 4366},
+       {0xFD64, 0, 3, 4369},
+       {0xFD65, 0, 3, 4372},
+       {0xFD66, 0, 3, 4375},
+       {0xFD67, 0, 3, 4378},
+       {0xFD68, 0, 3, 4381},
+       {0xFD69, 0, 3, 4384},
+       {0xFD6A, 0, 3, 4387},
+       {0xFD6B, 0, 3, 4390},
+       {0xFD6C, 0, 3, 4393},
+       {0xFD6D, 0, 3, 4396},
+       {0xFD6E, 0, 3, 4399},
+       {0xFD6F, 0, 3, 4402},
+       {0xFD70, 0, 3, 4405},
+       {0xFD71, 0, 3, 4408},
+       {0xFD72, 0, 3, 4411},
+       {0xFD73, 0, 3, 4414},
+       {0xFD74, 0, 3, 4417},
+       {0xFD75, 0, 3, 4420},
+       {0xFD76, 0, 3, 4423},
+       {0xFD77, 0, 3, 4426},
+       {0xFD78, 0, 3, 4429},
+       {0xFD79, 0, 3, 4432},
+       {0xFD7A, 0, 3, 4435},
+       {0xFD7B, 0, 3, 4438},
+       {0xFD7C, 0, 3, 4441},
+       {0xFD7D, 0, 3, 4444},
+       {0xFD7E, 0, 3, 4447},
+       {0xFD7F, 0, 3, 4450},
+       {0xFD80, 0, 3, 4453},
+       {0xFD81, 0, 3, 4456},
+       {0xFD82, 0, 3, 4459},
+       {0xFD83, 0, 3, 4462},
+       {0xFD84, 0, 3, 4465},
+       {0xFD85, 0, 3, 4468},
+       {0xFD86, 0, 3, 4471},
+       {0xFD87, 0, 3, 4474},
+       {0xFD88, 0, 3, 4477},
+       {0xFD89, 0, 3, 4480},
+       {0xFD8A, 0, 3, 4483},
+       {0xFD8B, 0, 3, 4486},
+       {0xFD8C, 0, 3, 4489},
+       {0xFD8D, 0, 3, 4492},
+       {0xFD8E, 0, 3, 4495},
+       {0xFD8F, 0, 3, 4498},
+       {0xFD92, 0, 3, 4501},
+       {0xFD93, 0, 3, 4504},
+       {0xFD94, 0, 3, 4507},
+       {0xFD95, 0, 3, 4510},
+       {0xFD96, 0, 3, 4513},
+       {0xFD97, 0, 3, 4516},
+       {0xFD98, 0, 3, 4519},
+       {0xFD99, 0, 3, 4522},
+       {0xFD9A, 0, 3, 4525},
+       {0xFD9B, 0, 3, 4528},
+       {0xFD9C, 0, 3, 4531},
+       {0xFD9D, 0, 3, 4534},
+       {0xFD9E, 0, 3, 4537},
+       {0xFD9F, 0, 3, 4540},
+       {0xFDA0, 0, 3, 4543},
+       {0xFDA1, 0, 3, 4546},
+       {0xFDA2, 0, 3, 4549},
+       {0xFDA3, 0, 3, 4552},
+       {0xFDA4, 0, 3, 4555},
+       {0xFDA5, 0, 3, 4558},
+       {0xFDA6, 0, 3, 4561},
+       {0xFDA7, 0, 3, 4564},
+       {0xFDA8, 0, 3, 4567},
+       {0xFDA9, 0, 3, 4570},
+       {0xFDAA, 0, 3, 4573},
+       {0xFDAB, 0, 3, 4576},
+       {0xFDAC, 0, 3, 4579},
+       {0xFDAD, 0, 3, 4582},
+       {0xFDAE, 0, 3, 4585},
+       {0xFDAF, 0, 3, 4588},
+       {0xFDB0, 0, 3, 4591},
+       {0xFDB1, 0, 3, 4594},
+       {0xFDB2, 0, 3, 4597},
+       {0xFDB3, 0, 3, 4600},
+       {0xFDB4, 0, 3, 4603},
+       {0xFDB5, 0, 3, 4606},
+       {0xFDB6, 0, 3, 4609},
+       {0xFDB7, 0, 3, 4612},
+       {0xFDB8, 0, 3, 4615},
+       {0xFDB9, 0, 3, 4618},
+       {0xFDBA, 0, 3, 4621},
+       {0xFDBB, 0, 3, 4624},
+       {0xFDBC, 0, 3, 4627},
+       {0xFDBD, 0, 3, 4630},
+       {0xFDBE, 0, 3, 4633},
+       {0xFDBF, 0, 3, 4636},
+       {0xFDC0, 0, 3, 4639},
+       {0xFDC1, 0, 3, 4642},
+       {0xFDC2, 0, 3, 4645},
+       {0xFDC3, 0, 3, 4648},
+       {0xFDC4, 0, 3, 4651},
+       {0xFDC5, 0, 3, 4654},
+       {0xFDC6, 0, 3, 4657},
+       {0xFDC7, 0, 3, 4660},
+       {0xFDF0, 0, 3, 4663},
+       {0xFDF1, 0, 3, 4666},
+       {0xFDF2, 0, 4, 4669},
+       {0xFDF3, 0, 4, 4673},
+       {0xFDF4, 0, 4, 4677},
+       {0xFDF5, 0, 4, 4681},
+       {0xFDF6, 0, 4, 4685},
+       {0xFDF7, 0, 4, 4689},
+       {0xFDF8, 0, 4, 4693},
+       {0xFDF9, 0, 3, 4697},
+       {0xFDFA, 0, 18, 4700},
+       {0xFDFB, 0, 8, 4718},
+       {0xFDFC, 0, 4, 4726},
+       {0xFE10, 0, 1 | DECOMP_INLINE, 0x002C},
+       {0xFE11, 0, 1 | DECOMP_INLINE, 0x3001},
+       {0xFE12, 0, 1 | DECOMP_INLINE, 0x3002},
+       {0xFE13, 0, 1 | DECOMP_INLINE, 0x003A},
+       {0xFE14, 0, 1 | DECOMP_INLINE, 0x003B},
+       {0xFE15, 0, 1 | DECOMP_INLINE, 0x0021},
+       {0xFE16, 0, 1 | DECOMP_INLINE, 0x003F},
+       {0xFE17, 0, 1 | DECOMP_INLINE, 0x3016},
+       {0xFE18, 0, 1 | DECOMP_INLINE, 0x3017},
+       {0xFE19, 0, 1 | DECOMP_INLINE, 0x2026},
+       {0xFE20, 230, 0, 0},
+       {0xFE21, 230, 0, 0},
+       {0xFE22, 230, 0, 0},
+       {0xFE23, 230, 0, 0},
+       {0xFE24, 230, 0, 0},
+       {0xFE25, 230, 0, 0},
+       {0xFE26, 230, 0, 0},
+       {0xFE27, 220, 0, 0},
+       {0xFE28, 220, 0, 0},
+       {0xFE29, 220, 0, 0},
+       {0xFE2A, 220, 0, 0},
+       {0xFE2B, 220, 0, 0},
+       {0xFE2C, 220, 0, 0},
+       {0xFE2D, 220, 0, 0},
+       {0xFE2E, 230, 0, 0},
+       {0xFE2F, 230, 0, 0},
+       {0xFE30, 0, 1 | DECOMP_INLINE, 0x2025},
+       {0xFE31, 0, 1 | DECOMP_INLINE, 0x2014},
+       {0xFE32, 0, 1 | DECOMP_INLINE, 0x2013},
+       {0xFE33, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFE34, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFE35, 0, 1 | DECOMP_INLINE, 0x0028},
+       {0xFE36, 0, 1 | DECOMP_INLINE, 0x0029},
+       {0xFE37, 0, 1 | DECOMP_INLINE, 0x007B},
+       {0xFE38, 0, 1 | DECOMP_INLINE, 0x007D},
+       {0xFE39, 0, 1 | DECOMP_INLINE, 0x3014},
+       {0xFE3A, 0, 1 | DECOMP_INLINE, 0x3015},
+       {0xFE3B, 0, 1 | DECOMP_INLINE, 0x3010},
+       {0xFE3C, 0, 1 | DECOMP_INLINE, 0x3011},
+       {0xFE3D, 0, 1 | DECOMP_INLINE, 0x300A},
+       {0xFE3E, 0, 1 | DECOMP_INLINE, 0x300B},
+       {0xFE3F, 0, 1 | DECOMP_INLINE, 0x3008},
+       {0xFE40, 0, 1 | DECOMP_INLINE, 0x3009},
+       {0xFE41, 0, 1 | DECOMP_INLINE, 0x300C},
+       {0xFE42, 0, 1 | DECOMP_INLINE, 0x300D},
+       {0xFE43, 0, 1 | DECOMP_INLINE, 0x300E},
+       {0xFE44, 0, 1 | DECOMP_INLINE, 0x300F},
+       {0xFE47, 0, 1 | DECOMP_INLINE, 0x005B},
+       {0xFE48, 0, 1 | DECOMP_INLINE, 0x005D},
+       {0xFE49, 0, 1 | DECOMP_INLINE, 0x203E},
+       {0xFE4A, 0, 1 | DECOMP_INLINE, 0x203E},
+       {0xFE4B, 0, 1 | DECOMP_INLINE, 0x203E},
+       {0xFE4C, 0, 1 | DECOMP_INLINE, 0x203E},
+       {0xFE4D, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFE4E, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFE4F, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFE50, 0, 1 | DECOMP_INLINE, 0x002C},
+       {0xFE51, 0, 1 | DECOMP_INLINE, 0x3001},
+       {0xFE52, 0, 1 | DECOMP_INLINE, 0x002E},
+       {0xFE54, 0, 1 | DECOMP_INLINE, 0x003B},
+       {0xFE55, 0, 1 | DECOMP_INLINE, 0x003A},
+       {0xFE56, 0, 1 | DECOMP_INLINE, 0x003F},
+       {0xFE57, 0, 1 | DECOMP_INLINE, 0x0021},
+       {0xFE58, 0, 1 | DECOMP_INLINE, 0x2014},
+       {0xFE59, 0, 1 | DECOMP_INLINE, 0x0028},
+       {0xFE5A, 0, 1 | DECOMP_INLINE, 0x0029},
+       {0xFE5B, 0, 1 | DECOMP_INLINE, 0x007B},
+       {0xFE5C, 0, 1 | DECOMP_INLINE, 0x007D},
+       {0xFE5D, 0, 1 | DECOMP_INLINE, 0x3014},
+       {0xFE5E, 0, 1 | DECOMP_INLINE, 0x3015},
+       {0xFE5F, 0, 1 | DECOMP_INLINE, 0x0023},
+       {0xFE60, 0, 1 | DECOMP_INLINE, 0x0026},
+       {0xFE61, 0, 1 | DECOMP_INLINE, 0x002A},
+       {0xFE62, 0, 1 | DECOMP_INLINE, 0x002B},
+       {0xFE63, 0, 1 | DECOMP_INLINE, 0x002D},
+       {0xFE64, 0, 1 | DECOMP_INLINE, 0x003C},
+       {0xFE65, 0, 1 | DECOMP_INLINE, 0x003E},
+       {0xFE66, 0, 1 | DECOMP_INLINE, 0x003D},
+       {0xFE68, 0, 1 | DECOMP_INLINE, 0x005C},
+       {0xFE69, 0, 1 | DECOMP_INLINE, 0x0024},
+       {0xFE6A, 0, 1 | DECOMP_INLINE, 0x0025},
+       {0xFE6B, 0, 1 | DECOMP_INLINE, 0x0040},
+       {0xFE70, 0, 2 | DECOMP_NO_COMPOSE, 4730},       /* compatibility mapping */
+       {0xFE71, 0, 2 | DECOMP_NO_COMPOSE, 4732},       /* compatibility mapping */
+       {0xFE72, 0, 2 | DECOMP_NO_COMPOSE, 4734},       /* compatibility mapping */
+       {0xFE74, 0, 2 | DECOMP_NO_COMPOSE, 4736},       /* compatibility mapping */
+       {0xFE76, 0, 2 | DECOMP_NO_COMPOSE, 4738},       /* compatibility mapping */
+       {0xFE77, 0, 2 | DECOMP_NO_COMPOSE, 4740},       /* compatibility mapping */
+       {0xFE78, 0, 2 | DECOMP_NO_COMPOSE, 4742},       /* compatibility mapping */
+       {0xFE79, 0, 2 | DECOMP_NO_COMPOSE, 4744},       /* compatibility mapping */
+       {0xFE7A, 0, 2 | DECOMP_NO_COMPOSE, 4746},       /* compatibility mapping */
+       {0xFE7B, 0, 2 | DECOMP_NO_COMPOSE, 4748},       /* compatibility mapping */
+       {0xFE7C, 0, 2 | DECOMP_NO_COMPOSE, 4750},       /* compatibility mapping */
+       {0xFE7D, 0, 2 | DECOMP_NO_COMPOSE, 4752},       /* compatibility mapping */
+       {0xFE7E, 0, 2 | DECOMP_NO_COMPOSE, 4754},       /* compatibility mapping */
+       {0xFE7F, 0, 2 | DECOMP_NO_COMPOSE, 4756},       /* compatibility mapping */
+       {0xFE80, 0, 1 | DECOMP_INLINE, 0x0621},
+       {0xFE81, 0, 1 | DECOMP_INLINE, 0x0622},
+       {0xFE82, 0, 1 | DECOMP_INLINE, 0x0622},
+       {0xFE83, 0, 1 | DECOMP_INLINE, 0x0623},
+       {0xFE84, 0, 1 | DECOMP_INLINE, 0x0623},
+       {0xFE85, 0, 1 | DECOMP_INLINE, 0x0624},
+       {0xFE86, 0, 1 | DECOMP_INLINE, 0x0624},
+       {0xFE87, 0, 1 | DECOMP_INLINE, 0x0625},
+       {0xFE88, 0, 1 | DECOMP_INLINE, 0x0625},
+       {0xFE89, 0, 1 | DECOMP_INLINE, 0x0626},
+       {0xFE8A, 0, 1 | DECOMP_INLINE, 0x0626},
+       {0xFE8B, 0, 1 | DECOMP_INLINE, 0x0626},
+       {0xFE8C, 0, 1 | DECOMP_INLINE, 0x0626},
+       {0xFE8D, 0, 1 | DECOMP_INLINE, 0x0627},
+       {0xFE8E, 0, 1 | DECOMP_INLINE, 0x0627},
+       {0xFE8F, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0xFE90, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0xFE91, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0xFE92, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0xFE93, 0, 1 | DECOMP_INLINE, 0x0629},
+       {0xFE94, 0, 1 | DECOMP_INLINE, 0x0629},
+       {0xFE95, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0xFE96, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0xFE97, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0xFE98, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0xFE99, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0xFE9A, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0xFE9B, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0xFE9C, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0xFE9D, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0xFE9E, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0xFE9F, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0xFEA0, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0xFEA1, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0xFEA2, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0xFEA3, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0xFEA4, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0xFEA5, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0xFEA6, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0xFEA7, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0xFEA8, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0xFEA9, 0, 1 | DECOMP_INLINE, 0x062F},
+       {0xFEAA, 0, 1 | DECOMP_INLINE, 0x062F},
+       {0xFEAB, 0, 1 | DECOMP_INLINE, 0x0630},
+       {0xFEAC, 0, 1 | DECOMP_INLINE, 0x0630},
+       {0xFEAD, 0, 1 | DECOMP_INLINE, 0x0631},
+       {0xFEAE, 0, 1 | DECOMP_INLINE, 0x0631},
+       {0xFEAF, 0, 1 | DECOMP_INLINE, 0x0632},
+       {0xFEB0, 0, 1 | DECOMP_INLINE, 0x0632},
+       {0xFEB1, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0xFEB2, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0xFEB3, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0xFEB4, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0xFEB5, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0xFEB6, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0xFEB7, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0xFEB8, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0xFEB9, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0xFEBA, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0xFEBB, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0xFEBC, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0xFEBD, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0xFEBE, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0xFEBF, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0xFEC0, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0xFEC1, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0xFEC2, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0xFEC3, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0xFEC4, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0xFEC5, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0xFEC6, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0xFEC7, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0xFEC8, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0xFEC9, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0xFECA, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0xFECB, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0xFECC, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0xFECD, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0xFECE, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0xFECF, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0xFED0, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0xFED1, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0xFED2, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0xFED3, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0xFED4, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0xFED5, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0xFED6, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0xFED7, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0xFED8, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0xFED9, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0xFEDA, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0xFEDB, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0xFEDC, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0xFEDD, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0xFEDE, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0xFEDF, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0xFEE0, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0xFEE1, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0xFEE2, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0xFEE3, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0xFEE4, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0xFEE5, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0xFEE6, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0xFEE7, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0xFEE8, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0xFEE9, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0xFEEA, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0xFEEB, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0xFEEC, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0xFEED, 0, 1 | DECOMP_INLINE, 0x0648},
+       {0xFEEE, 0, 1 | DECOMP_INLINE, 0x0648},
+       {0xFEEF, 0, 1 | DECOMP_INLINE, 0x0649},
+       {0xFEF0, 0, 1 | DECOMP_INLINE, 0x0649},
+       {0xFEF1, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0xFEF2, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0xFEF3, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0xFEF4, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0xFEF5, 0, 2 | DECOMP_NO_COMPOSE, 4758},       /* compatibility mapping */
+       {0xFEF6, 0, 2 | DECOMP_NO_COMPOSE, 4760},       /* compatibility mapping */
+       {0xFEF7, 0, 2 | DECOMP_NO_COMPOSE, 4762},       /* compatibility mapping */
+       {0xFEF8, 0, 2 | DECOMP_NO_COMPOSE, 4764},       /* compatibility mapping */
+       {0xFEF9, 0, 2 | DECOMP_NO_COMPOSE, 4766},       /* compatibility mapping */
+       {0xFEFA, 0, 2 | DECOMP_NO_COMPOSE, 4768},       /* compatibility mapping */
+       {0xFEFB, 0, 2 | DECOMP_NO_COMPOSE, 4770},       /* compatibility mapping */
+       {0xFEFC, 0, 2 | DECOMP_NO_COMPOSE, 4772},       /* compatibility mapping */
+       {0xFF01, 0, 1 | DECOMP_INLINE, 0x0021},
+       {0xFF02, 0, 1 | DECOMP_INLINE, 0x0022},
+       {0xFF03, 0, 1 | DECOMP_INLINE, 0x0023},
+       {0xFF04, 0, 1 | DECOMP_INLINE, 0x0024},
+       {0xFF05, 0, 1 | DECOMP_INLINE, 0x0025},
+       {0xFF06, 0, 1 | DECOMP_INLINE, 0x0026},
+       {0xFF07, 0, 1 | DECOMP_INLINE, 0x0027},
+       {0xFF08, 0, 1 | DECOMP_INLINE, 0x0028},
+       {0xFF09, 0, 1 | DECOMP_INLINE, 0x0029},
+       {0xFF0A, 0, 1 | DECOMP_INLINE, 0x002A},
+       {0xFF0B, 0, 1 | DECOMP_INLINE, 0x002B},
+       {0xFF0C, 0, 1 | DECOMP_INLINE, 0x002C},
+       {0xFF0D, 0, 1 | DECOMP_INLINE, 0x002D},
+       {0xFF0E, 0, 1 | DECOMP_INLINE, 0x002E},
+       {0xFF0F, 0, 1 | DECOMP_INLINE, 0x002F},
+       {0xFF10, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0xFF11, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0xFF12, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0xFF13, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0xFF14, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0xFF15, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0xFF16, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0xFF17, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0xFF18, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0xFF19, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0xFF1A, 0, 1 | DECOMP_INLINE, 0x003A},
+       {0xFF1B, 0, 1 | DECOMP_INLINE, 0x003B},
+       {0xFF1C, 0, 1 | DECOMP_INLINE, 0x003C},
+       {0xFF1D, 0, 1 | DECOMP_INLINE, 0x003D},
+       {0xFF1E, 0, 1 | DECOMP_INLINE, 0x003E},
+       {0xFF1F, 0, 1 | DECOMP_INLINE, 0x003F},
+       {0xFF20, 0, 1 | DECOMP_INLINE, 0x0040},
+       {0xFF21, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0xFF22, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0xFF23, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0xFF24, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0xFF25, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0xFF26, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0xFF27, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0xFF28, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0xFF29, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0xFF2A, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0xFF2B, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0xFF2C, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0xFF2D, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0xFF2E, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0xFF2F, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0xFF30, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0xFF31, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0xFF32, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0xFF33, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0xFF34, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0xFF35, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0xFF36, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0xFF37, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0xFF38, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0xFF39, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0xFF3A, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0xFF3B, 0, 1 | DECOMP_INLINE, 0x005B},
+       {0xFF3C, 0, 1 | DECOMP_INLINE, 0x005C},
+       {0xFF3D, 0, 1 | DECOMP_INLINE, 0x005D},
+       {0xFF3E, 0, 1 | DECOMP_INLINE, 0x005E},
+       {0xFF3F, 0, 1 | DECOMP_INLINE, 0x005F},
+       {0xFF40, 0, 1 | DECOMP_INLINE, 0x0060},
+       {0xFF41, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0xFF42, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0xFF43, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0xFF44, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0xFF45, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0xFF46, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0xFF47, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0xFF48, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0xFF49, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0xFF4A, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0xFF4B, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0xFF4C, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0xFF4D, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0xFF4E, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0xFF4F, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0xFF50, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0xFF51, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0xFF52, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0xFF53, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0xFF54, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0xFF55, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0xFF56, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0xFF57, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0xFF58, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0xFF59, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0xFF5A, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0xFF5B, 0, 1 | DECOMP_INLINE, 0x007B},
+       {0xFF5C, 0, 1 | DECOMP_INLINE, 0x007C},
+       {0xFF5D, 0, 1 | DECOMP_INLINE, 0x007D},
+       {0xFF5E, 0, 1 | DECOMP_INLINE, 0x007E},
+       {0xFF5F, 0, 1 | DECOMP_INLINE, 0x2985},
+       {0xFF60, 0, 1 | DECOMP_INLINE, 0x2986},
+       {0xFF61, 0, 1 | DECOMP_INLINE, 0x3002},
+       {0xFF62, 0, 1 | DECOMP_INLINE, 0x300C},
+       {0xFF63, 0, 1 | DECOMP_INLINE, 0x300D},
+       {0xFF64, 0, 1 | DECOMP_INLINE, 0x3001},
+       {0xFF65, 0, 1 | DECOMP_INLINE, 0x30FB},
+       {0xFF66, 0, 1 | DECOMP_INLINE, 0x30F2},
+       {0xFF67, 0, 1 | DECOMP_INLINE, 0x30A1},
+       {0xFF68, 0, 1 | DECOMP_INLINE, 0x30A3},
+       {0xFF69, 0, 1 | DECOMP_INLINE, 0x30A5},
+       {0xFF6A, 0, 1 | DECOMP_INLINE, 0x30A7},
+       {0xFF6B, 0, 1 | DECOMP_INLINE, 0x30A9},
+       {0xFF6C, 0, 1 | DECOMP_INLINE, 0x30E3},
+       {0xFF6D, 0, 1 | DECOMP_INLINE, 0x30E5},
+       {0xFF6E, 0, 1 | DECOMP_INLINE, 0x30E7},
+       {0xFF6F, 0, 1 | DECOMP_INLINE, 0x30C3},
+       {0xFF70, 0, 1 | DECOMP_INLINE, 0x30FC},
+       {0xFF71, 0, 1 | DECOMP_INLINE, 0x30A2},
+       {0xFF72, 0, 1 | DECOMP_INLINE, 0x30A4},
+       {0xFF73, 0, 1 | DECOMP_INLINE, 0x30A6},
+       {0xFF74, 0, 1 | DECOMP_INLINE, 0x30A8},
+       {0xFF75, 0, 1 | DECOMP_INLINE, 0x30AA},
+       {0xFF76, 0, 1 | DECOMP_INLINE, 0x30AB},
+       {0xFF77, 0, 1 | DECOMP_INLINE, 0x30AD},
+       {0xFF78, 0, 1 | DECOMP_INLINE, 0x30AF},
+       {0xFF79, 0, 1 | DECOMP_INLINE, 0x30B1},
+       {0xFF7A, 0, 1 | DECOMP_INLINE, 0x30B3},
+       {0xFF7B, 0, 1 | DECOMP_INLINE, 0x30B5},
+       {0xFF7C, 0, 1 | DECOMP_INLINE, 0x30B7},
+       {0xFF7D, 0, 1 | DECOMP_INLINE, 0x30B9},
+       {0xFF7E, 0, 1 | DECOMP_INLINE, 0x30BB},
+       {0xFF7F, 0, 1 | DECOMP_INLINE, 0x30BD},
+       {0xFF80, 0, 1 | DECOMP_INLINE, 0x30BF},
+       {0xFF81, 0, 1 | DECOMP_INLINE, 0x30C1},
+       {0xFF82, 0, 1 | DECOMP_INLINE, 0x30C4},
+       {0xFF83, 0, 1 | DECOMP_INLINE, 0x30C6},
+       {0xFF84, 0, 1 | DECOMP_INLINE, 0x30C8},
+       {0xFF85, 0, 1 | DECOMP_INLINE, 0x30CA},
+       {0xFF86, 0, 1 | DECOMP_INLINE, 0x30CB},
+       {0xFF87, 0, 1 | DECOMP_INLINE, 0x30CC},
+       {0xFF88, 0, 1 | DECOMP_INLINE, 0x30CD},
+       {0xFF89, 0, 1 | DECOMP_INLINE, 0x30CE},
+       {0xFF8A, 0, 1 | DECOMP_INLINE, 0x30CF},
+       {0xFF8B, 0, 1 | DECOMP_INLINE, 0x30D2},
+       {0xFF8C, 0, 1 | DECOMP_INLINE, 0x30D5},
+       {0xFF8D, 0, 1 | DECOMP_INLINE, 0x30D8},
+       {0xFF8E, 0, 1 | DECOMP_INLINE, 0x30DB},
+       {0xFF8F, 0, 1 | DECOMP_INLINE, 0x30DE},
+       {0xFF90, 0, 1 | DECOMP_INLINE, 0x30DF},
+       {0xFF91, 0, 1 | DECOMP_INLINE, 0x30E0},
+       {0xFF92, 0, 1 | DECOMP_INLINE, 0x30E1},
+       {0xFF93, 0, 1 | DECOMP_INLINE, 0x30E2},
+       {0xFF94, 0, 1 | DECOMP_INLINE, 0x30E4},
+       {0xFF95, 0, 1 | DECOMP_INLINE, 0x30E6},
+       {0xFF96, 0, 1 | DECOMP_INLINE, 0x30E8},
+       {0xFF97, 0, 1 | DECOMP_INLINE, 0x30E9},
+       {0xFF98, 0, 1 | DECOMP_INLINE, 0x30EA},
+       {0xFF99, 0, 1 | DECOMP_INLINE, 0x30EB},
+       {0xFF9A, 0, 1 | DECOMP_INLINE, 0x30EC},
+       {0xFF9B, 0, 1 | DECOMP_INLINE, 0x30ED},
+       {0xFF9C, 0, 1 | DECOMP_INLINE, 0x30EF},
+       {0xFF9D, 0, 1 | DECOMP_INLINE, 0x30F3},
+       {0xFF9E, 0, 1 | DECOMP_INLINE, 0x3099},
+       {0xFF9F, 0, 1 | DECOMP_INLINE, 0x309A},
+       {0xFFA0, 0, 1 | DECOMP_INLINE, 0x3164},
+       {0xFFA1, 0, 1 | DECOMP_INLINE, 0x3131},
+       {0xFFA2, 0, 1 | DECOMP_INLINE, 0x3132},
+       {0xFFA3, 0, 1 | DECOMP_INLINE, 0x3133},
+       {0xFFA4, 0, 1 | DECOMP_INLINE, 0x3134},
+       {0xFFA5, 0, 1 | DECOMP_INLINE, 0x3135},
+       {0xFFA6, 0, 1 | DECOMP_INLINE, 0x3136},
+       {0xFFA7, 0, 1 | DECOMP_INLINE, 0x3137},
+       {0xFFA8, 0, 1 | DECOMP_INLINE, 0x3138},
+       {0xFFA9, 0, 1 | DECOMP_INLINE, 0x3139},
+       {0xFFAA, 0, 1 | DECOMP_INLINE, 0x313A},
+       {0xFFAB, 0, 1 | DECOMP_INLINE, 0x313B},
+       {0xFFAC, 0, 1 | DECOMP_INLINE, 0x313C},
+       {0xFFAD, 0, 1 | DECOMP_INLINE, 0x313D},
+       {0xFFAE, 0, 1 | DECOMP_INLINE, 0x313E},
+       {0xFFAF, 0, 1 | DECOMP_INLINE, 0x313F},
+       {0xFFB0, 0, 1 | DECOMP_INLINE, 0x3140},
+       {0xFFB1, 0, 1 | DECOMP_INLINE, 0x3141},
+       {0xFFB2, 0, 1 | DECOMP_INLINE, 0x3142},
+       {0xFFB3, 0, 1 | DECOMP_INLINE, 0x3143},
+       {0xFFB4, 0, 1 | DECOMP_INLINE, 0x3144},
+       {0xFFB5, 0, 1 | DECOMP_INLINE, 0x3145},
+       {0xFFB6, 0, 1 | DECOMP_INLINE, 0x3146},
+       {0xFFB7, 0, 1 | DECOMP_INLINE, 0x3147},
+       {0xFFB8, 0, 1 | DECOMP_INLINE, 0x3148},
+       {0xFFB9, 0, 1 | DECOMP_INLINE, 0x3149},
+       {0xFFBA, 0, 1 | DECOMP_INLINE, 0x314A},
+       {0xFFBB, 0, 1 | DECOMP_INLINE, 0x314B},
+       {0xFFBC, 0, 1 | DECOMP_INLINE, 0x314C},
+       {0xFFBD, 0, 1 | DECOMP_INLINE, 0x314D},
+       {0xFFBE, 0, 1 | DECOMP_INLINE, 0x314E},
+       {0xFFC2, 0, 1 | DECOMP_INLINE, 0x314F},
+       {0xFFC3, 0, 1 | DECOMP_INLINE, 0x3150},
+       {0xFFC4, 0, 1 | DECOMP_INLINE, 0x3151},
+       {0xFFC5, 0, 1 | DECOMP_INLINE, 0x3152},
+       {0xFFC6, 0, 1 | DECOMP_INLINE, 0x3153},
+       {0xFFC7, 0, 1 | DECOMP_INLINE, 0x3154},
+       {0xFFCA, 0, 1 | DECOMP_INLINE, 0x3155},
+       {0xFFCB, 0, 1 | DECOMP_INLINE, 0x3156},
+       {0xFFCC, 0, 1 | DECOMP_INLINE, 0x3157},
+       {0xFFCD, 0, 1 | DECOMP_INLINE, 0x3158},
+       {0xFFCE, 0, 1 | DECOMP_INLINE, 0x3159},
+       {0xFFCF, 0, 1 | DECOMP_INLINE, 0x315A},
+       {0xFFD2, 0, 1 | DECOMP_INLINE, 0x315B},
+       {0xFFD3, 0, 1 | DECOMP_INLINE, 0x315C},
+       {0xFFD4, 0, 1 | DECOMP_INLINE, 0x315D},
+       {0xFFD5, 0, 1 | DECOMP_INLINE, 0x315E},
+       {0xFFD6, 0, 1 | DECOMP_INLINE, 0x315F},
+       {0xFFD7, 0, 1 | DECOMP_INLINE, 0x3160},
+       {0xFFDA, 0, 1 | DECOMP_INLINE, 0x3161},
+       {0xFFDB, 0, 1 | DECOMP_INLINE, 0x3162},
+       {0xFFDC, 0, 1 | DECOMP_INLINE, 0x3163},
+       {0xFFE0, 0, 1 | DECOMP_INLINE, 0x00A2},
+       {0xFFE1, 0, 1 | DECOMP_INLINE, 0x00A3},
+       {0xFFE2, 0, 1 | DECOMP_INLINE, 0x00AC},
+       {0xFFE3, 0, 1 | DECOMP_INLINE, 0x00AF},
+       {0xFFE4, 0, 1 | DECOMP_INLINE, 0x00A6},
+       {0xFFE5, 0, 1 | DECOMP_INLINE, 0x00A5},
+       {0xFFE6, 0, 1 | DECOMP_INLINE, 0x20A9},
+       {0xFFE8, 0, 1 | DECOMP_INLINE, 0x2502},
+       {0xFFE9, 0, 1 | DECOMP_INLINE, 0x2190},
+       {0xFFEA, 0, 1 | DECOMP_INLINE, 0x2191},
+       {0xFFEB, 0, 1 | DECOMP_INLINE, 0x2192},
+       {0xFFEC, 0, 1 | DECOMP_INLINE, 0x2193},
+       {0xFFED, 0, 1 | DECOMP_INLINE, 0x25A0},
+       {0xFFEE, 0, 1 | DECOMP_INLINE, 0x25CB},
+       {0x101FD, 220, 0, 0},
+       {0x102E0, 220, 0, 0},
+       {0x10376, 230, 0, 0},
+       {0x10377, 230, 0, 0},
+       {0x10378, 230, 0, 0},
+       {0x10379, 230, 0, 0},
+       {0x1037A, 230, 0, 0},
+       {0x10A0D, 220, 0, 0},
+       {0x10A0F, 230, 0, 0},
+       {0x10A38, 230, 0, 0},
+       {0x10A39, 1, 0, 0},
+       {0x10A3A, 220, 0, 0},
+       {0x10A3F, 9, 0, 0},
+       {0x10AE5, 230, 0, 0},
+       {0x10AE6, 220, 0, 0},
+       {0x11046, 9, 0, 0},
+       {0x1107F, 9, 0, 0},
+       {0x1109A, 0, 2, 4774},
+       {0x1109C, 0, 2, 4776},
+       {0x110AB, 0, 2, 4778},
+       {0x110B9, 9, 0, 0},
+       {0x110BA, 7, 0, 0},
+       {0x11100, 230, 0, 0},
+       {0x11101, 230, 0, 0},
+       {0x11102, 230, 0, 0},
+       {0x1112E, 0, 2, 4780},
+       {0x1112F, 0, 2, 4782},
+       {0x11133, 9, 0, 0},
+       {0x11134, 9, 0, 0},
+       {0x11173, 7, 0, 0},
+       {0x111C0, 9, 0, 0},
+       {0x111CA, 7, 0, 0},
+       {0x11235, 9, 0, 0},
+       {0x11236, 7, 0, 0},
+       {0x112E9, 7, 0, 0},
+       {0x112EA, 9, 0, 0},
+       {0x1133C, 7, 0, 0},
+       {0x1134B, 0, 2, 4784},
+       {0x1134C, 0, 2, 4786},
+       {0x1134D, 9, 0, 0},
+       {0x11366, 230, 0, 0},
+       {0x11367, 230, 0, 0},
+       {0x11368, 230, 0, 0},
+       {0x11369, 230, 0, 0},
+       {0x1136A, 230, 0, 0},
+       {0x1136B, 230, 0, 0},
+       {0x1136C, 230, 0, 0},
+       {0x11370, 230, 0, 0},
+       {0x11371, 230, 0, 0},
+       {0x11372, 230, 0, 0},
+       {0x11373, 230, 0, 0},
+       {0x11374, 230, 0, 0},
+       {0x11442, 9, 0, 0},
+       {0x11446, 7, 0, 0},
+       {0x114BB, 0, 2, 4788},
+       {0x114BC, 0, 2, 4790},
+       {0x114BE, 0, 2, 4792},
+       {0x114C2, 9, 0, 0},
+       {0x114C3, 7, 0, 0},
+       {0x115BA, 0, 2, 4794},
+       {0x115BB, 0, 2, 4796},
+       {0x115BF, 9, 0, 0},
+       {0x115C0, 7, 0, 0},
+       {0x1163F, 9, 0, 0},
+       {0x116B6, 9, 0, 0},
+       {0x116B7, 7, 0, 0},
+       {0x1172B, 9, 0, 0},
+       {0x11C3F, 9, 0, 0},
+       {0x16AF0, 1, 0, 0},
+       {0x16AF1, 1, 0, 0},
+       {0x16AF2, 1, 0, 0},
+       {0x16AF3, 1, 0, 0},
+       {0x16AF4, 1, 0, 0},
+       {0x16B30, 230, 0, 0},
+       {0x16B31, 230, 0, 0},
+       {0x16B32, 230, 0, 0},
+       {0x16B33, 230, 0, 0},
+       {0x16B34, 230, 0, 0},
+       {0x16B35, 230, 0, 0},
+       {0x16B36, 230, 0, 0},
+       {0x1BC9E, 1, 0, 0},
+       {0x1D15E, 0, 2 | DECOMP_NO_COMPOSE, 4798},      /* in exclusion list */
+       {0x1D15F, 0, 2 | DECOMP_NO_COMPOSE, 4800},      /* in exclusion list */
+       {0x1D160, 0, 2 | DECOMP_NO_COMPOSE, 4802},      /* in exclusion list */
+       {0x1D161, 0, 2 | DECOMP_NO_COMPOSE, 4804},      /* in exclusion list */
+       {0x1D162, 0, 2 | DECOMP_NO_COMPOSE, 4806},      /* in exclusion list */
+       {0x1D163, 0, 2 | DECOMP_NO_COMPOSE, 4808},      /* in exclusion list */
+       {0x1D164, 0, 2 | DECOMP_NO_COMPOSE, 4810},      /* in exclusion list */
+       {0x1D165, 216, 0, 0},
+       {0x1D166, 216, 0, 0},
+       {0x1D167, 1, 0, 0},
+       {0x1D168, 1, 0, 0},
+       {0x1D169, 1, 0, 0},
+       {0x1D16D, 226, 0, 0},
+       {0x1D16E, 216, 0, 0},
+       {0x1D16F, 216, 0, 0},
+       {0x1D170, 216, 0, 0},
+       {0x1D171, 216, 0, 0},
+       {0x1D172, 216, 0, 0},
+       {0x1D17B, 220, 0, 0},
+       {0x1D17C, 220, 0, 0},
+       {0x1D17D, 220, 0, 0},
+       {0x1D17E, 220, 0, 0},
+       {0x1D17F, 220, 0, 0},
+       {0x1D180, 220, 0, 0},
+       {0x1D181, 220, 0, 0},
+       {0x1D182, 220, 0, 0},
+       {0x1D185, 230, 0, 0},
+       {0x1D186, 230, 0, 0},
+       {0x1D187, 230, 0, 0},
+       {0x1D188, 230, 0, 0},
+       {0x1D189, 230, 0, 0},
+       {0x1D18A, 220, 0, 0},
+       {0x1D18B, 220, 0, 0},
+       {0x1D1AA, 230, 0, 0},
+       {0x1D1AB, 230, 0, 0},
+       {0x1D1AC, 230, 0, 0},
+       {0x1D1AD, 230, 0, 0},
+       {0x1D1BB, 0, 2 | DECOMP_NO_COMPOSE, 4812},      /* in exclusion list */
+       {0x1D1BC, 0, 2 | DECOMP_NO_COMPOSE, 4814},      /* in exclusion list */
+       {0x1D1BD, 0, 2 | DECOMP_NO_COMPOSE, 4816},      /* in exclusion list */
+       {0x1D1BE, 0, 2 | DECOMP_NO_COMPOSE, 4818},      /* in exclusion list */
+       {0x1D1BF, 0, 2 | DECOMP_NO_COMPOSE, 4820},      /* in exclusion list */
+       {0x1D1C0, 0, 2 | DECOMP_NO_COMPOSE, 4822},      /* in exclusion list */
+       {0x1D242, 230, 0, 0},
+       {0x1D243, 230, 0, 0},
+       {0x1D244, 230, 0, 0},
+       {0x1D400, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D401, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D402, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D403, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D404, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D405, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D406, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D407, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D408, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D409, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D40A, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D40B, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D40C, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D40D, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D40E, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D40F, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D410, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D411, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D412, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D413, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D414, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D415, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D416, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D417, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D418, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D419, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D41A, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D41B, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D41C, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D41D, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D41E, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D41F, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D420, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D421, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D422, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D423, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D424, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D425, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D426, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D427, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D428, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D429, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D42A, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D42B, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D42C, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D42D, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D42E, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D42F, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D430, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D431, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D432, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D433, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D434, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D435, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D436, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D437, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D438, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D439, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D43A, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D43B, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D43C, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D43D, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D43E, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D43F, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D440, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D441, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D442, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D443, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D444, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D445, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D446, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D447, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D448, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D449, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D44A, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D44B, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D44C, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D44D, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D44E, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D44F, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D450, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D451, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D452, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D453, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D454, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D456, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D457, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D458, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D459, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D45A, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D45B, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D45C, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D45D, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D45E, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D45F, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D460, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D461, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D462, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D463, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D464, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D465, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D466, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D467, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D468, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D469, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D46A, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D46B, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D46C, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D46D, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D46E, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D46F, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D470, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D471, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D472, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D473, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D474, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D475, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D476, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D477, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D478, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D479, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D47A, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D47B, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D47C, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D47D, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D47E, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D47F, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D480, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D481, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D482, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D483, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D484, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D485, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D486, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D487, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D488, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D489, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D48A, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D48B, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D48C, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D48D, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D48E, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D48F, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D490, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D491, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D492, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D493, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D494, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D495, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D496, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D497, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D498, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D499, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D49A, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D49B, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D49C, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D49E, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D49F, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D4A2, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D4A5, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D4A6, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D4A9, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D4AA, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D4AB, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D4AC, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D4AE, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D4AF, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D4B0, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D4B1, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D4B2, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D4B3, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D4B4, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D4B5, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D4B6, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D4B7, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D4B8, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D4B9, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D4BB, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D4BD, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D4BE, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D4BF, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D4C0, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D4C1, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D4C2, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D4C3, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D4C5, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D4C6, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D4C7, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D4C8, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D4C9, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D4CA, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D4CB, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D4CC, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D4CD, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D4CE, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D4CF, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D4D0, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D4D1, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D4D2, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D4D3, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D4D4, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D4D5, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D4D6, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D4D7, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D4D8, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D4D9, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D4DA, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D4DB, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D4DC, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D4DD, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D4DE, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D4DF, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D4E0, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D4E1, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D4E2, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D4E3, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D4E4, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D4E5, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D4E6, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D4E7, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D4E8, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D4E9, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D4EA, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D4EB, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D4EC, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D4ED, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D4EE, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D4EF, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D4F0, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D4F1, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D4F2, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D4F3, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D4F4, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D4F5, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D4F6, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D4F7, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D4F8, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D4F9, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D4FA, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D4FB, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D4FC, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D4FD, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D4FE, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D4FF, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D500, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D501, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D502, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D503, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D504, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D505, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D507, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D508, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D509, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D50A, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D50D, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D50E, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D50F, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D510, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D511, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D512, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D513, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D514, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D516, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D517, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D518, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D519, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D51A, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D51B, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D51C, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D51E, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D51F, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D520, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D521, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D522, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D523, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D524, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D525, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D526, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D527, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D528, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D529, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D52A, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D52B, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D52C, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D52D, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D52E, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D52F, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D530, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D531, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D532, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D533, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D534, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D535, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D536, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D537, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D538, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D539, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D53B, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D53C, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D53D, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D53E, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D540, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D541, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D542, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D543, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D544, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D546, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D54A, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D54B, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D54C, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D54D, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D54E, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D54F, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D550, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D552, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D553, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D554, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D555, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D556, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D557, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D558, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D559, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D55A, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D55B, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D55C, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D55D, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D55E, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D55F, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D560, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D561, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D562, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D563, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D564, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D565, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D566, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D567, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D568, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D569, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D56A, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D56B, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D56C, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D56D, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D56E, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D56F, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D570, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D571, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D572, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D573, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D574, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D575, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D576, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D577, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D578, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D579, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D57A, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D57B, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D57C, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D57D, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D57E, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D57F, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D580, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D581, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D582, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D583, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D584, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D585, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D586, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D587, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D588, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D589, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D58A, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D58B, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D58C, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D58D, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D58E, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D58F, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D590, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D591, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D592, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D593, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D594, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D595, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D596, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D597, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D598, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D599, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D59A, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D59B, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D59C, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D59D, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D59E, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D59F, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D5A0, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D5A1, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D5A2, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D5A3, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D5A4, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D5A5, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D5A6, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D5A7, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D5A8, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D5A9, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D5AA, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D5AB, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D5AC, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D5AD, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D5AE, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D5AF, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D5B0, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D5B1, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D5B2, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D5B3, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D5B4, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D5B5, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D5B6, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D5B7, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D5B8, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D5B9, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D5BA, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D5BB, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D5BC, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D5BD, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D5BE, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D5BF, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D5C0, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D5C1, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D5C2, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D5C3, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D5C4, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D5C5, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D5C6, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D5C7, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D5C8, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D5C9, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D5CA, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D5CB, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D5CC, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D5CD, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D5CE, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D5CF, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D5D0, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D5D1, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D5D2, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D5D3, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D5D4, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D5D5, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D5D6, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D5D7, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D5D8, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D5D9, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D5DA, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D5DB, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D5DC, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D5DD, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D5DE, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D5DF, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D5E0, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D5E1, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D5E2, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D5E3, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D5E4, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D5E5, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D5E6, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D5E7, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D5E8, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D5E9, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D5EA, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D5EB, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D5EC, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D5ED, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D5EE, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D5EF, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D5F0, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D5F1, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D5F2, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D5F3, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D5F4, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D5F5, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D5F6, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D5F7, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D5F8, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D5F9, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D5FA, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D5FB, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D5FC, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D5FD, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D5FE, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D5FF, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D600, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D601, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D602, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D603, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D604, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D605, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D606, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D607, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D608, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D609, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D60A, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D60B, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D60C, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D60D, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D60E, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D60F, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D610, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D611, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D612, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D613, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D614, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D615, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D616, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D617, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D618, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D619, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D61A, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D61B, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D61C, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D61D, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D61E, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D61F, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D620, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D621, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D622, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D623, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D624, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D625, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D626, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D627, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D628, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D629, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D62A, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D62B, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D62C, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D62D, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D62E, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D62F, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D630, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D631, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D632, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D633, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D634, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D635, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D636, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D637, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D638, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D639, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D63A, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D63B, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D63C, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D63D, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D63E, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D63F, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D640, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D641, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D642, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D643, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D644, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D645, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D646, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D647, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D648, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D649, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D64A, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D64B, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D64C, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D64D, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D64E, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D64F, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D650, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D651, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D652, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D653, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D654, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D655, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D656, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D657, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D658, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D659, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D65A, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D65B, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D65C, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D65D, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D65E, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D65F, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D660, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D661, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D662, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D663, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D664, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D665, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D666, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D667, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D668, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D669, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D66A, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D66B, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D66C, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D66D, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D66E, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D66F, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D670, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1D671, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1D672, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1D673, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1D674, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1D675, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1D676, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1D677, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1D678, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1D679, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1D67A, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1D67B, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1D67C, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1D67D, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1D67E, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1D67F, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1D680, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1D681, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1D682, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1D683, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1D684, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1D685, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1D686, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1D687, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1D688, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1D689, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1D68A, 0, 1 | DECOMP_INLINE, 0x0061},
+       {0x1D68B, 0, 1 | DECOMP_INLINE, 0x0062},
+       {0x1D68C, 0, 1 | DECOMP_INLINE, 0x0063},
+       {0x1D68D, 0, 1 | DECOMP_INLINE, 0x0064},
+       {0x1D68E, 0, 1 | DECOMP_INLINE, 0x0065},
+       {0x1D68F, 0, 1 | DECOMP_INLINE, 0x0066},
+       {0x1D690, 0, 1 | DECOMP_INLINE, 0x0067},
+       {0x1D691, 0, 1 | DECOMP_INLINE, 0x0068},
+       {0x1D692, 0, 1 | DECOMP_INLINE, 0x0069},
+       {0x1D693, 0, 1 | DECOMP_INLINE, 0x006A},
+       {0x1D694, 0, 1 | DECOMP_INLINE, 0x006B},
+       {0x1D695, 0, 1 | DECOMP_INLINE, 0x006C},
+       {0x1D696, 0, 1 | DECOMP_INLINE, 0x006D},
+       {0x1D697, 0, 1 | DECOMP_INLINE, 0x006E},
+       {0x1D698, 0, 1 | DECOMP_INLINE, 0x006F},
+       {0x1D699, 0, 1 | DECOMP_INLINE, 0x0070},
+       {0x1D69A, 0, 1 | DECOMP_INLINE, 0x0071},
+       {0x1D69B, 0, 1 | DECOMP_INLINE, 0x0072},
+       {0x1D69C, 0, 1 | DECOMP_INLINE, 0x0073},
+       {0x1D69D, 0, 1 | DECOMP_INLINE, 0x0074},
+       {0x1D69E, 0, 1 | DECOMP_INLINE, 0x0075},
+       {0x1D69F, 0, 1 | DECOMP_INLINE, 0x0076},
+       {0x1D6A0, 0, 1 | DECOMP_INLINE, 0x0077},
+       {0x1D6A1, 0, 1 | DECOMP_INLINE, 0x0078},
+       {0x1D6A2, 0, 1 | DECOMP_INLINE, 0x0079},
+       {0x1D6A3, 0, 1 | DECOMP_INLINE, 0x007A},
+       {0x1D6A4, 0, 1 | DECOMP_INLINE, 0x0131},
+       {0x1D6A5, 0, 1 | DECOMP_INLINE, 0x0237},
+       {0x1D6A8, 0, 1 | DECOMP_INLINE, 0x0391},
+       {0x1D6A9, 0, 1 | DECOMP_INLINE, 0x0392},
+       {0x1D6AA, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x1D6AB, 0, 1 | DECOMP_INLINE, 0x0394},
+       {0x1D6AC, 0, 1 | DECOMP_INLINE, 0x0395},
+       {0x1D6AD, 0, 1 | DECOMP_INLINE, 0x0396},
+       {0x1D6AE, 0, 1 | DECOMP_INLINE, 0x0397},
+       {0x1D6AF, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x1D6B0, 0, 1 | DECOMP_INLINE, 0x0399},
+       {0x1D6B1, 0, 1 | DECOMP_INLINE, 0x039A},
+       {0x1D6B2, 0, 1 | DECOMP_INLINE, 0x039B},
+       {0x1D6B3, 0, 1 | DECOMP_INLINE, 0x039C},
+       {0x1D6B4, 0, 1 | DECOMP_INLINE, 0x039D},
+       {0x1D6B5, 0, 1 | DECOMP_INLINE, 0x039E},
+       {0x1D6B6, 0, 1 | DECOMP_INLINE, 0x039F},
+       {0x1D6B7, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x1D6B8, 0, 1 | DECOMP_INLINE, 0x03A1},
+       {0x1D6B9, 0, 1 | DECOMP_INLINE, 0x03F4},
+       {0x1D6BA, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x1D6BB, 0, 1 | DECOMP_INLINE, 0x03A4},
+       {0x1D6BC, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x1D6BD, 0, 1 | DECOMP_INLINE, 0x03A6},
+       {0x1D6BE, 0, 1 | DECOMP_INLINE, 0x03A7},
+       {0x1D6BF, 0, 1 | DECOMP_INLINE, 0x03A8},
+       {0x1D6C0, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x1D6C1, 0, 1 | DECOMP_INLINE, 0x2207},
+       {0x1D6C2, 0, 1 | DECOMP_INLINE, 0x03B1},
+       {0x1D6C3, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D6C4, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D6C5, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D6C6, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x1D6C7, 0, 1 | DECOMP_INLINE, 0x03B6},
+       {0x1D6C8, 0, 1 | DECOMP_INLINE, 0x03B7},
+       {0x1D6C9, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1D6CA, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1D6CB, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x1D6CC, 0, 1 | DECOMP_INLINE, 0x03BB},
+       {0x1D6CD, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x1D6CE, 0, 1 | DECOMP_INLINE, 0x03BD},
+       {0x1D6CF, 0, 1 | DECOMP_INLINE, 0x03BE},
+       {0x1D6D0, 0, 1 | DECOMP_INLINE, 0x03BF},
+       {0x1D6D1, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x1D6D2, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D6D3, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x1D6D4, 0, 1 | DECOMP_INLINE, 0x03C3},
+       {0x1D6D5, 0, 1 | DECOMP_INLINE, 0x03C4},
+       {0x1D6D6, 0, 1 | DECOMP_INLINE, 0x03C5},
+       {0x1D6D7, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D6D8, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D6D9, 0, 1 | DECOMP_INLINE, 0x03C8},
+       {0x1D6DA, 0, 1 | DECOMP_INLINE, 0x03C9},
+       {0x1D6DB, 0, 1 | DECOMP_INLINE, 0x2202},
+       {0x1D6DC, 0, 1 | DECOMP_INLINE, 0x03F5},
+       {0x1D6DD, 0, 1 | DECOMP_INLINE, 0x03D1},
+       {0x1D6DE, 0, 1 | DECOMP_INLINE, 0x03F0},
+       {0x1D6DF, 0, 1 | DECOMP_INLINE, 0x03D5},
+       {0x1D6E0, 0, 1 | DECOMP_INLINE, 0x03F1},
+       {0x1D6E1, 0, 1 | DECOMP_INLINE, 0x03D6},
+       {0x1D6E2, 0, 1 | DECOMP_INLINE, 0x0391},
+       {0x1D6E3, 0, 1 | DECOMP_INLINE, 0x0392},
+       {0x1D6E4, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x1D6E5, 0, 1 | DECOMP_INLINE, 0x0394},
+       {0x1D6E6, 0, 1 | DECOMP_INLINE, 0x0395},
+       {0x1D6E7, 0, 1 | DECOMP_INLINE, 0x0396},
+       {0x1D6E8, 0, 1 | DECOMP_INLINE, 0x0397},
+       {0x1D6E9, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x1D6EA, 0, 1 | DECOMP_INLINE, 0x0399},
+       {0x1D6EB, 0, 1 | DECOMP_INLINE, 0x039A},
+       {0x1D6EC, 0, 1 | DECOMP_INLINE, 0x039B},
+       {0x1D6ED, 0, 1 | DECOMP_INLINE, 0x039C},
+       {0x1D6EE, 0, 1 | DECOMP_INLINE, 0x039D},
+       {0x1D6EF, 0, 1 | DECOMP_INLINE, 0x039E},
+       {0x1D6F0, 0, 1 | DECOMP_INLINE, 0x039F},
+       {0x1D6F1, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x1D6F2, 0, 1 | DECOMP_INLINE, 0x03A1},
+       {0x1D6F3, 0, 1 | DECOMP_INLINE, 0x03F4},
+       {0x1D6F4, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x1D6F5, 0, 1 | DECOMP_INLINE, 0x03A4},
+       {0x1D6F6, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x1D6F7, 0, 1 | DECOMP_INLINE, 0x03A6},
+       {0x1D6F8, 0, 1 | DECOMP_INLINE, 0x03A7},
+       {0x1D6F9, 0, 1 | DECOMP_INLINE, 0x03A8},
+       {0x1D6FA, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x1D6FB, 0, 1 | DECOMP_INLINE, 0x2207},
+       {0x1D6FC, 0, 1 | DECOMP_INLINE, 0x03B1},
+       {0x1D6FD, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D6FE, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D6FF, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D700, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x1D701, 0, 1 | DECOMP_INLINE, 0x03B6},
+       {0x1D702, 0, 1 | DECOMP_INLINE, 0x03B7},
+       {0x1D703, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1D704, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1D705, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x1D706, 0, 1 | DECOMP_INLINE, 0x03BB},
+       {0x1D707, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x1D708, 0, 1 | DECOMP_INLINE, 0x03BD},
+       {0x1D709, 0, 1 | DECOMP_INLINE, 0x03BE},
+       {0x1D70A, 0, 1 | DECOMP_INLINE, 0x03BF},
+       {0x1D70B, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x1D70C, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D70D, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x1D70E, 0, 1 | DECOMP_INLINE, 0x03C3},
+       {0x1D70F, 0, 1 | DECOMP_INLINE, 0x03C4},
+       {0x1D710, 0, 1 | DECOMP_INLINE, 0x03C5},
+       {0x1D711, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D712, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D713, 0, 1 | DECOMP_INLINE, 0x03C8},
+       {0x1D714, 0, 1 | DECOMP_INLINE, 0x03C9},
+       {0x1D715, 0, 1 | DECOMP_INLINE, 0x2202},
+       {0x1D716, 0, 1 | DECOMP_INLINE, 0x03F5},
+       {0x1D717, 0, 1 | DECOMP_INLINE, 0x03D1},
+       {0x1D718, 0, 1 | DECOMP_INLINE, 0x03F0},
+       {0x1D719, 0, 1 | DECOMP_INLINE, 0x03D5},
+       {0x1D71A, 0, 1 | DECOMP_INLINE, 0x03F1},
+       {0x1D71B, 0, 1 | DECOMP_INLINE, 0x03D6},
+       {0x1D71C, 0, 1 | DECOMP_INLINE, 0x0391},
+       {0x1D71D, 0, 1 | DECOMP_INLINE, 0x0392},
+       {0x1D71E, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x1D71F, 0, 1 | DECOMP_INLINE, 0x0394},
+       {0x1D720, 0, 1 | DECOMP_INLINE, 0x0395},
+       {0x1D721, 0, 1 | DECOMP_INLINE, 0x0396},
+       {0x1D722, 0, 1 | DECOMP_INLINE, 0x0397},
+       {0x1D723, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x1D724, 0, 1 | DECOMP_INLINE, 0x0399},
+       {0x1D725, 0, 1 | DECOMP_INLINE, 0x039A},
+       {0x1D726, 0, 1 | DECOMP_INLINE, 0x039B},
+       {0x1D727, 0, 1 | DECOMP_INLINE, 0x039C},
+       {0x1D728, 0, 1 | DECOMP_INLINE, 0x039D},
+       {0x1D729, 0, 1 | DECOMP_INLINE, 0x039E},
+       {0x1D72A, 0, 1 | DECOMP_INLINE, 0x039F},
+       {0x1D72B, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x1D72C, 0, 1 | DECOMP_INLINE, 0x03A1},
+       {0x1D72D, 0, 1 | DECOMP_INLINE, 0x03F4},
+       {0x1D72E, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x1D72F, 0, 1 | DECOMP_INLINE, 0x03A4},
+       {0x1D730, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x1D731, 0, 1 | DECOMP_INLINE, 0x03A6},
+       {0x1D732, 0, 1 | DECOMP_INLINE, 0x03A7},
+       {0x1D733, 0, 1 | DECOMP_INLINE, 0x03A8},
+       {0x1D734, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x1D735, 0, 1 | DECOMP_INLINE, 0x2207},
+       {0x1D736, 0, 1 | DECOMP_INLINE, 0x03B1},
+       {0x1D737, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D738, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D739, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D73A, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x1D73B, 0, 1 | DECOMP_INLINE, 0x03B6},
+       {0x1D73C, 0, 1 | DECOMP_INLINE, 0x03B7},
+       {0x1D73D, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1D73E, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1D73F, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x1D740, 0, 1 | DECOMP_INLINE, 0x03BB},
+       {0x1D741, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x1D742, 0, 1 | DECOMP_INLINE, 0x03BD},
+       {0x1D743, 0, 1 | DECOMP_INLINE, 0x03BE},
+       {0x1D744, 0, 1 | DECOMP_INLINE, 0x03BF},
+       {0x1D745, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x1D746, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D747, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x1D748, 0, 1 | DECOMP_INLINE, 0x03C3},
+       {0x1D749, 0, 1 | DECOMP_INLINE, 0x03C4},
+       {0x1D74A, 0, 1 | DECOMP_INLINE, 0x03C5},
+       {0x1D74B, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D74C, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D74D, 0, 1 | DECOMP_INLINE, 0x03C8},
+       {0x1D74E, 0, 1 | DECOMP_INLINE, 0x03C9},
+       {0x1D74F, 0, 1 | DECOMP_INLINE, 0x2202},
+       {0x1D750, 0, 1 | DECOMP_INLINE, 0x03F5},
+       {0x1D751, 0, 1 | DECOMP_INLINE, 0x03D1},
+       {0x1D752, 0, 1 | DECOMP_INLINE, 0x03F0},
+       {0x1D753, 0, 1 | DECOMP_INLINE, 0x03D5},
+       {0x1D754, 0, 1 | DECOMP_INLINE, 0x03F1},
+       {0x1D755, 0, 1 | DECOMP_INLINE, 0x03D6},
+       {0x1D756, 0, 1 | DECOMP_INLINE, 0x0391},
+       {0x1D757, 0, 1 | DECOMP_INLINE, 0x0392},
+       {0x1D758, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x1D759, 0, 1 | DECOMP_INLINE, 0x0394},
+       {0x1D75A, 0, 1 | DECOMP_INLINE, 0x0395},
+       {0x1D75B, 0, 1 | DECOMP_INLINE, 0x0396},
+       {0x1D75C, 0, 1 | DECOMP_INLINE, 0x0397},
+       {0x1D75D, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x1D75E, 0, 1 | DECOMP_INLINE, 0x0399},
+       {0x1D75F, 0, 1 | DECOMP_INLINE, 0x039A},
+       {0x1D760, 0, 1 | DECOMP_INLINE, 0x039B},
+       {0x1D761, 0, 1 | DECOMP_INLINE, 0x039C},
+       {0x1D762, 0, 1 | DECOMP_INLINE, 0x039D},
+       {0x1D763, 0, 1 | DECOMP_INLINE, 0x039E},
+       {0x1D764, 0, 1 | DECOMP_INLINE, 0x039F},
+       {0x1D765, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x1D766, 0, 1 | DECOMP_INLINE, 0x03A1},
+       {0x1D767, 0, 1 | DECOMP_INLINE, 0x03F4},
+       {0x1D768, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x1D769, 0, 1 | DECOMP_INLINE, 0x03A4},
+       {0x1D76A, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x1D76B, 0, 1 | DECOMP_INLINE, 0x03A6},
+       {0x1D76C, 0, 1 | DECOMP_INLINE, 0x03A7},
+       {0x1D76D, 0, 1 | DECOMP_INLINE, 0x03A8},
+       {0x1D76E, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x1D76F, 0, 1 | DECOMP_INLINE, 0x2207},
+       {0x1D770, 0, 1 | DECOMP_INLINE, 0x03B1},
+       {0x1D771, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D772, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D773, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D774, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x1D775, 0, 1 | DECOMP_INLINE, 0x03B6},
+       {0x1D776, 0, 1 | DECOMP_INLINE, 0x03B7},
+       {0x1D777, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1D778, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1D779, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x1D77A, 0, 1 | DECOMP_INLINE, 0x03BB},
+       {0x1D77B, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x1D77C, 0, 1 | DECOMP_INLINE, 0x03BD},
+       {0x1D77D, 0, 1 | DECOMP_INLINE, 0x03BE},
+       {0x1D77E, 0, 1 | DECOMP_INLINE, 0x03BF},
+       {0x1D77F, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x1D780, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D781, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x1D782, 0, 1 | DECOMP_INLINE, 0x03C3},
+       {0x1D783, 0, 1 | DECOMP_INLINE, 0x03C4},
+       {0x1D784, 0, 1 | DECOMP_INLINE, 0x03C5},
+       {0x1D785, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D786, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D787, 0, 1 | DECOMP_INLINE, 0x03C8},
+       {0x1D788, 0, 1 | DECOMP_INLINE, 0x03C9},
+       {0x1D789, 0, 1 | DECOMP_INLINE, 0x2202},
+       {0x1D78A, 0, 1 | DECOMP_INLINE, 0x03F5},
+       {0x1D78B, 0, 1 | DECOMP_INLINE, 0x03D1},
+       {0x1D78C, 0, 1 | DECOMP_INLINE, 0x03F0},
+       {0x1D78D, 0, 1 | DECOMP_INLINE, 0x03D5},
+       {0x1D78E, 0, 1 | DECOMP_INLINE, 0x03F1},
+       {0x1D78F, 0, 1 | DECOMP_INLINE, 0x03D6},
+       {0x1D790, 0, 1 | DECOMP_INLINE, 0x0391},
+       {0x1D791, 0, 1 | DECOMP_INLINE, 0x0392},
+       {0x1D792, 0, 1 | DECOMP_INLINE, 0x0393},
+       {0x1D793, 0, 1 | DECOMP_INLINE, 0x0394},
+       {0x1D794, 0, 1 | DECOMP_INLINE, 0x0395},
+       {0x1D795, 0, 1 | DECOMP_INLINE, 0x0396},
+       {0x1D796, 0, 1 | DECOMP_INLINE, 0x0397},
+       {0x1D797, 0, 1 | DECOMP_INLINE, 0x0398},
+       {0x1D798, 0, 1 | DECOMP_INLINE, 0x0399},
+       {0x1D799, 0, 1 | DECOMP_INLINE, 0x039A},
+       {0x1D79A, 0, 1 | DECOMP_INLINE, 0x039B},
+       {0x1D79B, 0, 1 | DECOMP_INLINE, 0x039C},
+       {0x1D79C, 0, 1 | DECOMP_INLINE, 0x039D},
+       {0x1D79D, 0, 1 | DECOMP_INLINE, 0x039E},
+       {0x1D79E, 0, 1 | DECOMP_INLINE, 0x039F},
+       {0x1D79F, 0, 1 | DECOMP_INLINE, 0x03A0},
+       {0x1D7A0, 0, 1 | DECOMP_INLINE, 0x03A1},
+       {0x1D7A1, 0, 1 | DECOMP_INLINE, 0x03F4},
+       {0x1D7A2, 0, 1 | DECOMP_INLINE, 0x03A3},
+       {0x1D7A3, 0, 1 | DECOMP_INLINE, 0x03A4},
+       {0x1D7A4, 0, 1 | DECOMP_INLINE, 0x03A5},
+       {0x1D7A5, 0, 1 | DECOMP_INLINE, 0x03A6},
+       {0x1D7A6, 0, 1 | DECOMP_INLINE, 0x03A7},
+       {0x1D7A7, 0, 1 | DECOMP_INLINE, 0x03A8},
+       {0x1D7A8, 0, 1 | DECOMP_INLINE, 0x03A9},
+       {0x1D7A9, 0, 1 | DECOMP_INLINE, 0x2207},
+       {0x1D7AA, 0, 1 | DECOMP_INLINE, 0x03B1},
+       {0x1D7AB, 0, 1 | DECOMP_INLINE, 0x03B2},
+       {0x1D7AC, 0, 1 | DECOMP_INLINE, 0x03B3},
+       {0x1D7AD, 0, 1 | DECOMP_INLINE, 0x03B4},
+       {0x1D7AE, 0, 1 | DECOMP_INLINE, 0x03B5},
+       {0x1D7AF, 0, 1 | DECOMP_INLINE, 0x03B6},
+       {0x1D7B0, 0, 1 | DECOMP_INLINE, 0x03B7},
+       {0x1D7B1, 0, 1 | DECOMP_INLINE, 0x03B8},
+       {0x1D7B2, 0, 1 | DECOMP_INLINE, 0x03B9},
+       {0x1D7B3, 0, 1 | DECOMP_INLINE, 0x03BA},
+       {0x1D7B4, 0, 1 | DECOMP_INLINE, 0x03BB},
+       {0x1D7B5, 0, 1 | DECOMP_INLINE, 0x03BC},
+       {0x1D7B6, 0, 1 | DECOMP_INLINE, 0x03BD},
+       {0x1D7B7, 0, 1 | DECOMP_INLINE, 0x03BE},
+       {0x1D7B8, 0, 1 | DECOMP_INLINE, 0x03BF},
+       {0x1D7B9, 0, 1 | DECOMP_INLINE, 0x03C0},
+       {0x1D7BA, 0, 1 | DECOMP_INLINE, 0x03C1},
+       {0x1D7BB, 0, 1 | DECOMP_INLINE, 0x03C2},
+       {0x1D7BC, 0, 1 | DECOMP_INLINE, 0x03C3},
+       {0x1D7BD, 0, 1 | DECOMP_INLINE, 0x03C4},
+       {0x1D7BE, 0, 1 | DECOMP_INLINE, 0x03C5},
+       {0x1D7BF, 0, 1 | DECOMP_INLINE, 0x03C6},
+       {0x1D7C0, 0, 1 | DECOMP_INLINE, 0x03C7},
+       {0x1D7C1, 0, 1 | DECOMP_INLINE, 0x03C8},
+       {0x1D7C2, 0, 1 | DECOMP_INLINE, 0x03C9},
+       {0x1D7C3, 0, 1 | DECOMP_INLINE, 0x2202},
+       {0x1D7C4, 0, 1 | DECOMP_INLINE, 0x03F5},
+       {0x1D7C5, 0, 1 | DECOMP_INLINE, 0x03D1},
+       {0x1D7C6, 0, 1 | DECOMP_INLINE, 0x03F0},
+       {0x1D7C7, 0, 1 | DECOMP_INLINE, 0x03D5},
+       {0x1D7C8, 0, 1 | DECOMP_INLINE, 0x03F1},
+       {0x1D7C9, 0, 1 | DECOMP_INLINE, 0x03D6},
+       {0x1D7CA, 0, 1 | DECOMP_INLINE, 0x03DC},
+       {0x1D7CB, 0, 1 | DECOMP_INLINE, 0x03DD},
+       {0x1D7CE, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x1D7CF, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x1D7D0, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x1D7D1, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x1D7D2, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x1D7D3, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x1D7D4, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x1D7D5, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x1D7D6, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x1D7D7, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x1D7D8, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x1D7D9, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x1D7DA, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x1D7DB, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x1D7DC, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x1D7DD, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x1D7DE, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x1D7DF, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x1D7E0, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x1D7E1, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x1D7E2, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x1D7E3, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x1D7E4, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x1D7E5, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x1D7E6, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x1D7E7, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x1D7E8, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x1D7E9, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x1D7EA, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x1D7EB, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x1D7EC, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x1D7ED, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x1D7EE, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x1D7EF, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x1D7F0, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x1D7F1, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x1D7F2, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x1D7F3, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x1D7F4, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x1D7F5, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x1D7F6, 0, 1 | DECOMP_INLINE, 0x0030},
+       {0x1D7F7, 0, 1 | DECOMP_INLINE, 0x0031},
+       {0x1D7F8, 0, 1 | DECOMP_INLINE, 0x0032},
+       {0x1D7F9, 0, 1 | DECOMP_INLINE, 0x0033},
+       {0x1D7FA, 0, 1 | DECOMP_INLINE, 0x0034},
+       {0x1D7FB, 0, 1 | DECOMP_INLINE, 0x0035},
+       {0x1D7FC, 0, 1 | DECOMP_INLINE, 0x0036},
+       {0x1D7FD, 0, 1 | DECOMP_INLINE, 0x0037},
+       {0x1D7FE, 0, 1 | DECOMP_INLINE, 0x0038},
+       {0x1D7FF, 0, 1 | DECOMP_INLINE, 0x0039},
+       {0x1E000, 230, 0, 0},
+       {0x1E001, 230, 0, 0},
+       {0x1E002, 230, 0, 0},
+       {0x1E003, 230, 0, 0},
+       {0x1E004, 230, 0, 0},
+       {0x1E005, 230, 0, 0},
+       {0x1E006, 230, 0, 0},
+       {0x1E008, 230, 0, 0},
+       {0x1E009, 230, 0, 0},
+       {0x1E00A, 230, 0, 0},
+       {0x1E00B, 230, 0, 0},
+       {0x1E00C, 230, 0, 0},
+       {0x1E00D, 230, 0, 0},
+       {0x1E00E, 230, 0, 0},
+       {0x1E00F, 230, 0, 0},
+       {0x1E010, 230, 0, 0},
+       {0x1E011, 230, 0, 0},
+       {0x1E012, 230, 0, 0},
+       {0x1E013, 230, 0, 0},
+       {0x1E014, 230, 0, 0},
+       {0x1E015, 230, 0, 0},
+       {0x1E016, 230, 0, 0},
+       {0x1E017, 230, 0, 0},
+       {0x1E018, 230, 0, 0},
+       {0x1E01B, 230, 0, 0},
+       {0x1E01C, 230, 0, 0},
+       {0x1E01D, 230, 0, 0},
+       {0x1E01E, 230, 0, 0},
+       {0x1E01F, 230, 0, 0},
+       {0x1E020, 230, 0, 0},
+       {0x1E021, 230, 0, 0},
+       {0x1E023, 230, 0, 0},
+       {0x1E024, 230, 0, 0},
+       {0x1E026, 230, 0, 0},
+       {0x1E027, 230, 0, 0},
+       {0x1E028, 230, 0, 0},
+       {0x1E029, 230, 0, 0},
+       {0x1E02A, 230, 0, 0},
+       {0x1E8D0, 220, 0, 0},
+       {0x1E8D1, 220, 0, 0},
+       {0x1E8D2, 220, 0, 0},
+       {0x1E8D3, 220, 0, 0},
+       {0x1E8D4, 220, 0, 0},
+       {0x1E8D5, 220, 0, 0},
+       {0x1E8D6, 220, 0, 0},
+       {0x1E944, 230, 0, 0},
+       {0x1E945, 230, 0, 0},
+       {0x1E946, 230, 0, 0},
+       {0x1E947, 230, 0, 0},
+       {0x1E948, 230, 0, 0},
+       {0x1E949, 230, 0, 0},
+       {0x1E94A, 7, 0, 0},
+       {0x1EE00, 0, 1 | DECOMP_INLINE, 0x0627},
+       {0x1EE01, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0x1EE02, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EE03, 0, 1 | DECOMP_INLINE, 0x062F},
+       {0x1EE05, 0, 1 | DECOMP_INLINE, 0x0648},
+       {0x1EE06, 0, 1 | DECOMP_INLINE, 0x0632},
+       {0x1EE07, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EE08, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0x1EE09, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EE0A, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0x1EE0B, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0x1EE0C, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0x1EE0D, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EE0E, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EE0F, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EE10, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0x1EE11, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EE12, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EE13, 0, 1 | DECOMP_INLINE, 0x0631},
+       {0x1EE14, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EE15, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0x1EE16, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0x1EE17, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EE18, 0, 1 | DECOMP_INLINE, 0x0630},
+       {0x1EE19, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EE1A, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0x1EE1B, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1EE1C, 0, 1 | DECOMP_INLINE, 0x066E},
+       {0x1EE1D, 0, 1 | DECOMP_INLINE, 0x06BA},
+       {0x1EE1E, 0, 1 | DECOMP_INLINE, 0x06A1},
+       {0x1EE1F, 0, 1 | DECOMP_INLINE, 0x066F},
+       {0x1EE21, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0x1EE22, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EE24, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0x1EE27, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EE29, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EE2A, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0x1EE2B, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0x1EE2C, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0x1EE2D, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EE2E, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EE2F, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EE30, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0x1EE31, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EE32, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EE34, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EE35, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0x1EE36, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0x1EE37, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EE39, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EE3B, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1EE42, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EE47, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EE49, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EE4B, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0x1EE4D, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EE4E, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EE4F, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EE51, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EE52, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EE54, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EE57, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EE59, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EE5B, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1EE5D, 0, 1 | DECOMP_INLINE, 0x06BA},
+       {0x1EE5F, 0, 1 | DECOMP_INLINE, 0x066F},
+       {0x1EE61, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0x1EE62, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EE64, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0x1EE67, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EE68, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0x1EE69, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EE6A, 0, 1 | DECOMP_INLINE, 0x0643},
+       {0x1EE6C, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0x1EE6D, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EE6E, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EE6F, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EE70, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0x1EE71, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EE72, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EE74, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EE75, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0x1EE76, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0x1EE77, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EE79, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EE7A, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0x1EE7B, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1EE7C, 0, 1 | DECOMP_INLINE, 0x066E},
+       {0x1EE7E, 0, 1 | DECOMP_INLINE, 0x06A1},
+       {0x1EE80, 0, 1 | DECOMP_INLINE, 0x0627},
+       {0x1EE81, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0x1EE82, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EE83, 0, 1 | DECOMP_INLINE, 0x062F},
+       {0x1EE84, 0, 1 | DECOMP_INLINE, 0x0647},
+       {0x1EE85, 0, 1 | DECOMP_INLINE, 0x0648},
+       {0x1EE86, 0, 1 | DECOMP_INLINE, 0x0632},
+       {0x1EE87, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EE88, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0x1EE89, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EE8B, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0x1EE8C, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0x1EE8D, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EE8E, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EE8F, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EE90, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0x1EE91, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EE92, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EE93, 0, 1 | DECOMP_INLINE, 0x0631},
+       {0x1EE94, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EE95, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0x1EE96, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0x1EE97, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EE98, 0, 1 | DECOMP_INLINE, 0x0630},
+       {0x1EE99, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EE9A, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0x1EE9B, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1EEA1, 0, 1 | DECOMP_INLINE, 0x0628},
+       {0x1EEA2, 0, 1 | DECOMP_INLINE, 0x062C},
+       {0x1EEA3, 0, 1 | DECOMP_INLINE, 0x062F},
+       {0x1EEA5, 0, 1 | DECOMP_INLINE, 0x0648},
+       {0x1EEA6, 0, 1 | DECOMP_INLINE, 0x0632},
+       {0x1EEA7, 0, 1 | DECOMP_INLINE, 0x062D},
+       {0x1EEA8, 0, 1 | DECOMP_INLINE, 0x0637},
+       {0x1EEA9, 0, 1 | DECOMP_INLINE, 0x064A},
+       {0x1EEAB, 0, 1 | DECOMP_INLINE, 0x0644},
+       {0x1EEAC, 0, 1 | DECOMP_INLINE, 0x0645},
+       {0x1EEAD, 0, 1 | DECOMP_INLINE, 0x0646},
+       {0x1EEAE, 0, 1 | DECOMP_INLINE, 0x0633},
+       {0x1EEAF, 0, 1 | DECOMP_INLINE, 0x0639},
+       {0x1EEB0, 0, 1 | DECOMP_INLINE, 0x0641},
+       {0x1EEB1, 0, 1 | DECOMP_INLINE, 0x0635},
+       {0x1EEB2, 0, 1 | DECOMP_INLINE, 0x0642},
+       {0x1EEB3, 0, 1 | DECOMP_INLINE, 0x0631},
+       {0x1EEB4, 0, 1 | DECOMP_INLINE, 0x0634},
+       {0x1EEB5, 0, 1 | DECOMP_INLINE, 0x062A},
+       {0x1EEB6, 0, 1 | DECOMP_INLINE, 0x062B},
+       {0x1EEB7, 0, 1 | DECOMP_INLINE, 0x062E},
+       {0x1EEB8, 0, 1 | DECOMP_INLINE, 0x0630},
+       {0x1EEB9, 0, 1 | DECOMP_INLINE, 0x0636},
+       {0x1EEBA, 0, 1 | DECOMP_INLINE, 0x0638},
+       {0x1EEBB, 0, 1 | DECOMP_INLINE, 0x063A},
+       {0x1F100, 0, 2 | DECOMP_NO_COMPOSE, 4824},      /* compatibility mapping */
+       {0x1F101, 0, 2 | DECOMP_NO_COMPOSE, 4826},      /* compatibility mapping */
+       {0x1F102, 0, 2 | DECOMP_NO_COMPOSE, 4828},      /* compatibility mapping */
+       {0x1F103, 0, 2 | DECOMP_NO_COMPOSE, 4830},      /* compatibility mapping */
+       {0x1F104, 0, 2 | DECOMP_NO_COMPOSE, 4832},      /* compatibility mapping */
+       {0x1F105, 0, 2 | DECOMP_NO_COMPOSE, 4834},      /* compatibility mapping */
+       {0x1F106, 0, 2 | DECOMP_NO_COMPOSE, 4836},      /* compatibility mapping */
+       {0x1F107, 0, 2 | DECOMP_NO_COMPOSE, 4838},      /* compatibility mapping */
+       {0x1F108, 0, 2 | DECOMP_NO_COMPOSE, 4840},      /* compatibility mapping */
+       {0x1F109, 0, 2 | DECOMP_NO_COMPOSE, 4842},      /* compatibility mapping */
+       {0x1F10A, 0, 2 | DECOMP_NO_COMPOSE, 4844},      /* compatibility mapping */
+       {0x1F110, 0, 3, 4846},
+       {0x1F111, 0, 3, 4849},
+       {0x1F112, 0, 3, 4852},
+       {0x1F113, 0, 3, 4855},
+       {0x1F114, 0, 3, 4858},
+       {0x1F115, 0, 3, 4861},
+       {0x1F116, 0, 3, 4864},
+       {0x1F117, 0, 3, 4867},
+       {0x1F118, 0, 3, 4870},
+       {0x1F119, 0, 3, 4873},
+       {0x1F11A, 0, 3, 4876},
+       {0x1F11B, 0, 3, 4879},
+       {0x1F11C, 0, 3, 4882},
+       {0x1F11D, 0, 3, 4885},
+       {0x1F11E, 0, 3, 4888},
+       {0x1F11F, 0, 3, 4891},
+       {0x1F120, 0, 3, 4894},
+       {0x1F121, 0, 3, 4897},
+       {0x1F122, 0, 3, 4900},
+       {0x1F123, 0, 3, 4903},
+       {0x1F124, 0, 3, 4906},
+       {0x1F125, 0, 3, 4909},
+       {0x1F126, 0, 3, 4912},
+       {0x1F127, 0, 3, 4915},
+       {0x1F128, 0, 3, 4918},
+       {0x1F129, 0, 3, 4921},
+       {0x1F12A, 0, 3, 4924},
+       {0x1F12B, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1F12C, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1F12D, 0, 2 | DECOMP_NO_COMPOSE, 4927},      /* compatibility mapping */
+       {0x1F12E, 0, 2 | DECOMP_NO_COMPOSE, 4929},      /* compatibility mapping */
+       {0x1F130, 0, 1 | DECOMP_INLINE, 0x0041},
+       {0x1F131, 0, 1 | DECOMP_INLINE, 0x0042},
+       {0x1F132, 0, 1 | DECOMP_INLINE, 0x0043},
+       {0x1F133, 0, 1 | DECOMP_INLINE, 0x0044},
+       {0x1F134, 0, 1 | DECOMP_INLINE, 0x0045},
+       {0x1F135, 0, 1 | DECOMP_INLINE, 0x0046},
+       {0x1F136, 0, 1 | DECOMP_INLINE, 0x0047},
+       {0x1F137, 0, 1 | DECOMP_INLINE, 0x0048},
+       {0x1F138, 0, 1 | DECOMP_INLINE, 0x0049},
+       {0x1F139, 0, 1 | DECOMP_INLINE, 0x004A},
+       {0x1F13A, 0, 1 | DECOMP_INLINE, 0x004B},
+       {0x1F13B, 0, 1 | DECOMP_INLINE, 0x004C},
+       {0x1F13C, 0, 1 | DECOMP_INLINE, 0x004D},
+       {0x1F13D, 0, 1 | DECOMP_INLINE, 0x004E},
+       {0x1F13E, 0, 1 | DECOMP_INLINE, 0x004F},
+       {0x1F13F, 0, 1 | DECOMP_INLINE, 0x0050},
+       {0x1F140, 0, 1 | DECOMP_INLINE, 0x0051},
+       {0x1F141, 0, 1 | DECOMP_INLINE, 0x0052},
+       {0x1F142, 0, 1 | DECOMP_INLINE, 0x0053},
+       {0x1F143, 0, 1 | DECOMP_INLINE, 0x0054},
+       {0x1F144, 0, 1 | DECOMP_INLINE, 0x0055},
+       {0x1F145, 0, 1 | DECOMP_INLINE, 0x0056},
+       {0x1F146, 0, 1 | DECOMP_INLINE, 0x0057},
+       {0x1F147, 0, 1 | DECOMP_INLINE, 0x0058},
+       {0x1F148, 0, 1 | DECOMP_INLINE, 0x0059},
+       {0x1F149, 0, 1 | DECOMP_INLINE, 0x005A},
+       {0x1F14A, 0, 2 | DECOMP_NO_COMPOSE, 4931},      /* compatibility mapping */
+       {0x1F14B, 0, 2 | DECOMP_NO_COMPOSE, 4933},      /* compatibility mapping */
+       {0x1F14C, 0, 2 | DECOMP_NO_COMPOSE, 4935},      /* compatibility mapping */
+       {0x1F14D, 0, 2 | DECOMP_NO_COMPOSE, 4937},      /* compatibility mapping */
+       {0x1F14E, 0, 3, 4939},
+       {0x1F14F, 0, 2 | DECOMP_NO_COMPOSE, 4942},      /* compatibility mapping */
+       {0x1F16A, 0, 2 | DECOMP_NO_COMPOSE, 4944},      /* compatibility mapping */
+       {0x1F16B, 0, 2 | DECOMP_NO_COMPOSE, 4946},      /* compatibility mapping */
+       {0x1F190, 0, 2 | DECOMP_NO_COMPOSE, 4948},      /* compatibility mapping */
+       {0x1F200, 0, 2 | DECOMP_NO_COMPOSE, 4950},      /* compatibility mapping */
+       {0x1F201, 0, 2 | DECOMP_NO_COMPOSE, 4952},      /* compatibility mapping */
+       {0x1F202, 0, 1 | DECOMP_INLINE, 0x30B5},
+       {0x1F210, 0, 1 | DECOMP_INLINE, 0x624B},
+       {0x1F211, 0, 1 | DECOMP_INLINE, 0x5B57},
+       {0x1F212, 0, 1 | DECOMP_INLINE, 0x53CC},
+       {0x1F213, 0, 1 | DECOMP_INLINE, 0x30C7},
+       {0x1F214, 0, 1 | DECOMP_INLINE, 0x4E8C},
+       {0x1F215, 0, 1 | DECOMP_INLINE, 0x591A},
+       {0x1F216, 0, 1 | DECOMP_INLINE, 0x89E3},
+       {0x1F217, 0, 1 | DECOMP_INLINE, 0x5929},
+       {0x1F218, 0, 1 | DECOMP_INLINE, 0x4EA4},
+       {0x1F219, 0, 1 | DECOMP_INLINE, 0x6620},
+       {0x1F21A, 0, 1 | DECOMP_INLINE, 0x7121},
+       {0x1F21B, 0, 1 | DECOMP_INLINE, 0x6599},
+       {0x1F21C, 0, 1 | DECOMP_INLINE, 0x524D},
+       {0x1F21D, 0, 1 | DECOMP_INLINE, 0x5F8C},
+       {0x1F21E, 0, 1 | DECOMP_INLINE, 0x518D},
+       {0x1F21F, 0, 1 | DECOMP_INLINE, 0x65B0},
+       {0x1F220, 0, 1 | DECOMP_INLINE, 0x521D},
+       {0x1F221, 0, 1 | DECOMP_INLINE, 0x7D42},
+       {0x1F222, 0, 1 | DECOMP_INLINE, 0x751F},
+       {0x1F223, 0, 1 | DECOMP_INLINE, 0x8CA9},
+       {0x1F224, 0, 1 | DECOMP_INLINE, 0x58F0},
+       {0x1F225, 0, 1 | DECOMP_INLINE, 0x5439},
+       {0x1F226, 0, 1 | DECOMP_INLINE, 0x6F14},
+       {0x1F227, 0, 1 | DECOMP_INLINE, 0x6295},
+       {0x1F228, 0, 1 | DECOMP_INLINE, 0x6355},
+       {0x1F229, 0, 1 | DECOMP_INLINE, 0x4E00},
+       {0x1F22A, 0, 1 | DECOMP_INLINE, 0x4E09},
+       {0x1F22B, 0, 1 | DECOMP_INLINE, 0x904A},
+       {0x1F22C, 0, 1 | DECOMP_INLINE, 0x5DE6},
+       {0x1F22D, 0, 1 | DECOMP_INLINE, 0x4E2D},
+       {0x1F22E, 0, 1 | DECOMP_INLINE, 0x53F3},
+       {0x1F22F, 0, 1 | DECOMP_INLINE, 0x6307},
+       {0x1F230, 0, 1 | DECOMP_INLINE, 0x8D70},
+       {0x1F231, 0, 1 | DECOMP_INLINE, 0x6253},
+       {0x1F232, 0, 1 | DECOMP_INLINE, 0x7981},
+       {0x1F233, 0, 1 | DECOMP_INLINE, 0x7A7A},
+       {0x1F234, 0, 1 | DECOMP_INLINE, 0x5408},
+       {0x1F235, 0, 1 | DECOMP_INLINE, 0x6E80},
+       {0x1F236, 0, 1 | DECOMP_INLINE, 0x6709},
+       {0x1F237, 0, 1 | DECOMP_INLINE, 0x6708},
+       {0x1F238, 0, 1 | DECOMP_INLINE, 0x7533},
+       {0x1F239, 0, 1 | DECOMP_INLINE, 0x5272},
+       {0x1F23A, 0, 1 | DECOMP_INLINE, 0x55B6},
+       {0x1F23B, 0, 1 | DECOMP_INLINE, 0x914D},
+       {0x1F240, 0, 3, 4954},
+       {0x1F241, 0, 3, 4957},
+       {0x1F242, 0, 3, 4960},
+       {0x1F243, 0, 3, 4963},
+       {0x1F244, 0, 3, 4966},
+       {0x1F245, 0, 3, 4969},
+       {0x1F246, 0, 3, 4972},
+       {0x1F247, 0, 3, 4975},
+       {0x1F248, 0, 3, 4978},
+       {0x1F250, 0, 1 | DECOMP_INLINE, 0x5F97},
+       {0x1F251, 0, 1 | DECOMP_INLINE, 0x53EF},
+       {0x2F800, 0, 1 | DECOMP_INLINE, 0x4E3D},
+       {0x2F801, 0, 1 | DECOMP_INLINE, 0x4E38},
+       {0x2F802, 0, 1 | DECOMP_INLINE, 0x4E41},
+       {0x2F803, 0, 1, 4981},
+       {0x2F804, 0, 1 | DECOMP_INLINE, 0x4F60},
+       {0x2F805, 0, 1 | DECOMP_INLINE, 0x4FAE},
+       {0x2F806, 0, 1 | DECOMP_INLINE, 0x4FBB},
+       {0x2F807, 0, 1 | DECOMP_INLINE, 0x5002},
+       {0x2F808, 0, 1 | DECOMP_INLINE, 0x507A},
+       {0x2F809, 0, 1 | DECOMP_INLINE, 0x5099},
+       {0x2F80A, 0, 1 | DECOMP_INLINE, 0x50E7},
+       {0x2F80B, 0, 1 | DECOMP_INLINE, 0x50CF},
+       {0x2F80C, 0, 1 | DECOMP_INLINE, 0x349E},
+       {0x2F80D, 0, 1, 4982},
+       {0x2F80E, 0, 1 | DECOMP_INLINE, 0x514D},
+       {0x2F80F, 0, 1 | DECOMP_INLINE, 0x5154},
+       {0x2F810, 0, 1 | DECOMP_INLINE, 0x5164},
+       {0x2F811, 0, 1 | DECOMP_INLINE, 0x5177},
+       {0x2F812, 0, 1, 4983},
+       {0x2F813, 0, 1 | DECOMP_INLINE, 0x34B9},
+       {0x2F814, 0, 1 | DECOMP_INLINE, 0x5167},
+       {0x2F815, 0, 1 | DECOMP_INLINE, 0x518D},
+       {0x2F816, 0, 1, 4984},
+       {0x2F817, 0, 1 | DECOMP_INLINE, 0x5197},
+       {0x2F818, 0, 1 | DECOMP_INLINE, 0x51A4},
+       {0x2F819, 0, 1 | DECOMP_INLINE, 0x4ECC},
+       {0x2F81A, 0, 1 | DECOMP_INLINE, 0x51AC},
+       {0x2F81B, 0, 1 | DECOMP_INLINE, 0x51B5},
+       {0x2F81C, 0, 1, 4985},
+       {0x2F81D, 0, 1 | DECOMP_INLINE, 0x51F5},
+       {0x2F81E, 0, 1 | DECOMP_INLINE, 0x5203},
+       {0x2F81F, 0, 1 | DECOMP_INLINE, 0x34DF},
+       {0x2F820, 0, 1 | DECOMP_INLINE, 0x523B},
+       {0x2F821, 0, 1 | DECOMP_INLINE, 0x5246},
+       {0x2F822, 0, 1 | DECOMP_INLINE, 0x5272},
+       {0x2F823, 0, 1 | DECOMP_INLINE, 0x5277},
+       {0x2F824, 0, 1 | DECOMP_INLINE, 0x3515},
+       {0x2F825, 0, 1 | DECOMP_INLINE, 0x52C7},
+       {0x2F826, 0, 1 | DECOMP_INLINE, 0x52C9},
+       {0x2F827, 0, 1 | DECOMP_INLINE, 0x52E4},
+       {0x2F828, 0, 1 | DECOMP_INLINE, 0x52FA},
+       {0x2F829, 0, 1 | DECOMP_INLINE, 0x5305},
+       {0x2F82A, 0, 1 | DECOMP_INLINE, 0x5306},
+       {0x2F82B, 0, 1 | DECOMP_INLINE, 0x5317},
+       {0x2F82C, 0, 1 | DECOMP_INLINE, 0x5349},
+       {0x2F82D, 0, 1 | DECOMP_INLINE, 0x5351},
+       {0x2F82E, 0, 1 | DECOMP_INLINE, 0x535A},
+       {0x2F82F, 0, 1 | DECOMP_INLINE, 0x5373},
+       {0x2F830, 0, 1 | DECOMP_INLINE, 0x537D},
+       {0x2F831, 0, 1 | DECOMP_INLINE, 0x537F},
+       {0x2F832, 0, 1 | DECOMP_INLINE, 0x537F},
+       {0x2F833, 0, 1 | DECOMP_INLINE, 0x537F},
+       {0x2F834, 0, 1, 4986},
+       {0x2F835, 0, 1 | DECOMP_INLINE, 0x7070},
+       {0x2F836, 0, 1 | DECOMP_INLINE, 0x53CA},
+       {0x2F837, 0, 1 | DECOMP_INLINE, 0x53DF},
+       {0x2F838, 0, 1, 4987},
+       {0x2F839, 0, 1 | DECOMP_INLINE, 0x53EB},
+       {0x2F83A, 0, 1 | DECOMP_INLINE, 0x53F1},
+       {0x2F83B, 0, 1 | DECOMP_INLINE, 0x5406},
+       {0x2F83C, 0, 1 | DECOMP_INLINE, 0x549E},
+       {0x2F83D, 0, 1 | DECOMP_INLINE, 0x5438},
+       {0x2F83E, 0, 1 | DECOMP_INLINE, 0x5448},
+       {0x2F83F, 0, 1 | DECOMP_INLINE, 0x5468},
+       {0x2F840, 0, 1 | DECOMP_INLINE, 0x54A2},
+       {0x2F841, 0, 1 | DECOMP_INLINE, 0x54F6},
+       {0x2F842, 0, 1 | DECOMP_INLINE, 0x5510},
+       {0x2F843, 0, 1 | DECOMP_INLINE, 0x5553},
+       {0x2F844, 0, 1 | DECOMP_INLINE, 0x5563},
+       {0x2F845, 0, 1 | DECOMP_INLINE, 0x5584},
+       {0x2F846, 0, 1 | DECOMP_INLINE, 0x5584},
+       {0x2F847, 0, 1 | DECOMP_INLINE, 0x5599},
+       {0x2F848, 0, 1 | DECOMP_INLINE, 0x55AB},
+       {0x2F849, 0, 1 | DECOMP_INLINE, 0x55B3},
+       {0x2F84A, 0, 1 | DECOMP_INLINE, 0x55C2},
+       {0x2F84B, 0, 1 | DECOMP_INLINE, 0x5716},
+       {0x2F84C, 0, 1 | DECOMP_INLINE, 0x5606},
+       {0x2F84D, 0, 1 | DECOMP_INLINE, 0x5717},
+       {0x2F84E, 0, 1 | DECOMP_INLINE, 0x5651},
+       {0x2F84F, 0, 1 | DECOMP_INLINE, 0x5674},
+       {0x2F850, 0, 1 | DECOMP_INLINE, 0x5207},
+       {0x2F851, 0, 1 | DECOMP_INLINE, 0x58EE},
+       {0x2F852, 0, 1 | DECOMP_INLINE, 0x57CE},
+       {0x2F853, 0, 1 | DECOMP_INLINE, 0x57F4},
+       {0x2F854, 0, 1 | DECOMP_INLINE, 0x580D},
+       {0x2F855, 0, 1 | DECOMP_INLINE, 0x578B},
+       {0x2F856, 0, 1 | DECOMP_INLINE, 0x5832},
+       {0x2F857, 0, 1 | DECOMP_INLINE, 0x5831},
+       {0x2F858, 0, 1 | DECOMP_INLINE, 0x58AC},
+       {0x2F859, 0, 1, 4988},
+       {0x2F85A, 0, 1 | DECOMP_INLINE, 0x58F2},
+       {0x2F85B, 0, 1 | DECOMP_INLINE, 0x58F7},
+       {0x2F85C, 0, 1 | DECOMP_INLINE, 0x5906},
+       {0x2F85D, 0, 1 | DECOMP_INLINE, 0x591A},
+       {0x2F85E, 0, 1 | DECOMP_INLINE, 0x5922},
+       {0x2F85F, 0, 1 | DECOMP_INLINE, 0x5962},
+       {0x2F860, 0, 1, 4989},
+       {0x2F861, 0, 1, 4990},
+       {0x2F862, 0, 1 | DECOMP_INLINE, 0x59EC},
+       {0x2F863, 0, 1 | DECOMP_INLINE, 0x5A1B},
+       {0x2F864, 0, 1 | DECOMP_INLINE, 0x5A27},
+       {0x2F865, 0, 1 | DECOMP_INLINE, 0x59D8},
+       {0x2F866, 0, 1 | DECOMP_INLINE, 0x5A66},
+       {0x2F867, 0, 1 | DECOMP_INLINE, 0x36EE},
+       {0x2F868, 0, 1 | DECOMP_INLINE, 0x36FC},
+       {0x2F869, 0, 1 | DECOMP_INLINE, 0x5B08},
+       {0x2F86A, 0, 1 | DECOMP_INLINE, 0x5B3E},
+       {0x2F86B, 0, 1 | DECOMP_INLINE, 0x5B3E},
+       {0x2F86C, 0, 1, 4991},
+       {0x2F86D, 0, 1 | DECOMP_INLINE, 0x5BC3},
+       {0x2F86E, 0, 1 | DECOMP_INLINE, 0x5BD8},
+       {0x2F86F, 0, 1 | DECOMP_INLINE, 0x5BE7},
+       {0x2F870, 0, 1 | DECOMP_INLINE, 0x5BF3},
+       {0x2F871, 0, 1, 4992},
+       {0x2F872, 0, 1 | DECOMP_INLINE, 0x5BFF},
+       {0x2F873, 0, 1 | DECOMP_INLINE, 0x5C06},
+       {0x2F874, 0, 1 | DECOMP_INLINE, 0x5F53},
+       {0x2F875, 0, 1 | DECOMP_INLINE, 0x5C22},
+       {0x2F876, 0, 1 | DECOMP_INLINE, 0x3781},
+       {0x2F877, 0, 1 | DECOMP_INLINE, 0x5C60},
+       {0x2F878, 0, 1 | DECOMP_INLINE, 0x5C6E},
+       {0x2F879, 0, 1 | DECOMP_INLINE, 0x5CC0},
+       {0x2F87A, 0, 1 | DECOMP_INLINE, 0x5C8D},
+       {0x2F87B, 0, 1, 4993},
+       {0x2F87C, 0, 1 | DECOMP_INLINE, 0x5D43},
+       {0x2F87D, 0, 1, 4994},
+       {0x2F87E, 0, 1 | DECOMP_INLINE, 0x5D6E},
+       {0x2F87F, 0, 1 | DECOMP_INLINE, 0x5D6B},
+       {0x2F880, 0, 1 | DECOMP_INLINE, 0x5D7C},
+       {0x2F881, 0, 1 | DECOMP_INLINE, 0x5DE1},
+       {0x2F882, 0, 1 | DECOMP_INLINE, 0x5DE2},
+       {0x2F883, 0, 1 | DECOMP_INLINE, 0x382F},
+       {0x2F884, 0, 1 | DECOMP_INLINE, 0x5DFD},
+       {0x2F885, 0, 1 | DECOMP_INLINE, 0x5E28},
+       {0x2F886, 0, 1 | DECOMP_INLINE, 0x5E3D},
+       {0x2F887, 0, 1 | DECOMP_INLINE, 0x5E69},
+       {0x2F888, 0, 1 | DECOMP_INLINE, 0x3862},
+       {0x2F889, 0, 1, 4995},
+       {0x2F88A, 0, 1 | DECOMP_INLINE, 0x387C},
+       {0x2F88B, 0, 1 | DECOMP_INLINE, 0x5EB0},
+       {0x2F88C, 0, 1 | DECOMP_INLINE, 0x5EB3},
+       {0x2F88D, 0, 1 | DECOMP_INLINE, 0x5EB6},
+       {0x2F88E, 0, 1 | DECOMP_INLINE, 0x5ECA},
+       {0x2F88F, 0, 1, 4996},
+       {0x2F890, 0, 1 | DECOMP_INLINE, 0x5EFE},
+       {0x2F891, 0, 1, 4997},
+       {0x2F892, 0, 1, 4998},
+       {0x2F893, 0, 1 | DECOMP_INLINE, 0x8201},
+       {0x2F894, 0, 1 | DECOMP_INLINE, 0x5F22},
+       {0x2F895, 0, 1 | DECOMP_INLINE, 0x5F22},
+       {0x2F896, 0, 1 | DECOMP_INLINE, 0x38C7},
+       {0x2F897, 0, 1, 4999},
+       {0x2F898, 0, 1, 5000},
+       {0x2F899, 0, 1 | DECOMP_INLINE, 0x5F62},
+       {0x2F89A, 0, 1 | DECOMP_INLINE, 0x5F6B},
+       {0x2F89B, 0, 1 | DECOMP_INLINE, 0x38E3},
+       {0x2F89C, 0, 1 | DECOMP_INLINE, 0x5F9A},
+       {0x2F89D, 0, 1 | DECOMP_INLINE, 0x5FCD},
+       {0x2F89E, 0, 1 | DECOMP_INLINE, 0x5FD7},
+       {0x2F89F, 0, 1 | DECOMP_INLINE, 0x5FF9},
+       {0x2F8A0, 0, 1 | DECOMP_INLINE, 0x6081},
+       {0x2F8A1, 0, 1 | DECOMP_INLINE, 0x393A},
+       {0x2F8A2, 0, 1 | DECOMP_INLINE, 0x391C},
+       {0x2F8A3, 0, 1 | DECOMP_INLINE, 0x6094},
+       {0x2F8A4, 0, 1, 5001},
+       {0x2F8A5, 0, 1 | DECOMP_INLINE, 0x60C7},
+       {0x2F8A6, 0, 1 | DECOMP_INLINE, 0x6148},
+       {0x2F8A7, 0, 1 | DECOMP_INLINE, 0x614C},
+       {0x2F8A8, 0, 1 | DECOMP_INLINE, 0x614E},
+       {0x2F8A9, 0, 1 | DECOMP_INLINE, 0x614C},
+       {0x2F8AA, 0, 1 | DECOMP_INLINE, 0x617A},
+       {0x2F8AB, 0, 1 | DECOMP_INLINE, 0x618E},
+       {0x2F8AC, 0, 1 | DECOMP_INLINE, 0x61B2},
+       {0x2F8AD, 0, 1 | DECOMP_INLINE, 0x61A4},
+       {0x2F8AE, 0, 1 | DECOMP_INLINE, 0x61AF},
+       {0x2F8AF, 0, 1 | DECOMP_INLINE, 0x61DE},
+       {0x2F8B0, 0, 1 | DECOMP_INLINE, 0x61F2},
+       {0x2F8B1, 0, 1 | DECOMP_INLINE, 0x61F6},
+       {0x2F8B2, 0, 1 | DECOMP_INLINE, 0x6210},
+       {0x2F8B3, 0, 1 | DECOMP_INLINE, 0x621B},
+       {0x2F8B4, 0, 1 | DECOMP_INLINE, 0x625D},
+       {0x2F8B5, 0, 1 | DECOMP_INLINE, 0x62B1},
+       {0x2F8B6, 0, 1 | DECOMP_INLINE, 0x62D4},
+       {0x2F8B7, 0, 1 | DECOMP_INLINE, 0x6350},
+       {0x2F8B8, 0, 1, 5002},
+       {0x2F8B9, 0, 1 | DECOMP_INLINE, 0x633D},
+       {0x2F8BA, 0, 1 | DECOMP_INLINE, 0x62FC},
+       {0x2F8BB, 0, 1 | DECOMP_INLINE, 0x6368},
+       {0x2F8BC, 0, 1 | DECOMP_INLINE, 0x6383},
+       {0x2F8BD, 0, 1 | DECOMP_INLINE, 0x63E4},
+       {0x2F8BE, 0, 1, 5003},
+       {0x2F8BF, 0, 1 | DECOMP_INLINE, 0x6422},
+       {0x2F8C0, 0, 1 | DECOMP_INLINE, 0x63C5},
+       {0x2F8C1, 0, 1 | DECOMP_INLINE, 0x63A9},
+       {0x2F8C2, 0, 1 | DECOMP_INLINE, 0x3A2E},
+       {0x2F8C3, 0, 1 | DECOMP_INLINE, 0x6469},
+       {0x2F8C4, 0, 1 | DECOMP_INLINE, 0x647E},
+       {0x2F8C5, 0, 1 | DECOMP_INLINE, 0x649D},
+       {0x2F8C6, 0, 1 | DECOMP_INLINE, 0x6477},
+       {0x2F8C7, 0, 1 | DECOMP_INLINE, 0x3A6C},
+       {0x2F8C8, 0, 1 | DECOMP_INLINE, 0x654F},
+       {0x2F8C9, 0, 1 | DECOMP_INLINE, 0x656C},
+       {0x2F8CA, 0, 1, 5004},
+       {0x2F8CB, 0, 1 | DECOMP_INLINE, 0x65E3},
+       {0x2F8CC, 0, 1 | DECOMP_INLINE, 0x66F8},
+       {0x2F8CD, 0, 1 | DECOMP_INLINE, 0x6649},
+       {0x2F8CE, 0, 1 | DECOMP_INLINE, 0x3B19},
+       {0x2F8CF, 0, 1 | DECOMP_INLINE, 0x6691},
+       {0x2F8D0, 0, 1 | DECOMP_INLINE, 0x3B08},
+       {0x2F8D1, 0, 1 | DECOMP_INLINE, 0x3AE4},
+       {0x2F8D2, 0, 1 | DECOMP_INLINE, 0x5192},
+       {0x2F8D3, 0, 1 | DECOMP_INLINE, 0x5195},
+       {0x2F8D4, 0, 1 | DECOMP_INLINE, 0x6700},
+       {0x2F8D5, 0, 1 | DECOMP_INLINE, 0x669C},
+       {0x2F8D6, 0, 1 | DECOMP_INLINE, 0x80AD},
+       {0x2F8D7, 0, 1 | DECOMP_INLINE, 0x43D9},
+       {0x2F8D8, 0, 1 | DECOMP_INLINE, 0x6717},
+       {0x2F8D9, 0, 1 | DECOMP_INLINE, 0x671B},
+       {0x2F8DA, 0, 1 | DECOMP_INLINE, 0x6721},
+       {0x2F8DB, 0, 1 | DECOMP_INLINE, 0x675E},
+       {0x2F8DC, 0, 1 | DECOMP_INLINE, 0x6753},
+       {0x2F8DD, 0, 1, 5005},
+       {0x2F8DE, 0, 1 | DECOMP_INLINE, 0x3B49},
+       {0x2F8DF, 0, 1 | DECOMP_INLINE, 0x67FA},
+       {0x2F8E0, 0, 1 | DECOMP_INLINE, 0x6785},
+       {0x2F8E1, 0, 1 | DECOMP_INLINE, 0x6852},
+       {0x2F8E2, 0, 1 | DECOMP_INLINE, 0x6885},
+       {0x2F8E3, 0, 1, 5006},
+       {0x2F8E4, 0, 1 | DECOMP_INLINE, 0x688E},
+       {0x2F8E5, 0, 1 | DECOMP_INLINE, 0x681F},
+       {0x2F8E6, 0, 1 | DECOMP_INLINE, 0x6914},
+       {0x2F8E7, 0, 1 | DECOMP_INLINE, 0x3B9D},
+       {0x2F8E8, 0, 1 | DECOMP_INLINE, 0x6942},
+       {0x2F8E9, 0, 1 | DECOMP_INLINE, 0x69A3},
+       {0x2F8EA, 0, 1 | DECOMP_INLINE, 0x69EA},
+       {0x2F8EB, 0, 1 | DECOMP_INLINE, 0x6AA8},
+       {0x2F8EC, 0, 1, 5007},
+       {0x2F8ED, 0, 1 | DECOMP_INLINE, 0x6ADB},
+       {0x2F8EE, 0, 1 | DECOMP_INLINE, 0x3C18},
+       {0x2F8EF, 0, 1 | DECOMP_INLINE, 0x6B21},
+       {0x2F8F0, 0, 1, 5008},
+       {0x2F8F1, 0, 1 | DECOMP_INLINE, 0x6B54},
+       {0x2F8F2, 0, 1 | DECOMP_INLINE, 0x3C4E},
+       {0x2F8F3, 0, 1 | DECOMP_INLINE, 0x6B72},
+       {0x2F8F4, 0, 1 | DECOMP_INLINE, 0x6B9F},
+       {0x2F8F5, 0, 1 | DECOMP_INLINE, 0x6BBA},
+       {0x2F8F6, 0, 1 | DECOMP_INLINE, 0x6BBB},
+       {0x2F8F7, 0, 1, 5009},
+       {0x2F8F8, 0, 1, 5010},
+       {0x2F8F9, 0, 1, 5011},
+       {0x2F8FA, 0, 1 | DECOMP_INLINE, 0x6C4E},
+       {0x2F8FB, 0, 1, 5012},
+       {0x2F8FC, 0, 1 | DECOMP_INLINE, 0x6CBF},
+       {0x2F8FD, 0, 1 | DECOMP_INLINE, 0x6CCD},
+       {0x2F8FE, 0, 1 | DECOMP_INLINE, 0x6C67},
+       {0x2F8FF, 0, 1 | DECOMP_INLINE, 0x6D16},
+       {0x2F900, 0, 1 | DECOMP_INLINE, 0x6D3E},
+       {0x2F901, 0, 1 | DECOMP_INLINE, 0x6D77},
+       {0x2F902, 0, 1 | DECOMP_INLINE, 0x6D41},
+       {0x2F903, 0, 1 | DECOMP_INLINE, 0x6D69},
+       {0x2F904, 0, 1 | DECOMP_INLINE, 0x6D78},
+       {0x2F905, 0, 1 | DECOMP_INLINE, 0x6D85},
+       {0x2F906, 0, 1, 5013},
+       {0x2F907, 0, 1 | DECOMP_INLINE, 0x6D34},
+       {0x2F908, 0, 1 | DECOMP_INLINE, 0x6E2F},
+       {0x2F909, 0, 1 | DECOMP_INLINE, 0x6E6E},
+       {0x2F90A, 0, 1 | DECOMP_INLINE, 0x3D33},
+       {0x2F90B, 0, 1 | DECOMP_INLINE, 0x6ECB},
+       {0x2F90C, 0, 1 | DECOMP_INLINE, 0x6EC7},
+       {0x2F90D, 0, 1, 5014},
+       {0x2F90E, 0, 1 | DECOMP_INLINE, 0x6DF9},
+       {0x2F90F, 0, 1 | DECOMP_INLINE, 0x6F6E},
+       {0x2F910, 0, 1, 5015},
+       {0x2F911, 0, 1, 5016},
+       {0x2F912, 0, 1 | DECOMP_INLINE, 0x6FC6},
+       {0x2F913, 0, 1 | DECOMP_INLINE, 0x7039},
+       {0x2F914, 0, 1 | DECOMP_INLINE, 0x701E},
+       {0x2F915, 0, 1 | DECOMP_INLINE, 0x701B},
+       {0x2F916, 0, 1 | DECOMP_INLINE, 0x3D96},
+       {0x2F917, 0, 1 | DECOMP_INLINE, 0x704A},
+       {0x2F918, 0, 1 | DECOMP_INLINE, 0x707D},
+       {0x2F919, 0, 1 | DECOMP_INLINE, 0x7077},
+       {0x2F91A, 0, 1 | DECOMP_INLINE, 0x70AD},
+       {0x2F91B, 0, 1, 5017},
+       {0x2F91C, 0, 1 | DECOMP_INLINE, 0x7145},
+       {0x2F91D, 0, 1, 5018},
+       {0x2F91E, 0, 1 | DECOMP_INLINE, 0x719C},
+       {0x2F91F, 0, 1, 5019},
+       {0x2F920, 0, 1 | DECOMP_INLINE, 0x7228},
+       {0x2F921, 0, 1 | DECOMP_INLINE, 0x7235},
+       {0x2F922, 0, 1 | DECOMP_INLINE, 0x7250},
+       {0x2F923, 0, 1, 5020},
+       {0x2F924, 0, 1 | DECOMP_INLINE, 0x7280},
+       {0x2F925, 0, 1 | DECOMP_INLINE, 0x7295},
+       {0x2F926, 0, 1, 5021},
+       {0x2F927, 0, 1, 5022},
+       {0x2F928, 0, 1 | DECOMP_INLINE, 0x737A},
+       {0x2F929, 0, 1 | DECOMP_INLINE, 0x738B},
+       {0x2F92A, 0, 1 | DECOMP_INLINE, 0x3EAC},
+       {0x2F92B, 0, 1 | DECOMP_INLINE, 0x73A5},
+       {0x2F92C, 0, 1 | DECOMP_INLINE, 0x3EB8},
+       {0x2F92D, 0, 1 | DECOMP_INLINE, 0x3EB8},
+       {0x2F92E, 0, 1 | DECOMP_INLINE, 0x7447},
+       {0x2F92F, 0, 1 | DECOMP_INLINE, 0x745C},
+       {0x2F930, 0, 1 | DECOMP_INLINE, 0x7471},
+       {0x2F931, 0, 1 | DECOMP_INLINE, 0x7485},
+       {0x2F932, 0, 1 | DECOMP_INLINE, 0x74CA},
+       {0x2F933, 0, 1 | DECOMP_INLINE, 0x3F1B},
+       {0x2F934, 0, 1 | DECOMP_INLINE, 0x7524},
+       {0x2F935, 0, 1, 5023},
+       {0x2F936, 0, 1 | DECOMP_INLINE, 0x753E},
+       {0x2F937, 0, 1, 5024},
+       {0x2F938, 0, 1 | DECOMP_INLINE, 0x7570},
+       {0x2F939, 0, 1, 5025},
+       {0x2F93A, 0, 1 | DECOMP_INLINE, 0x7610},
+       {0x2F93B, 0, 1, 5026},
+       {0x2F93C, 0, 1, 5027},
+       {0x2F93D, 0, 1, 5028},
+       {0x2F93E, 0, 1 | DECOMP_INLINE, 0x3FFC},
+       {0x2F93F, 0, 1 | DECOMP_INLINE, 0x4008},
+       {0x2F940, 0, 1 | DECOMP_INLINE, 0x76F4},
+       {0x2F941, 0, 1, 5029},
+       {0x2F942, 0, 1, 5030},
+       {0x2F943, 0, 1, 5031},
+       {0x2F944, 0, 1, 5032},
+       {0x2F945, 0, 1 | DECOMP_INLINE, 0x771E},
+       {0x2F946, 0, 1 | DECOMP_INLINE, 0x771F},
+       {0x2F947, 0, 1 | DECOMP_INLINE, 0x771F},
+       {0x2F948, 0, 1 | DECOMP_INLINE, 0x774A},
+       {0x2F949, 0, 1 | DECOMP_INLINE, 0x4039},
+       {0x2F94A, 0, 1 | DECOMP_INLINE, 0x778B},
+       {0x2F94B, 0, 1 | DECOMP_INLINE, 0x4046},
+       {0x2F94C, 0, 1 | DECOMP_INLINE, 0x4096},
+       {0x2F94D, 0, 1, 5033},
+       {0x2F94E, 0, 1 | DECOMP_INLINE, 0x784E},
+       {0x2F94F, 0, 1 | DECOMP_INLINE, 0x788C},
+       {0x2F950, 0, 1 | DECOMP_INLINE, 0x78CC},
+       {0x2F951, 0, 1 | DECOMP_INLINE, 0x40E3},
+       {0x2F952, 0, 1, 5034},
+       {0x2F953, 0, 1 | DECOMP_INLINE, 0x7956},
+       {0x2F954, 0, 1, 5035},
+       {0x2F955, 0, 1, 5036},
+       {0x2F956, 0, 1 | DECOMP_INLINE, 0x798F},
+       {0x2F957, 0, 1 | DECOMP_INLINE, 0x79EB},
+       {0x2F958, 0, 1 | DECOMP_INLINE, 0x412F},
+       {0x2F959, 0, 1 | DECOMP_INLINE, 0x7A40},
+       {0x2F95A, 0, 1 | DECOMP_INLINE, 0x7A4A},
+       {0x2F95B, 0, 1 | DECOMP_INLINE, 0x7A4F},
+       {0x2F95C, 0, 1, 5037},
+       {0x2F95D, 0, 1, 5038},
+       {0x2F95E, 0, 1, 5039},
+       {0x2F95F, 0, 1 | DECOMP_INLINE, 0x7AEE},
+       {0x2F960, 0, 1 | DECOMP_INLINE, 0x4202},
+       {0x2F961, 0, 1, 5040},
+       {0x2F962, 0, 1 | DECOMP_INLINE, 0x7BC6},
+       {0x2F963, 0, 1 | DECOMP_INLINE, 0x7BC9},
+       {0x2F964, 0, 1 | DECOMP_INLINE, 0x4227},
+       {0x2F965, 0, 1, 5041},
+       {0x2F966, 0, 1 | DECOMP_INLINE, 0x7CD2},
+       {0x2F967, 0, 1 | DECOMP_INLINE, 0x42A0},
+       {0x2F968, 0, 1 | DECOMP_INLINE, 0x7CE8},
+       {0x2F969, 0, 1 | DECOMP_INLINE, 0x7CE3},
+       {0x2F96A, 0, 1 | DECOMP_INLINE, 0x7D00},
+       {0x2F96B, 0, 1, 5042},
+       {0x2F96C, 0, 1 | DECOMP_INLINE, 0x7D63},
+       {0x2F96D, 0, 1 | DECOMP_INLINE, 0x4301},
+       {0x2F96E, 0, 1 | DECOMP_INLINE, 0x7DC7},
+       {0x2F96F, 0, 1 | DECOMP_INLINE, 0x7E02},
+       {0x2F970, 0, 1 | DECOMP_INLINE, 0x7E45},
+       {0x2F971, 0, 1 | DECOMP_INLINE, 0x4334},
+       {0x2F972, 0, 1, 5043},
+       {0x2F973, 0, 1, 5044},
+       {0x2F974, 0, 1 | DECOMP_INLINE, 0x4359},
+       {0x2F975, 0, 1, 5045},
+       {0x2F976, 0, 1 | DECOMP_INLINE, 0x7F7A},
+       {0x2F977, 0, 1, 5046},
+       {0x2F978, 0, 1 | DECOMP_INLINE, 0x7F95},
+       {0x2F979, 0, 1 | DECOMP_INLINE, 0x7FFA},
+       {0x2F97A, 0, 1 | DECOMP_INLINE, 0x8005},
+       {0x2F97B, 0, 1, 5047},
+       {0x2F97C, 0, 1, 5048},
+       {0x2F97D, 0, 1 | DECOMP_INLINE, 0x8060},
+       {0x2F97E, 0, 1, 5049},
+       {0x2F97F, 0, 1 | DECOMP_INLINE, 0x8070},
+       {0x2F980, 0, 1, 5050},
+       {0x2F981, 0, 1 | DECOMP_INLINE, 0x43D5},
+       {0x2F982, 0, 1 | DECOMP_INLINE, 0x80B2},
+       {0x2F983, 0, 1 | DECOMP_INLINE, 0x8103},
+       {0x2F984, 0, 1 | DECOMP_INLINE, 0x440B},
+       {0x2F985, 0, 1 | DECOMP_INLINE, 0x813E},
+       {0x2F986, 0, 1 | DECOMP_INLINE, 0x5AB5},
+       {0x2F987, 0, 1, 5051},
+       {0x2F988, 0, 1, 5052},
+       {0x2F989, 0, 1, 5053},
+       {0x2F98A, 0, 1, 5054},
+       {0x2F98B, 0, 1 | DECOMP_INLINE, 0x8201},
+       {0x2F98C, 0, 1 | DECOMP_INLINE, 0x8204},
+       {0x2F98D, 0, 1 | DECOMP_INLINE, 0x8F9E},
+       {0x2F98E, 0, 1 | DECOMP_INLINE, 0x446B},
+       {0x2F98F, 0, 1 | DECOMP_INLINE, 0x8291},
+       {0x2F990, 0, 1 | DECOMP_INLINE, 0x828B},
+       {0x2F991, 0, 1 | DECOMP_INLINE, 0x829D},
+       {0x2F992, 0, 1 | DECOMP_INLINE, 0x52B3},
+       {0x2F993, 0, 1 | DECOMP_INLINE, 0x82B1},
+       {0x2F994, 0, 1 | DECOMP_INLINE, 0x82B3},
+       {0x2F995, 0, 1 | DECOMP_INLINE, 0x82BD},
+       {0x2F996, 0, 1 | DECOMP_INLINE, 0x82E6},
+       {0x2F997, 0, 1, 5055},
+       {0x2F998, 0, 1 | DECOMP_INLINE, 0x82E5},
+       {0x2F999, 0, 1 | DECOMP_INLINE, 0x831D},
+       {0x2F99A, 0, 1 | DECOMP_INLINE, 0x8363},
+       {0x2F99B, 0, 1 | DECOMP_INLINE, 0x83AD},
+       {0x2F99C, 0, 1 | DECOMP_INLINE, 0x8323},
+       {0x2F99D, 0, 1 | DECOMP_INLINE, 0x83BD},
+       {0x2F99E, 0, 1 | DECOMP_INLINE, 0x83E7},
+       {0x2F99F, 0, 1 | DECOMP_INLINE, 0x8457},
+       {0x2F9A0, 0, 1 | DECOMP_INLINE, 0x8353},
+       {0x2F9A1, 0, 1 | DECOMP_INLINE, 0x83CA},
+       {0x2F9A2, 0, 1 | DECOMP_INLINE, 0x83CC},
+       {0x2F9A3, 0, 1 | DECOMP_INLINE, 0x83DC},
+       {0x2F9A4, 0, 1, 5056},
+       {0x2F9A5, 0, 1, 5057},
+       {0x2F9A6, 0, 1, 5058},
+       {0x2F9A7, 0, 1 | DECOMP_INLINE, 0x452B},
+       {0x2F9A8, 0, 1 | DECOMP_INLINE, 0x84F1},
+       {0x2F9A9, 0, 1 | DECOMP_INLINE, 0x84F3},
+       {0x2F9AA, 0, 1 | DECOMP_INLINE, 0x8516},
+       {0x2F9AB, 0, 1, 5059},
+       {0x2F9AC, 0, 1 | DECOMP_INLINE, 0x8564},
+       {0x2F9AD, 0, 1, 5060},
+       {0x2F9AE, 0, 1 | DECOMP_INLINE, 0x455D},
+       {0x2F9AF, 0, 1 | DECOMP_INLINE, 0x4561},
+       {0x2F9B0, 0, 1, 5061},
+       {0x2F9B1, 0, 1, 5062},
+       {0x2F9B2, 0, 1 | DECOMP_INLINE, 0x456B},
+       {0x2F9B3, 0, 1 | DECOMP_INLINE, 0x8650},
+       {0x2F9B4, 0, 1 | DECOMP_INLINE, 0x865C},
+       {0x2F9B5, 0, 1 | DECOMP_INLINE, 0x8667},
+       {0x2F9B6, 0, 1 | DECOMP_INLINE, 0x8669},
+       {0x2F9B7, 0, 1 | DECOMP_INLINE, 0x86A9},
+       {0x2F9B8, 0, 1 | DECOMP_INLINE, 0x8688},
+       {0x2F9B9, 0, 1 | DECOMP_INLINE, 0x870E},
+       {0x2F9BA, 0, 1 | DECOMP_INLINE, 0x86E2},
+       {0x2F9BB, 0, 1 | DECOMP_INLINE, 0x8779},
+       {0x2F9BC, 0, 1 | DECOMP_INLINE, 0x8728},
+       {0x2F9BD, 0, 1 | DECOMP_INLINE, 0x876B},
+       {0x2F9BE, 0, 1 | DECOMP_INLINE, 0x8786},
+       {0x2F9BF, 0, 1 | DECOMP_INLINE, 0x45D7},
+       {0x2F9C0, 0, 1 | DECOMP_INLINE, 0x87E1},
+       {0x2F9C1, 0, 1 | DECOMP_INLINE, 0x8801},
+       {0x2F9C2, 0, 1 | DECOMP_INLINE, 0x45F9},
+       {0x2F9C3, 0, 1 | DECOMP_INLINE, 0x8860},
+       {0x2F9C4, 0, 1 | DECOMP_INLINE, 0x8863},
+       {0x2F9C5, 0, 1, 5063},
+       {0x2F9C6, 0, 1 | DECOMP_INLINE, 0x88D7},
+       {0x2F9C7, 0, 1 | DECOMP_INLINE, 0x88DE},
+       {0x2F9C8, 0, 1 | DECOMP_INLINE, 0x4635},
+       {0x2F9C9, 0, 1 | DECOMP_INLINE, 0x88FA},
+       {0x2F9CA, 0, 1 | DECOMP_INLINE, 0x34BB},
+       {0x2F9CB, 0, 1, 5064},
+       {0x2F9CC, 0, 1, 5065},
+       {0x2F9CD, 0, 1 | DECOMP_INLINE, 0x46BE},
+       {0x2F9CE, 0, 1 | DECOMP_INLINE, 0x46C7},
+       {0x2F9CF, 0, 1 | DECOMP_INLINE, 0x8AA0},
+       {0x2F9D0, 0, 1 | DECOMP_INLINE, 0x8AED},
+       {0x2F9D1, 0, 1 | DECOMP_INLINE, 0x8B8A},
+       {0x2F9D2, 0, 1 | DECOMP_INLINE, 0x8C55},
+       {0x2F9D3, 0, 1, 5066},
+       {0x2F9D4, 0, 1 | DECOMP_INLINE, 0x8CAB},
+       {0x2F9D5, 0, 1 | DECOMP_INLINE, 0x8CC1},
+       {0x2F9D6, 0, 1 | DECOMP_INLINE, 0x8D1B},
+       {0x2F9D7, 0, 1 | DECOMP_INLINE, 0x8D77},
+       {0x2F9D8, 0, 1, 5067},
+       {0x2F9D9, 0, 1, 5068},
+       {0x2F9DA, 0, 1 | DECOMP_INLINE, 0x8DCB},
+       {0x2F9DB, 0, 1 | DECOMP_INLINE, 0x8DBC},
+       {0x2F9DC, 0, 1 | DECOMP_INLINE, 0x8DF0},
+       {0x2F9DD, 0, 1, 5069},
+       {0x2F9DE, 0, 1 | DECOMP_INLINE, 0x8ED4},
+       {0x2F9DF, 0, 1 | DECOMP_INLINE, 0x8F38},
+       {0x2F9E0, 0, 1, 5070},
+       {0x2F9E1, 0, 1, 5071},
+       {0x2F9E2, 0, 1 | DECOMP_INLINE, 0x9094},
+       {0x2F9E3, 0, 1 | DECOMP_INLINE, 0x90F1},
+       {0x2F9E4, 0, 1 | DECOMP_INLINE, 0x9111},
+       {0x2F9E5, 0, 1, 5072},
+       {0x2F9E6, 0, 1 | DECOMP_INLINE, 0x911B},
+       {0x2F9E7, 0, 1 | DECOMP_INLINE, 0x9238},
+       {0x2F9E8, 0, 1 | DECOMP_INLINE, 0x92D7},
+       {0x2F9E9, 0, 1 | DECOMP_INLINE, 0x92D8},
+       {0x2F9EA, 0, 1 | DECOMP_INLINE, 0x927C},
+       {0x2F9EB, 0, 1 | DECOMP_INLINE, 0x93F9},
+       {0x2F9EC, 0, 1 | DECOMP_INLINE, 0x9415},
+       {0x2F9ED, 0, 1, 5073},
+       {0x2F9EE, 0, 1 | DECOMP_INLINE, 0x958B},
+       {0x2F9EF, 0, 1 | DECOMP_INLINE, 0x4995},
+       {0x2F9F0, 0, 1 | DECOMP_INLINE, 0x95B7},
+       {0x2F9F1, 0, 1, 5074},
+       {0x2F9F2, 0, 1 | DECOMP_INLINE, 0x49E6},
+       {0x2F9F3, 0, 1 | DECOMP_INLINE, 0x96C3},
+       {0x2F9F4, 0, 1 | DECOMP_INLINE, 0x5DB2},
+       {0x2F9F5, 0, 1 | DECOMP_INLINE, 0x9723},
+       {0x2F9F6, 0, 1, 5075},
+       {0x2F9F7, 0, 1, 5076},
+       {0x2F9F8, 0, 1 | DECOMP_INLINE, 0x4A6E},
+       {0x2F9F9, 0, 1 | DECOMP_INLINE, 0x4A76},
+       {0x2F9FA, 0, 1 | DECOMP_INLINE, 0x97E0},
+       {0x2F9FB, 0, 1, 5077},
+       {0x2F9FC, 0, 1 | DECOMP_INLINE, 0x4AB2},
+       {0x2F9FD, 0, 1, 5078},
+       {0x2F9FE, 0, 1 | DECOMP_INLINE, 0x980B},
+       {0x2F9FF, 0, 1 | DECOMP_INLINE, 0x980B},
+       {0x2FA00, 0, 1 | DECOMP_INLINE, 0x9829},
+       {0x2FA01, 0, 1, 5079},
+       {0x2FA02, 0, 1 | DECOMP_INLINE, 0x98E2},
+       {0x2FA03, 0, 1 | DECOMP_INLINE, 0x4B33},
+       {0x2FA04, 0, 1 | DECOMP_INLINE, 0x9929},
+       {0x2FA05, 0, 1 | DECOMP_INLINE, 0x99A7},
+       {0x2FA06, 0, 1 | DECOMP_INLINE, 0x99C2},
+       {0x2FA07, 0, 1 | DECOMP_INLINE, 0x99FE},
+       {0x2FA08, 0, 1 | DECOMP_INLINE, 0x4BCE},
+       {0x2FA09, 0, 1, 5080},
+       {0x2FA0A, 0, 1 | DECOMP_INLINE, 0x9B12},
+       {0x2FA0B, 0, 1 | DECOMP_INLINE, 0x9C40},
+       {0x2FA0C, 0, 1 | DECOMP_INLINE, 0x9CFD},
+       {0x2FA0D, 0, 1 | DECOMP_INLINE, 0x4CCE},
+       {0x2FA0E, 0, 1 | DECOMP_INLINE, 0x4CED},
+       {0x2FA0F, 0, 1 | DECOMP_INLINE, 0x9D67},
+       {0x2FA10, 0, 1, 5081},
+       {0x2FA11, 0, 1 | DECOMP_INLINE, 0x4CF8},
+       {0x2FA12, 0, 1, 5082},
+       {0x2FA13, 0, 1, 5083},
+       {0x2FA14, 0, 1, 5084},
+       {0x2FA15, 0, 1 | DECOMP_INLINE, 0x9EBB},
+       {0x2FA16, 0, 1 | DECOMP_INLINE, 0x4D56},
+       {0x2FA17, 0, 1 | DECOMP_INLINE, 0x9EF9},
+       {0x2FA18, 0, 1 | DECOMP_INLINE, 0x9EFE},
+       {0x2FA19, 0, 1 | DECOMP_INLINE, 0x9F05},
+       {0x2FA1A, 0, 1 | DECOMP_INLINE, 0x9F0F},
+       {0x2FA1B, 0, 1 | DECOMP_INLINE, 0x9F16},
+       {0x2FA1C, 0, 1 | DECOMP_INLINE, 0x9F3B},
+       {0x2FA1D, 0, 1, 5085}
+
+};
+
+/* codepoints array  */
+static const uint32 UnicodeDecomp_codepoints[5086] =
+{
+        /* 0 */ 0x0020, 0x0308,
+        /* 2 */ 0x0020, 0x0304,
+        /* 4 */ 0x0020, 0x0301,
+        /* 6 */ 0x0020, 0x0327,
+        /* 8 */ 0x0031, 0x2044, 0x0034,
+        /* 11 */ 0x0031, 0x2044, 0x0032,
+        /* 14 */ 0x0033, 0x2044, 0x0034,
+        /* 17 */ 0x0041, 0x0300,
+        /* 19 */ 0x0041, 0x0301,
+        /* 21 */ 0x0041, 0x0302,
+        /* 23 */ 0x0041, 0x0303,
+        /* 25 */ 0x0041, 0x0308,
+        /* 27 */ 0x0041, 0x030A,
+        /* 29 */ 0x0043, 0x0327,
+        /* 31 */ 0x0045, 0x0300,
+        /* 33 */ 0x0045, 0x0301,
+        /* 35 */ 0x0045, 0x0302,
+        /* 37 */ 0x0045, 0x0308,
+        /* 39 */ 0x0049, 0x0300,
+        /* 41 */ 0x0049, 0x0301,
+        /* 43 */ 0x0049, 0x0302,
+        /* 45 */ 0x0049, 0x0308,
+        /* 47 */ 0x004E, 0x0303,
+        /* 49 */ 0x004F, 0x0300,
+        /* 51 */ 0x004F, 0x0301,
+        /* 53 */ 0x004F, 0x0302,
+        /* 55 */ 0x004F, 0x0303,
+        /* 57 */ 0x004F, 0x0308,
+        /* 59 */ 0x0055, 0x0300,
+        /* 61 */ 0x0055, 0x0301,
+        /* 63 */ 0x0055, 0x0302,
+        /* 65 */ 0x0055, 0x0308,
+        /* 67 */ 0x0059, 0x0301,
+        /* 69 */ 0x0061, 0x0300,
+        /* 71 */ 0x0061, 0x0301,
+        /* 73 */ 0x0061, 0x0302,
+        /* 75 */ 0x0061, 0x0303,
+        /* 77 */ 0x0061, 0x0308,
+        /* 79 */ 0x0061, 0x030A,
+        /* 81 */ 0x0063, 0x0327,
+        /* 83 */ 0x0065, 0x0300,
+        /* 85 */ 0x0065, 0x0301,
+        /* 87 */ 0x0065, 0x0302,
+        /* 89 */ 0x0065, 0x0308,
+        /* 91 */ 0x0069, 0x0300,
+        /* 93 */ 0x0069, 0x0301,
+        /* 95 */ 0x0069, 0x0302,
+        /* 97 */ 0x0069, 0x0308,
+        /* 99 */ 0x006E, 0x0303,
+        /* 101 */ 0x006F, 0x0300,
+        /* 103 */ 0x006F, 0x0301,
+        /* 105 */ 0x006F, 0x0302,
+        /* 107 */ 0x006F, 0x0303,
+        /* 109 */ 0x006F, 0x0308,
+        /* 111 */ 0x0075, 0x0300,
+        /* 113 */ 0x0075, 0x0301,
+        /* 115 */ 0x0075, 0x0302,
+        /* 117 */ 0x0075, 0x0308,
+        /* 119 */ 0x0079, 0x0301,
+        /* 121 */ 0x0079, 0x0308,
+        /* 123 */ 0x0041, 0x0304,
+        /* 125 */ 0x0061, 0x0304,
+        /* 127 */ 0x0041, 0x0306,
+        /* 129 */ 0x0061, 0x0306,
+        /* 131 */ 0x0041, 0x0328,
+        /* 133 */ 0x0061, 0x0328,
+        /* 135 */ 0x0043, 0x0301,
+        /* 137 */ 0x0063, 0x0301,
+        /* 139 */ 0x0043, 0x0302,
+        /* 141 */ 0x0063, 0x0302,
+        /* 143 */ 0x0043, 0x0307,
+        /* 145 */ 0x0063, 0x0307,
+        /* 147 */ 0x0043, 0x030C,
+        /* 149 */ 0x0063, 0x030C,
+        /* 151 */ 0x0044, 0x030C,
+        /* 153 */ 0x0064, 0x030C,
+        /* 155 */ 0x0045, 0x0304,
+        /* 157 */ 0x0065, 0x0304,
+        /* 159 */ 0x0045, 0x0306,
+        /* 161 */ 0x0065, 0x0306,
+        /* 163 */ 0x0045, 0x0307,
+        /* 165 */ 0x0065, 0x0307,
+        /* 167 */ 0x0045, 0x0328,
+        /* 169 */ 0x0065, 0x0328,
+        /* 171 */ 0x0045, 0x030C,
+        /* 173 */ 0x0065, 0x030C,
+        /* 175 */ 0x0047, 0x0302,
+        /* 177 */ 0x0067, 0x0302,
+        /* 179 */ 0x0047, 0x0306,
+        /* 181 */ 0x0067, 0x0306,
+        /* 183 */ 0x0047, 0x0307,
+        /* 185 */ 0x0067, 0x0307,
+        /* 187 */ 0x0047, 0x0327,
+        /* 189 */ 0x0067, 0x0327,
+        /* 191 */ 0x0048, 0x0302,
+        /* 193 */ 0x0068, 0x0302,
+        /* 195 */ 0x0049, 0x0303,
+        /* 197 */ 0x0069, 0x0303,
+        /* 199 */ 0x0049, 0x0304,
+        /* 201 */ 0x0069, 0x0304,
+        /* 203 */ 0x0049, 0x0306,
+        /* 205 */ 0x0069, 0x0306,
+        /* 207 */ 0x0049, 0x0328,
+        /* 209 */ 0x0069, 0x0328,
+        /* 211 */ 0x0049, 0x0307,
+        /* 213 */ 0x0049, 0x004A,
+        /* 215 */ 0x0069, 0x006A,
+        /* 217 */ 0x004A, 0x0302,
+        /* 219 */ 0x006A, 0x0302,
+        /* 221 */ 0x004B, 0x0327,
+        /* 223 */ 0x006B, 0x0327,
+        /* 225 */ 0x004C, 0x0301,
+        /* 227 */ 0x006C, 0x0301,
+        /* 229 */ 0x004C, 0x0327,
+        /* 231 */ 0x006C, 0x0327,
+        /* 233 */ 0x004C, 0x030C,
+        /* 235 */ 0x006C, 0x030C,
+        /* 237 */ 0x004C, 0x00B7,
+        /* 239 */ 0x006C, 0x00B7,
+        /* 241 */ 0x004E, 0x0301,
+        /* 243 */ 0x006E, 0x0301,
+        /* 245 */ 0x004E, 0x0327,
+        /* 247 */ 0x006E, 0x0327,
+        /* 249 */ 0x004E, 0x030C,
+        /* 251 */ 0x006E, 0x030C,
+        /* 253 */ 0x02BC, 0x006E,
+        /* 255 */ 0x004F, 0x0304,
+        /* 257 */ 0x006F, 0x0304,
+        /* 259 */ 0x004F, 0x0306,
+        /* 261 */ 0x006F, 0x0306,
+        /* 263 */ 0x004F, 0x030B,
+        /* 265 */ 0x006F, 0x030B,
+        /* 267 */ 0x0052, 0x0301,
+        /* 269 */ 0x0072, 0x0301,
+        /* 271 */ 0x0052, 0x0327,
+        /* 273 */ 0x0072, 0x0327,
+        /* 275 */ 0x0052, 0x030C,
+        /* 277 */ 0x0072, 0x030C,
+        /* 279 */ 0x0053, 0x0301,
+        /* 281 */ 0x0073, 0x0301,
+        /* 283 */ 0x0053, 0x0302,
+        /* 285 */ 0x0073, 0x0302,
+        /* 287 */ 0x0053, 0x0327,
+        /* 289 */ 0x0073, 0x0327,
+        /* 291 */ 0x0053, 0x030C,
+        /* 293 */ 0x0073, 0x030C,
+        /* 295 */ 0x0054, 0x0327,
+        /* 297 */ 0x0074, 0x0327,
+        /* 299 */ 0x0054, 0x030C,
+        /* 301 */ 0x0074, 0x030C,
+        /* 303 */ 0x0055, 0x0303,
+        /* 305 */ 0x0075, 0x0303,
+        /* 307 */ 0x0055, 0x0304,
+        /* 309 */ 0x0075, 0x0304,
+        /* 311 */ 0x0055, 0x0306,
+        /* 313 */ 0x0075, 0x0306,
+        /* 315 */ 0x0055, 0x030A,
+        /* 317 */ 0x0075, 0x030A,
+        /* 319 */ 0x0055, 0x030B,
+        /* 321 */ 0x0075, 0x030B,
+        /* 323 */ 0x0055, 0x0328,
+        /* 325 */ 0x0075, 0x0328,
+        /* 327 */ 0x0057, 0x0302,
+        /* 329 */ 0x0077, 0x0302,
+        /* 331 */ 0x0059, 0x0302,
+        /* 333 */ 0x0079, 0x0302,
+        /* 335 */ 0x0059, 0x0308,
+        /* 337 */ 0x005A, 0x0301,
+        /* 339 */ 0x007A, 0x0301,
+        /* 341 */ 0x005A, 0x0307,
+        /* 343 */ 0x007A, 0x0307,
+        /* 345 */ 0x005A, 0x030C,
+        /* 347 */ 0x007A, 0x030C,
+        /* 349 */ 0x004F, 0x031B,
+        /* 351 */ 0x006F, 0x031B,
+        /* 353 */ 0x0055, 0x031B,
+        /* 355 */ 0x0075, 0x031B,
+        /* 357 */ 0x0044, 0x017D,
+        /* 359 */ 0x0044, 0x017E,
+        /* 361 */ 0x0064, 0x017E,
+        /* 363 */ 0x004C, 0x004A,
+        /* 365 */ 0x004C, 0x006A,
+        /* 367 */ 0x006C, 0x006A,
+        /* 369 */ 0x004E, 0x004A,
+        /* 371 */ 0x004E, 0x006A,
+        /* 373 */ 0x006E, 0x006A,
+        /* 375 */ 0x0041, 0x030C,
+        /* 377 */ 0x0061, 0x030C,
+        /* 379 */ 0x0049, 0x030C,
+        /* 381 */ 0x0069, 0x030C,
+        /* 383 */ 0x004F, 0x030C,
+        /* 385 */ 0x006F, 0x030C,
+        /* 387 */ 0x0055, 0x030C,
+        /* 389 */ 0x0075, 0x030C,
+        /* 391 */ 0x00DC, 0x0304,
+        /* 393 */ 0x00FC, 0x0304,
+        /* 395 */ 0x00DC, 0x0301,
+        /* 397 */ 0x00FC, 0x0301,
+        /* 399 */ 0x00DC, 0x030C,
+        /* 401 */ 0x00FC, 0x030C,
+        /* 403 */ 0x00DC, 0x0300,
+        /* 405 */ 0x00FC, 0x0300,
+        /* 407 */ 0x00C4, 0x0304,
+        /* 409 */ 0x00E4, 0x0304,
+        /* 411 */ 0x0226, 0x0304,
+        /* 413 */ 0x0227, 0x0304,
+        /* 415 */ 0x00C6, 0x0304,
+        /* 417 */ 0x00E6, 0x0304,
+        /* 419 */ 0x0047, 0x030C,
+        /* 421 */ 0x0067, 0x030C,
+        /* 423 */ 0x004B, 0x030C,
+        /* 425 */ 0x006B, 0x030C,
+        /* 427 */ 0x004F, 0x0328,
+        /* 429 */ 0x006F, 0x0328,
+        /* 431 */ 0x01EA, 0x0304,
+        /* 433 */ 0x01EB, 0x0304,
+        /* 435 */ 0x01B7, 0x030C,
+        /* 437 */ 0x0292, 0x030C,
+        /* 439 */ 0x006A, 0x030C,
+        /* 441 */ 0x0044, 0x005A,
+        /* 443 */ 0x0044, 0x007A,
+        /* 445 */ 0x0064, 0x007A,
+        /* 447 */ 0x0047, 0x0301,
+        /* 449 */ 0x0067, 0x0301,
+        /* 451 */ 0x004E, 0x0300,
+        /* 453 */ 0x006E, 0x0300,
+        /* 455 */ 0x00C5, 0x0301,
+        /* 457 */ 0x00E5, 0x0301,
+        /* 459 */ 0x00C6, 0x0301,
+        /* 461 */ 0x00E6, 0x0301,
+        /* 463 */ 0x00D8, 0x0301,
+        /* 465 */ 0x00F8, 0x0301,
+        /* 467 */ 0x0041, 0x030F,
+        /* 469 */ 0x0061, 0x030F,
+        /* 471 */ 0x0041, 0x0311,
+        /* 473 */ 0x0061, 0x0311,
+        /* 475 */ 0x0045, 0x030F,
+        /* 477 */ 0x0065, 0x030F,
+        /* 479 */ 0x0045, 0x0311,
+        /* 481 */ 0x0065, 0x0311,
+        /* 483 */ 0x0049, 0x030F,
+        /* 485 */ 0x0069, 0x030F,
+        /* 487 */ 0x0049, 0x0311,
+        /* 489 */ 0x0069, 0x0311,
+        /* 491 */ 0x004F, 0x030F,
+        /* 493 */ 0x006F, 0x030F,
+        /* 495 */ 0x004F, 0x0311,
+        /* 497 */ 0x006F, 0x0311,
+        /* 499 */ 0x0052, 0x030F,
+        /* 501 */ 0x0072, 0x030F,
+        /* 503 */ 0x0052, 0x0311,
+        /* 505 */ 0x0072, 0x0311,
+        /* 507 */ 0x0055, 0x030F,
+        /* 509 */ 0x0075, 0x030F,
+        /* 511 */ 0x0055, 0x0311,
+        /* 513 */ 0x0075, 0x0311,
+        /* 515 */ 0x0053, 0x0326,
+        /* 517 */ 0x0073, 0x0326,
+        /* 519 */ 0x0054, 0x0326,
+        /* 521 */ 0x0074, 0x0326,
+        /* 523 */ 0x0048, 0x030C,
+        /* 525 */ 0x0068, 0x030C,
+        /* 527 */ 0x0041, 0x0307,
+        /* 529 */ 0x0061, 0x0307,
+        /* 531 */ 0x0045, 0x0327,
+        /* 533 */ 0x0065, 0x0327,
+        /* 535 */ 0x00D6, 0x0304,
+        /* 537 */ 0x00F6, 0x0304,
+        /* 539 */ 0x00D5, 0x0304,
+        /* 541 */ 0x00F5, 0x0304,
+        /* 543 */ 0x004F, 0x0307,
+        /* 545 */ 0x006F, 0x0307,
+        /* 547 */ 0x022E, 0x0304,
+        /* 549 */ 0x022F, 0x0304,
+        /* 551 */ 0x0059, 0x0304,
+        /* 553 */ 0x0079, 0x0304,
+        /* 555 */ 0x0020, 0x0306,
+        /* 557 */ 0x0020, 0x0307,
+        /* 559 */ 0x0020, 0x030A,
+        /* 561 */ 0x0020, 0x0328,
+        /* 563 */ 0x0020, 0x0303,
+        /* 565 */ 0x0020, 0x030B,
+        /* 567 */ 0x0308, 0x0301,
+        /* 569 */ 0x0020, 0x0345,
+        /* 571 */ 0x0020, 0x0301,
+        /* 573 */ 0x00A8, 0x0301,
+        /* 575 */ 0x0391, 0x0301,
+        /* 577 */ 0x0395, 0x0301,
+        /* 579 */ 0x0397, 0x0301,
+        /* 581 */ 0x0399, 0x0301,
+        /* 583 */ 0x039F, 0x0301,
+        /* 585 */ 0x03A5, 0x0301,
+        /* 587 */ 0x03A9, 0x0301,
+        /* 589 */ 0x03CA, 0x0301,
+        /* 591 */ 0x0399, 0x0308,
+        /* 593 */ 0x03A5, 0x0308,
+        /* 595 */ 0x03B1, 0x0301,
+        /* 597 */ 0x03B5, 0x0301,
+        /* 599 */ 0x03B7, 0x0301,
+        /* 601 */ 0x03B9, 0x0301,
+        /* 603 */ 0x03CB, 0x0301,
+        /* 605 */ 0x03B9, 0x0308,
+        /* 607 */ 0x03C5, 0x0308,
+        /* 609 */ 0x03BF, 0x0301,
+        /* 611 */ 0x03C5, 0x0301,
+        /* 613 */ 0x03C9, 0x0301,
+        /* 615 */ 0x03D2, 0x0301,
+        /* 617 */ 0x03D2, 0x0308,
+        /* 619 */ 0x0415, 0x0300,
+        /* 621 */ 0x0415, 0x0308,
+        /* 623 */ 0x0413, 0x0301,
+        /* 625 */ 0x0406, 0x0308,
+        /* 627 */ 0x041A, 0x0301,
+        /* 629 */ 0x0418, 0x0300,
+        /* 631 */ 0x0423, 0x0306,
+        /* 633 */ 0x0418, 0x0306,
+        /* 635 */ 0x0438, 0x0306,
+        /* 637 */ 0x0435, 0x0300,
+        /* 639 */ 0x0435, 0x0308,
+        /* 641 */ 0x0433, 0x0301,
+        /* 643 */ 0x0456, 0x0308,
+        /* 645 */ 0x043A, 0x0301,
+        /* 647 */ 0x0438, 0x0300,
+        /* 649 */ 0x0443, 0x0306,
+        /* 651 */ 0x0474, 0x030F,
+        /* 653 */ 0x0475, 0x030F,
+        /* 655 */ 0x0416, 0x0306,
+        /* 657 */ 0x0436, 0x0306,
+        /* 659 */ 0x0410, 0x0306,
+        /* 661 */ 0x0430, 0x0306,
+        /* 663 */ 0x0410, 0x0308,
+        /* 665 */ 0x0430, 0x0308,
+        /* 667 */ 0x0415, 0x0306,
+        /* 669 */ 0x0435, 0x0306,
+        /* 671 */ 0x04D8, 0x0308,
+        /* 673 */ 0x04D9, 0x0308,
+        /* 675 */ 0x0416, 0x0308,
+        /* 677 */ 0x0436, 0x0308,
+        /* 679 */ 0x0417, 0x0308,
+        /* 681 */ 0x0437, 0x0308,
+        /* 683 */ 0x0418, 0x0304,
+        /* 685 */ 0x0438, 0x0304,
+        /* 687 */ 0x0418, 0x0308,
+        /* 689 */ 0x0438, 0x0308,
+        /* 691 */ 0x041E, 0x0308,
+        /* 693 */ 0x043E, 0x0308,
+        /* 695 */ 0x04E8, 0x0308,
+        /* 697 */ 0x04E9, 0x0308,
+        /* 699 */ 0x042D, 0x0308,
+        /* 701 */ 0x044D, 0x0308,
+        /* 703 */ 0x0423, 0x0304,
+        /* 705 */ 0x0443, 0x0304,
+        /* 707 */ 0x0423, 0x0308,
+        /* 709 */ 0x0443, 0x0308,
+        /* 711 */ 0x0423, 0x030B,
+        /* 713 */ 0x0443, 0x030B,
+        /* 715 */ 0x0427, 0x0308,
+        /* 717 */ 0x0447, 0x0308,
+        /* 719 */ 0x042B, 0x0308,
+        /* 721 */ 0x044B, 0x0308,
+        /* 723 */ 0x0565, 0x0582,
+        /* 725 */ 0x0627, 0x0653,
+        /* 727 */ 0x0627, 0x0654,
+        /* 729 */ 0x0648, 0x0654,
+        /* 731 */ 0x0627, 0x0655,
+        /* 733 */ 0x064A, 0x0654,
+        /* 735 */ 0x0627, 0x0674,
+        /* 737 */ 0x0648, 0x0674,
+        /* 739 */ 0x06C7, 0x0674,
+        /* 741 */ 0x064A, 0x0674,
+        /* 743 */ 0x06D5, 0x0654,
+        /* 745 */ 0x06C1, 0x0654,
+        /* 747 */ 0x06D2, 0x0654,
+        /* 749 */ 0x0928, 0x093C,
+        /* 751 */ 0x0930, 0x093C,
+        /* 753 */ 0x0933, 0x093C,
+        /* 755 */ 0x0915, 0x093C,
+        /* 757 */ 0x0916, 0x093C,
+        /* 759 */ 0x0917, 0x093C,
+        /* 761 */ 0x091C, 0x093C,
+        /* 763 */ 0x0921, 0x093C,
+        /* 765 */ 0x0922, 0x093C,
+        /* 767 */ 0x092B, 0x093C,
+        /* 769 */ 0x092F, 0x093C,
+        /* 771 */ 0x09C7, 0x09BE,
+        /* 773 */ 0x09C7, 0x09D7,
+        /* 775 */ 0x09A1, 0x09BC,
+        /* 777 */ 0x09A2, 0x09BC,
+        /* 779 */ 0x09AF, 0x09BC,
+        /* 781 */ 0x0A32, 0x0A3C,
+        /* 783 */ 0x0A38, 0x0A3C,
+        /* 785 */ 0x0A16, 0x0A3C,
+        /* 787 */ 0x0A17, 0x0A3C,
+        /* 789 */ 0x0A1C, 0x0A3C,
+        /* 791 */ 0x0A2B, 0x0A3C,
+        /* 793 */ 0x0B47, 0x0B56,
+        /* 795 */ 0x0B47, 0x0B3E,
+        /* 797 */ 0x0B47, 0x0B57,
+        /* 799 */ 0x0B21, 0x0B3C,
+        /* 801 */ 0x0B22, 0x0B3C,
+        /* 803 */ 0x0B92, 0x0BD7,
+        /* 805 */ 0x0BC6, 0x0BBE,
+        /* 807 */ 0x0BC7, 0x0BBE,
+        /* 809 */ 0x0BC6, 0x0BD7,
+        /* 811 */ 0x0C46, 0x0C56,
+        /* 813 */ 0x0CBF, 0x0CD5,
+        /* 815 */ 0x0CC6, 0x0CD5,
+        /* 817 */ 0x0CC6, 0x0CD6,
+        /* 819 */ 0x0CC6, 0x0CC2,
+        /* 821 */ 0x0CCA, 0x0CD5,
+        /* 823 */ 0x0D46, 0x0D3E,
+        /* 825 */ 0x0D47, 0x0D3E,
+        /* 827 */ 0x0D46, 0x0D57,
+        /* 829 */ 0x0DD9, 0x0DCA,
+        /* 831 */ 0x0DD9, 0x0DCF,
+        /* 833 */ 0x0DDC, 0x0DCA,
+        /* 835 */ 0x0DD9, 0x0DDF,
+        /* 837 */ 0x0E4D, 0x0E32,
+        /* 839 */ 0x0ECD, 0x0EB2,
+        /* 841 */ 0x0EAB, 0x0E99,
+        /* 843 */ 0x0EAB, 0x0EA1,
+        /* 845 */ 0x0F42, 0x0FB7,
+        /* 847 */ 0x0F4C, 0x0FB7,
+        /* 849 */ 0x0F51, 0x0FB7,
+        /* 851 */ 0x0F56, 0x0FB7,
+        /* 853 */ 0x0F5B, 0x0FB7,
+        /* 855 */ 0x0F40, 0x0FB5,
+        /* 857 */ 0x0F71, 0x0F72,
+        /* 859 */ 0x0F71, 0x0F74,
+        /* 861 */ 0x0FB2, 0x0F80,
+        /* 863 */ 0x0FB2, 0x0F81,
+        /* 865 */ 0x0FB3, 0x0F80,
+        /* 867 */ 0x0FB3, 0x0F81,
+        /* 869 */ 0x0F71, 0x0F80,
+        /* 871 */ 0x0F92, 0x0FB7,
+        /* 873 */ 0x0F9C, 0x0FB7,
+        /* 875 */ 0x0FA1, 0x0FB7,
+        /* 877 */ 0x0FA6, 0x0FB7,
+        /* 879 */ 0x0FAB, 0x0FB7,
+        /* 881 */ 0x0F90, 0x0FB5,
+        /* 883 */ 0x1025, 0x102E,
+        /* 885 */ 0x1B05, 0x1B35,
+        /* 887 */ 0x1B07, 0x1B35,
+        /* 889 */ 0x1B09, 0x1B35,
+        /* 891 */ 0x1B0B, 0x1B35,
+        /* 893 */ 0x1B0D, 0x1B35,
+        /* 895 */ 0x1B11, 0x1B35,
+        /* 897 */ 0x1B3A, 0x1B35,
+        /* 899 */ 0x1B3C, 0x1B35,
+        /* 901 */ 0x1B3E, 0x1B35,
+        /* 903 */ 0x1B3F, 0x1B35,
+        /* 905 */ 0x1B42, 0x1B35,
+        /* 907 */ 0x0041, 0x0325,
+        /* 909 */ 0x0061, 0x0325,
+        /* 911 */ 0x0042, 0x0307,
+        /* 913 */ 0x0062, 0x0307,
+        /* 915 */ 0x0042, 0x0323,
+        /* 917 */ 0x0062, 0x0323,
+        /* 919 */ 0x0042, 0x0331,
+        /* 921 */ 0x0062, 0x0331,
+        /* 923 */ 0x00C7, 0x0301,
+        /* 925 */ 0x00E7, 0x0301,
+        /* 927 */ 0x0044, 0x0307,
+        /* 929 */ 0x0064, 0x0307,
+        /* 931 */ 0x0044, 0x0323,
+        /* 933 */ 0x0064, 0x0323,
+        /* 935 */ 0x0044, 0x0331,
+        /* 937 */ 0x0064, 0x0331,
+        /* 939 */ 0x0044, 0x0327,
+        /* 941 */ 0x0064, 0x0327,
+        /* 943 */ 0x0044, 0x032D,
+        /* 945 */ 0x0064, 0x032D,
+        /* 947 */ 0x0112, 0x0300,
+        /* 949 */ 0x0113, 0x0300,
+        /* 951 */ 0x0112, 0x0301,
+        /* 953 */ 0x0113, 0x0301,
+        /* 955 */ 0x0045, 0x032D,
+        /* 957 */ 0x0065, 0x032D,
+        /* 959 */ 0x0045, 0x0330,
+        /* 961 */ 0x0065, 0x0330,
+        /* 963 */ 0x0228, 0x0306,
+        /* 965 */ 0x0229, 0x0306,
+        /* 967 */ 0x0046, 0x0307,
+        /* 969 */ 0x0066, 0x0307,
+        /* 971 */ 0x0047, 0x0304,
+        /* 973 */ 0x0067, 0x0304,
+        /* 975 */ 0x0048, 0x0307,
+        /* 977 */ 0x0068, 0x0307,
+        /* 979 */ 0x0048, 0x0323,
+        /* 981 */ 0x0068, 0x0323,
+        /* 983 */ 0x0048, 0x0308,
+        /* 985 */ 0x0068, 0x0308,
+        /* 987 */ 0x0048, 0x0327,
+        /* 989 */ 0x0068, 0x0327,
+        /* 991 */ 0x0048, 0x032E,
+        /* 993 */ 0x0068, 0x032E,
+        /* 995 */ 0x0049, 0x0330,
+        /* 997 */ 0x0069, 0x0330,
+        /* 999 */ 0x00CF, 0x0301,
+        /* 1001 */ 0x00EF, 0x0301,
+        /* 1003 */ 0x004B, 0x0301,
+        /* 1005 */ 0x006B, 0x0301,
+        /* 1007 */ 0x004B, 0x0323,
+        /* 1009 */ 0x006B, 0x0323,
+        /* 1011 */ 0x004B, 0x0331,
+        /* 1013 */ 0x006B, 0x0331,
+        /* 1015 */ 0x004C, 0x0323,
+        /* 1017 */ 0x006C, 0x0323,
+        /* 1019 */ 0x1E36, 0x0304,
+        /* 1021 */ 0x1E37, 0x0304,
+        /* 1023 */ 0x004C, 0x0331,
+        /* 1025 */ 0x006C, 0x0331,
+        /* 1027 */ 0x004C, 0x032D,
+        /* 1029 */ 0x006C, 0x032D,
+        /* 1031 */ 0x004D, 0x0301,
+        /* 1033 */ 0x006D, 0x0301,
+        /* 1035 */ 0x004D, 0x0307,
+        /* 1037 */ 0x006D, 0x0307,
+        /* 1039 */ 0x004D, 0x0323,
+        /* 1041 */ 0x006D, 0x0323,
+        /* 1043 */ 0x004E, 0x0307,
+        /* 1045 */ 0x006E, 0x0307,
+        /* 1047 */ 0x004E, 0x0323,
+        /* 1049 */ 0x006E, 0x0323,
+        /* 1051 */ 0x004E, 0x0331,
+        /* 1053 */ 0x006E, 0x0331,
+        /* 1055 */ 0x004E, 0x032D,
+        /* 1057 */ 0x006E, 0x032D,
+        /* 1059 */ 0x00D5, 0x0301,
+        /* 1061 */ 0x00F5, 0x0301,
+        /* 1063 */ 0x00D5, 0x0308,
+        /* 1065 */ 0x00F5, 0x0308,
+        /* 1067 */ 0x014C, 0x0300,
+        /* 1069 */ 0x014D, 0x0300,
+        /* 1071 */ 0x014C, 0x0301,
+        /* 1073 */ 0x014D, 0x0301,
+        /* 1075 */ 0x0050, 0x0301,
+        /* 1077 */ 0x0070, 0x0301,
+        /* 1079 */ 0x0050, 0x0307,
+        /* 1081 */ 0x0070, 0x0307,
+        /* 1083 */ 0x0052, 0x0307,
+        /* 1085 */ 0x0072, 0x0307,
+        /* 1087 */ 0x0052, 0x0323,
+        /* 1089 */ 0x0072, 0x0323,
+        /* 1091 */ 0x1E5A, 0x0304,
+        /* 1093 */ 0x1E5B, 0x0304,
+        /* 1095 */ 0x0052, 0x0331,
+        /* 1097 */ 0x0072, 0x0331,
+        /* 1099 */ 0x0053, 0x0307,
+        /* 1101 */ 0x0073, 0x0307,
+        /* 1103 */ 0x0053, 0x0323,
+        /* 1105 */ 0x0073, 0x0323,
+        /* 1107 */ 0x015A, 0x0307,
+        /* 1109 */ 0x015B, 0x0307,
+        /* 1111 */ 0x0160, 0x0307,
+        /* 1113 */ 0x0161, 0x0307,
+        /* 1115 */ 0x1E62, 0x0307,
+        /* 1117 */ 0x1E63, 0x0307,
+        /* 1119 */ 0x0054, 0x0307,
+        /* 1121 */ 0x0074, 0x0307,
+        /* 1123 */ 0x0054, 0x0323,
+        /* 1125 */ 0x0074, 0x0323,
+        /* 1127 */ 0x0054, 0x0331,
+        /* 1129 */ 0x0074, 0x0331,
+        /* 1131 */ 0x0054, 0x032D,
+        /* 1133 */ 0x0074, 0x032D,
+        /* 1135 */ 0x0055, 0x0324,
+        /* 1137 */ 0x0075, 0x0324,
+        /* 1139 */ 0x0055, 0x0330,
+        /* 1141 */ 0x0075, 0x0330,
+        /* 1143 */ 0x0055, 0x032D,
+        /* 1145 */ 0x0075, 0x032D,
+        /* 1147 */ 0x0168, 0x0301,
+        /* 1149 */ 0x0169, 0x0301,
+        /* 1151 */ 0x016A, 0x0308,
+        /* 1153 */ 0x016B, 0x0308,
+        /* 1155 */ 0x0056, 0x0303,
+        /* 1157 */ 0x0076, 0x0303,
+        /* 1159 */ 0x0056, 0x0323,
+        /* 1161 */ 0x0076, 0x0323,
+        /* 1163 */ 0x0057, 0x0300,
+        /* 1165 */ 0x0077, 0x0300,
+        /* 1167 */ 0x0057, 0x0301,
+        /* 1169 */ 0x0077, 0x0301,
+        /* 1171 */ 0x0057, 0x0308,
+        /* 1173 */ 0x0077, 0x0308,
+        /* 1175 */ 0x0057, 0x0307,
+        /* 1177 */ 0x0077, 0x0307,
+        /* 1179 */ 0x0057, 0x0323,
+        /* 1181 */ 0x0077, 0x0323,
+        /* 1183 */ 0x0058, 0x0307,
+        /* 1185 */ 0x0078, 0x0307,
+        /* 1187 */ 0x0058, 0x0308,
+        /* 1189 */ 0x0078, 0x0308,
+        /* 1191 */ 0x0059, 0x0307,
+        /* 1193 */ 0x0079, 0x0307,
+        /* 1195 */ 0x005A, 0x0302,
+        /* 1197 */ 0x007A, 0x0302,
+        /* 1199 */ 0x005A, 0x0323,
+        /* 1201 */ 0x007A, 0x0323,
+        /* 1203 */ 0x005A, 0x0331,
+        /* 1205 */ 0x007A, 0x0331,
+        /* 1207 */ 0x0068, 0x0331,
+        /* 1209 */ 0x0074, 0x0308,
+        /* 1211 */ 0x0077, 0x030A,
+        /* 1213 */ 0x0079, 0x030A,
+        /* 1215 */ 0x0061, 0x02BE,
+        /* 1217 */ 0x017F, 0x0307,
+        /* 1219 */ 0x0041, 0x0323,
+        /* 1221 */ 0x0061, 0x0323,
+        /* 1223 */ 0x0041, 0x0309,
+        /* 1225 */ 0x0061, 0x0309,
+        /* 1227 */ 0x00C2, 0x0301,
+        /* 1229 */ 0x00E2, 0x0301,
+        /* 1231 */ 0x00C2, 0x0300,
+        /* 1233 */ 0x00E2, 0x0300,
+        /* 1235 */ 0x00C2, 0x0309,
+        /* 1237 */ 0x00E2, 0x0309,
+        /* 1239 */ 0x00C2, 0x0303,
+        /* 1241 */ 0x00E2, 0x0303,
+        /* 1243 */ 0x1EA0, 0x0302,
+        /* 1245 */ 0x1EA1, 0x0302,
+        /* 1247 */ 0x0102, 0x0301,
+        /* 1249 */ 0x0103, 0x0301,
+        /* 1251 */ 0x0102, 0x0300,
+        /* 1253 */ 0x0103, 0x0300,
+        /* 1255 */ 0x0102, 0x0309,
+        /* 1257 */ 0x0103, 0x0309,
+        /* 1259 */ 0x0102, 0x0303,
+        /* 1261 */ 0x0103, 0x0303,
+        /* 1263 */ 0x1EA0, 0x0306,
+        /* 1265 */ 0x1EA1, 0x0306,
+        /* 1267 */ 0x0045, 0x0323,
+        /* 1269 */ 0x0065, 0x0323,
+        /* 1271 */ 0x0045, 0x0309,
+        /* 1273 */ 0x0065, 0x0309,
+        /* 1275 */ 0x0045, 0x0303,
+        /* 1277 */ 0x0065, 0x0303,
+        /* 1279 */ 0x00CA, 0x0301,
+        /* 1281 */ 0x00EA, 0x0301,
+        /* 1283 */ 0x00CA, 0x0300,
+        /* 1285 */ 0x00EA, 0x0300,
+        /* 1287 */ 0x00CA, 0x0309,
+        /* 1289 */ 0x00EA, 0x0309,
+        /* 1291 */ 0x00CA, 0x0303,
+        /* 1293 */ 0x00EA, 0x0303,
+        /* 1295 */ 0x1EB8, 0x0302,
+        /* 1297 */ 0x1EB9, 0x0302,
+        /* 1299 */ 0x0049, 0x0309,
+        /* 1301 */ 0x0069, 0x0309,
+        /* 1303 */ 0x0049, 0x0323,
+        /* 1305 */ 0x0069, 0x0323,
+        /* 1307 */ 0x004F, 0x0323,
+        /* 1309 */ 0x006F, 0x0323,
+        /* 1311 */ 0x004F, 0x0309,
+        /* 1313 */ 0x006F, 0x0309,
+        /* 1315 */ 0x00D4, 0x0301,
+        /* 1317 */ 0x00F4, 0x0301,
+        /* 1319 */ 0x00D4, 0x0300,
+        /* 1321 */ 0x00F4, 0x0300,
+        /* 1323 */ 0x00D4, 0x0309,
+        /* 1325 */ 0x00F4, 0x0309,
+        /* 1327 */ 0x00D4, 0x0303,
+        /* 1329 */ 0x00F4, 0x0303,
+        /* 1331 */ 0x1ECC, 0x0302,
+        /* 1333 */ 0x1ECD, 0x0302,
+        /* 1335 */ 0x01A0, 0x0301,
+        /* 1337 */ 0x01A1, 0x0301,
+        /* 1339 */ 0x01A0, 0x0300,
+        /* 1341 */ 0x01A1, 0x0300,
+        /* 1343 */ 0x01A0, 0x0309,
+        /* 1345 */ 0x01A1, 0x0309,
+        /* 1347 */ 0x01A0, 0x0303,
+        /* 1349 */ 0x01A1, 0x0303,
+        /* 1351 */ 0x01A0, 0x0323,
+        /* 1353 */ 0x01A1, 0x0323,
+        /* 1355 */ 0x0055, 0x0323,
+        /* 1357 */ 0x0075, 0x0323,
+        /* 1359 */ 0x0055, 0x0309,
+        /* 1361 */ 0x0075, 0x0309,
+        /* 1363 */ 0x01AF, 0x0301,
+        /* 1365 */ 0x01B0, 0x0301,
+        /* 1367 */ 0x01AF, 0x0300,
+        /* 1369 */ 0x01B0, 0x0300,
+        /* 1371 */ 0x01AF, 0x0309,
+        /* 1373 */ 0x01B0, 0x0309,
+        /* 1375 */ 0x01AF, 0x0303,
+        /* 1377 */ 0x01B0, 0x0303,
+        /* 1379 */ 0x01AF, 0x0323,
+        /* 1381 */ 0x01B0, 0x0323,
+        /* 1383 */ 0x0059, 0x0300,
+        /* 1385 */ 0x0079, 0x0300,
+        /* 1387 */ 0x0059, 0x0323,
+        /* 1389 */ 0x0079, 0x0323,
+        /* 1391 */ 0x0059, 0x0309,
+        /* 1393 */ 0x0079, 0x0309,
+        /* 1395 */ 0x0059, 0x0303,
+        /* 1397 */ 0x0079, 0x0303,
+        /* 1399 */ 0x03B1, 0x0313,
+        /* 1401 */ 0x03B1, 0x0314,
+        /* 1403 */ 0x1F00, 0x0300,
+        /* 1405 */ 0x1F01, 0x0300,
+        /* 1407 */ 0x1F00, 0x0301,
+        /* 1409 */ 0x1F01, 0x0301,
+        /* 1411 */ 0x1F00, 0x0342,
+        /* 1413 */ 0x1F01, 0x0342,
+        /* 1415 */ 0x0391, 0x0313,
+        /* 1417 */ 0x0391, 0x0314,
+        /* 1419 */ 0x1F08, 0x0300,
+        /* 1421 */ 0x1F09, 0x0300,
+        /* 1423 */ 0x1F08, 0x0301,
+        /* 1425 */ 0x1F09, 0x0301,
+        /* 1427 */ 0x1F08, 0x0342,
+        /* 1429 */ 0x1F09, 0x0342,
+        /* 1431 */ 0x03B5, 0x0313,
+        /* 1433 */ 0x03B5, 0x0314,
+        /* 1435 */ 0x1F10, 0x0300,
+        /* 1437 */ 0x1F11, 0x0300,
+        /* 1439 */ 0x1F10, 0x0301,
+        /* 1441 */ 0x1F11, 0x0301,
+        /* 1443 */ 0x0395, 0x0313,
+        /* 1445 */ 0x0395, 0x0314,
+        /* 1447 */ 0x1F18, 0x0300,
+        /* 1449 */ 0x1F19, 0x0300,
+        /* 1451 */ 0x1F18, 0x0301,
+        /* 1453 */ 0x1F19, 0x0301,
+        /* 1455 */ 0x03B7, 0x0313,
+        /* 1457 */ 0x03B7, 0x0314,
+        /* 1459 */ 0x1F20, 0x0300,
+        /* 1461 */ 0x1F21, 0x0300,
+        /* 1463 */ 0x1F20, 0x0301,
+        /* 1465 */ 0x1F21, 0x0301,
+        /* 1467 */ 0x1F20, 0x0342,
+        /* 1469 */ 0x1F21, 0x0342,
+        /* 1471 */ 0x0397, 0x0313,
+        /* 1473 */ 0x0397, 0x0314,
+        /* 1475 */ 0x1F28, 0x0300,
+        /* 1477 */ 0x1F29, 0x0300,
+        /* 1479 */ 0x1F28, 0x0301,
+        /* 1481 */ 0x1F29, 0x0301,
+        /* 1483 */ 0x1F28, 0x0342,
+        /* 1485 */ 0x1F29, 0x0342,
+        /* 1487 */ 0x03B9, 0x0313,
+        /* 1489 */ 0x03B9, 0x0314,
+        /* 1491 */ 0x1F30, 0x0300,
+        /* 1493 */ 0x1F31, 0x0300,
+        /* 1495 */ 0x1F30, 0x0301,
+        /* 1497 */ 0x1F31, 0x0301,
+        /* 1499 */ 0x1F30, 0x0342,
+        /* 1501 */ 0x1F31, 0x0342,
+        /* 1503 */ 0x0399, 0x0313,
+        /* 1505 */ 0x0399, 0x0314,
+        /* 1507 */ 0x1F38, 0x0300,
+        /* 1509 */ 0x1F39, 0x0300,
+        /* 1511 */ 0x1F38, 0x0301,
+        /* 1513 */ 0x1F39, 0x0301,
+        /* 1515 */ 0x1F38, 0x0342,
+        /* 1517 */ 0x1F39, 0x0342,
+        /* 1519 */ 0x03BF, 0x0313,
+        /* 1521 */ 0x03BF, 0x0314,
+        /* 1523 */ 0x1F40, 0x0300,
+        /* 1525 */ 0x1F41, 0x0300,
+        /* 1527 */ 0x1F40, 0x0301,
+        /* 1529 */ 0x1F41, 0x0301,
+        /* 1531 */ 0x039F, 0x0313,
+        /* 1533 */ 0x039F, 0x0314,
+        /* 1535 */ 0x1F48, 0x0300,
+        /* 1537 */ 0x1F49, 0x0300,
+        /* 1539 */ 0x1F48, 0x0301,
+        /* 1541 */ 0x1F49, 0x0301,
+        /* 1543 */ 0x03C5, 0x0313,
+        /* 1545 */ 0x03C5, 0x0314,
+        /* 1547 */ 0x1F50, 0x0300,
+        /* 1549 */ 0x1F51, 0x0300,
+        /* 1551 */ 0x1F50, 0x0301,
+        /* 1553 */ 0x1F51, 0x0301,
+        /* 1555 */ 0x1F50, 0x0342,
+        /* 1557 */ 0x1F51, 0x0342,
+        /* 1559 */ 0x03A5, 0x0314,
+        /* 1561 */ 0x1F59, 0x0300,
+        /* 1563 */ 0x1F59, 0x0301,
+        /* 1565 */ 0x1F59, 0x0342,
+        /* 1567 */ 0x03C9, 0x0313,
+        /* 1569 */ 0x03C9, 0x0314,
+        /* 1571 */ 0x1F60, 0x0300,
+        /* 1573 */ 0x1F61, 0x0300,
+        /* 1575 */ 0x1F60, 0x0301,
+        /* 1577 */ 0x1F61, 0x0301,
+        /* 1579 */ 0x1F60, 0x0342,
+        /* 1581 */ 0x1F61, 0x0342,
+        /* 1583 */ 0x03A9, 0x0313,
+        /* 1585 */ 0x03A9, 0x0314,
+        /* 1587 */ 0x1F68, 0x0300,
+        /* 1589 */ 0x1F69, 0x0300,
+        /* 1591 */ 0x1F68, 0x0301,
+        /* 1593 */ 0x1F69, 0x0301,
+        /* 1595 */ 0x1F68, 0x0342,
+        /* 1597 */ 0x1F69, 0x0342,
+        /* 1599 */ 0x03B1, 0x0300,
+        /* 1601 */ 0x03B5, 0x0300,
+        /* 1603 */ 0x03B7, 0x0300,
+        /* 1605 */ 0x03B9, 0x0300,
+        /* 1607 */ 0x03BF, 0x0300,
+        /* 1609 */ 0x03C5, 0x0300,
+        /* 1611 */ 0x03C9, 0x0300,
+        /* 1613 */ 0x1F00, 0x0345,
+        /* 1615 */ 0x1F01, 0x0345,
+        /* 1617 */ 0x1F02, 0x0345,
+        /* 1619 */ 0x1F03, 0x0345,
+        /* 1621 */ 0x1F04, 0x0345,
+        /* 1623 */ 0x1F05, 0x0345,
+        /* 1625 */ 0x1F06, 0x0345,
+        /* 1627 */ 0x1F07, 0x0345,
+        /* 1629 */ 0x1F08, 0x0345,
+        /* 1631 */ 0x1F09, 0x0345,
+        /* 1633 */ 0x1F0A, 0x0345,
+        /* 1635 */ 0x1F0B, 0x0345,
+        /* 1637 */ 0x1F0C, 0x0345,
+        /* 1639 */ 0x1F0D, 0x0345,
+        /* 1641 */ 0x1F0E, 0x0345,
+        /* 1643 */ 0x1F0F, 0x0345,
+        /* 1645 */ 0x1F20, 0x0345,
+        /* 1647 */ 0x1F21, 0x0345,
+        /* 1649 */ 0x1F22, 0x0345,
+        /* 1651 */ 0x1F23, 0x0345,
+        /* 1653 */ 0x1F24, 0x0345,
+        /* 1655 */ 0x1F25, 0x0345,
+        /* 1657 */ 0x1F26, 0x0345,
+        /* 1659 */ 0x1F27, 0x0345,
+        /* 1661 */ 0x1F28, 0x0345,
+        /* 1663 */ 0x1F29, 0x0345,
+        /* 1665 */ 0x1F2A, 0x0345,
+        /* 1667 */ 0x1F2B, 0x0345,
+        /* 1669 */ 0x1F2C, 0x0345,
+        /* 1671 */ 0x1F2D, 0x0345,
+        /* 1673 */ 0x1F2E, 0x0345,
+        /* 1675 */ 0x1F2F, 0x0345,
+        /* 1677 */ 0x1F60, 0x0345,
+        /* 1679 */ 0x1F61, 0x0345,
+        /* 1681 */ 0x1F62, 0x0345,
+        /* 1683 */ 0x1F63, 0x0345,
+        /* 1685 */ 0x1F64, 0x0345,
+        /* 1687 */ 0x1F65, 0x0345,
+        /* 1689 */ 0x1F66, 0x0345,
+        /* 1691 */ 0x1F67, 0x0345,
+        /* 1693 */ 0x1F68, 0x0345,
+        /* 1695 */ 0x1F69, 0x0345,
+        /* 1697 */ 0x1F6A, 0x0345,
+        /* 1699 */ 0x1F6B, 0x0345,
+        /* 1701 */ 0x1F6C, 0x0345,
+        /* 1703 */ 0x1F6D, 0x0345,
+        /* 1705 */ 0x1F6E, 0x0345,
+        /* 1707 */ 0x1F6F, 0x0345,
+        /* 1709 */ 0x03B1, 0x0306,
+        /* 1711 */ 0x03B1, 0x0304,
+        /* 1713 */ 0x1F70, 0x0345,
+        /* 1715 */ 0x03B1, 0x0345,
+        /* 1717 */ 0x03AC, 0x0345,
+        /* 1719 */ 0x03B1, 0x0342,
+        /* 1721 */ 0x1FB6, 0x0345,
+        /* 1723 */ 0x0391, 0x0306,
+        /* 1725 */ 0x0391, 0x0304,
+        /* 1727 */ 0x0391, 0x0300,
+        /* 1729 */ 0x0391, 0x0345,
+        /* 1731 */ 0x0020, 0x0313,
+        /* 1733 */ 0x0020, 0x0313,
+        /* 1735 */ 0x0020, 0x0342,
+        /* 1737 */ 0x00A8, 0x0342,
+        /* 1739 */ 0x1F74, 0x0345,
+        /* 1741 */ 0x03B7, 0x0345,
+        /* 1743 */ 0x03AE, 0x0345,
+        /* 1745 */ 0x03B7, 0x0342,
+        /* 1747 */ 0x1FC6, 0x0345,
+        /* 1749 */ 0x0395, 0x0300,
+        /* 1751 */ 0x0397, 0x0300,
+        /* 1753 */ 0x0397, 0x0345,
+        /* 1755 */ 0x1FBF, 0x0300,
+        /* 1757 */ 0x1FBF, 0x0301,
+        /* 1759 */ 0x1FBF, 0x0342,
+        /* 1761 */ 0x03B9, 0x0306,
+        /* 1763 */ 0x03B9, 0x0304,
+        /* 1765 */ 0x03CA, 0x0300,
+        /* 1767 */ 0x03B9, 0x0342,
+        /* 1769 */ 0x03CA, 0x0342,
+        /* 1771 */ 0x0399, 0x0306,
+        /* 1773 */ 0x0399, 0x0304,
+        /* 1775 */ 0x0399, 0x0300,
+        /* 1777 */ 0x1FFE, 0x0300,
+        /* 1779 */ 0x1FFE, 0x0301,
+        /* 1781 */ 0x1FFE, 0x0342,
+        /* 1783 */ 0x03C5, 0x0306,
+        /* 1785 */ 0x03C5, 0x0304,
+        /* 1787 */ 0x03CB, 0x0300,
+        /* 1789 */ 0x03C1, 0x0313,
+        /* 1791 */ 0x03C1, 0x0314,
+        /* 1793 */ 0x03C5, 0x0342,
+        /* 1795 */ 0x03CB, 0x0342,
+        /* 1797 */ 0x03A5, 0x0306,
+        /* 1799 */ 0x03A5, 0x0304,
+        /* 1801 */ 0x03A5, 0x0300,
+        /* 1803 */ 0x03A1, 0x0314,
+        /* 1805 */ 0x00A8, 0x0300,
+        /* 1807 */ 0x1F7C, 0x0345,
+        /* 1809 */ 0x03C9, 0x0345,
+        /* 1811 */ 0x03CE, 0x0345,
+        /* 1813 */ 0x03C9, 0x0342,
+        /* 1815 */ 0x1FF6, 0x0345,
+        /* 1817 */ 0x039F, 0x0300,
+        /* 1819 */ 0x03A9, 0x0300,
+        /* 1821 */ 0x03A9, 0x0345,
+        /* 1823 */ 0x0020, 0x0314,
+        /* 1825 */ 0x0020, 0x0333,
+        /* 1827 */ 0x002E, 0x002E,
+        /* 1829 */ 0x002E, 0x002E, 0x002E,
+        /* 1832 */ 0x2032, 0x2032,
+        /* 1834 */ 0x2032, 0x2032, 0x2032,
+        /* 1837 */ 0x2035, 0x2035,
+        /* 1839 */ 0x2035, 0x2035, 0x2035,
+        /* 1842 */ 0x0021, 0x0021,
+        /* 1844 */ 0x0020, 0x0305,
+        /* 1846 */ 0x003F, 0x003F,
+        /* 1848 */ 0x003F, 0x0021,
+        /* 1850 */ 0x0021, 0x003F,
+        /* 1852 */ 0x2032, 0x2032, 0x2032, 0x2032,
+        /* 1856 */ 0x0052, 0x0073,
+        /* 1858 */ 0x0061, 0x002F, 0x0063,
+        /* 1861 */ 0x0061, 0x002F, 0x0073,
+        /* 1864 */ 0x00B0, 0x0043,
+        /* 1866 */ 0x0063, 0x002F, 0x006F,
+        /* 1869 */ 0x0063, 0x002F, 0x0075,
+        /* 1872 */ 0x00B0, 0x0046,
+        /* 1874 */ 0x004E, 0x006F,
+        /* 1876 */ 0x0053, 0x004D,
+        /* 1878 */ 0x0054, 0x0045, 0x004C,
+        /* 1881 */ 0x0054, 0x004D,
+        /* 1883 */ 0x0046, 0x0041, 0x0058,
+        /* 1886 */ 0x0031, 0x2044, 0x0037,
+        /* 1889 */ 0x0031, 0x2044, 0x0039,
+        /* 1892 */ 0x0031, 0x2044, 0x0031, 0x0030,
+        /* 1896 */ 0x0031, 0x2044, 0x0033,
+        /* 1899 */ 0x0032, 0x2044, 0x0033,
+        /* 1902 */ 0x0031, 0x2044, 0x0035,
+        /* 1905 */ 0x0032, 0x2044, 0x0035,
+        /* 1908 */ 0x0033, 0x2044, 0x0035,
+        /* 1911 */ 0x0034, 0x2044, 0x0035,
+        /* 1914 */ 0x0031, 0x2044, 0x0036,
+        /* 1917 */ 0x0035, 0x2044, 0x0036,
+        /* 1920 */ 0x0031, 0x2044, 0x0038,
+        /* 1923 */ 0x0033, 0x2044, 0x0038,
+        /* 1926 */ 0x0035, 0x2044, 0x0038,
+        /* 1929 */ 0x0037, 0x2044, 0x0038,
+        /* 1932 */ 0x0031, 0x2044,
+        /* 1934 */ 0x0049, 0x0049,
+        /* 1936 */ 0x0049, 0x0049, 0x0049,
+        /* 1939 */ 0x0049, 0x0056,
+        /* 1941 */ 0x0056, 0x0049,
+        /* 1943 */ 0x0056, 0x0049, 0x0049,
+        /* 1946 */ 0x0056, 0x0049, 0x0049, 0x0049,
+        /* 1950 */ 0x0049, 0x0058,
+        /* 1952 */ 0x0058, 0x0049,
+        /* 1954 */ 0x0058, 0x0049, 0x0049,
+        /* 1957 */ 0x0069, 0x0069,
+        /* 1959 */ 0x0069, 0x0069, 0x0069,
+        /* 1962 */ 0x0069, 0x0076,
+        /* 1964 */ 0x0076, 0x0069,
+        /* 1966 */ 0x0076, 0x0069, 0x0069,
+        /* 1969 */ 0x0076, 0x0069, 0x0069, 0x0069,
+        /* 1973 */ 0x0069, 0x0078,
+        /* 1975 */ 0x0078, 0x0069,
+        /* 1977 */ 0x0078, 0x0069, 0x0069,
+        /* 1980 */ 0x0030, 0x2044, 0x0033,
+        /* 1983 */ 0x2190, 0x0338,
+        /* 1985 */ 0x2192, 0x0338,
+        /* 1987 */ 0x2194, 0x0338,
+        /* 1989 */ 0x21D0, 0x0338,
+        /* 1991 */ 0x21D4, 0x0338,
+        /* 1993 */ 0x21D2, 0x0338,
+        /* 1995 */ 0x2203, 0x0338,
+        /* 1997 */ 0x2208, 0x0338,
+        /* 1999 */ 0x220B, 0x0338,
+        /* 2001 */ 0x2223, 0x0338,
+        /* 2003 */ 0x2225, 0x0338,
+        /* 2005 */ 0x222B, 0x222B,
+        /* 2007 */ 0x222B, 0x222B, 0x222B,
+        /* 2010 */ 0x222E, 0x222E,
+        /* 2012 */ 0x222E, 0x222E, 0x222E,
+        /* 2015 */ 0x223C, 0x0338,
+        /* 2017 */ 0x2243, 0x0338,
+        /* 2019 */ 0x2245, 0x0338,
+        /* 2021 */ 0x2248, 0x0338,
+        /* 2023 */ 0x003D, 0x0338,
+        /* 2025 */ 0x2261, 0x0338,
+        /* 2027 */ 0x224D, 0x0338,
+        /* 2029 */ 0x003C, 0x0338,
+        /* 2031 */ 0x003E, 0x0338,
+        /* 2033 */ 0x2264, 0x0338,
+        /* 2035 */ 0x2265, 0x0338,
+        /* 2037 */ 0x2272, 0x0338,
+        /* 2039 */ 0x2273, 0x0338,
+        /* 2041 */ 0x2276, 0x0338,
+        /* 2043 */ 0x2277, 0x0338,
+        /* 2045 */ 0x227A, 0x0338,
+        /* 2047 */ 0x227B, 0x0338,
+        /* 2049 */ 0x2282, 0x0338,
+        /* 2051 */ 0x2283, 0x0338,
+        /* 2053 */ 0x2286, 0x0338,
+        /* 2055 */ 0x2287, 0x0338,
+        /* 2057 */ 0x22A2, 0x0338,
+        /* 2059 */ 0x22A8, 0x0338,
+        /* 2061 */ 0x22A9, 0x0338,
+        /* 2063 */ 0x22AB, 0x0338,
+        /* 2065 */ 0x227C, 0x0338,
+        /* 2067 */ 0x227D, 0x0338,
+        /* 2069 */ 0x2291, 0x0338,
+        /* 2071 */ 0x2292, 0x0338,
+        /* 2073 */ 0x22B2, 0x0338,
+        /* 2075 */ 0x22B3, 0x0338,
+        /* 2077 */ 0x22B4, 0x0338,
+        /* 2079 */ 0x22B5, 0x0338,
+        /* 2081 */ 0x0031, 0x0030,
+        /* 2083 */ 0x0031, 0x0031,
+        /* 2085 */ 0x0031, 0x0032,
+        /* 2087 */ 0x0031, 0x0033,
+        /* 2089 */ 0x0031, 0x0034,
+        /* 2091 */ 0x0031, 0x0035,
+        /* 2093 */ 0x0031, 0x0036,
+        /* 2095 */ 0x0031, 0x0037,
+        /* 2097 */ 0x0031, 0x0038,
+        /* 2099 */ 0x0031, 0x0039,
+        /* 2101 */ 0x0032, 0x0030,
+        /* 2103 */ 0x0028, 0x0031, 0x0029,
+        /* 2106 */ 0x0028, 0x0032, 0x0029,
+        /* 2109 */ 0x0028, 0x0033, 0x0029,
+        /* 2112 */ 0x0028, 0x0034, 0x0029,
+        /* 2115 */ 0x0028, 0x0035, 0x0029,
+        /* 2118 */ 0x0028, 0x0036, 0x0029,
+        /* 2121 */ 0x0028, 0x0037, 0x0029,
+        /* 2124 */ 0x0028, 0x0038, 0x0029,
+        /* 2127 */ 0x0028, 0x0039, 0x0029,
+        /* 2130 */ 0x0028, 0x0031, 0x0030, 0x0029,
+        /* 2134 */ 0x0028, 0x0031, 0x0031, 0x0029,
+        /* 2138 */ 0x0028, 0x0031, 0x0032, 0x0029,
+        /* 2142 */ 0x0028, 0x0031, 0x0033, 0x0029,
+        /* 2146 */ 0x0028, 0x0031, 0x0034, 0x0029,
+        /* 2150 */ 0x0028, 0x0031, 0x0035, 0x0029,
+        /* 2154 */ 0x0028, 0x0031, 0x0036, 0x0029,
+        /* 2158 */ 0x0028, 0x0031, 0x0037, 0x0029,
+        /* 2162 */ 0x0028, 0x0031, 0x0038, 0x0029,
+        /* 2166 */ 0x0028, 0x0031, 0x0039, 0x0029,
+        /* 2170 */ 0x0028, 0x0032, 0x0030, 0x0029,
+        /* 2174 */ 0x0031, 0x002E,
+        /* 2176 */ 0x0032, 0x002E,
+        /* 2178 */ 0x0033, 0x002E,
+        /* 2180 */ 0x0034, 0x002E,
+        /* 2182 */ 0x0035, 0x002E,
+        /* 2184 */ 0x0036, 0x002E,
+        /* 2186 */ 0x0037, 0x002E,
+        /* 2188 */ 0x0038, 0x002E,
+        /* 2190 */ 0x0039, 0x002E,
+        /* 2192 */ 0x0031, 0x0030, 0x002E,
+        /* 2195 */ 0x0031, 0x0031, 0x002E,
+        /* 2198 */ 0x0031, 0x0032, 0x002E,
+        /* 2201 */ 0x0031, 0x0033, 0x002E,
+        /* 2204 */ 0x0031, 0x0034, 0x002E,
+        /* 2207 */ 0x0031, 0x0035, 0x002E,
+        /* 2210 */ 0x0031, 0x0036, 0x002E,
+        /* 2213 */ 0x0031, 0x0037, 0x002E,
+        /* 2216 */ 0x0031, 0x0038, 0x002E,
+        /* 2219 */ 0x0031, 0x0039, 0x002E,
+        /* 2222 */ 0x0032, 0x0030, 0x002E,
+        /* 2225 */ 0x0028, 0x0061, 0x0029,
+        /* 2228 */ 0x0028, 0x0062, 0x0029,
+        /* 2231 */ 0x0028, 0x0063, 0x0029,
+        /* 2234 */ 0x0028, 0x0064, 0x0029,
+        /* 2237 */ 0x0028, 0x0065, 0x0029,
+        /* 2240 */ 0x0028, 0x0066, 0x0029,
+        /* 2243 */ 0x0028, 0x0067, 0x0029,
+        /* 2246 */ 0x0028, 0x0068, 0x0029,
+        /* 2249 */ 0x0028, 0x0069, 0x0029,
+        /* 2252 */ 0x0028, 0x006A, 0x0029,
+        /* 2255 */ 0x0028, 0x006B, 0x0029,
+        /* 2258 */ 0x0028, 0x006C, 0x0029,
+        /* 2261 */ 0x0028, 0x006D, 0x0029,
+        /* 2264 */ 0x0028, 0x006E, 0x0029,
+        /* 2267 */ 0x0028, 0x006F, 0x0029,
+        /* 2270 */ 0x0028, 0x0070, 0x0029,
+        /* 2273 */ 0x0028, 0x0071, 0x0029,
+        /* 2276 */ 0x0028, 0x0072, 0x0029,
+        /* 2279 */ 0x0028, 0x0073, 0x0029,
+        /* 2282 */ 0x0028, 0x0074, 0x0029,
+        /* 2285 */ 0x0028, 0x0075, 0x0029,
+        /* 2288 */ 0x0028, 0x0076, 0x0029,
+        /* 2291 */ 0x0028, 0x0077, 0x0029,
+        /* 2294 */ 0x0028, 0x0078, 0x0029,
+        /* 2297 */ 0x0028, 0x0079, 0x0029,
+        /* 2300 */ 0x0028, 0x007A, 0x0029,
+        /* 2303 */ 0x222B, 0x222B, 0x222B, 0x222B,
+        /* 2307 */ 0x003A, 0x003A, 0x003D,
+        /* 2310 */ 0x003D, 0x003D,
+        /* 2312 */ 0x003D, 0x003D, 0x003D,
+        /* 2315 */ 0x2ADD, 0x0338,
+        /* 2317 */ 0x304B, 0x3099,
+        /* 2319 */ 0x304D, 0x3099,
+        /* 2321 */ 0x304F, 0x3099,
+        /* 2323 */ 0x3051, 0x3099,
+        /* 2325 */ 0x3053, 0x3099,
+        /* 2327 */ 0x3055, 0x3099,
+        /* 2329 */ 0x3057, 0x3099,
+        /* 2331 */ 0x3059, 0x3099,
+        /* 2333 */ 0x305B, 0x3099,
+        /* 2335 */ 0x305D, 0x3099,
+        /* 2337 */ 0x305F, 0x3099,
+        /* 2339 */ 0x3061, 0x3099,
+        /* 2341 */ 0x3064, 0x3099,
+        /* 2343 */ 0x3066, 0x3099,
+        /* 2345 */ 0x3068, 0x3099,
+        /* 2347 */ 0x306F, 0x3099,
+        /* 2349 */ 0x306F, 0x309A,
+        /* 2351 */ 0x3072, 0x3099,
+        /* 2353 */ 0x3072, 0x309A,
+        /* 2355 */ 0x3075, 0x3099,
+        /* 2357 */ 0x3075, 0x309A,
+        /* 2359 */ 0x3078, 0x3099,
+        /* 2361 */ 0x3078, 0x309A,
+        /* 2363 */ 0x307B, 0x3099,
+        /* 2365 */ 0x307B, 0x309A,
+        /* 2367 */ 0x3046, 0x3099,
+        /* 2369 */ 0x0020, 0x3099,
+        /* 2371 */ 0x0020, 0x309A,
+        /* 2373 */ 0x309D, 0x3099,
+        /* 2375 */ 0x3088, 0x308A,
+        /* 2377 */ 0x30AB, 0x3099,
+        /* 2379 */ 0x30AD, 0x3099,
+        /* 2381 */ 0x30AF, 0x3099,
+        /* 2383 */ 0x30B1, 0x3099,
+        /* 2385 */ 0x30B3, 0x3099,
+        /* 2387 */ 0x30B5, 0x3099,
+        /* 2389 */ 0x30B7, 0x3099,
+        /* 2391 */ 0x30B9, 0x3099,
+        /* 2393 */ 0x30BB, 0x3099,
+        /* 2395 */ 0x30BD, 0x3099,
+        /* 2397 */ 0x30BF, 0x3099,
+        /* 2399 */ 0x30C1, 0x3099,
+        /* 2401 */ 0x30C4, 0x3099,
+        /* 2403 */ 0x30C6, 0x3099,
+        /* 2405 */ 0x30C8, 0x3099,
+        /* 2407 */ 0x30CF, 0x3099,
+        /* 2409 */ 0x30CF, 0x309A,
+        /* 2411 */ 0x30D2, 0x3099,
+        /* 2413 */ 0x30D2, 0x309A,
+        /* 2415 */ 0x30D5, 0x3099,
+        /* 2417 */ 0x30D5, 0x309A,
+        /* 2419 */ 0x30D8, 0x3099,
+        /* 2421 */ 0x30D8, 0x309A,
+        /* 2423 */ 0x30DB, 0x3099,
+        /* 2425 */ 0x30DB, 0x309A,
+        /* 2427 */ 0x30A6, 0x3099,
+        /* 2429 */ 0x30EF, 0x3099,
+        /* 2431 */ 0x30F0, 0x3099,
+        /* 2433 */ 0x30F1, 0x3099,
+        /* 2435 */ 0x30F2, 0x3099,
+        /* 2437 */ 0x30FD, 0x3099,
+        /* 2439 */ 0x30B3, 0x30C8,
+        /* 2441 */ 0x0028, 0x1100, 0x0029,
+        /* 2444 */ 0x0028, 0x1102, 0x0029,
+        /* 2447 */ 0x0028, 0x1103, 0x0029,
+        /* 2450 */ 0x0028, 0x1105, 0x0029,
+        /* 2453 */ 0x0028, 0x1106, 0x0029,
+        /* 2456 */ 0x0028, 0x1107, 0x0029,
+        /* 2459 */ 0x0028, 0x1109, 0x0029,
+        /* 2462 */ 0x0028, 0x110B, 0x0029,
+        /* 2465 */ 0x0028, 0x110C, 0x0029,
+        /* 2468 */ 0x0028, 0x110E, 0x0029,
+        /* 2471 */ 0x0028, 0x110F, 0x0029,
+        /* 2474 */ 0x0028, 0x1110, 0x0029,
+        /* 2477 */ 0x0028, 0x1111, 0x0029,
+        /* 2480 */ 0x0028, 0x1112, 0x0029,
+        /* 2483 */ 0x0028, 0x1100, 0x1161, 0x0029,
+        /* 2487 */ 0x0028, 0x1102, 0x1161, 0x0029,
+        /* 2491 */ 0x0028, 0x1103, 0x1161, 0x0029,
+        /* 2495 */ 0x0028, 0x1105, 0x1161, 0x0029,
+        /* 2499 */ 0x0028, 0x1106, 0x1161, 0x0029,
+        /* 2503 */ 0x0028, 0x1107, 0x1161, 0x0029,
+        /* 2507 */ 0x0028, 0x1109, 0x1161, 0x0029,
+        /* 2511 */ 0x0028, 0x110B, 0x1161, 0x0029,
+        /* 2515 */ 0x0028, 0x110C, 0x1161, 0x0029,
+        /* 2519 */ 0x0028, 0x110E, 0x1161, 0x0029,
+        /* 2523 */ 0x0028, 0x110F, 0x1161, 0x0029,
+        /* 2527 */ 0x0028, 0x1110, 0x1161, 0x0029,
+        /* 2531 */ 0x0028, 0x1111, 0x1161, 0x0029,
+        /* 2535 */ 0x0028, 0x1112, 0x1161, 0x0029,
+        /* 2539 */ 0x0028, 0x110C, 0x116E, 0x0029,
+        /* 2543 */ 0x0028, 0x110B, 0x1169, 0x110C, 0x1165, 0x11AB, 0x0029,
+        /* 2550 */ 0x0028, 0x110B, 0x1169, 0x1112, 0x116E, 0x0029,
+        /* 2556 */ 0x0028, 0x4E00, 0x0029,
+        /* 2559 */ 0x0028, 0x4E8C, 0x0029,
+        /* 2562 */ 0x0028, 0x4E09, 0x0029,
+        /* 2565 */ 0x0028, 0x56DB, 0x0029,
+        /* 2568 */ 0x0028, 0x4E94, 0x0029,
+        /* 2571 */ 0x0028, 0x516D, 0x0029,
+        /* 2574 */ 0x0028, 0x4E03, 0x0029,
+        /* 2577 */ 0x0028, 0x516B, 0x0029,
+        /* 2580 */ 0x0028, 0x4E5D, 0x0029,
+        /* 2583 */ 0x0028, 0x5341, 0x0029,
+        /* 2586 */ 0x0028, 0x6708, 0x0029,
+        /* 2589 */ 0x0028, 0x706B, 0x0029,
+        /* 2592 */ 0x0028, 0x6C34, 0x0029,
+        /* 2595 */ 0x0028, 0x6728, 0x0029,
+        /* 2598 */ 0x0028, 0x91D1, 0x0029,
+        /* 2601 */ 0x0028, 0x571F, 0x0029,
+        /* 2604 */ 0x0028, 0x65E5, 0x0029,
+        /* 2607 */ 0x0028, 0x682A, 0x0029,
+        /* 2610 */ 0x0028, 0x6709, 0x0029,
+        /* 2613 */ 0x0028, 0x793E, 0x0029,
+        /* 2616 */ 0x0028, 0x540D, 0x0029,
+        /* 2619 */ 0x0028, 0x7279, 0x0029,
+        /* 2622 */ 0x0028, 0x8CA1, 0x0029,
+        /* 2625 */ 0x0028, 0x795D, 0x0029,
+        /* 2628 */ 0x0028, 0x52B4, 0x0029,
+        /* 2631 */ 0x0028, 0x4EE3, 0x0029,
+        /* 2634 */ 0x0028, 0x547C, 0x0029,
+        /* 2637 */ 0x0028, 0x5B66, 0x0029,
+        /* 2640 */ 0x0028, 0x76E3, 0x0029,
+        /* 2643 */ 0x0028, 0x4F01, 0x0029,
+        /* 2646 */ 0x0028, 0x8CC7, 0x0029,
+        /* 2649 */ 0x0028, 0x5354, 0x0029,
+        /* 2652 */ 0x0028, 0x796D, 0x0029,
+        /* 2655 */ 0x0028, 0x4F11, 0x0029,
+        /* 2658 */ 0x0028, 0x81EA, 0x0029,
+        /* 2661 */ 0x0028, 0x81F3, 0x0029,
+        /* 2664 */ 0x0050, 0x0054, 0x0045,
+        /* 2667 */ 0x0032, 0x0031,
+        /* 2669 */ 0x0032, 0x0032,
+        /* 2671 */ 0x0032, 0x0033,
+        /* 2673 */ 0x0032, 0x0034,
+        /* 2675 */ 0x0032, 0x0035,
+        /* 2677 */ 0x0032, 0x0036,
+        /* 2679 */ 0x0032, 0x0037,
+        /* 2681 */ 0x0032, 0x0038,
+        /* 2683 */ 0x0032, 0x0039,
+        /* 2685 */ 0x0033, 0x0030,
+        /* 2687 */ 0x0033, 0x0031,
+        /* 2689 */ 0x0033, 0x0032,
+        /* 2691 */ 0x0033, 0x0033,
+        /* 2693 */ 0x0033, 0x0034,
+        /* 2695 */ 0x0033, 0x0035,
+        /* 2697 */ 0x1100, 0x1161,
+        /* 2699 */ 0x1102, 0x1161,
+        /* 2701 */ 0x1103, 0x1161,
+        /* 2703 */ 0x1105, 0x1161,
+        /* 2705 */ 0x1106, 0x1161,
+        /* 2707 */ 0x1107, 0x1161,
+        /* 2709 */ 0x1109, 0x1161,
+        /* 2711 */ 0x110B, 0x1161,
+        /* 2713 */ 0x110C, 0x1161,
+        /* 2715 */ 0x110E, 0x1161,
+        /* 2717 */ 0x110F, 0x1161,
+        /* 2719 */ 0x1110, 0x1161,
+        /* 2721 */ 0x1111, 0x1161,
+        /* 2723 */ 0x1112, 0x1161,
+        /* 2725 */ 0x110E, 0x1161, 0x11B7, 0x1100, 0x1169,
+        /* 2730 */ 0x110C, 0x116E, 0x110B, 0x1174,
+        /* 2734 */ 0x110B, 0x116E,
+        /* 2736 */ 0x0033, 0x0036,
+        /* 2738 */ 0x0033, 0x0037,
+        /* 2740 */ 0x0033, 0x0038,
+        /* 2742 */ 0x0033, 0x0039,
+        /* 2744 */ 0x0034, 0x0030,
+        /* 2746 */ 0x0034, 0x0031,
+        /* 2748 */ 0x0034, 0x0032,
+        /* 2750 */ 0x0034, 0x0033,
+        /* 2752 */ 0x0034, 0x0034,
+        /* 2754 */ 0x0034, 0x0035,
+        /* 2756 */ 0x0034, 0x0036,
+        /* 2758 */ 0x0034, 0x0037,
+        /* 2760 */ 0x0034, 0x0038,
+        /* 2762 */ 0x0034, 0x0039,
+        /* 2764 */ 0x0035, 0x0030,
+        /* 2766 */ 0x0031, 0x6708,
+        /* 2768 */ 0x0032, 0x6708,
+        /* 2770 */ 0x0033, 0x6708,
+        /* 2772 */ 0x0034, 0x6708,
+        /* 2774 */ 0x0035, 0x6708,
+        /* 2776 */ 0x0036, 0x6708,
+        /* 2778 */ 0x0037, 0x6708,
+        /* 2780 */ 0x0038, 0x6708,
+        /* 2782 */ 0x0039, 0x6708,
+        /* 2784 */ 0x0031, 0x0030, 0x6708,
+        /* 2787 */ 0x0031, 0x0031, 0x6708,
+        /* 2790 */ 0x0031, 0x0032, 0x6708,
+        /* 2793 */ 0x0048, 0x0067,
+        /* 2795 */ 0x0065, 0x0072, 0x0067,
+        /* 2798 */ 0x0065, 0x0056,
+        /* 2800 */ 0x004C, 0x0054, 0x0044,
+        /* 2803 */ 0x30A2, 0x30D1, 0x30FC, 0x30C8,
+        /* 2807 */ 0x30A2, 0x30EB, 0x30D5, 0x30A1,
+        /* 2811 */ 0x30A2, 0x30F3, 0x30DA, 0x30A2,
+        /* 2815 */ 0x30A2, 0x30FC, 0x30EB,
+        /* 2818 */ 0x30A4, 0x30CB, 0x30F3, 0x30B0,
+        /* 2822 */ 0x30A4, 0x30F3, 0x30C1,
+        /* 2825 */ 0x30A6, 0x30A9, 0x30F3,
+        /* 2828 */ 0x30A8, 0x30B9, 0x30AF, 0x30FC, 0x30C9,
+        /* 2833 */ 0x30A8, 0x30FC, 0x30AB, 0x30FC,
+        /* 2837 */ 0x30AA, 0x30F3, 0x30B9,
+        /* 2840 */ 0x30AA, 0x30FC, 0x30E0,
+        /* 2843 */ 0x30AB, 0x30A4, 0x30EA,
+        /* 2846 */ 0x30AB, 0x30E9, 0x30C3, 0x30C8,
+        /* 2850 */ 0x30AB, 0x30ED, 0x30EA, 0x30FC,
+        /* 2854 */ 0x30AC, 0x30ED, 0x30F3,
+        /* 2857 */ 0x30AC, 0x30F3, 0x30DE,
+        /* 2860 */ 0x30AE, 0x30AC,
+        /* 2862 */ 0x30AE, 0x30CB, 0x30FC,
+        /* 2865 */ 0x30AD, 0x30E5, 0x30EA, 0x30FC,
+        /* 2869 */ 0x30AE, 0x30EB, 0x30C0, 0x30FC,
+        /* 2873 */ 0x30AD, 0x30ED,
+        /* 2875 */ 0x30AD, 0x30ED, 0x30B0, 0x30E9, 0x30E0,
+        /* 2880 */ 0x30AD, 0x30ED, 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+        /* 2886 */ 0x30AD, 0x30ED, 0x30EF, 0x30C3, 0x30C8,
+        /* 2891 */ 0x30B0, 0x30E9, 0x30E0,
+        /* 2894 */ 0x30B0, 0x30E9, 0x30E0, 0x30C8, 0x30F3,
+        /* 2899 */ 0x30AF, 0x30EB, 0x30BC, 0x30A4, 0x30ED,
+        /* 2904 */ 0x30AF, 0x30ED, 0x30FC, 0x30CD,
+        /* 2908 */ 0x30B1, 0x30FC, 0x30B9,
+        /* 2911 */ 0x30B3, 0x30EB, 0x30CA,
+        /* 2914 */ 0x30B3, 0x30FC, 0x30DD,
+        /* 2917 */ 0x30B5, 0x30A4, 0x30AF, 0x30EB,
+        /* 2921 */ 0x30B5, 0x30F3, 0x30C1, 0x30FC, 0x30E0,
+        /* 2926 */ 0x30B7, 0x30EA, 0x30F3, 0x30B0,
+        /* 2930 */ 0x30BB, 0x30F3, 0x30C1,
+        /* 2933 */ 0x30BB, 0x30F3, 0x30C8,
+        /* 2936 */ 0x30C0, 0x30FC, 0x30B9,
+        /* 2939 */ 0x30C7, 0x30B7,
+        /* 2941 */ 0x30C9, 0x30EB,
+        /* 2943 */ 0x30C8, 0x30F3,
+        /* 2945 */ 0x30CA, 0x30CE,
+        /* 2947 */ 0x30CE, 0x30C3, 0x30C8,
+        /* 2950 */ 0x30CF, 0x30A4, 0x30C4,
+        /* 2953 */ 0x30D1, 0x30FC, 0x30BB, 0x30F3, 0x30C8,
+        /* 2958 */ 0x30D1, 0x30FC, 0x30C4,
+        /* 2961 */ 0x30D0, 0x30FC, 0x30EC, 0x30EB,
+        /* 2965 */ 0x30D4, 0x30A2, 0x30B9, 0x30C8, 0x30EB,
+        /* 2970 */ 0x30D4, 0x30AF, 0x30EB,
+        /* 2973 */ 0x30D4, 0x30B3,
+        /* 2975 */ 0x30D3, 0x30EB,
+        /* 2977 */ 0x30D5, 0x30A1, 0x30E9, 0x30C3, 0x30C9,
+        /* 2982 */ 0x30D5, 0x30A3, 0x30FC, 0x30C8,
+        /* 2986 */ 0x30D6, 0x30C3, 0x30B7, 0x30A7, 0x30EB,
+        /* 2991 */ 0x30D5, 0x30E9, 0x30F3,
+        /* 2994 */ 0x30D8, 0x30AF, 0x30BF, 0x30FC, 0x30EB,
+        /* 2999 */ 0x30DA, 0x30BD,
+        /* 3001 */ 0x30DA, 0x30CB, 0x30D2,
+        /* 3004 */ 0x30D8, 0x30EB, 0x30C4,
+        /* 3007 */ 0x30DA, 0x30F3, 0x30B9,
+        /* 3010 */ 0x30DA, 0x30FC, 0x30B8,
+        /* 3013 */ 0x30D9, 0x30FC, 0x30BF,
+        /* 3016 */ 0x30DD, 0x30A4, 0x30F3, 0x30C8,
+        /* 3020 */ 0x30DC, 0x30EB, 0x30C8,
+        /* 3023 */ 0x30DB, 0x30F3,
+        /* 3025 */ 0x30DD, 0x30F3, 0x30C9,
+        /* 3028 */ 0x30DB, 0x30FC, 0x30EB,
+        /* 3031 */ 0x30DB, 0x30FC, 0x30F3,
+        /* 3034 */ 0x30DE, 0x30A4, 0x30AF, 0x30ED,
+        /* 3038 */ 0x30DE, 0x30A4, 0x30EB,
+        /* 3041 */ 0x30DE, 0x30C3, 0x30CF,
+        /* 3044 */ 0x30DE, 0x30EB, 0x30AF,
+        /* 3047 */ 0x30DE, 0x30F3, 0x30B7, 0x30E7, 0x30F3,
+        /* 3052 */ 0x30DF, 0x30AF, 0x30ED, 0x30F3,
+        /* 3056 */ 0x30DF, 0x30EA,
+        /* 3058 */ 0x30DF, 0x30EA, 0x30D0, 0x30FC, 0x30EB,
+        /* 3063 */ 0x30E1, 0x30AC,
+        /* 3065 */ 0x30E1, 0x30AC, 0x30C8, 0x30F3,
+        /* 3069 */ 0x30E1, 0x30FC, 0x30C8, 0x30EB,
+        /* 3073 */ 0x30E4, 0x30FC, 0x30C9,
+        /* 3076 */ 0x30E4, 0x30FC, 0x30EB,
+        /* 3079 */ 0x30E6, 0x30A2, 0x30F3,
+        /* 3082 */ 0x30EA, 0x30C3, 0x30C8, 0x30EB,
+        /* 3086 */ 0x30EA, 0x30E9,
+        /* 3088 */ 0x30EB, 0x30D4, 0x30FC,
+        /* 3091 */ 0x30EB, 0x30FC, 0x30D6, 0x30EB,
+        /* 3095 */ 0x30EC, 0x30E0,
+        /* 3097 */ 0x30EC, 0x30F3, 0x30C8, 0x30B2, 0x30F3,
+        /* 3102 */ 0x30EF, 0x30C3, 0x30C8,
+        /* 3105 */ 0x0030, 0x70B9,
+        /* 3107 */ 0x0031, 0x70B9,
+        /* 3109 */ 0x0032, 0x70B9,
+        /* 3111 */ 0x0033, 0x70B9,
+        /* 3113 */ 0x0034, 0x70B9,
+        /* 3115 */ 0x0035, 0x70B9,
+        /* 3117 */ 0x0036, 0x70B9,
+        /* 3119 */ 0x0037, 0x70B9,
+        /* 3121 */ 0x0038, 0x70B9,
+        /* 3123 */ 0x0039, 0x70B9,
+        /* 3125 */ 0x0031, 0x0030, 0x70B9,
+        /* 3128 */ 0x0031, 0x0031, 0x70B9,
+        /* 3131 */ 0x0031, 0x0032, 0x70B9,
+        /* 3134 */ 0x0031, 0x0033, 0x70B9,
+        /* 3137 */ 0x0031, 0x0034, 0x70B9,
+        /* 3140 */ 0x0031, 0x0035, 0x70B9,
+        /* 3143 */ 0x0031, 0x0036, 0x70B9,
+        /* 3146 */ 0x0031, 0x0037, 0x70B9,
+        /* 3149 */ 0x0031, 0x0038, 0x70B9,
+        /* 3152 */ 0x0031, 0x0039, 0x70B9,
+        /* 3155 */ 0x0032, 0x0030, 0x70B9,
+        /* 3158 */ 0x0032, 0x0031, 0x70B9,
+        /* 3161 */ 0x0032, 0x0032, 0x70B9,
+        /* 3164 */ 0x0032, 0x0033, 0x70B9,
+        /* 3167 */ 0x0032, 0x0034, 0x70B9,
+        /* 3170 */ 0x0068, 0x0050, 0x0061,
+        /* 3173 */ 0x0064, 0x0061,
+        /* 3175 */ 0x0041, 0x0055,
+        /* 3177 */ 0x0062, 0x0061, 0x0072,
+        /* 3180 */ 0x006F, 0x0056,
+        /* 3182 */ 0x0070, 0x0063,
+        /* 3184 */ 0x0064, 0x006D,
+        /* 3186 */ 0x0064, 0x006D, 0x00B2,
+        /* 3189 */ 0x0064, 0x006D, 0x00B3,
+        /* 3192 */ 0x0049, 0x0055,
+        /* 3194 */ 0x5E73, 0x6210,
+        /* 3196 */ 0x662D, 0x548C,
+        /* 3198 */ 0x5927, 0x6B63,
+        /* 3200 */ 0x660E, 0x6CBB,
+        /* 3202 */ 0x682A, 0x5F0F, 0x4F1A, 0x793E,
+        /* 3206 */ 0x0070, 0x0041,
+        /* 3208 */ 0x006E, 0x0041,
+        /* 3210 */ 0x03BC, 0x0041,
+        /* 3212 */ 0x006D, 0x0041,
+        /* 3214 */ 0x006B, 0x0041,
+        /* 3216 */ 0x004B, 0x0042,
+        /* 3218 */ 0x004D, 0x0042,
+        /* 3220 */ 0x0047, 0x0042,
+        /* 3222 */ 0x0063, 0x0061, 0x006C,
+        /* 3225 */ 0x006B, 0x0063, 0x0061, 0x006C,
+        /* 3229 */ 0x0070, 0x0046,
+        /* 3231 */ 0x006E, 0x0046,
+        /* 3233 */ 0x03BC, 0x0046,
+        /* 3235 */ 0x03BC, 0x0067,
+        /* 3237 */ 0x006D, 0x0067,
+        /* 3239 */ 0x006B, 0x0067,
+        /* 3241 */ 0x0048, 0x007A,
+        /* 3243 */ 0x006B, 0x0048, 0x007A,
+        /* 3246 */ 0x004D, 0x0048, 0x007A,
+        /* 3249 */ 0x0047, 0x0048, 0x007A,
+        /* 3252 */ 0x0054, 0x0048, 0x007A,
+        /* 3255 */ 0x03BC, 0x2113,
+        /* 3257 */ 0x006D, 0x2113,
+        /* 3259 */ 0x0064, 0x2113,
+        /* 3261 */ 0x006B, 0x2113,
+        /* 3263 */ 0x0066, 0x006D,
+        /* 3265 */ 0x006E, 0x006D,
+        /* 3267 */ 0x03BC, 0x006D,
+        /* 3269 */ 0x006D, 0x006D,
+        /* 3271 */ 0x0063, 0x006D,
+        /* 3273 */ 0x006B, 0x006D,
+        /* 3275 */ 0x006D, 0x006D, 0x00B2,
+        /* 3278 */ 0x0063, 0x006D, 0x00B2,
+        /* 3281 */ 0x006D, 0x00B2,
+        /* 3283 */ 0x006B, 0x006D, 0x00B2,
+        /* 3286 */ 0x006D, 0x006D, 0x00B3,
+        /* 3289 */ 0x0063, 0x006D, 0x00B3,
+        /* 3292 */ 0x006D, 0x00B3,
+        /* 3294 */ 0x006B, 0x006D, 0x00B3,
+        /* 3297 */ 0x006D, 0x2215, 0x0073,
+        /* 3300 */ 0x006D, 0x2215, 0x0073, 0x00B2,
+        /* 3304 */ 0x0050, 0x0061,
+        /* 3306 */ 0x006B, 0x0050, 0x0061,
+        /* 3309 */ 0x004D, 0x0050, 0x0061,
+        /* 3312 */ 0x0047, 0x0050, 0x0061,
+        /* 3315 */ 0x0072, 0x0061, 0x0064,
+        /* 3318 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073,
+        /* 3323 */ 0x0072, 0x0061, 0x0064, 0x2215, 0x0073, 0x00B2,
+        /* 3329 */ 0x0070, 0x0073,
+        /* 3331 */ 0x006E, 0x0073,
+        /* 3333 */ 0x03BC, 0x0073,
+        /* 3335 */ 0x006D, 0x0073,
+        /* 3337 */ 0x0070, 0x0056,
+        /* 3339 */ 0x006E, 0x0056,
+        /* 3341 */ 0x03BC, 0x0056,
+        /* 3343 */ 0x006D, 0x0056,
+        /* 3345 */ 0x006B, 0x0056,
+        /* 3347 */ 0x004D, 0x0056,
+        /* 3349 */ 0x0070, 0x0057,
+        /* 3351 */ 0x006E, 0x0057,
+        /* 3353 */ 0x03BC, 0x0057,
+        /* 3355 */ 0x006D, 0x0057,
+        /* 3357 */ 0x006B, 0x0057,
+        /* 3359 */ 0x004D, 0x0057,
+        /* 3361 */ 0x006B, 0x03A9,
+        /* 3363 */ 0x004D, 0x03A9,
+        /* 3365 */ 0x0061, 0x002E, 0x006D, 0x002E,
+        /* 3369 */ 0x0042, 0x0071,
+        /* 3371 */ 0x0063, 0x0063,
+        /* 3373 */ 0x0063, 0x0064,
+        /* 3375 */ 0x0043, 0x2215, 0x006B, 0x0067,
+        /* 3379 */ 0x0043, 0x006F, 0x002E,
+        /* 3382 */ 0x0064, 0x0042,
+        /* 3384 */ 0x0047, 0x0079,
+        /* 3386 */ 0x0068, 0x0061,
+        /* 3388 */ 0x0048, 0x0050,
+        /* 3390 */ 0x0069, 0x006E,
+        /* 3392 */ 0x004B, 0x004B,
+        /* 3394 */ 0x004B, 0x004D,
+        /* 3396 */ 0x006B, 0x0074,
+        /* 3398 */ 0x006C, 0x006D,
+        /* 3400 */ 0x006C, 0x006E,
+        /* 3402 */ 0x006C, 0x006F, 0x0067,
+        /* 3405 */ 0x006C, 0x0078,
+        /* 3407 */ 0x006D, 0x0062,
+        /* 3409 */ 0x006D, 0x0069, 0x006C,
+        /* 3412 */ 0x006D, 0x006F, 0x006C,
+        /* 3415 */ 0x0050, 0x0048,
+        /* 3417 */ 0x0070, 0x002E, 0x006D, 0x002E,
+        /* 3421 */ 0x0050, 0x0050, 0x004D,
+        /* 3424 */ 0x0050, 0x0052,
+        /* 3426 */ 0x0073, 0x0072,
+        /* 3428 */ 0x0053, 0x0076,
+        /* 3430 */ 0x0057, 0x0062,
+        /* 3432 */ 0x0056, 0x2215, 0x006D,
+        /* 3435 */ 0x0041, 0x2215, 0x006D,
+        /* 3438 */ 0x0031, 0x65E5,
+        /* 3440 */ 0x0032, 0x65E5,
+        /* 3442 */ 0x0033, 0x65E5,
+        /* 3444 */ 0x0034, 0x65E5,
+        /* 3446 */ 0x0035, 0x65E5,
+        /* 3448 */ 0x0036, 0x65E5,
+        /* 3450 */ 0x0037, 0x65E5,
+        /* 3452 */ 0x0038, 0x65E5,
+        /* 3454 */ 0x0039, 0x65E5,
+        /* 3456 */ 0x0031, 0x0030, 0x65E5,
+        /* 3459 */ 0x0031, 0x0031, 0x65E5,
+        /* 3462 */ 0x0031, 0x0032, 0x65E5,
+        /* 3465 */ 0x0031, 0x0033, 0x65E5,
+        /* 3468 */ 0x0031, 0x0034, 0x65E5,
+        /* 3471 */ 0x0031, 0x0035, 0x65E5,
+        /* 3474 */ 0x0031, 0x0036, 0x65E5,
+        /* 3477 */ 0x0031, 0x0037, 0x65E5,
+        /* 3480 */ 0x0031, 0x0038, 0x65E5,
+        /* 3483 */ 0x0031, 0x0039, 0x65E5,
+        /* 3486 */ 0x0032, 0x0030, 0x65E5,
+        /* 3489 */ 0x0032, 0x0031, 0x65E5,
+        /* 3492 */ 0x0032, 0x0032, 0x65E5,
+        /* 3495 */ 0x0032, 0x0033, 0x65E5,
+        /* 3498 */ 0x0032, 0x0034, 0x65E5,
+        /* 3501 */ 0x0032, 0x0035, 0x65E5,
+        /* 3504 */ 0x0032, 0x0036, 0x65E5,
+        /* 3507 */ 0x0032, 0x0037, 0x65E5,
+        /* 3510 */ 0x0032, 0x0038, 0x65E5,
+        /* 3513 */ 0x0032, 0x0039, 0x65E5,
+        /* 3516 */ 0x0033, 0x0030, 0x65E5,
+        /* 3519 */ 0x0033, 0x0031, 0x65E5,
+        /* 3522 */ 0x0067, 0x0061, 0x006C,
+        /* 3525 */ 0x242EE,
+        /* 3526 */ 0x2284A,
+        /* 3527 */ 0x22844,
+        /* 3528 */ 0x233D5,
+        /* 3529 */ 0x25249,
+        /* 3530 */ 0x25CD0,
+        /* 3531 */ 0x27ED3,
+        /* 3532 */ 0x0066, 0x0066,
+        /* 3534 */ 0x0066, 0x0069,
+        /* 3536 */ 0x0066, 0x006C,
+        /* 3538 */ 0x0066, 0x0066, 0x0069,
+        /* 3541 */ 0x0066, 0x0066, 0x006C,
+        /* 3544 */ 0x017F, 0x0074,
+        /* 3546 */ 0x0073, 0x0074,
+        /* 3548 */ 0x0574, 0x0576,
+        /* 3550 */ 0x0574, 0x0565,
+        /* 3552 */ 0x0574, 0x056B,
+        /* 3554 */ 0x057E, 0x0576,
+        /* 3556 */ 0x0574, 0x056D,
+        /* 3558 */ 0x05D9, 0x05B4,
+        /* 3560 */ 0x05F2, 0x05B7,
+        /* 3562 */ 0x05E9, 0x05C1,
+        /* 3564 */ 0x05E9, 0x05C2,
+        /* 3566 */ 0xFB49, 0x05C1,
+        /* 3568 */ 0xFB49, 0x05C2,
+        /* 3570 */ 0x05D0, 0x05B7,
+        /* 3572 */ 0x05D0, 0x05B8,
+        /* 3574 */ 0x05D0, 0x05BC,
+        /* 3576 */ 0x05D1, 0x05BC,
+        /* 3578 */ 0x05D2, 0x05BC,
+        /* 3580 */ 0x05D3, 0x05BC,
+        /* 3582 */ 0x05D4, 0x05BC,
+        /* 3584 */ 0x05D5, 0x05BC,
+        /* 3586 */ 0x05D6, 0x05BC,
+        /* 3588 */ 0x05D8, 0x05BC,
+        /* 3590 */ 0x05D9, 0x05BC,
+        /* 3592 */ 0x05DA, 0x05BC,
+        /* 3594 */ 0x05DB, 0x05BC,
+        /* 3596 */ 0x05DC, 0x05BC,
+        /* 3598 */ 0x05DE, 0x05BC,
+        /* 3600 */ 0x05E0, 0x05BC,
+        /* 3602 */ 0x05E1, 0x05BC,
+        /* 3604 */ 0x05E3, 0x05BC,
+        /* 3606 */ 0x05E4, 0x05BC,
+        /* 3608 */ 0x05E6, 0x05BC,
+        /* 3610 */ 0x05E7, 0x05BC,
+        /* 3612 */ 0x05E8, 0x05BC,
+        /* 3614 */ 0x05E9, 0x05BC,
+        /* 3616 */ 0x05EA, 0x05BC,
+        /* 3618 */ 0x05D5, 0x05B9,
+        /* 3620 */ 0x05D1, 0x05BF,
+        /* 3622 */ 0x05DB, 0x05BF,
+        /* 3624 */ 0x05E4, 0x05BF,
+        /* 3626 */ 0x05D0, 0x05DC,
+        /* 3628 */ 0x0626, 0x0627,
+        /* 3630 */ 0x0626, 0x0627,
+        /* 3632 */ 0x0626, 0x06D5,
+        /* 3634 */ 0x0626, 0x06D5,
+        /* 3636 */ 0x0626, 0x0648,
+        /* 3638 */ 0x0626, 0x0648,
+        /* 3640 */ 0x0626, 0x06C7,
+        /* 3642 */ 0x0626, 0x06C7,
+        /* 3644 */ 0x0626, 0x06C6,
+        /* 3646 */ 0x0626, 0x06C6,
+        /* 3648 */ 0x0626, 0x06C8,
+        /* 3650 */ 0x0626, 0x06C8,
+        /* 3652 */ 0x0626, 0x06D0,
+        /* 3654 */ 0x0626, 0x06D0,
+        /* 3656 */ 0x0626, 0x06D0,
+        /* 3658 */ 0x0626, 0x0649,
+        /* 3660 */ 0x0626, 0x0649,
+        /* 3662 */ 0x0626, 0x0649,
+        /* 3664 */ 0x0626, 0x062C,
+        /* 3666 */ 0x0626, 0x062D,
+        /* 3668 */ 0x0626, 0x0645,
+        /* 3670 */ 0x0626, 0x0649,
+        /* 3672 */ 0x0626, 0x064A,
+        /* 3674 */ 0x0628, 0x062C,
+        /* 3676 */ 0x0628, 0x062D,
+        /* 3678 */ 0x0628, 0x062E,
+        /* 3680 */ 0x0628, 0x0645,
+        /* 3682 */ 0x0628, 0x0649,
+        /* 3684 */ 0x0628, 0x064A,
+        /* 3686 */ 0x062A, 0x062C,
+        /* 3688 */ 0x062A, 0x062D,
+        /* 3690 */ 0x062A, 0x062E,
+        /* 3692 */ 0x062A, 0x0645,
+        /* 3694 */ 0x062A, 0x0649,
+        /* 3696 */ 0x062A, 0x064A,
+        /* 3698 */ 0x062B, 0x062C,
+        /* 3700 */ 0x062B, 0x0645,
+        /* 3702 */ 0x062B, 0x0649,
+        /* 3704 */ 0x062B, 0x064A,
+        /* 3706 */ 0x062C, 0x062D,
+        /* 3708 */ 0x062C, 0x0645,
+        /* 3710 */ 0x062D, 0x062C,
+        /* 3712 */ 0x062D, 0x0645,
+        /* 3714 */ 0x062E, 0x062C,
+        /* 3716 */ 0x062E, 0x062D,
+        /* 3718 */ 0x062E, 0x0645,
+        /* 3720 */ 0x0633, 0x062C,
+        /* 3722 */ 0x0633, 0x062D,
+        /* 3724 */ 0x0633, 0x062E,
+        /* 3726 */ 0x0633, 0x0645,
+        /* 3728 */ 0x0635, 0x062D,
+        /* 3730 */ 0x0635, 0x0645,
+        /* 3732 */ 0x0636, 0x062C,
+        /* 3734 */ 0x0636, 0x062D,
+        /* 3736 */ 0x0636, 0x062E,
+        /* 3738 */ 0x0636, 0x0645,
+        /* 3740 */ 0x0637, 0x062D,
+        /* 3742 */ 0x0637, 0x0645,
+        /* 3744 */ 0x0638, 0x0645,
+        /* 3746 */ 0x0639, 0x062C,
+        /* 3748 */ 0x0639, 0x0645,
+        /* 3750 */ 0x063A, 0x062C,
+        /* 3752 */ 0x063A, 0x0645,
+        /* 3754 */ 0x0641, 0x062C,
+        /* 3756 */ 0x0641, 0x062D,
+        /* 3758 */ 0x0641, 0x062E,
+        /* 3760 */ 0x0641, 0x0645,
+        /* 3762 */ 0x0641, 0x0649,
+        /* 3764 */ 0x0641, 0x064A,
+        /* 3766 */ 0x0642, 0x062D,
+        /* 3768 */ 0x0642, 0x0645,
+        /* 3770 */ 0x0642, 0x0649,
+        /* 3772 */ 0x0642, 0x064A,
+        /* 3774 */ 0x0643, 0x0627,
+        /* 3776 */ 0x0643, 0x062C,
+        /* 3778 */ 0x0643, 0x062D,
+        /* 3780 */ 0x0643, 0x062E,
+        /* 3782 */ 0x0643, 0x0644,
+        /* 3784 */ 0x0643, 0x0645,
+        /* 3786 */ 0x0643, 0x0649,
+        /* 3788 */ 0x0643, 0x064A,
+        /* 3790 */ 0x0644, 0x062C,
+        /* 3792 */ 0x0644, 0x062D,
+        /* 3794 */ 0x0644, 0x062E,
+        /* 3796 */ 0x0644, 0x0645,
+        /* 3798 */ 0x0644, 0x0649,
+        /* 3800 */ 0x0644, 0x064A,
+        /* 3802 */ 0x0645, 0x062C,
+        /* 3804 */ 0x0645, 0x062D,
+        /* 3806 */ 0x0645, 0x062E,
+        /* 3808 */ 0x0645, 0x0645,
+        /* 3810 */ 0x0645, 0x0649,
+        /* 3812 */ 0x0645, 0x064A,
+        /* 3814 */ 0x0646, 0x062C,
+        /* 3816 */ 0x0646, 0x062D,
+        /* 3818 */ 0x0646, 0x062E,
+        /* 3820 */ 0x0646, 0x0645,
+        /* 3822 */ 0x0646, 0x0649,
+        /* 3824 */ 0x0646, 0x064A,
+        /* 3826 */ 0x0647, 0x062C,
+        /* 3828 */ 0x0647, 0x0645,
+        /* 3830 */ 0x0647, 0x0649,
+        /* 3832 */ 0x0647, 0x064A,
+        /* 3834 */ 0x064A, 0x062C,
+        /* 3836 */ 0x064A, 0x062D,
+        /* 3838 */ 0x064A, 0x062E,
+        /* 3840 */ 0x064A, 0x0645,
+        /* 3842 */ 0x064A, 0x0649,
+        /* 3844 */ 0x064A, 0x064A,
+        /* 3846 */ 0x0630, 0x0670,
+        /* 3848 */ 0x0631, 0x0670,
+        /* 3850 */ 0x0649, 0x0670,
+        /* 3852 */ 0x0020, 0x064C, 0x0651,
+        /* 3855 */ 0x0020, 0x064D, 0x0651,
+        /* 3858 */ 0x0020, 0x064E, 0x0651,
+        /* 3861 */ 0x0020, 0x064F, 0x0651,
+        /* 3864 */ 0x0020, 0x0650, 0x0651,
+        /* 3867 */ 0x0020, 0x0651, 0x0670,
+        /* 3870 */ 0x0626, 0x0631,
+        /* 3872 */ 0x0626, 0x0632,
+        /* 3874 */ 0x0626, 0x0645,
+        /* 3876 */ 0x0626, 0x0646,
+        /* 3878 */ 0x0626, 0x0649,
+        /* 3880 */ 0x0626, 0x064A,
+        /* 3882 */ 0x0628, 0x0631,
+        /* 3884 */ 0x0628, 0x0632,
+        /* 3886 */ 0x0628, 0x0645,
+        /* 3888 */ 0x0628, 0x0646,
+        /* 3890 */ 0x0628, 0x0649,
+        /* 3892 */ 0x0628, 0x064A,
+        /* 3894 */ 0x062A, 0x0631,
+        /* 3896 */ 0x062A, 0x0632,
+        /* 3898 */ 0x062A, 0x0645,
+        /* 3900 */ 0x062A, 0x0646,
+        /* 3902 */ 0x062A, 0x0649,
+        /* 3904 */ 0x062A, 0x064A,
+        /* 3906 */ 0x062B, 0x0631,
+        /* 3908 */ 0x062B, 0x0632,
+        /* 3910 */ 0x062B, 0x0645,
+        /* 3912 */ 0x062B, 0x0646,
+        /* 3914 */ 0x062B, 0x0649,
+        /* 3916 */ 0x062B, 0x064A,
+        /* 3918 */ 0x0641, 0x0649,
+        /* 3920 */ 0x0641, 0x064A,
+        /* 3922 */ 0x0642, 0x0649,
+        /* 3924 */ 0x0642, 0x064A,
+        /* 3926 */ 0x0643, 0x0627,
+        /* 3928 */ 0x0643, 0x0644,
+        /* 3930 */ 0x0643, 0x0645,
+        /* 3932 */ 0x0643, 0x0649,
+        /* 3934 */ 0x0643, 0x064A,
+        /* 3936 */ 0x0644, 0x0645,
+        /* 3938 */ 0x0644, 0x0649,
+        /* 3940 */ 0x0644, 0x064A,
+        /* 3942 */ 0x0645, 0x0627,
+        /* 3944 */ 0x0645, 0x0645,
+        /* 3946 */ 0x0646, 0x0631,
+        /* 3948 */ 0x0646, 0x0632,
+        /* 3950 */ 0x0646, 0x0645,
+        /* 3952 */ 0x0646, 0x0646,
+        /* 3954 */ 0x0646, 0x0649,
+        /* 3956 */ 0x0646, 0x064A,
+        /* 3958 */ 0x0649, 0x0670,
+        /* 3960 */ 0x064A, 0x0631,
+        /* 3962 */ 0x064A, 0x0632,
+        /* 3964 */ 0x064A, 0x0645,
+        /* 3966 */ 0x064A, 0x0646,
+        /* 3968 */ 0x064A, 0x0649,
+        /* 3970 */ 0x064A, 0x064A,
+        /* 3972 */ 0x0626, 0x062C,
+        /* 3974 */ 0x0626, 0x062D,
+        /* 3976 */ 0x0626, 0x062E,
+        /* 3978 */ 0x0626, 0x0645,
+        /* 3980 */ 0x0626, 0x0647,
+        /* 3982 */ 0x0628, 0x062C,
+        /* 3984 */ 0x0628, 0x062D,
+        /* 3986 */ 0x0628, 0x062E,
+        /* 3988 */ 0x0628, 0x0645,
+        /* 3990 */ 0x0628, 0x0647,
+        /* 3992 */ 0x062A, 0x062C,
+        /* 3994 */ 0x062A, 0x062D,
+        /* 3996 */ 0x062A, 0x062E,
+        /* 3998 */ 0x062A, 0x0645,
+        /* 4000 */ 0x062A, 0x0647,
+        /* 4002 */ 0x062B, 0x0645,
+        /* 4004 */ 0x062C, 0x062D,
+        /* 4006 */ 0x062C, 0x0645,
+        /* 4008 */ 0x062D, 0x062C,
+        /* 4010 */ 0x062D, 0x0645,
+        /* 4012 */ 0x062E, 0x062C,
+        /* 4014 */ 0x062E, 0x0645,
+        /* 4016 */ 0x0633, 0x062C,
+        /* 4018 */ 0x0633, 0x062D,
+        /* 4020 */ 0x0633, 0x062E,
+        /* 4022 */ 0x0633, 0x0645,
+        /* 4024 */ 0x0635, 0x062D,
+        /* 4026 */ 0x0635, 0x062E,
+        /* 4028 */ 0x0635, 0x0645,
+        /* 4030 */ 0x0636, 0x062C,
+        /* 4032 */ 0x0636, 0x062D,
+        /* 4034 */ 0x0636, 0x062E,
+        /* 4036 */ 0x0636, 0x0645,
+        /* 4038 */ 0x0637, 0x062D,
+        /* 4040 */ 0x0638, 0x0645,
+        /* 4042 */ 0x0639, 0x062C,
+        /* 4044 */ 0x0639, 0x0645,
+        /* 4046 */ 0x063A, 0x062C,
+        /* 4048 */ 0x063A, 0x0645,
+        /* 4050 */ 0x0641, 0x062C,
+        /* 4052 */ 0x0641, 0x062D,
+        /* 4054 */ 0x0641, 0x062E,
+        /* 4056 */ 0x0641, 0x0645,
+        /* 4058 */ 0x0642, 0x062D,
+        /* 4060 */ 0x0642, 0x0645,
+        /* 4062 */ 0x0643, 0x062C,
+        /* 4064 */ 0x0643, 0x062D,
+        /* 4066 */ 0x0643, 0x062E,
+        /* 4068 */ 0x0643, 0x0644,
+        /* 4070 */ 0x0643, 0x0645,
+        /* 4072 */ 0x0644, 0x062C,
+        /* 4074 */ 0x0644, 0x062D,
+        /* 4076 */ 0x0644, 0x062E,
+        /* 4078 */ 0x0644, 0x0645,
+        /* 4080 */ 0x0644, 0x0647,
+        /* 4082 */ 0x0645, 0x062C,
+        /* 4084 */ 0x0645, 0x062D,
+        /* 4086 */ 0x0645, 0x062E,
+        /* 4088 */ 0x0645, 0x0645,
+        /* 4090 */ 0x0646, 0x062C,
+        /* 4092 */ 0x0646, 0x062D,
+        /* 4094 */ 0x0646, 0x062E,
+        /* 4096 */ 0x0646, 0x0645,
+        /* 4098 */ 0x0646, 0x0647,
+        /* 4100 */ 0x0647, 0x062C,
+        /* 4102 */ 0x0647, 0x0645,
+        /* 4104 */ 0x0647, 0x0670,
+        /* 4106 */ 0x064A, 0x062C,
+        /* 4108 */ 0x064A, 0x062D,
+        /* 4110 */ 0x064A, 0x062E,
+        /* 4112 */ 0x064A, 0x0645,
+        /* 4114 */ 0x064A, 0x0647,
+        /* 4116 */ 0x0626, 0x0645,
+        /* 4118 */ 0x0626, 0x0647,
+        /* 4120 */ 0x0628, 0x0645,
+        /* 4122 */ 0x0628, 0x0647,
+        /* 4124 */ 0x062A, 0x0645,
+        /* 4126 */ 0x062A, 0x0647,
+        /* 4128 */ 0x062B, 0x0645,
+        /* 4130 */ 0x062B, 0x0647,
+        /* 4132 */ 0x0633, 0x0645,
+        /* 4134 */ 0x0633, 0x0647,
+        /* 4136 */ 0x0634, 0x0645,
+        /* 4138 */ 0x0634, 0x0647,
+        /* 4140 */ 0x0643, 0x0644,
+        /* 4142 */ 0x0643, 0x0645,
+        /* 4144 */ 0x0644, 0x0645,
+        /* 4146 */ 0x0646, 0x0645,
+        /* 4148 */ 0x0646, 0x0647,
+        /* 4150 */ 0x064A, 0x0645,
+        /* 4152 */ 0x064A, 0x0647,
+        /* 4154 */ 0x0640, 0x064E, 0x0651,
+        /* 4157 */ 0x0640, 0x064F, 0x0651,
+        /* 4160 */ 0x0640, 0x0650, 0x0651,
+        /* 4163 */ 0x0637, 0x0649,
+        /* 4165 */ 0x0637, 0x064A,
+        /* 4167 */ 0x0639, 0x0649,
+        /* 4169 */ 0x0639, 0x064A,
+        /* 4171 */ 0x063A, 0x0649,
+        /* 4173 */ 0x063A, 0x064A,
+        /* 4175 */ 0x0633, 0x0649,
+        /* 4177 */ 0x0633, 0x064A,
+        /* 4179 */ 0x0634, 0x0649,
+        /* 4181 */ 0x0634, 0x064A,
+        /* 4183 */ 0x062D, 0x0649,
+        /* 4185 */ 0x062D, 0x064A,
+        /* 4187 */ 0x062C, 0x0649,
+        /* 4189 */ 0x062C, 0x064A,
+        /* 4191 */ 0x062E, 0x0649,
+        /* 4193 */ 0x062E, 0x064A,
+        /* 4195 */ 0x0635, 0x0649,
+        /* 4197 */ 0x0635, 0x064A,
+        /* 4199 */ 0x0636, 0x0649,
+        /* 4201 */ 0x0636, 0x064A,
+        /* 4203 */ 0x0634, 0x062C,
+        /* 4205 */ 0x0634, 0x062D,
+        /* 4207 */ 0x0634, 0x062E,
+        /* 4209 */ 0x0634, 0x0645,
+        /* 4211 */ 0x0634, 0x0631,
+        /* 4213 */ 0x0633, 0x0631,
+        /* 4215 */ 0x0635, 0x0631,
+        /* 4217 */ 0x0636, 0x0631,
+        /* 4219 */ 0x0637, 0x0649,
+        /* 4221 */ 0x0637, 0x064A,
+        /* 4223 */ 0x0639, 0x0649,
+        /* 4225 */ 0x0639, 0x064A,
+        /* 4227 */ 0x063A, 0x0649,
+        /* 4229 */ 0x063A, 0x064A,
+        /* 4231 */ 0x0633, 0x0649,
+        /* 4233 */ 0x0633, 0x064A,
+        /* 4235 */ 0x0634, 0x0649,
+        /* 4237 */ 0x0634, 0x064A,
+        /* 4239 */ 0x062D, 0x0649,
+        /* 4241 */ 0x062D, 0x064A,
+        /* 4243 */ 0x062C, 0x0649,
+        /* 4245 */ 0x062C, 0x064A,
+        /* 4247 */ 0x062E, 0x0649,
+        /* 4249 */ 0x062E, 0x064A,
+        /* 4251 */ 0x0635, 0x0649,
+        /* 4253 */ 0x0635, 0x064A,
+        /* 4255 */ 0x0636, 0x0649,
+        /* 4257 */ 0x0636, 0x064A,
+        /* 4259 */ 0x0634, 0x062C,
+        /* 4261 */ 0x0634, 0x062D,
+        /* 4263 */ 0x0634, 0x062E,
+        /* 4265 */ 0x0634, 0x0645,
+        /* 4267 */ 0x0634, 0x0631,
+        /* 4269 */ 0x0633, 0x0631,
+        /* 4271 */ 0x0635, 0x0631,
+        /* 4273 */ 0x0636, 0x0631,
+        /* 4275 */ 0x0634, 0x062C,
+        /* 4277 */ 0x0634, 0x062D,
+        /* 4279 */ 0x0634, 0x062E,
+        /* 4281 */ 0x0634, 0x0645,
+        /* 4283 */ 0x0633, 0x0647,
+        /* 4285 */ 0x0634, 0x0647,
+        /* 4287 */ 0x0637, 0x0645,
+        /* 4289 */ 0x0633, 0x062C,
+        /* 4291 */ 0x0633, 0x062D,
+        /* 4293 */ 0x0633, 0x062E,
+        /* 4295 */ 0x0634, 0x062C,
+        /* 4297 */ 0x0634, 0x062D,
+        /* 4299 */ 0x0634, 0x062E,
+        /* 4301 */ 0x0637, 0x0645,
+        /* 4303 */ 0x0638, 0x0645,
+        /* 4305 */ 0x0627, 0x064B,
+        /* 4307 */ 0x0627, 0x064B,
+        /* 4309 */ 0x062A, 0x062C, 0x0645,
+        /* 4312 */ 0x062A, 0x062D, 0x062C,
+        /* 4315 */ 0x062A, 0x062D, 0x062C,
+        /* 4318 */ 0x062A, 0x062D, 0x0645,
+        /* 4321 */ 0x062A, 0x062E, 0x0645,
+        /* 4324 */ 0x062A, 0x0645, 0x062C,
+        /* 4327 */ 0x062A, 0x0645, 0x062D,
+        /* 4330 */ 0x062A, 0x0645, 0x062E,
+        /* 4333 */ 0x062C, 0x0645, 0x062D,
+        /* 4336 */ 0x062C, 0x0645, 0x062D,
+        /* 4339 */ 0x062D, 0x0645, 0x064A,
+        /* 4342 */ 0x062D, 0x0645, 0x0649,
+        /* 4345 */ 0x0633, 0x062D, 0x062C,
+        /* 4348 */ 0x0633, 0x062C, 0x062D,
+        /* 4351 */ 0x0633, 0x062C, 0x0649,
+        /* 4354 */ 0x0633, 0x0645, 0x062D,
+        /* 4357 */ 0x0633, 0x0645, 0x062D,
+        /* 4360 */ 0x0633, 0x0645, 0x062C,
+        /* 4363 */ 0x0633, 0x0645, 0x0645,
+        /* 4366 */ 0x0633, 0x0645, 0x0645,
+        /* 4369 */ 0x0635, 0x062D, 0x062D,
+        /* 4372 */ 0x0635, 0x062D, 0x062D,
+        /* 4375 */ 0x0635, 0x0645, 0x0645,
+        /* 4378 */ 0x0634, 0x062D, 0x0645,
+        /* 4381 */ 0x0634, 0x062D, 0x0645,
+        /* 4384 */ 0x0634, 0x062C, 0x064A,
+        /* 4387 */ 0x0634, 0x0645, 0x062E,
+        /* 4390 */ 0x0634, 0x0645, 0x062E,
+        /* 4393 */ 0x0634, 0x0645, 0x0645,
+        /* 4396 */ 0x0634, 0x0645, 0x0645,
+        /* 4399 */ 0x0636, 0x062D, 0x0649,
+        /* 4402 */ 0x0636, 0x062E, 0x0645,
+        /* 4405 */ 0x0636, 0x062E, 0x0645,
+        /* 4408 */ 0x0637, 0x0645, 0x062D,
+        /* 4411 */ 0x0637, 0x0645, 0x062D,
+        /* 4414 */ 0x0637, 0x0645, 0x0645,
+        /* 4417 */ 0x0637, 0x0645, 0x064A,
+        /* 4420 */ 0x0639, 0x062C, 0x0645,
+        /* 4423 */ 0x0639, 0x0645, 0x0645,
+        /* 4426 */ 0x0639, 0x0645, 0x0645,
+        /* 4429 */ 0x0639, 0x0645, 0x0649,
+        /* 4432 */ 0x063A, 0x0645, 0x0645,
+        /* 4435 */ 0x063A, 0x0645, 0x064A,
+        /* 4438 */ 0x063A, 0x0645, 0x0649,
+        /* 4441 */ 0x0641, 0x062E, 0x0645,
+        /* 4444 */ 0x0641, 0x062E, 0x0645,
+        /* 4447 */ 0x0642, 0x0645, 0x062D,
+        /* 4450 */ 0x0642, 0x0645, 0x0645,
+        /* 4453 */ 0x0644, 0x062D, 0x0645,
+        /* 4456 */ 0x0644, 0x062D, 0x064A,
+        /* 4459 */ 0x0644, 0x062D, 0x0649,
+        /* 4462 */ 0x0644, 0x062C, 0x062C,
+        /* 4465 */ 0x0644, 0x062C, 0x062C,
+        /* 4468 */ 0x0644, 0x062E, 0x0645,
+        /* 4471 */ 0x0644, 0x062E, 0x0645,
+        /* 4474 */ 0x0644, 0x0645, 0x062D,
+        /* 4477 */ 0x0644, 0x0645, 0x062D,
+        /* 4480 */ 0x0645, 0x062D, 0x062C,
+        /* 4483 */ 0x0645, 0x062D, 0x0645,
+        /* 4486 */ 0x0645, 0x062D, 0x064A,
+        /* 4489 */ 0x0645, 0x062C, 0x062D,
+        /* 4492 */ 0x0645, 0x062C, 0x0645,
+        /* 4495 */ 0x0645, 0x062E, 0x062C,
+        /* 4498 */ 0x0645, 0x062E, 0x0645,
+        /* 4501 */ 0x0645, 0x062C, 0x062E,
+        /* 4504 */ 0x0647, 0x0645, 0x062C,
+        /* 4507 */ 0x0647, 0x0645, 0x0645,
+        /* 4510 */ 0x0646, 0x062D, 0x0645,
+        /* 4513 */ 0x0646, 0x062D, 0x0649,
+        /* 4516 */ 0x0646, 0x062C, 0x0645,
+        /* 4519 */ 0x0646, 0x062C, 0x0645,
+        /* 4522 */ 0x0646, 0x062C, 0x0649,
+        /* 4525 */ 0x0646, 0x0645, 0x064A,
+        /* 4528 */ 0x0646, 0x0645, 0x0649,
+        /* 4531 */ 0x064A, 0x0645, 0x0645,
+        /* 4534 */ 0x064A, 0x0645, 0x0645,
+        /* 4537 */ 0x0628, 0x062E, 0x064A,
+        /* 4540 */ 0x062A, 0x062C, 0x064A,
+        /* 4543 */ 0x062A, 0x062C, 0x0649,
+        /* 4546 */ 0x062A, 0x062E, 0x064A,
+        /* 4549 */ 0x062A, 0x062E, 0x0649,
+        /* 4552 */ 0x062A, 0x0645, 0x064A,
+        /* 4555 */ 0x062A, 0x0645, 0x0649,
+        /* 4558 */ 0x062C, 0x0645, 0x064A,
+        /* 4561 */ 0x062C, 0x062D, 0x0649,
+        /* 4564 */ 0x062C, 0x0645, 0x0649,
+        /* 4567 */ 0x0633, 0x062E, 0x0649,
+        /* 4570 */ 0x0635, 0x062D, 0x064A,
+        /* 4573 */ 0x0634, 0x062D, 0x064A,
+        /* 4576 */ 0x0636, 0x062D, 0x064A,
+        /* 4579 */ 0x0644, 0x062C, 0x064A,
+        /* 4582 */ 0x0644, 0x0645, 0x064A,
+        /* 4585 */ 0x064A, 0x062D, 0x064A,
+        /* 4588 */ 0x064A, 0x062C, 0x064A,
+        /* 4591 */ 0x064A, 0x0645, 0x064A,
+        /* 4594 */ 0x0645, 0x0645, 0x064A,
+        /* 4597 */ 0x0642, 0x0645, 0x064A,
+        /* 4600 */ 0x0646, 0x062D, 0x064A,
+        /* 4603 */ 0x0642, 0x0645, 0x062D,
+        /* 4606 */ 0x0644, 0x062D, 0x0645,
+        /* 4609 */ 0x0639, 0x0645, 0x064A,
+        /* 4612 */ 0x0643, 0x0645, 0x064A,
+        /* 4615 */ 0x0646, 0x062C, 0x062D,
+        /* 4618 */ 0x0645, 0x062E, 0x064A,
+        /* 4621 */ 0x0644, 0x062C, 0x0645,
+        /* 4624 */ 0x0643, 0x0645, 0x0645,
+        /* 4627 */ 0x0644, 0x062C, 0x0645,
+        /* 4630 */ 0x0646, 0x062C, 0x062D,
+        /* 4633 */ 0x062C, 0x062D, 0x064A,
+        /* 4636 */ 0x062D, 0x062C, 0x064A,
+        /* 4639 */ 0x0645, 0x062C, 0x064A,
+        /* 4642 */ 0x0641, 0x0645, 0x064A,
+        /* 4645 */ 0x0628, 0x062D, 0x064A,
+        /* 4648 */ 0x0643, 0x0645, 0x0645,
+        /* 4651 */ 0x0639, 0x062C, 0x0645,
+        /* 4654 */ 0x0635, 0x0645, 0x0645,
+        /* 4657 */ 0x0633, 0x062E, 0x064A,
+        /* 4660 */ 0x0646, 0x062C, 0x064A,
+        /* 4663 */ 0x0635, 0x0644, 0x06D2,
+        /* 4666 */ 0x0642, 0x0644, 0x06D2,
+        /* 4669 */ 0x0627, 0x0644, 0x0644, 0x0647,
+        /* 4673 */ 0x0627, 0x0643, 0x0628, 0x0631,
+        /* 4677 */ 0x0645, 0x062D, 0x0645, 0x062F,
+        /* 4681 */ 0x0635, 0x0644, 0x0639, 0x0645,
+        /* 4685 */ 0x0631, 0x0633, 0x0648, 0x0644,
+        /* 4689 */ 0x0639, 0x0644, 0x064A, 0x0647,
+        /* 4693 */ 0x0648, 0x0633, 0x0644, 0x0645,
+        /* 4697 */ 0x0635, 0x0644, 0x0649,
+        /* 4700 */ 0x0635, 0x0644, 0x0649, 0x0020, 0x0627, 0x0644, 0x0644, 0x0647, 0x0020, 0x0639, 0x0644, 0x064A, 0x0647, 0x0020, 0x0648, 0x0633, 0x0644, 0x0645,
+        /* 4718 */ 0x062C, 0x0644, 0x0020, 0x062C, 0x0644, 0x0627, 0x0644, 0x0647,
+        /* 4726 */ 0x0631, 0x06CC, 0x0627, 0x0644,
+        /* 4730 */ 0x0020, 0x064B,
+        /* 4732 */ 0x0640, 0x064B,
+        /* 4734 */ 0x0020, 0x064C,
+        /* 4736 */ 0x0020, 0x064D,
+        /* 4738 */ 0x0020, 0x064E,
+        /* 4740 */ 0x0640, 0x064E,
+        /* 4742 */ 0x0020, 0x064F,
+        /* 4744 */ 0x0640, 0x064F,
+        /* 4746 */ 0x0020, 0x0650,
+        /* 4748 */ 0x0640, 0x0650,
+        /* 4750 */ 0x0020, 0x0651,
+        /* 4752 */ 0x0640, 0x0651,
+        /* 4754 */ 0x0020, 0x0652,
+        /* 4756 */ 0x0640, 0x0652,
+        /* 4758 */ 0x0644, 0x0622,
+        /* 4760 */ 0x0644, 0x0622,
+        /* 4762 */ 0x0644, 0x0623,
+        /* 4764 */ 0x0644, 0x0623,
+        /* 4766 */ 0x0644, 0x0625,
+        /* 4768 */ 0x0644, 0x0625,
+        /* 4770 */ 0x0644, 0x0627,
+        /* 4772 */ 0x0644, 0x0627,
+        /* 4774 */ 0x11099, 0x110BA,
+        /* 4776 */ 0x1109B, 0x110BA,
+        /* 4778 */ 0x110A5, 0x110BA,
+        /* 4780 */ 0x11131, 0x11127,
+        /* 4782 */ 0x11132, 0x11127,
+        /* 4784 */ 0x11347, 0x1133E,
+        /* 4786 */ 0x11347, 0x11357,
+        /* 4788 */ 0x114B9, 0x114BA,
+        /* 4790 */ 0x114B9, 0x114B0,
+        /* 4792 */ 0x114B9, 0x114BD,
+        /* 4794 */ 0x115B8, 0x115AF,
+        /* 4796 */ 0x115B9, 0x115AF,
+        /* 4798 */ 0x1D157, 0x1D165,
+        /* 4800 */ 0x1D158, 0x1D165,
+        /* 4802 */ 0x1D15F, 0x1D16E,
+        /* 4804 */ 0x1D15F, 0x1D16F,
+        /* 4806 */ 0x1D15F, 0x1D170,
+        /* 4808 */ 0x1D15F, 0x1D171,
+        /* 4810 */ 0x1D15F, 0x1D172,
+        /* 4812 */ 0x1D1B9, 0x1D165,
+        /* 4814 */ 0x1D1BA, 0x1D165,
+        /* 4816 */ 0x1D1BB, 0x1D16E,
+        /* 4818 */ 0x1D1BC, 0x1D16E,
+        /* 4820 */ 0x1D1BB, 0x1D16F,
+        /* 4822 */ 0x1D1BC, 0x1D16F,
+        /* 4824 */ 0x0030, 0x002E,
+        /* 4826 */ 0x0030, 0x002C,
+        /* 4828 */ 0x0031, 0x002C,
+        /* 4830 */ 0x0032, 0x002C,
+        /* 4832 */ 0x0033, 0x002C,
+        /* 4834 */ 0x0034, 0x002C,
+        /* 4836 */ 0x0035, 0x002C,
+        /* 4838 */ 0x0036, 0x002C,
+        /* 4840 */ 0x0037, 0x002C,
+        /* 4842 */ 0x0038, 0x002C,
+        /* 4844 */ 0x0039, 0x002C,
+        /* 4846 */ 0x0028, 0x0041, 0x0029,
+        /* 4849 */ 0x0028, 0x0042, 0x0029,
+        /* 4852 */ 0x0028, 0x0043, 0x0029,
+        /* 4855 */ 0x0028, 0x0044, 0x0029,
+        /* 4858 */ 0x0028, 0x0045, 0x0029,
+        /* 4861 */ 0x0028, 0x0046, 0x0029,
+        /* 4864 */ 0x0028, 0x0047, 0x0029,
+        /* 4867 */ 0x0028, 0x0048, 0x0029,
+        /* 4870 */ 0x0028, 0x0049, 0x0029,
+        /* 4873 */ 0x0028, 0x004A, 0x0029,
+        /* 4876 */ 0x0028, 0x004B, 0x0029,
+        /* 4879 */ 0x0028, 0x004C, 0x0029,
+        /* 4882 */ 0x0028, 0x004D, 0x0029,
+        /* 4885 */ 0x0028, 0x004E, 0x0029,
+        /* 4888 */ 0x0028, 0x004F, 0x0029,
+        /* 4891 */ 0x0028, 0x0050, 0x0029,
+        /* 4894 */ 0x0028, 0x0051, 0x0029,
+        /* 4897 */ 0x0028, 0x0052, 0x0029,
+        /* 4900 */ 0x0028, 0x0053, 0x0029,
+        /* 4903 */ 0x0028, 0x0054, 0x0029,
+        /* 4906 */ 0x0028, 0x0055, 0x0029,
+        /* 4909 */ 0x0028, 0x0056, 0x0029,
+        /* 4912 */ 0x0028, 0x0057, 0x0029,
+        /* 4915 */ 0x0028, 0x0058, 0x0029,
+        /* 4918 */ 0x0028, 0x0059, 0x0029,
+        /* 4921 */ 0x0028, 0x005A, 0x0029,
+        /* 4924 */ 0x3014, 0x0053, 0x3015,
+        /* 4927 */ 0x0043, 0x0044,
+        /* 4929 */ 0x0057, 0x005A,
+        /* 4931 */ 0x0048, 0x0056,
+        /* 4933 */ 0x004D, 0x0056,
+        /* 4935 */ 0x0053, 0x0044,
+        /* 4937 */ 0x0053, 0x0053,
+        /* 4939 */ 0x0050, 0x0050, 0x0056,
+        /* 4942 */ 0x0057, 0x0043,
+        /* 4944 */ 0x004D, 0x0043,
+        /* 4946 */ 0x004D, 0x0044,
+        /* 4948 */ 0x0044, 0x004A,
+        /* 4950 */ 0x307B, 0x304B,
+        /* 4952 */ 0x30B3, 0x30B3,
+        /* 4954 */ 0x3014, 0x672C, 0x3015,
+        /* 4957 */ 0x3014, 0x4E09, 0x3015,
+        /* 4960 */ 0x3014, 0x4E8C, 0x3015,
+        /* 4963 */ 0x3014, 0x5B89, 0x3015,
+        /* 4966 */ 0x3014, 0x70B9, 0x3015,
+        /* 4969 */ 0x3014, 0x6253, 0x3015,
+        /* 4972 */ 0x3014, 0x76D7, 0x3015,
+        /* 4975 */ 0x3014, 0x52DD, 0x3015,
+        /* 4978 */ 0x3014, 0x6557, 0x3015,
+        /* 4981 */ 0x20122,
+        /* 4982 */ 0x2063A,
+        /* 4983 */ 0x2051C,
+        /* 4984 */ 0x2054B,
+        /* 4985 */ 0x291DF,
+        /* 4986 */ 0x20A2C,
+        /* 4987 */ 0x20B63,
+        /* 4988 */ 0x214E4,
+        /* 4989 */ 0x216A8,
+        /* 4990 */ 0x216EA,
+        /* 4991 */ 0x219C8,
+        /* 4992 */ 0x21B18,
+        /* 4993 */ 0x21DE4,
+        /* 4994 */ 0x21DE6,
+        /* 4995 */ 0x22183,
+        /* 4996 */ 0x2A392,
+        /* 4997 */ 0x22331,
+        /* 4998 */ 0x22331,
+        /* 4999 */ 0x232B8,
+        /* 5000 */ 0x261DA,
+        /* 5001 */ 0x226D4,
+        /* 5002 */ 0x22B0C,
+        /* 5003 */ 0x22BF1,
+        /* 5004 */ 0x2300A,
+        /* 5005 */ 0x233C3,
+        /* 5006 */ 0x2346D,
+        /* 5007 */ 0x236A3,
+        /* 5008 */ 0x238A7,
+        /* 5009 */ 0x23A8D,
+        /* 5010 */ 0x21D0B,
+        /* 5011 */ 0x23AFA,
+        /* 5012 */ 0x23CBC,
+        /* 5013 */ 0x23D1E,
+        /* 5014 */ 0x23ED1,
+        /* 5015 */ 0x23F5E,
+        /* 5016 */ 0x23F8E,
+        /* 5017 */ 0x20525,
+        /* 5018 */ 0x24263,
+        /* 5019 */ 0x243AB,
+        /* 5020 */ 0x24608,
+        /* 5021 */ 0x24735,
+        /* 5022 */ 0x24814,
+        /* 5023 */ 0x24C36,
+        /* 5024 */ 0x24C92,
+        /* 5025 */ 0x2219F,
+        /* 5026 */ 0x24FA1,
+        /* 5027 */ 0x24FB8,
+        /* 5028 */ 0x25044,
+        /* 5029 */ 0x250F3,
+        /* 5030 */ 0x250F2,
+        /* 5031 */ 0x25119,
+        /* 5032 */ 0x25133,
+        /* 5033 */ 0x2541D,
+        /* 5034 */ 0x25626,
+        /* 5035 */ 0x2569A,
+        /* 5036 */ 0x256C5,
+        /* 5037 */ 0x2597C,
+        /* 5038 */ 0x25AA7,
+        /* 5039 */ 0x25AA7,
+        /* 5040 */ 0x25BAB,
+        /* 5041 */ 0x25C80,
+        /* 5042 */ 0x25F86,
+        /* 5043 */ 0x26228,
+        /* 5044 */ 0x26247,
+        /* 5045 */ 0x262D9,
+        /* 5046 */ 0x2633E,
+        /* 5047 */ 0x264DA,
+        /* 5048 */ 0x26523,
+        /* 5049 */ 0x265A8,
+        /* 5050 */ 0x2335F,
+        /* 5051 */ 0x267A7,
+        /* 5052 */ 0x267B5,
+        /* 5053 */ 0x23393,
+        /* 5054 */ 0x2339C,
+        /* 5055 */ 0x26B3C,
+        /* 5056 */ 0x26C36,
+        /* 5057 */ 0x26D6B,
+        /* 5058 */ 0x26CD5,
+        /* 5059 */ 0x273CA,
+        /* 5060 */ 0x26F2C,
+        /* 5061 */ 0x26FB1,
+        /* 5062 */ 0x270D2,
+        /* 5063 */ 0x27667,
+        /* 5064 */ 0x278AE,
+        /* 5065 */ 0x27966,
+        /* 5066 */ 0x27CA8,
+        /* 5067 */ 0x27F2F,
+        /* 5068 */ 0x20804,
+        /* 5069 */ 0x208DE,
+        /* 5070 */ 0x285D2,
+        /* 5071 */ 0x285ED,
+        /* 5072 */ 0x2872E,
+        /* 5073 */ 0x28BFA,
+        /* 5074 */ 0x28D77,
+        /* 5075 */ 0x29145,
+        /* 5076 */ 0x2921A,
+        /* 5077 */ 0x2940A,
+        /* 5078 */ 0x29496,
+        /* 5079 */ 0x295B6,
+        /* 5080 */ 0x29B30,
+        /* 5081 */ 0x2A0CE,
+        /* 5082 */ 0x2A105,
+        /* 5083 */ 0x2A20E,
+        /* 5084 */ 0x2A291,
+        /* 5085 */ 0x2A600
+};
index de0500cd27813043249aba25e3b23f1a7defa548..b73de1baae962ac3b4258f7f57dd4f42cf160af9 100644 (file)
@@ -103,6 +103,12 @@ void pktbuf_write_ExtQuery(PktBuf *buf, const char *query, int nargs, ...);
 #define pktbuf_write_PasswordMessage(buf, psw) \
        pktbuf_write_generic(buf, 'p', "s", psw)
 
+#define pkgbuf_write_SASLInitialResponseMessage(buf, mech, cir) \
+       pktbuf_write_generic(buf, 'p', "sib", mech, strlen(cir), cir, strlen(cir))
+
+#define pkgbuf_write_SASLResponseMessage(buf, cr) \
+       pktbuf_write_generic(buf, 'p', "b", cr, strlen(cr))
+
 #define pktbuf_write_Notice(buf, msg) \
        pktbuf_write_generic(buf, 'N', "sscss", "SNOTICE", "C00000", 'M', msg, "");
 
@@ -146,4 +152,10 @@ void pktbuf_write_ExtQuery(PktBuf *buf, const char *query, int nargs, ...);
 #define SEND_PasswordMessage(res, sk, psw) \
        SEND_wrap(512, pktbuf_write_PasswordMessage, res, sk, psw)
 
+#define SEND_SASLInitialResponseMessage(res, sk, mech, cir) \
+       SEND_wrap(512, pkgbuf_write_SASLInitialResponseMessage, res, sk, mech, cir)
+
+#define SEND_SASLResponseMessage(res, sk, cr) \
+       SEND_wrap(512, pkgbuf_write_SASLResponseMessage, res, sk, cr)
+
 void pktbuf_cleanup(void);
diff --git a/include/scram.h b/include/scram.h
new file mode 100644 (file)
index 0000000..c45ebec
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * PgBouncer - Lightweight connection pooler for PostgreSQL.
+ *
+ * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÃœ
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * SCRAM support
+ */
+
+#include <usual/crypto/sha256.h>
+
+void free_scram_state(ScramState *scram_state);
+
+typedef enum PasswordType
+{
+    PASSWORD_TYPE_PLAINTEXT = 0,
+    PASSWORD_TYPE_MD5,
+    PASSWORD_TYPE_SCRAM_SHA_256
+} PasswordType;
+
+PasswordType get_password_type(const char *shadow_pass);
+
+/*
+ * Functions for communicating as a client with the server
+ */
+
+char *build_client_first_message(ScramState *scram_state);
+char *build_client_final_message(ScramState *scram_state,
+                                const char *passwd,
+                                const char *server_nonce,
+                                const char *salt,
+                                int saltlen,
+                                int iterations);
+
+bool read_server_first_message(PgSocket *server, char *input,
+                              char **server_nonce_p, char **salt_p, int *saltlen_p, int *iterations_p);
+bool read_server_final_message(PgSocket *server, char *input, char *ServerSignature);
+
+bool verify_server_signature(ScramState *scram_state, const char *ServerSignature);
+
+
+/*
+ * Functions for communicating as a server to the client
+ */
+
+bool read_client_first_message(PgSocket *client, char *input,
+                              char **client_first_message_bare_p,
+                              char **client_nonce_p);
+
+bool read_client_final_message(PgSocket *client, const uint8_t *raw_input, char *input,
+                              const char **client_final_nonce_p,
+                              char **proof_p);
+
+char *build_server_first_message(ScramState *scram_state, const char *stored_secret);
+
+char *build_server_final_message(ScramState *scram_state);
+
+bool verify_final_nonce(const ScramState *scram_state, const char *client_final_nonce);
+
+bool verify_client_proof(ScramState *state, const char *ClientProof);
+
+bool scram_verify_plain_password(PgSocket *client,
+                                const char *username, const char *password,
+                                const char *verifier);
index e38f2159efc0d710655bd21e460a7cc15c91c8ae..dfe7a557e368279892c7d0d47a95bd418ff39689 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 bool server_proto(SBuf *sbuf, SBufEvent evtype, struct MBuf *pkt)  _MUSTCHECK;
+void kill_pool_logins(PgPool *pool, const char *msg);
 int pool_pool_mode(PgPool *pool) _MUSTCHECK;
 int database_max_connections(PgDatabase *db) _MUSTCHECK;
 int user_max_connections(PgUser *user) _MUSTCHECK;
index 10bc5448c96165fa4e1d60b4e7689720c0df8ad6..75662add09d1cc2c31eb71af84792aff3a42556e 100644 (file)
@@ -37,8 +37,6 @@ int log_socket_prefix(enum LogLevel lev, void *ctx, char *dst, unsigned int dstl
  * password tools
  */
 #define MD5_PASSWD_LEN  35
-#define isMD5(passwd) (memcmp(passwd, "md5", 3) == 0 \
-               && strlen(passwd) == MD5_PASSWD_LEN)
 void pg_md5_encrypt(const char *part1, const char *part2, size_t p2len, char *dest);
 void get_random_bytes(uint8_t *dest, int len);
 
index fe1ef63e37de6e1d116865abfaf7174369b1be91..8a3a6ebed0c01cee9c1d736be877dc5a197806d4 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "bouncer.h"
 #include "pam.h"
+#include "scram.h"
 
 #include <usual/pgutil.h>
 
@@ -46,15 +47,21 @@ static bool check_client_passwd(PgSocket *client, const char *passwd)
 
        switch (auth_type) {
        case AUTH_PLAIN:
-               if (isMD5(user->passwd)) {
+               switch (get_password_type(user->passwd)) {
+               case PASSWORD_TYPE_PLAINTEXT:
+                       return strcmp(user->passwd, passwd) == 0;
+               case PASSWORD_TYPE_MD5:
                        pg_md5_encrypt(passwd, user->name, strlen(user->name), md5);
                        return strcmp(user->passwd, md5) == 0;
-               } else
-                       return strcmp(user->passwd, passwd) == 0;
+               case PASSWORD_TYPE_SCRAM_SHA_256:
+                       return scram_verify_plain_password(client, user->name, passwd, user->passwd);
+               default:
+                       return false;
+               }
        case AUTH_MD5:
                if (strlen(passwd) != MD5_PASSWD_LEN)
                        return false;
-               if (!isMD5(user->passwd))
+               if (get_password_type(user->passwd) == PASSWORD_TYPE_PLAINTEXT)
                        pg_md5_encrypt(user->passwd, user->name, strlen(user->name), user->passwd);
                pg_md5_encrypt(user->passwd + 3, (char *)client->tmp_login_salt, 4, md5);
                return strcmp(md5, passwd) == 0;
@@ -64,25 +71,21 @@ static bool check_client_passwd(PgSocket *client, const char *passwd)
 
 static bool send_client_authreq(PgSocket *client)
 {
-       uint8_t saltlen = 0;
        int res;
        int auth_type = client->client_auth_type;
 
-       /* Always use plain text to communicate with clients during PAM authorization */
-       if (auth_type == AUTH_PAM) {
-               auth_type = AUTH_PLAIN;
-       }
-
        if (auth_type == AUTH_MD5) {
-               saltlen = 4;
+               uint8_t saltlen = 4;
                get_random_bytes((void*)client->tmp_login_salt, saltlen);
-       } else if (auth_type == AUTH_PLAIN) {
-               /* nothing to do */
+               SEND_generic(res, client, 'R', "ib", AUTH_MD5, client->tmp_login_salt, saltlen);
+       } else if (auth_type == AUTH_PLAIN || auth_type == AUTH_PAM) {
+               SEND_generic(res, client, 'R', "i", AUTH_PLAIN);
+       } else if (auth_type == AUTH_SCRAM_SHA_256) {
+               SEND_generic(res, client, 'R', "iss", AUTH_SASL, "SCRAM-SHA-256", "");
        } else {
                return false;
        }
 
-       SEND_generic(res, client, 'R', "ib", auth_type, client->tmp_login_salt, saltlen);
        if (!res)
                disconnect_client(client, false, "failed to send auth req");
        return res;
@@ -208,6 +211,12 @@ static bool finish_set_pool(PgSocket *client, bool takeover)
                                client->db->name, client->auth_user->name);
        }
 
+       if (auth == AUTH_MD5)
+       {
+               if (get_password_type(client->auth_user->passwd) == PASSWORD_TYPE_SCRAM_SHA_256)
+                       auth = AUTH_SCRAM_SHA_256;
+       }
+
        /* remember method */
        client->client_auth_type = auth;
 
@@ -219,6 +228,7 @@ static bool finish_set_pool(PgSocket *client, bool takeover)
        case AUTH_PLAIN:
        case AUTH_MD5:
        case AUTH_PAM:
+       case AUTH_SCRAM_SHA_256:
                ok = send_client_authreq(client);
                break;
        case AUTH_CERT:
@@ -504,6 +514,106 @@ static bool decide_startup_pool(PgSocket *client, PktHdr *pkt)
        return set_pool(client, dbname, username, "", false);
 }
 
+static bool scram_client_first(PgSocket *client, uint32_t datalen, const uint8_t *data)
+{
+       char *ibuf;
+       char *input;
+       int res;
+       PgUser *user = client->auth_user;
+
+       ibuf = malloc(datalen + 1);
+       if (ibuf == NULL)
+               return false;
+       memcpy(ibuf, data, datalen);
+       ibuf[datalen] = '\0';
+
+       input = ibuf;
+       slog_debug(client, "SCRAM client-first-message = \"%s\"", input);
+       if (!read_client_first_message(client, input,
+                                      &client->scram_state.client_first_message_bare,
+                                      &client->scram_state.client_nonce))
+               goto failed;
+
+       slog_debug(client, "stored secret = \"%s\"", user->passwd);
+       switch (get_password_type(user->passwd)) {
+       case PASSWORD_TYPE_MD5:
+               slog_error(client, "SCRAM authentication failed: user has MD5 secret");
+               goto failed;
+       case PASSWORD_TYPE_PLAINTEXT:
+       case PASSWORD_TYPE_SCRAM_SHA_256:
+               break;
+       }
+
+       if (!build_server_first_message(&client->scram_state, user->passwd))
+               goto failed;
+       slog_debug(client, "SCRAM server-first-message = \"%s\"", client->scram_state.server_first_message);
+
+       SEND_generic(res, client, 'R', "ib",
+                    AUTH_SASL_CONT,
+                    client->scram_state.server_first_message,
+                    strlen(client->scram_state.server_first_message));
+
+       free(ibuf);
+       return res;
+failed:
+       free(ibuf);
+       return false;
+}
+
+static bool scram_client_final(PgSocket *client, uint32_t datalen, const uint8_t *data)
+{
+       char *ibuf;
+       char *input;
+       const char *client_final_nonce = NULL;
+       char *proof = NULL;
+       char *server_final_message;
+       int res;
+
+       ibuf = malloc(datalen + 1);
+       if (ibuf == NULL)
+               return false;
+       memcpy(ibuf, data, datalen);
+       ibuf[datalen] = '\0';
+
+       input = ibuf;
+       slog_debug(client, "SCRAM client-final-message = \"%s\"", input);
+       if (!read_client_final_message(client, data, input,
+                                      &client_final_nonce,
+                                      &proof))
+               goto failed;
+       slog_debug(client, "SCRAM client-final-message-without-proof = \"%s\"",
+                  client->scram_state.client_final_message_without_proof);
+
+       if (!verify_final_nonce(&client->scram_state, client_final_nonce)) {
+               slog_error(client, "invalid SCRAM response (nonce does not match)");
+               goto failed;
+       }
+
+       if (!verify_client_proof(&client->scram_state, proof)) {
+               slog_error(client, "password authentication failed");
+               goto failed;
+       }
+
+       server_final_message = build_server_final_message(&client->scram_state);
+       if (!server_final_message)
+               goto failed;
+       slog_debug(client, "SCRAM server-final-message = \"%s\"", server_final_message);
+
+       SEND_generic(res, client, 'R', "ib",
+                    AUTH_SASL_FIN,
+                    server_final_message,
+                    strlen(server_final_message));
+
+       free(server_final_message);
+       free(proof);
+       free(ibuf);
+       return res;
+failed:
+       free(proof);
+       free(ibuf);
+       return false;
+}
+
 /* decide on packets of client in login phase */
 static bool handle_client_startup(PgSocket *client, PktHdr *pkt)
 {
@@ -590,31 +700,71 @@ static bool handle_client_startup(PgSocket *client, PktHdr *pkt)
                }
 
                break;
-       case 'p':               /* PasswordMessage */
+       case 'p':               /* PasswordMessage, SASLInitialResponse, or SASLResponse */
                /* too early */
                if (!client->auth_user) {
                        disconnect_client(client, true, "client password pkt before startup packet");
                        return false;
                }
 
-               ok = mbuf_get_string(&pkt->data, &passwd);
+               if (client->client_auth_type == AUTH_SCRAM_SHA_256) {
+                       const char *mech;
+                       uint32_t length;
+                       const uint8_t *data;
 
-               if (ok) {
-                       if (client->client_auth_type == AUTH_PAM) {
-                               if (!sbuf_pause(&client->sbuf)) {
-                                       disconnect_client(client, true, "pause failed");
+                       if (!client->scram_state.server_nonce) {
+                               /* process as SASLInitialResponse */
+                               if (!mbuf_get_string(&pkt->data, &mech))
+                                       return false;
+                               slog_debug(client, "C: selected SASL mechanism: %s", mech);
+                               if (strcmp(mech, "SCRAM-SHA-256") != 0) {
+                                       disconnect_client(client, true, "client selected an invalid SASL authentication mechanism");
+                                       return false;
+                               }
+                               if (!mbuf_get_uint32be(&pkt->data, &length))
+                                       return false;
+                               if (!mbuf_get_bytes(&pkt->data, length, &data))
+                                       return false;
+                               if (!scram_client_first(client, length, data)) {
+                                       disconnect_client(client, true, "SASL authentication failed");
+                                       return false;
+                               }
+                       } else {
+                               /* process as SASLResponse */
+                               length = mbuf_avail_for_read(&pkt->data);
+                               if (!mbuf_get_bytes(&pkt->data, length, &data))
+                                       return false;
+                               if (scram_client_final(client, length, data)) {
+                                       free_scram_state(&client->scram_state);
+                                       if (!finish_client_login(client))
+                                               return false;
+                               }
+                               else {
+                                       disconnect_client(client, true, "SASL authentication failed");
                                        return false;
                                }
-                               pam_auth_begin(client, passwd);
-                               return false;
                        }
+               } else {
+                       /* process as PasswordMessage */
+                       ok = mbuf_get_string(&pkt->data, &passwd);
+
+                       if (ok) {
+                               if (client->client_auth_type == AUTH_PAM) {
+                                       if (!sbuf_pause(&client->sbuf)) {
+                                               disconnect_client(client, true, "pause failed");
+                                               return false;
+                                       }
+                                       pam_auth_begin(client, passwd);
+                                       return false;
+                               }
 
-                       if (check_client_passwd(client, passwd)) {
-                               if (!finish_client_login(client))
+                               if (check_client_passwd(client, passwd)) {
+                                       if (!finish_client_login(client))
+                                               return false;
+                               } else {
+                                       disconnect_client(client, true, "password authentication failed");
                                        return false;
-                       } else {
-                               disconnect_client(client, true, "auth failed");
-                               return false;
+                               }
                        }
                }
                break;
diff --git a/src/common/base64.c b/src/common/base64.c
new file mode 100644 (file)
index 0000000..e989434
--- /dev/null
@@ -0,0 +1,201 @@
+/*-------------------------------------------------------------------------
+ *
+ * base64.c
+ *       Encoding and decoding routines for base64 without whitespace.
+ *
+ * Copyright (c) 2001-2018, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *       src/common/base64.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+//#ifndef FRONTEND
+//#include "postgres.h"
+//#else
+//#include "postgres_fe.h"
+//#endif
+#include "system.h"
+#include "common/postgres_compat.h"
+
+#include "common/base64.h"
+
+/*
+ * BASE64
+ */
+
+static const char _base64[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static const int8 b64lookup[128] = {
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+       -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+       52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+       -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+       15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+       -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+       41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
+};
+
+/*
+ * pg_b64_encode
+ *
+ * Encode into base64 the given string.  Returns the length of the encoded
+ * string.
+ */
+int
+pg_b64_encode(const char *src, int len, char *dst)
+{
+       char       *p;
+       const char *s,
+                          *end = src + len;
+       int                     pos = 2;
+       uint32          buf = 0;
+
+       s = src;
+       p = dst;
+
+       while (s < end)
+       {
+               buf |= (unsigned char) *s << (pos << 3);
+               pos--;
+               s++;
+
+               /* write it out */
+               if (pos < 0)
+               {
+                       *p++ = _base64[(buf >> 18) & 0x3f];
+                       *p++ = _base64[(buf >> 12) & 0x3f];
+                       *p++ = _base64[(buf >> 6) & 0x3f];
+                       *p++ = _base64[buf & 0x3f];
+
+                       pos = 2;
+                       buf = 0;
+               }
+       }
+       if (pos != 2)
+       {
+               *p++ = _base64[(buf >> 18) & 0x3f];
+               *p++ = _base64[(buf >> 12) & 0x3f];
+               *p++ = (pos == 0) ? _base64[(buf >> 6) & 0x3f] : '=';
+               *p++ = '=';
+       }
+
+       return p - dst;
+}
+
+/*
+ * pg_b64_decode
+ *
+ * Decode the given base64 string.  Returns the length of the decoded
+ * string on success, and -1 in the event of an error.
+ */
+int
+pg_b64_decode(const char *src, int len, char *dst)
+{
+       const char *srcend = src + len,
+                          *s = src;
+       char       *p = dst;
+       char            c;
+       int                     b = 0;
+       uint32          buf = 0;
+       int                     pos = 0,
+                               end = 0;
+
+       while (s < srcend)
+       {
+               c = *s++;
+
+               /* Leave if a whitespace is found */
+               if (c == ' ' || c == '\t' || c == '\n' || c == '\r')
+                       return -1;
+
+               if (c == '=')
+               {
+                       /* end sequence */
+                       if (!end)
+                       {
+                               if (pos == 2)
+                                       end = 1;
+                               else if (pos == 3)
+                                       end = 2;
+                               else
+                               {
+                                       /*
+                                        * Unexpected "=" character found while decoding base64
+                                        * sequence.
+                                        */
+                                       return -1;
+                               }
+                       }
+                       b = 0;
+               }
+               else
+               {
+                       b = -1;
+                       if (c > 0 && c < 127)
+                               b = b64lookup[(unsigned char) c];
+                       if (b < 0)
+                       {
+                               /* invalid symbol found */
+                               return -1;
+                       }
+               }
+               /* add it to buffer */
+               buf = (buf << 6) + b;
+               pos++;
+               if (pos == 4)
+               {
+                       *p++ = (buf >> 16) & 255;
+                       if (end == 0 || end > 1)
+                               *p++ = (buf >> 8) & 255;
+                       if (end == 0 || end > 2)
+                               *p++ = buf & 255;
+                       buf = 0;
+                       pos = 0;
+               }
+       }
+
+       if (pos != 0)
+       {
+               /*
+                * base64 end sequence is invalid.  Input data is missing padding, is
+                * truncated or is otherwise corrupted.
+                */
+               return -1;
+       }
+
+       return p - dst;
+}
+
+/*
+ * pg_b64_enc_len
+ *
+ * Returns to caller the length of the string if it were encoded with
+ * base64 based on the length provided by caller.  This is useful to
+ * estimate how large a buffer allocation needs to be done before doing
+ * the actual encoding.
+ */
+int
+pg_b64_enc_len(int srclen)
+{
+       /* 3 bytes will be converted to 4 */
+       return (srclen + 2) * 4 / 3;
+}
+
+/*
+ * pg_b64_dec_len
+ *
+ * Returns to caller the length of the string if it were to be decoded
+ * with base64, based on the length given by caller.  This is useful to
+ * estimate how large a buffer allocation needs to be done before doing
+ * the actual decoding.
+ */
+int
+pg_b64_dec_len(int srclen)
+{
+       return (srclen * 3) >> 2;
+}
diff --git a/src/common/saslprep.c b/src/common/saslprep.c
new file mode 100644 (file)
index 0000000..33b036c
--- /dev/null
@@ -0,0 +1,1286 @@
+/*-------------------------------------------------------------------------
+ * saslprep.c
+ *             SASLprep normalization, for SCRAM authentication
+ *
+ * The SASLprep algorithm is used to process a user-supplied password into
+ * canonical form.  For more details, see:
+ *
+ * [RFC3454] Preparation of Internationalized Strings ("stringprep"),
+ *       http://www.ietf.org/rfc/rfc3454.txt
+ *
+ * [RFC4013] SASLprep: Stringprep Profile for User Names and Passwords
+ *       http://www.ietf.org/rfc/rfc4013.txt
+ *
+ *
+ * Portions Copyright (c) 2017-2018, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       src/common/saslprep.c
+ *
+ *-------------------------------------------------------------------------
+ */
+//#ifndef FRONTEND
+//#include "postgres.h"
+//#else
+//#include "postgres_fe.h"
+//#endif
+#include "system.h"
+#include "common/postgres_compat.h"
+
+#include "common/saslprep.h"
+#include "common/unicode_norm.h"
+
+/*
+ * Note: The functions in this file depend on functions from
+ * src/backend/utils/mb/wchar.c, so in order to use this in frontend
+ * code, you will need to link that in, too.
+ */
+#include "common/pg_wchar.h"
+
+/*
+ * Limit on how large password's we will try to process.  A password
+ * larger than this will be treated the same as out-of-memory.
+ */
+#define MAX_PASSWORD_LENGTH            1024
+
+/*
+ * In backend, we will use palloc/pfree.  In frontend, use malloc, and
+ * return SASLPREP_OOM on out-of-memory.
+ */
+#ifndef FRONTEND
+#define STRDUP(s) pstrdup(s)
+#define ALLOC(size) palloc(size)
+#define FREE(size) pfree(size)
+#else
+#define STRDUP(s) strdup(s)
+#define ALLOC(size) malloc(size)
+#define FREE(size) free(size)
+#endif
+
+/* Prototypes for local functions */
+static int     codepoint_range_cmp(const void *a, const void *b);
+static bool is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize);
+static int     pg_utf8_string_len(const char *source);
+static bool pg_is_ascii_string(const char *p);
+
+/*
+ * Stringprep Mapping Tables.
+ *
+ * The stringprep specification includes a number of tables of Unicode
+ * codepoints, used in different parts of the algorithm.  They are below,
+ * as arrays of codepoint ranges.  Each range is a pair of codepoints,
+ * for the first and last codepoint included the range (inclusive!).
+ */
+
+/*
+ * C.1.2 Non-ASCII space characters
+ *
+ * These are all mapped to the ASCII space character (U+00A0).
+ */
+static const pg_wchar non_ascii_space_ranges[] =
+{
+       0x00A0, 0x00A0,
+       0x1680, 0x1680,
+       0x2000, 0x200B,
+       0x202F, 0x202F,
+       0x205F, 0x205F,
+       0x3000, 0x3000
+};
+
+/*
+ * B.1 Commonly mapped to nothing
+ *
+ * If any of these appear in the input, they are removed.
+ */
+static const pg_wchar commonly_mapped_to_nothing_ranges[] =
+{
+       0x00AD, 0x00AD,
+       0x034F, 0x034F,
+       0x1806, 0x1806,
+       0x180B, 0x180D,
+       0x200B, 0x200D,
+       0x2060, 0x2060,
+       0xFE00, 0xFE0F,
+       0xFEFF, 0xFEFF
+};
+
+/*
+ * prohibited_output_ranges is a union of all the characters from
+ * the following tables:
+ *
+ * C.1.2 Non-ASCII space characters
+ * C.2.1 ASCII control characters
+ * C.2.2 Non-ASCII control characters
+ * C.3 Private Use characters
+ * C.4 Non-character code points
+ * C.5 Surrogate code points
+ * C.6 Inappropriate for plain text characters
+ * C.7 Inappropriate for canonical representation characters
+ * C.7 Change display properties or deprecated characters
+ * C.8 Tagging characters
+ *
+ * These are the tables that are listed as "prohibited output"
+ * characters in the SASLprep profile.
+ *
+ * The comment after each code range indicates which source table
+ * the code came from.  Note that there is some overlap in the source
+ * tables, so one code might originate from multiple source tables.
+ * Adjacent ranges have also been merged together, to save space.
+ */
+static const pg_wchar prohibited_output_ranges[] =
+{
+       0x0000, 0x001F,                         /* C.2.1 */
+       0x007F, 0x00A0,                         /* C.1.2, C.2.1, C.2.2 */
+       0x0340, 0x0341,                         /* C.8 */
+       0x06DD, 0x06DD,                         /* C.2.2 */
+       0x070F, 0x070F,                         /* C.2.2 */
+       0x1680, 0x1680,                         /* C.1.2 */
+       0x180E, 0x180E,                         /* C.2.2 */
+       0x2000, 0x200F,                         /* C.1.2, C.2.2, C.8 */
+       0x2028, 0x202F,                         /* C.1.2, C.2.2, C.8 */
+       0x205F, 0x2063,                         /* C.1.2, C.2.2 */
+       0x206A, 0x206F,                         /* C.2.2, C.8 */
+       0x2FF0, 0x2FFB,                         /* C.7 */
+       0x3000, 0x3000,                         /* C.1.2 */
+       0xD800, 0xF8FF,                         /* C.3, C.5 */
+       0xFDD0, 0xFDEF,                         /* C.4 */
+       0xFEFF, 0xFEFF,                         /* C.2.2 */
+       0xFFF9, 0xFFFF,                         /* C.2.2, C.4, C.6 */
+       0x1D173, 0x1D17A,                       /* C.2.2 */
+       0x1FFFE, 0x1FFFF,                       /* C.4 */
+       0x2FFFE, 0x2FFFF,                       /* C.4 */
+       0x3FFFE, 0x3FFFF,                       /* C.4 */
+       0x4FFFE, 0x4FFFF,                       /* C.4 */
+       0x5FFFE, 0x5FFFF,                       /* C.4 */
+       0x6FFFE, 0x6FFFF,                       /* C.4 */
+       0x7FFFE, 0x7FFFF,                       /* C.4 */
+       0x8FFFE, 0x8FFFF,                       /* C.4 */
+       0x9FFFE, 0x9FFFF,                       /* C.4 */
+       0xAFFFE, 0xAFFFF,                       /* C.4 */
+       0xBFFFE, 0xBFFFF,                       /* C.4 */
+       0xCFFFE, 0xCFFFF,                       /* C.4 */
+       0xDFFFE, 0xDFFFF,                       /* C.4 */
+       0xE0001, 0xE0001,                       /* C.9 */
+       0xE0020, 0xE007F,                       /* C.9 */
+       0xEFFFE, 0xEFFFF,                       /* C.4 */
+       0xF0000, 0xFFFFF,                       /* C.3, C.4 */
+       0x100000, 0x10FFFF                      /* C.3, C.4 */
+};
+
+/* A.1 Unassigned code points in Unicode 3.2 */
+static const pg_wchar unassigned_codepoint_ranges[] =
+{
+       0x0221, 0x0221,
+       0x0234, 0x024F,
+       0x02AE, 0x02AF,
+       0x02EF, 0x02FF,
+       0x0350, 0x035F,
+       0x0370, 0x0373,
+       0x0376, 0x0379,
+       0x037B, 0x037D,
+       0x037F, 0x0383,
+       0x038B, 0x038B,
+       0x038D, 0x038D,
+       0x03A2, 0x03A2,
+       0x03CF, 0x03CF,
+       0x03F7, 0x03FF,
+       0x0487, 0x0487,
+       0x04CF, 0x04CF,
+       0x04F6, 0x04F7,
+       0x04FA, 0x04FF,
+       0x0510, 0x0530,
+       0x0557, 0x0558,
+       0x0560, 0x0560,
+       0x0588, 0x0588,
+       0x058B, 0x0590,
+       0x05A2, 0x05A2,
+       0x05BA, 0x05BA,
+       0x05C5, 0x05CF,
+       0x05EB, 0x05EF,
+       0x05F5, 0x060B,
+       0x060D, 0x061A,
+       0x061C, 0x061E,
+       0x0620, 0x0620,
+       0x063B, 0x063F,
+       0x0656, 0x065F,
+       0x06EE, 0x06EF,
+       0x06FF, 0x06FF,
+       0x070E, 0x070E,
+       0x072D, 0x072F,
+       0x074B, 0x077F,
+       0x07B2, 0x0900,
+       0x0904, 0x0904,
+       0x093A, 0x093B,
+       0x094E, 0x094F,
+       0x0955, 0x0957,
+       0x0971, 0x0980,
+       0x0984, 0x0984,
+       0x098D, 0x098E,
+       0x0991, 0x0992,
+       0x09A9, 0x09A9,
+       0x09B1, 0x09B1,
+       0x09B3, 0x09B5,
+       0x09BA, 0x09BB,
+       0x09BD, 0x09BD,
+       0x09C5, 0x09C6,
+       0x09C9, 0x09CA,
+       0x09CE, 0x09D6,
+       0x09D8, 0x09DB,
+       0x09DE, 0x09DE,
+       0x09E4, 0x09E5,
+       0x09FB, 0x0A01,
+       0x0A03, 0x0A04,
+       0x0A0B, 0x0A0E,
+       0x0A11, 0x0A12,
+       0x0A29, 0x0A29,
+       0x0A31, 0x0A31,
+       0x0A34, 0x0A34,
+       0x0A37, 0x0A37,
+       0x0A3A, 0x0A3B,
+       0x0A3D, 0x0A3D,
+       0x0A43, 0x0A46,
+       0x0A49, 0x0A4A,
+       0x0A4E, 0x0A58,
+       0x0A5D, 0x0A5D,
+       0x0A5F, 0x0A65,
+       0x0A75, 0x0A80,
+       0x0A84, 0x0A84,
+       0x0A8C, 0x0A8C,
+       0x0A8E, 0x0A8E,
+       0x0A92, 0x0A92,
+       0x0AA9, 0x0AA9,
+       0x0AB1, 0x0AB1,
+       0x0AB4, 0x0AB4,
+       0x0ABA, 0x0ABB,
+       0x0AC6, 0x0AC6,
+       0x0ACA, 0x0ACA,
+       0x0ACE, 0x0ACF,
+       0x0AD1, 0x0ADF,
+       0x0AE1, 0x0AE5,
+       0x0AF0, 0x0B00,
+       0x0B04, 0x0B04,
+       0x0B0D, 0x0B0E,
+       0x0B11, 0x0B12,
+       0x0B29, 0x0B29,
+       0x0B31, 0x0B31,
+       0x0B34, 0x0B35,
+       0x0B3A, 0x0B3B,
+       0x0B44, 0x0B46,
+       0x0B49, 0x0B4A,
+       0x0B4E, 0x0B55,
+       0x0B58, 0x0B5B,
+       0x0B5E, 0x0B5E,
+       0x0B62, 0x0B65,
+       0x0B71, 0x0B81,
+       0x0B84, 0x0B84,
+       0x0B8B, 0x0B8D,
+       0x0B91, 0x0B91,
+       0x0B96, 0x0B98,
+       0x0B9B, 0x0B9B,
+       0x0B9D, 0x0B9D,
+       0x0BA0, 0x0BA2,
+       0x0BA5, 0x0BA7,
+       0x0BAB, 0x0BAD,
+       0x0BB6, 0x0BB6,
+       0x0BBA, 0x0BBD,
+       0x0BC3, 0x0BC5,
+       0x0BC9, 0x0BC9,
+       0x0BCE, 0x0BD6,
+       0x0BD8, 0x0BE6,
+       0x0BF3, 0x0C00,
+       0x0C04, 0x0C04,
+       0x0C0D, 0x0C0D,
+       0x0C11, 0x0C11,
+       0x0C29, 0x0C29,
+       0x0C34, 0x0C34,
+       0x0C3A, 0x0C3D,
+       0x0C45, 0x0C45,
+       0x0C49, 0x0C49,
+       0x0C4E, 0x0C54,
+       0x0C57, 0x0C5F,
+       0x0C62, 0x0C65,
+       0x0C70, 0x0C81,
+       0x0C84, 0x0C84,
+       0x0C8D, 0x0C8D,
+       0x0C91, 0x0C91,
+       0x0CA9, 0x0CA9,
+       0x0CB4, 0x0CB4,
+       0x0CBA, 0x0CBD,
+       0x0CC5, 0x0CC5,
+       0x0CC9, 0x0CC9,
+       0x0CCE, 0x0CD4,
+       0x0CD7, 0x0CDD,
+       0x0CDF, 0x0CDF,
+       0x0CE2, 0x0CE5,
+       0x0CF0, 0x0D01,
+       0x0D04, 0x0D04,
+       0x0D0D, 0x0D0D,
+       0x0D11, 0x0D11,
+       0x0D29, 0x0D29,
+       0x0D3A, 0x0D3D,
+       0x0D44, 0x0D45,
+       0x0D49, 0x0D49,
+       0x0D4E, 0x0D56,
+       0x0D58, 0x0D5F,
+       0x0D62, 0x0D65,
+       0x0D70, 0x0D81,
+       0x0D84, 0x0D84,
+       0x0D97, 0x0D99,
+       0x0DB2, 0x0DB2,
+       0x0DBC, 0x0DBC,
+       0x0DBE, 0x0DBF,
+       0x0DC7, 0x0DC9,
+       0x0DCB, 0x0DCE,
+       0x0DD5, 0x0DD5,
+       0x0DD7, 0x0DD7,
+       0x0DE0, 0x0DF1,
+       0x0DF5, 0x0E00,
+       0x0E3B, 0x0E3E,
+       0x0E5C, 0x0E80,
+       0x0E83, 0x0E83,
+       0x0E85, 0x0E86,
+       0x0E89, 0x0E89,
+       0x0E8B, 0x0E8C,
+       0x0E8E, 0x0E93,
+       0x0E98, 0x0E98,
+       0x0EA0, 0x0EA0,
+       0x0EA4, 0x0EA4,
+       0x0EA6, 0x0EA6,
+       0x0EA8, 0x0EA9,
+       0x0EAC, 0x0EAC,
+       0x0EBA, 0x0EBA,
+       0x0EBE, 0x0EBF,
+       0x0EC5, 0x0EC5,
+       0x0EC7, 0x0EC7,
+       0x0ECE, 0x0ECF,
+       0x0EDA, 0x0EDB,
+       0x0EDE, 0x0EFF,
+       0x0F48, 0x0F48,
+       0x0F6B, 0x0F70,
+       0x0F8C, 0x0F8F,
+       0x0F98, 0x0F98,
+       0x0FBD, 0x0FBD,
+       0x0FCD, 0x0FCE,
+       0x0FD0, 0x0FFF,
+       0x1022, 0x1022,
+       0x1028, 0x1028,
+       0x102B, 0x102B,
+       0x1033, 0x1035,
+       0x103A, 0x103F,
+       0x105A, 0x109F,
+       0x10C6, 0x10CF,
+       0x10F9, 0x10FA,
+       0x10FC, 0x10FF,
+       0x115A, 0x115E,
+       0x11A3, 0x11A7,
+       0x11FA, 0x11FF,
+       0x1207, 0x1207,
+       0x1247, 0x1247,
+       0x1249, 0x1249,
+       0x124E, 0x124F,
+       0x1257, 0x1257,
+       0x1259, 0x1259,
+       0x125E, 0x125F,
+       0x1287, 0x1287,
+       0x1289, 0x1289,
+       0x128E, 0x128F,
+       0x12AF, 0x12AF,
+       0x12B1, 0x12B1,
+       0x12B6, 0x12B7,
+       0x12BF, 0x12BF,
+       0x12C1, 0x12C1,
+       0x12C6, 0x12C7,
+       0x12CF, 0x12CF,
+       0x12D7, 0x12D7,
+       0x12EF, 0x12EF,
+       0x130F, 0x130F,
+       0x1311, 0x1311,
+       0x1316, 0x1317,
+       0x131F, 0x131F,
+       0x1347, 0x1347,
+       0x135B, 0x1360,
+       0x137D, 0x139F,
+       0x13F5, 0x1400,
+       0x1677, 0x167F,
+       0x169D, 0x169F,
+       0x16F1, 0x16FF,
+       0x170D, 0x170D,
+       0x1715, 0x171F,
+       0x1737, 0x173F,
+       0x1754, 0x175F,
+       0x176D, 0x176D,
+       0x1771, 0x1771,
+       0x1774, 0x177F,
+       0x17DD, 0x17DF,
+       0x17EA, 0x17FF,
+       0x180F, 0x180F,
+       0x181A, 0x181F,
+       0x1878, 0x187F,
+       0x18AA, 0x1DFF,
+       0x1E9C, 0x1E9F,
+       0x1EFA, 0x1EFF,
+       0x1F16, 0x1F17,
+       0x1F1E, 0x1F1F,
+       0x1F46, 0x1F47,
+       0x1F4E, 0x1F4F,
+       0x1F58, 0x1F58,
+       0x1F5A, 0x1F5A,
+       0x1F5C, 0x1F5C,
+       0x1F5E, 0x1F5E,
+       0x1F7E, 0x1F7F,
+       0x1FB5, 0x1FB5,
+       0x1FC5, 0x1FC5,
+       0x1FD4, 0x1FD5,
+       0x1FDC, 0x1FDC,
+       0x1FF0, 0x1FF1,
+       0x1FF5, 0x1FF5,
+       0x1FFF, 0x1FFF,
+       0x2053, 0x2056,
+       0x2058, 0x205E,
+       0x2064, 0x2069,
+       0x2072, 0x2073,
+       0x208F, 0x209F,
+       0x20B2, 0x20CF,
+       0x20EB, 0x20FF,
+       0x213B, 0x213C,
+       0x214C, 0x2152,
+       0x2184, 0x218F,
+       0x23CF, 0x23FF,
+       0x2427, 0x243F,
+       0x244B, 0x245F,
+       0x24FF, 0x24FF,
+       0x2614, 0x2615,
+       0x2618, 0x2618,
+       0x267E, 0x267F,
+       0x268A, 0x2700,
+       0x2705, 0x2705,
+       0x270A, 0x270B,
+       0x2728, 0x2728,
+       0x274C, 0x274C,
+       0x274E, 0x274E,
+       0x2753, 0x2755,
+       0x2757, 0x2757,
+       0x275F, 0x2760,
+       0x2795, 0x2797,
+       0x27B0, 0x27B0,
+       0x27BF, 0x27CF,
+       0x27EC, 0x27EF,
+       0x2B00, 0x2E7F,
+       0x2E9A, 0x2E9A,
+       0x2EF4, 0x2EFF,
+       0x2FD6, 0x2FEF,
+       0x2FFC, 0x2FFF,
+       0x3040, 0x3040,
+       0x3097, 0x3098,
+       0x3100, 0x3104,
+       0x312D, 0x3130,
+       0x318F, 0x318F,
+       0x31B8, 0x31EF,
+       0x321D, 0x321F,
+       0x3244, 0x3250,
+       0x327C, 0x327E,
+       0x32CC, 0x32CF,
+       0x32FF, 0x32FF,
+       0x3377, 0x337A,
+       0x33DE, 0x33DF,
+       0x33FF, 0x33FF,
+       0x4DB6, 0x4DFF,
+       0x9FA6, 0x9FFF,
+       0xA48D, 0xA48F,
+       0xA4C7, 0xABFF,
+       0xD7A4, 0xD7FF,
+       0xFA2E, 0xFA2F,
+       0xFA6B, 0xFAFF,
+       0xFB07, 0xFB12,
+       0xFB18, 0xFB1C,
+       0xFB37, 0xFB37,
+       0xFB3D, 0xFB3D,
+       0xFB3F, 0xFB3F,
+       0xFB42, 0xFB42,
+       0xFB45, 0xFB45,
+       0xFBB2, 0xFBD2,
+       0xFD40, 0xFD4F,
+       0xFD90, 0xFD91,
+       0xFDC8, 0xFDCF,
+       0xFDFD, 0xFDFF,
+       0xFE10, 0xFE1F,
+       0xFE24, 0xFE2F,
+       0xFE47, 0xFE48,
+       0xFE53, 0xFE53,
+       0xFE67, 0xFE67,
+       0xFE6C, 0xFE6F,
+       0xFE75, 0xFE75,
+       0xFEFD, 0xFEFE,
+       0xFF00, 0xFF00,
+       0xFFBF, 0xFFC1,
+       0xFFC8, 0xFFC9,
+       0xFFD0, 0xFFD1,
+       0xFFD8, 0xFFD9,
+       0xFFDD, 0xFFDF,
+       0xFFE7, 0xFFE7,
+       0xFFEF, 0xFFF8,
+       0x10000, 0x102FF,
+       0x1031F, 0x1031F,
+       0x10324, 0x1032F,
+       0x1034B, 0x103FF,
+       0x10426, 0x10427,
+       0x1044E, 0x1CFFF,
+       0x1D0F6, 0x1D0FF,
+       0x1D127, 0x1D129,
+       0x1D1DE, 0x1D3FF,
+       0x1D455, 0x1D455,
+       0x1D49D, 0x1D49D,
+       0x1D4A0, 0x1D4A1,
+       0x1D4A3, 0x1D4A4,
+       0x1D4A7, 0x1D4A8,
+       0x1D4AD, 0x1D4AD,
+       0x1D4BA, 0x1D4BA,
+       0x1D4BC, 0x1D4BC,
+       0x1D4C1, 0x1D4C1,
+       0x1D4C4, 0x1D4C4,
+       0x1D506, 0x1D506,
+       0x1D50B, 0x1D50C,
+       0x1D515, 0x1D515,
+       0x1D51D, 0x1D51D,
+       0x1D53A, 0x1D53A,
+       0x1D53F, 0x1D53F,
+       0x1D545, 0x1D545,
+       0x1D547, 0x1D549,
+       0x1D551, 0x1D551,
+       0x1D6A4, 0x1D6A7,
+       0x1D7CA, 0x1D7CD,
+       0x1D800, 0x1FFFD,
+       0x2A6D7, 0x2F7FF,
+       0x2FA1E, 0x2FFFD,
+       0x30000, 0x3FFFD,
+       0x40000, 0x4FFFD,
+       0x50000, 0x5FFFD,
+       0x60000, 0x6FFFD,
+       0x70000, 0x7FFFD,
+       0x80000, 0x8FFFD,
+       0x90000, 0x9FFFD,
+       0xA0000, 0xAFFFD,
+       0xB0000, 0xBFFFD,
+       0xC0000, 0xCFFFD,
+       0xD0000, 0xDFFFD,
+       0xE0000, 0xE0000,
+       0xE0002, 0xE001F,
+       0xE0080, 0xEFFFD
+};
+
+/* D.1 Characters with bidirectional property "R" or "AL" */
+static const pg_wchar RandALCat_codepoint_ranges[] =
+{
+       0x05BE, 0x05BE,
+       0x05C0, 0x05C0,
+       0x05C3, 0x05C3,
+       0x05D0, 0x05EA,
+       0x05F0, 0x05F4,
+       0x061B, 0x061B,
+       0x061F, 0x061F,
+       0x0621, 0x063A,
+       0x0640, 0x064A,
+       0x066D, 0x066F,
+       0x0671, 0x06D5,
+       0x06DD, 0x06DD,
+       0x06E5, 0x06E6,
+       0x06FA, 0x06FE,
+       0x0700, 0x070D,
+       0x0710, 0x0710,
+       0x0712, 0x072C,
+       0x0780, 0x07A5,
+       0x07B1, 0x07B1,
+       0x200F, 0x200F,
+       0xFB1D, 0xFB1D,
+       0xFB1F, 0xFB28,
+       0xFB2A, 0xFB36,
+       0xFB38, 0xFB3C,
+       0xFB3E, 0xFB3E,
+       0xFB40, 0xFB41,
+       0xFB43, 0xFB44,
+       0xFB46, 0xFBB1,
+       0xFBD3, 0xFD3D,
+       0xFD50, 0xFD8F,
+       0xFD92, 0xFDC7,
+       0xFDF0, 0xFDFC,
+       0xFE70, 0xFE74,
+       0xFE76, 0xFEFC
+};
+
+/* D.2 Characters with bidirectional property "L" */
+static const pg_wchar LCat_codepoint_ranges[] =
+{
+       0x0041, 0x005A,
+       0x0061, 0x007A,
+       0x00AA, 0x00AA,
+       0x00B5, 0x00B5,
+       0x00BA, 0x00BA,
+       0x00C0, 0x00D6,
+       0x00D8, 0x00F6,
+       0x00F8, 0x0220,
+       0x0222, 0x0233,
+       0x0250, 0x02AD,
+       0x02B0, 0x02B8,
+       0x02BB, 0x02C1,
+       0x02D0, 0x02D1,
+       0x02E0, 0x02E4,
+       0x02EE, 0x02EE,
+       0x037A, 0x037A,
+       0x0386, 0x0386,
+       0x0388, 0x038A,
+       0x038C, 0x038C,
+       0x038E, 0x03A1,
+       0x03A3, 0x03CE,
+       0x03D0, 0x03F5,
+       0x0400, 0x0482,
+       0x048A, 0x04CE,
+       0x04D0, 0x04F5,
+       0x04F8, 0x04F9,
+       0x0500, 0x050F,
+       0x0531, 0x0556,
+       0x0559, 0x055F,
+       0x0561, 0x0587,
+       0x0589, 0x0589,
+       0x0903, 0x0903,
+       0x0905, 0x0939,
+       0x093D, 0x0940,
+       0x0949, 0x094C,
+       0x0950, 0x0950,
+       0x0958, 0x0961,
+       0x0964, 0x0970,
+       0x0982, 0x0983,
+       0x0985, 0x098C,
+       0x098F, 0x0990,
+       0x0993, 0x09A8,
+       0x09AA, 0x09B0,
+       0x09B2, 0x09B2,
+       0x09B6, 0x09B9,
+       0x09BE, 0x09C0,
+       0x09C7, 0x09C8,
+       0x09CB, 0x09CC,
+       0x09D7, 0x09D7,
+       0x09DC, 0x09DD,
+       0x09DF, 0x09E1,
+       0x09E6, 0x09F1,
+       0x09F4, 0x09FA,
+       0x0A05, 0x0A0A,
+       0x0A0F, 0x0A10,
+       0x0A13, 0x0A28,
+       0x0A2A, 0x0A30,
+       0x0A32, 0x0A33,
+       0x0A35, 0x0A36,
+       0x0A38, 0x0A39,
+       0x0A3E, 0x0A40,
+       0x0A59, 0x0A5C,
+       0x0A5E, 0x0A5E,
+       0x0A66, 0x0A6F,
+       0x0A72, 0x0A74,
+       0x0A83, 0x0A83,
+       0x0A85, 0x0A8B,
+       0x0A8D, 0x0A8D,
+       0x0A8F, 0x0A91,
+       0x0A93, 0x0AA8,
+       0x0AAA, 0x0AB0,
+       0x0AB2, 0x0AB3,
+       0x0AB5, 0x0AB9,
+       0x0ABD, 0x0AC0,
+       0x0AC9, 0x0AC9,
+       0x0ACB, 0x0ACC,
+       0x0AD0, 0x0AD0,
+       0x0AE0, 0x0AE0,
+       0x0AE6, 0x0AEF,
+       0x0B02, 0x0B03,
+       0x0B05, 0x0B0C,
+       0x0B0F, 0x0B10,
+       0x0B13, 0x0B28,
+       0x0B2A, 0x0B30,
+       0x0B32, 0x0B33,
+       0x0B36, 0x0B39,
+       0x0B3D, 0x0B3E,
+       0x0B40, 0x0B40,
+       0x0B47, 0x0B48,
+       0x0B4B, 0x0B4C,
+       0x0B57, 0x0B57,
+       0x0B5C, 0x0B5D,
+       0x0B5F, 0x0B61,
+       0x0B66, 0x0B70,
+       0x0B83, 0x0B83,
+       0x0B85, 0x0B8A,
+       0x0B8E, 0x0B90,
+       0x0B92, 0x0B95,
+       0x0B99, 0x0B9A,
+       0x0B9C, 0x0B9C,
+       0x0B9E, 0x0B9F,
+       0x0BA3, 0x0BA4,
+       0x0BA8, 0x0BAA,
+       0x0BAE, 0x0BB5,
+       0x0BB7, 0x0BB9,
+       0x0BBE, 0x0BBF,
+       0x0BC1, 0x0BC2,
+       0x0BC6, 0x0BC8,
+       0x0BCA, 0x0BCC,
+       0x0BD7, 0x0BD7,
+       0x0BE7, 0x0BF2,
+       0x0C01, 0x0C03,
+       0x0C05, 0x0C0C,
+       0x0C0E, 0x0C10,
+       0x0C12, 0x0C28,
+       0x0C2A, 0x0C33,
+       0x0C35, 0x0C39,
+       0x0C41, 0x0C44,
+       0x0C60, 0x0C61,
+       0x0C66, 0x0C6F,
+       0x0C82, 0x0C83,
+       0x0C85, 0x0C8C,
+       0x0C8E, 0x0C90,
+       0x0C92, 0x0CA8,
+       0x0CAA, 0x0CB3,
+       0x0CB5, 0x0CB9,
+       0x0CBE, 0x0CBE,
+       0x0CC0, 0x0CC4,
+       0x0CC7, 0x0CC8,
+       0x0CCA, 0x0CCB,
+       0x0CD5, 0x0CD6,
+       0x0CDE, 0x0CDE,
+       0x0CE0, 0x0CE1,
+       0x0CE6, 0x0CEF,
+       0x0D02, 0x0D03,
+       0x0D05, 0x0D0C,
+       0x0D0E, 0x0D10,
+       0x0D12, 0x0D28,
+       0x0D2A, 0x0D39,
+       0x0D3E, 0x0D40,
+       0x0D46, 0x0D48,
+       0x0D4A, 0x0D4C,
+       0x0D57, 0x0D57,
+       0x0D60, 0x0D61,
+       0x0D66, 0x0D6F,
+       0x0D82, 0x0D83,
+       0x0D85, 0x0D96,
+       0x0D9A, 0x0DB1,
+       0x0DB3, 0x0DBB,
+       0x0DBD, 0x0DBD,
+       0x0DC0, 0x0DC6,
+       0x0DCF, 0x0DD1,
+       0x0DD8, 0x0DDF,
+       0x0DF2, 0x0DF4,
+       0x0E01, 0x0E30,
+       0x0E32, 0x0E33,
+       0x0E40, 0x0E46,
+       0x0E4F, 0x0E5B,
+       0x0E81, 0x0E82,
+       0x0E84, 0x0E84,
+       0x0E87, 0x0E88,
+       0x0E8A, 0x0E8A,
+       0x0E8D, 0x0E8D,
+       0x0E94, 0x0E97,
+       0x0E99, 0x0E9F,
+       0x0EA1, 0x0EA3,
+       0x0EA5, 0x0EA5,
+       0x0EA7, 0x0EA7,
+       0x0EAA, 0x0EAB,
+       0x0EAD, 0x0EB0,
+       0x0EB2, 0x0EB3,
+       0x0EBD, 0x0EBD,
+       0x0EC0, 0x0EC4,
+       0x0EC6, 0x0EC6,
+       0x0ED0, 0x0ED9,
+       0x0EDC, 0x0EDD,
+       0x0F00, 0x0F17,
+       0x0F1A, 0x0F34,
+       0x0F36, 0x0F36,
+       0x0F38, 0x0F38,
+       0x0F3E, 0x0F47,
+       0x0F49, 0x0F6A,
+       0x0F7F, 0x0F7F,
+       0x0F85, 0x0F85,
+       0x0F88, 0x0F8B,
+       0x0FBE, 0x0FC5,
+       0x0FC7, 0x0FCC,
+       0x0FCF, 0x0FCF,
+       0x1000, 0x1021,
+       0x1023, 0x1027,
+       0x1029, 0x102A,
+       0x102C, 0x102C,
+       0x1031, 0x1031,
+       0x1038, 0x1038,
+       0x1040, 0x1057,
+       0x10A0, 0x10C5,
+       0x10D0, 0x10F8,
+       0x10FB, 0x10FB,
+       0x1100, 0x1159,
+       0x115F, 0x11A2,
+       0x11A8, 0x11F9,
+       0x1200, 0x1206,
+       0x1208, 0x1246,
+       0x1248, 0x1248,
+       0x124A, 0x124D,
+       0x1250, 0x1256,
+       0x1258, 0x1258,
+       0x125A, 0x125D,
+       0x1260, 0x1286,
+       0x1288, 0x1288,
+       0x128A, 0x128D,
+       0x1290, 0x12AE,
+       0x12B0, 0x12B0,
+       0x12B2, 0x12B5,
+       0x12B8, 0x12BE,
+       0x12C0, 0x12C0,
+       0x12C2, 0x12C5,
+       0x12C8, 0x12CE,
+       0x12D0, 0x12D6,
+       0x12D8, 0x12EE,
+       0x12F0, 0x130E,
+       0x1310, 0x1310,
+       0x1312, 0x1315,
+       0x1318, 0x131E,
+       0x1320, 0x1346,
+       0x1348, 0x135A,
+       0x1361, 0x137C,
+       0x13A0, 0x13F4,
+       0x1401, 0x1676,
+       0x1681, 0x169A,
+       0x16A0, 0x16F0,
+       0x1700, 0x170C,
+       0x170E, 0x1711,
+       0x1720, 0x1731,
+       0x1735, 0x1736,
+       0x1740, 0x1751,
+       0x1760, 0x176C,
+       0x176E, 0x1770,
+       0x1780, 0x17B6,
+       0x17BE, 0x17C5,
+       0x17C7, 0x17C8,
+       0x17D4, 0x17DA,
+       0x17DC, 0x17DC,
+       0x17E0, 0x17E9,
+       0x1810, 0x1819,
+       0x1820, 0x1877,
+       0x1880, 0x18A8,
+       0x1E00, 0x1E9B,
+       0x1EA0, 0x1EF9,
+       0x1F00, 0x1F15,
+       0x1F18, 0x1F1D,
+       0x1F20, 0x1F45,
+       0x1F48, 0x1F4D,
+       0x1F50, 0x1F57,
+       0x1F59, 0x1F59,
+       0x1F5B, 0x1F5B,
+       0x1F5D, 0x1F5D,
+       0x1F5F, 0x1F7D,
+       0x1F80, 0x1FB4,
+       0x1FB6, 0x1FBC,
+       0x1FBE, 0x1FBE,
+       0x1FC2, 0x1FC4,
+       0x1FC6, 0x1FCC,
+       0x1FD0, 0x1FD3,
+       0x1FD6, 0x1FDB,
+       0x1FE0, 0x1FEC,
+       0x1FF2, 0x1FF4,
+       0x1FF6, 0x1FFC,
+       0x200E, 0x200E,
+       0x2071, 0x2071,
+       0x207F, 0x207F,
+       0x2102, 0x2102,
+       0x2107, 0x2107,
+       0x210A, 0x2113,
+       0x2115, 0x2115,
+       0x2119, 0x211D,
+       0x2124, 0x2124,
+       0x2126, 0x2126,
+       0x2128, 0x2128,
+       0x212A, 0x212D,
+       0x212F, 0x2131,
+       0x2133, 0x2139,
+       0x213D, 0x213F,
+       0x2145, 0x2149,
+       0x2160, 0x2183,
+       0x2336, 0x237A,
+       0x2395, 0x2395,
+       0x249C, 0x24E9,
+       0x3005, 0x3007,
+       0x3021, 0x3029,
+       0x3031, 0x3035,
+       0x3038, 0x303C,
+       0x3041, 0x3096,
+       0x309D, 0x309F,
+       0x30A1, 0x30FA,
+       0x30FC, 0x30FF,
+       0x3105, 0x312C,
+       0x3131, 0x318E,
+       0x3190, 0x31B7,
+       0x31F0, 0x321C,
+       0x3220, 0x3243,
+       0x3260, 0x327B,
+       0x327F, 0x32B0,
+       0x32C0, 0x32CB,
+       0x32D0, 0x32FE,
+       0x3300, 0x3376,
+       0x337B, 0x33DD,
+       0x33E0, 0x33FE,
+       0x3400, 0x4DB5,
+       0x4E00, 0x9FA5,
+       0xA000, 0xA48C,
+       0xAC00, 0xD7A3,
+       0xD800, 0xFA2D,
+       0xFA30, 0xFA6A,
+       0xFB00, 0xFB06,
+       0xFB13, 0xFB17,
+       0xFF21, 0xFF3A,
+       0xFF41, 0xFF5A,
+       0xFF66, 0xFFBE,
+       0xFFC2, 0xFFC7,
+       0xFFCA, 0xFFCF,
+       0xFFD2, 0xFFD7,
+       0xFFDA, 0xFFDC,
+       0x10300, 0x1031E,
+       0x10320, 0x10323,
+       0x10330, 0x1034A,
+       0x10400, 0x10425,
+       0x10428, 0x1044D,
+       0x1D000, 0x1D0F5,
+       0x1D100, 0x1D126,
+       0x1D12A, 0x1D166,
+       0x1D16A, 0x1D172,
+       0x1D183, 0x1D184,
+       0x1D18C, 0x1D1A9,
+       0x1D1AE, 0x1D1DD,
+       0x1D400, 0x1D454,
+       0x1D456, 0x1D49C,
+       0x1D49E, 0x1D49F,
+       0x1D4A2, 0x1D4A2,
+       0x1D4A5, 0x1D4A6,
+       0x1D4A9, 0x1D4AC,
+       0x1D4AE, 0x1D4B9,
+       0x1D4BB, 0x1D4BB,
+       0x1D4BD, 0x1D4C0,
+       0x1D4C2, 0x1D4C3,
+       0x1D4C5, 0x1D505,
+       0x1D507, 0x1D50A,
+       0x1D50D, 0x1D514,
+       0x1D516, 0x1D51C,
+       0x1D51E, 0x1D539,
+       0x1D53B, 0x1D53E,
+       0x1D540, 0x1D544,
+       0x1D546, 0x1D546,
+       0x1D54A, 0x1D550,
+       0x1D552, 0x1D6A3,
+       0x1D6A8, 0x1D7C9,
+       0x20000, 0x2A6D6,
+       0x2F800, 0x2FA1D,
+       0xF0000, 0xFFFFD,
+       0x100000, 0x10FFFD
+};
+
+/* End of stringprep tables */
+
+
+/* Is the given Unicode codepoint in the given table of ranges? */
+#define IS_CODE_IN_TABLE(code, map) is_code_in_table(code, map, lengthof(map))
+
+static int
+codepoint_range_cmp(const void *a, const void *b)
+{
+       const pg_wchar *key = (const pg_wchar *) a;
+       const pg_wchar *range = (const pg_wchar *) b;
+
+       if (*key < range[0])
+               return -1;                              /* less than lower bound */
+       if (*key > range[1])
+               return 1;                               /* greater than upper bound */
+
+       return 0;                                       /* within range */
+}
+
+static bool
+is_code_in_table(pg_wchar code, const pg_wchar *map, int mapsize)
+{
+       Assert(mapsize % 2 == 0);
+
+       if (code < map[0] || code > map[mapsize - 1])
+               return false;
+
+       if (bsearch(&code, map, mapsize / 2, sizeof(pg_wchar) * 2,
+                               codepoint_range_cmp))
+               return true;
+       else
+               return false;
+}
+
+/*
+ * Calculate the length in characters of a null-terminated UTF-8 string.
+ *
+ * Returns -1 if the input is not valid UTF-8.
+ */
+static int
+pg_utf8_string_len(const char *source)
+{
+       const unsigned char *p = (const unsigned char *) source;
+       int                     l;
+       int                     num_chars = 0;
+
+       while (*p)
+       {
+               l = pg_utf_mblen(p);
+
+               if (!pg_utf8_islegal(p, l))
+                       return -1;
+
+               p += l;
+               num_chars++;
+       }
+
+       return num_chars;
+}
+
+/*
+ * Returns true if the input string is pure ASCII.
+ */
+static bool
+pg_is_ascii_string(const char *p)
+{
+       while (*p)
+       {
+               if (IS_HIGHBIT_SET(*p))
+                       return false;
+               p++;
+       }
+       return true;
+}
+
+
+/*
+ * pg_saslprep - Normalize a password with SASLprep.
+ *
+ * SASLprep requires the input to be in UTF-8 encoding, but PostgreSQL
+ * supports many encodings, so we don't blindly assume that.  pg_saslprep
+ * will check if the input looks like valid UTF-8, and returns
+ * SASLPREP_INVALID_UTF8 if not.
+ *
+ * If the string contains prohibited characters (or more precisely, if the
+ * output string would contain prohibited characters after normalization),
+ * returns SASLPREP_PROHIBITED.
+ *
+ * On success, returns SASLPREP_SUCCESS, and the normalized string in
+ * *output.
+ *
+ * In frontend, the normalized string is malloc'd, and the caller is
+ * responsible for freeing it.  If an allocation fails, returns
+ * SASLPREP_OOM.  In backend, the normalized string is palloc'd instead,
+ * and a failed allocation leads to ereport(ERROR).
+ */
+pg_saslprep_rc
+pg_saslprep(const char *input, char **output)
+{
+       pg_wchar   *input_chars = NULL;
+       pg_wchar   *output_chars = NULL;
+       int                     input_size;
+       char       *result;
+       int                     result_size;
+       int                     count;
+       int                     i;
+       bool            contains_RandALCat;
+       unsigned char *p;
+       pg_wchar   *wp;
+
+       /* Ensure we return *output as NULL on failure */
+       *output = NULL;
+
+       /* Check that the password isn't stupendously long */
+       if (strlen(input) > MAX_PASSWORD_LENGTH)
+       {
+#ifndef FRONTEND
+               ereport(ERROR,
+                               (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
+                                errmsg("password too long")));
+#else
+               return SASLPREP_OOM;
+#endif
+       }
+
+       /*
+        * Quick check if the input is pure ASCII.  An ASCII string requires no
+        * further processing.
+        */
+       if (pg_is_ascii_string(input))
+       {
+               *output = STRDUP(input);
+               if (!(*output))
+                       goto oom;
+               return SASLPREP_SUCCESS;
+       }
+
+       /*
+        * Convert the input from UTF-8 to an array of Unicode codepoints.
+        *
+        * This also checks that the input is a legal UTF-8 string.
+        */
+       input_size = pg_utf8_string_len(input);
+       if (input_size < 0)
+               return SASLPREP_INVALID_UTF8;
+
+       input_chars = ALLOC((input_size + 1) * sizeof(pg_wchar));
+       if (!input_chars)
+               goto oom;
+
+       p = (unsigned char *) input;
+       for (i = 0; i < input_size; i++)
+       {
+               input_chars[i] = utf8_to_unicode(p);
+               p += pg_utf_mblen(p);
+       }
+       input_chars[i] = (pg_wchar) '\0';
+
+       /*
+        * The steps below correspond to the steps listed in [RFC3454], Section
+        * "2. Preparation Overview"
+        */
+
+       /*
+        * 1) Map -- For each character in the input, check if it has a mapping
+        * and, if so, replace it with its mapping.
+        */
+       count = 0;
+       for (i = 0; i < input_size; i++)
+       {
+               pg_wchar        code = input_chars[i];
+
+               if (IS_CODE_IN_TABLE(code, non_ascii_space_ranges))
+                       input_chars[count++] = 0x0020;
+               else if (IS_CODE_IN_TABLE(code, commonly_mapped_to_nothing_ranges))
+               {
+                       /* map to nothing */
+               }
+               else
+                       input_chars[count++] = code;
+       }
+       input_chars[count] = (pg_wchar) '\0';
+       input_size = count;
+
+       if (input_size == 0)
+               goto prohibited;                /* don't allow empty password */
+
+       /*
+        * 2) Normalize -- Normalize the result of step 1 using Unicode
+        * normalization.
+        */
+       output_chars = unicode_normalize_kc(input_chars);
+       if (!output_chars)
+               goto oom;
+
+       /*
+        * 3) Prohibit -- Check for any characters that are not allowed in the
+        * output.  If any are found, return an error.
+        */
+       for (i = 0; i < input_size; i++)
+       {
+               pg_wchar        code = input_chars[i];
+
+               if (IS_CODE_IN_TABLE(code, prohibited_output_ranges))
+                       goto prohibited;
+               if (IS_CODE_IN_TABLE(code, unassigned_codepoint_ranges))
+                       goto prohibited;
+       }
+
+       /*
+        * 4) Check bidi -- Possibly check for right-to-left characters, and if
+        * any are found, make sure that the whole string satisfies the
+        * requirements for bidirectional strings.  If the string does not satisfy
+        * the requirements for bidirectional strings, return an error.
+        *
+        * [RFC3454], Section "6. Bidirectional Characters" explains in more
+        * detail what that means:
+        *
+        * "In any profile that specifies bidirectional character handling, all
+        * three of the following requirements MUST be met:
+        *
+        * 1) The characters in section 5.8 MUST be prohibited.
+        *
+        * 2) If a string contains any RandALCat character, the string MUST NOT
+        * contain any LCat character.
+        *
+        * 3) If a string contains any RandALCat character, a RandALCat character
+        * MUST be the first character of the string, and a RandALCat character
+        * MUST be the last character of the string."
+        */
+       contains_RandALCat = false;
+       for (i = 0; i < input_size; i++)
+       {
+               pg_wchar        code = input_chars[i];
+
+               if (IS_CODE_IN_TABLE(code, RandALCat_codepoint_ranges))
+               {
+                       contains_RandALCat = true;
+                       break;
+               }
+       }
+
+       if (contains_RandALCat)
+       {
+               pg_wchar        first = input_chars[0];
+               pg_wchar        last = input_chars[input_size - 1];
+
+               for (i = 0; i < input_size; i++)
+               {
+                       pg_wchar        code = input_chars[i];
+
+                       if (IS_CODE_IN_TABLE(code, LCat_codepoint_ranges))
+                               goto prohibited;
+               }
+
+               if (!IS_CODE_IN_TABLE(first, RandALCat_codepoint_ranges) ||
+                       !IS_CODE_IN_TABLE(last, RandALCat_codepoint_ranges))
+                       goto prohibited;
+       }
+
+       /*
+        * Finally, convert the result back to UTF-8.
+        */
+       result_size = 0;
+       for (wp = output_chars; *wp; wp++)
+       {
+               unsigned char buf[4];
+
+               unicode_to_utf8(*wp, buf);
+               result_size += pg_utf_mblen(buf);
+       }
+
+       result = ALLOC(result_size + 1);
+       if (!result)
+               goto oom;
+
+       /*
+        * There are no error exits below here, so the error exit paths don't need
+        * to worry about possibly freeing "result".
+        */
+       p = (unsigned char *) result;
+       for (wp = output_chars; *wp; wp++)
+       {
+               unicode_to_utf8(*wp, p);
+               p += pg_utf_mblen(p);
+       }
+       Assert((char *) p == result + result_size);
+       *p = '\0';
+
+       FREE(input_chars);
+       FREE(output_chars);
+
+       *output = result;
+       return SASLPREP_SUCCESS;
+
+prohibited:
+       if (input_chars)
+               FREE(input_chars);
+       if (output_chars)
+               FREE(output_chars);
+
+       return SASLPREP_PROHIBITED;
+
+oom:
+       if (input_chars)
+               FREE(input_chars);
+       if (output_chars)
+               FREE(output_chars);
+
+       return SASLPREP_OOM;
+}
diff --git a/src/common/scram-common.c b/src/common/scram-common.c
new file mode 100644 (file)
index 0000000..bde6c8e
--- /dev/null
@@ -0,0 +1,248 @@
+/*-------------------------------------------------------------------------
+ * scram-common.c
+ *             Shared frontend/backend code for SCRAM authentication
+ *
+ * This contains the common low-level functions needed in both frontend and
+ * backend, for implement the Salted Challenge Response Authentication
+ * Mechanism (SCRAM), per IETF's RFC 5802.
+ *
+ * Portions Copyright (c) 2017-2018, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       src/common/scram-common.c
+ *
+ *-------------------------------------------------------------------------
+ */
+//#ifndef FRONTEND
+//#include "postgres.h"
+//#else
+//#include "postgres_fe.h"
+//#endif
+#include "system.h"
+#include "common/postgres_compat.h"
+
+#include "usual/crypto/sha256.h"
+#include "usual/endian.h"
+
+#include "common/base64.h"
+#include "common/scram-common.h"
+
+#define HMAC_IPAD 0x36
+#define HMAC_OPAD 0x5C
+
+/*
+ * Calculate HMAC per RFC2104.
+ *
+ * The hash function used is SHA-256.
+ */
+void
+scram_HMAC_init(scram_HMAC_ctx *ctx, const uint8 *key, int keylen)
+{
+       uint8           k_ipad[SHA256_HMAC_B];
+       int                     i;
+       uint8           keybuf[SCRAM_KEY_LEN];
+
+       /*
+        * If the key is longer than the block size (64 bytes for SHA-256), pass
+        * it through SHA-256 once to shrink it down.
+        */
+       if (keylen > SHA256_HMAC_B)
+       {
+               pg_sha256_ctx sha256_ctx;
+
+               pg_sha256_init(&sha256_ctx);
+               pg_sha256_update(&sha256_ctx, key, keylen);
+               pg_sha256_final(&sha256_ctx, keybuf);
+               key = keybuf;
+               keylen = SCRAM_KEY_LEN;
+       }
+
+       memset(k_ipad, HMAC_IPAD, SHA256_HMAC_B);
+       memset(ctx->k_opad, HMAC_OPAD, SHA256_HMAC_B);
+
+       for (i = 0; i < keylen; i++)
+       {
+               k_ipad[i] ^= key[i];
+               ctx->k_opad[i] ^= key[i];
+       }
+
+       /* tmp = H(K XOR ipad, text) */
+       pg_sha256_init(&ctx->sha256ctx);
+       pg_sha256_update(&ctx->sha256ctx, k_ipad, SHA256_HMAC_B);
+}
+
+/*
+ * Update HMAC calculation
+ * The hash function used is SHA-256.
+ */
+void
+scram_HMAC_update(scram_HMAC_ctx *ctx, const char *str, int slen)
+{
+       pg_sha256_update(&ctx->sha256ctx, (const uint8 *) str, slen);
+}
+
+/*
+ * Finalize HMAC calculation.
+ * The hash function used is SHA-256.
+ */
+void
+scram_HMAC_final(uint8 *result, scram_HMAC_ctx *ctx)
+{
+       uint8           h[SCRAM_KEY_LEN];
+
+       pg_sha256_final(&ctx->sha256ctx, h);
+
+       /* H(K XOR opad, tmp) */
+       pg_sha256_init(&ctx->sha256ctx);
+       pg_sha256_update(&ctx->sha256ctx, ctx->k_opad, SHA256_HMAC_B);
+       pg_sha256_update(&ctx->sha256ctx, h, SCRAM_KEY_LEN);
+       pg_sha256_final(&ctx->sha256ctx, result);
+}
+
+/*
+ * Calculate SaltedPassword.
+ *
+ * The password should already be normalized by SASLprep.
+ */
+void
+scram_SaltedPassword(const char *password,
+                                        const char *salt, int saltlen, int iterations,
+                                        uint8 *result)
+{
+       int                     password_len = strlen(password);
+       uint32          one = pg_hton32(1);
+       int                     i,
+                               j;
+       uint8           Ui[SCRAM_KEY_LEN];
+       uint8           Ui_prev[SCRAM_KEY_LEN];
+       scram_HMAC_ctx hmac_ctx;
+
+       /*
+        * Iterate hash calculation of HMAC entry using given salt.  This is
+        * essentially PBKDF2 (see RFC2898) with HMAC() as the pseudorandom
+        * function.
+        */
+
+       /* First iteration */
+       scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len);
+       scram_HMAC_update(&hmac_ctx, salt, saltlen);
+       scram_HMAC_update(&hmac_ctx, (char *) &one, sizeof(uint32));
+       scram_HMAC_final(Ui_prev, &hmac_ctx);
+       memcpy(result, Ui_prev, SCRAM_KEY_LEN);
+
+       /* Subsequent iterations */
+       for (i = 2; i <= iterations; i++)
+       {
+               scram_HMAC_init(&hmac_ctx, (uint8 *) password, password_len);
+               scram_HMAC_update(&hmac_ctx, (const char *) Ui_prev, SCRAM_KEY_LEN);
+               scram_HMAC_final(Ui, &hmac_ctx);
+               for (j = 0; j < SCRAM_KEY_LEN; j++)
+                       result[j] ^= Ui[j];
+               memcpy(Ui_prev, Ui, SCRAM_KEY_LEN);
+       }
+}
+
+
+/*
+ * Calculate SHA-256 hash for a NULL-terminated string. (The NULL terminator is
+ * not included in the hash).
+ */
+void
+scram_H(const uint8 *input, int len, uint8 *result)
+{
+       pg_sha256_ctx ctx;
+
+       pg_sha256_init(&ctx);
+       pg_sha256_update(&ctx, input, len);
+       pg_sha256_final(&ctx, result);
+}
+
+/*
+ * Calculate ClientKey.
+ */
+void
+scram_ClientKey(const uint8 *salted_password, uint8 *result)
+{
+       scram_HMAC_ctx ctx;
+
+       scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN);
+       scram_HMAC_update(&ctx, "Client Key", strlen("Client Key"));
+       scram_HMAC_final(result, &ctx);
+}
+
+/*
+ * Calculate ServerKey.
+ */
+void
+scram_ServerKey(const uint8 *salted_password, uint8 *result)
+{
+       scram_HMAC_ctx ctx;
+
+       scram_HMAC_init(&ctx, salted_password, SCRAM_KEY_LEN);
+       scram_HMAC_update(&ctx, "Server Key", strlen("Server Key"));
+       scram_HMAC_final(result, &ctx);
+}
+
+
+/*
+ * Construct a verifier string for SCRAM, stored in pg_authid.rolpassword.
+ *
+ * The password should already have been processed with SASLprep, if necessary!
+ *
+ * If iterations is 0, default number of iterations is used.  The result is
+ * palloc'd or malloc'd, so caller is responsible for freeing it.
+ */
+char *
+scram_build_verifier(const char *salt, int saltlen, int iterations,
+                                        const char *password)
+{
+       uint8           salted_password[SCRAM_KEY_LEN];
+       uint8           stored_key[SCRAM_KEY_LEN];
+       uint8           server_key[SCRAM_KEY_LEN];
+       char       *result;
+       char       *p;
+       int                     maxlen;
+
+       if (iterations <= 0)
+               iterations = SCRAM_DEFAULT_ITERATIONS;
+
+       /* Calculate StoredKey and ServerKey */
+       scram_SaltedPassword(password, salt, saltlen, iterations,
+                                                salted_password);
+       scram_ClientKey(salted_password, stored_key);
+       scram_H(stored_key, SCRAM_KEY_LEN, stored_key);
+
+       scram_ServerKey(salted_password, server_key);
+
+       /*----------
+        * The format is:
+        * SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
+        *----------
+        */
+       maxlen = strlen("SCRAM-SHA-256") + 1
+               + 10 + 1                                /* iteration count */
+               + pg_b64_enc_len(saltlen) + 1   /* Base64-encoded salt */
+               + pg_b64_enc_len(SCRAM_KEY_LEN) + 1 /* Base64-encoded StoredKey */
+               + pg_b64_enc_len(SCRAM_KEY_LEN) + 1;    /* Base64-encoded ServerKey */
+
+#ifdef FRONTEND
+       result = malloc(maxlen);
+       if (!result)
+               return NULL;
+#else
+       result = palloc(maxlen);
+#endif
+
+       p = result + sprintf(result, "SCRAM-SHA-256$%d:", iterations);
+
+       p += pg_b64_encode(salt, saltlen, p);
+       *(p++) = '$';
+       p += pg_b64_encode((char *) stored_key, SCRAM_KEY_LEN, p);
+       *(p++) = ':';
+       p += pg_b64_encode((char *) server_key, SCRAM_KEY_LEN, p);
+       *(p++) = '\0';
+
+       Assert(p - result <= maxlen);
+
+       return result;
+}
diff --git a/src/common/unicode_norm.c b/src/common/unicode_norm.c
new file mode 100644 (file)
index 0000000..e30bbe9
--- /dev/null
@@ -0,0 +1,439 @@
+/*-------------------------------------------------------------------------
+ * unicode_norm.c
+ *             Normalize a Unicode string to NFKC form
+ *
+ * This implements Unicode normalization, per the documentation at
+ * http://www.unicode.org/reports/tr15/.
+ *
+ * Portions Copyright (c) 2017-2018, PostgreSQL Global Development Group
+ *
+ * IDENTIFICATION
+ *       src/common/unicode_norm.c
+ *
+ *-------------------------------------------------------------------------
+ */
+//#ifndef FRONTEND
+//#include "postgres.h"
+//#else
+//#include "postgres_fe.h"
+//#endif
+#include "system.h"
+#include "common/postgres_compat.h"
+
+#include "common/unicode_norm.h"
+#include "common/unicode_norm_table.h"
+
+#ifndef FRONTEND
+#define ALLOC(size) palloc(size)
+#define FREE(size) pfree(size)
+#else
+#define ALLOC(size) malloc(size)
+#define FREE(size) free(size)
+#endif
+
+/* Constants for calculations with Hangul characters */
+#define SBASE          0xAC00          /* U+AC00 */
+#define LBASE          0x1100          /* U+1100 */
+#define VBASE          0x1161          /* U+1161 */
+#define TBASE          0x11A7          /* U+11A7 */
+#define LCOUNT         19
+#define VCOUNT         21
+#define TCOUNT         28
+#define NCOUNT         VCOUNT * TCOUNT
+#define SCOUNT         LCOUNT * NCOUNT
+
+/* comparison routine for bsearch() of decomposition lookup table. */
+static int
+conv_compare(const void *p1, const void *p2)
+{
+       uint32          v1,
+                               v2;
+
+       v1 = *(const uint32 *) p1;
+       v2 = ((const pg_unicode_decomposition *) p2)->codepoint;
+       return (v1 > v2) ? 1 : ((v1 == v2) ? 0 : -1);
+}
+
+/*
+ * Get the entry corresponding to code in the decomposition lookup table.
+ */
+static pg_unicode_decomposition *
+get_code_entry(pg_wchar code)
+{
+       return bsearch(&(code),
+                                  (void *) UnicodeDecompMain,
+                                  lengthof(UnicodeDecompMain),
+                                  sizeof(pg_unicode_decomposition),
+                                  conv_compare);
+}
+
+/*
+ * Given a decomposition entry looked up earlier, get the decomposed
+ * characters.
+ *
+ * Note: the returned pointer can point to statically allocated buffer, and
+ * is only valid until next call to this function!
+ */
+static const pg_wchar *
+get_code_decomposition(pg_unicode_decomposition *entry, int *dec_size)
+{
+       static pg_wchar x;
+
+       if (DECOMPOSITION_IS_INLINE(entry))
+       {
+               Assert(DECOMPOSITION_SIZE(entry) == 1);
+               x = (pg_wchar) entry->dec_index;
+               *dec_size = 1;
+               return &x;
+       }
+       else
+       {
+               *dec_size = DECOMPOSITION_SIZE(entry);
+               return &UnicodeDecomp_codepoints[entry->dec_index];
+       }
+}
+
+/*
+ * Calculate how many characters a given character will decompose to.
+ *
+ * This needs to recurse, if the character decomposes into characters that
+ * are, in turn, decomposable.
+ */
+static int
+get_decomposed_size(pg_wchar code)
+{
+       pg_unicode_decomposition *entry;
+       int                     size = 0;
+       int                     i;
+       const uint32 *decomp;
+       int                     dec_size;
+
+       /*
+        * Fast path for Hangul characters not stored in tables to save memory as
+        * decomposition is algorithmic. See
+        * http://unicode.org/reports/tr15/tr15-18.html, annex 10 for details on
+        * the matter.
+        */
+       if (code >= SBASE && code < SBASE + SCOUNT)
+       {
+               uint32          tindex,
+                                       sindex;
+
+               sindex = code - SBASE;
+               tindex = sindex % TCOUNT;
+
+               if (tindex != 0)
+                       return 3;
+               return 2;
+       }
+
+       entry = get_code_entry(code);
+
+       /*
+        * Just count current code if no other decompositions.  A NULL entry is
+        * equivalent to a character with class 0 and no decompositions.
+        */
+       if (entry == NULL || DECOMPOSITION_SIZE(entry) == 0)
+               return 1;
+
+       /*
+        * If this entry has other decomposition codes look at them as well. First
+        * get its decomposition in the list of tables available.
+        */
+       decomp = get_code_decomposition(entry, &dec_size);
+       for (i = 0; i < dec_size; i++)
+       {
+               uint32          lcode = decomp[i];
+
+               size += get_decomposed_size(lcode);
+       }
+
+       return size;
+}
+
+/*
+ * Recompose a set of characters. For hangul characters, the calculation
+ * is algorithmic. For others, an inverse lookup at the decomposition
+ * table is necessary. Returns true if a recomposition can be done, and
+ * false otherwise.
+ */
+static bool
+recompose_code(uint32 start, uint32 code, uint32 *result)
+{
+       /*
+        * Handle Hangul characters algorithmically, per the Unicode spec.
+        *
+        * Check if two current characters are L and V.
+        */
+       if (start >= LBASE && start < LBASE + LCOUNT &&
+               code >= VBASE && code < VBASE + VCOUNT)
+       {
+               /* make syllable of form LV */
+               uint32          lindex = start - LBASE;
+               uint32          vindex = code - VBASE;
+
+               *result = SBASE + (lindex * VCOUNT + vindex) * TCOUNT;
+               return true;
+       }
+       /* Check if two current characters are LV and T */
+       else if (start >= SBASE && start < (SBASE + SCOUNT) &&
+                        ((start - SBASE) % TCOUNT) == 0 &&
+                        code >= TBASE && code < (TBASE + TCOUNT))
+       {
+               /* make syllable of from LVT */
+               uint32          tindex = code - TBASE;
+
+               *result = start + tindex;
+               return true;
+       }
+       else
+       {
+               unsigned int            i;
+
+               /*
+                * Do an inverse lookup of the decomposition tables to see if anything
+                * matches. The comparison just needs to be a perfect match on the
+                * sub-table of size two, because the start character has already been
+                * recomposed partially.
+                */
+               for (i = 0; i < lengthof(UnicodeDecompMain); i++)
+               {
+                       const pg_unicode_decomposition *entry = &UnicodeDecompMain[i];
+
+                       if (DECOMPOSITION_SIZE(entry) != 2)
+                               continue;
+
+                       if (DECOMPOSITION_NO_COMPOSE(entry))
+                               continue;
+
+                       if (start == UnicodeDecomp_codepoints[entry->dec_index] &&
+                               code == UnicodeDecomp_codepoints[entry->dec_index + 1])
+                       {
+                               *result = entry->codepoint;
+                               return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+/*
+ * Decompose the given code into the array given by caller. The
+ * decomposition begins at the position given by caller, saving one
+ * lookup on the decomposition table. The current position needs to be
+ * updated here to let the caller know from where to continue filling
+ * in the array result.
+ */
+static void
+decompose_code(pg_wchar code, pg_wchar **result, int *current)
+{
+       pg_unicode_decomposition *entry;
+       int                     i;
+       const uint32 *decomp;
+       int                     dec_size;
+
+       /*
+        * Fast path for Hangul characters not stored in tables to save memory as
+        * decomposition is algorithmic. See
+        * http://unicode.org/reports/tr15/tr15-18.html, annex 10 for details on
+        * the matter.
+        */
+       if (code >= SBASE && code < SBASE + SCOUNT)
+       {
+               uint32          l,
+                                       v,
+                                       tindex,
+                                       sindex;
+               pg_wchar   *res = *result;
+
+               sindex = code - SBASE;
+               l = LBASE + sindex / (VCOUNT * TCOUNT);
+               v = VBASE + (sindex % (VCOUNT * TCOUNT)) / TCOUNT;
+               tindex = sindex % TCOUNT;
+
+               res[*current] = l;
+               (*current)++;
+               res[*current] = v;
+               (*current)++;
+
+               if (tindex != 0)
+               {
+                       res[*current] = TBASE + tindex;
+                       (*current)++;
+               }
+
+               return;
+       }
+
+       entry = get_code_entry(code);
+
+       /*
+        * Just fill in with the current decomposition if there are no
+        * decomposition codes to recurse to.  A NULL entry is equivalent to a
+        * character with class 0 and no decompositions, so just leave also in
+        * this case.
+        */
+       if (entry == NULL || DECOMPOSITION_SIZE(entry) == 0)
+       {
+               pg_wchar   *res = *result;
+
+               res[*current] = code;
+               (*current)++;
+               return;
+       }
+
+       /*
+        * If this entry has other decomposition codes look at them as well.
+        */
+       decomp = get_code_decomposition(entry, &dec_size);
+       for (i = 0; i < dec_size; i++)
+       {
+               pg_wchar        lcode = (pg_wchar) decomp[i];
+
+               /* Leave if no more decompositions */
+               decompose_code(lcode, result, current);
+       }
+}
+
+/*
+ * unicode_normalize_kc - Normalize a Unicode string to NFKC form.
+ *
+ * The input is a 0-terminated array of codepoints.
+ *
+ * In frontend, returns a 0-terminated array of codepoints, allocated with
+ * malloc. Or NULL if we run out of memory. In frontend, the returned
+ * string is palloc'd instead, and OOM is reported with ereport().
+ */
+pg_wchar *
+unicode_normalize_kc(const pg_wchar *input)
+{
+       pg_wchar   *decomp_chars;
+       pg_wchar   *recomp_chars;
+       int                     decomp_size,
+                               current_size;
+       int                     count;
+       const pg_wchar *p;
+
+       /* variables for recomposition */
+       int                     last_class;
+       int                     starter_pos;
+       int                     target_pos;
+       uint32          starter_ch;
+
+       /* First, do character decomposition */
+
+       /*
+        * Calculate how many characters long the decomposed version will be.
+        */
+       decomp_size = 0;
+       for (p = input; *p; p++)
+               decomp_size += get_decomposed_size(*p);
+
+       decomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar));
+       if (decomp_chars == NULL)
+               return NULL;
+
+       /*
+        * Now fill in each entry recursively. This needs a second pass on the
+        * decomposition table.
+        */
+       current_size = 0;
+       for (p = input; *p; p++)
+               decompose_code(*p, &decomp_chars, &current_size);
+       decomp_chars[decomp_size] = '\0';
+       Assert(decomp_size == current_size);
+
+       /*
+        * Now apply canonical ordering.
+        */
+       for (count = 1; count < decomp_size; count++)
+       {
+               pg_wchar        prev = decomp_chars[count - 1];
+               pg_wchar        next = decomp_chars[count];
+               pg_wchar        tmp;
+               pg_unicode_decomposition *prevEntry = get_code_entry(prev);
+               pg_unicode_decomposition *nextEntry = get_code_entry(next);
+
+               /*
+                * If no entries are found, the character used is either an Hangul
+                * character or a character with a class of 0 and no decompositions,
+                * so move to next result.
+                */
+               if (prevEntry == NULL || nextEntry == NULL)
+                       continue;
+
+               /*
+                * Per Unicode (http://unicode.org/reports/tr15/tr15-18.html) annex 4,
+                * a sequence of two adjacent characters in a string is an
+                * exchangeable pair if the combining class (from the Unicode
+                * Character Database) for the first character is greater than the
+                * combining class for the second, and the second is not a starter.  A
+                * character is a starter if its combining class is 0.
+                */
+               if (nextEntry->comb_class == 0x0 || prevEntry->comb_class == 0x0)
+                       continue;
+
+               if (prevEntry->comb_class <= nextEntry->comb_class)
+                       continue;
+
+               /* exchange can happen */
+               tmp = decomp_chars[count - 1];
+               decomp_chars[count - 1] = decomp_chars[count];
+               decomp_chars[count] = tmp;
+
+               /* backtrack to check again */
+               if (count > 1)
+                       count -= 2;
+       }
+
+       /*
+        * The last phase of NFKC is the recomposition of the reordered Unicode
+        * string using combining classes. The recomposed string cannot be longer
+        * than the decomposed one, so make the allocation of the output string
+        * based on that assumption.
+        */
+       recomp_chars = (pg_wchar *) ALLOC((decomp_size + 1) * sizeof(pg_wchar));
+       if (!recomp_chars)
+       {
+               FREE(decomp_chars);
+               return NULL;
+       }
+
+       last_class = -1;                        /* this eliminates a special check */
+       starter_pos = 0;
+       target_pos = 1;
+       starter_ch = recomp_chars[0] = decomp_chars[0];
+
+       for (count = 1; count < decomp_size; count++)
+       {
+               pg_wchar        ch = decomp_chars[count];
+               pg_unicode_decomposition *ch_entry = get_code_entry(ch);
+               int                     ch_class = (ch_entry == NULL) ? 0 : ch_entry->comb_class;
+               pg_wchar        composite;
+
+               if (last_class < ch_class &&
+                       recompose_code(starter_ch, ch, &composite))
+               {
+                       recomp_chars[starter_pos] = composite;
+                       starter_ch = composite;
+               }
+               else if (ch_class == 0)
+               {
+                       starter_pos = target_pos;
+                       starter_ch = ch;
+                       last_class = -1;
+                       recomp_chars[target_pos++] = ch;
+               }
+               else
+               {
+                       last_class = ch_class;
+                       recomp_chars[target_pos++] = ch;
+               }
+       }
+       recomp_chars[target_pos] = (pg_wchar) '\0';
+
+       FREE(decomp_chars);
+
+       return recomp_chars;
+}
diff --git a/src/common/wchar.c b/src/common/wchar.c
new file mode 100644 (file)
index 0000000..6c6cce5
--- /dev/null
@@ -0,0 +1,2056 @@
+/*
+ * conversion functions between pg_wchar and multibyte streams.
+ * Tatsuo Ishii
+ * src/backend/utils/mb/wchar.c
+ *
+ */
+/* can be used in either frontend or backend */
+//#ifdef FRONTEND
+//#include "postgres_fe.h"
+//#else
+//#include "postgres.h"
+//#endif
+#include "system.h"
+#include "common/postgres_compat.h"
+
+#include "common/pg_wchar.h"
+
+
+/*
+ * conversion to pg_wchar is done by "table driven."
+ * to add an encoding support, define mb2wchar_with_len(), mblen(), dsplen()
+ * for the particular encoding. Note that if the encoding is only
+ * supported in the client, you don't need to define
+ * mb2wchar_with_len() function (SJIS is the case).
+ *
+ * These functions generally assume that their input is validly formed.
+ * The "verifier" functions, further down in the file, have to be more
+ * paranoid.  We expect that mblen() does not need to examine more than
+ * the first byte of the character to discover the correct length.
+ *
+ * Note: for the display output of psql to work properly, the return values
+ * of the dsplen functions must conform to the Unicode standard. In particular
+ * the NUL character is zero width and control characters are generally
+ * width -1. It is recommended that non-ASCII encodings refer their ASCII
+ * subset to the ASCII routines to ensure consistency.
+ */
+
+/*
+ * SQL/ASCII
+ */
+static int
+pg_ascii2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               *to++ = *from++;
+               len--;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+static int
+pg_ascii_mblen(const unsigned char *s)
+{
+       return 1;
+}
+
+static int
+pg_ascii_dsplen(const unsigned char *s)
+{
+       if (*s == '\0')
+               return 0;
+       if (*s < 0x20 || *s == 0x7f)
+               return -1;
+
+       return 1;
+}
+
+/*
+ * EUC
+ */
+static int
+pg_euc2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               if (*from == SS2 && len >= 2)   /* JIS X 0201 (so called "1 byte
+                                                                                * KANA") */
+               {
+                       from++;
+                       *to = (SS2 << 8) | *from++;
+                       len -= 2;
+               }
+               else if (*from == SS3 && len >= 3)      /* JIS X 0212 KANJI */
+               {
+                       from++;
+                       *to = (SS3 << 16) | (*from++ << 8);
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (IS_HIGHBIT_SET(*from) && len >= 2) /* JIS X 0208 KANJI */
+               {
+                       *to = *from++ << 8;
+                       *to |= *from++;
+                       len -= 2;
+               }
+               else                                    /* must be ASCII */
+               {
+                       *to = *from++;
+                       len--;
+               }
+               to++;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+static inline int
+pg_euc_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s == SS2)
+               len = 2;
+       else if (*s == SS3)
+               len = 3;
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = 1;
+       return len;
+}
+
+static inline int
+pg_euc_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s == SS2)
+               len = 2;
+       else if (*s == SS3)
+               len = 2;
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = pg_ascii_dsplen(s);
+       return len;
+}
+
+/*
+ * EUC_JP
+ */
+static int
+pg_eucjp2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       return pg_euc2wchar_with_len(from, to, len);
+}
+
+static int
+pg_eucjp_mblen(const unsigned char *s)
+{
+       return pg_euc_mblen(s);
+}
+
+static int
+pg_eucjp_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s == SS2)
+               len = 1;
+       else if (*s == SS3)
+               len = 2;
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = pg_ascii_dsplen(s);
+       return len;
+}
+
+/*
+ * EUC_KR
+ */
+static int
+pg_euckr2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       return pg_euc2wchar_with_len(from, to, len);
+}
+
+static int
+pg_euckr_mblen(const unsigned char *s)
+{
+       return pg_euc_mblen(s);
+}
+
+static int
+pg_euckr_dsplen(const unsigned char *s)
+{
+       return pg_euc_dsplen(s);
+}
+
+/*
+ * EUC_CN
+ *
+ */
+static int
+pg_euccn2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               if (*from == SS2 && len >= 3)   /* code set 2 (unused?) */
+               {
+                       from++;
+                       *to = (SS2 << 16) | (*from++ << 8);
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (*from == SS3 && len >= 3)      /* code set 3 (unused ?) */
+               {
+                       from++;
+                       *to = (SS3 << 16) | (*from++ << 8);
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 1 */
+               {
+                       *to = *from++ << 8;
+                       *to |= *from++;
+                       len -= 2;
+               }
+               else
+               {
+                       *to = *from++;
+                       len--;
+               }
+               to++;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+static int
+pg_euccn_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = 1;
+       return len;
+}
+
+static int
+pg_euccn_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = pg_ascii_dsplen(s);
+       return len;
+}
+
+/*
+ * EUC_TW
+ *
+ */
+static int
+pg_euctw2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               if (*from == SS2 && len >= 4)   /* code set 2 */
+               {
+                       from++;
+                       *to = (((uint32) SS2) << 24) | (*from++ << 16);
+                       *to |= *from++ << 8;
+                       *to |= *from++;
+                       len -= 4;
+               }
+               else if (*from == SS3 && len >= 3)      /* code set 3 (unused?) */
+               {
+                       from++;
+                       *to = (SS3 << 16) | (*from++ << 8);
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (IS_HIGHBIT_SET(*from) && len >= 2) /* code set 2 */
+               {
+                       *to = *from++ << 8;
+                       *to |= *from++;
+                       len -= 2;
+               }
+               else
+               {
+                       *to = *from++;
+                       len--;
+               }
+               to++;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+static int
+pg_euctw_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s == SS2)
+               len = 4;
+       else if (*s == SS3)
+               len = 3;
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = 1;
+       return len;
+}
+
+static int
+pg_euctw_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s == SS2)
+               len = 2;
+       else if (*s == SS3)
+               len = 2;
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = pg_ascii_dsplen(s);
+       return len;
+}
+
+/*
+ * Convert pg_wchar to EUC_* encoding.
+ * caller must allocate enough space for "to", including a trailing zero!
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2euc_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               unsigned char c;
+
+               if ((c = (*from >> 24)))
+               {
+                       *to++ = c;
+                       *to++ = (*from >> 16) & 0xff;
+                       *to++ = (*from >> 8) & 0xff;
+                       *to++ = *from & 0xff;
+                       cnt += 4;
+               }
+               else if ((c = (*from >> 16)))
+               {
+                       *to++ = c;
+                       *to++ = (*from >> 8) & 0xff;
+                       *to++ = *from & 0xff;
+                       cnt += 3;
+               }
+               else if ((c = (*from >> 8)))
+               {
+                       *to++ = c;
+                       *to++ = *from & 0xff;
+                       cnt += 2;
+               }
+               else
+               {
+                       *to++ = *from;
+                       cnt++;
+               }
+               from++;
+               len--;
+       }
+       *to = 0;
+       return cnt;
+}
+
+
+/*
+ * JOHAB
+ */
+static int
+pg_johab_mblen(const unsigned char *s)
+{
+       return pg_euc_mblen(s);
+}
+
+static int
+pg_johab_dsplen(const unsigned char *s)
+{
+       return pg_euc_dsplen(s);
+}
+
+/*
+ * convert UTF8 string to pg_wchar (UCS-4)
+ * caller must allocate enough space for "to", including a trailing zero!
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+       uint32          c1,
+                               c2,
+                               c3,
+                               c4;
+
+       while (len > 0 && *from)
+       {
+               if ((*from & 0x80) == 0)
+               {
+                       *to = *from++;
+                       len--;
+               }
+               else if ((*from & 0xe0) == 0xc0)
+               {
+                       if (len < 2)
+                               break;                  /* drop trailing incomplete char */
+                       c1 = *from++ & 0x1f;
+                       c2 = *from++ & 0x3f;
+                       *to = (c1 << 6) | c2;
+                       len -= 2;
+               }
+               else if ((*from & 0xf0) == 0xe0)
+               {
+                       if (len < 3)
+                               break;                  /* drop trailing incomplete char */
+                       c1 = *from++ & 0x0f;
+                       c2 = *from++ & 0x3f;
+                       c3 = *from++ & 0x3f;
+                       *to = (c1 << 12) | (c2 << 6) | c3;
+                       len -= 3;
+               }
+               else if ((*from & 0xf8) == 0xf0)
+               {
+                       if (len < 4)
+                               break;                  /* drop trailing incomplete char */
+                       c1 = *from++ & 0x07;
+                       c2 = *from++ & 0x3f;
+                       c3 = *from++ & 0x3f;
+                       c4 = *from++ & 0x3f;
+                       *to = (c1 << 18) | (c2 << 12) | (c3 << 6) | c4;
+                       len -= 4;
+               }
+               else
+               {
+                       /* treat a bogus char as length 1; not ours to raise error */
+                       *to = *from++;
+                       len--;
+               }
+               to++;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+
+/*
+ * Map a Unicode code point to UTF-8.  utf8string must have 4 bytes of
+ * space allocated.
+ */
+unsigned char *
+unicode_to_utf8(pg_wchar c, unsigned char *utf8string)
+{
+       if (c <= 0x7F)
+       {
+               utf8string[0] = c;
+       }
+       else if (c <= 0x7FF)
+       {
+               utf8string[0] = 0xC0 | ((c >> 6) & 0x1F);
+               utf8string[1] = 0x80 | (c & 0x3F);
+       }
+       else if (c <= 0xFFFF)
+       {
+               utf8string[0] = 0xE0 | ((c >> 12) & 0x0F);
+               utf8string[1] = 0x80 | ((c >> 6) & 0x3F);
+               utf8string[2] = 0x80 | (c & 0x3F);
+       }
+       else
+       {
+               utf8string[0] = 0xF0 | ((c >> 18) & 0x07);
+               utf8string[1] = 0x80 | ((c >> 12) & 0x3F);
+               utf8string[2] = 0x80 | ((c >> 6) & 0x3F);
+               utf8string[3] = 0x80 | (c & 0x3F);
+       }
+
+       return utf8string;
+}
+
+/*
+ * Trivial conversion from pg_wchar to UTF-8.
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2utf_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               int                     char_len;
+
+               unicode_to_utf8(*from, to);
+               char_len = pg_utf_mblen(to);
+               cnt += char_len;
+               to += char_len;
+               from++;
+               len--;
+       }
+       *to = 0;
+       return cnt;
+}
+
+/*
+ * Return the byte length of a UTF8 character pointed to by s
+ *
+ * Note: in the current implementation we do not support UTF8 sequences
+ * of more than 4 bytes; hence do NOT return a value larger than 4.
+ * We return "1" for any leading byte that is either flat-out illegal or
+ * indicates a length larger than we support.
+ *
+ * pg_utf2wchar_with_len(), utf8_to_unicode(), pg_utf8_islegal(), and perhaps
+ * other places would need to be fixed to change this.
+ */
+int
+pg_utf_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if ((*s & 0x80) == 0)
+               len = 1;
+       else if ((*s & 0xe0) == 0xc0)
+               len = 2;
+       else if ((*s & 0xf0) == 0xe0)
+               len = 3;
+       else if ((*s & 0xf8) == 0xf0)
+               len = 4;
+#ifdef NOT_USED
+       else if ((*s & 0xfc) == 0xf8)
+               len = 5;
+       else if ((*s & 0xfe) == 0xfc)
+               len = 6;
+#endif
+       else
+               len = 1;
+       return len;
+}
+
+/*
+ * This is an implementation of wcwidth() and wcswidth() as defined in
+ * "The Single UNIX Specification, Version 2, The Open Group, 1997"
+ * <http://www.UNIX-systems.org/online.html>
+ *
+ * Markus Kuhn -- 2001-09-08 -- public domain
+ *
+ * customised for PostgreSQL
+ *
+ * original available at : http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
+ */
+
+struct mbinterval
+{
+       unsigned short first;
+       unsigned short last;
+};
+
+/* auxiliary function for binary search in interval table */
+static int
+mbbisearch(pg_wchar ucs, const struct mbinterval *table, int max)
+{
+       int                     min = 0;
+       int                     mid;
+
+       if (ucs < table[0].first || ucs > table[max].last)
+               return 0;
+       while (max >= min)
+       {
+               mid = (min + max) / 2;
+               if (ucs > table[mid].last)
+                       min = mid + 1;
+               else if (ucs < table[mid].first)
+                       max = mid - 1;
+               else
+                       return 1;
+       }
+
+       return 0;
+}
+
+
+/* The following functions define the column width of an ISO 10646
+ * character as follows:
+ *
+ *       - The null character (U+0000) has a column width of 0.
+ *
+ *       - Other C0/C1 control characters and DEL will lead to a return
+ *             value of -1.
+ *
+ *       - Non-spacing and enclosing combining characters (general
+ *             category code Mn or Me in the Unicode database) have a
+ *             column width of 0.
+ *
+ *       - Other format characters (general category code Cf in the Unicode
+ *             database) and ZERO WIDTH SPACE (U+200B) have a column width of 0.
+ *
+ *       - Hangul Jamo medial vowels and final consonants (U+1160-U+11FF)
+ *             have a column width of 0.
+ *
+ *       - Spacing characters in the East Asian Wide (W) or East Asian
+ *             FullWidth (F) category as defined in Unicode Technical
+ *             Report #11 have a column width of 2.
+ *
+ *       - All remaining characters (including all printable
+ *             ISO 8859-1 and WGL4 characters, Unicode control characters,
+ *             etc.) have a column width of 1.
+ *
+ * This implementation assumes that wchar_t characters are encoded
+ * in ISO 10646.
+ */
+
+static int
+ucs_wcwidth(pg_wchar ucs)
+{
+       /* sorted list of non-overlapping intervals of non-spacing characters */
+       static const struct mbinterval combining[] = {
+               {0x0300, 0x034E}, {0x0360, 0x0362}, {0x0483, 0x0486},
+               {0x0488, 0x0489}, {0x0591, 0x05A1}, {0x05A3, 0x05B9},
+               {0x05BB, 0x05BD}, {0x05BF, 0x05BF}, {0x05C1, 0x05C2},
+               {0x05C4, 0x05C4}, {0x064B, 0x0655}, {0x0670, 0x0670},
+               {0x06D6, 0x06E4}, {0x06E7, 0x06E8}, {0x06EA, 0x06ED},
+               {0x070F, 0x070F}, {0x0711, 0x0711}, {0x0730, 0x074A},
+               {0x07A6, 0x07B0}, {0x0901, 0x0902}, {0x093C, 0x093C},
+               {0x0941, 0x0948}, {0x094D, 0x094D}, {0x0951, 0x0954},
+               {0x0962, 0x0963}, {0x0981, 0x0981}, {0x09BC, 0x09BC},
+               {0x09C1, 0x09C4}, {0x09CD, 0x09CD}, {0x09E2, 0x09E3},
+               {0x0A02, 0x0A02}, {0x0A3C, 0x0A3C}, {0x0A41, 0x0A42},
+               {0x0A47, 0x0A48}, {0x0A4B, 0x0A4D}, {0x0A70, 0x0A71},
+               {0x0A81, 0x0A82}, {0x0ABC, 0x0ABC}, {0x0AC1, 0x0AC5},
+               {0x0AC7, 0x0AC8}, {0x0ACD, 0x0ACD}, {0x0B01, 0x0B01},
+               {0x0B3C, 0x0B3C}, {0x0B3F, 0x0B3F}, {0x0B41, 0x0B43},
+               {0x0B4D, 0x0B4D}, {0x0B56, 0x0B56}, {0x0B82, 0x0B82},
+               {0x0BC0, 0x0BC0}, {0x0BCD, 0x0BCD}, {0x0C3E, 0x0C40},
+               {0x0C46, 0x0C48}, {0x0C4A, 0x0C4D}, {0x0C55, 0x0C56},
+               {0x0CBF, 0x0CBF}, {0x0CC6, 0x0CC6}, {0x0CCC, 0x0CCD},
+               {0x0D41, 0x0D43}, {0x0D4D, 0x0D4D}, {0x0DCA, 0x0DCA},
+               {0x0DD2, 0x0DD4}, {0x0DD6, 0x0DD6}, {0x0E31, 0x0E31},
+               {0x0E34, 0x0E3A}, {0x0E47, 0x0E4E}, {0x0EB1, 0x0EB1},
+               {0x0EB4, 0x0EB9}, {0x0EBB, 0x0EBC}, {0x0EC8, 0x0ECD},
+               {0x0F18, 0x0F19}, {0x0F35, 0x0F35}, {0x0F37, 0x0F37},
+               {0x0F39, 0x0F39}, {0x0F71, 0x0F7E}, {0x0F80, 0x0F84},
+               {0x0F86, 0x0F87}, {0x0F90, 0x0F97}, {0x0F99, 0x0FBC},
+               {0x0FC6, 0x0FC6}, {0x102D, 0x1030}, {0x1032, 0x1032},
+               {0x1036, 0x1037}, {0x1039, 0x1039}, {0x1058, 0x1059},
+               {0x1160, 0x11FF}, {0x17B7, 0x17BD}, {0x17C6, 0x17C6},
+               {0x17C9, 0x17D3}, {0x180B, 0x180E}, {0x18A9, 0x18A9},
+               {0x200B, 0x200F}, {0x202A, 0x202E}, {0x206A, 0x206F},
+               {0x20D0, 0x20E3}, {0x302A, 0x302F}, {0x3099, 0x309A},
+               {0xFB1E, 0xFB1E}, {0xFE20, 0xFE23}, {0xFEFF, 0xFEFF},
+               {0xFFF9, 0xFFFB}
+       };
+
+       /* test for 8-bit control characters */
+       if (ucs == 0)
+               return 0;
+
+       if (ucs < 0x20 || (ucs >= 0x7f && ucs < 0xa0) || ucs > 0x0010ffff)
+               return -1;
+
+       /* binary search in table of non-spacing characters */
+       if (mbbisearch(ucs, combining,
+                                  sizeof(combining) / sizeof(struct mbinterval) - 1))
+               return 0;
+
+       /*
+        * if we arrive here, ucs is not a combining or C0/C1 control character
+        */
+
+       return 1 +
+               (ucs >= 0x1100 &&
+                (ucs <= 0x115f ||              /* Hangul Jamo init. consonants */
+                 (ucs >= 0x2e80 && ucs <= 0xa4cf && (ucs & ~0x0011) != 0x300a &&
+                  ucs != 0x303f) ||    /* CJK ... Yi */
+                 (ucs >= 0xac00 && ucs <= 0xd7a3) ||   /* Hangul Syllables */
+                 (ucs >= 0xf900 && ucs <= 0xfaff) ||   /* CJK Compatibility
+                                                                                                * Ideographs */
+                 (ucs >= 0xfe30 && ucs <= 0xfe6f) ||   /* CJK Compatibility Forms */
+                 (ucs >= 0xff00 && ucs <= 0xff5f) ||   /* Fullwidth Forms */
+                 (ucs >= 0xffe0 && ucs <= 0xffe6) ||
+                 (ucs >= 0x20000 && ucs <= 0x2ffff)));
+}
+
+/*
+ * Convert a UTF-8 character to a Unicode code point.
+ * This is a one-character version of pg_utf2wchar_with_len.
+ *
+ * No error checks here, c must point to a long-enough string.
+ */
+pg_wchar
+utf8_to_unicode(const unsigned char *c)
+{
+       if ((*c & 0x80) == 0)
+               return (pg_wchar) c[0];
+       else if ((*c & 0xe0) == 0xc0)
+               return (pg_wchar) (((c[0] & 0x1f) << 6) |
+                                                  (c[1] & 0x3f));
+       else if ((*c & 0xf0) == 0xe0)
+               return (pg_wchar) (((c[0] & 0x0f) << 12) |
+                                                  ((c[1] & 0x3f) << 6) |
+                                                  (c[2] & 0x3f));
+       else if ((*c & 0xf8) == 0xf0)
+               return (pg_wchar) (((c[0] & 0x07) << 18) |
+                                                  ((c[1] & 0x3f) << 12) |
+                                                  ((c[2] & 0x3f) << 6) |
+                                                  (c[3] & 0x3f));
+       else
+               /* that is an invalid code on purpose */
+               return 0xffffffff;
+}
+
+static int
+pg_utf_dsplen(const unsigned char *s)
+{
+       return ucs_wcwidth(utf8_to_unicode(s));
+}
+
+/*
+ * convert mule internal code to pg_wchar
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_mule2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               if (IS_LC1(*from) && len >= 2)
+               {
+                       *to = *from++ << 16;
+                       *to |= *from++;
+                       len -= 2;
+               }
+               else if (IS_LCPRV1(*from) && len >= 3)
+               {
+                       from++;
+                       *to = *from++ << 16;
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (IS_LC2(*from) && len >= 3)
+               {
+                       *to = *from++ << 16;
+                       *to |= *from++ << 8;
+                       *to |= *from++;
+                       len -= 3;
+               }
+               else if (IS_LCPRV2(*from) && len >= 4)
+               {
+                       from++;
+                       *to = *from++ << 16;
+                       *to |= *from++ << 8;
+                       *to |= *from++;
+                       len -= 4;
+               }
+               else
+               {                                               /* assume ASCII */
+                       *to = (unsigned char) *from++;
+                       len--;
+               }
+               to++;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+/*
+ * convert pg_wchar to mule internal code
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2mule_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               unsigned char lb;
+
+               lb = (*from >> 16) & 0xff;
+               if (IS_LC1(lb))
+               {
+                       *to++ = lb;
+                       *to++ = *from & 0xff;
+                       cnt += 2;
+               }
+               else if (IS_LC2(lb))
+               {
+                       *to++ = lb;
+                       *to++ = (*from >> 8) & 0xff;
+                       *to++ = *from & 0xff;
+                       cnt += 3;
+               }
+               else if (IS_LCPRV1_A_RANGE(lb))
+               {
+                       *to++ = LCPRV1_A;
+                       *to++ = lb;
+                       *to++ = *from & 0xff;
+                       cnt += 3;
+               }
+               else if (IS_LCPRV1_B_RANGE(lb))
+               {
+                       *to++ = LCPRV1_B;
+                       *to++ = lb;
+                       *to++ = *from & 0xff;
+                       cnt += 3;
+               }
+               else if (IS_LCPRV2_A_RANGE(lb))
+               {
+                       *to++ = LCPRV2_A;
+                       *to++ = lb;
+                       *to++ = (*from >> 8) & 0xff;
+                       *to++ = *from & 0xff;
+                       cnt += 4;
+               }
+               else if (IS_LCPRV2_B_RANGE(lb))
+               {
+                       *to++ = LCPRV2_B;
+                       *to++ = lb;
+                       *to++ = (*from >> 8) & 0xff;
+                       *to++ = *from & 0xff;
+                       cnt += 4;
+               }
+               else
+               {
+                       *to++ = *from & 0xff;
+                       cnt += 1;
+               }
+               from++;
+               len--;
+       }
+       *to = 0;
+       return cnt;
+}
+
+int
+pg_mule_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_LC1(*s))
+               len = 2;
+       else if (IS_LCPRV1(*s))
+               len = 3;
+       else if (IS_LC2(*s))
+               len = 3;
+       else if (IS_LCPRV2(*s))
+               len = 4;
+       else
+               len = 1;                                /* assume ASCII */
+       return len;
+}
+
+static int
+pg_mule_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       /*
+        * Note: it's not really appropriate to assume that all multibyte charsets
+        * are double-wide on screen.  But this seems an okay approximation for
+        * the MULE charsets we currently support.
+        */
+
+       if (IS_LC1(*s))
+               len = 1;
+       else if (IS_LCPRV1(*s))
+               len = 1;
+       else if (IS_LC2(*s))
+               len = 2;
+       else if (IS_LCPRV2(*s))
+               len = 2;
+       else
+               len = 1;                                /* assume ASCII */
+
+       return len;
+}
+
+/*
+ * ISO8859-1
+ */
+static int
+pg_latin12wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               *to++ = *from++;
+               len--;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+/*
+ * Trivial conversion from pg_wchar to single byte encoding. Just ignores
+ * high bits.
+ * caller should allocate enough space for "to"
+ * len: length of from.
+ * "from" not necessarily null terminated.
+ */
+static int
+pg_wchar2single_with_len(const pg_wchar *from, unsigned char *to, int len)
+{
+       int                     cnt = 0;
+
+       while (len > 0 && *from)
+       {
+               *to++ = *from++;
+               len--;
+               cnt++;
+       }
+       *to = 0;
+       return cnt;
+}
+
+static int
+pg_latin1_mblen(const unsigned char *s)
+{
+       return 1;
+}
+
+static int
+pg_latin1_dsplen(const unsigned char *s)
+{
+       return pg_ascii_dsplen(s);
+}
+
+/*
+ * SJIS
+ */
+static int
+pg_sjis_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s >= 0xa1 && *s <= 0xdf)
+               len = 1;                                /* 1 byte kana? */
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = 1;                                /* should be ASCII */
+       return len;
+}
+
+static int
+pg_sjis_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (*s >= 0xa1 && *s <= 0xdf)
+               len = 1;                                /* 1 byte kana? */
+       else if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = pg_ascii_dsplen(s);       /* should be ASCII */
+       return len;
+}
+
+/*
+ * Big5
+ */
+static int
+pg_big5_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = 1;                                /* should be ASCII */
+       return len;
+}
+
+static int
+pg_big5_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = pg_ascii_dsplen(s);       /* should be ASCII */
+       return len;
+}
+
+/*
+ * GBK
+ */
+static int
+pg_gbk_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = 1;                                /* should be ASCII */
+       return len;
+}
+
+static int
+pg_gbk_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* kanji? */
+       else
+               len = pg_ascii_dsplen(s);       /* should be ASCII */
+       return len;
+}
+
+/*
+ * UHC
+ */
+static int
+pg_uhc_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* 2byte? */
+       else
+               len = 1;                                /* should be ASCII */
+       return len;
+}
+
+static int
+pg_uhc_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;                                /* 2byte? */
+       else
+               len = pg_ascii_dsplen(s);       /* should be ASCII */
+       return len;
+}
+
+/*
+ * GB18030
+ *     Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp>
+ */
+static int
+pg_gb18030_mblen(const unsigned char *s)
+{
+       int                     len;
+
+       if (!IS_HIGHBIT_SET(*s))
+               len = 1;                                /* ASCII */
+       else if (*(s + 1) >= 0x30 && *(s + 1) <= 0x39)
+               len = 4;
+       else
+               len = 2;
+       return len;
+}
+
+static int
+pg_gb18030_dsplen(const unsigned char *s)
+{
+       int                     len;
+
+       if (IS_HIGHBIT_SET(*s))
+               len = 2;
+       else
+               len = pg_ascii_dsplen(s);       /* ASCII */
+       return len;
+}
+
+/*
+ *-------------------------------------------------------------------
+ * multibyte sequence validators
+ *
+ * These functions accept "s", a pointer to the first byte of a string,
+ * and "len", the remaining length of the string.  If there is a validly
+ * encoded character beginning at *s, return its length in bytes; else
+ * return -1.
+ *
+ * The functions can assume that len > 0 and that *s != '\0', but they must
+ * test for and reject zeroes in any additional bytes of a multibyte character.
+ *
+ * Note that this definition allows the function for a single-byte
+ * encoding to be just "return 1".
+ *-------------------------------------------------------------------
+ */
+
+static int
+pg_ascii_verifier(const unsigned char *s, int len)
+{
+       return 1;
+}
+
+#define IS_EUC_RANGE_VALID(c)  ((c) >= 0xa1 && (c) <= 0xfe)
+
+static int
+pg_eucjp_verifier(const unsigned char *s, int len)
+{
+       int                     l;
+       unsigned char c1,
+                               c2;
+
+       c1 = *s++;
+
+       switch (c1)
+       {
+               case SS2:                               /* JIS X 0201 */
+                       l = 2;
+                       if (l > len)
+                               return -1;
+                       c2 = *s++;
+                       if (c2 < 0xa1 || c2 > 0xdf)
+                               return -1;
+                       break;
+
+               case SS3:                               /* JIS X 0212 */
+                       l = 3;
+                       if (l > len)
+                               return -1;
+                       c2 = *s++;
+                       if (!IS_EUC_RANGE_VALID(c2))
+                               return -1;
+                       c2 = *s++;
+                       if (!IS_EUC_RANGE_VALID(c2))
+                               return -1;
+                       break;
+
+               default:
+                       if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
+                       {
+                               l = 2;
+                               if (l > len)
+                                       return -1;
+                               if (!IS_EUC_RANGE_VALID(c1))
+                                       return -1;
+                               c2 = *s++;
+                               if (!IS_EUC_RANGE_VALID(c2))
+                                       return -1;
+                       }
+                       else
+                               /* must be ASCII */
+                       {
+                               l = 1;
+                       }
+                       break;
+       }
+
+       return l;
+}
+
+static int
+pg_euckr_verifier(const unsigned char *s, int len)
+{
+       int                     l;
+       unsigned char c1,
+                               c2;
+
+       c1 = *s++;
+
+       if (IS_HIGHBIT_SET(c1))
+       {
+               l = 2;
+               if (l > len)
+                       return -1;
+               if (!IS_EUC_RANGE_VALID(c1))
+                       return -1;
+               c2 = *s++;
+               if (!IS_EUC_RANGE_VALID(c2))
+                       return -1;
+       }
+       else
+               /* must be ASCII */
+       {
+               l = 1;
+       }
+
+       return l;
+}
+
+/* EUC-CN byte sequences are exactly same as EUC-KR */
+#define pg_euccn_verifier      pg_euckr_verifier
+
+static int
+pg_euctw_verifier(const unsigned char *s, int len)
+{
+       int                     l;
+       unsigned char c1,
+                               c2;
+
+       c1 = *s++;
+
+       switch (c1)
+       {
+               case SS2:                               /* CNS 11643 Plane 1-7 */
+                       l = 4;
+                       if (l > len)
+                               return -1;
+                       c2 = *s++;
+                       if (c2 < 0xa1 || c2 > 0xa7)
+                               return -1;
+                       c2 = *s++;
+                       if (!IS_EUC_RANGE_VALID(c2))
+                               return -1;
+                       c2 = *s++;
+                       if (!IS_EUC_RANGE_VALID(c2))
+                               return -1;
+                       break;
+
+               case SS3:                               /* unused */
+                       return -1;
+
+               default:
+                       if (IS_HIGHBIT_SET(c1)) /* CNS 11643 Plane 1 */
+                       {
+                               l = 2;
+                               if (l > len)
+                                       return -1;
+                               /* no further range check on c1? */
+                               c2 = *s++;
+                               if (!IS_EUC_RANGE_VALID(c2))
+                                       return -1;
+                       }
+                       else
+                               /* must be ASCII */
+                       {
+                               l = 1;
+                       }
+                       break;
+       }
+       return l;
+}
+
+static int
+pg_johab_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+       unsigned char c;
+
+       l = mbl = pg_johab_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       if (!IS_HIGHBIT_SET(*s))
+               return mbl;
+
+       while (--l > 0)
+       {
+               c = *++s;
+               if (!IS_EUC_RANGE_VALID(c))
+                       return -1;
+       }
+       return mbl;
+}
+
+static int
+pg_mule_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+       unsigned char c;
+
+       l = mbl = pg_mule_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       while (--l > 0)
+       {
+               c = *++s;
+               if (!IS_HIGHBIT_SET(c))
+                       return -1;
+       }
+       return mbl;
+}
+
+static int
+pg_latin1_verifier(const unsigned char *s, int len)
+{
+       return 1;
+}
+
+static int
+pg_sjis_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+       unsigned char c1,
+                               c2;
+
+       l = mbl = pg_sjis_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       if (l == 1)                                     /* pg_sjis_mblen already verified it */
+               return mbl;
+
+       c1 = *s++;
+       c2 = *s;
+       if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
+               return -1;
+       return mbl;
+}
+
+static int
+pg_big5_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+
+       l = mbl = pg_big5_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       while (--l > 0)
+       {
+               if (*++s == '\0')
+                       return -1;
+       }
+
+       return mbl;
+}
+
+static int
+pg_gbk_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+
+       l = mbl = pg_gbk_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       while (--l > 0)
+       {
+               if (*++s == '\0')
+                       return -1;
+       }
+
+       return mbl;
+}
+
+static int
+pg_uhc_verifier(const unsigned char *s, int len)
+{
+       int                     l,
+                               mbl;
+
+       l = mbl = pg_uhc_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       while (--l > 0)
+       {
+               if (*++s == '\0')
+                       return -1;
+       }
+
+       return mbl;
+}
+
+static int
+pg_gb18030_verifier(const unsigned char *s, int len)
+{
+       int                     l;
+
+       if (!IS_HIGHBIT_SET(*s))
+               l = 1;                                  /* ASCII */
+       else if (len >= 4 && *(s + 1) >= 0x30 && *(s + 1) <= 0x39)
+       {
+               /* Should be 4-byte, validate remaining bytes */
+               if (*s >= 0x81 && *s <= 0xfe &&
+                       *(s + 2) >= 0x81 && *(s + 2) <= 0xfe &&
+                       *(s + 3) >= 0x30 && *(s + 3) <= 0x39)
+                       l = 4;
+               else
+                       l = -1;
+       }
+       else if (len >= 2 && *s >= 0x81 && *s <= 0xfe)
+       {
+               /* Should be 2-byte, validate */
+               if ((*(s + 1) >= 0x40 && *(s + 1) <= 0x7e) ||
+                       (*(s + 1) >= 0x80 && *(s + 1) <= 0xfe))
+                       l = 2;
+               else
+                       l = -1;
+       }
+       else
+               l = -1;
+       return l;
+}
+
+static int
+pg_utf8_verifier(const unsigned char *s, int len)
+{
+       int                     l = pg_utf_mblen(s);
+
+       if (len < l)
+               return -1;
+
+       if (!pg_utf8_islegal(s, l))
+               return -1;
+
+       return l;
+}
+
+/*
+ * Check for validity of a single UTF-8 encoded character
+ *
+ * This directly implements the rules in RFC3629.  The bizarre-looking
+ * restrictions on the second byte are meant to ensure that there isn't
+ * more than one encoding of a given Unicode character point; that is,
+ * you may not use a longer-than-necessary byte sequence with high order
+ * zero bits to represent a character that would fit in fewer bytes.
+ * To do otherwise is to create security hazards (eg, create an apparent
+ * non-ASCII character that decodes to plain ASCII).
+ *
+ * length is assumed to have been obtained by pg_utf_mblen(), and the
+ * caller must have checked that that many bytes are present in the buffer.
+ */
+bool
+pg_utf8_islegal(const unsigned char *source, int length)
+{
+       unsigned char a;
+
+       switch (length)
+       {
+               default:
+                       /* reject lengths 5 and 6 for now */
+                       return false;
+               case 4:
+                       a = source[3];
+                       if (a < 0x80 || a > 0xBF)
+                               return false;
+                       /* FALL THRU */
+               case 3:
+                       a = source[2];
+                       if (a < 0x80 || a > 0xBF)
+                               return false;
+                       /* FALL THRU */
+               case 2:
+                       a = source[1];
+                       switch (*source)
+                       {
+                               case 0xE0:
+                                       if (a < 0xA0 || a > 0xBF)
+                                               return false;
+                                       break;
+                               case 0xED:
+                                       if (a < 0x80 || a > 0x9F)
+                                               return false;
+                                       break;
+                               case 0xF0:
+                                       if (a < 0x90 || a > 0xBF)
+                                               return false;
+                                       break;
+                               case 0xF4:
+                                       if (a < 0x80 || a > 0x8F)
+                                               return false;
+                                       break;
+                               default:
+                                       if (a < 0x80 || a > 0xBF)
+                                               return false;
+                                       break;
+                       }
+                       /* FALL THRU */
+               case 1:
+                       a = *source;
+                       if (a >= 0x80 && a < 0xC2)
+                               return false;
+                       if (a > 0xF4)
+                               return false;
+                       break;
+       }
+       return true;
+}
+
+#ifndef FRONTEND
+
+/*
+ * Generic character incrementer function.
+ *
+ * Not knowing anything about the properties of the encoding in use, we just
+ * keep incrementing the last byte until we get a validly-encoded result,
+ * or we run out of values to try.  We don't bother to try incrementing
+ * higher-order bytes, so there's no growth in runtime for wider characters.
+ * (If we did try to do that, we'd need to consider the likelihood that 255
+ * is not a valid final byte in the encoding.)
+ */
+static bool
+pg_generic_charinc(unsigned char *charptr, int len)
+{
+       unsigned char *lastbyte = charptr + len - 1;
+       mbverifier      mbverify;
+
+       /* We can just invoke the character verifier directly. */
+       mbverify = pg_wchar_table[GetDatabaseEncoding()].mbverify;
+
+       while (*lastbyte < (unsigned char) 255)
+       {
+               (*lastbyte)++;
+               if ((*mbverify) (charptr, len) == len)
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * UTF-8 character incrementer function.
+ *
+ * For a one-byte character less than 0x7F, we just increment the byte.
+ *
+ * For a multibyte character, every byte but the first must fall between 0x80
+ * and 0xBF; and the first byte must be between 0xC0 and 0xF4.  We increment
+ * the last byte that's not already at its maximum value.  If we can't find a
+ * byte that's less than the maximum allowable value, we simply fail.  We also
+ * need some special-case logic to skip regions used for surrogate pair
+ * handling, as those should not occur in valid UTF-8.
+ *
+ * Note that we don't reset lower-order bytes back to their minimums, since
+ * we can't afford to make an exhaustive search (see make_greater_string).
+ */
+static bool
+pg_utf8_increment(unsigned char *charptr, int length)
+{
+       unsigned char a;
+       unsigned char limit;
+
+       switch (length)
+       {
+               default:
+                       /* reject lengths 5 and 6 for now */
+                       return false;
+               case 4:
+                       a = charptr[3];
+                       if (a < 0xBF)
+                       {
+                               charptr[3]++;
+                               break;
+                       }
+                       /* FALL THRU */
+               case 3:
+                       a = charptr[2];
+                       if (a < 0xBF)
+                       {
+                               charptr[2]++;
+                               break;
+                       }
+                       /* FALL THRU */
+               case 2:
+                       a = charptr[1];
+                       switch (*charptr)
+                       {
+                               case 0xED:
+                                       limit = 0x9F;
+                                       break;
+                               case 0xF4:
+                                       limit = 0x8F;
+                                       break;
+                               default:
+                                       limit = 0xBF;
+                                       break;
+                       }
+                       if (a < limit)
+                       {
+                               charptr[1]++;
+                               break;
+                       }
+                       /* FALL THRU */
+               case 1:
+                       a = *charptr;
+                       if (a == 0x7F || a == 0xDF || a == 0xEF || a == 0xF4)
+                               return false;
+                       charptr[0]++;
+                       break;
+       }
+
+       return true;
+}
+
+/*
+ * EUC-JP character incrementer function.
+ *
+ * If the sequence starts with SS2 (0x8e), it must be a two-byte sequence
+ * representing JIS X 0201 characters with the second byte ranging between
+ * 0xa1 and 0xdf.  We just increment the last byte if it's less than 0xdf,
+ * and otherwise rewrite the whole sequence to 0xa1 0xa1.
+ *
+ * If the sequence starts with SS3 (0x8f), it must be a three-byte sequence
+ * in which the last two bytes range between 0xa1 and 0xfe.  The last byte
+ * is incremented if possible, otherwise the second-to-last byte.
+ *
+ * If the sequence starts with a value other than the above and its MSB
+ * is set, it must be a two-byte sequence representing JIS X 0208 characters
+ * with both bytes ranging between 0xa1 and 0xfe.  The last byte is
+ * incremented if possible, otherwise the second-to-last byte.
+ *
+ * Otherwise, the sequence is a single-byte ASCII character. It is
+ * incremented up to 0x7f.
+ */
+static bool
+pg_eucjp_increment(unsigned char *charptr, int length)
+{
+       unsigned char c1,
+                               c2;
+       int                     i;
+
+       c1 = *charptr;
+
+       switch (c1)
+       {
+               case SS2:                               /* JIS X 0201 */
+                       if (length != 2)
+                               return false;
+
+                       c2 = charptr[1];
+
+                       if (c2 >= 0xdf)
+                               charptr[0] = charptr[1] = 0xa1;
+                       else if (c2 < 0xa1)
+                               charptr[1] = 0xa1;
+                       else
+                               charptr[1]++;
+                       break;
+
+               case SS3:                               /* JIS X 0212 */
+                       if (length != 3)
+                               return false;
+
+                       for (i = 2; i > 0; i--)
+                       {
+                               c2 = charptr[i];
+                               if (c2 < 0xa1)
+                               {
+                                       charptr[i] = 0xa1;
+                                       return true;
+                               }
+                               else if (c2 < 0xfe)
+                               {
+                                       charptr[i]++;
+                                       return true;
+                               }
+                       }
+
+                       /* Out of 3-byte code region */
+                       return false;
+
+               default:
+                       if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
+                       {
+                               if (length != 2)
+                                       return false;
+
+                               for (i = 1; i >= 0; i--)
+                               {
+                                       c2 = charptr[i];
+                                       if (c2 < 0xa1)
+                                       {
+                                               charptr[i] = 0xa1;
+                                               return true;
+                                       }
+                                       else if (c2 < 0xfe)
+                                       {
+                                               charptr[i]++;
+                                               return true;
+                                       }
+                               }
+
+                               /* Out of 2 byte code region */
+                               return false;
+                       }
+                       else
+                       {                                       /* ASCII, single byte */
+                               if (c1 > 0x7e)
+                                       return false;
+                               (*charptr)++;
+                       }
+                       break;
+       }
+
+       return true;
+}
+#endif                                                 /* !FRONTEND */
+
+
+/*
+ *-------------------------------------------------------------------
+ * encoding info table
+ * XXX must be sorted by the same order as enum pg_enc (in mb/pg_wchar.h)
+ *-------------------------------------------------------------------
+ */
+const pg_wchar_tbl pg_wchar_table[] = {
+       {pg_ascii2wchar_with_len, pg_wchar2single_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifier, 1}, /* PG_SQL_ASCII */
+       {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3},        /* PG_EUC_JP */
+       {pg_euccn2wchar_with_len, pg_wchar2euc_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifier, 2},        /* PG_EUC_CN */
+       {pg_euckr2wchar_with_len, pg_wchar2euc_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifier, 3},        /* PG_EUC_KR */
+       {pg_euctw2wchar_with_len, pg_wchar2euc_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifier, 4},        /* PG_EUC_TW */
+       {pg_eucjp2wchar_with_len, pg_wchar2euc_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3},        /* PG_EUC_JIS_2004 */
+       {pg_utf2wchar_with_len, pg_wchar2utf_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifier, 4},       /* PG_UTF8 */
+       {pg_mule2wchar_with_len, pg_wchar2mule_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifier, 4},   /* PG_MULE_INTERNAL */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN1 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN2 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN3 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN4 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN5 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN6 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN7 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN8 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN9 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_LATIN10 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1256 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1258 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN866 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN874 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8R */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1251 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1252 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-5 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-6 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-7 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* ISO-8859-8 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1250 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1253 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1254 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1255 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_WIN1257 */
+       {pg_latin12wchar_with_len, pg_wchar2single_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* PG_KOI8U */
+       {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}, /* PG_SJIS */
+       {0, 0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifier, 2}, /* PG_BIG5 */
+       {0, 0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifier, 2},        /* PG_GBK */
+       {0, 0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifier, 2},        /* PG_UHC */
+       {0, 0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifier, 4},    /* PG_GB18030 */
+       {0, 0, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifier, 3},  /* PG_JOHAB */
+       {0, 0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}      /* PG_SHIFT_JIS_2004 */
+};
+
+/* returns the byte length of a word for mule internal code */
+int
+pg_mic_mblen(const unsigned char *mbstr)
+{
+       return pg_mule_mblen(mbstr);
+}
+
+/*
+ * Returns the byte length of a multibyte character.
+ */
+int
+pg_encoding_mblen(int encoding, const char *mbstr)
+{
+       return (PG_VALID_ENCODING(encoding) ?
+                       pg_wchar_table[encoding].mblen((const unsigned char *) mbstr) :
+                       pg_wchar_table[PG_SQL_ASCII].mblen((const unsigned char *) mbstr));
+}
+
+/*
+ * Returns the display length of a multibyte character.
+ */
+int
+pg_encoding_dsplen(int encoding, const char *mbstr)
+{
+       return (PG_VALID_ENCODING(encoding) ?
+                       pg_wchar_table[encoding].dsplen((const unsigned char *) mbstr) :
+                       pg_wchar_table[PG_SQL_ASCII].dsplen((const unsigned char *) mbstr));
+}
+
+/*
+ * Verify the first multibyte character of the given string.
+ * Return its byte length if good, -1 if bad.  (See comments above for
+ * full details of the mbverify API.)
+ */
+int
+pg_encoding_verifymb(int encoding, const char *mbstr, int len)
+{
+       return (PG_VALID_ENCODING(encoding) ?
+                       pg_wchar_table[encoding].mbverify((const unsigned char *) mbstr, len) :
+                       pg_wchar_table[PG_SQL_ASCII].mbverify((const unsigned char *) mbstr, len));
+}
+
+/*
+ * fetch maximum length of a given encoding
+ */
+int
+pg_encoding_max_length(int encoding)
+{
+       Assert(PG_VALID_ENCODING(encoding));
+
+       return pg_wchar_table[encoding].maxmblen;
+}
+
+#ifndef FRONTEND
+
+/*
+ * fetch maximum length of the encoding for the current database
+ */
+int
+pg_database_encoding_max_length(void)
+{
+       return pg_wchar_table[GetDatabaseEncoding()].maxmblen;
+}
+
+/*
+ * get the character incrementer for the encoding for the current database
+ */
+mbcharacter_incrementer
+pg_database_encoding_character_incrementer(void)
+{
+       /*
+        * Eventually it might be best to add a field to pg_wchar_table[], but for
+        * now we just use a switch.
+        */
+       switch (GetDatabaseEncoding())
+       {
+               case PG_UTF8:
+                       return pg_utf8_increment;
+
+               case PG_EUC_JP:
+                       return pg_eucjp_increment;
+
+               default:
+                       return pg_generic_charinc;
+       }
+}
+
+/*
+ * Verify mbstr to make sure that it is validly encoded in the current
+ * database encoding.  Otherwise same as pg_verify_mbstr().
+ */
+bool
+pg_verifymbstr(const char *mbstr, int len, bool noError)
+{
+       return
+               pg_verify_mbstr_len(GetDatabaseEncoding(), mbstr, len, noError) >= 0;
+}
+
+/*
+ * Verify mbstr to make sure that it is validly encoded in the specified
+ * encoding.
+ */
+bool
+pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
+{
+       return pg_verify_mbstr_len(encoding, mbstr, len, noError) >= 0;
+}
+
+/*
+ * Verify mbstr to make sure that it is validly encoded in the specified
+ * encoding.
+ *
+ * mbstr is not necessarily zero terminated; length of mbstr is
+ * specified by len.
+ *
+ * If OK, return length of string in the encoding.
+ * If a problem is found, return -1 when noError is
+ * true; when noError is false, ereport() a descriptive message.
+ */
+int
+pg_verify_mbstr_len(int encoding, const char *mbstr, int len, bool noError)
+{
+       mbverifier      mbverify;
+       int                     mb_len;
+
+       Assert(PG_VALID_ENCODING(encoding));
+
+       /*
+        * In single-byte encodings, we need only reject nulls (\0).
+        */
+       if (pg_encoding_max_length(encoding) <= 1)
+       {
+               const char *nullpos = memchr(mbstr, 0, len);
+
+               if (nullpos == NULL)
+                       return len;
+               if (noError)
+                       return -1;
+               report_invalid_encoding(encoding, nullpos, 1);
+       }
+
+       /* fetch function pointer just once */
+       mbverify = pg_wchar_table[encoding].mbverify;
+
+       mb_len = 0;
+
+       while (len > 0)
+       {
+               int                     l;
+
+               /* fast path for ASCII-subset characters */
+               if (!IS_HIGHBIT_SET(*mbstr))
+               {
+                       if (*mbstr != '\0')
+                       {
+                               mb_len++;
+                               mbstr++;
+                               len--;
+                               continue;
+                       }
+                       if (noError)
+                               return -1;
+                       report_invalid_encoding(encoding, mbstr, len);
+               }
+
+               l = (*mbverify) ((const unsigned char *) mbstr, len);
+
+               if (l < 0)
+               {
+                       if (noError)
+                               return -1;
+                       report_invalid_encoding(encoding, mbstr, len);
+               }
+
+               mbstr += l;
+               len -= l;
+               mb_len++;
+       }
+       return mb_len;
+}
+
+/*
+ * check_encoding_conversion_args: check arguments of a conversion function
+ *
+ * "expected" arguments can be either an encoding ID or -1 to indicate that
+ * the caller will check whether it accepts the ID.
+ *
+ * Note: the errors here are not really user-facing, so elog instead of
+ * ereport seems sufficient.  Also, we trust that the "expected" encoding
+ * arguments are valid encoding IDs, but we don't trust the actuals.
+ */
+void
+check_encoding_conversion_args(int src_encoding,
+                                                          int dest_encoding,
+                                                          int len,
+                                                          int expected_src_encoding,
+                                                          int expected_dest_encoding)
+{
+       if (!PG_VALID_ENCODING(src_encoding))
+               elog(ERROR, "invalid source encoding ID: %d", src_encoding);
+       if (src_encoding != expected_src_encoding && expected_src_encoding >= 0)
+               elog(ERROR, "expected source encoding \"%s\", but got \"%s\"",
+                        pg_enc2name_tbl[expected_src_encoding].name,
+                        pg_enc2name_tbl[src_encoding].name);
+       if (!PG_VALID_ENCODING(dest_encoding))
+               elog(ERROR, "invalid destination encoding ID: %d", dest_encoding);
+       if (dest_encoding != expected_dest_encoding && expected_dest_encoding >= 0)
+               elog(ERROR, "expected destination encoding \"%s\", but got \"%s\"",
+                        pg_enc2name_tbl[expected_dest_encoding].name,
+                        pg_enc2name_tbl[dest_encoding].name);
+       if (len < 0)
+               elog(ERROR, "encoding conversion length must not be negative");
+}
+
+/*
+ * report_invalid_encoding: complain about invalid multibyte character
+ *
+ * note: len is remaining length of string, not length of character;
+ * len must be greater than zero, as we always examine the first byte.
+ */
+void
+report_invalid_encoding(int encoding, const char *mbstr, int len)
+{
+       int                     l = pg_encoding_mblen(encoding, mbstr);
+       char            buf[8 * 5 + 1];
+       char       *p = buf;
+       int                     j,
+                               jlimit;
+
+       jlimit = Min(l, len);
+       jlimit = Min(jlimit, 8);        /* prevent buffer overrun */
+
+       for (j = 0; j < jlimit; j++)
+       {
+               p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
+               if (j < jlimit - 1)
+                       p += sprintf(p, " ");
+       }
+
+       ereport(ERROR,
+                       (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
+                        errmsg("invalid byte sequence for encoding \"%s\": %s",
+                                       pg_enc2name_tbl[encoding].name,
+                                       buf)));
+}
+
+/*
+ * report_untranslatable_char: complain about untranslatable character
+ *
+ * note: len is remaining length of string, not length of character;
+ * len must be greater than zero, as we always examine the first byte.
+ */
+void
+report_untranslatable_char(int src_encoding, int dest_encoding,
+                                                  const char *mbstr, int len)
+{
+       int                     l = pg_encoding_mblen(src_encoding, mbstr);
+       char            buf[8 * 5 + 1];
+       char       *p = buf;
+       int                     j,
+                               jlimit;
+
+       jlimit = Min(l, len);
+       jlimit = Min(jlimit, 8);        /* prevent buffer overrun */
+
+       for (j = 0; j < jlimit; j++)
+       {
+               p += sprintf(p, "0x%02x", (unsigned char) mbstr[j]);
+               if (j < jlimit - 1)
+                       p += sprintf(p, " ");
+       }
+
+       ereport(ERROR,
+                       (errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
+                        errmsg("character with byte sequence %s in encoding \"%s\" has no equivalent in encoding \"%s\"",
+                                       buf,
+                                       pg_enc2name_tbl[src_encoding].name,
+                                       pg_enc2name_tbl[dest_encoding].name)));
+}
+
+#endif                                                 /* !FRONTEND */
index ffe885e641498fab893b8d76a20f66e79fc80a5c..6b0b098a98fb414cdb035292b9d154809e960915 100644 (file)
--- a/src/hba.c
+++ b/src/hba.c
@@ -588,6 +588,8 @@ static bool parse_line(struct HBA *hba, struct TokParser *tp, int linenr, const
                rule->rule_method = AUTH_PEER;
        } else if (eat_kw(tp, "cert")) {
                rule->rule_method = AUTH_CERT;
+       } else if (eat_kw(tp, "scram-sha-256")) {
+               rule->rule_method = AUTH_SCRAM_SHA_256;
        } else {
                log_warning("hba line %d: unsupported method: buf=%s", linenr, tp->buf);
                goto failed;
index dba18736cecaf5a1797fe0ad3546693a6182aeae..aa77551f256cfcd306a0adf1c9a0f6339c967d37 100644 (file)
@@ -178,6 +178,7 @@ static const struct CfLookup auth_type_map[] = {
 #ifdef HAVE_PAM
        { "pam", AUTH_PAM },
 #endif
+       { "scram-sha-256", AUTH_SCRAM_SHA_256 },
        { NULL }
 };
 
index ba0479e93730418d9189cf0328c37b5db2fc275a..193f5e0b0adfb83732c64e97d3e73eacb70adb27 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "bouncer.h"
+#include "scram.h"
 
 /* those items will be allocated as needed, never freed */
 STATLIST(user_list);
@@ -865,6 +866,8 @@ void disconnect_server(PgSocket *server, bool notify, const char *reason, ...)
                server->dns_token = NULL;
        }
 
+       free_scram_state(&server->scram_state);
+
        server->pool->db->connection_count--;
        server->pool->user->connection_count--;
 
@@ -921,6 +924,8 @@ void disconnect_client(PgSocket *client, bool notify, const char *reason, ...)
                send_pooler_error(client, false, reason);
        }
 
+       free_scram_state(&client->scram_state);
+
        change_client_state(client, CL_JUSTFREE);
        if (!sbuf_close(&client->sbuf))
                log_noise("sbuf_close failed, retry later");
index 17ffdc8b4b68e2f8de93c77b8065d13141511a36..e0310f08625e6d85127400d2228205c3b540b670 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "bouncer.h"
+#include "scram.h"
 
 /*
  * parse protocol header from struct MBuf
@@ -283,17 +284,149 @@ static bool login_md5_psw(PgSocket *server, const uint8_t *salt)
        PgUser *user = get_srv_psw(server);
 
        slog_debug(server, "P: send md5 password");
-       if (!isMD5(user->passwd)) {
+
+       switch (get_password_type(user->passwd)) {
+       case PASSWORD_TYPE_PLAINTEXT:
                pg_md5_encrypt(user->passwd, user->name, strlen(user->name), txt);
                src = txt + 3;
-       } else {
+               break;
+       case PASSWORD_TYPE_MD5:
                src = user->passwd + 3;
+               break;
+       default:
+               slog_error(server, "cannot do MD5 authentication: wrong password type");
+               kill_pool_logins(server->pool, "server login failed: wrong password type");
+               return false;
        }
+
        pg_md5_encrypt(src, (char *)salt, 4, txt);
 
        return send_password(server, txt);
 }
 
+static bool login_scram_sha_256(PgSocket *server)
+{
+       PgUser *user = get_srv_psw(server);
+       bool res;
+       char *client_first_message = NULL;
+
+       if (get_password_type(user->passwd) != PASSWORD_TYPE_PLAINTEXT) {
+               slog_error(server, "cannot do SCRAM authentication: password is not plain text");
+               kill_pool_logins(server->pool, "server login failed: wrong password type");
+               return false;
+       }
+
+       if (server->scram_state.client_nonce)
+       {
+               slog_error(server, "protocol error: duplicate AuthenticationSASL message from server");
+               return false;
+       }
+
+       client_first_message = build_client_first_message(&server->scram_state);
+       if (!client_first_message)
+               return false;
+
+       slog_debug(server, "SCRAM client-first-message = \"%s\"", client_first_message);
+       slog_debug(server, "P: send SASLInitialResponse");
+       SEND_SASLInitialResponseMessage(res, server, "SCRAM-SHA-256", client_first_message);
+
+       free(client_first_message);
+       return res;
+}
+
+static bool login_scram_sha_256_cont(PgSocket *server, unsigned datalen, const uint8_t *data)
+{
+       PgUser *user = get_srv_psw(server);
+       char *ibuf = NULL;
+       char *input;
+       char *server_nonce;
+       int saltlen;
+       char *salt = NULL;
+       int iterations;
+       bool res;
+       char *client_final_message = NULL;
+
+       if (!server->scram_state.client_nonce)
+       {
+               slog_error(server, "protocol error: AuthenticationSASLContinue without prior AuthenticationSASL");
+               return false;
+       }
+
+       if (server->scram_state.server_first_message)
+       {
+               slog_error(server, "SCRAM exchange protocol error: received second AuthenticationSASLContinue");
+               return false;
+       }
+
+       ibuf = malloc(datalen + 1);
+       if (ibuf == NULL)
+               return false;
+       memcpy(ibuf, data, datalen);
+       ibuf[datalen] = '\0';
+
+       input = ibuf;
+       slog_debug(server, "SCRAM server-first-message = \"%s\"", input);
+       if (!read_server_first_message(server, input,
+                                      &server_nonce, &salt, &saltlen, &iterations))
+               goto failed;
+
+       client_final_message = build_client_final_message(&server->scram_state,
+                                                         user->passwd, server_nonce,
+                                                         salt, saltlen, iterations);
+
+       free(salt);
+       free(ibuf);
+
+       slog_debug(server, "SCRAM client-final-message = \"%s\"", client_final_message);
+       slog_debug(server, "P: send SASLResponse");
+       SEND_SASLResponseMessage(res, server, client_final_message);
+
+       free(client_final_message);
+       return res;
+failed:
+       free(salt);
+       free(ibuf);
+       free(client_final_message);
+       return false;
+}
+
+static bool login_scram_sha_256_final(PgSocket *server, unsigned datalen, const uint8_t *data)
+{
+       char *ibuf = NULL;
+       char *input;
+       char ServerSignature[SHA256_DIGEST_LENGTH];
+
+       if (!server->scram_state.server_first_message)
+       {
+               slog_error(server, "protocol error: AuthenticationSASLFinal without prior AuthenticationSASLContinue");
+               return false;
+       }
+
+       ibuf = malloc(datalen + 1);
+       if (ibuf == NULL)
+               return false;
+       memcpy(ibuf, data, datalen);
+       ibuf[datalen] = '\0';
+
+       input = ibuf;
+       slog_debug(server, "SCRAM server-final-message = \"%s\"", input);
+       if (!read_server_final_message(server, input, ServerSignature))
+               goto failed;
+
+       if (!verify_server_signature(&server->scram_state, ServerSignature))
+       {
+               slog_error(server, "invalid server signature");
+               kill_pool_logins(server->pool, "server login failed: invalid server signature");
+               return false;
+       }
+
+       free(ibuf);
+       return true;
+failed:
+       free(ibuf);
+       return false;
+}
+
 /* answer server authentication request */
 bool answer_authreq(PgSocket *server, PktHdr *pkt)
 {
@@ -322,6 +455,56 @@ bool answer_authreq(PgSocket *server, PktHdr *pkt)
                        return false;
                res = login_md5_psw(server, salt);
                break;
+       case AUTH_SASL:
+       {
+               bool selected_mechanism = false;
+
+               slog_debug(server, "S: req SASL");
+
+               do {
+                       const char *mech;
+
+                       if (!mbuf_get_string(&pkt->data, &mech))
+                               return false;
+                       if (!mech[0])
+                               break;
+                       slog_debug(server, "S: SASL advertised mechanism: %s", mech);
+                       if (strcmp(mech, "SCRAM-SHA-256") == 0)
+                               selected_mechanism = true;
+               } while (!selected_mechanism);
+
+               if (!selected_mechanism) {
+                       slog_error(server, "none of the server's SASL authentication mechanisms are supported");
+                       kill_pool_logins(server->pool, "server login failed: none of the server's SASL authentication mechanisms are supported");
+               } else
+                       res = login_scram_sha_256(server);
+               break;
+       }
+       case AUTH_SASL_CONT:
+       {
+               unsigned len;
+               const uint8_t *data;
+
+               slog_debug(server, "S: SASL cont");
+               len = mbuf_avail_for_read(&pkt->data);
+               if (!mbuf_get_bytes(&pkt->data, len, &data))
+                       return false;
+               res = login_scram_sha_256_cont(server, len, data);
+               break;
+       }
+       case AUTH_SASL_FIN:
+       {
+               unsigned len;
+               const uint8_t *data;
+
+               slog_debug(server, "S: SASL final");
+               len = mbuf_avail_for_read(&pkt->data);
+               if (!mbuf_get_bytes(&pkt->data, len, &data))
+                       return false;
+               res = login_scram_sha_256_final(server, len, data);
+               free_scram_state(&server->scram_state);
+               break;
+       }
        default:
                slog_error(server, "unknown/unsupported auth method: %d", cmd);
                res = false;
diff --git a/src/scram.c b/src/scram.c
new file mode 100644 (file)
index 0000000..10df2f9
--- /dev/null
@@ -0,0 +1,986 @@
+/*
+ * PgBouncer - Lightweight connection pooler for PostgreSQL.
+ *
+ * Copyright (c) 2007-2009  Marko Kreen, Skype Technologies OÃœ
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * SCRAM support
+ */
+
+#include "bouncer.h"
+#include "scram.h"
+#include "common/base64.h"
+#include "common/saslprep.h"
+#include "common/scram-common.h"
+
+
+static bool calculate_client_proof(ScramState *scram_state,
+                                  const char *passwd,
+                                  const char *salt,
+                                  int saltlen,
+                                  int iterations,
+                                  const char *client_final_message_without_proof,
+                                  uint8_t *result);
+
+
+/*
+ * free SCRAM state info after auth is done
+ */
+void free_scram_state(ScramState *scram_state)
+{
+       free(scram_state->client_nonce);
+       free(scram_state->client_first_message_bare);
+       free(scram_state->client_final_message_without_proof);
+       free(scram_state->server_nonce);
+       free(scram_state->server_first_message);
+       free(scram_state->SaltedPassword);
+       free(scram_state->salt);
+       memset(scram_state, 0, sizeof(*scram_state));
+}
+
+static bool is_scram_printable(char *p)
+{
+       /*------
+        * Printable characters, as defined by SCRAM spec: (RFC 5802)
+        *
+        *  printable       = %x21-2B / %x2D-7E
+        *                    ;; Printable ASCII except ",".
+        *                    ;; Note that any "printable" is also
+        *                    ;; a valid "value".
+        *------
+        */
+       for (; *p; p++)
+               if (*p < 0x21 || *p > 0x7E || *p == 0x2C /* comma */ )
+                       return false;
+
+       return true;
+}
+
+static char *sanitize_char(char c)
+{
+       static char buf[5];
+
+       if (c >= 0x21 && c <= 0x7E)
+               snprintf(buf, sizeof(buf), "'%c'", c);
+       else
+               snprintf(buf, sizeof(buf), "0x%02x", (unsigned char) c);
+       return buf;
+}
+
+/*
+ * Read value for an attribute part of a SCRAM message.
+ */
+static char *read_attr_value(PgSocket *sk, char **input, char attr)
+{
+       char *begin = *input;
+       char *end;
+
+       if (*begin != attr)
+       {
+               slog_error(sk, "malformed SCRAM message (attribute \"%c\" expected)",
+                          attr);
+               return NULL;
+       }
+       begin++;
+
+       if (*begin != '=')
+       {
+               slog_error(sk, "malformed SCRAM message (expected \"=\" after attribute \"%c\")",
+                          attr);
+               return NULL;
+       }
+       begin++;
+
+       end = begin;
+       while (*end && *end != ',')
+               end++;
+
+       if (*end)
+       {
+               *end = '\0';
+               *input = end + 1;
+       }
+       else
+               *input = end;
+
+       return begin;
+}
+
+/*
+ * Read the next attribute and value in a SCRAM exchange message.
+ *
+ * Returns NULL if there is no attribute.
+ */
+static char *
+read_any_attr(PgSocket *sk, char **input, char *attr_p)
+{
+       char *begin = *input;
+       char *end;
+       char attr = *begin;
+
+       if (!((attr >= 'A' && attr <= 'Z') ||
+             (attr >= 'a' && attr <= 'z')))
+       {
+               slog_error(sk, "malformed SCRAM message (attribute expected, but found invalid character \"%s\")",
+                          sanitize_char(attr));
+               return NULL;
+       }
+       if (attr_p)
+               *attr_p = attr;
+       begin++;
+
+       if (*begin != '=')
+       {
+               slog_error(sk, "malformed SCRAM message (expected character \"=\" after attribute \"%c\")",
+                          attr);
+               return NULL;
+       }
+       begin++;
+
+       end = begin;
+       while (*end && *end != ',')
+               end++;
+
+       if (*end)
+       {
+               *end = '\0';
+               *input = end + 1;
+       }
+       else
+               *input = end;
+
+       return begin;
+}
+
+/*
+ * Parse and validate format of given SCRAM verifier.
+ *
+ * Returns true if the SCRAM verifier has been parsed, and false otherwise.
+ */
+static bool parse_scram_verifier(const char *verifier, int *iterations, char **salt,
+                                uint8_t *stored_key, uint8_t *server_key)
+{
+       char       *v;
+       char       *p;
+       char       *scheme_str;
+       char       *salt_str;
+       char       *iterations_str;
+       char       *storedkey_str;
+       char       *serverkey_str;
+       int                     decoded_len;
+       char       *decoded_salt_buf;
+       char       *decoded_stored_buf = NULL;
+       char       *decoded_server_buf = NULL;
+
+       /*
+        * The verifier is of form:
+        *
+        * SCRAM-SHA-256$<iterations>:<salt>$<storedkey>:<serverkey>
+        */
+       v = strdup(verifier);
+       if (!v)
+               goto invalid_verifier;
+       if ((scheme_str = strtok(v, "$")) == NULL)
+               goto invalid_verifier;
+       if ((iterations_str = strtok(NULL, ":")) == NULL)
+               goto invalid_verifier;
+       if ((salt_str = strtok(NULL, "$")) == NULL)
+               goto invalid_verifier;
+       if ((storedkey_str = strtok(NULL, ":")) == NULL)
+               goto invalid_verifier;
+       if ((serverkey_str = strtok(NULL, "")) == NULL)
+               goto invalid_verifier;
+
+       /* Parse the fields */
+       if (strcmp(scheme_str, "SCRAM-SHA-256") != 0)
+               goto invalid_verifier;
+
+       errno = 0;
+       *iterations = strtol(iterations_str, &p, 10);
+       if (*p || errno != 0)
+               goto invalid_verifier;
+
+       /*
+        * Verify that the salt is in Base64-encoded format, by decoding it,
+        * although we return the encoded version to the caller.
+        */
+       decoded_salt_buf = malloc(pg_b64_dec_len(strlen(salt_str)));
+       if (!decoded_salt_buf)
+               goto invalid_verifier;
+       decoded_len = pg_b64_decode(salt_str, strlen(salt_str), decoded_salt_buf);
+       free(decoded_salt_buf);
+       if (decoded_len < 0)
+               goto invalid_verifier;
+       *salt = strdup(salt_str);
+
+       /*
+        * Decode StoredKey and ServerKey.
+        */
+       decoded_stored_buf = malloc(pg_b64_dec_len(strlen(storedkey_str)));
+       if (!decoded_stored_buf)
+               goto invalid_verifier;
+       decoded_len = pg_b64_decode(storedkey_str, strlen(storedkey_str), decoded_stored_buf);
+       if (decoded_len != SCRAM_KEY_LEN)
+               goto invalid_verifier;
+       memcpy(stored_key, decoded_stored_buf, SCRAM_KEY_LEN);
+
+       decoded_server_buf = malloc(pg_b64_dec_len(strlen(serverkey_str)));
+       decoded_len = pg_b64_decode(serverkey_str, strlen(serverkey_str),
+                                   decoded_server_buf);
+       if (decoded_len != SCRAM_KEY_LEN)
+               goto invalid_verifier;
+       memcpy(server_key, decoded_server_buf, SCRAM_KEY_LEN);
+
+       free(decoded_stored_buf);
+       free(decoded_server_buf);
+       free(v);
+       return true;
+
+invalid_verifier:
+       free(decoded_stored_buf);
+       free(decoded_server_buf);
+       free(v);
+       *salt = NULL;
+       return false;
+}
+
+#define MD5_PASSWD_CHARSET "0123456789abcdef"
+
+/*
+ * What kind of a password verifier is 'shadow_pass'?
+ */
+PasswordType
+get_password_type(const char *shadow_pass)
+{
+       char *encoded_salt = NULL;
+       int iterations;
+       uint8_t stored_key[SCRAM_KEY_LEN];
+       uint8_t server_key[SCRAM_KEY_LEN];
+
+       if (strncmp(shadow_pass, "md5", 3) == 0 &&
+           strlen(shadow_pass) == MD5_PASSWD_LEN &&
+           strspn(shadow_pass + 3, MD5_PASSWD_CHARSET) == MD5_PASSWD_LEN - 3)
+               return PASSWORD_TYPE_MD5;
+       if (parse_scram_verifier(shadow_pass, &iterations, &encoded_salt,
+                                stored_key, server_key)) {
+               free(encoded_salt);
+               return PASSWORD_TYPE_SCRAM_SHA_256;
+       }
+       free(encoded_salt);
+       return PASSWORD_TYPE_PLAINTEXT;
+}
+
+/*
+ * Functions for communicating as a client with the server
+ */
+
+char *build_client_first_message(ScramState *scram_state)
+{
+       uint8_t raw_nonce[SCRAM_RAW_NONCE_LEN + 1];
+       int encoded_len;
+       size_t len;
+       char *result = NULL;
+
+       get_random_bytes(raw_nonce, SCRAM_RAW_NONCE_LEN);
+
+       scram_state->client_nonce = malloc(pg_b64_enc_len(SCRAM_RAW_NONCE_LEN) + 1);
+       if (scram_state->client_nonce == NULL)
+               goto failed;
+       encoded_len = pg_b64_encode((char *) raw_nonce, SCRAM_RAW_NONCE_LEN, scram_state->client_nonce);
+       scram_state->client_nonce[encoded_len] = '\0';
+
+       len = 8 + strlen(scram_state->client_nonce) + 1;
+       result = malloc(len);
+       if (result == NULL)
+               goto failed;
+       snprintf(result, len, "n,,n=,r=%s", scram_state->client_nonce);
+
+       scram_state->client_first_message_bare = strdup(result + 3);
+       if (scram_state->client_first_message_bare == NULL)
+               goto failed;
+
+       return result;
+
+failed:
+       free(result);
+       free(scram_state->client_nonce);
+       free(scram_state->client_first_message_bare);
+       return NULL;
+}
+
+char *build_client_final_message(ScramState *scram_state,
+                                const char *passwd,
+                                const char *server_nonce,
+                                const char *salt,
+                                int saltlen,
+                                int iterations)
+{
+       char buf[512];
+       size_t len;
+       uint8_t client_proof[SCRAM_KEY_LEN];
+
+       len = snprintf(buf, sizeof(buf), "c=biws,r=%s", server_nonce);
+
+       scram_state->client_final_message_without_proof = strdup(buf);
+       if (scram_state->client_final_message_without_proof == NULL)
+               goto failed;
+
+       if (!calculate_client_proof(scram_state, passwd,
+                                   salt, saltlen, iterations, buf,
+                                   client_proof))
+               goto failed;
+
+       len = strlcat(buf, ",p=", sizeof(buf));
+       len += pg_b64_encode((char *) client_proof,
+                            SCRAM_KEY_LEN,
+                            buf + len);
+       buf[len] = '\0';
+
+       return strdup(buf);
+failed:
+       return NULL;
+}
+
+bool read_server_first_message(PgSocket *server, char *input,
+                              char **server_nonce_p, char **salt_p, int *saltlen_p, int *iterations_p)
+{
+       char *server_nonce;
+       char *encoded_salt;
+       char *salt = NULL;
+       int saltlen;
+       char *iterations_str;
+       char *endptr;
+       int iterations;
+
+       server->scram_state.server_first_message = strdup(input);
+       if (server->scram_state.server_first_message == NULL)
+               goto failed;
+
+       server_nonce = read_attr_value(server, &input, 'r');
+       if (server_nonce == NULL)
+               goto failed;
+
+       if (strlen(server_nonce) < strlen(server->scram_state.client_nonce) ||
+           memcmp(server_nonce, server->scram_state.client_nonce, strlen(server->scram_state.client_nonce)) != 0)
+       {
+               slog_error(server, "invalid SCRAM response (nonce mismatch)");
+               goto failed;
+       }
+
+       encoded_salt = read_attr_value(server, &input, 's');
+       if (encoded_salt == NULL)
+               goto failed;
+       salt = malloc(pg_b64_dec_len(strlen(encoded_salt)));
+       if (salt == NULL)
+               goto failed;
+       saltlen = pg_b64_decode(encoded_salt,
+                               strlen(encoded_salt),
+                               salt);
+       if (saltlen < 0)
+       {
+               slog_error(server, "malformed SCRAM message (invalid salt)");
+               goto failed;
+       }
+
+       iterations_str = read_attr_value(server, &input, 'i');
+       if (iterations_str == NULL)
+               goto failed;
+
+       iterations = strtol(iterations_str, &endptr, 10);
+       if (*endptr != '\0' || iterations < 1)
+       {
+               slog_error(server, "malformed SCRAM message (invalid iteration count)");
+               goto failed;
+       }
+
+       if (*input != '\0')
+       {
+               slog_error(server, "malformed SCRAM message (garbage at end of server-first-message)");
+               goto failed;
+       }
+
+       *server_nonce_p = server_nonce;
+       *salt_p = salt;
+       *saltlen_p = saltlen;
+       *iterations_p = iterations;
+       return true;
+failed:
+       free(salt);
+       return false;
+}
+
+bool read_server_final_message(PgSocket *server, char *input, char *ServerSignature)
+{
+       char *encoded_server_signature;
+       char *decoded_server_signature = NULL;
+       int server_signature_len;
+
+       if (*input == 'e')
+       {
+               char *errmsg = read_attr_value(server, &input, 'e');
+               slog_error(server, "error received from server in SCRAM exchange: %s",
+                          errmsg);
+               goto failed;
+       }
+
+       encoded_server_signature = read_attr_value(server, &input, 'v');
+       if (encoded_server_signature == NULL)
+               goto failed;
+
+       if (*input != '\0')
+               slog_error(server, "malformed SCRAM message (garbage at end of server-final-message)");
+
+       server_signature_len = pg_b64_dec_len(strlen(encoded_server_signature));
+       decoded_server_signature = malloc(server_signature_len);
+       if (!decoded_server_signature)
+               goto failed;
+
+       server_signature_len = pg_b64_decode(encoded_server_signature,
+                                            strlen(encoded_server_signature),
+                                            decoded_server_signature);
+       if (server_signature_len != SCRAM_KEY_LEN)
+       {
+               slog_error(server, "malformed SCRAM message (malformed server signature)");
+               goto failed;
+       }
+       memcpy(ServerSignature, decoded_server_signature, SCRAM_KEY_LEN);
+
+       free(decoded_server_signature);
+       return true;
+failed:
+       free(decoded_server_signature);
+       return false;
+}
+
+static bool calculate_client_proof(ScramState *scram_state,
+                                  const char *passwd,
+                                  const char *salt,
+                                  int saltlen,
+                                  int iterations,
+                                  const char *client_final_message_without_proof,
+                                  uint8_t *result)
+{
+       pg_saslprep_rc rc;
+       char *prep_password = NULL;
+       uint8_t StoredKey[SCRAM_KEY_LEN];
+       uint8_t ClientKey[SCRAM_KEY_LEN];
+       uint8_t ClientSignature[SCRAM_KEY_LEN];
+       scram_HMAC_ctx ctx;
+
+       rc = pg_saslprep(passwd, &prep_password);
+       if (rc == SASLPREP_OOM)
+               false;
+       if (rc != SASLPREP_SUCCESS)
+       {
+               prep_password = strdup(passwd);
+               if (!prep_password)
+                       return false;
+       }
+
+       scram_state->SaltedPassword = malloc(SCRAM_KEY_LEN);
+       if (scram_state->SaltedPassword == NULL)
+               goto failed;
+       scram_SaltedPassword(prep_password,
+                            salt,
+                            saltlen,
+                            iterations,
+                            scram_state->SaltedPassword);
+
+       scram_ClientKey(scram_state->SaltedPassword, ClientKey);
+       scram_H(ClientKey, SCRAM_KEY_LEN, StoredKey);
+
+       scram_HMAC_init(&ctx, StoredKey, SCRAM_KEY_LEN);
+       scram_HMAC_update(&ctx,
+                         scram_state->client_first_message_bare,
+                         strlen(scram_state->client_first_message_bare));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         scram_state->server_first_message,
+                         strlen(scram_state->server_first_message));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         client_final_message_without_proof,
+                         strlen(client_final_message_without_proof));
+       scram_HMAC_final(ClientSignature, &ctx);
+
+       for (int i = 0; i < SCRAM_KEY_LEN; i++)
+               result[i] = ClientKey[i] ^ ClientSignature[i];
+
+       free(prep_password);
+       return true;
+failed:
+       free(prep_password);
+       return false;
+}
+
+bool verify_server_signature(ScramState *scram_state, const char *ServerSignature)
+{
+       uint8_t expected_ServerSignature[SCRAM_KEY_LEN];
+       uint8_t ServerKey[SCRAM_KEY_LEN];
+       scram_HMAC_ctx ctx;
+
+       scram_ServerKey(scram_state->SaltedPassword, ServerKey);
+
+       scram_HMAC_init(&ctx, ServerKey, SCRAM_KEY_LEN);
+       scram_HMAC_update(&ctx,
+                         scram_state->client_first_message_bare,
+                         strlen(scram_state->client_first_message_bare));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         scram_state->server_first_message,
+                         strlen(scram_state->server_first_message));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         scram_state->client_final_message_without_proof,
+                         strlen(scram_state->client_final_message_without_proof));
+       scram_HMAC_final(expected_ServerSignature, &ctx);
+
+       if (memcmp(expected_ServerSignature, ServerSignature, SCRAM_KEY_LEN) != 0)
+               return false;
+
+       return true;
+}
+
+
+/*
+ * Functions for communicating as a server to the client
+ */
+
+bool read_client_first_message(PgSocket *client, char *input,
+                              char **client_first_message_bare_p,
+                              char **client_nonce_p)
+{
+       char *client_first_message_bare = NULL;
+       char *client_nonce = NULL;
+
+       switch (*input) {
+       case 'n':
+               /* Client does not support channel binding */
+               input++;
+               break;
+       case 'y':
+               /* Client supports channel binding, but we're not doing it today */
+               input++;
+               break;
+       case 'p':
+               /* Client requires channel binding.  We don't support it. */
+               slog_error(client, "client requires SCRAM channel binding, but it is not supported");
+               goto failed;
+       default:
+               slog_error(client, "malformed SCRAM message (unexpected channel-binding flag \"%s\")",
+                          sanitize_char(*input));
+               goto failed;
+       }
+
+       if (*input != ',') {
+               slog_error(client, "malformed SCRAM message (comma expected, but found character \"%s\")",
+                          sanitize_char(*input));
+               goto failed;
+       }
+       input++;
+
+       if (*input == 'a') {
+               slog_error(client, "client uses authorization identity, but it is not supported");
+               goto failed;
+       }
+       if (*input != ',') {
+               slog_error(client, "malformed SCRAM message (unexpected attribute \"%s\" in client-first-message)",
+                          sanitize_char(*input));
+               goto failed;
+       }
+       input++;
+
+       client_first_message_bare = strdup(input);
+       if (client_first_message_bare == NULL)
+               goto failed;
+
+       if (*input == 'm') {
+               slog_error(client, "client requires an unsupported SCRAM extension");
+               goto failed;
+       }
+
+       /* read and ignore user name */
+       read_attr_value(client, &input, 'n');
+
+       client_nonce = read_attr_value(client, &input, 'r');
+       if (client_nonce == NULL)
+               goto failed;
+       if (!is_scram_printable(client_nonce)) {
+               slog_error(client, "non-printable characters in SCRAM nonce");
+               goto failed;
+       }
+       client_nonce = strdup(client_nonce);
+       if (client_nonce == NULL)
+               goto failed;
+
+       /*
+        * There can be any number of optional extensions after this.  We don't
+        * support any extensions, so ignore them.
+        */
+       while (*input != '\0')
+               read_any_attr(client, &input, NULL);
+
+       *client_first_message_bare_p = client_first_message_bare;
+       *client_nonce_p = client_nonce;
+       return true;
+failed:
+       free(client_first_message_bare);
+       return false;
+}
+
+bool read_client_final_message(PgSocket *client, const uint8_t *raw_input, char *input,
+                              const char **client_final_nonce_p,
+                              char **proof_p)
+{
+       const char *input_start = input;
+       char attr;
+       char *channel_binding;
+       char *client_final_nonce;
+       char *proof_start;
+       char *encoded_proof;
+       char *proof = NULL;
+       int prooflen;
+
+       /*
+        * Read channel-binding.  We don't support channel binding, so
+        * it's expected to always be "biws", which is "n,,",
+        * base64-encoded.
+        */
+       channel_binding = read_attr_value(client, &input, 'c');
+       if (channel_binding == NULL)
+               goto failed;
+       if (strcmp(channel_binding, "biws") != 0) {
+               slog_error(client, "unexpected SCRAM channel-binding attribute in client-final-message");
+               goto failed;
+       }
+
+       client_final_nonce = read_attr_value(client, &input, 'r');
+
+       /* ignore optional extensions */
+       do
+       {
+               proof_start = input - 1;
+               encoded_proof = read_any_attr(client, &input, &attr);
+       } while (attr != 'p');
+
+       if (!encoded_proof) {
+               slog_error(client, "could not read proof");
+               goto failed;
+       }
+
+       proof = malloc(pg_b64_dec_len(strlen(encoded_proof)));
+       if (proof == NULL) {
+               slog_error(client, "could not decode proof");
+               goto failed;
+       }
+       prooflen = pg_b64_decode(encoded_proof,
+                                strlen(encoded_proof),
+                                proof);
+       (void) prooflen;
+
+       if (*input != '\0') {
+               slog_error(client, "malformed SCRAM message (garbage at the end of client-final-message)");
+               goto failed;
+       }
+
+       client->scram_state.client_final_message_without_proof = malloc(proof_start - input_start + 1);
+       if (!client->scram_state.client_final_message_without_proof)
+               goto failed;
+       memcpy(client->scram_state.client_final_message_without_proof, raw_input, proof_start - input_start);
+       client->scram_state.client_final_message_without_proof[proof_start - input_start] = '\0';
+
+       *client_final_nonce_p = client_final_nonce;
+       *proof_p = proof;
+       return true;
+failed:
+       free(proof);
+       return false;
+}
+
+/*
+ * For doing SCRAM with a password stored in plain text, build a SCRAM
+ * secret on the fly.
+ */
+static bool build_adhoc_scram_secret(const char *plain_password, ScramState *scram_state)
+{
+       const char *password;
+       char *prep_password;
+       pg_saslprep_rc rc;
+       char saltbuf[SCRAM_DEFAULT_SALT_LEN];
+       int encoded_len;
+       uint8_t salted_password[SCRAM_KEY_LEN];
+
+       rc = pg_saslprep(plain_password, &prep_password);
+       if (rc == SASLPREP_OOM)
+               goto failed;
+       else if (rc == SASLPREP_SUCCESS)
+               password = prep_password;
+       else
+               password = plain_password;
+
+       get_random_bytes((uint8_t *) saltbuf, sizeof(saltbuf));
+
+       scram_state->iterations = SCRAM_DEFAULT_ITERATIONS;
+
+       scram_state->salt = malloc(pg_b64_enc_len(sizeof(saltbuf)) + 1);
+       if (!scram_state->salt)
+               goto failed;
+       encoded_len = pg_b64_encode(saltbuf, sizeof(saltbuf), scram_state->salt);
+       scram_state->salt[encoded_len] = '\0';
+
+       /* Calculate StoredKey and ServerKey */
+       scram_SaltedPassword(password, saltbuf, sizeof(saltbuf),
+                            scram_state->iterations,
+                            salted_password);
+       scram_ClientKey(salted_password, scram_state->StoredKey);
+       scram_H(scram_state->StoredKey, SCRAM_KEY_LEN, scram_state->StoredKey);
+       scram_ServerKey(salted_password, scram_state->ServerKey);
+
+       if (prep_password)
+               free(prep_password);
+       return true;
+failed:
+       if (prep_password)
+               free(prep_password);
+       return false;
+}
+
+char *build_server_first_message(ScramState *scram_state, const char *stored_secret)
+{
+       uint8_t raw_nonce[SCRAM_RAW_NONCE_LEN + 1];
+       int encoded_len;
+       size_t len;
+       char *result;
+
+       switch (get_password_type(stored_secret)) {
+       case PASSWORD_TYPE_SCRAM_SHA_256:
+               if (!parse_scram_verifier(stored_secret,
+                                         &scram_state->iterations,
+                                         &scram_state->salt,
+                                         scram_state->StoredKey,
+                                         scram_state->ServerKey))
+                       goto failed;
+               break;
+       case PASSWORD_TYPE_PLAINTEXT:
+               if (!build_adhoc_scram_secret(stored_secret, scram_state))
+                       goto failed;
+               break;
+       default:
+               /* shouldn't get here */
+               goto failed;
+       }
+
+       get_random_bytes(raw_nonce, SCRAM_RAW_NONCE_LEN);
+       scram_state->server_nonce = malloc(pg_b64_enc_len(SCRAM_RAW_NONCE_LEN) + 1);
+       if (scram_state->server_nonce == NULL)
+               goto failed;
+       encoded_len = pg_b64_encode((char *) raw_nonce, SCRAM_RAW_NONCE_LEN, scram_state->server_nonce);
+       scram_state->server_nonce[encoded_len] = '\0';
+
+       len = (2
+              + strlen(scram_state->client_nonce)
+              + strlen(scram_state->server_nonce)
+              + 3
+              + strlen(scram_state->salt)
+              + 3 + 10 + 1);
+       result = malloc(len);
+       if (!result)
+               goto failed;
+       snprintf(result, len,
+                "r=%s%s,s=%s,i=%u",
+                scram_state->client_nonce,
+                scram_state->server_nonce,
+                scram_state->salt,
+                scram_state->iterations);
+
+       scram_state->server_first_message = result;
+
+       return result;
+failed:
+       free(scram_state->server_nonce);
+       free(scram_state->server_first_message);
+       return NULL;
+}
+
+static char *
+compute_server_signature(ScramState *state)
+{
+       uint8_t         ServerSignature[SCRAM_KEY_LEN];
+       char       *server_signature_base64;
+       int                     siglen;
+       scram_HMAC_ctx ctx;
+
+       /* calculate ServerSignature */
+       scram_HMAC_init(&ctx, state->ServerKey, SCRAM_KEY_LEN);
+       scram_HMAC_update(&ctx,
+                         state->client_first_message_bare,
+                         strlen(state->client_first_message_bare));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         state->server_first_message,
+                         strlen(state->server_first_message));
+       scram_HMAC_update(&ctx, ",", 1);
+       scram_HMAC_update(&ctx,
+                         state->client_final_message_without_proof,
+                         strlen(state->client_final_message_without_proof));
+       scram_HMAC_final(ServerSignature, &ctx);
+
+       server_signature_base64 = malloc(pg_b64_enc_len(SCRAM_KEY_LEN) + 1);
+       if (!server_signature_base64)
+               return NULL;
+       siglen = pg_b64_encode((const char *) ServerSignature,
+                                                  SCRAM_KEY_LEN, server_signature_base64);
+       server_signature_base64[siglen] = '\0';
+
+       return server_signature_base64;
+}
+
+char *build_server_final_message(ScramState *scram_state)
+{
+       char *server_signature = NULL;
+       size_t len;
+       char *result;
+
+       server_signature = compute_server_signature(scram_state);
+       if (!server_signature)
+               goto failed;
+
+       len = 2 + strlen(server_signature) + 1;
+       result = malloc(len);
+       if (!result)
+               goto failed;
+       snprintf(result, len, "v=%s", server_signature);
+
+       free(server_signature);
+       return result;
+failed:
+       free(server_signature);
+       return NULL;
+}
+
+bool verify_final_nonce(const ScramState *scram_state, const char *client_final_nonce)
+{
+       size_t client_nonce_len = strlen(scram_state->client_nonce);
+       size_t server_nonce_len = strlen(scram_state->server_nonce);
+       size_t final_nonce_len = strlen(client_final_nonce);
+
+       if (final_nonce_len != client_nonce_len + server_nonce_len)
+               return false;
+       if (memcmp(client_final_nonce, scram_state->client_nonce, client_nonce_len) != 0)
+               return false;
+       if (memcmp(client_final_nonce + client_nonce_len, scram_state->server_nonce, server_nonce_len) != 0)
+               return false;
+
+       return true;
+}
+
+bool verify_client_proof(ScramState *state, const char *ClientProof)
+{
+    uint8_t ClientSignature[SCRAM_KEY_LEN];
+    uint8_t ClientKey[SCRAM_KEY_LEN];
+    uint8_t client_StoredKey[SCRAM_KEY_LEN];
+    scram_HMAC_ctx ctx;
+    int i;
+
+    /* calculate ClientSignature */
+    scram_HMAC_init(&ctx, state->StoredKey, SCRAM_KEY_LEN);
+    scram_HMAC_update(&ctx,
+                     state->client_first_message_bare,
+                     strlen(state->client_first_message_bare));
+    scram_HMAC_update(&ctx, ",", 1);
+    scram_HMAC_update(&ctx,
+                     state->server_first_message,
+                     strlen(state->server_first_message));
+    scram_HMAC_update(&ctx, ",", 1);
+    scram_HMAC_update(&ctx,
+                     state->client_final_message_without_proof,
+                     strlen(state->client_final_message_without_proof));
+    scram_HMAC_final(ClientSignature, &ctx);
+
+    /* Extract the ClientKey that the client calculated from the proof */
+    for (i = 0; i < SCRAM_KEY_LEN; i++)
+           ClientKey[i] = ClientProof[i] ^ ClientSignature[i];
+
+    /* Hash it one more time, and compare with StoredKey */
+    scram_H(ClientKey, SCRAM_KEY_LEN, client_StoredKey);
+
+    if (memcmp(client_StoredKey, state->StoredKey, SCRAM_KEY_LEN) != 0)
+           return false;
+
+    return true;
+}
+
+/*
+ * Verify a plaintext password against a SCRAM verifier.  This is used when
+ * performing plaintext password authentication for a user that has a SCRAM
+ * verifier stored in pg_authid.
+ */
+bool
+scram_verify_plain_password(PgSocket *client,
+                           const char *username, const char *password,
+                           const char *verifier)
+{
+       char *encoded_salt = NULL;
+       char *salt = NULL;
+       int saltlen;
+       int iterations;
+       uint8_t salted_password[SCRAM_KEY_LEN];
+       uint8_t stored_key[SCRAM_KEY_LEN];
+       uint8_t server_key[SCRAM_KEY_LEN];
+       uint8_t computed_key[SCRAM_KEY_LEN];
+       char *prep_password = NULL;
+       pg_saslprep_rc rc;
+       bool result = false;
+
+       if (!parse_scram_verifier(verifier, &iterations, &encoded_salt,
+                                 stored_key, server_key))
+       {
+               /* The password looked like a SCRAM verifier, but could not be parsed. */
+               slog_warning(client, "invalid SCRAM verifier for user \"%s\"", username);
+               goto failed;
+       }
+
+       salt = malloc(pg_b64_dec_len(strlen(encoded_salt)));
+       if (!salt)
+               goto failed;
+       saltlen = pg_b64_decode(encoded_salt, strlen(encoded_salt), salt);
+       if (saltlen == -1)
+       {
+               slog_warning(client, "invalid SCRAM verifier for user \"%s\"", username);
+               goto failed;
+       }
+
+       /* Normalize the password */
+       rc = pg_saslprep(password, &prep_password);
+       if (rc == SASLPREP_SUCCESS)
+               password = prep_password;
+
+       /* Compute Server Key based on the user-supplied plaintext password */
+       scram_SaltedPassword(password, salt, saltlen, iterations, salted_password);
+       scram_ServerKey(salted_password, computed_key);
+
+       /*
+        * Compare the verifier's Server Key with the one computed from the
+        * user-supplied password.
+        */
+       result = memcmp(computed_key, server_key, SCRAM_KEY_LEN) == 0;
+
+failed:
+       free(encoded_salt);
+       free(salt);
+       free(prep_password);
+       return result;
+}
index c825c6acde2b38200612749d90c842aa2e35c5d6..af300877e15d426d3719520fbec14d2b73fe02cb 100644 (file)
@@ -62,15 +62,10 @@ failed_store:
 }
 
 /* we cannot log in at all, notify clients */
-static void kill_pool_logins(PgPool *pool, PktHdr *errpkt)
+void kill_pool_logins(PgPool *pool, const char *msg)
 {
        struct List *item, *tmp;
        PgSocket *client;
-       const char *level, *msg;
-
-       parse_server_error(errpkt, &level, &msg);
-
-       log_warning("server login failed: %s %s", level, msg);
 
        statlist_for_each_safe(item, &pool->waiting_client_list, tmp) {
                client = container_of(item, PgSocket, head);
@@ -81,6 +76,16 @@ static void kill_pool_logins(PgPool *pool, PktHdr *errpkt)
        }
 }
 
+/* we cannot log in at all, notify clients with server error */
+static void kill_pool_logins_server_error(PgPool *pool, PktHdr *errpkt)
+{
+       const char *level, *msg;
+
+       parse_server_error(errpkt, &level, &msg);
+       log_warning("server login failed: %s %s", level, msg);
+       kill_pool_logins(pool, msg);
+}
+
 /* process packets on server auth phase */
 static bool handle_server_startup(PgSocket *server, PktHdr *pkt)
 {
@@ -117,7 +122,7 @@ static bool handle_server_startup(PgSocket *server, PktHdr *pkt)
 
        case 'E':               /* ErrorResponse */
                if (!server->pool->welcome_msg_ready)
-                       kill_pool_logins(server->pool, pkt);
+                       kill_pool_logins_server_error(server->pool, pkt);
                else
                        log_server_error("S: login failed", pkt);
 
index 2b3394b57b708a478884b9fb6891152f9913b994..75663cbb5703979f21e797ec4fb4def04bd3c0fc 100644 (file)
@@ -38,6 +38,8 @@ static const char *method2string(int method)
                return "reject";
        case AUTH_PAM:
                return "pam";
+       case AUTH_SCRAM_SHA_256:
+               return "scram-sha-256";
        default:
                return "???";
        }
index 5ad79e7baa592d850c15520181fbb07f54a911ae..3cd28b98f234b5bc2ea86a6750e6c1aef417fb71 100644 (file)
@@ -3,6 +3,7 @@ md5             db      user            unix
 peer           dbp     user            unix
 password       db      userp           unix
 trust          dbz     userz           unix
+scram-sha-256  dbs     users           unix
 
 # hostssl
 cert           db      user            10.1.1.1        tls
index 76d8aa57dbfc031826944f4683ceef841a96664b..1efe467e8b750a2cdbcb0111d27c277532d4d148 100644 (file)
@@ -14,6 +14,7 @@
 local          dbp             all                                     peer
 local          all             userp                                   password
 local          dbz             userz                                   trust
+local          dbs             users                                   scram-sha-256
 local          all             all                                     md5
 
 hostssl                all             all     10.0.0.0/8                      cert
index 0f22aaa310fd0e31b5edbd1b828e9d96903bea84..a8928908df1423f775ad37df51ca9d27faaa501e 100644 (file)
@@ -10,6 +10,10 @@ p5 = port=6666 host=127.0.0.1 dbname=p5 user=muser1 password=foo
 p5x= port=6666 host=127.0.0.1 dbname=p5 user=muser1 password=wrong
 p5y= port=6666 host=127.0.0.1 dbname=p5 user=muser1
 p5z= port=6666 host=127.0.0.1 dbname=p5 user=muser2
+p6 = port=6666 host=127.0.0.1 dbname=p6 user=scramuser1 password=foo
+p6x= port=6666 host=127.0.0.1 dbname=p6 user=scramuser1 password=wrong
+p6y= port=6666 host=127.0.0.1 dbname=p6 user=scramuser1
+p6z= port=6666 host=127.0.0.1 dbname=p6 user=scramuser2
 
 authdb = port=6666 host=127.0.0.1 dbname=p1 auth_user=pswcheck
 
index fbd563f3a8be67570012a208cf43049dbc6b6dae..718d05c951eb48afe0dab72ec06214ff6abd1850 100755 (executable)
@@ -32,6 +32,21 @@ which initdb > /dev/null || {
        exit 1
 }
 
+# System configuration checks
+SED_ERE_OP='-E'
+case `uname` in
+Linux)
+       SED_ERE_OP='-r'
+       ;;
+esac
+
+pg_majorversion=$(initdb --version | sed -n $SED_ERE_OP 's/.* ([0-9]+).*/\1/p')
+if test $pg_majorversion -ge 10; then
+       pg_supports_scram=true
+else
+       pg_supports_scram=false
+fi
+
 # System configuration checks
 if ! grep -q "^\"${USER}\"" userlist.txt; then
        cp userlist.txt userlist.txt.bak
@@ -57,14 +72,6 @@ if test -n "$CAN_SUDO"; then
        esac
 fi
 
-# System configuration checks
-SED_ERE_OP='-E'
-case `uname` in
-Linux)
-       SED_ERE_OP='-r'
-       ;;
-esac
-
 stopit() {
        local pid
        if test -f "$1"; then
@@ -89,7 +96,16 @@ if [ ! -d $PGDATA ]; then
        cat >>pgdata/postgresql.conf <<-EOF
        log_connections = on
        EOF
-       cat >pgdata/pg_hba.conf <<-EOF
+       if $pg_supports_scram; then
+               cat >pgdata/pg_hba.conf <<-EOF
+               local  p6   all                scram-sha-256
+               host   p6   all  127.0.0.1/32  scram-sha-256
+               host   p6   all  ::1/128       scram-sha-256
+               EOF
+       else
+               cat >pgdata/pg_hba.conf </dev/null
+       fi
+       cat >>pgdata/pg_hba.conf <<-EOF
        local  p4   all                password
        host   p4   all  127.0.0.1/32  password
        host   p4   all  ::1/128       password
@@ -107,7 +123,7 @@ pgctl start
 echo "Creating databases"
 psql -X -p $PG_PORT -l | grep p0 > /dev/null || {
        psql -X -o /dev/null -p $PG_PORT -c "create user bouncer" template1 || exit 1
-       for dbname in p0 p1 p3 p4 p5; do
+       for dbname in p0 p1 p3 p4 p5 p6; do
                createdb -p $PG_PORT $dbname || exit 1
        done
 }
@@ -116,10 +132,18 @@ psql -X -p $PG_PORT -d p0 -c "select * from pg_user" | grep pswcheck > /dev/null
        echo "Creating users"
        psql -X -o /dev/null -p $PG_PORT -c "create user pswcheck with superuser createdb password 'pgbouncer-check';" p0 || exit 1
        psql -X -o /dev/null -p $PG_PORT -c "create user someuser with password 'anypasswd';" p0 || exit 1
-       psql -X -o /dev/null -p $PG_PORT -c "create user muser1 password 'foo';" p0 || exit 1
-       psql -X -o /dev/null -p $PG_PORT -c "create user muser2 password 'wrong';" p0 || exit 1
-       psql -X -o /dev/null -p $PG_PORT -c "create user puser1 password 'foo';" p0 || exit 1
-       psql -X -o /dev/null -p $PG_PORT -c "create user puser2 password 'wrong';" p0 || exit 1
+       if $pg_supports_scram; then
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'md5'; create user muser1 password 'foo';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'md5'; create user muser2 password 'wrong';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'md5'; create user puser1 password 'foo';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'md5'; create user puser2 password 'wrong';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = 'scram-sha-256'; create user scramuser1 password 'foo';" p0 || exit 1
+       else
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = on; create user muser1 password 'foo';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = on; create user muser2 password 'wrong';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = on; create user puser1 password 'foo';" p0 || exit 1
+               psql -X -o /dev/null -p $PG_PORT -c "set password_encryption = on; create user puser2 password 'wrong';" p0 || exit 1
+       fi
 }
 
 #
@@ -635,6 +659,13 @@ test_password_client() {
        # bad password
        PGPASSWORD=wrong psql -X -U muser2 -c "select 2" p1 && return 1
 
+       # test with users that have a SCRAM password stored
+
+       # good password
+       PGPASSWORD=foo psql -X -U scramuser1 -c "select 1" p1 || return 1
+       # bad password
+       PGPASSWORD=wrong psql -X -U scramuser2 -c "select 2" p1 && return 1
+
        admin "set auth_type='trust'"
 
        return 0
@@ -680,6 +711,65 @@ test_md5_client() {
        return 0
 }
 
+# test SCRAM authentication from PgBouncer to PostgreSQL server
+test_scram_server() {
+       $pg_supports_scram || return 77
+
+       admin "set auth_type='trust'"
+
+       # good password from ini
+       psql -X -c "select 1" p6 || return 1
+       # bad password from ini
+       psql -X -c "select 2" p6x && return 1
+
+       # good password from auth_file (fails: not supported with SCRAM)
+       psql -X -c "select 1" p6y && return 1
+       # bad password from auth_file
+       psql -X -c "select 1" p6z && return 1
+
+       return 0
+}
+
+# test SCRAM authentication from client to PgBouncer
+test_scram_client() {
+       $pg_supports_scram || return 77
+
+       admin "set auth_type='scram-sha-256'"
+
+       # test with users that have a plain-text password stored
+
+       # good password
+       PGPASSWORD=foo psql -X -U puser1 -c "select 1" p1 || return 1
+       # bad password
+       PGPASSWORD=wrong psql -X -U puser2 -c "select 2" p1 && return 1
+
+       # test with users that have an md5 password stored (all fail)
+
+       # good password
+       PGPASSWORD=foo psql -X -U muser1 -c "select 1" p1 && return 1
+       # bad password
+       PGPASSWORD=wrong psql -X -U muser2 -c "select 2" p1 && return 1
+
+       # test with users that have a SCRAM password stored
+
+       # good password
+       PGPASSWORD=foo psql -X -U scramuser1 -c "select 1" p1 || return 1
+       # bad password
+       PGPASSWORD=wrong psql -X -U scramuser2 -c "select 2" p1 && return 1
+
+       # SCRAM should also work when auth_type is "md5"
+       admin "set auth_type='md5'"
+
+       # good password
+       PGPASSWORD=foo psql -X -U scramuser1 -c "select 1" p1 || return 1
+       # bad password
+       PGPASSWORD=wrong psql -X -U scramuser2 -c "select 2" p1 && return 1
+
+       admin "set auth_type='trust'"
+
+       return 0
+}
+
 testlist="
 test_server_login_retry
 test_auth_user
@@ -706,6 +796,8 @@ test_password_server
 test_password_client
 test_md5_server
 test_md5_client
+test_scram_server
+test_scram_client
 "
 
 if [ $# -gt 0 ]; then
index dd722b3df76664300ba063910e1be557c0be3572..80e89618afcf4fe79566e81bddfc80a3bac9cda1 100644 (file)
@@ -11,3 +11,6 @@
 
 "muser1" "md5ab8b744ff66bee42dc47bae34ca17959"
 "muser2" "md598455b3585818e23c2653a59f6d84551"
+
+"scramuser1" "SCRAM-SHA-256$4096:D76gvGUVj9Z4DNiGoabOBg==$RukL0Xo3Ql/2F9FsD7mcQ3GATG2fD3PA71qY1JagGDs=:BhKUwyyivFm7Tq2jDJVXSVRbRDgTWyBilZKgg6DDuYU="
+"scramuser2" "SCRAM-SHA-256$4096:BUYIT9YAsWf036OHLPfv2Q==$zuk7pzdEc5tvftsRIuwlStNxVc+wIE/xfDs7ahsKN0k=:Lov6mndE0DmlgtY60e1LyDsLctQyoH+Bvkm9K9njSa8="