From 1bb25bb33d03cdc65ff2312889df5417efec063d Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Mon, 8 Aug 2011 11:32:51 +0200
Subject: [PATCH 4/7] Dumb16 (UCS-2) and Dumb32 (Unicode) external modes added

---
 run/john.conf | 2437 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 2437 insertions(+), 0 deletions(-)

diff --git a/run/john.conf b/run/john.conf
index 36e5366..7d5b91f 100644
--- a/run/john.conf
+++ b/run/john.conf
@@ -711,6 +711,2443 @@ void restore()
 	/* This sample can be enhanced to infer the rest of the indices here */
 }
 
+# Generic implementation of "dumb" exhaustive search of Unicode/UCS-2 and
+# an arbitrary charset. Default is to try *all* allocated characters (there's
+# 15801 of them). A fast format like NT can exhaust up to 3 characters in a
+# couple of weeks while four characters would take over 500 years...
+#
+# The output is UTF-8, so for 16-bit formats you need to give --enc=utf8
+[List.External:Dumb16]
+int maxlength;            // Maximum password length to try
+int last;                 // Last character position, zero-based
+int lastid;               // Character index in the last position
+int id[0x7f];             // Current character indices for other positions
+int charset[0x4000], c0;  // Characters (raise to 0x10000 for *all* codepoints)
+int word16[0x7F];         // Word in UCS-2
+
+void init()
+{
+	int minlength;
+	int i, c;
+
+	minlength = 1;	// Initial password length to try, must be at least 1
+	maxlength = 2;	// Must be at least same as minlength
+
+/*
+ * This defines the character set. This is auto-generated from UnicodeData.txt
+ * and we skip control characters.
+ */
+	i = 0;
+    c = 0x0020;
+    while (c < 0x007f)
+        charset[i++] = c++;
+    c = 0x00a0;
+    while (c < 0x0378)
+        charset[i++] = c++;
+    c = 0x037a;
+    while (c < 0x037f)
+        charset[i++] = c++;
+    c = 0x0384;
+    while (c < 0x038b)
+        charset[i++] = c++;
+    c = 0x038e;
+    while (c < 0x03a2)
+        charset[i++] = c++;
+    c = 0x03a3;
+    while (c < 0x0528)
+        charset[i++] = c++;
+    c = 0x0531;
+    while (c < 0x0557)
+        charset[i++] = c++;
+    c = 0x0559;
+    while (c < 0x0560)
+        charset[i++] = c++;
+    c = 0x0561;
+    while (c < 0x0588)
+        charset[i++] = c++;
+    charset[i++] = 0x0589;
+    charset[i++] = 0x058a;
+    c = 0x0591;
+    while (c < 0x05c8)
+        charset[i++] = c++;
+    c = 0x05d0;
+    while (c < 0x05eb)
+        charset[i++] = c++;
+    c = 0x05f0;
+    while (c < 0x05f5)
+        charset[i++] = c++;
+    c = 0x0600;
+    while (c < 0x0604)
+        charset[i++] = c++;
+    c = 0x0606;
+    while (c < 0x061c)
+        charset[i++] = c++;
+    c = 0x061e;
+    while (c < 0x070e)
+        charset[i++] = c++;
+    c = 0x070f;
+    while (c < 0x074b)
+        charset[i++] = c++;
+    c = 0x074d;
+    while (c < 0x07b2)
+        charset[i++] = c++;
+    c = 0x07c0;
+    while (c < 0x07fb)
+        charset[i++] = c++;
+    c = 0x0800;
+    while (c < 0x082e)
+        charset[i++] = c++;
+    c = 0x0830;
+    while (c < 0x083f)
+        charset[i++] = c++;
+    c = 0x0840;
+    while (c < 0x085c)
+        charset[i++] = c++;
+    c = 0x0900;
+    while (c < 0x0978)
+        charset[i++] = c++;
+    c = 0x0979;
+    while (c < 0x0980)
+        charset[i++] = c++;
+    charset[i++] = 0x0981;
+    charset[i++] = 0x0983;
+    c = 0x0985;
+    while (c < 0x098d)
+        charset[i++] = c++;
+    charset[i++] = 0x098f;
+    charset[i++] = 0x0990;
+    c = 0x0993;
+    while (c < 0x09a9)
+        charset[i++] = c++;
+    c = 0x09aa;
+    while (c < 0x09b1)
+        charset[i++] = c++;
+    c = 0x09b6;
+    while (c < 0x09ba)
+        charset[i++] = c++;
+    c = 0x09bc;
+    while (c < 0x09c5)
+        charset[i++] = c++;
+    charset[i++] = 0x09c7;
+    charset[i++] = 0x09c8;
+    c = 0x09cb;
+    while (c < 0x09cf)
+        charset[i++] = c++;
+    charset[i++] = 0x09dc;
+    charset[i++] = 0x09dd;
+    c = 0x09df;
+    while (c < 0x09e4)
+        charset[i++] = c++;
+    c = 0x09e6;
+    while (c < 0x09fc)
+        charset[i++] = c++;
+    charset[i++] = 0x0a01;
+    charset[i++] = 0x0a03;
+    c = 0x0a05;
+    while (c < 0x0a0b)
+        charset[i++] = c++;
+    charset[i++] = 0x0a0f;
+    charset[i++] = 0x0a10;
+    c = 0x0a13;
+    while (c < 0x0a29)
+        charset[i++] = c++;
+    c = 0x0a2a;
+    while (c < 0x0a31)
+        charset[i++] = c++;
+    charset[i++] = 0x0a32;
+    charset[i++] = 0x0a33;
+    charset[i++] = 0x0a35;
+    charset[i++] = 0x0a36;
+    charset[i++] = 0x0a38;
+    charset[i++] = 0x0a39;
+    c = 0x0a3e;
+    while (c < 0x0a43)
+        charset[i++] = c++;
+    charset[i++] = 0x0a47;
+    charset[i++] = 0x0a48;
+    charset[i++] = 0x0a4b;
+    charset[i++] = 0x0a4d;
+    c = 0x0a59;
+    while (c < 0x0a5d)
+        charset[i++] = c++;
+    c = 0x0a66;
+    while (c < 0x0a76)
+        charset[i++] = c++;
+    charset[i++] = 0x0a81;
+    charset[i++] = 0x0a83;
+    c = 0x0a85;
+    while (c < 0x0a8e)
+        charset[i++] = c++;
+    charset[i++] = 0x0a8f;
+    charset[i++] = 0x0a91;
+    c = 0x0a93;
+    while (c < 0x0aa9)
+        charset[i++] = c++;
+    c = 0x0aaa;
+    while (c < 0x0ab1)
+        charset[i++] = c++;
+    charset[i++] = 0x0ab2;
+    charset[i++] = 0x0ab3;
+    c = 0x0ab5;
+    while (c < 0x0aba)
+        charset[i++] = c++;
+    c = 0x0abc;
+    while (c < 0x0ac6)
+        charset[i++] = c++;
+    charset[i++] = 0x0ac7;
+    charset[i++] = 0x0ac9;
+    charset[i++] = 0x0acb;
+    charset[i++] = 0x0acd;
+    c = 0x0ae0;
+    while (c < 0x0ae4)
+        charset[i++] = c++;
+    c = 0x0ae6;
+    while (c < 0x0af0)
+        charset[i++] = c++;
+    charset[i++] = 0x0b01;
+    charset[i++] = 0x0b03;
+    c = 0x0b05;
+    while (c < 0x0b0d)
+        charset[i++] = c++;
+    charset[i++] = 0x0b0f;
+    charset[i++] = 0x0b10;
+    c = 0x0b13;
+    while (c < 0x0b29)
+        charset[i++] = c++;
+    c = 0x0b2a;
+    while (c < 0x0b31)
+        charset[i++] = c++;
+    charset[i++] = 0x0b32;
+    charset[i++] = 0x0b33;
+    c = 0x0b35;
+    while (c < 0x0b3a)
+        charset[i++] = c++;
+    c = 0x0b3c;
+    while (c < 0x0b45)
+        charset[i++] = c++;
+    charset[i++] = 0x0b47;
+    charset[i++] = 0x0b48;
+    charset[i++] = 0x0b4b;
+    charset[i++] = 0x0b4d;
+    charset[i++] = 0x0b56;
+    charset[i++] = 0x0b57;
+    charset[i++] = 0x0b5c;
+    charset[i++] = 0x0b5d;
+    c = 0x0b5f;
+    while (c < 0x0b64)
+        charset[i++] = c++;
+    c = 0x0b66;
+    while (c < 0x0b78)
+        charset[i++] = c++;
+    charset[i++] = 0x0b82;
+    charset[i++] = 0x0b83;
+    c = 0x0b85;
+    while (c < 0x0b8b)
+        charset[i++] = c++;
+    charset[i++] = 0x0b8e;
+    charset[i++] = 0x0b90;
+    c = 0x0b92;
+    while (c < 0x0b96)
+        charset[i++] = c++;
+    charset[i++] = 0x0b99;
+    charset[i++] = 0x0b9a;
+    charset[i++] = 0x0b9e;
+    charset[i++] = 0x0b9f;
+    charset[i++] = 0x0ba3;
+    charset[i++] = 0x0ba4;
+    charset[i++] = 0x0ba8;
+    charset[i++] = 0x0baa;
+    c = 0x0bae;
+    while (c < 0x0bba)
+        charset[i++] = c++;
+    c = 0x0bbe;
+    while (c < 0x0bc3)
+        charset[i++] = c++;
+    charset[i++] = 0x0bc6;
+    charset[i++] = 0x0bc8;
+    c = 0x0bca;
+    while (c < 0x0bce)
+        charset[i++] = c++;
+    c = 0x0be6;
+    while (c < 0x0bfb)
+        charset[i++] = c++;
+    charset[i++] = 0x0c01;
+    charset[i++] = 0x0c03;
+    c = 0x0c05;
+    while (c < 0x0c0d)
+        charset[i++] = c++;
+    charset[i++] = 0x0c0e;
+    charset[i++] = 0x0c10;
+    c = 0x0c12;
+    while (c < 0x0c29)
+        charset[i++] = c++;
+    c = 0x0c2a;
+    while (c < 0x0c34)
+        charset[i++] = c++;
+    c = 0x0c35;
+    while (c < 0x0c3a)
+        charset[i++] = c++;
+    c = 0x0c3d;
+    while (c < 0x0c45)
+        charset[i++] = c++;
+    charset[i++] = 0x0c46;
+    charset[i++] = 0x0c48;
+    c = 0x0c4a;
+    while (c < 0x0c4e)
+        charset[i++] = c++;
+    charset[i++] = 0x0c55;
+    charset[i++] = 0x0c56;
+    charset[i++] = 0x0c58;
+    charset[i++] = 0x0c59;
+    c = 0x0c60;
+    while (c < 0x0c64)
+        charset[i++] = c++;
+    c = 0x0c66;
+    while (c < 0x0c70)
+        charset[i++] = c++;
+    c = 0x0c78;
+    while (c < 0x0c80)
+        charset[i++] = c++;
+    charset[i++] = 0x0c82;
+    charset[i++] = 0x0c83;
+    c = 0x0c85;
+    while (c < 0x0c8d)
+        charset[i++] = c++;
+    charset[i++] = 0x0c8e;
+    charset[i++] = 0x0c90;
+    c = 0x0c92;
+    while (c < 0x0ca9)
+        charset[i++] = c++;
+    c = 0x0caa;
+    while (c < 0x0cb4)
+        charset[i++] = c++;
+    c = 0x0cb5;
+    while (c < 0x0cba)
+        charset[i++] = c++;
+    c = 0x0cbc;
+    while (c < 0x0cc5)
+        charset[i++] = c++;
+    charset[i++] = 0x0cc6;
+    charset[i++] = 0x0cc8;
+    c = 0x0cca;
+    while (c < 0x0cce)
+        charset[i++] = c++;
+    charset[i++] = 0x0cd5;
+    charset[i++] = 0x0cd6;
+    c = 0x0ce0;
+    while (c < 0x0ce4)
+        charset[i++] = c++;
+    c = 0x0ce6;
+    while (c < 0x0cf0)
+        charset[i++] = c++;
+    charset[i++] = 0x0cf1;
+    charset[i++] = 0x0cf2;
+    charset[i++] = 0x0d02;
+    charset[i++] = 0x0d03;
+    c = 0x0d05;
+    while (c < 0x0d0d)
+        charset[i++] = c++;
+    charset[i++] = 0x0d0e;
+    charset[i++] = 0x0d10;
+    c = 0x0d12;
+    while (c < 0x0d3b)
+        charset[i++] = c++;
+    c = 0x0d3d;
+    while (c < 0x0d45)
+        charset[i++] = c++;
+    charset[i++] = 0x0d46;
+    charset[i++] = 0x0d48;
+    c = 0x0d4a;
+    while (c < 0x0d4f)
+        charset[i++] = c++;
+    c = 0x0d60;
+    while (c < 0x0d64)
+        charset[i++] = c++;
+    c = 0x0d66;
+    while (c < 0x0d76)
+        charset[i++] = c++;
+    c = 0x0d79;
+    while (c < 0x0d80)
+        charset[i++] = c++;
+    charset[i++] = 0x0d82;
+    charset[i++] = 0x0d83;
+    c = 0x0d85;
+    while (c < 0x0d97)
+        charset[i++] = c++;
+    c = 0x0d9a;
+    while (c < 0x0db2)
+        charset[i++] = c++;
+    c = 0x0db3;
+    while (c < 0x0dbc)
+        charset[i++] = c++;
+    c = 0x0dc0;
+    while (c < 0x0dc7)
+        charset[i++] = c++;
+    c = 0x0dcf;
+    while (c < 0x0dd5)
+        charset[i++] = c++;
+    c = 0x0dd8;
+    while (c < 0x0de0)
+        charset[i++] = c++;
+    charset[i++] = 0x0df2;
+    charset[i++] = 0x0df4;
+    c = 0x0e01;
+    while (c < 0x0e3b)
+        charset[i++] = c++;
+    c = 0x0e3f;
+    while (c < 0x0e5c)
+        charset[i++] = c++;
+    charset[i++] = 0x0e81;
+    charset[i++] = 0x0e82;
+    charset[i++] = 0x0e87;
+    charset[i++] = 0x0e88;
+    c = 0x0e94;
+    while (c < 0x0e98)
+        charset[i++] = c++;
+    c = 0x0e99;
+    while (c < 0x0ea0)
+        charset[i++] = c++;
+    charset[i++] = 0x0ea1;
+    charset[i++] = 0x0ea3;
+    charset[i++] = 0x0eaa;
+    charset[i++] = 0x0eab;
+    c = 0x0ead;
+    while (c < 0x0eba)
+        charset[i++] = c++;
+    charset[i++] = 0x0ebb;
+    charset[i++] = 0x0ebd;
+    c = 0x0ec0;
+    while (c < 0x0ec5)
+        charset[i++] = c++;
+    c = 0x0ec8;
+    while (c < 0x0ece)
+        charset[i++] = c++;
+    c = 0x0ed0;
+    while (c < 0x0eda)
+        charset[i++] = c++;
+    charset[i++] = 0x0edc;
+    charset[i++] = 0x0edd;
+    c = 0x0f00;
+    while (c < 0x0f48)
+        charset[i++] = c++;
+    c = 0x0f49;
+    while (c < 0x0f6d)
+        charset[i++] = c++;
+    c = 0x0f71;
+    while (c < 0x0f98)
+        charset[i++] = c++;
+    c = 0x0f99;
+    while (c < 0x0fbd)
+        charset[i++] = c++;
+    c = 0x0fbe;
+    while (c < 0x0fcd)
+        charset[i++] = c++;
+    c = 0x0fce;
+    while (c < 0x0fdb)
+        charset[i++] = c++;
+    c = 0x1000;
+    while (c < 0x10c6)
+        charset[i++] = c++;
+    c = 0x10d0;
+    while (c < 0x10fd)
+        charset[i++] = c++;
+    c = 0x1100;
+    while (c < 0x1249)
+        charset[i++] = c++;
+    c = 0x124a;
+    while (c < 0x124e)
+        charset[i++] = c++;
+    c = 0x1250;
+    while (c < 0x1257)
+        charset[i++] = c++;
+    c = 0x125a;
+    while (c < 0x125e)
+        charset[i++] = c++;
+    c = 0x1260;
+    while (c < 0x1289)
+        charset[i++] = c++;
+    c = 0x128a;
+    while (c < 0x128e)
+        charset[i++] = c++;
+    c = 0x1290;
+    while (c < 0x12b1)
+        charset[i++] = c++;
+    c = 0x12b2;
+    while (c < 0x12b6)
+        charset[i++] = c++;
+    c = 0x12b8;
+    while (c < 0x12bf)
+        charset[i++] = c++;
+    c = 0x12c2;
+    while (c < 0x12c6)
+        charset[i++] = c++;
+    c = 0x12c8;
+    while (c < 0x12d7)
+        charset[i++] = c++;
+    c = 0x12d8;
+    while (c < 0x1311)
+        charset[i++] = c++;
+    c = 0x1312;
+    while (c < 0x1316)
+        charset[i++] = c++;
+    c = 0x1318;
+    while (c < 0x135b)
+        charset[i++] = c++;
+    c = 0x135d;
+    while (c < 0x137d)
+        charset[i++] = c++;
+    c = 0x1380;
+    while (c < 0x139a)
+        charset[i++] = c++;
+    c = 0x13a0;
+    while (c < 0x13f5)
+        charset[i++] = c++;
+    c = 0x1400;
+    while (c < 0x169d)
+        charset[i++] = c++;
+    c = 0x16a0;
+    while (c < 0x16f1)
+        charset[i++] = c++;
+    c = 0x1700;
+    while (c < 0x170d)
+        charset[i++] = c++;
+    c = 0x170e;
+    while (c < 0x1715)
+        charset[i++] = c++;
+    c = 0x1720;
+    while (c < 0x1737)
+        charset[i++] = c++;
+    c = 0x1740;
+    while (c < 0x1754)
+        charset[i++] = c++;
+    c = 0x1760;
+    while (c < 0x176d)
+        charset[i++] = c++;
+    charset[i++] = 0x176e;
+    charset[i++] = 0x1770;
+    charset[i++] = 0x1772;
+    charset[i++] = 0x1773;
+    c = 0x1780;
+    while (c < 0x17de)
+        charset[i++] = c++;
+    c = 0x17e0;
+    while (c < 0x17ea)
+        charset[i++] = c++;
+    c = 0x17f0;
+    while (c < 0x17fa)
+        charset[i++] = c++;
+    c = 0x1800;
+    while (c < 0x180f)
+        charset[i++] = c++;
+    c = 0x1810;
+    while (c < 0x181a)
+        charset[i++] = c++;
+    c = 0x1820;
+    while (c < 0x1878)
+        charset[i++] = c++;
+    c = 0x1880;
+    while (c < 0x18ab)
+        charset[i++] = c++;
+    c = 0x18b0;
+    while (c < 0x18f6)
+        charset[i++] = c++;
+    c = 0x1900;
+    while (c < 0x191d)
+        charset[i++] = c++;
+    c = 0x1920;
+    while (c < 0x192c)
+        charset[i++] = c++;
+    c = 0x1930;
+    while (c < 0x193c)
+        charset[i++] = c++;
+    c = 0x1944;
+    while (c < 0x196e)
+        charset[i++] = c++;
+    c = 0x1970;
+    while (c < 0x1975)
+        charset[i++] = c++;
+    c = 0x1980;
+    while (c < 0x19ac)
+        charset[i++] = c++;
+    c = 0x19b0;
+    while (c < 0x19ca)
+        charset[i++] = c++;
+    c = 0x19d0;
+    while (c < 0x19db)
+        charset[i++] = c++;
+    c = 0x19de;
+    while (c < 0x1a1c)
+        charset[i++] = c++;
+    c = 0x1a1e;
+    while (c < 0x1a5f)
+        charset[i++] = c++;
+    c = 0x1a60;
+    while (c < 0x1a7d)
+        charset[i++] = c++;
+    c = 0x1a7f;
+    while (c < 0x1a8a)
+        charset[i++] = c++;
+    c = 0x1a90;
+    while (c < 0x1a9a)
+        charset[i++] = c++;
+    c = 0x1aa0;
+    while (c < 0x1aae)
+        charset[i++] = c++;
+    c = 0x1b00;
+    while (c < 0x1b4c)
+        charset[i++] = c++;
+    c = 0x1b50;
+    while (c < 0x1b7d)
+        charset[i++] = c++;
+    c = 0x1b80;
+    while (c < 0x1bab)
+        charset[i++] = c++;
+    c = 0x1bae;
+    while (c < 0x1bba)
+        charset[i++] = c++;
+    c = 0x1bc0;
+    while (c < 0x1bf4)
+        charset[i++] = c++;
+    c = 0x1bfc;
+    while (c < 0x1c38)
+        charset[i++] = c++;
+    c = 0x1c3b;
+    while (c < 0x1c4a)
+        charset[i++] = c++;
+    c = 0x1c4d;
+    while (c < 0x1c80)
+        charset[i++] = c++;
+    c = 0x1cd0;
+    while (c < 0x1cf3)
+        charset[i++] = c++;
+    c = 0x1d00;
+    while (c < 0x1de7)
+        charset[i++] = c++;
+    c = 0x1dfc;
+    while (c < 0x1f16)
+        charset[i++] = c++;
+    c = 0x1f18;
+    while (c < 0x1f1e)
+        charset[i++] = c++;
+    c = 0x1f20;
+    while (c < 0x1f46)
+        charset[i++] = c++;
+    c = 0x1f48;
+    while (c < 0x1f4e)
+        charset[i++] = c++;
+    c = 0x1f50;
+    while (c < 0x1f58)
+        charset[i++] = c++;
+    c = 0x1f5f;
+    while (c < 0x1f7e)
+        charset[i++] = c++;
+    c = 0x1f80;
+    while (c < 0x1fb5)
+        charset[i++] = c++;
+    c = 0x1fb6;
+    while (c < 0x1fc5)
+        charset[i++] = c++;
+    c = 0x1fc6;
+    while (c < 0x1fd4)
+        charset[i++] = c++;
+    c = 0x1fd6;
+    while (c < 0x1fdc)
+        charset[i++] = c++;
+    c = 0x1fdd;
+    while (c < 0x1ff0)
+        charset[i++] = c++;
+    charset[i++] = 0x1ff2;
+    charset[i++] = 0x1ff4;
+    c = 0x1ff6;
+    while (c < 0x1fff)
+        charset[i++] = c++;
+    c = 0x2000;
+    while (c < 0x2065)
+        charset[i++] = c++;
+    c = 0x206a;
+    while (c < 0x2072)
+        charset[i++] = c++;
+    c = 0x2074;
+    while (c < 0x208f)
+        charset[i++] = c++;
+    c = 0x2090;
+    while (c < 0x209d)
+        charset[i++] = c++;
+    c = 0x20a0;
+    while (c < 0x20ba)
+        charset[i++] = c++;
+    c = 0x20d0;
+    while (c < 0x20f1)
+        charset[i++] = c++;
+    c = 0x2100;
+    while (c < 0x218a)
+        charset[i++] = c++;
+    c = 0x2190;
+    while (c < 0x23f4)
+        charset[i++] = c++;
+    c = 0x2400;
+    while (c < 0x2427)
+        charset[i++] = c++;
+    c = 0x2440;
+    while (c < 0x244b)
+        charset[i++] = c++;
+    c = 0x2460;
+    while (c < 0x2700)
+        charset[i++] = c++;
+    c = 0x2701;
+    while (c < 0x27cb)
+        charset[i++] = c++;
+    c = 0x27ce;
+    while (c < 0x2b4d)
+        charset[i++] = c++;
+    c = 0x2b50;
+    while (c < 0x2b5a)
+        charset[i++] = c++;
+    c = 0x2c00;
+    while (c < 0x2c2f)
+        charset[i++] = c++;
+    c = 0x2c30;
+    while (c < 0x2c5f)
+        charset[i++] = c++;
+    c = 0x2c60;
+    while (c < 0x2cf2)
+        charset[i++] = c++;
+    c = 0x2cf9;
+    while (c < 0x2d26)
+        charset[i++] = c++;
+    c = 0x2d30;
+    while (c < 0x2d66)
+        charset[i++] = c++;
+    charset[i++] = 0x2d6f;
+    charset[i++] = 0x2d70;
+    c = 0x2d7f;
+    while (c < 0x2d97)
+        charset[i++] = c++;
+    c = 0x2da0;
+    while (c < 0x2da7)
+        charset[i++] = c++;
+    c = 0x2da8;
+    while (c < 0x2daf)
+        charset[i++] = c++;
+    c = 0x2db0;
+    while (c < 0x2db7)
+        charset[i++] = c++;
+    c = 0x2db8;
+    while (c < 0x2dbf)
+        charset[i++] = c++;
+    c = 0x2dc0;
+    while (c < 0x2dc7)
+        charset[i++] = c++;
+    c = 0x2dc8;
+    while (c < 0x2dcf)
+        charset[i++] = c++;
+    c = 0x2dd0;
+    while (c < 0x2dd7)
+        charset[i++] = c++;
+    c = 0x2dd8;
+    while (c < 0x2ddf)
+        charset[i++] = c++;
+    c = 0x2de0;
+    while (c < 0x2e32)
+        charset[i++] = c++;
+    c = 0x2e80;
+    while (c < 0x2e9a)
+        charset[i++] = c++;
+    c = 0x2e9b;
+    while (c < 0x2ef4)
+        charset[i++] = c++;
+    c = 0x2f00;
+    while (c < 0x2fd6)
+        charset[i++] = c++;
+    c = 0x2ff0;
+    while (c < 0x2ffc)
+        charset[i++] = c++;
+    c = 0x3000;
+    while (c < 0x3040)
+        charset[i++] = c++;
+    c = 0x3041;
+    while (c < 0x3097)
+        charset[i++] = c++;
+    c = 0x3099;
+    while (c < 0x3100)
+        charset[i++] = c++;
+    c = 0x3105;
+    while (c < 0x312e)
+        charset[i++] = c++;
+    c = 0x3131;
+    while (c < 0x318f)
+        charset[i++] = c++;
+    c = 0x3190;
+    while (c < 0x31bb)
+        charset[i++] = c++;
+    c = 0x31c0;
+    while (c < 0x31e4)
+        charset[i++] = c++;
+    c = 0x31f0;
+    while (c < 0x321f)
+        charset[i++] = c++;
+    c = 0x3220;
+    while (c < 0x32ff)
+        charset[i++] = c++;
+    c = 0x3300;
+    while (c < 0x3401)
+        charset[i++] = c++;
+    c = 0x4dc0;
+    while (c < 0x4e01)
+        charset[i++] = c++;
+    c = 0xa000;
+    while (c < 0xa48d)
+        charset[i++] = c++;
+    c = 0xa490;
+    while (c < 0xa4c7)
+        charset[i++] = c++;
+    c = 0xa4d0;
+    while (c < 0xa62c)
+        charset[i++] = c++;
+    c = 0xa640;
+    while (c < 0xa674)
+        charset[i++] = c++;
+    c = 0xa67c;
+    while (c < 0xa698)
+        charset[i++] = c++;
+    c = 0xa6a0;
+    while (c < 0xa6f8)
+        charset[i++] = c++;
+    c = 0xa700;
+    while (c < 0xa78f)
+        charset[i++] = c++;
+    charset[i++] = 0xa790;
+    charset[i++] = 0xa791;
+    c = 0xa7a0;
+    while (c < 0xa7aa)
+        charset[i++] = c++;
+    c = 0xa7fa;
+    while (c < 0xa82c)
+        charset[i++] = c++;
+    c = 0xa830;
+    while (c < 0xa83a)
+        charset[i++] = c++;
+    c = 0xa840;
+    while (c < 0xa878)
+        charset[i++] = c++;
+    c = 0xa880;
+    while (c < 0xa8c5)
+        charset[i++] = c++;
+    c = 0xa8ce;
+    while (c < 0xa8da)
+        charset[i++] = c++;
+    c = 0xa8e0;
+    while (c < 0xa8fc)
+        charset[i++] = c++;
+    c = 0xa900;
+    while (c < 0xa954)
+        charset[i++] = c++;
+    c = 0xa95f;
+    while (c < 0xa97d)
+        charset[i++] = c++;
+    c = 0xa980;
+    while (c < 0xa9ce)
+        charset[i++] = c++;
+    c = 0xa9cf;
+    while (c < 0xa9da)
+        charset[i++] = c++;
+    charset[i++] = 0xa9de;
+    charset[i++] = 0xa9df;
+    c = 0xaa00;
+    while (c < 0xaa37)
+        charset[i++] = c++;
+    c = 0xaa40;
+    while (c < 0xaa4e)
+        charset[i++] = c++;
+    c = 0xaa50;
+    while (c < 0xaa5a)
+        charset[i++] = c++;
+    c = 0xaa5c;
+    while (c < 0xaa7c)
+        charset[i++] = c++;
+    c = 0xaa80;
+    while (c < 0xaac3)
+        charset[i++] = c++;
+    c = 0xaadb;
+    while (c < 0xaae0)
+        charset[i++] = c++;
+    c = 0xab01;
+    while (c < 0xab07)
+        charset[i++] = c++;
+    c = 0xab09;
+    while (c < 0xab0f)
+        charset[i++] = c++;
+    c = 0xab11;
+    while (c < 0xab17)
+        charset[i++] = c++;
+    c = 0xab20;
+    while (c < 0xab27)
+        charset[i++] = c++;
+    c = 0xab28;
+    while (c < 0xab2f)
+        charset[i++] = c++;
+    c = 0xabc0;
+    while (c < 0xabee)
+        charset[i++] = c++;
+    c = 0xabf0;
+    while (c < 0xabfa)
+        charset[i++] = c++;
+    c = 0xd7b0;
+    while (c < 0xd7c7)
+        charset[i++] = c++;
+    c = 0xd7cb;
+    while (c < 0xd7fc)
+        charset[i++] = c++;
+    c = 0xf900;
+    while (c < 0xfa2e)
+        charset[i++] = c++;
+    c = 0xfa30;
+    while (c < 0xfa6e)
+        charset[i++] = c++;
+    c = 0xfa70;
+    while (c < 0xfada)
+        charset[i++] = c++;
+    c = 0xfb00;
+    while (c < 0xfb07)
+        charset[i++] = c++;
+    c = 0xfb13;
+    while (c < 0xfb18)
+        charset[i++] = c++;
+    c = 0xfb1d;
+    while (c < 0xfb37)
+        charset[i++] = c++;
+    c = 0xfb38;
+    while (c < 0xfb3d)
+        charset[i++] = c++;
+    charset[i++] = 0xfb40;
+    charset[i++] = 0xfb41;
+    charset[i++] = 0xfb43;
+    charset[i++] = 0xfb44;
+    c = 0xfb46;
+    while (c < 0xfbc2)
+        charset[i++] = c++;
+    c = 0xfbd3;
+    while (c < 0xfd40)
+        charset[i++] = c++;
+    c = 0xfd50;
+    while (c < 0xfd90)
+        charset[i++] = c++;
+    c = 0xfd92;
+    while (c < 0xfdc8)
+        charset[i++] = c++;
+    c = 0xfdf0;
+    while (c < 0xfdfe)
+        charset[i++] = c++;
+    c = 0xfe00;
+    while (c < 0xfe1a)
+        charset[i++] = c++;
+    c = 0xfe20;
+    while (c < 0xfe27)
+        charset[i++] = c++;
+    c = 0xfe30;
+    while (c < 0xfe53)
+        charset[i++] = c++;
+    c = 0xfe54;
+    while (c < 0xfe67)
+        charset[i++] = c++;
+    c = 0xfe68;
+    while (c < 0xfe6c)
+        charset[i++] = c++;
+    c = 0xfe70;
+    while (c < 0xfe75)
+        charset[i++] = c++;
+    c = 0xfe76;
+    while (c < 0xfefd)
+        charset[i++] = c++;
+    c = 0xff01;
+    while (c < 0xffbf)
+        charset[i++] = c++;
+    c = 0xffc2;
+    while (c < 0xffc8)
+        charset[i++] = c++;
+    c = 0xffca;
+    while (c < 0xffd0)
+        charset[i++] = c++;
+    c = 0xffd2;
+    while (c < 0xffd8)
+        charset[i++] = c++;
+    charset[i++] = 0xffda;
+    charset[i++] = 0xffdc;
+    c = 0xffe0;
+    while (c < 0xffe7)
+        charset[i++] = c++;
+    c = 0xffe8;
+    while (c < 0xffef)
+        charset[i++] = c++;
+
+/* Zero-terminate it, and cache the first character */
+	charset[i] = 0;
+	c0 = charset[0];
+
+	last = minlength - 1;
+	i = 0;
+	while (i <= last) {
+		id[i] = 0;
+		word16[i++] = c0;
+	}
+	lastid = -1;
+	word16[i] = 0;
+
+/* We must init word with dummy data, it doesn't get set until filter() */
+    word = 1;
+}
+
+void generate()
+{
+	int i;
+
+/* Handle the typical case specially */
+	if (word16[last] = charset[++lastid]) return;
+
+	lastid = 0;
+	word16[i = last] = c0;
+	while (i--) {			// Have a preceding position?
+		if (word16[i] = charset[++id[i]]) return;
+		id[i] = 0;
+		word16[i] = c0;
+	}
+
+	if (++last < maxlength) {	// Next length?
+		id[last] = lastid = 0;
+		word16[last] = c0;
+		word16[last + 1] = 0;
+	} else				// We're done
+		word16 = 0;
+}
+
+void restore()
+{
+	int i, c;
+
+/* Calculate the current length and infer the character indices */
+	last = 0;
+	while (c = word16[last]) {
+		i = 0; while (charset[i] != c && charset[i]) i++;
+		if (!charset[i]) i = 0;	// Not found
+		id[last++] = i;
+	}
+	lastid = id[--last];
+}
+
+/* Convert from UCS-2 to UTF-8 */
+void filter()
+{
+    int i, c;
+    i = -1; c = 0;
+
+    while (word16[++i]) {
+        if (word16[i] < 0x7f) {
+            word[c++] = word16[i];
+        }
+        else if (word16[i] < 0x0800) {
+            word[c++] = 0xc0 | (word16[i]>>6);
+            word[c++] = 0x80 | (word16[i] & 0x3f);
+        }
+        else {
+            word[c++] = 0xe0 | (word16[i]>>12);
+            word[c++] = 0x80 | (word16[i]>>6 & 0x3f);
+            word[c++] = 0x80 | (word16[i] & 0x3f);
+        }
+    }
+    word[c] = 0;
+}
+
+# Generic implementation of "dumb" exhaustive search of FULL Unicode and
+# an arbitrary charset. Default is to try *all* allocated characters (there's
+# 23296 of them). A fast format like NT can exhaust up to 3 characters in a
+# couple of weeks while four characters would take thousands of years...
+#
+# The output is UTF-8, so for 16-bit formats you need to give --enc=utf8
+[List.External:Dumb32]
+int maxlength;            // Maximum password length to try
+int last;                 // Last character position, zero-based
+int lastid;               // Character index in the last position
+int id[0x7f];             // Current character indices for other positions
+int charset[0x8000], c0;  // Characters (raise to 100000 for *all* codepoints)
+int word16[0x7F];         // Word in UCS-2
+
+void init()
+{
+	int minlength;
+	int i, c;
+
+	minlength = 1;	// Initial password length to try, must be at least 1
+	maxlength = 2;	// Must be at least same as minlength
+
+/*
+ * This defines the character set. This is auto-generated from UnicodeData.txt
+ * and we skip control characters.
+ */
+	i = 0;
+    c = 0x20;
+    while (c < 0x7f)
+        charset[i++] = c++;
+    c = 0xa0;
+    while (c < 0x378)
+        charset[i++] = c++;
+    c = 0x37a;
+    while (c < 0x37f)
+        charset[i++] = c++;
+    c = 0x384;
+    while (c < 0x38b)
+        charset[i++] = c++;
+    c = 0x38e;
+    while (c < 0x3a2)
+        charset[i++] = c++;
+    c = 0x3a3;
+    while (c < 0x528)
+        charset[i++] = c++;
+    c = 0x531;
+    while (c < 0x557)
+        charset[i++] = c++;
+    c = 0x559;
+    while (c < 0x560)
+        charset[i++] = c++;
+    c = 0x561;
+    while (c < 0x588)
+        charset[i++] = c++;
+    charset[i++] = 0x589;
+    charset[i++] = 0x58a;
+    c = 0x591;
+    while (c < 0x5c8)
+        charset[i++] = c++;
+    c = 0x5d0;
+    while (c < 0x5eb)
+        charset[i++] = c++;
+    c = 0x5f0;
+    while (c < 0x5f5)
+        charset[i++] = c++;
+    c = 0x600;
+    while (c < 0x604)
+        charset[i++] = c++;
+    c = 0x606;
+    while (c < 0x61c)
+        charset[i++] = c++;
+    c = 0x61e;
+    while (c < 0x70e)
+        charset[i++] = c++;
+    c = 0x70f;
+    while (c < 0x74b)
+        charset[i++] = c++;
+    c = 0x74d;
+    while (c < 0x7b2)
+        charset[i++] = c++;
+    c = 0x7c0;
+    while (c < 0x7fb)
+        charset[i++] = c++;
+    c = 0x800;
+    while (c < 0x82e)
+        charset[i++] = c++;
+    c = 0x830;
+    while (c < 0x83f)
+        charset[i++] = c++;
+    c = 0x840;
+    while (c < 0x85c)
+        charset[i++] = c++;
+    c = 0x900;
+    while (c < 0x978)
+        charset[i++] = c++;
+    c = 0x979;
+    while (c < 0x980)
+        charset[i++] = c++;
+    charset[i++] = 0x981;
+    charset[i++] = 0x983;
+    c = 0x985;
+    while (c < 0x98d)
+        charset[i++] = c++;
+    charset[i++] = 0x98f;
+    charset[i++] = 0x990;
+    c = 0x993;
+    while (c < 0x9a9)
+        charset[i++] = c++;
+    c = 0x9aa;
+    while (c < 0x9b1)
+        charset[i++] = c++;
+    c = 0x9b6;
+    while (c < 0x9ba)
+        charset[i++] = c++;
+    c = 0x9bc;
+    while (c < 0x9c5)
+        charset[i++] = c++;
+    charset[i++] = 0x9c7;
+    charset[i++] = 0x9c8;
+    c = 0x9cb;
+    while (c < 0x9cf)
+        charset[i++] = c++;
+    charset[i++] = 0x9dc;
+    charset[i++] = 0x9dd;
+    c = 0x9df;
+    while (c < 0x9e4)
+        charset[i++] = c++;
+    c = 0x9e6;
+    while (c < 0x9fc)
+        charset[i++] = c++;
+    charset[i++] = 0xa01;
+    charset[i++] = 0xa03;
+    c = 0xa05;
+    while (c < 0xa0b)
+        charset[i++] = c++;
+    charset[i++] = 0xa0f;
+    charset[i++] = 0xa10;
+    c = 0xa13;
+    while (c < 0xa29)
+        charset[i++] = c++;
+    c = 0xa2a;
+    while (c < 0xa31)
+        charset[i++] = c++;
+    charset[i++] = 0xa32;
+    charset[i++] = 0xa33;
+    charset[i++] = 0xa35;
+    charset[i++] = 0xa36;
+    charset[i++] = 0xa38;
+    charset[i++] = 0xa39;
+    c = 0xa3e;
+    while (c < 0xa43)
+        charset[i++] = c++;
+    charset[i++] = 0xa47;
+    charset[i++] = 0xa48;
+    charset[i++] = 0xa4b;
+    charset[i++] = 0xa4d;
+    c = 0xa59;
+    while (c < 0xa5d)
+        charset[i++] = c++;
+    c = 0xa66;
+    while (c < 0xa76)
+        charset[i++] = c++;
+    charset[i++] = 0xa81;
+    charset[i++] = 0xa83;
+    c = 0xa85;
+    while (c < 0xa8e)
+        charset[i++] = c++;
+    charset[i++] = 0xa8f;
+    charset[i++] = 0xa91;
+    c = 0xa93;
+    while (c < 0xaa9)
+        charset[i++] = c++;
+    c = 0xaaa;
+    while (c < 0xab1)
+        charset[i++] = c++;
+    charset[i++] = 0xab2;
+    charset[i++] = 0xab3;
+    c = 0xab5;
+    while (c < 0xaba)
+        charset[i++] = c++;
+    c = 0xabc;
+    while (c < 0xac6)
+        charset[i++] = c++;
+    charset[i++] = 0xac7;
+    charset[i++] = 0xac9;
+    charset[i++] = 0xacb;
+    charset[i++] = 0xacd;
+    c = 0xae0;
+    while (c < 0xae4)
+        charset[i++] = c++;
+    c = 0xae6;
+    while (c < 0xaf0)
+        charset[i++] = c++;
+    charset[i++] = 0xb01;
+    charset[i++] = 0xb03;
+    c = 0xb05;
+    while (c < 0xb0d)
+        charset[i++] = c++;
+    charset[i++] = 0xb0f;
+    charset[i++] = 0xb10;
+    c = 0xb13;
+    while (c < 0xb29)
+        charset[i++] = c++;
+    c = 0xb2a;
+    while (c < 0xb31)
+        charset[i++] = c++;
+    charset[i++] = 0xb32;
+    charset[i++] = 0xb33;
+    c = 0xb35;
+    while (c < 0xb3a)
+        charset[i++] = c++;
+    c = 0xb3c;
+    while (c < 0xb45)
+        charset[i++] = c++;
+    charset[i++] = 0xb47;
+    charset[i++] = 0xb48;
+    charset[i++] = 0xb4b;
+    charset[i++] = 0xb4d;
+    charset[i++] = 0xb56;
+    charset[i++] = 0xb57;
+    charset[i++] = 0xb5c;
+    charset[i++] = 0xb5d;
+    c = 0xb5f;
+    while (c < 0xb64)
+        charset[i++] = c++;
+    c = 0xb66;
+    while (c < 0xb78)
+        charset[i++] = c++;
+    charset[i++] = 0xb82;
+    charset[i++] = 0xb83;
+    c = 0xb85;
+    while (c < 0xb8b)
+        charset[i++] = c++;
+    charset[i++] = 0xb8e;
+    charset[i++] = 0xb90;
+    c = 0xb92;
+    while (c < 0xb96)
+        charset[i++] = c++;
+    charset[i++] = 0xb99;
+    charset[i++] = 0xb9a;
+    charset[i++] = 0xb9e;
+    charset[i++] = 0xb9f;
+    charset[i++] = 0xba3;
+    charset[i++] = 0xba4;
+    charset[i++] = 0xba8;
+    charset[i++] = 0xbaa;
+    c = 0xbae;
+    while (c < 0xbba)
+        charset[i++] = c++;
+    c = 0xbbe;
+    while (c < 0xbc3)
+        charset[i++] = c++;
+    charset[i++] = 0xbc6;
+    charset[i++] = 0xbc8;
+    c = 0xbca;
+    while (c < 0xbce)
+        charset[i++] = c++;
+    c = 0xbe6;
+    while (c < 0xbfb)
+        charset[i++] = c++;
+    charset[i++] = 0xc01;
+    charset[i++] = 0xc03;
+    c = 0xc05;
+    while (c < 0xc0d)
+        charset[i++] = c++;
+    charset[i++] = 0xc0e;
+    charset[i++] = 0xc10;
+    c = 0xc12;
+    while (c < 0xc29)
+        charset[i++] = c++;
+    c = 0xc2a;
+    while (c < 0xc34)
+        charset[i++] = c++;
+    c = 0xc35;
+    while (c < 0xc3a)
+        charset[i++] = c++;
+    c = 0xc3d;
+    while (c < 0xc45)
+        charset[i++] = c++;
+    charset[i++] = 0xc46;
+    charset[i++] = 0xc48;
+    c = 0xc4a;
+    while (c < 0xc4e)
+        charset[i++] = c++;
+    charset[i++] = 0xc55;
+    charset[i++] = 0xc56;
+    charset[i++] = 0xc58;
+    charset[i++] = 0xc59;
+    c = 0xc60;
+    while (c < 0xc64)
+        charset[i++] = c++;
+    c = 0xc66;
+    while (c < 0xc70)
+        charset[i++] = c++;
+    c = 0xc78;
+    while (c < 0xc80)
+        charset[i++] = c++;
+    charset[i++] = 0xc82;
+    charset[i++] = 0xc83;
+    c = 0xc85;
+    while (c < 0xc8d)
+        charset[i++] = c++;
+    charset[i++] = 0xc8e;
+    charset[i++] = 0xc90;
+    c = 0xc92;
+    while (c < 0xca9)
+        charset[i++] = c++;
+    c = 0xcaa;
+    while (c < 0xcb4)
+        charset[i++] = c++;
+    c = 0xcb5;
+    while (c < 0xcba)
+        charset[i++] = c++;
+    c = 0xcbc;
+    while (c < 0xcc5)
+        charset[i++] = c++;
+    charset[i++] = 0xcc6;
+    charset[i++] = 0xcc8;
+    c = 0xcca;
+    while (c < 0xcce)
+        charset[i++] = c++;
+    charset[i++] = 0xcd5;
+    charset[i++] = 0xcd6;
+    c = 0xce0;
+    while (c < 0xce4)
+        charset[i++] = c++;
+    c = 0xce6;
+    while (c < 0xcf0)
+        charset[i++] = c++;
+    charset[i++] = 0xcf1;
+    charset[i++] = 0xcf2;
+    charset[i++] = 0xd02;
+    charset[i++] = 0xd03;
+    c = 0xd05;
+    while (c < 0xd0d)
+        charset[i++] = c++;
+    charset[i++] = 0xd0e;
+    charset[i++] = 0xd10;
+    c = 0xd12;
+    while (c < 0xd3b)
+        charset[i++] = c++;
+    c = 0xd3d;
+    while (c < 0xd45)
+        charset[i++] = c++;
+    charset[i++] = 0xd46;
+    charset[i++] = 0xd48;
+    c = 0xd4a;
+    while (c < 0xd4f)
+        charset[i++] = c++;
+    c = 0xd60;
+    while (c < 0xd64)
+        charset[i++] = c++;
+    c = 0xd66;
+    while (c < 0xd76)
+        charset[i++] = c++;
+    c = 0xd79;
+    while (c < 0xd80)
+        charset[i++] = c++;
+    charset[i++] = 0xd82;
+    charset[i++] = 0xd83;
+    c = 0xd85;
+    while (c < 0xd97)
+        charset[i++] = c++;
+    c = 0xd9a;
+    while (c < 0xdb2)
+        charset[i++] = c++;
+    c = 0xdb3;
+    while (c < 0xdbc)
+        charset[i++] = c++;
+    c = 0xdc0;
+    while (c < 0xdc7)
+        charset[i++] = c++;
+    c = 0xdcf;
+    while (c < 0xdd5)
+        charset[i++] = c++;
+    c = 0xdd8;
+    while (c < 0xde0)
+        charset[i++] = c++;
+    charset[i++] = 0xdf2;
+    charset[i++] = 0xdf4;
+    c = 0xe01;
+    while (c < 0xe3b)
+        charset[i++] = c++;
+    c = 0xe3f;
+    while (c < 0xe5c)
+        charset[i++] = c++;
+    charset[i++] = 0xe81;
+    charset[i++] = 0xe82;
+    charset[i++] = 0xe87;
+    charset[i++] = 0xe88;
+    c = 0xe94;
+    while (c < 0xe98)
+        charset[i++] = c++;
+    c = 0xe99;
+    while (c < 0xea0)
+        charset[i++] = c++;
+    charset[i++] = 0xea1;
+    charset[i++] = 0xea3;
+    charset[i++] = 0xeaa;
+    charset[i++] = 0xeab;
+    c = 0xead;
+    while (c < 0xeba)
+        charset[i++] = c++;
+    charset[i++] = 0xebb;
+    charset[i++] = 0xebd;
+    c = 0xec0;
+    while (c < 0xec5)
+        charset[i++] = c++;
+    c = 0xec8;
+    while (c < 0xece)
+        charset[i++] = c++;
+    c = 0xed0;
+    while (c < 0xeda)
+        charset[i++] = c++;
+    charset[i++] = 0xedc;
+    charset[i++] = 0xedd;
+    c = 0xf00;
+    while (c < 0xf48)
+        charset[i++] = c++;
+    c = 0xf49;
+    while (c < 0xf6d)
+        charset[i++] = c++;
+    c = 0xf71;
+    while (c < 0xf98)
+        charset[i++] = c++;
+    c = 0xf99;
+    while (c < 0xfbd)
+        charset[i++] = c++;
+    c = 0xfbe;
+    while (c < 0xfcd)
+        charset[i++] = c++;
+    c = 0xfce;
+    while (c < 0xfdb)
+        charset[i++] = c++;
+    c = 0x1000;
+    while (c < 0x10c6)
+        charset[i++] = c++;
+    c = 0x10d0;
+    while (c < 0x10fd)
+        charset[i++] = c++;
+    c = 0x1100;
+    while (c < 0x1249)
+        charset[i++] = c++;
+    c = 0x124a;
+    while (c < 0x124e)
+        charset[i++] = c++;
+    c = 0x1250;
+    while (c < 0x1257)
+        charset[i++] = c++;
+    c = 0x125a;
+    while (c < 0x125e)
+        charset[i++] = c++;
+    c = 0x1260;
+    while (c < 0x1289)
+        charset[i++] = c++;
+    c = 0x128a;
+    while (c < 0x128e)
+        charset[i++] = c++;
+    c = 0x1290;
+    while (c < 0x12b1)
+        charset[i++] = c++;
+    c = 0x12b2;
+    while (c < 0x12b6)
+        charset[i++] = c++;
+    c = 0x12b8;
+    while (c < 0x12bf)
+        charset[i++] = c++;
+    c = 0x12c2;
+    while (c < 0x12c6)
+        charset[i++] = c++;
+    c = 0x12c8;
+    while (c < 0x12d7)
+        charset[i++] = c++;
+    c = 0x12d8;
+    while (c < 0x1311)
+        charset[i++] = c++;
+    c = 0x1312;
+    while (c < 0x1316)
+        charset[i++] = c++;
+    c = 0x1318;
+    while (c < 0x135b)
+        charset[i++] = c++;
+    c = 0x135d;
+    while (c < 0x137d)
+        charset[i++] = c++;
+    c = 0x1380;
+    while (c < 0x139a)
+        charset[i++] = c++;
+    c = 0x13a0;
+    while (c < 0x13f5)
+        charset[i++] = c++;
+    c = 0x1400;
+    while (c < 0x169d)
+        charset[i++] = c++;
+    c = 0x16a0;
+    while (c < 0x16f1)
+        charset[i++] = c++;
+    c = 0x1700;
+    while (c < 0x170d)
+        charset[i++] = c++;
+    c = 0x170e;
+    while (c < 0x1715)
+        charset[i++] = c++;
+    c = 0x1720;
+    while (c < 0x1737)
+        charset[i++] = c++;
+    c = 0x1740;
+    while (c < 0x1754)
+        charset[i++] = c++;
+    c = 0x1760;
+    while (c < 0x176d)
+        charset[i++] = c++;
+    charset[i++] = 0x176e;
+    charset[i++] = 0x1770;
+    charset[i++] = 0x1772;
+    charset[i++] = 0x1773;
+    c = 0x1780;
+    while (c < 0x17de)
+        charset[i++] = c++;
+    c = 0x17e0;
+    while (c < 0x17ea)
+        charset[i++] = c++;
+    c = 0x17f0;
+    while (c < 0x17fa)
+        charset[i++] = c++;
+    c = 0x1800;
+    while (c < 0x180f)
+        charset[i++] = c++;
+    c = 0x1810;
+    while (c < 0x181a)
+        charset[i++] = c++;
+    c = 0x1820;
+    while (c < 0x1878)
+        charset[i++] = c++;
+    c = 0x1880;
+    while (c < 0x18ab)
+        charset[i++] = c++;
+    c = 0x18b0;
+    while (c < 0x18f6)
+        charset[i++] = c++;
+    c = 0x1900;
+    while (c < 0x191d)
+        charset[i++] = c++;
+    c = 0x1920;
+    while (c < 0x192c)
+        charset[i++] = c++;
+    c = 0x1930;
+    while (c < 0x193c)
+        charset[i++] = c++;
+    c = 0x1944;
+    while (c < 0x196e)
+        charset[i++] = c++;
+    c = 0x1970;
+    while (c < 0x1975)
+        charset[i++] = c++;
+    c = 0x1980;
+    while (c < 0x19ac)
+        charset[i++] = c++;
+    c = 0x19b0;
+    while (c < 0x19ca)
+        charset[i++] = c++;
+    c = 0x19d0;
+    while (c < 0x19db)
+        charset[i++] = c++;
+    c = 0x19de;
+    while (c < 0x1a1c)
+        charset[i++] = c++;
+    c = 0x1a1e;
+    while (c < 0x1a5f)
+        charset[i++] = c++;
+    c = 0x1a60;
+    while (c < 0x1a7d)
+        charset[i++] = c++;
+    c = 0x1a7f;
+    while (c < 0x1a8a)
+        charset[i++] = c++;
+    c = 0x1a90;
+    while (c < 0x1a9a)
+        charset[i++] = c++;
+    c = 0x1aa0;
+    while (c < 0x1aae)
+        charset[i++] = c++;
+    c = 0x1b00;
+    while (c < 0x1b4c)
+        charset[i++] = c++;
+    c = 0x1b50;
+    while (c < 0x1b7d)
+        charset[i++] = c++;
+    c = 0x1b80;
+    while (c < 0x1bab)
+        charset[i++] = c++;
+    c = 0x1bae;
+    while (c < 0x1bba)
+        charset[i++] = c++;
+    c = 0x1bc0;
+    while (c < 0x1bf4)
+        charset[i++] = c++;
+    c = 0x1bfc;
+    while (c < 0x1c38)
+        charset[i++] = c++;
+    c = 0x1c3b;
+    while (c < 0x1c4a)
+        charset[i++] = c++;
+    c = 0x1c4d;
+    while (c < 0x1c80)
+        charset[i++] = c++;
+    c = 0x1cd0;
+    while (c < 0x1cf3)
+        charset[i++] = c++;
+    c = 0x1d00;
+    while (c < 0x1de7)
+        charset[i++] = c++;
+    c = 0x1dfc;
+    while (c < 0x1f16)
+        charset[i++] = c++;
+    c = 0x1f18;
+    while (c < 0x1f1e)
+        charset[i++] = c++;
+    c = 0x1f20;
+    while (c < 0x1f46)
+        charset[i++] = c++;
+    c = 0x1f48;
+    while (c < 0x1f4e)
+        charset[i++] = c++;
+    c = 0x1f50;
+    while (c < 0x1f58)
+        charset[i++] = c++;
+    c = 0x1f5f;
+    while (c < 0x1f7e)
+        charset[i++] = c++;
+    c = 0x1f80;
+    while (c < 0x1fb5)
+        charset[i++] = c++;
+    c = 0x1fb6;
+    while (c < 0x1fc5)
+        charset[i++] = c++;
+    c = 0x1fc6;
+    while (c < 0x1fd4)
+        charset[i++] = c++;
+    c = 0x1fd6;
+    while (c < 0x1fdc)
+        charset[i++] = c++;
+    c = 0x1fdd;
+    while (c < 0x1ff0)
+        charset[i++] = c++;
+    charset[i++] = 0x1ff2;
+    charset[i++] = 0x1ff4;
+    c = 0x1ff6;
+    while (c < 0x1fff)
+        charset[i++] = c++;
+    c = 0x2000;
+    while (c < 0x2065)
+        charset[i++] = c++;
+    c = 0x206a;
+    while (c < 0x2072)
+        charset[i++] = c++;
+    c = 0x2074;
+    while (c < 0x208f)
+        charset[i++] = c++;
+    c = 0x2090;
+    while (c < 0x209d)
+        charset[i++] = c++;
+    c = 0x20a0;
+    while (c < 0x20ba)
+        charset[i++] = c++;
+    c = 0x20d0;
+    while (c < 0x20f1)
+        charset[i++] = c++;
+    c = 0x2100;
+    while (c < 0x218a)
+        charset[i++] = c++;
+    c = 0x2190;
+    while (c < 0x23f4)
+        charset[i++] = c++;
+    c = 0x2400;
+    while (c < 0x2427)
+        charset[i++] = c++;
+    c = 0x2440;
+    while (c < 0x244b)
+        charset[i++] = c++;
+    c = 0x2460;
+    while (c < 0x2700)
+        charset[i++] = c++;
+    c = 0x2701;
+    while (c < 0x27cb)
+        charset[i++] = c++;
+    c = 0x27ce;
+    while (c < 0x2b4d)
+        charset[i++] = c++;
+    c = 0x2b50;
+    while (c < 0x2b5a)
+        charset[i++] = c++;
+    c = 0x2c00;
+    while (c < 0x2c2f)
+        charset[i++] = c++;
+    c = 0x2c30;
+    while (c < 0x2c5f)
+        charset[i++] = c++;
+    c = 0x2c60;
+    while (c < 0x2cf2)
+        charset[i++] = c++;
+    c = 0x2cf9;
+    while (c < 0x2d26)
+        charset[i++] = c++;
+    c = 0x2d30;
+    while (c < 0x2d66)
+        charset[i++] = c++;
+    charset[i++] = 0x2d6f;
+    charset[i++] = 0x2d70;
+    c = 0x2d7f;
+    while (c < 0x2d97)
+        charset[i++] = c++;
+    c = 0x2da0;
+    while (c < 0x2da7)
+        charset[i++] = c++;
+    c = 0x2da8;
+    while (c < 0x2daf)
+        charset[i++] = c++;
+    c = 0x2db0;
+    while (c < 0x2db7)
+        charset[i++] = c++;
+    c = 0x2db8;
+    while (c < 0x2dbf)
+        charset[i++] = c++;
+    c = 0x2dc0;
+    while (c < 0x2dc7)
+        charset[i++] = c++;
+    c = 0x2dc8;
+    while (c < 0x2dcf)
+        charset[i++] = c++;
+    c = 0x2dd0;
+    while (c < 0x2dd7)
+        charset[i++] = c++;
+    c = 0x2dd8;
+    while (c < 0x2ddf)
+        charset[i++] = c++;
+    c = 0x2de0;
+    while (c < 0x2e32)
+        charset[i++] = c++;
+    c = 0x2e80;
+    while (c < 0x2e9a)
+        charset[i++] = c++;
+    c = 0x2e9b;
+    while (c < 0x2ef4)
+        charset[i++] = c++;
+    c = 0x2f00;
+    while (c < 0x2fd6)
+        charset[i++] = c++;
+    c = 0x2ff0;
+    while (c < 0x2ffc)
+        charset[i++] = c++;
+    c = 0x3000;
+    while (c < 0x3040)
+        charset[i++] = c++;
+    c = 0x3041;
+    while (c < 0x3097)
+        charset[i++] = c++;
+    c = 0x3099;
+    while (c < 0x3100)
+        charset[i++] = c++;
+    c = 0x3105;
+    while (c < 0x312e)
+        charset[i++] = c++;
+    c = 0x3131;
+    while (c < 0x318f)
+        charset[i++] = c++;
+    c = 0x3190;
+    while (c < 0x31bb)
+        charset[i++] = c++;
+    c = 0x31c0;
+    while (c < 0x31e4)
+        charset[i++] = c++;
+    c = 0x31f0;
+    while (c < 0x321f)
+        charset[i++] = c++;
+    c = 0x3220;
+    while (c < 0x32ff)
+        charset[i++] = c++;
+    c = 0x3300;
+    while (c < 0x3401)
+        charset[i++] = c++;
+    c = 0x4dc0;
+    while (c < 0x4e01)
+        charset[i++] = c++;
+    c = 0xa000;
+    while (c < 0xa48d)
+        charset[i++] = c++;
+    c = 0xa490;
+    while (c < 0xa4c7)
+        charset[i++] = c++;
+    c = 0xa4d0;
+    while (c < 0xa62c)
+        charset[i++] = c++;
+    c = 0xa640;
+    while (c < 0xa674)
+        charset[i++] = c++;
+    c = 0xa67c;
+    while (c < 0xa698)
+        charset[i++] = c++;
+    c = 0xa6a0;
+    while (c < 0xa6f8)
+        charset[i++] = c++;
+    c = 0xa700;
+    while (c < 0xa78f)
+        charset[i++] = c++;
+    charset[i++] = 0xa790;
+    charset[i++] = 0xa791;
+    c = 0xa7a0;
+    while (c < 0xa7aa)
+        charset[i++] = c++;
+    c = 0xa7fa;
+    while (c < 0xa82c)
+        charset[i++] = c++;
+    c = 0xa830;
+    while (c < 0xa83a)
+        charset[i++] = c++;
+    c = 0xa840;
+    while (c < 0xa878)
+        charset[i++] = c++;
+    c = 0xa880;
+    while (c < 0xa8c5)
+        charset[i++] = c++;
+    c = 0xa8ce;
+    while (c < 0xa8da)
+        charset[i++] = c++;
+    c = 0xa8e0;
+    while (c < 0xa8fc)
+        charset[i++] = c++;
+    c = 0xa900;
+    while (c < 0xa954)
+        charset[i++] = c++;
+    c = 0xa95f;
+    while (c < 0xa97d)
+        charset[i++] = c++;
+    c = 0xa980;
+    while (c < 0xa9ce)
+        charset[i++] = c++;
+    c = 0xa9cf;
+    while (c < 0xa9da)
+        charset[i++] = c++;
+    charset[i++] = 0xa9de;
+    charset[i++] = 0xa9df;
+    c = 0xaa00;
+    while (c < 0xaa37)
+        charset[i++] = c++;
+    c = 0xaa40;
+    while (c < 0xaa4e)
+        charset[i++] = c++;
+    c = 0xaa50;
+    while (c < 0xaa5a)
+        charset[i++] = c++;
+    c = 0xaa5c;
+    while (c < 0xaa7c)
+        charset[i++] = c++;
+    c = 0xaa80;
+    while (c < 0xaac3)
+        charset[i++] = c++;
+    c = 0xaadb;
+    while (c < 0xaae0)
+        charset[i++] = c++;
+    c = 0xab01;
+    while (c < 0xab07)
+        charset[i++] = c++;
+    c = 0xab09;
+    while (c < 0xab0f)
+        charset[i++] = c++;
+    c = 0xab11;
+    while (c < 0xab17)
+        charset[i++] = c++;
+    c = 0xab20;
+    while (c < 0xab27)
+        charset[i++] = c++;
+    c = 0xab28;
+    while (c < 0xab2f)
+        charset[i++] = c++;
+    c = 0xabc0;
+    while (c < 0xabee)
+        charset[i++] = c++;
+    c = 0xabf0;
+    while (c < 0xabfa)
+        charset[i++] = c++;
+    c = 0xd7b0;
+    while (c < 0xd7c7)
+        charset[i++] = c++;
+    c = 0xd7cb;
+    while (c < 0xd7fc)
+        charset[i++] = c++;
+    c = 0xf900;
+    while (c < 0xfa2e)
+        charset[i++] = c++;
+    c = 0xfa30;
+    while (c < 0xfa6e)
+        charset[i++] = c++;
+    c = 0xfa70;
+    while (c < 0xfada)
+        charset[i++] = c++;
+    c = 0xfb00;
+    while (c < 0xfb07)
+        charset[i++] = c++;
+    c = 0xfb13;
+    while (c < 0xfb18)
+        charset[i++] = c++;
+    c = 0xfb1d;
+    while (c < 0xfb37)
+        charset[i++] = c++;
+    c = 0xfb38;
+    while (c < 0xfb3d)
+        charset[i++] = c++;
+    charset[i++] = 0xfb40;
+    charset[i++] = 0xfb41;
+    charset[i++] = 0xfb43;
+    charset[i++] = 0xfb44;
+    c = 0xfb46;
+    while (c < 0xfbc2)
+        charset[i++] = c++;
+    c = 0xfbd3;
+    while (c < 0xfd40)
+        charset[i++] = c++;
+    c = 0xfd50;
+    while (c < 0xfd90)
+        charset[i++] = c++;
+    c = 0xfd92;
+    while (c < 0xfdc8)
+        charset[i++] = c++;
+    c = 0xfdf0;
+    while (c < 0xfdfe)
+        charset[i++] = c++;
+    c = 0xfe00;
+    while (c < 0xfe1a)
+        charset[i++] = c++;
+    c = 0xfe20;
+    while (c < 0xfe27)
+        charset[i++] = c++;
+    c = 0xfe30;
+    while (c < 0xfe53)
+        charset[i++] = c++;
+    c = 0xfe54;
+    while (c < 0xfe67)
+        charset[i++] = c++;
+    c = 0xfe68;
+    while (c < 0xfe6c)
+        charset[i++] = c++;
+    c = 0xfe70;
+    while (c < 0xfe75)
+        charset[i++] = c++;
+    c = 0xfe76;
+    while (c < 0xfefd)
+        charset[i++] = c++;
+    c = 0xff01;
+    while (c < 0xffbf)
+        charset[i++] = c++;
+    c = 0xffc2;
+    while (c < 0xffc8)
+        charset[i++] = c++;
+    c = 0xffca;
+    while (c < 0xffd0)
+        charset[i++] = c++;
+    c = 0xffd2;
+    while (c < 0xffd8)
+        charset[i++] = c++;
+    charset[i++] = 0xffda;
+    charset[i++] = 0xffdc;
+    c = 0xffe0;
+    while (c < 0xffe7)
+        charset[i++] = c++;
+    c = 0xffe8;
+    while (c < 0xffef)
+        charset[i++] = c++;
+    c = 0xfff9;
+    while (c < 0xfffe)
+        charset[i++] = c++;
+    c = 0x10000;
+    while (c < 0x1000c)
+        charset[i++] = c++;
+    c = 0x1000d;
+    while (c < 0x10027)
+        charset[i++] = c++;
+    c = 0x10028;
+    while (c < 0x1003b)
+        charset[i++] = c++;
+    charset[i++] = 0x1003c;
+    charset[i++] = 0x1003d;
+    c = 0x1003f;
+    while (c < 0x1004e)
+        charset[i++] = c++;
+    c = 0x10050;
+    while (c < 0x1005e)
+        charset[i++] = c++;
+    c = 0x10080;
+    while (c < 0x100fb)
+        charset[i++] = c++;
+    charset[i++] = 0x10100;
+    charset[i++] = 0x10102;
+    c = 0x10107;
+    while (c < 0x10134)
+        charset[i++] = c++;
+    c = 0x10137;
+    while (c < 0x1018b)
+        charset[i++] = c++;
+    c = 0x10190;
+    while (c < 0x1019c)
+        charset[i++] = c++;
+    c = 0x101d0;
+    while (c < 0x101fe)
+        charset[i++] = c++;
+    c = 0x10280;
+    while (c < 0x1029d)
+        charset[i++] = c++;
+    c = 0x102a0;
+    while (c < 0x102d1)
+        charset[i++] = c++;
+    c = 0x10300;
+    while (c < 0x1031f)
+        charset[i++] = c++;
+    c = 0x10320;
+    while (c < 0x10324)
+        charset[i++] = c++;
+    c = 0x10330;
+    while (c < 0x1034b)
+        charset[i++] = c++;
+    c = 0x10380;
+    while (c < 0x1039e)
+        charset[i++] = c++;
+    c = 0x1039f;
+    while (c < 0x103c4)
+        charset[i++] = c++;
+    c = 0x103c8;
+    while (c < 0x103d6)
+        charset[i++] = c++;
+    c = 0x10400;
+    while (c < 0x1049e)
+        charset[i++] = c++;
+    c = 0x104a0;
+    while (c < 0x104aa)
+        charset[i++] = c++;
+    c = 0x10800;
+    while (c < 0x10806)
+        charset[i++] = c++;
+    c = 0x1080a;
+    while (c < 0x10836)
+        charset[i++] = c++;
+    charset[i++] = 0x10837;
+    charset[i++] = 0x10838;
+    c = 0x1083f;
+    while (c < 0x10856)
+        charset[i++] = c++;
+    c = 0x10857;
+    while (c < 0x10860)
+        charset[i++] = c++;
+    c = 0x10900;
+    while (c < 0x1091c)
+        charset[i++] = c++;
+    c = 0x1091f;
+    while (c < 0x1093a)
+        charset[i++] = c++;
+    c = 0x10a00;
+    while (c < 0x10a04)
+        charset[i++] = c++;
+    charset[i++] = 0x10a05;
+    charset[i++] = 0x10a06;
+    c = 0x10a0c;
+    while (c < 0x10a14)
+        charset[i++] = c++;
+    charset[i++] = 0x10a15;
+    charset[i++] = 0x10a17;
+    c = 0x10a19;
+    while (c < 0x10a34)
+        charset[i++] = c++;
+    charset[i++] = 0x10a38;
+    charset[i++] = 0x10a3a;
+    c = 0x10a3f;
+    while (c < 0x10a48)
+        charset[i++] = c++;
+    c = 0x10a50;
+    while (c < 0x10a59)
+        charset[i++] = c++;
+    c = 0x10a60;
+    while (c < 0x10a80)
+        charset[i++] = c++;
+    c = 0x10b00;
+    while (c < 0x10b36)
+        charset[i++] = c++;
+    c = 0x10b39;
+    while (c < 0x10b56)
+        charset[i++] = c++;
+    c = 0x10b58;
+    while (c < 0x10b73)
+        charset[i++] = c++;
+    c = 0x10b78;
+    while (c < 0x10b80)
+        charset[i++] = c++;
+    c = 0x10c00;
+    while (c < 0x10c49)
+        charset[i++] = c++;
+    c = 0x10e60;
+    while (c < 0x10e7f)
+        charset[i++] = c++;
+    c = 0x11000;
+    while (c < 0x1104e)
+        charset[i++] = c++;
+    c = 0x11052;
+    while (c < 0x11070)
+        charset[i++] = c++;
+    c = 0x11080;
+    while (c < 0x110c2)
+        charset[i++] = c++;
+    c = 0x12000;
+    while (c < 0x1236f)
+        charset[i++] = c++;
+    c = 0x12400;
+    while (c < 0x12463)
+        charset[i++] = c++;
+    c = 0x12470;
+    while (c < 0x12474)
+        charset[i++] = c++;
+    c = 0x13000;
+    while (c < 0x1342f)
+        charset[i++] = c++;
+    c = 0x16800;
+    while (c < 0x16a39)
+        charset[i++] = c++;
+    charset[i++] = 0x1b000;
+    charset[i++] = 0x1b001;
+    c = 0x1d000;
+    while (c < 0x1d0f6)
+        charset[i++] = c++;
+    c = 0x1d100;
+    while (c < 0x1d127)
+        charset[i++] = c++;
+    c = 0x1d129;
+    while (c < 0x1d1de)
+        charset[i++] = c++;
+    c = 0x1d200;
+    while (c < 0x1d246)
+        charset[i++] = c++;
+    c = 0x1d300;
+    while (c < 0x1d357)
+        charset[i++] = c++;
+    c = 0x1d360;
+    while (c < 0x1d372)
+        charset[i++] = c++;
+    c = 0x1d400;
+    while (c < 0x1d455)
+        charset[i++] = c++;
+    c = 0x1d456;
+    while (c < 0x1d49d)
+        charset[i++] = c++;
+    charset[i++] = 0x1d49e;
+    charset[i++] = 0x1d49f;
+    charset[i++] = 0x1d4a5;
+    charset[i++] = 0x1d4a6;
+    c = 0x1d4a9;
+    while (c < 0x1d4ad)
+        charset[i++] = c++;
+    c = 0x1d4ae;
+    while (c < 0x1d4ba)
+        charset[i++] = c++;
+    c = 0x1d4bd;
+    while (c < 0x1d4c4)
+        charset[i++] = c++;
+    c = 0x1d4c5;
+    while (c < 0x1d506)
+        charset[i++] = c++;
+    c = 0x1d507;
+    while (c < 0x1d50b)
+        charset[i++] = c++;
+    c = 0x1d50d;
+    while (c < 0x1d515)
+        charset[i++] = c++;
+    c = 0x1d516;
+    while (c < 0x1d51d)
+        charset[i++] = c++;
+    c = 0x1d51e;
+    while (c < 0x1d53a)
+        charset[i++] = c++;
+    c = 0x1d53b;
+    while (c < 0x1d53f)
+        charset[i++] = c++;
+    c = 0x1d540;
+    while (c < 0x1d545)
+        charset[i++] = c++;
+    c = 0x1d54a;
+    while (c < 0x1d551)
+        charset[i++] = c++;
+    c = 0x1d552;
+    while (c < 0x1d6a6)
+        charset[i++] = c++;
+    c = 0x1d6a8;
+    while (c < 0x1d7cc)
+        charset[i++] = c++;
+    c = 0x1d7ce;
+    while (c < 0x1d800)
+        charset[i++] = c++;
+    c = 0x1f000;
+    while (c < 0x1f02c)
+        charset[i++] = c++;
+    c = 0x1f030;
+    while (c < 0x1f094)
+        charset[i++] = c++;
+    c = 0x1f0a0;
+    while (c < 0x1f0af)
+        charset[i++] = c++;
+    c = 0x1f0b1;
+    while (c < 0x1f0bf)
+        charset[i++] = c++;
+    c = 0x1f0c1;
+    while (c < 0x1f0d0)
+        charset[i++] = c++;
+    c = 0x1f0d1;
+    while (c < 0x1f0e0)
+        charset[i++] = c++;
+    c = 0x1f100;
+    while (c < 0x1f10b)
+        charset[i++] = c++;
+    c = 0x1f110;
+    while (c < 0x1f12f)
+        charset[i++] = c++;
+    c = 0x1f130;
+    while (c < 0x1f16a)
+        charset[i++] = c++;
+    c = 0x1f170;
+    while (c < 0x1f19b)
+        charset[i++] = c++;
+    c = 0x1f1e6;
+    while (c < 0x1f203)
+        charset[i++] = c++;
+    c = 0x1f210;
+    while (c < 0x1f23b)
+        charset[i++] = c++;
+    c = 0x1f240;
+    while (c < 0x1f249)
+        charset[i++] = c++;
+    charset[i++] = 0x1f250;
+    charset[i++] = 0x1f251;
+    c = 0x1f300;
+    while (c < 0x1f321)
+        charset[i++] = c++;
+    c = 0x1f330;
+    while (c < 0x1f336)
+        charset[i++] = c++;
+    c = 0x1f337;
+    while (c < 0x1f37d)
+        charset[i++] = c++;
+    c = 0x1f380;
+    while (c < 0x1f394)
+        charset[i++] = c++;
+    c = 0x1f3a0;
+    while (c < 0x1f3c5)
+        charset[i++] = c++;
+    c = 0x1f3c6;
+    while (c < 0x1f3cb)
+        charset[i++] = c++;
+    c = 0x1f3e0;
+    while (c < 0x1f3f1)
+        charset[i++] = c++;
+    c = 0x1f400;
+    while (c < 0x1f43f)
+        charset[i++] = c++;
+    c = 0x1f442;
+    while (c < 0x1f4f8)
+        charset[i++] = c++;
+    c = 0x1f4f9;
+    while (c < 0x1f4fd)
+        charset[i++] = c++;
+    c = 0x1f500;
+    while (c < 0x1f53e)
+        charset[i++] = c++;
+    c = 0x1f550;
+    while (c < 0x1f568)
+        charset[i++] = c++;
+    c = 0x1f5fb;
+    while (c < 0x1f600)
+        charset[i++] = c++;
+    c = 0x1f601;
+    while (c < 0x1f611)
+        charset[i++] = c++;
+    charset[i++] = 0x1f612;
+    charset[i++] = 0x1f614;
+    charset[i++] = 0x1f61c;
+    charset[i++] = 0x1f61e;
+    c = 0x1f620;
+    while (c < 0x1f626)
+        charset[i++] = c++;
+    c = 0x1f628;
+    while (c < 0x1f62c)
+        charset[i++] = c++;
+    c = 0x1f630;
+    while (c < 0x1f634)
+        charset[i++] = c++;
+    c = 0x1f635;
+    while (c < 0x1f641)
+        charset[i++] = c++;
+    c = 0x1f645;
+    while (c < 0x1f650)
+        charset[i++] = c++;
+    c = 0x1f680;
+    while (c < 0x1f6c6)
+        charset[i++] = c++;
+    c = 0x1f700;
+    while (c < 0x1f774)
+        charset[i++] = c++;
+    c = 0x2f800;
+    while (c < 0x2fa1e)
+        charset[i++] = c++;
+    c = 0xe0020;
+    while (c < 0xe0080)
+        charset[i++] = c++;
+
+/* Zero-terminate it, and cache the first character */
+	charset[i] = 0;
+	c0 = charset[0];
+
+	last = minlength - 1;
+	i = 0;
+	while (i <= last) {
+		id[i] = 0;
+		word16[i++] = c0;
+	}
+	lastid = -1;
+	word16[i] = 0;
+
+/* We must init word with dummy data, it doesn't get set until filter() */
+    word = 1;
+}
+
+void generate()
+{
+	int i;
+
+/* Handle the typical case specially */
+	if (word16[last] = charset[++lastid]) return;
+
+	lastid = 0;
+	word16[i = last] = c0;
+	while (i--) {			// Have a preceding position?
+		if (word16[i] = charset[++id[i]]) return;
+		id[i] = 0;
+		word16[i] = c0;
+	}
+
+	if (++last < maxlength) {	// Next length?
+		id[last] = lastid = 0;
+		word16[last] = c0;
+		word16[last + 1] = 0;
+	} else				// We're done
+		word16 = 0;
+}
+
+void restore()
+{
+	int i, c;
+
+/* Calculate the current length and infer the character indices */
+	last = 0;
+	while (c = word16[last]) {
+		i = 0; while (charset[i] != c && charset[i]) i++;
+		if (!charset[i]) i = 0;	// Not found
+		id[last++] = i;
+	}
+	lastid = id[--last];
+}
+
+/* Convert from UTF-32 to UTF-8 */
+void filter()
+{
+    int i, c;
+    i = -1; c = 0;
+
+    while (word16[++i]) {
+        if (word16[i] < 0x7f) {
+            word[c++] = word16[i];
+        }
+        else if (word16[i] < 0x0800) {
+            word[c++] = 0xc0 | (word16[i]>>6);
+            word[c++] = 0x80 | (word16[i] & 0x3f);
+        }
+        else if (word16[i] < 0x10000) {
+            word[c++] = 0xe0 | (word16[i]>>12);
+            word[c++] = 0x80 | (word16[i]>>6 & 0x3f);
+            word[c++] = 0x80 | (word16[i] & 0x3f);
+        }
+        else {
+            word[c++] = 0xf0 | (word16[i]>>18);
+            word[c++] = 0x80 | (word16[i]>>12 & 0x3f);
+            word[c++] = 0x80 | (word16[i]>>6 & 0x3f);
+            word[c++] = 0x80 | (word16[i] & 0x3f);
+        }
+    }
+    word[c] = 0;
+}
+
 # Generic implementation of "dumb" exhaustive search, given a range of lengths
 # and an arbitrary charset.  This is pre-configured to try 8-bit characters
 # against LM hashes, which is only reasonable to do for very short password
-- 
1.7.4.1

