summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Scribunto/includes
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Scribunto/includes')
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/ApiScribuntoConsole.php150
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/Base.php361
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/Common.php209
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/Hooks.php397
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/ScribuntoContent.php160
-rw-r--r--www/wiki/extensions/Scribunto/includes/common/ScribuntoContentHandler.php52
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HashLibrary.php44
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HtmlLibrary.php11
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LanguageLibrary.php364
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LibraryBase.php181
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaCommon.php1063
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaInterpreter.php68
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/MessageLibrary.php59
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/SiteLibrary.php189
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TextLibrary.php142
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TitleLibrary.php381
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UriLibrary.php56
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UstringLibrary.php781
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/bit32.lua209
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/libraryUtil.lua71
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/bit.lua264
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/hex.lua99
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/readme.txt143
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.hash.lua30
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.html.lua433
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.language.lua189
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.lua784
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.message.lua198
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.site.lua86
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.text.lua330
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.title.lua337
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.uri.lua623
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.ustring.lua108
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mwInit.lua143
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/package.lua127
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/README51
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/charsets.lua3117
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/lower.lua679
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-normalization-table.php237
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-tables.php154
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/normalization-data.lua9450
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/string.lua15
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/upper.lua715
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/ustring.lua1242
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaSandbox/Engine.php401
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneEngine.php781
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/MWServer.lua710
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/README39
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/generic.patch22
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win32_bin/lua5.1.exebin0 -> 409600 bytes
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win64_bin/lua5.1.exebin0 -> 483328 bytes
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_32_generic/luabin0 -> 171697 bytes
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_64_generic/luabin0 -> 195508 bytes
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_mac_lion_fat_generic/luabin0 -> 201644 bytes
-rwxr-xr-xwww/wiki/extensions/Scribunto/includes/engines/LuaStandalone/lua_ulimit.sh7
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/mw_main.lua8
-rw-r--r--www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/protocol.txt176
57 files changed, 26646 insertions, 0 deletions
diff --git a/www/wiki/extensions/Scribunto/includes/common/ApiScribuntoConsole.php b/www/wiki/extensions/Scribunto/includes/common/ApiScribuntoConsole.php
new file mode 100644
index 00000000..22f29668
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/ApiScribuntoConsole.php
@@ -0,0 +1,150 @@
+<?php
+
+/**
+ * API module for serving debug console requests on the edit page
+ */
+
+class ApiScribuntoConsole extends ApiBase {
+ const SC_MAX_SIZE = 500000;
+ const SC_SESSION_EXPIRY = 3600;
+
+ public function execute() {
+ $params = $this->extractRequestParams();
+
+ $title = Title::newFromText( $params['title'] );
+ if ( !$title ) {
+ $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
+ }
+
+ if ( $params['session'] ) {
+ $sessionId = $params['session'];
+ } else {
+ $sessionId = mt_rand( 0, 0x7fffffff );
+ }
+
+ $cache = ObjectCache::getInstance( CACHE_ANYTHING );
+ $sessionKey = $cache->makeKey( 'scribunto-console', $this->getUser()->getId(), $sessionId );
+ $session = null;
+ $sessionIsNew = false;
+ if ( $params['session'] ) {
+ $session = $cache->get( $sessionKey );
+ }
+ if ( !isset( $session['version'] ) ) {
+ $session = $this->newSession();
+ $sessionIsNew = true;
+ }
+
+ // Create a variable holding the session which will be stored if there
+ // are no errors. If there are errors, we don't want to store the current
+ // question to the state builder array, since that will cause subsequent
+ // requests to fail.
+ $newSession = $session;
+
+ if ( !empty( $params['clear'] ) ) {
+ $newSession['size'] -= strlen( implode( '', $newSession['questions'] ) );
+ $newSession['questions'] = [];
+ $session['questions'] = [];
+ }
+ if ( strlen( $params['question'] ) ) {
+ $newSession['size'] += strlen( $params['question'] );
+ $newSession['questions'][] = $params['question'];
+ }
+ if ( $params['content'] ) {
+ $newSession['size'] += strlen( $params['content'] ) - strlen( $newSession['content'] );
+ $newSession['content'] = $params['content'];
+ }
+
+ if ( $newSession['size'] > self::SC_MAX_SIZE ) {
+ $this->dieWithError( 'scribunto-console-too-large' );
+ }
+ $result = $this->runConsole( [
+ 'title' => $title,
+ 'content' => $newSession['content'],
+ 'prevQuestions' => $session['questions'],
+ 'question' => $params['question'],
+ ] );
+
+ if ( $result['type'] === 'error' ) {
+ // Restore the questions array
+ $newSession['questions'] = $session['questions'];
+ }
+ $cache->set( $sessionKey, $newSession, self::SC_SESSION_EXPIRY );
+ $result['session'] = $sessionId;
+ $result['sessionSize'] = $newSession['size'];
+ $result['sessionMaxSize'] = self::SC_MAX_SIZE;
+ if ( $sessionIsNew ) {
+ $result['sessionIsNew'] = '';
+ }
+ foreach ( $result as $key => $value ) {
+ $this->getResult()->addValue( null, $key, $value );
+ }
+ }
+
+ protected function runConsole( array $params ) {
+ global $wgParser;
+ $options = new ParserOptions;
+ $wgParser->startExternalParse( $params['title'], $options, Parser::OT_HTML, true );
+ $engine = Scribunto::getParserEngine( $wgParser );
+ try {
+ $result = $engine->runConsole( $params );
+ } catch ( ScribuntoException $e ) {
+ $trace = $e->getScriptTraceHtml();
+ $message = $e->getMessage();
+ $html = Html::element( 'p', [], $message );
+ if ( $trace !== false ) {
+ $html .= Html::element( 'p',
+ [],
+ $this->msg( 'scribunto-common-backtrace' )->inContentLanguage()->text()
+ ) . $trace;
+ }
+
+ return [
+ 'type' => 'error',
+ 'html' => $html,
+ 'message' => $message,
+ 'messagename' => $e->getMessageName() ];
+ }
+ return [
+ 'type' => 'normal',
+ 'print' => strval( $result['print'] ),
+ 'return' => strval( $result['return'] )
+ ];
+ }
+
+ /**
+ * @return array
+ */
+ protected function newSession() {
+ return [
+ 'content' => '',
+ 'questions' => [],
+ 'size' => 0,
+ 'version' => 1,
+ ];
+ }
+
+ public function isInternal() {
+ return true;
+ }
+
+ public function getAllowedParams() {
+ return [
+ 'title' => [
+ ApiBase::PARAM_TYPE => 'string',
+ ],
+ 'content' => [
+ ApiBase::PARAM_TYPE => 'string'
+ ],
+ 'session' => [
+ ApiBase::PARAM_TYPE => 'integer',
+ ],
+ 'question' => [
+ ApiBase::PARAM_TYPE => 'string',
+ ApiBase::PARAM_REQUIRED => true,
+ ],
+ 'clear' => [
+ ApiBase::PARAM_TYPE => 'boolean',
+ ],
+ ];
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/common/Base.php b/www/wiki/extensions/Scribunto/includes/common/Base.php
new file mode 100644
index 00000000..e6c78111
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/Base.php
@@ -0,0 +1,361 @@
+<?php
+
+/**
+ * Wikitext scripting infrastructure for MediaWiki: base classes.
+ * Copyright (C) 2012 Victor Vasiliev <vasilvv@gmail.com> et al
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/**
+ * Base class for all script engines. Includes all code
+ * not related to particular modules, like tracking links between
+ * modules or loading module texts.
+ */
+abstract class ScribuntoEngineBase {
+
+ // Flags for ScribuntoEngineBase::getResourceUsage()
+ const CPU_SECONDS = 1;
+ const MEM_PEAK_BYTES = 2;
+
+ /**
+ * @var Title
+ */
+ protected $title;
+
+ /**
+ * @var array
+ */
+ protected $options;
+
+ /**
+ * @var ScribuntoModuleBase[]
+ */
+ protected $modules = [];
+
+ /**
+ * @var Parser
+ */
+ protected $parser;
+
+ /**
+ * Creates a new module object within this engine
+ *
+ * @param string $text
+ * @param string|bool $chunkName
+ * @return ScribuntoModuleBase
+ */
+ abstract protected function newModule( $text, $chunkName );
+
+ /**
+ * Run an interactive console request
+ *
+ * @param array $params Associative array. Options are:
+ * - title: The title object for the module being debugged
+ * - content: The text content of the module
+ * - prevQuestions: An array of previous "questions" used to establish the state
+ * - question: The current "question", a string script
+ *
+ * @return array containing:
+ * - print: The resulting print buffer
+ * - return: The resulting return value
+ */
+ abstract function runConsole( array $params );
+
+ /**
+ * Get software information for Special:Version
+ * @param array &$software
+ */
+ abstract public function getSoftwareInfo( array &$software );
+
+ /**
+ * @param array $options Associative array of options:
+ * - parser: A Parser object
+ */
+ public function __construct( array $options ) {
+ $this->options = $options;
+ if ( isset( $options['parser'] ) ) {
+ $this->parser = $options['parser'];
+ }
+ if ( isset( $options['title'] ) ) {
+ $this->title = $options['title'];
+ }
+ }
+
+ public function __destruct() {
+ $this->destroy();
+ }
+
+ public function destroy() {
+ // Break reference cycles
+ $this->parser = null;
+ $this->title = null;
+ $this->modules = null;
+ }
+
+ /**
+ * @param Title $title
+ */
+ public function setTitle( $title ) {
+ $this->title = $title;
+ }
+
+ /**
+ * @return Title
+ */
+ public function getTitle() {
+ return $this->title;
+ }
+
+ /**
+ * Get an element from the configuration array
+ *
+ * @param string $optionName
+ * @return mixed
+ */
+ public function getOption( $optionName ) {
+ return isset( $this->options[$optionName] )
+ ? $this->options[$optionName] : null;
+ }
+
+ /**
+ * @param string $message
+ * @param array $params
+ * @return ScribuntoException
+ */
+ public function newException( $message, array $params = [] ) {
+ return new ScribuntoException( $message, $this->getDefaultExceptionParams() + $params );
+ }
+
+ /**
+ * @return array
+ */
+ public function getDefaultExceptionParams() {
+ $params = [];
+ if ( $this->title ) {
+ $params['title'] = $this->title;
+ }
+ return $params;
+ }
+
+ /**
+ * Load a module from some parser-defined template loading mechanism and
+ * register a parser output dependency.
+ *
+ * Does not initialize the module, i.e. do not expect it to complain if the module
+ * text is garbage or has syntax error. Returns a module or null if it doesn't exist.
+ *
+ * @param Title $title The title of the module
+ * @return ScribuntoModuleBase|null
+ */
+ function fetchModuleFromParser( Title $title ) {
+ $key = $title->getPrefixedDBkey();
+ if ( !array_key_exists( $key, $this->modules ) ) {
+ list( $text, $finalTitle ) = $this->parser->fetchTemplateAndTitle( $title );
+ if ( $text === false ) {
+ $this->modules[$key] = null;
+ return null;
+ }
+
+ $finalKey = $finalTitle->getPrefixedDBkey();
+ if ( !isset( $this->modules[$finalKey] ) ) {
+ $this->modules[$finalKey] = $this->newModule( $text, $finalKey );
+ }
+ // Almost certainly $key === $finalKey, but just in case...
+ $this->modules[$key] = $this->modules[$finalKey];
+ }
+ return $this->modules[$key];
+ }
+
+ /**
+ * Validates the script and returns a Status object containing the syntax
+ * errors for the given code.
+ *
+ * @param string $text
+ * @param string|bool $chunkName
+ * @return Status
+ */
+ function validate( $text, $chunkName = false ) {
+ $module = $this->newModule( $text, $chunkName );
+ return $module->validate();
+ }
+
+ /**
+ * Get CPU and memory usage information, if the script engine
+ * provides it.
+ *
+ * If the script engine is capable of reporting CPU and memory usage
+ * data, it should override this implementation.
+ *
+ * @param int $resource One of ScribuntoEngineBase::CPU_SECONDS
+ * or ScribuntoEngineBase::MEM_PEAK_BYTES.
+ * @return float|int|false Resource usage for the specified resource
+ * or false if not available.
+ */
+ public function getResourceUsage( $resource ) {
+ return false;
+ }
+
+ /**
+ * Get the language for GeSHi syntax highlighter.
+ * @return string|false
+ */
+ function getGeSHiLanguage() {
+ return false;
+ }
+
+ /**
+ * Get the language for Ace code editor.
+ * @return string|false
+ */
+ function getCodeEditorLanguage() {
+ return false;
+ }
+
+ /**
+ * @return Parser
+ */
+ public function getParser() {
+ return $this->parser;
+ }
+
+ /**
+ * Load a list of all libraries supported by this engine
+ *
+ * The return value is an array with keys being the library name seen by
+ * the module and values being either a PHP class name or an array with the
+ * following elements:
+ * - class: (string) Class to load (required)
+ * - deferLoad: (bool) Library should not be loaded at startup; modules
+ * needing the library must request it (e.g. via 'require' in Lua)
+ *
+ * @param string $engine script engine we're using (eg: lua)
+ * @param array $coreLibraries Array of core libraries we support
+ * @return array
+ */
+ protected function getLibraries( $engine, array $coreLibraries = [] ) {
+ $extraLibraries = [];
+ Hooks::run( 'ScribuntoExternalLibraries', [ $engine, &$extraLibraries ] );
+ return $coreLibraries + $extraLibraries;
+ }
+
+ /**
+ * Load a list of all paths libraries can be in for this engine
+ *
+ * @param string $engine script engine we're using (eg: lua)
+ * @param array $coreLibraryPaths Array of library paths to use by default
+ * @return array
+ */
+ protected function getLibraryPaths( $engine, array $coreLibraryPaths = [] ) {
+ $extraLibraryPaths = [];
+ Hooks::run( 'ScribuntoExternalLibraryPaths', [ $engine, &$extraLibraryPaths ] );
+ return array_merge( $coreLibraryPaths, $extraLibraryPaths );
+ }
+
+ /**
+ * Add limit report data to a ParserOutput object
+ *
+ * @param ParserOutput $output ParserOutput object in which to add limit data
+ * @return null
+ */
+ public function reportLimitData( ParserOutput $output ) {
+ }
+
+ /**
+ * Format limit report data
+ *
+ * @param string $key
+ * @param mixed &$value
+ * @param string &$report
+ * @param bool $isHTML
+ * @param bool $localize
+ * @return bool
+ */
+ public function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) {
+ return true;
+ }
+}
+
+/**
+ * Class that represents a module. Responsible for initial module parsing
+ * and maintaining the contents of the module.
+ */
+abstract class ScribuntoModuleBase {
+ /**
+ * @var ScribuntoEngineBase
+ */
+ protected $engine;
+
+ /**
+ * @var string
+ */
+ protected $code;
+
+ /**
+ * @var string|bool
+ */
+ protected $chunkName;
+
+ /**
+ * @param ScribuntoEngineBase $engine
+ * @param string $code
+ * @param string|bool $chunkName
+ */
+ public function __construct( ScribuntoEngineBase $engine, $code, $chunkName ) {
+ $this->engine = $engine;
+ $this->code = $code;
+ $this->chunkName = $chunkName;
+ }
+
+ /**
+ * @return ScribuntoEngineBase
+ */
+ public function getEngine() {
+ return $this->engine;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCode() {
+ return $this->code;
+ }
+
+ /**
+ * @return string|bool
+ */
+ public function getChunkName() {
+ return $this->chunkName;
+ }
+
+ /**
+ * Validates the script and returns a Status object containing the syntax
+ * errors for the given code.
+ *
+ * @return Status
+ */
+ abstract public function validate();
+
+ /**
+ * Invoke the function with the specified name.
+ *
+ * @param string $name
+ * @param PPFrame $frame
+ * @return string
+ */
+ abstract public function invoke( $name, $frame );
+}
diff --git a/www/wiki/extensions/Scribunto/includes/common/Common.php b/www/wiki/extensions/Scribunto/includes/common/Common.php
new file mode 100644
index 00000000..e92e615b
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/Common.php
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * Static function collection for general extension support.
+ */
+class Scribunto {
+ const LOCAL = 'local';
+
+ /**
+ * Create a new engine object with specified parameters.
+ *
+ * @param array $options
+ * @return ScribuntoEngineBase
+ */
+ public static function newEngine( $options ) {
+ if ( isset( $options['factory'] ) ) {
+ return call_user_func( $options['factory'], $options );
+ } else {
+ $class = $options['class'];
+ return new $class( $options );
+ }
+ }
+
+ /**
+ * Create a new engine object with default parameters
+ *
+ * @param array $extraOptions Extra options to pass to the constructor,
+ * in addition to the configured options
+ * @throws MWException
+ * @return ScribuntoEngineBase
+ */
+ public static function newDefaultEngine( $extraOptions = [] ) {
+ global $wgScribuntoDefaultEngine, $wgScribuntoEngineConf;
+ if ( !$wgScribuntoDefaultEngine ) {
+ throw new MWException(
+ 'Scribunto extension is enabled but $wgScribuntoDefaultEngine is not set'
+ );
+ }
+
+ if ( !isset( $wgScribuntoEngineConf[$wgScribuntoDefaultEngine] ) ) {
+ throw new MWException( 'Invalid scripting engine is specified in $wgScribuntoDefaultEngine' );
+ }
+ $options = $extraOptions + $wgScribuntoEngineConf[$wgScribuntoDefaultEngine];
+ return self::newEngine( $options );
+ }
+
+ /**
+ * Get an engine instance for the given parser, and cache it in the parser
+ * so that subsequent calls to this function for the same parser will return
+ * the same engine.
+ *
+ * @param Parser $parser
+ * @return ScribuntoEngineBase
+ */
+ public static function getParserEngine( Parser $parser ) {
+ if ( empty( $parser->scribunto_engine ) ) {
+ $parser->scribunto_engine = self::newDefaultEngine( [ 'parser' => $parser ] );
+ $parser->scribunto_engine->setTitle( $parser->getTitle() );
+ }
+ return $parser->scribunto_engine;
+ }
+
+ /**
+ * Check if an engine instance is present in the given parser
+ *
+ * @param Parser $parser
+ * @return bool
+ */
+ public static function isParserEnginePresent( Parser $parser ) {
+ return !empty( $parser->scribunto_engine );
+ }
+
+ /**
+ * Remove the current engine instance from the parser
+ * @param Parser $parser
+ */
+ public static function resetParserEngine( Parser $parser ) {
+ if ( !empty( $parser->scribunto_engine ) ) {
+ $parser->scribunto_engine->destroy();
+ $parser->scribunto_engine = null;
+ }
+ }
+
+ /**
+ * Test whether the page should be considered a documentation page
+ *
+ * @param Title $title
+ * @param Title|null &$forModule Module for which this is a doc page
+ * @return bool
+ */
+ public static function isDocPage( Title $title, Title &$forModule = null ) {
+ $docPage = wfMessage( 'scribunto-doc-page-name' )->inContentLanguage();
+ if ( $docPage->isDisabled() ) {
+ return false;
+ }
+
+ // Canonicalize the input pseudo-title. The unreplaced "$1" shouldn't
+ // cause a problem.
+ $docTitle = Title::newFromText( $docPage->plain() );
+ if ( !$docTitle ) {
+ return false;
+ }
+ $docPage = $docTitle->getPrefixedText();
+
+ // Make it into a regex, and match it against the input title
+ $docPage = str_replace( '\\$1', '(.+)', preg_quote( $docPage, '/' ) );
+ if ( preg_match( "/^$docPage$/", $title->getPrefixedText(), $m ) ) {
+ $forModule = Title::makeTitleSafe( NS_MODULE, $m[1] );
+ return $forModule !== null;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Return the Title for the documentation page
+ *
+ * @param Title $title
+ * @return Title|null
+ */
+ public static function getDocPage( Title $title ) {
+ $docPage = wfMessage( 'scribunto-doc-page-name', $title->getText() )->inContentLanguage();
+ if ( $docPage->isDisabled() ) {
+ return null;
+ }
+
+ return Title::newFromText( $docPage->plain() );
+ }
+}
+
+/**
+ * An exception class which represents an error in the script. This does not
+ * normally abort the request, instead it is caught and shown to the user.
+ */
+class ScribuntoException extends MWException {
+ /**
+ * @var string
+ */
+ public $messageName;
+
+ /**
+ * @var array
+ */
+ public $messageArgs;
+
+ /**
+ * @var array
+ */
+ public $params;
+
+ /**
+ * @param string $messageName
+ * @param array $params
+ */
+ function __construct( $messageName, $params = [] ) {
+ if ( isset( $params['args'] ) ) {
+ $this->messageArgs = $params['args'];
+ } else {
+ $this->messageArgs = [];
+ }
+ if ( isset( $params['module'] ) && isset( $params['line'] ) ) {
+ $codeLocation = false;
+ if ( isset( $params['title'] ) ) {
+ $moduleTitle = Title::newFromText( $params['module'] );
+ if ( $moduleTitle && $moduleTitle->equals( $params['title'] ) ) {
+ $codeLocation = wfMessage( 'scribunto-line', $params['line'] )->inContentLanguage()->text();
+ }
+ }
+ if ( $codeLocation === false ) {
+ $codeLocation = wfMessage(
+ 'scribunto-module-line',
+ $params['module'],
+ $params['line']
+ )->inContentLanguage()->text();
+ }
+ } else {
+ $codeLocation = '[UNKNOWN]';
+ }
+ array_unshift( $this->messageArgs, $codeLocation );
+ $msg = wfMessage( $messageName )->params( $this->messageArgs )->inContentLanguage()->text();
+ parent::__construct( $msg );
+
+ $this->messageName = $messageName;
+ $this->params = $params;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMessageName() {
+ return $this->messageName;
+ }
+
+ public function toStatus() {
+ $args = array_merge( [ $this->messageName ], $this->messageArgs );
+ $status = call_user_func_array( [ 'Status', 'newFatal' ], $args );
+ $status->scribunto_error = $this;
+ return $status;
+ }
+
+ /**
+ * Get the backtrace as HTML, or false if there is none available.
+ * @param array $options
+ * @return bool|string
+ */
+ public function getScriptTraceHtml( $options = [] ) {
+ return false;
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/common/Hooks.php b/www/wiki/extensions/Scribunto/includes/common/Hooks.php
new file mode 100644
index 00000000..9ad63731
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/Hooks.php
@@ -0,0 +1,397 @@
+<?php
+/**
+ * Wikitext scripting infrastructure for MediaWiki: hooks.
+ * Copyright (C) 2009-2012 Victor Vasiliev <vasilvv@gmail.com>
+ * http://www.mediawiki.org/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+use MediaWiki\MediaWikiServices;
+use UtfNormal\Validator;
+use Wikimedia\PSquare;
+
+/**
+ * Hooks for the Scribunto extension.
+ */
+class ScribuntoHooks {
+
+ /**
+ * Define content handler constant upon extension registration
+ */
+ public static function onRegistration() {
+ define( 'CONTENT_MODEL_SCRIBUNTO', 'Scribunto' );
+ }
+
+ /**
+ * Get software information for Special:Version
+ *
+ * @param array &$software
+ * @return bool
+ */
+ public static function getSoftwareInfo( array &$software ) {
+ $engine = Scribunto::newDefaultEngine();
+ $engine->setTitle( Title::makeTitle( NS_SPECIAL, 'Version' ) );
+ $engine->getSoftwareInfo( $software );
+ return true;
+ }
+
+ /**
+ * Register parser hooks.
+ *
+ * @param Parser &$parser
+ * @return bool
+ */
+ public static function setupParserHook( Parser &$parser ) {
+ $parser->setFunctionHook( 'invoke', 'ScribuntoHooks::invokeHook', Parser::SFH_OBJECT_ARGS );
+ return true;
+ }
+
+ /**
+ * Called when the interpreter is to be reset.
+ *
+ * @param Parser &$parser
+ * @return bool
+ */
+ public static function clearState( Parser &$parser ) {
+ Scribunto::resetParserEngine( $parser );
+ return true;
+ }
+
+ /**
+ * Called when the parser is cloned
+ *
+ * @param Parser $parser
+ * @return bool
+ */
+ public static function parserCloned( Parser $parser ) {
+ $parser->scribunto_engine = null;
+ return true;
+ }
+
+ /**
+ * Hook function for {{#invoke:module|func}}
+ *
+ * @param Parser &$parser
+ * @param PPFrame $frame
+ * @param array $args
+ * @throws MWException
+ * @throws ScribuntoException
+ * @return string
+ */
+ public static function invokeHook( Parser &$parser, PPFrame $frame, array $args ) {
+ global $wgScribuntoGatherFunctionStats;
+
+ try {
+ if ( count( $args ) < 2 ) {
+ throw new ScribuntoException( 'scribunto-common-nofunction' );
+ }
+ $moduleName = trim( $frame->expand( $args[0] ) );
+ $engine = Scribunto::getParserEngine( $parser );
+
+ $title = Title::makeTitleSafe( NS_MODULE, $moduleName );
+ if ( !$title || !$title->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ throw new ScribuntoException( 'scribunto-common-nosuchmodule',
+ [ 'args' => [ $moduleName ] ] );
+ }
+ $module = $engine->fetchModuleFromParser( $title );
+ if ( !$module ) {
+ throw new ScribuntoException( 'scribunto-common-nosuchmodule',
+ [ 'args' => [ $moduleName ] ] );
+ }
+ $functionName = trim( $frame->expand( $args[1] ) );
+
+ $bits = $args[1]->splitArg();
+ unset( $args[0] );
+ unset( $args[1] );
+
+ // If $bits['index'] is empty, then the function name was parsed as a
+ // key=value pair (because of an equals sign in it), and since it didn't
+ // have an index, we don't need the index offset.
+ $childFrame = $frame->newChild( $args, $title, $bits['index'] === '' ? 0 : 1 );
+
+ if ( $wgScribuntoGatherFunctionStats ) {
+ $u0 = $engine->getResourceUsage( $engine::CPU_SECONDS );
+ $result = $module->invoke( $functionName, $childFrame );
+ $u1 = $engine->getResourceUsage( $engine::CPU_SECONDS );
+
+ if ( $u1 > $u0 ) {
+ $timingMs = (int)( 1000 * ( $u1 - $u0 ) );
+ // Since the overhead of stats is worst when when #invoke
+ // calls are very short, don't process measurements <= 20ms.
+ if ( $timingMs > 20 ) {
+ self::reportTiming( $moduleName, $functionName, $timingMs );
+ }
+ }
+ } else {
+ $result = $module->invoke( $functionName, $childFrame );
+ }
+
+ return Validator::cleanUp( strval( $result ) );
+ } catch ( ScribuntoException $e ) {
+ $trace = $e->getScriptTraceHtml( [ 'msgOptions' => [ 'content' ] ] );
+ $html = Html::element( 'p', [], $e->getMessage() );
+ if ( $trace !== false ) {
+ $html .= Html::element( 'p',
+ [],
+ wfMessage( 'scribunto-common-backtrace' )->inContentLanguage()->text()
+ ) . $trace;
+ } else {
+ $html .= Html::element( 'p',
+ [],
+ wfMessage( 'scribunto-common-no-details' )->inContentLanguage()->text()
+ );
+ }
+ $out = $parser->getOutput();
+ $errors = $out->getExtensionData( 'ScribuntoErrors' );
+ if ( $errors === null ) {
+ // On first hook use, set up error array and output
+ $errors = [];
+ $parser->addTrackingCategory( 'scribunto-common-error-category' );
+ $out->addModules( 'ext.scribunto.errors' );
+ }
+ $errors[] = $html;
+ $out->setExtensionData( 'ScribuntoErrors', $errors );
+ $out->addJsConfigVars( 'ScribuntoErrors', $errors );
+ $id = 'mw-scribunto-error-' . ( count( $errors ) - 1 );
+ $parserError = htmlspecialchars( $e->getMessage() );
+
+ // #iferror-compatible error element
+ return "<strong class=\"error\"><span class=\"scribunto-error\" id=\"$id\">" .
+ $parserError. "</span></strong>";
+ }
+ }
+
+ /**
+ * Record stats on slow function calls.
+ *
+ * @param string $moduleName
+ * @param string $functionName
+ * @param int $timing Function execution time in milliseconds.
+ */
+ public static function reportTiming( $moduleName, $functionName, $timing ) {
+ global $wgScribuntoGatherFunctionStats, $wgScribuntoSlowFunctionThreshold;
+
+ if ( !$wgScribuntoGatherFunctionStats ) {
+ return;
+ }
+
+ $threshold = $wgScribuntoSlowFunctionThreshold;
+ if ( !( is_float( $threshold ) && $threshold > 0 && $threshold < 1 ) ) {
+ return;
+ }
+
+ static $cache;
+
+ if ( !$cache ) {
+ $cache = ObjectCache::getLocalServerInstance( CACHE_NONE );
+
+ }
+
+ // To control the sampling rate, we keep a compact histogram of
+ // observations in APC, and extract the Nth percentile (specified
+ // via $wgScribuntoSlowFunctionThreshold; defaults to 0.90).
+ // We need APC and \Wikimedia\PSquare to do that.
+ if ( !class_exists( PSquare::class ) || $cache instanceof EmptyBagOStuff ) {
+ return;
+ }
+
+ $cacheVersion = '1';
+ $key = $cache->makeGlobalKey( __METHOD__, $cacheVersion, $threshold );
+
+ // This is a classic "read-update-write" critical section with no
+ // mutual exclusion, but the only consequence is that some samples
+ // will be dropped. We only need enough samples to estimate the
+ // the shape of the data, so that's fine.
+ $ps = $cache->get( $key ) ?: new PSquare( $threshold );
+ $ps->addObservation( $timing );
+ $cache->set( $key, $ps, 60 );
+
+ if ( $ps->getCount() < 1000 || $timing < $ps->getValue() ) {
+ return;
+ }
+
+ static $stats;
+
+ if ( !$stats ) {
+ $stats = MediaWikiServices::getInstance()->getStatsdDataFactory();
+ }
+
+ $metricKey = sprintf( 'scribunto.traces.%s__%s__%s', wfWikiId(), $moduleName, $functionName );
+ $stats->timing( $metricKey, $timing );
+ }
+
+ /**
+ * @param Title $title
+ * @param string &$languageCode
+ * @return bool
+ */
+ public static function getCodeLanguage( Title $title, &$languageCode ) {
+ global $wgScribuntoUseCodeEditor;
+ if ( $wgScribuntoUseCodeEditor && $title->hasContentModel( CONTENT_MODEL_SCRIBUNTO )
+ ) {
+ $engine = Scribunto::newDefaultEngine();
+ if ( $engine->getCodeEditorLanguage() ) {
+ $languageCode = $engine->getCodeEditorLanguage();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Set the Scribunto content handler for modules
+ *
+ * @param Title $title
+ * @param string &$model
+ * @return bool
+ */
+ public static function contentHandlerDefaultModelFor( Title $title, &$model ) {
+ if ( $title->getNamespace() == NS_MODULE && !Scribunto::isDocPage( $title ) ) {
+ $model = CONTENT_MODEL_SCRIBUNTO;
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Adds report of number of evaluations by the single wikitext page.
+ *
+ * @param Parser $parser
+ * @param ParserOutput $output
+ * @return bool
+ */
+ public static function reportLimitData( Parser $parser, ParserOutput $output ) {
+ if ( Scribunto::isParserEnginePresent( $parser ) ) {
+ $engine = Scribunto::getParserEngine( $parser );
+ $engine->reportLimitData( $output );
+ }
+ return true;
+ }
+
+ /**
+ * Formats the limit report data
+ *
+ * @param string $key
+ * @param mixed &$value
+ * @param string &$report
+ * @param bool $isHTML
+ * @param bool $localize
+ * @return bool
+ */
+ public static function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) {
+ $engine = Scribunto::newDefaultEngine();
+ return $engine->formatLimitData( $key, $value, $report, $isHTML, $localize );
+ }
+
+ /**
+ * EditPage::showStandardInputs:options hook
+ *
+ * @param EditPage $editor
+ * @param OutputPage $output
+ * @param int &$tab Current tabindex
+ * @return bool
+ */
+ public static function showStandardInputsOptions( EditPage $editor, OutputPage $output, &$tab ) {
+ if ( $editor->getTitle()->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ $output->addModules( 'ext.scribunto.edit' );
+ $editor->editFormTextAfterTools .= '<div id="mw-scribunto-console"></div>';
+ }
+ return true;
+ }
+
+ /**
+ * EditPage::showReadOnlyForm:initial hook
+ *
+ * @param EditPage $editor
+ * @param OutputPage $output
+ * @return bool
+ */
+ public static function showReadOnlyFormInitial( EditPage $editor, OutputPage $output ) {
+ if ( $editor->getTitle()->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ $output->addModules( 'ext.scribunto.edit' );
+ $editor->editFormTextAfterContent .= '<div id="mw-scribunto-console"></div>';
+ }
+ return true;
+ }
+
+ /**
+ * EditPageBeforeEditButtons hook
+ *
+ * @param EditPage &$editor
+ * @param array &$buttons Button array
+ * @param int &$tabindex Current tabindex
+ * @return bool
+ */
+ public static function beforeEditButtons( EditPage &$editor, array &$buttons, &$tabindex ) {
+ if ( $editor->getTitle()->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ unset( $buttons['preview'] );
+ }
+ return true;
+ }
+
+ /**
+ * @param IContextSource $context
+ * @param Content $content
+ * @param Status $status
+ * @return bool
+ */
+ public static function validateScript( IContextSource $context, Content $content,
+ Status $status
+ ) {
+ $title = $context->getTitle();
+
+ if ( !$content instanceof ScribuntoContent ) {
+ return true;
+ }
+
+ /** @suppress PhanUndeclaredMethod */
+ $validateStatus = $content->validate( $title );
+ if ( $validateStatus->isOK() ) {
+ return true;
+ }
+
+ $status->merge( $validateStatus );
+
+ if ( isset( $validateStatus->scribunto_error->params['module'] ) ) {
+ $module = $validateStatus->scribunto_error->params['module'];
+ $line = $validateStatus->scribunto_error->params['line'];
+ if ( $module === $title->getPrefixedDBkey() && preg_match( '/^\d+$/', $line ) ) {
+ $out = $context->getOutput();
+ $out->addInlineScript( 'window.location.hash = ' . Xml::encodeJsVar( "#mw-ce-l$line" ) );
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @param Article &$article
+ * @param bool &$outputDone
+ * @param bool &$pcache
+ * @return bool
+ */
+ public static function showDocPageHeader( Article &$article, &$outputDone, &$pcache ) {
+ $title = $article->getTitle();
+ if ( Scribunto::isDocPage( $title, $forModule ) ) {
+ $article->getContext()->getOutput()->addHTML(
+ wfMessage( 'scribunto-doc-page-header', $forModule->getPrefixedText() )->parseAsBlock()
+ );
+ }
+ return true;
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/common/ScribuntoContent.php b/www/wiki/extensions/Scribunto/includes/common/ScribuntoContent.php
new file mode 100644
index 00000000..ff2ec8e4
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/ScribuntoContent.php
@@ -0,0 +1,160 @@
+<?php
+/**
+ * Scribunto Content Model
+ *
+ * @file
+ * @ingroup Extensions
+ * @ingroup Scribunto
+ *
+ * @author Brad Jorsch <bjorsch@wikimedia.org>
+ */
+
+/**
+ * Represents the content of a Scribunto script page
+ */
+class ScribuntoContent extends TextContent {
+
+ function __construct( $text ) {
+ parent::__construct( $text, CONTENT_MODEL_SCRIBUNTO );
+ }
+
+ /**
+ * Checks whether the script is valid
+ *
+ * @param Title $title
+ * @return Status
+ */
+ public function validate( Title $title ) {
+ $engine = Scribunto::newDefaultEngine();
+ $engine->setTitle( $title );
+ return $engine->validate( $this->getNativeData(), $title->getPrefixedDBkey() );
+ }
+
+ public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user ) {
+ return $this->validate( $page->getTitle() );
+ }
+
+ /**
+ * Parse the Content object and generate a ParserOutput from the result.
+ *
+ * @param Title $title The page title to use as a context for rendering
+ * @param null|int $revId The revision being rendered (optional)
+ * @param null|ParserOptions $options Any parser options
+ * @param bool $generateHtml Whether to generate HTML (default: true).
+ * @param ParserOutput &$output ParserOutput representing the HTML form of the text.
+ * @return ParserOutput
+ */
+ protected function fillParserOutput(
+ Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
+ global $wgParser;
+
+ $text = $this->getNativeData();
+
+ // Get documentation, if any
+ $output = new ParserOutput();
+ $doc = Scribunto::getDocPage( $title );
+ if ( $doc ) {
+ $msg = wfMessage(
+ $doc->exists() ? 'scribunto-doc-page-show' : 'scribunto-doc-page-does-not-exist',
+ $doc->getPrefixedText()
+ )->inContentLanguage();
+
+ if ( !$msg->isDisabled() ) {
+ // We need the ParserOutput for categories and such, so we
+ // can't use $msg->parse().
+ $docViewLang = $doc->getPageViewLanguage();
+ $dir = $docViewLang->getDir();
+
+ // Code is forced to be ltr, but the documentation can be rtl.
+ // Correct direction class is needed for correct formatting.
+ // The possible classes are
+ // mw-content-ltr or mw-content-rtl
+ $dirClass = "mw-content-$dir";
+
+ $docWikitext = Html::rawElement(
+ 'div',
+ [
+ 'lang' => $docViewLang->getHtmlCode(),
+ 'dir' => $dir,
+ 'class' => $dirClass,
+ ],
+ // Line breaks are needed so that wikitext would be
+ // appropriately isolated for correct parsing. See Bug 60664.
+ "\n" . $msg->plain() . "\n"
+ );
+
+ if ( !$options ) {
+ // NOTE: use canonical options per default to produce cacheable output
+ $options = ContentHandler::getForTitle( $doc )->makeParserOptions( 'canonical' );
+ } else {
+ if ( $options->getTargetLanguage() === null ) {
+ $options->setTargetLanguage( $doc->getPageLanguage() );
+ }
+ }
+
+ $output = $wgParser->parse( $docWikitext, $title, $options, true, true, $revId );
+ }
+
+ // Mark the doc page as a transclusion, so we get purged when it
+ // changes.
+ $output->addTemplate( $doc, $doc->getArticleID(), $doc->getLatestRevID() );
+ }
+
+ // Validate the script, and include an error message and tracking
+ // category if it's invalid
+ $status = $this->validate( $title );
+ if ( !$status->isOK() ) {
+ $output->setText( $output->getRawText() .
+ Html::rawElement( 'div', [ 'class' => 'errorbox' ],
+ $status->getHTML( 'scribunto-error-short', 'scribunto-error-long' )
+ )
+ );
+ $output->addTrackingCategory( 'scribunto-module-with-errors-category', $title );
+ }
+
+ if ( !$generateHtml ) {
+ // We don't need the actual HTML
+ $output->setText( '' );
+ return $output;
+ }
+
+ $engine = Scribunto::newDefaultEngine();
+ $engine->setTitle( $title );
+ if ( $this->highlight( $text, $output, $engine ) ) {
+ return $output;
+ }
+
+ // No GeSHi, or GeSHi can't parse it, use plain <pre>
+ $output->setText( $output->getRawText() .
+ "<pre class='mw-code mw-script' dir='ltr'>\n" .
+ htmlspecialchars( $text ) .
+ "\n</pre>\n"
+ );
+
+ return $output;
+ }
+
+ /**
+ * Adds syntax highlighting to the output (or do not touch it and return false).
+ * @param string $text
+ * @param ParserOutput $output
+ * @param ScribuntoEngineBase $engine
+ * @return bool Success status
+ */
+ protected function highlight( $text, ParserOutput $output, ScribuntoEngineBase $engine ) {
+ global $wgScribuntoUseGeSHi;
+ $language = $engine->getGeSHiLanguage();
+ if ( $wgScribuntoUseGeSHi && class_exists( SyntaxHighlight::class ) && $language ) {
+ $status = SyntaxHighlight::highlight( $text, $language );
+ if ( $status->isGood() ) {
+ // @todo replace addModuleStyles line with the appropriate call on
+ // SyntaxHighlight once one is created
+ $output->addModuleStyles( 'ext.pygments' );
+ $output->setText( $output->getRawText() . $status->getValue() );
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/common/ScribuntoContentHandler.php b/www/wiki/extensions/Scribunto/includes/common/ScribuntoContentHandler.php
new file mode 100644
index 00000000..ad2c1baa
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/common/ScribuntoContentHandler.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Scribunto Content Handler
+ *
+ * @file
+ * @ingroup Extensions
+ * @ingroup Scribunto
+ *
+ * @author Brad Jorsch <bjorsch@wikimedia.org>
+ */
+
+class ScribuntoContentHandler extends CodeContentHandler {
+
+ /**
+ * @param string $modelId
+ * @param string[] $formats
+ */
+ public function __construct(
+ $modelId = CONTENT_MODEL_SCRIBUNTO, $formats = [ CONTENT_FORMAT_TEXT ]
+ ) {
+ parent::__construct( $modelId, $formats );
+ }
+
+ protected function getContentClass() {
+ return 'ScribuntoContent';
+ }
+
+ /**
+ * @param string $format
+ * @return bool
+ */
+ public function isSupportedFormat( $format ) {
+ // An error in an earlier version of Scribunto means we might see this.
+ if ( $format === 'CONTENT_FORMAT_TEXT' ) {
+ $format = CONTENT_FORMAT_TEXT;
+ }
+ return parent::isSupportedFormat( $format );
+ }
+
+ /**
+ * Only allow this content handler to be used in the Module namespace
+ * @param Title $title
+ * @return bool
+ */
+ public function canBeUsedOn( Title $title ) {
+ if ( $title->getNamespace() !== NS_MODULE ) {
+ return false;
+ }
+
+ return parent::canBeUsedOn( $title );
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HashLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HashLibrary.php
new file mode 100644
index 00000000..b2720de5
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HashLibrary.php
@@ -0,0 +1,44 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaHashLibrary extends Scribunto_LuaLibraryBase {
+
+ public function register() {
+ $lib = [
+ 'listAlgorithms' => [ $this, 'listAlgorithms' ],
+ 'hashValue' => [ $this, 'hashValue' ],
+ ];
+
+ return $this->getEngine()->registerInterface( 'mw.hash.lua', $lib );
+ }
+
+ /**
+ * Returns a list of known/ supported hash algorithms
+ *
+ * @return string[][]
+ */
+ public function listAlgorithms() {
+ $algos = hash_algos();
+ $algos = array_combine( range( 1, count( $algos ) ), $algos );
+
+ return [ $algos ];
+ }
+
+ /**
+ * Hash a given value.
+ *
+ * @param string $algo
+ * @param string $value
+ * @return string[]
+ */
+ public function hashValue( $algo, $value ) {
+ if ( !in_array( $algo, hash_algos() ) ) {
+ throw new Scribunto_LuaError( "Unknown hashing algorithm: $algo" );
+ }
+
+ $hash = hash( $algo, $value );
+
+ return [ $hash ];
+ }
+
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HtmlLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HtmlLibrary.php
new file mode 100644
index 00000000..00716ca8
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/HtmlLibrary.php
@@ -0,0 +1,11 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaHtmlLibrary extends Scribunto_LuaLibraryBase {
+ function register() {
+ return $this->getEngine()->registerInterface( 'mw.html.lua', [], [
+ 'uniqPrefix' => Parser::MARKER_PREFIX,
+ 'uniqSuffix' => Parser::MARKER_SUFFIX,
+ ] );
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LanguageLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LanguageLibrary.php
new file mode 100644
index 00000000..b3671e67
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LanguageLibrary.php
@@ -0,0 +1,364 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaLanguageLibrary extends Scribunto_LuaLibraryBase {
+ public $langCache = [];
+ public $timeCache = [];
+ public $maxLangCacheSize;
+
+ function register() {
+ // Pre-populate the language cache
+ global $wgContLang;
+ $this->langCache[$wgContLang->getCode()] = $wgContLang;
+ $this->maxLangCacheSize = $this->getEngine()->getOption( 'maxLangCacheSize' );
+
+ $statics = [
+ 'getContLangCode',
+ 'isSupportedLanguage',
+ 'isKnownLanguageTag',
+ 'isValidCode',
+ 'isValidBuiltInCode',
+ 'fetchLanguageName',
+ 'fetchLanguageNames',
+ 'getFallbacksFor',
+ ];
+ $methods = [
+ 'lcfirst',
+ 'ucfirst',
+ 'lc',
+ 'uc',
+ 'caseFold',
+ 'formatNum',
+ 'formatDate',
+ 'formatDuration',
+ 'getDurationIntervals',
+ 'parseFormattedNumber',
+ 'convertPlural',
+ 'convertGrammar',
+ 'gender',
+ 'isRTL',
+ ];
+ $lib = [];
+ foreach ( $statics as $name ) {
+ $lib[$name] = [ $this, $name ];
+ }
+ $ths = $this;
+ foreach ( $methods as $name ) {
+ $lib[$name] = function () use ( $ths, $name ) {
+ $args = func_get_args();
+ return $ths->languageMethod( $name, $args );
+ };
+ }
+ return $this->getEngine()->registerInterface( 'mw.language.lua', $lib );
+ }
+
+ function getContLangCode() {
+ global $wgContLang;
+ return [ $wgContLang->getCode() ];
+ }
+
+ function isSupportedLanguage( $code ) {
+ $this->checkType( 'isSupportedLanguage', 1, $code, 'string' );
+ try {
+ // There's no good reason this should throw, but it does. Sigh.
+ return [ Language::isSupportedLanguage( $code ) ];
+ } catch ( MWException $ex ) {
+ return [ false ];
+ }
+ }
+
+ function isKnownLanguageTag( $code ) {
+ $this->checkType( 'isKnownLanguageTag', 1, $code, 'string' );
+ return [ Language::isKnownLanguageTag( $code ) ];
+ }
+
+ function isValidCode( $code ) {
+ $this->checkType( 'isValidCode', 1, $code, 'string' );
+ return [ Language::isValidCode( $code ) ];
+ }
+
+ function isValidBuiltInCode( $code ) {
+ $this->checkType( 'isValidBuiltInCode', 1, $code, 'string' );
+ return [ (bool)Language::isValidBuiltInCode( $code ) ];
+ }
+
+ function fetchLanguageName( $code, $inLanguage ) {
+ $this->checkType( 'fetchLanguageName', 1, $code, 'string' );
+ $this->checkTypeOptional( 'fetchLanguageName', 2, $inLanguage, 'string', null );
+ return [ Language::fetchLanguageName( $code, $inLanguage ) ];
+ }
+
+ function fetchLanguageNames( $inLanguage, $include ) {
+ $this->checkTypeOptional( 'fetchLanguageNames', 1, $inLanguage, 'string', null );
+ $this->checkTypeOptional( 'fetchLanguageNames', 2, $include, 'string', 'mw' );
+ return [ Language::fetchLanguageNames( $inLanguage, $include ) ];
+ }
+
+ function getFallbacksFor( $code ) {
+ $this->checkType( 'getFallbacksFor', 1, $code, 'string' );
+ $ret = Language::getFallbacksFor( $code );
+ // Make 1-based
+ if ( count( $ret ) ) {
+ $ret = array_combine( range( 1, count( $ret ) ), $ret );
+ }
+ return [ $ret ];
+ }
+
+ /**
+ * Language object method handler
+ * @param string $name
+ * @param array $args
+ * @return array
+ * @throws Scribunto_LuaError
+ */
+ function languageMethod( $name, $args ) {
+ $name = strval( $name );
+ $code = array_shift( $args );
+ if ( !isset( $this->langCache[$code] ) ) {
+ if ( count( $this->langCache ) > $this->maxLangCacheSize ) {
+ throw new Scribunto_LuaError( 'too many language codes requested' );
+ }
+ try {
+ $this->langCache[$code] = Language::factory( $code );
+ } catch ( MWException $ex ) {
+ throw new Scribunto_LuaError( "language code '$code' is invalid" );
+ }
+ }
+ $lang = $this->langCache[$code];
+ switch ( $name ) {
+ // Zero arguments
+ case 'isRTL':
+ return [ $lang->$name() ];
+
+ // One string argument passed straight through
+ case 'lcfirst':
+ case 'ucfirst':
+ case 'lc':
+ case 'uc':
+ case 'caseFold':
+ $this->checkType( $name, 1, $args[0], 'string' );
+ return [ $lang->$name( $args[0] ) ];
+
+ case 'parseFormattedNumber':
+ if ( is_numeric( $args[0] ) ) {
+ $args[0] = strval( $args[0] );
+ }
+ if ( $this->getLuaType( $args[0] ) !== 'string' ) {
+ // Be like tonumber(), return nil instead of erroring out
+ return [ null ];
+ }
+ return [ $lang->$name( $args[0] ) ];
+
+ // Custom handling
+ default:
+ return $this->$name( $lang, $args );
+ }
+ }
+
+ /**
+ * convertPlural handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function convertPlural( $lang, $args ) {
+ $number = array_shift( $args );
+ $this->checkType( 'convertPlural', 1, $number, 'number' );
+ if ( is_array( $args[0] ) ) {
+ $args = $args[0];
+ }
+ $forms = array_values( array_map( 'strval', $args ) );
+ return [ $lang->convertPlural( $number, $forms ) ];
+ }
+
+ /**
+ * convertGrammar handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function convertGrammar( $lang, $args ) {
+ $this->checkType( 'convertGrammar', 1, $args[0], 'string' );
+ $this->checkType( 'convertGrammar', 2, $args[1], 'string' );
+ return [ $lang->convertGrammar( $args[0], $args[1] ) ];
+ }
+
+ /**
+ * gender handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function gender( $lang, $args ) {
+ $this->checkType( 'gender', 1, $args[0], 'string' );
+ $username = trim( array_shift( $args ) );
+
+ if ( is_array( $args[0] ) ) {
+ $args = $args[0];
+ }
+ $forms = array_values( array_map( 'strval', $args ) );
+
+ // Shortcuts
+ if ( count( $forms ) === 0 ) {
+ return [ '' ];
+ } elseif ( count( $forms ) === 1 ) {
+ return [ $forms[0] ];
+ }
+
+ if ( $username === 'male' || $username === 'female' ) {
+ $gender = $username;
+ } else {
+ // default
+ $gender = User::getDefaultOption( 'gender' );
+
+ // Check for "User:" prefix
+ $title = Title::newFromText( $username );
+ if ( $title && $title->getNamespace() == NS_USER ) {
+ $username = $title->getText();
+ }
+
+ // check parameter, or use the ParserOptions if in interface message
+ $user = User::newFromName( $username );
+ if ( $user ) {
+ $gender = GenderCache::singleton()->getGenderOf( $user, __METHOD__ );
+ } elseif ( $username === '' ) {
+ $parserOptions = $this->getParserOptions();
+ if ( $parserOptions->getInterfaceMessage() ) {
+ $gender = GenderCache::singleton()->getGenderOf( $parserOptions->getUser(), __METHOD__ );
+ }
+ }
+ }
+ return [ $lang->gender( $gender, $forms ) ];
+ }
+
+ /**
+ * formatNum handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function formatNum( $lang, $args ) {
+ $num = $args[0];
+ $this->checkType( 'formatNum', 1, $num, 'number' );
+
+ $noCommafy = false;
+ if ( isset( $args[1] ) ) {
+ $this->checkType( 'formatNum', 2, $args[1], 'table' );
+ $options = $args[1];
+ $noCommafy = !empty( $options['noCommafy'] );
+ }
+ return [ $lang->formatNum( $num, $noCommafy ) ];
+ }
+
+ /**
+ * formatDate handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ * @throws Scribunto_LuaError
+ */
+ function formatDate( $lang, $args ) {
+ $this->checkType( 'formatDate', 1, $args[0], 'string' );
+ $this->checkTypeOptional( 'formatDate', 2, $args[1], 'string', '' );
+ $this->checkTypeOptional( 'formatDate', 3, $args[2], 'boolean', false );
+
+ list( $format, $date, $local ) = $args;
+ $langcode = $lang->getCode();
+
+ if ( $date === '' ) {
+ $cacheKey = $this->getParserOptions()->getTimestamp();
+ $timestamp = new MWTimestamp( $cacheKey );
+ $date = $timestamp->getTimestamp( TS_ISO_8601 );
+ $useTTL = true;
+ } else {
+ # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
+ if ( preg_match( '/^[0-9]{4}$/', $date ) ) {
+ $date = '00:00 '.$date;
+ }
+
+ $cacheKey = $date;
+ $useTTL = false;
+ }
+
+ if ( isset( $this->timeCache[$format][$cacheKey][$langcode][$local] ) ) {
+ $ttl = $this->timeCache[$format][$cacheKey][$langcode][$local][1];
+ if ( $useTTL && $ttl !== null ) {
+ $this->getEngine()->setTTL( $ttl );
+ }
+ return [ $this->timeCache[$format][$cacheKey][$langcode][$local][0] ];
+ }
+
+ # Default input timezone is UTC.
+ try {
+ $utc = new DateTimeZone( 'UTC' );
+ $dateObject = new DateTime( $date, $utc );
+ } catch ( Exception $ex ) {
+ throw new Scribunto_LuaError( "bad argument #2 to 'formatDate' (not a valid timestamp)" );
+ }
+
+ # Set output timezone.
+ if ( $local ) {
+ global $wgLocaltimezone;
+ if ( isset( $wgLocaltimezone ) ) {
+ $tz = new DateTimeZone( $wgLocaltimezone );
+ } else {
+ $tz = new DateTimeZone( date_default_timezone_get() );
+ }
+ } else {
+ $tz = $utc;
+ }
+ $dateObject->setTimezone( $tz );
+ # Generate timestamp
+ $ts = $dateObject->format( 'YmdHis' );
+
+ if ( $ts < 0 ) {
+ throw new Scribunto_LuaError( "mw.language:formatDate() only supports years from 0" );
+ } elseif ( $ts >= 100000000000000 ) {
+ throw new Scribunto_LuaError( "mw.language:formatDate() only supports years up to 9999" );
+ }
+
+ $ttl = null;
+ $ret = $lang->sprintfDate( $format, $ts, $tz, $ttl );
+ $this->timeCache[$format][$cacheKey][$langcode][$local] = [ $ret, $ttl ];
+ if ( $useTTL && $ttl !== null ) {
+ $this->getEngine()->setTTL( $ttl );
+ }
+ return [ $ret ];
+ }
+
+ /**
+ * formatDuration handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function formatDuration( $lang, $args ) {
+ $this->checkType( 'formatDuration', 1, $args[0], 'number' );
+ $this->checkTypeOptional( 'formatDuration', 2, $args[1], 'table', [] );
+
+ list( $seconds, $chosenIntervals ) = $args;
+ $langcode = $lang->getCode();
+ $chosenIntervals = array_values( $chosenIntervals );
+
+ $ret = $lang->formatDuration( $seconds, $chosenIntervals );
+ return [ $ret ];
+ }
+
+ /**
+ * getDurationIntervals handler
+ * @param Language $lang
+ * @param array $args
+ * @return array
+ */
+ function getDurationIntervals( $lang, $args ) {
+ $this->checkType( 'getDurationIntervals', 1, $args[0], 'number' );
+ $this->checkTypeOptional( 'getDurationIntervals', 2, $args[1], 'table', [] );
+
+ list( $seconds, $chosenIntervals ) = $args;
+ $langcode = $lang->getCode();
+ $chosenIntervals = array_values( $chosenIntervals );
+
+ $ret = $lang->getDurationIntervals( $seconds, $chosenIntervals );
+ return [ $ret ];
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LibraryBase.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LibraryBase.php
new file mode 100644
index 00000000..38505fa9
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LibraryBase.php
@@ -0,0 +1,181 @@
+<?php
+/**
+ * Basic services that Lua libraries will probably need
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @author Brad Jorsch
+ */
+
+/**
+ * This class provides some basic services that Lua libraries will probably need
+ */
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+abstract class Scribunto_LuaLibraryBase {
+ /**
+ * @var Scribunto_LuaEngine
+ */
+ private $engine;
+
+ /**
+ * @param Scribunto_LuaEngine $engine
+ */
+ function __construct( Scribunto_LuaEngine $engine ) {
+ $this->engine = $engine;
+ }
+
+ /**
+ * Called to register the library.
+ *
+ * This should do any necessary setup and then call $this->getEngine()->registerInterface().
+ * The value returned by that call should be returned from this function,
+ * and must be for 'deferLoad' libraries to work right.
+ *
+ * @return array Lua package
+ */
+ abstract function register();
+
+ /**
+ * Get the engine
+ *
+ * @return Scribunto_LuaEngine engine
+ */
+ protected function getEngine() {
+ return $this->engine;
+ }
+
+ /**
+ * Get the interpreter
+ *
+ * @return Scribunto_LuaInterpreter interpreter
+ */
+ protected function getInterpreter() {
+ return $this->engine->getInterpreter();
+ }
+
+ /**
+ * Get the parser
+ *
+ * @return Parser parser
+ */
+ protected function getParser() {
+ return $this->engine->getParser();
+ }
+
+ /**
+ * Get the title
+ *
+ * @return Title title
+ */
+ protected function getTitle() {
+ return $this->getEngine()->getTitle();
+ }
+
+ /**
+ * Get the parser options
+ *
+ * @return ParserOptions parser options
+ */
+ protected function getParserOptions() {
+ return $this->engine->getParser()->getOptions();
+ }
+
+ /**
+ * Get the Lua type corresponding to the type of the variable.
+ *
+ * If the variable does not correspond to any type, the PHP type will be
+ * returned (prefixed with "PHP"). For example, "PHP resource" or "PHP
+ * object of class Foo".
+ *
+ * @param mixed $var Variable to test
+ * @return string Type
+ */
+ protected function getLuaType( $var ) {
+ static $luaTypes = [
+ 'NULL' => 'nil',
+ 'double' => 'number',
+ 'integer' => 'number',
+ 'string' => 'string',
+ 'boolean' => 'boolean',
+ 'array' => 'table',
+ ];
+ $type = gettype( $var );
+ if ( isset( $luaTypes[$type] ) ) {
+ return $luaTypes[$type];
+ } elseif ( $this->getInterpreter()->isLuaFunction( $var ) ) {
+ return 'function';
+ } else {
+ $type = "PHP $type";
+ if ( is_object( $var ) ) {
+ $type .= " of class " . get_class( $var );
+ }
+ return $type;
+ }
+ }
+
+ /**
+ * Check the type of a variable
+ *
+ * If the type of the variable does not match the expected type,
+ * a Scribunto_LuaError will be thrown.
+ *
+ * @param string $name Name of the calling function (as seen from Lua)
+ * @param int $argIdx Index of the argument being tested (1-based)
+ * @param mixed $arg Variable to test
+ * @param string $expectType Lua type expected
+ * @return void
+ */
+ protected function checkType( $name, $argIdx, $arg, $expectType ) {
+ $type = $this->getLuaType( $arg );
+ if ( $type !== $expectType ) {
+ throw new Scribunto_LuaError(
+ "bad argument #$argIdx to '$name' ($expectType expected, got $type)"
+ );
+ }
+ }
+
+ /**
+ * Check the type of a variable, with default if null
+ *
+ * If the variable is null, $default will be assigned. Otherwise, if the
+ * type of the variable does not match the expected type, a
+ * Scribunto_LuaError will be thrown.
+ *
+ * @param string $name Name of the calling function (as seen from Lua)
+ * @param int $argIdx Index of the argument being tested (1-based)
+ * @param mixed &$arg Variable to test/set
+ * @param string $expectType Lua type expected
+ * @param mixed $default Default value
+ * @return void
+ */
+ protected function checkTypeOptional( $name, $argIdx, &$arg, $expectType, $default ) {
+ if ( $arg === null ) {
+ $arg = $default;
+ } else {
+ $this->checkType( $name, $argIdx, $arg, $expectType );
+ }
+ }
+
+ /**
+ * Increment the expensive function count, and throw if limit exceeded
+ *
+ * @return null
+ */
+ public function incrementExpensiveFunctionCount() {
+ return $this->getEngine()->incrementExpensiveFunctionCount();
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaCommon.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaCommon.php
new file mode 100644
index 00000000..db38e49d
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaCommon.php
@@ -0,0 +1,1063 @@
+<?php
+
+use Wikimedia\ScopedCallback;
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+abstract class Scribunto_LuaEngine extends ScribuntoEngineBase {
+ /**
+ * Libraries to load. See also the 'ScribuntoExternalLibraries' hook.
+ * @var array Maps module names to PHP classes or definition arrays
+ */
+ protected static $libraryClasses = [
+ 'mw.site' => 'Scribunto_LuaSiteLibrary',
+ 'mw.uri' => 'Scribunto_LuaUriLibrary',
+ 'mw.ustring' => 'Scribunto_LuaUstringLibrary',
+ 'mw.language' => 'Scribunto_LuaLanguageLibrary',
+ 'mw.message' => 'Scribunto_LuaMessageLibrary',
+ 'mw.title' => 'Scribunto_LuaTitleLibrary',
+ 'mw.text' => 'Scribunto_LuaTextLibrary',
+ 'mw.html' => 'Scribunto_LuaHtmlLibrary',
+ 'mw.hash' => 'Scribunto_LuaHashLibrary',
+ ];
+
+ /**
+ * Paths for modules that may be loaded from Lua. See also the
+ * 'ScribuntoExternalLibraryPaths' hook.
+ * @var array Paths
+ */
+ protected static $libraryPaths = [
+ '.',
+ 'luabit',
+ 'ustring',
+ ];
+
+ protected $loaded = false;
+
+ /**
+ * @var Scribunto_LuaInterpreter
+ */
+ protected $interpreter;
+
+ /**
+ * @var array
+ */
+ protected $mw;
+
+ /**
+ * @var array
+ */
+ protected $currentFrames = [];
+ protected $expandCache = [];
+ protected $availableLibraries = [];
+
+ const MAX_EXPAND_CACHE_SIZE = 100;
+
+ /**
+ * If luasandbox is installed and usable then use it,
+ * otherwise
+ *
+ * @param array $options
+ * @return Scribunto_LuaEngine
+ */
+ public static function newAutodetectEngine( array $options ) {
+ global $wgScribuntoEngineConf;
+ $engine = 'luastandalone';
+ try {
+ Scribunto_LuaSandboxInterpreter::checkLuaSandboxVersion();
+ $engine = 'luasandbox';
+ } catch ( Scribunto_LuaInterpreterNotFoundError $e ) {
+ // pass
+ } catch ( Scribunto_LuaInterpreterBadVersionError $e ) {
+ // pass
+ }
+
+ unset( $options['factory'] );
+
+ return Scribunto::newEngine( $options + $wgScribuntoEngineConf[$engine] );
+ }
+
+ /**
+ * Create a new interpreter object
+ * @return Scribunto_LuaInterpreter
+ */
+ abstract function newInterpreter();
+
+ /**
+ * @param string $text
+ * @param string|bool $chunkName
+ * @return Scribunto_LuaModule
+ */
+ protected function newModule( $text, $chunkName ) {
+ return new Scribunto_LuaModule( $this, $text, $chunkName );
+ }
+
+ /**
+ * @param string $message
+ * @param array $params
+ * @return Scribunto_LuaError
+ */
+ public function newLuaError( $message, $params = [] ) {
+ return new Scribunto_LuaError( $message, $this->getDefaultExceptionParams() + $params );
+ }
+
+ public function destroy() {
+ // Break reference cycles
+ $this->interpreter = null;
+ $this->mw = null;
+ $this->expandCache = null;
+ parent::destroy();
+ }
+
+ /**
+ * Initialise the interpreter and the base environment
+ */
+ public function load() {
+ if ( $this->loaded ) {
+ return;
+ }
+ $this->loaded = true;
+
+ try {
+ $this->interpreter = $this->newInterpreter();
+
+ $funcs = [
+ 'loadPackage',
+ 'loadPHPLibrary',
+ 'frameExists',
+ 'newChildFrame',
+ 'getExpandedArgument',
+ 'getAllExpandedArguments',
+ 'expandTemplate',
+ 'callParserFunction',
+ 'preprocess',
+ 'incrementExpensiveFunctionCount',
+ 'isSubsting',
+ 'getFrameTitle',
+ 'setTTL',
+ 'addWarning',
+ ];
+
+ $lib = [];
+ foreach ( $funcs as $name ) {
+ $lib[$name] = [ $this, $name ];
+ }
+
+ $this->registerInterface( 'mwInit.lua', [] );
+ $this->mw = $this->registerInterface( 'mw.lua', $lib,
+ [ 'allowEnvFuncs' => $this->options['allowEnvFuncs'] ] );
+
+ $this->availableLibraries = $this->getLibraries( 'lua', self::$libraryClasses );
+ foreach ( $this->availableLibraries as $name => $def ) {
+ $this->instantiatePHPLibrary( $name, $def, false );
+ }
+ } catch ( Exception $ex ) {
+ $this->loaded = false;
+ $this->interpreter = null;
+ throw $ex;
+ }
+ }
+
+ /**
+ * Register a Lua Library
+ *
+ * This should be called from the library's PHP module's register() method.
+ *
+ * The value for $interfaceFuncs is used to populate the mw_interface
+ * global that is defined when the library's Lua module is loaded. Values
+ * must be PHP callables, which will be seen in Lua as functions.
+ *
+ * @param string $moduleFileName The path to the Lua portion of the library
+ * (absolute, or relative to $this->getLuaLibDir())
+ * @param array $interfaceFuncs Populates mw_interface
+ * @param array $setupOptions Passed to the modules setupInterface() method.
+ * @return array Lua package
+ */
+ public function registerInterface( $moduleFileName, $interfaceFuncs, $setupOptions = [] ) {
+ $this->interpreter->registerLibrary( 'mw_interface', $interfaceFuncs );
+ $moduleFileName = $this->normalizeModuleFileName( $moduleFileName );
+ $package = $this->loadLibraryFromFile( $moduleFileName );
+ if ( !empty( $package['setupInterface'] ) ) {
+ $this->interpreter->callFunction( $package['setupInterface'], $setupOptions );
+ }
+ return $package;
+ }
+
+ /**
+ * Return the base path for Lua modules.
+ * @return string
+ */
+ public function getLuaLibDir() {
+ return __DIR__ . '/lualib';
+ }
+
+ /**
+ * Normalize a lua module to its full path. If path does not look like an
+ * absolute path (i.e. begins with DIRECTORY_SEPARATOR or "X:"), prepend
+ * getLuaLibDir()
+ *
+ * @param string $fileName name of the lua module file
+ * @return string
+ */
+ protected function normalizeModuleFileName( $fileName ) {
+ if ( !preg_match( '<^(?:[a-zA-Z]:)?' . preg_quote( DIRECTORY_SEPARATOR ) . '>', $fileName ) ) {
+ $fileName = "{$this->getLuaLibDir()}/{$fileName}";
+ }
+ return $fileName;
+ }
+
+ /**
+ * Get performance characteristics of the Lua engine/interpreter
+ *
+ * phpCallsRequireSerialization: boolean
+ * whether calls between PHP and Lua functions require (slow)
+ * serialization of parameters and return values
+ *
+ * @return array
+ */
+ abstract public function getPerformanceCharacteristics();
+
+ /**
+ * Get the current interpreter object
+ * @return Scribunto_LuaInterpreter
+ */
+ public function getInterpreter() {
+ $this->load();
+ return $this->interpreter;
+ }
+
+ /**
+ * Replaces the list of current frames, and return a ScopedCallback that
+ * will reset them when it goes out of scope.
+ *
+ * @param PPFrame|null $frame If null, an empty frame with no parent will be used
+ * @return ScopedCallback
+ */
+ private function setupCurrentFrames( PPFrame $frame = null ) {
+ if ( !$frame ) {
+ $frame = $this->getParser()->getPreprocessor()->newFrame();
+ }
+
+ $oldFrames = $this->currentFrames;
+ $oldExpandCache = $this->expandCache;
+ $this->currentFrames = [
+ 'current' => $frame,
+ 'parent' => isset( $frame->parent ) ? $frame->parent : null,
+ ];
+ $this->expandCache = [];
+
+ return new ScopedCallback( function () use ( $oldFrames, $oldExpandCache ) {
+ $this->currentFrames = $oldFrames;
+ $this->expandCache = $oldExpandCache;
+ } );
+ }
+
+ /**
+ * Execute a module chunk in a new isolated environment, and return the specified function
+ * @param mixed $chunk As accepted by Scribunto_LuaInterpreter::callFunction()
+ * @param string $functionName
+ * @param PPFrame|null $frame
+ * @return mixed
+ * @throws ScribuntoException
+ */
+ public function executeModule( $chunk, $functionName, $frame ) {
+ $resetFrames = null;
+ if ( !$this->currentFrames || !isset( $this->currentFrames['current'] ) ) {
+ // Only reset frames if there isn't already current frame
+ // $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
+ $resetFrames = $this->setupCurrentFrames( $frame );
+ }
+
+ $retval = $this->getInterpreter()->callFunction(
+ $this->mw['executeModule'], $chunk, $functionName
+ );
+ if ( !$retval[0] ) {
+ // If we get here, it means we asked for an element from the table the module returned,
+ // but it returned something other than a table. In this case, $retval[1] contains the type
+ // of what it did returned, instead of the value we asked for.
+ throw $this->newException(
+ 'scribunto-lua-notarrayreturn', [ 'args' => [ $retval[1] ] ]
+ );
+ }
+ return $retval[1];
+ }
+
+ /**
+ * Execute a module function chunk
+ * @param mixed $chunk As accepted by Scribunto_LuaInterpreter::callFunction()
+ * @param PPFrame|null $frame
+ * @return array
+ */
+ public function executeFunctionChunk( $chunk, $frame ) {
+ // $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
+ $resetFrames = $this->setupCurrentFrames( $frame );
+
+ return $this->getInterpreter()->callFunction(
+ $this->mw['executeFunction'],
+ $chunk );
+ }
+
+ /**
+ * Get data logged by modules
+ * @return string Logged data
+ */
+ protected function getLogBuffer() {
+ if ( !$this->loaded ) {
+ return '';
+ }
+ try {
+ $log = $this->getInterpreter()->callFunction( $this->mw['getLogBuffer'] );
+ return $log[0];
+ } catch ( ScribuntoException $ex ) {
+ // Probably time expired, ignore it.
+ return '';
+ }
+ }
+
+ /**
+ * Format the logged data for HTML output
+ * @param string $logs Logged data
+ * @param bool $localize Whether to localize the message key
+ * @return string HTML
+ */
+ protected function formatHtmlLogs( $logs, $localize ) {
+ $keyMsg = wfMessage( 'scribunto-limitreport-logs' );
+ if ( !$localize ) {
+ $keyMsg->inLanguage( 'en' )->useDatabase( false );
+ }
+ return Html::openElement( 'tr' ) .
+ Html::rawElement( 'th', [ 'colspan' => 2 ], $keyMsg->parse() ) .
+ Html::closeElement( 'tr' ) .
+ Html::openElement( 'tr' ) .
+ Html::openElement( 'td', [ 'colspan' => 2 ] ) .
+ Html::openElement( 'div', [ 'class' => 'mw-collapsible mw-collapsed' ] ) .
+ Html::element( 'pre', [ 'class' => 'scribunto-limitreport-logs' ], $logs ) .
+ Html::closeElement( 'div' ) .
+ Html::closeElement( 'td' ) .
+ Html::closeElement( 'tr' );
+ }
+
+ /**
+ * Load a library from the given file and execute it in the base environment.
+ * @param string $fileName File name/path to load
+ * @return array|null the export list, or null if there isn't one.
+ */
+ protected function loadLibraryFromFile( $fileName ) {
+ static $cache = null;
+
+ if ( !$cache ) {
+ $cache = ObjectCache::getLocalServerInstance( 'hash' );
+ }
+
+ $mtime = filemtime( $fileName );
+ if ( $mtime === false ) {
+ throw new MWException( 'Lua file does not exist: ' . $fileName );
+ }
+
+ $cacheKey = $cache->makeGlobalKey( __CLASS__, $fileName );
+ $fileData = $cache->get( $cacheKey );
+
+ $code = false;
+ if ( $fileData ) {
+ list( $code, $cachedMtime ) = $fileData;
+ if ( $cachedMtime < $mtime ) {
+ $code = false;
+ }
+ }
+ if ( !$code ) {
+ $code = file_get_contents( $fileName );
+ if ( $code === false ) {
+ throw new MWException( 'Lua file does not exist: ' . $fileName );
+ }
+ $cache->set( $cacheKey, [ $code, $mtime ], 60 * 5 );
+ }
+
+ # Prepending an "@" to the chunk name makes Lua think it is a filename
+ $module = $this->getInterpreter()->loadString( $code, '@' . basename( $fileName ) );
+ $ret = $this->getInterpreter()->callFunction( $module );
+ return isset( $ret[0] ) ? $ret[0] : null;
+ }
+
+ public function getGeSHiLanguage() {
+ return 'lua';
+ }
+
+ public function getCodeEditorLanguage() {
+ return 'lua';
+ }
+
+ public function runConsole( array $params ) {
+ // $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
+ $resetFrames = $this->setupCurrentFrames();
+
+ /**
+ * TODO: provide some means for giving correct line numbers for errors
+ * in console input, and for producing an informative error message
+ * if there is an error in prevQuestions.
+ *
+ * Maybe each console line could be evaluated as a different chunk,
+ * apparently that's what lua.c does.
+ */
+ $code = "return function (__init, exe)\n" .
+ "if not exe then exe = function(...) return true, ... end end\n" .
+ "local p = select(2, exe(__init) )\n" .
+ "__init, exe = nil, nil\n" .
+ "local print = mw.log\n";
+ foreach ( $params['prevQuestions'] as $q ) {
+ if ( substr( $q, 0, 1 ) === '=' ) {
+ $code .= "print(" . substr( $q, 1 ) . ")";
+ } else {
+ $code .= $q;
+ }
+ $code .= "\n";
+ }
+ $code .= "mw.clearLogBuffer()\n";
+ if ( substr( $params['question'], 0, 1 ) === '=' ) {
+ // Treat a statement starting with "=" as a return statement, like in lua.c
+ $code .= "local ret = mw.allToString(" . substr( $params['question'], 1 ) . ")\n" .
+ "return ret, mw.getLogBuffer()\n";
+ } else {
+ $code .= $params['question'] . "\n" .
+ "return nil, mw.getLogBuffer()\n";
+ }
+ $code .= "end\n";
+
+ if ( $params['title']->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ $contentModule = $this->newModule(
+ $params['content'], $params['title']->getPrefixedDBkey() );
+ $contentInit = $contentModule->getInitChunk();
+ $contentExe = $this->mw['executeModule'];
+ } else {
+ $contentInit = $params['content'];
+ $contentExe = null;
+ }
+
+ $consoleModule = $this->newModule(
+ $code,
+ wfMessage( 'scribunto-console-current-src' )->text()
+ );
+ $consoleInit = $consoleModule->getInitChunk();
+ $ret = $this->getInterpreter()->callFunction( $this->mw['executeModule'], $consoleInit, false );
+ $func = $ret[1];
+ $ret = $this->getInterpreter()->callFunction( $func, $contentInit, $contentExe );
+
+ return [
+ 'return' => isset( $ret[0] ) ? $ret[0] : null,
+ 'print' => isset( $ret[1] ) ? $ret[1] : '',
+ ];
+ }
+
+ /**
+ * Workalike for luaL_checktype()
+ *
+ * @param string $funcName The Lua function name, for use in error messages
+ * @param array $args The argument array
+ * @param int $index0 The zero-based argument index
+ * @param string|array $type The allowed type names as given by gettype()
+ * @param string $msgType The type name used in the error message
+ * @throws Scribunto_LuaError
+ */
+ public function checkType( $funcName, $args, $index0, $type, $msgType ) {
+ if ( !is_array( $type ) ) {
+ $type = [ $type ];
+ }
+ if ( !isset( $args[$index0] ) || !in_array( gettype( $args[$index0] ), $type, true ) ) {
+ $index1 = $index0 + 1;
+ throw new Scribunto_LuaError( "bad argument #$index1 to '$funcName' ($msgType expected)" );
+ }
+ }
+
+ /**
+ * Workalike for luaL_checkstring()
+ *
+ * @param string $funcName The Lua function name, for use in error messages
+ * @param array $args The argument array
+ * @param int $index0 The zero-based argument index
+ */
+ public function checkString( $funcName, $args, $index0 ) {
+ $this->checkType( $funcName, $args, $index0, 'string', 'string' );
+ }
+
+ /**
+ * Workalike for luaL_checknumber()
+ *
+ * @param string $funcName The Lua function name, for use in error messages
+ * @param array $args The argument array
+ * @param int $index0 The zero-based argument index
+ */
+ public function checkNumber( $funcName, $args, $index0 ) {
+ $this->checkType( $funcName, $args, $index0, [ 'integer', 'double' ], 'number' );
+ }
+
+ /**
+ * Instantiate and register a library.
+ * @param string $name
+ * @param array|string $def
+ * @param bool $loadDeferred
+ * @throws MWException
+ * @return array|null
+ */
+ private function instantiatePHPLibrary( $name, $def, $loadDeferred ) {
+ $def = $this->availableLibraries[$name];
+ if ( is_string( $def ) ) {
+ $class = new $def( $this );
+ } else {
+ if ( !$loadDeferred && !empty( $def['deferLoad'] ) ) {
+ return null;
+ }
+ if ( isset( $def['class'] ) ) {
+ $class = new $def['class']( $this );
+ } else {
+ throw new MWException( "No class for library \"$name\"" );
+ }
+ }
+ return $class->register();
+ }
+
+ /**
+ * Handler for the loadPHPLibrary() callback. Register the specified
+ * library and return its function table. It's not necessary to cache the
+ * function table in the object instance, since there is caching in a
+ * wrapper on the Lua side.
+ * @param string $name
+ * @return array
+ */
+ function loadPHPLibrary( $name ) {
+ $args = func_get_args();
+ $this->checkString( 'loadPHPLibrary', $args, 0 );
+
+ $ret = null;
+ if ( isset( $this->availableLibraries[$name] ) ) {
+ $ret = $this->instantiatePHPLibrary( $name, $this->availableLibraries[$name], true );
+ }
+
+ return [ $ret ];
+ }
+
+ /**
+ * Handler for the loadPackage() callback. Load the specified
+ * module and return its chunk. It's not necessary to cache the resulting
+ * chunk in the object instance, since there is caching in a wrapper on the
+ * Lua side.
+ * @param string $name
+ * @return array
+ */
+ function loadPackage( $name ) {
+ $args = func_get_args();
+ $this->checkString( 'loadPackage', $args, 0 );
+
+ # This is what Lua does for its built-in loaders
+ $luaName = str_replace( '.', '/', $name ) . '.lua';
+ $paths = $this->getLibraryPaths( 'lua', self::$libraryPaths );
+ foreach ( $paths as $path ) {
+ $fileName = $this->normalizeModuleFileName( "$path/$luaName" );
+ if ( !file_exists( $fileName ) ) {
+ continue;
+ }
+ $code = file_get_contents( $fileName );
+ $init = $this->interpreter->loadString( $code, "@$luaName" );
+ return [ $init ];
+ }
+
+ $title = Title::newFromText( $name );
+ if ( !$title || !$title->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ return [];
+ }
+
+ $module = $this->fetchModuleFromParser( $title );
+ if ( $module ) {
+ /** @suppress PhanUndeclaredMethod */
+ return [ $module->getInitChunk() ];
+ } else {
+ return [];
+ }
+ }
+
+ /**
+ * Helper function for the implementation of frame methods
+ *
+ * @param string $frameId
+ * @return PPFrame
+ *
+ * @throws Scribunto_LuaError
+ */
+ protected function getFrameById( $frameId ) {
+ if ( $frameId === 'empty' ) {
+ return $this->getParser()->getPreprocessor()->newFrame();
+ } elseif ( isset( $this->currentFrames[$frameId] ) ) {
+ return $this->currentFrames[$frameId];
+ } else {
+ throw new Scribunto_LuaError( 'invalid frame ID' );
+ }
+ }
+
+ /**
+ * Handler for frameExists()
+ *
+ * @param string $frameId
+ * @return array
+ */
+ function frameExists( $frameId ) {
+ return [ $frameId === 'empty' || isset( $this->currentFrames[$frameId] ) ];
+ }
+
+ /**
+ * Handler for newChildFrame()
+ *
+ * @param string $frameId
+ * @param string $title
+ * @param array $args
+ * @return array
+ * @throws Scribunto_LuaError
+ */
+ function newChildFrame( $frameId, $title, array $args ) {
+ if ( count( $this->currentFrames ) > 100 ) {
+ throw new Scribunto_LuaError( 'newChild: too many frames' );
+ }
+
+ $frame = $this->getFrameById( $frameId );
+ if ( $title === false ) {
+ $title = $frame->getTitle();
+ } else {
+ $title = Title::newFromText( $title );
+ if ( !$title ) {
+ throw new Scribunto_LuaError( 'newChild: invalid title' );
+ }
+ }
+ $args = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
+ $newFrame = $frame->newChild( $args, $title );
+ $newFrameId = 'frame' . count( $this->currentFrames );
+ $this->currentFrames[$newFrameId] = $newFrame;
+ return [ $newFrameId ];
+ }
+
+ /**
+ * Handler for getTitle()
+ *
+ * @param string $frameId
+ *
+ * @return array
+ */
+ function getFrameTitle( $frameId ) {
+ $frame = $this->getFrameById( $frameId );
+ return [ $frame->getTitle()->getPrefixedText() ];
+ }
+
+ /**
+ * Handler for setTTL()
+ * @param int $ttl
+ */
+ function setTTL( $ttl ) {
+ $args = func_get_args();
+ $this->checkNumber( 'setTTL', $args, 0 );
+
+ $frame = $this->getFrameById( 'current' );
+ $frame->setTTL( $ttl );
+ }
+
+ /**
+ * Handler for getExpandedArgument()
+ * @param string $frameId
+ * @param string $name
+ * @return array
+ */
+ function getExpandedArgument( $frameId, $name ) {
+ $args = func_get_args();
+ $this->checkString( 'getExpandedArgument', $args, 0 );
+
+ $frame = $this->getFrameById( $frameId );
+ $this->getInterpreter()->pauseUsageTimer();
+ $result = $frame->getArgument( $name );
+ if ( $result === false ) {
+ return [];
+ } else {
+ return [ $result ];
+ }
+ }
+
+ /**
+ * Handler for getAllExpandedArguments()
+ * @param string $frameId
+ * @return array
+ */
+ function getAllExpandedArguments( $frameId ) {
+ $frame = $this->getFrameById( $frameId );
+ $this->getInterpreter()->pauseUsageTimer();
+ return [ $frame->getArguments() ];
+ }
+
+ /**
+ * Handler for expandTemplate()
+ * @param string $frameId
+ * @param string $titleText
+ * @param array $args
+ * @return array
+ * @throws Scribunto_LuaError
+ */
+ function expandTemplate( $frameId, $titleText, $args ) {
+ $frame = $this->getFrameById( $frameId );
+ $title = Title::newFromText( $titleText, NS_TEMPLATE );
+ if ( !$title ) {
+ throw new Scribunto_LuaError( "expandTemplate: invalid title \"$titleText\"" );
+ }
+
+ if ( $frame->depth >= $this->parser->mOptions->getMaxTemplateDepth() ) {
+ throw new Scribunto_LuaError( 'expandTemplate: template depth limit exceeded' );
+ }
+ if ( MWNamespace::isNonincludable( $title->getNamespace() ) ) {
+ throw new Scribunto_LuaError( 'expandTemplate: template inclusion denied' );
+ }
+
+ list( $dom, $finalTitle ) = $this->parser->getTemplateDom( $title );
+ if ( $dom === false ) {
+ throw new Scribunto_LuaError( "expandTemplate: template \"$titleText\" does not exist" );
+ }
+ if ( !$frame->loopCheck( $finalTitle ) ) {
+ throw new Scribunto_LuaError( 'expandTemplate: template loop detected' );
+ }
+
+ $fargs = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
+ $newFrame = $frame->newChild( $fargs, $finalTitle );
+ $text = $this->doCachedExpansion( $newFrame, $dom,
+ [
+ 'frameId' => $frameId,
+ 'template' => $finalTitle->getPrefixedDBkey(),
+ 'args' => $args
+ ] );
+ return [ $text ];
+ }
+
+ /**
+ * Handler for callParserFunction()
+ * @param string $frameId
+ * @param string $function
+ * @param array $args
+ * @throws MWException
+ * @throws Scribunto_LuaError
+ * @return array
+ */
+ function callParserFunction( $frameId, $function, $args ) {
+ $frame = $this->getFrameById( $frameId );
+
+ # Make zero-based, without screwing up named args
+ $args = array_merge( [], $args );
+
+ # Sort, since we can't rely on the order coming in from Lua
+ uksort( $args, function ( $a, $b ) {
+ if ( is_int( $a ) !== is_int( $b ) ) {
+ return is_int( $a ) ? -1 : 1;
+ }
+ if ( is_int( $a ) ) {
+ return $a - $b;
+ }
+ return strcmp( $a, $b );
+ } );
+
+ # Be user-friendly
+ $colonPos = strpos( $function, ':' );
+ if ( $colonPos !== false ) {
+ array_unshift( $args, trim( substr( $function, $colonPos + 1 ) ) );
+ $function = substr( $function, 0, $colonPos );
+ }
+ if ( !isset( $args[0] ) ) {
+ # It's impossible to call a parser function from wikitext without
+ # supplying an arg 0. Insist that one be provided via Lua, too.
+ throw new Scribunto_LuaError( 'callParserFunction: At least one unnamed parameter ' .
+ '(the parameter that comes after the colon in wikitext) ' .
+ 'must be provided'
+ );
+ }
+
+ $result = $this->parser->callParserFunction( $frame, $function, $args );
+ if ( !$result['found'] ) {
+ throw new Scribunto_LuaError( "callParserFunction: function \"$function\" was not found" );
+ }
+
+ # Set defaults for various flags
+ $result += [
+ 'nowiki' => false,
+ 'isChildObj' => false,
+ 'isLocalObj' => false,
+ 'isHTML' => false,
+ 'title' => false,
+ ];
+
+ $text = $result['text'];
+ if ( $result['isChildObj'] ) {
+ $fargs = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
+ $newFrame = $frame->newChild( $fargs, $result['title'] );
+ if ( $result['nowiki'] ) {
+ $text = $newFrame->expand( $text, PPFrame::RECOVER_ORIG );
+ } else {
+ $text = $newFrame->expand( $text );
+ }
+ }
+ if ( $result['isLocalObj'] && $result['nowiki'] ) {
+ $text = $frame->expand( $text, PPFrame::RECOVER_ORIG );
+ $result['isLocalObj'] = false;
+ }
+
+ # Replace raw HTML by a placeholder
+ if ( $result['isHTML'] ) {
+ $text = $this->parser->insertStripItem( $text );
+ } elseif ( $result['nowiki'] ) {
+ # Escape nowiki-style return values
+ $text = wfEscapeWikiText( $text );
+ }
+
+ if ( $result['isLocalObj'] ) {
+ $text = $frame->expand( $text );
+ }
+
+ return [ "$text" ];
+ }
+
+ /**
+ * Handler for preprocess()
+ * @param string $frameId
+ * @param string $text
+ * @return array
+ * @throws Scribunto_LuaError
+ */
+ function preprocess( $frameId, $text ) {
+ $args = func_get_args();
+ $this->checkString( 'preprocess', $args, 0 );
+
+ $frame = $this->getFrameById( $frameId );
+
+ if ( !$frame ) {
+ throw new Scribunto_LuaError( 'attempt to call mw.preprocess with no frame' );
+ }
+
+ // Don't count the time for expanding all the frame arguments against
+ // the Lua time limit.
+ $this->getInterpreter()->pauseUsageTimer();
+ $frame->getArguments();
+ $this->getInterpreter()->unpauseUsageTimer();
+
+ $text = $this->doCachedExpansion( $frame, $text,
+ [
+ 'frameId' => $frameId,
+ 'inputText' => $text
+ ] );
+ return [ $text ];
+ }
+
+ /**
+ * Increment the expensive function count, and throw if limit exceeded
+ *
+ * @throws Scribunto_LuaError
+ * @return null
+ */
+ public function incrementExpensiveFunctionCount() {
+ if ( !$this->getParser()->incrementExpensiveFunctionCount() ) {
+ throw new Scribunto_LuaError( "too many expensive function calls" );
+ }
+ return null;
+ }
+
+ /**
+ * Adds a warning to be displayed upon preview
+ *
+ * @param string $text wikitext
+ */
+ public function addWarning( $text ) {
+ $this->getParser()->getOutput()->addWarning( $text );
+ }
+
+ /**
+ * Return whether the parser is currently substing
+ *
+ * @return array
+ */
+ public function isSubsting() {
+ // See Parser::braceSubstitution, OT_WIKI is the switch
+ return [ $this->getParser()->OutputType() === Parser::OT_WIKI ];
+ }
+
+ function doCachedExpansion( $frame, $input, $cacheKey ) {
+ $hash = md5( serialize( $cacheKey ) );
+ if ( isset( $this->expandCache[$hash] ) ) {
+ return $this->expandCache[$hash];
+ }
+
+ if ( is_scalar( $input ) ) {
+ $input = str_replace( [ "\r\n", "\r" ], "\n", $input );
+ $dom = $this->parser->getPreprocessor()->preprocessToObj(
+ $input, $frame->depth ? Parser::PTD_FOR_INCLUSION : 0 );
+ } else {
+ $dom = $input;
+ }
+ $ret = $frame->expand( $dom );
+ if ( !$frame->isVolatile() ) {
+ if ( count( $this->expandCache ) > self::MAX_EXPAND_CACHE_SIZE ) {
+ reset( $this->expandCache );
+ $oldHash = key( $this->expandCache );
+ unset( $this->expandCache[$oldHash] );
+ }
+ $this->expandCache[$hash] = $ret;
+ }
+ return $ret;
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaModule extends ScribuntoModuleBase {
+ /**
+ * @var mixed
+ */
+ protected $initChunk;
+
+ /**
+ * @var Scribunto_LuaEngine
+ */
+ protected $engine;
+
+ /**
+ * @param Scribunto_LuaEngine $engine
+ * @param string $code
+ * @param string|bool $chunkName
+ */
+ public function __construct( Scribunto_LuaEngine $engine, $code, $chunkName ) {
+ parent::__construct( $engine, $code, $chunkName );
+ }
+
+ public function validate() {
+ try {
+ $this->getInitChunk();
+ } catch ( ScribuntoException $e ) {
+ return $e->toStatus();
+ }
+ return Status::newGood();
+ }
+
+ /**
+ * Get the chunk which, when called, will return the export table.
+ * @return mixed
+ */
+ public function getInitChunk() {
+ if ( !$this->initChunk ) {
+ $this->initChunk = $this->engine->getInterpreter()->loadString(
+ $this->code,
+ // Prepending an "=" to the chunk name avoids truncation or a "[string" prefix
+ '=' . $this->chunkName );
+ }
+ return $this->initChunk;
+ }
+
+ /**
+ * Invoke a function within the module. Return the expanded wikitext result.
+ *
+ * @param string $name
+ * @param PPFrame $frame
+ * @throws ScribuntoException
+ * @return string|null
+ */
+ public function invoke( $name, $frame ) {
+ $ret = $this->engine->executeModule( $this->getInitChunk(), $name, $frame );
+
+ if ( !isset( $ret ) ) {
+ throw $this->engine->newException(
+ 'scribunto-common-nosuchfunction', [ 'args' => [ $name ] ]
+ );
+ }
+ if ( !$this->engine->getInterpreter()->isLuaFunction( $ret ) ) {
+ throw $this->engine->newException(
+ 'scribunto-common-notafunction', [ 'args' => [ $name ] ]
+ );
+ }
+
+ $result = $this->engine->executeFunctionChunk( $ret, $frame );
+ if ( isset( $result[0] ) ) {
+ return $result[0];
+ } else {
+ return null;
+ }
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaError extends ScribuntoException {
+ public $luaMessage, $lineMap = [];
+
+ function __construct( $message, array $options = [] ) {
+ $this->luaMessage = $message;
+ $options = $options + [ 'args' => [ $message ] ];
+ if ( isset( $options['module'] ) && isset( $options['line'] ) ) {
+ $msg = 'scribunto-lua-error-location';
+ } else {
+ $msg = 'scribunto-lua-error';
+ }
+
+ parent::__construct( $msg, $options );
+ }
+
+ function getLuaMessage() {
+ return $this->luaMessage;
+ }
+
+ function setLineMap( $map ) {
+ $this->lineMap = $map;
+ }
+
+ /**
+ * @param array $options Options for message processing. Currently supports:
+ * $options['msgOptions']['content'] to use content language.
+ * @return bool|string
+ */
+ function getScriptTraceHtml( $options = [] ) {
+ if ( !isset( $this->params['trace'] ) ) {
+ return false;
+ }
+ if ( isset( $options['msgOptions'] ) ) {
+ $msgOptions = $options['msgOptions'];
+ } else {
+ $msgOptions = [];
+ }
+
+ $s = '<ol class="scribunto-trace">';
+ foreach ( $this->params['trace'] as $info ) {
+ $short_src = $srcdefined = $info['short_src'];
+ $currentline = $info['currentline'];
+
+ $src = htmlspecialchars( $short_src );
+ if ( $currentline > 0 ) {
+ $src .= ':' . htmlspecialchars( $currentline );
+
+ $title = Title::newFromText( $short_src );
+ if ( $title && $title->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ $title = $title->createFragmentTarget( 'mw-ce-l' . $currentline );
+ $src = Html::rawElement( 'a',
+ [ 'href' => $title->getFullURL( 'action=edit' ) ],
+ $src );
+ }
+ }
+
+ if ( strval( $info['namewhat'] ) !== '' ) {
+ $function = wfMessage( 'scribunto-lua-in-function', wfEscapeWikiText( $info['name'] ) );
+ in_array( 'content', $msgOptions ) ?
+ $function = $function->inContentLanguage()->plain() :
+ $function = $function->plain();
+ } elseif ( $info['what'] == 'main' ) {
+ $function = wfMessage( 'scribunto-lua-in-main' );
+ in_array( 'content', $msgOptions ) ?
+ $function = $function->inContentLanguage()->plain() :
+ $function = $function->plain();
+ } else {
+ // C function, tail call, or a Lua function where Lua can't
+ // guess the name
+ $function = '?';
+ }
+
+ $backtraceLine = wfMessage( 'scribunto-lua-backtrace-line' )
+ ->rawParams( "<strong>$src</strong>" )
+ ->params( $function );
+ in_array( 'content', $msgOptions ) ?
+ $backtraceLine = $backtraceLine->inContentLanguage()->parse() :
+ $backtraceLine = $backtraceLine->parse();
+
+ $s .= "<li>$backtraceLine</li>";
+ }
+ $s .= '</ol>';
+ return $s;
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaInterpreter.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaInterpreter.php
new file mode 100644
index 00000000..e1840310
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/LuaInterpreter.php
@@ -0,0 +1,68 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+abstract class Scribunto_LuaInterpreter {
+ /**
+ * Load a string. Return an object which can later be passed to callFunction.
+ * If there is a pass error, a Scribunto_LuaError will be thrown.
+ *
+ * @param string $text The Lua source code
+ * @param string $chunkName The chunk name
+ * @return mixed
+ */
+ abstract public function loadString( $text, $chunkName );
+
+ /**
+ * Call a Lua function. Return an array of results, with indices starting
+ * at zero. If an error occurs, a Scribunto_LuaError will be thrown.
+ *
+ * @param mixed $func The function object
+ */
+ abstract public function callFunction( $func /*...*/ );
+
+ /**
+ * Wrap a PHP callable as a Lua function, which can be passed back into
+ * Lua. If an error occurs, a Scribunto_LuaError will be thrown.
+ *
+ * @param callable $callable The PHP callable
+ * @return object a Lua function
+ */
+ abstract public function wrapPhpFunction( $callable );
+
+ /**
+ * Test whether an object is a Lua function.
+ *
+ * @param object $object
+ * @return bool
+ */
+ abstract public function isLuaFunction( $object );
+
+ /**
+ * Register a library of functions.
+ *
+ * @param string $name The global variable name to be created or added to.
+ * @param array $functions An associative array mapping the function name to the
+ * callback. The callback may throw a Scribunto_LuaError, which will be
+ * caught and raised in the Lua code as a Lua error, catchable with
+ * pcall().
+ */
+ abstract public function registerLibrary( $name, array $functions );
+
+ /**
+ * Pause CPU usage and limits
+ * @return void
+ */
+ abstract public function pauseUsageTimer();
+
+ /**
+ * Unpause CPU usage and limits
+ * @return void
+ */
+ abstract public function unpauseUsageTimer();
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaInterpreterNotFoundError extends MWException {}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaInterpreterBadVersionError extends MWException {}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/MessageLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/MessageLibrary.php
new file mode 100644
index 00000000..4d9edbd3
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/MessageLibrary.php
@@ -0,0 +1,59 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaMessageLibrary extends Scribunto_LuaLibraryBase {
+ function register() {
+ $lib = [
+ 'plain' => [ $this, 'messagePlain' ],
+ 'check' => [ $this, 'messageCheck' ],
+ ];
+
+ // Get the correct default language from the parser
+ if ( $this->getParser() ) {
+ $lang = $this->getParser()->getTargetLanguage();
+ } else {
+ global $wgContLang;
+ $lang = $wgContLang;
+ }
+
+ return $this->getEngine()->registerInterface( 'mw.message.lua', $lib, [
+ 'lang' => $lang->getCode(),
+ ] );
+ }
+
+ private function makeMessage( $data, $setParams ) {
+ if ( isset( $data['rawMessage'] ) ) {
+ $msg = new RawMessage( $data['rawMessage'] );
+ } else {
+ $msg = Message::newFallbackSequence( $data['keys'] );
+ }
+ $msg->inLanguage( $data['lang'] )
+ ->useDatabase( $data['useDB'] );
+ if ( $setParams ) {
+ $msg->params( array_values( $data['params'] ) );
+ }
+ return $msg;
+ }
+
+ function messagePlain( $data ) {
+ try {
+ $msg = $this->makeMessage( $data, true );
+ return [ $msg->plain() ];
+ } catch ( MWException $ex ) {
+ throw new Scribunto_LuaError( "msg:plain() failed (" . $ex->getMessage() . ")" );
+ }
+ }
+
+ function messageCheck( $what, $data ) {
+ if ( !in_array( $what, [ 'exists', 'isBlank', 'isDisabled' ] ) ) {
+ throw new Scribunto_LuaError( "invalid what for 'messageCheck'" );
+ }
+
+ try {
+ $msg = $this->makeMessage( $data, false );
+ return [ call_user_func( [ $msg, $what ] ) ];
+ } catch ( MWException $ex ) {
+ throw new Scribunto_LuaError( "msg:$what() failed (" . $ex->getMessage() . ")" );
+ }
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/SiteLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/SiteLibrary.php
new file mode 100644
index 00000000..92d733c4
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/SiteLibrary.php
@@ -0,0 +1,189 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaSiteLibrary extends Scribunto_LuaLibraryBase {
+ private static $namespacesCacheLang = null;
+ private static $namespacesCache = null;
+ private static $interwikiMapCache = [];
+ private $pagesInCategoryCache = [];
+
+ function register() {
+ global $wgContLang, $wgNamespaceAliases;
+
+ $lib = [
+ 'getNsIndex' => [ $this, 'getNsIndex' ],
+ 'pagesInCategory' => [ $this, 'pagesInCategory' ],
+ 'pagesInNamespace' => [ $this, 'pagesInNamespace' ],
+ 'usersInGroup' => [ $this, 'usersInGroup' ],
+ 'interwikiMap' => [ $this, 'interwikiMap' ],
+ ];
+ $parser = $this->getParser();
+ $info = [
+ 'siteName' => $GLOBALS['wgSitename'],
+ 'server' => $GLOBALS['wgServer'],
+ 'scriptPath' => $GLOBALS['wgScriptPath'],
+ 'stylePath' => $GLOBALS['wgStylePath'],
+ 'currentVersion' => SpecialVersion::getVersion(
+ '', $parser ? $parser->getTargetLanguage() : $wgContLang
+ ),
+ ];
+
+ if ( !self::$namespacesCache || self::$namespacesCacheLang !== $wgContLang->getCode() ) {
+ $namespaces = [];
+ $namespacesByName = [];
+ foreach ( $wgContLang->getFormattedNamespaces() as $ns => $title ) {
+ $canonical = MWNamespace::getCanonicalName( $ns );
+ $namespaces[$ns] = [
+ 'id' => $ns,
+ 'name' => $title,
+ 'canonicalName' => strtr( $canonical, '_', ' ' ),
+ 'hasSubpages' => MWNamespace::hasSubpages( $ns ),
+ 'hasGenderDistinction' => MWNamespace::hasGenderDistinction( $ns ),
+ 'isCapitalized' => MWNamespace::isCapitalized( $ns ),
+ 'isContent' => MWNamespace::isContent( $ns ),
+ 'isIncludable' => !MWNamespace::isNonincludable( $ns ),
+ 'isMovable' => MWNamespace::isMovable( $ns ),
+ 'isSubject' => MWNamespace::isSubject( $ns ),
+ 'isTalk' => MWNamespace::isTalk( $ns ),
+ 'defaultContentModel' => MWNamespace::getNamespaceContentModel( $ns ),
+ 'aliases' => [],
+ ];
+ if ( $ns >= NS_MAIN ) {
+ $namespaces[$ns]['subject'] = MWNamespace::getSubject( $ns );
+ $namespaces[$ns]['talk'] = MWNamespace::getTalk( $ns );
+ $namespaces[$ns]['associated'] = MWNamespace::getAssociated( $ns );
+ } else {
+ $namespaces[$ns]['subject'] = $ns;
+ }
+ $namespacesByName[strtr( $title, ' ', '_' )] = $ns;
+ if ( $canonical ) {
+ $namespacesByName[$canonical] = $ns;
+ }
+ }
+
+ $aliases = array_merge( $wgNamespaceAliases, $wgContLang->getNamespaceAliases() );
+ foreach ( $aliases as $title => $ns ) {
+ if ( !isset( $namespacesByName[$title] ) && isset( $namespaces[$ns] ) ) {
+ $ct = count( $namespaces[$ns]['aliases'] );
+ $namespaces[$ns]['aliases'][$ct + 1] = $title;
+ $namespacesByName[$title] = $ns;
+ }
+ }
+
+ $namespaces[NS_MAIN]['displayName'] = wfMessage( 'blanknamespace' )->inContentLanguage()->text();
+
+ self::$namespacesCache = $namespaces;
+ self::$namespacesCacheLang = $wgContLang->getCode();
+ }
+ $info['namespaces'] = self::$namespacesCache;
+
+ $info['stats'] = [
+ 'pages' => (int)SiteStats::pages(),
+ 'articles' => (int)SiteStats::articles(),
+ 'files' => (int)SiteStats::images(),
+ 'edits' => (int)SiteStats::edits(),
+ 'users' => (int)SiteStats::users(),
+ 'activeUsers' => (int)SiteStats::activeUsers(),
+ 'admins' => (int)SiteStats::numberingroup( 'sysop' ),
+ ];
+
+ return $this->getEngine()->registerInterface( 'mw.site.lua', $lib, $info );
+ }
+
+ public function pagesInCategory( $category = null, $which = null ) {
+ $this->checkType( 'pagesInCategory', 1, $category, 'string' );
+ $this->checkTypeOptional( 'pagesInCategory', 2, $which, 'string', 'all' );
+
+ $title = Title::makeTitleSafe( NS_CATEGORY, $category );
+ if ( !$title ) {
+ return [ 0 ];
+ }
+ $cacheKey = $title->getDBkey();
+
+ if ( !isset( $this->pagesInCategoryCache[$cacheKey] ) ) {
+ $this->incrementExpensiveFunctionCount();
+ $category = Category::newFromTitle( $title );
+ $counts = [
+ 'all' => (int)$category->getPageCount(),
+ 'subcats' => (int)$category->getSubcatCount(),
+ 'files' => (int)$category->getFileCount(),
+ ];
+ $counts['pages'] = $counts['all'] - $counts['subcats'] - $counts['files'];
+ $this->pagesInCategoryCache[$cacheKey] = $counts;
+ }
+ if ( $which === '*' ) {
+ return [ $this->pagesInCategoryCache[$cacheKey] ];
+ }
+ if ( !isset( $this->pagesInCategoryCache[$cacheKey][$which] ) ) {
+ $this->checkType(
+ 'pagesInCategory', 2, $which, "one of '*', 'all', 'pages', 'subcats', or 'files'"
+ );
+ }
+ return [ $this->pagesInCategoryCache[$cacheKey][$which] ];
+ }
+
+ public function pagesInNamespace( $ns = null ) {
+ $this->checkType( 'pagesInNamespace', 1, $ns, 'number' );
+ return [ (int)SiteStats::pagesInNs( intval( $ns ) ) ];
+ }
+
+ public function usersInGroup( $group = null ) {
+ $this->checkType( 'usersInGroup', 1, $group, 'string' );
+ return [ (int)SiteStats::numberingroup( strtolower( $group ) ) ];
+ }
+
+ public function getNsIndex( $name = null ) {
+ global $wgContLang;
+ $this->checkType( 'getNsIndex', 1, $name, 'string' );
+ // PHP call is case-insensitive but chokes on non-standard spaces/underscores.
+ $name = trim( preg_replace( '/[\s_]+/', '_', $name ), '_' );
+ return [ $wgContLang->getNsIndex( $name ) ];
+ }
+
+ public function interwikiMap( $filter = null ) {
+ global $wgLocalInterwikis, $wgExtraInterlanguageLinkPrefixes;
+ $this->checkTypeOptional( 'interwikiMap', 1, $filter, 'string', null );
+ $local = null;
+ if ( $filter === 'local' ) {
+ $local = 1;
+ } elseif ( $filter === '!local' ) {
+ $local = 0;
+ } elseif ( $filter !== null ) {
+ throw new Scribunto_LuaError(
+ "bad argument #1 to 'interwikiMap' (unknown filter '$filter')"
+ );
+ }
+ $cacheKey = $filter === null ? 'null' : $filter;
+ if ( !isset( self::$interwikiMapCache[$cacheKey] ) ) {
+ // Not expensive because we can have a max of three cache misses in the
+ // entire page parse.
+ $interwikiMap = [];
+ $prefixes = Interwiki::getAllPrefixes( $local );
+ foreach ( $prefixes as $row ) {
+ $prefix = $row['iw_prefix'];
+ $val = [
+ 'prefix' => $prefix,
+ 'url' => wfExpandUrl( $row['iw_url'], PROTO_RELATIVE ),
+ 'isProtocolRelative' => substr( $row['iw_url'], 0, 2 ) === '//',
+ 'isLocal' => isset( $row['iw_local'] ) && $row['iw_local'] == '1',
+ 'isTranscludable' => isset( $row['iw_trans'] ) && $row['iw_trans'] == '1',
+ 'isCurrentWiki' => in_array( $prefix, $wgLocalInterwikis ),
+ 'isExtraLanguageLink' => in_array( $prefix, $wgExtraInterlanguageLinkPrefixes ),
+ ];
+ if ( $val['isExtraLanguageLink'] ) {
+ $displayText = wfMessage( "interlanguage-link-$prefix" );
+ if ( !$displayText->isDisabled() ) {
+ $val['displayText'] = $displayText->text();
+ }
+ $tooltip = wfMessage( "interlanguage-link-sitename-$prefix" );
+ if ( !$tooltip->isDisabled() ) {
+ $val['tooltip'] = $tooltip->text();
+ }
+ }
+ $interwikiMap[$prefix] = $val;
+ }
+ self::$interwikiMapCache[$cacheKey] = $interwikiMap;
+ }
+ return [ self::$interwikiMapCache[$cacheKey] ];
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TextLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TextLibrary.php
new file mode 100644
index 00000000..794d3821
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TextLibrary.php
@@ -0,0 +1,142 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaTextLibrary extends Scribunto_LuaLibraryBase {
+ // Matches Lua mw.text constants
+ const JSON_PRESERVE_KEYS = 1;
+ const JSON_TRY_FIXING = 2;
+ const JSON_PRETTY = 4;
+
+ function register() {
+ global $wgUrlProtocols;
+
+ $lib = [
+ 'unstrip' => [ $this, 'textUnstrip' ],
+ 'unstripNoWiki' => [ $this, 'textUnstripNoWiki' ],
+ 'killMarkers' => [ $this, 'killMarkers' ],
+ 'getEntityTable' => [ $this, 'getEntityTable' ],
+ 'jsonEncode' => [ $this, 'jsonEncode' ],
+ 'jsonDecode' => [ $this, 'jsonDecode' ],
+ ];
+ $opts = [
+ 'comma' => wfMessage( 'comma-separator' )->inContentLanguage()->text(),
+ 'and' => wfMessage( 'and' )->inContentLanguage()->text() .
+ wfMessage( 'word-separator' )->inContentLanguage()->text(),
+ 'ellipsis' => wfMessage( 'ellipsis' )->inContentLanguage()->text(),
+ 'nowiki_protocols' => [],
+ ];
+
+ foreach ( $wgUrlProtocols as $prot ) {
+ if ( substr( $prot, -1 ) === ':' ) {
+ // To convert the protocol into a case-insensitive Lua pattern,
+ // we need to replace letters with a character class like [Xx]
+ // and insert a '%' before various punctuation.
+ $prot = preg_replace_callback( '/([a-zA-Z])|([()^$%.\[\]*+?-])/', function ( $m ) {
+ if ( $m[1] ) {
+ return '[' . strtoupper( $m[1] ) . strtolower( $m[1] ) . ']';
+ } else {
+ return '%' . $m[2];
+ }
+ }, substr( $prot, 0, -1 ) );
+ $opts['nowiki_protocols']["($prot):"] = '%1&#58;';
+ }
+ }
+
+ return $this->getEngine()->registerInterface( 'mw.text.lua', $lib, $opts );
+ }
+
+ function textUnstrip( $s ) {
+ $this->checkType( 'unstrip', 1, $s, 'string' );
+ $stripState = $this->getParser()->mStripState;
+ return [ $stripState->killMarkers( $stripState->unstripNoWiki( $s ) ) ];
+ }
+
+ function textUnstripNoWiki( $s ) {
+ $this->checkType( 'unstripNoWiki', 1, $s, 'string' );
+ return [ $this->getParser()->mStripState->unstripNoWiki( $s ) ];
+ }
+
+ function killMarkers( $s ) {
+ $this->checkType( 'killMarkers', 1, $s, 'string' );
+ return [ $this->getParser()->mStripState->killMarkers( $s ) ];
+ }
+
+ function getEntityTable() {
+ $table = array_flip(
+ get_html_translation_table( HTML_ENTITIES, ENT_QUOTES | ENT_HTML5, "UTF-8" )
+ );
+ return [ $table ];
+ }
+
+ public function jsonEncode( $value, $flags ) {
+ $this->checkTypeOptional( 'mw.text.jsonEncode', 2, $flags, 'number', 0 );
+ $flags = (int)$flags;
+ if ( !( $flags & self::JSON_PRESERVE_KEYS ) && is_array( $value ) ) {
+ $value = self::reindexArrays( $value, true );
+ }
+ $ret = FormatJson::encode( $value, (bool)( $flags & self::JSON_PRETTY ), FormatJson::ALL_OK );
+ if ( $ret === false ) {
+ throw new Scribunto_LuaError( 'mw.text.jsonEncode: Unable to encode value' );
+ }
+ return [ $ret ];
+ }
+
+ public function jsonDecode( $s, $flags ) {
+ $this->checkType( 'mw.text.jsonDecode', 1, $s, 'string' );
+ $this->checkTypeOptional( 'mw.text.jsonDecode', 2, $flags, 'number', 0 );
+ $flags = (int)$flags;
+ $opts = FormatJson::FORCE_ASSOC;
+ if ( $flags & self::JSON_TRY_FIXING ) {
+ $opts |= FormatJson::TRY_FIXING;
+ }
+ $status = FormatJson::parse( $s, $opts );
+ if ( !$status->isOk() ) {
+ throw new Scribunto_LuaError( 'mw.text.jsonDecode: ' . $status->getMessage()->text() );
+ }
+ $val = $status->getValue();
+ if ( !( $flags & self::JSON_PRESERVE_KEYS ) && is_array( $val ) ) {
+ $val = self::reindexArrays( $val, false );
+ }
+ return [ $val ];
+ }
+
+ /** Recursively reindex array with integer keys to 0-based or 1-based
+ * @param array $arr
+ * @param bool $isEncoding
+ * @return array
+ */
+ private static function reindexArrays( array $arr, $isEncoding ) {
+ if ( $isEncoding ) {
+ ksort( $arr, SORT_NUMERIC );
+ $next = 1;
+ } else {
+ $next = 0;
+ }
+ $isSequence = true;
+ foreach ( $arr as $k => &$v ) {
+ if ( is_array( $v ) ) {
+ $v = self::reindexArrays( $v, $isEncoding );
+ }
+
+ if ( $isSequence ) {
+ if ( is_int( $k ) ) {
+ $isSequence = $next++ === $k;
+ } elseif ( $isEncoding && ctype_digit( $k ) ) {
+ // json_decode currently doesn't return integer keys for {}
+ $isSequence = $next++ === (int)$k;
+ } else {
+ $isSequence = false;
+ }
+ }
+ }
+ if ( $isSequence ) {
+ if ( $isEncoding ) {
+ return array_values( $arr );
+ } else {
+ return $arr ? array_combine( range( 1, count( $arr ) ), $arr ) : $arr;
+ }
+ }
+ return $arr;
+ }
+
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TitleLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TitleLibrary.php
new file mode 100644
index 00000000..bf015639
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/TitleLibrary.php
@@ -0,0 +1,381 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaTitleLibrary extends Scribunto_LuaLibraryBase {
+ // Note these caches are naturally limited to
+ // $wgExpensiveParserFunctionLimit + 1 actual Title objects because any
+ // addition besides the one for the current page calls
+ // incrementExpensiveFunctionCount()
+ private $titleCache = [];
+ private $idCache = [ 0 => null ];
+
+ function register() {
+ $lib = [
+ 'newTitle' => [ $this, 'newTitle' ],
+ 'makeTitle' => [ $this, 'makeTitle' ],
+ 'getExpensiveData' => [ $this, 'getExpensiveData' ],
+ 'getUrl' => [ $this, 'getUrl' ],
+ 'getContent' => [ $this, 'getContent' ],
+ 'getFileInfo' => [ $this, 'getFileInfo' ],
+ 'protectionLevels' => [ $this, 'protectionLevels' ],
+ 'cascadingProtection' => [ $this, 'cascadingProtection' ],
+ 'redirectTarget' => [ $this, 'redirectTarget' ],
+ ];
+ return $this->getEngine()->registerInterface( 'mw.title.lua', $lib, [
+ 'thisTitle' => $this->getInexpensiveTitleData( $this->getTitle() ),
+ 'NS_MEDIA' => NS_MEDIA,
+ ] );
+ }
+
+ private function checkNamespace( $name, $argIdx, &$arg, $default = null ) {
+ global $wgContLang;
+
+ if ( $arg === null && $default !== null ) {
+ $arg = $default;
+ } elseif ( is_numeric( $arg ) ) {
+ $arg = (int)$arg;
+ if ( !MWNamespace::exists( $arg ) ) {
+ throw new Scribunto_LuaError(
+ "bad argument #$argIdx to '$name' (unrecognized namespace number '$arg')"
+ );
+ }
+ } elseif ( is_string( $arg ) ) {
+ $ns = $wgContLang->getNsIndex( $arg );
+ if ( $ns === false ) {
+ throw new Scribunto_LuaError(
+ "bad argument #$argIdx to '$name' (unrecognized namespace name '$arg')"
+ );
+ }
+ $arg = $ns;
+ } else {
+ $this->checkType( $name, $argIdx, $arg, 'namespace number or name' );
+ }
+ }
+
+ /**
+ * Extract inexpensive information from a Title object for return to Lua
+ *
+ * @param Title $title Title to return
+ * @return array Lua data
+ */
+ private function getInexpensiveTitleData( Title $title ) {
+ $ns = $title->getNamespace();
+ $ret = [
+ 'isLocal' => (bool)$title->isLocal(),
+ 'interwiki' => $title->getInterwiki(),
+ 'namespace' => $ns,
+ 'nsText' => $title->getNsText(),
+ 'text' => $title->getText(),
+ 'fragment' => $title->getFragment(),
+ 'thePartialUrl' => $title->getPartialURL(),
+ ];
+ if ( $ns === NS_SPECIAL ) {
+ // Core doesn't currently record special page links, but it may in the future.
+ if ( $this->getParser() && !$title->equals( $this->getTitle() ) ) {
+ $this->getParser()->getOutput()->addLink( $title );
+ }
+ $ret['exists'] = (bool)SpecialPageFactory::exists( $title->getDBkey() );
+ }
+ if ( $ns !== NS_FILE && $ns !== NS_MEDIA ) {
+ $ret['file'] = false;
+ }
+ return $ret;
+ }
+
+ /**
+ * Extract expensive information from a Title object for return to Lua
+ *
+ * This records a link to this title in the current ParserOutput and caches the
+ * title for repeated lookups. It may call incrementExpensiveFunctionCount() if
+ * the title is not already cached.
+ *
+ * @param string $text Title text
+ * @return array Lua data
+ */
+ public function getExpensiveData( $text ) {
+ $this->checkType( 'getExpensiveData', 1, $text, 'string' );
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return [ null ];
+ }
+ $dbKey = $title->getPrefixedDBkey();
+ if ( isset( $this->titleCache[$dbKey] ) ) {
+ // It was already cached, so we already did the expensive work and added a link
+ $title = $this->titleCache[$dbKey];
+ } else {
+ if ( !$title->equals( $this->getTitle() ) ) {
+ $this->incrementExpensiveFunctionCount();
+
+ // Record a link
+ if ( $this->getParser() ) {
+ $this->getParser()->getOutput()->addLink( $title );
+ }
+ }
+
+ // Cache it
+ $this->titleCache[$dbKey] = $title;
+ if ( $title->getArticleID() > 0 ) {
+ $this->idCache[$title->getArticleID()] = $title;
+ }
+ }
+
+ $ret = [
+ 'isRedirect' => (bool)$title->isRedirect(),
+ 'id' => $title->getArticleID(),
+ 'contentModel' => $title->getContentModel(),
+ ];
+ if ( $title->getNamespace() === NS_SPECIAL ) {
+ $ret['exists'] = (bool)SpecialPageFactory::exists( $title->getDBkey() );
+ } else {
+ // bug 70495: don't just check whether the ID != 0
+ $ret['exists'] = $title->exists();
+ }
+ return [ $ret ];
+ }
+
+ /**
+ * Handler for title.new
+ *
+ * Calls Title::newFromID or Title::newFromTitle as appropriate for the
+ * arguments.
+ *
+ * @param string|int $text_or_id Title or page_id to fetch
+ * @param string|int $defaultNamespace Namespace name or number to use if
+ * $text_or_id doesn't override
+ * @return array Lua data
+ */
+ function newTitle( $text_or_id, $defaultNamespace = null ) {
+ $type = $this->getLuaType( $text_or_id );
+ if ( $type === 'number' ) {
+ if ( array_key_exists( $text_or_id, $this->idCache ) ) {
+ $title = $this->idCache[$text_or_id];
+ } else {
+ $this->incrementExpensiveFunctionCount();
+ $title = Title::newFromID( $text_or_id );
+ $this->idCache[$text_or_id] = $title;
+
+ // Record a link
+ if ( $this->getParser() && $title && !$title->equals( $this->getTitle() ) ) {
+ $this->getParser()->getOutput()->addLink( $title );
+ }
+ }
+ if ( $title ) {
+ $this->titleCache[$title->getPrefixedDBkey()] = $title;
+ } else {
+ return [ null ];
+ }
+ } elseif ( $type === 'string' ) {
+ $this->checkNamespace( 'title.new', 2, $defaultNamespace, NS_MAIN );
+
+ // Note this just fills in the given fields, it doesn't fetch from
+ // the page table.
+ $title = Title::newFromText( $text_or_id, $defaultNamespace );
+ if ( !$title ) {
+ return [ null ];
+ }
+ } else {
+ // This will always fail
+ $this->checkType( 'title.new', 1, $text_or_id, 'number or string' );
+ }
+
+ return [ $this->getInexpensiveTitleData( $title ) ];
+ }
+
+ /**
+ * Handler for title.makeTitle
+ *
+ * Calls Title::makeTitleSafe.
+ *
+ * @param string|int $ns Namespace
+ * @param string $text Title text
+ * @param string $fragment URI fragment
+ * @param string $interwiki Interwiki code
+ * @return array Lua data
+ */
+ function makeTitle( $ns, $text, $fragment = null, $interwiki = null ) {
+ $this->checkNamespace( 'makeTitle', 1, $ns );
+ $this->checkType( 'makeTitle', 2, $text, 'string' );
+ $this->checkTypeOptional( 'makeTitle', 3, $fragment, 'string', '' );
+ $this->checkTypeOptional( 'makeTitle', 4, $interwiki, 'string', '' );
+
+ // Note this just fills in the given fields, it doesn't fetch from the
+ // page table.
+ $title = Title::makeTitleSafe( $ns, $text, $fragment, $interwiki );
+ if ( !$title ) {
+ return [ null ];
+ }
+
+ return [ $this->getInexpensiveTitleData( $title ) ];
+ }
+
+ /**
+ * Get a URL referring to this title
+ * @param string $text Title text.
+ * @param string $which 'fullUrl', 'localUrl', or 'canonicalUrl'
+ * @param string|array|null $query Query string or query string data.
+ * @param string|null $proto 'http', 'https', 'relative', or 'canonical'
+ * @return array
+ */
+ function getUrl( $text, $which, $query = null, $proto = null ) {
+ static $protoMap = [
+ 'http' => PROTO_HTTP,
+ 'https' => PROTO_HTTPS,
+ 'relative' => PROTO_RELATIVE,
+ 'canonical' => PROTO_CANONICAL,
+ ];
+
+ $this->checkType( 'getUrl', 1, $text, 'string' );
+ $this->checkType( 'getUrl', 2, $which, 'string' );
+ if ( !in_array( $which, [ 'fullUrl', 'localUrl', 'canonicalUrl' ], true ) ) {
+ $this->checkType( 'getUrl', 2, $which, "'fullUrl', 'localUrl', or 'canonicalUrl'" );
+ }
+
+ // May call the following Title methods:
+ // getFullUrl, getLocalUrl, getCanonicalUrl
+ $func = "get" . ucfirst( $which );
+
+ $args = [ $query, false ];
+ if ( !is_string( $query ) && !is_array( $query ) ) {
+ $this->checkTypeOptional( $which, 1, $query, 'table or string', '' );
+ }
+ if ( $which === 'fullUrl' ) {
+ $this->checkTypeOptional( $which, 2, $proto, 'string', 'relative' );
+ if ( !isset( $protoMap[$proto] ) ) {
+ $this->checkType( $which, 2, $proto, "'http', 'https', 'relative', or 'canonical'" );
+ }
+ $args[] = $protoMap[$proto];
+ }
+
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return [ null ];
+ }
+ return [ call_user_func_array( [ $title, $func ], $args ) ];
+ }
+
+ /**
+ * Utility to get a Content object from a title
+ *
+ * The title is counted as a transclusion.
+ *
+ * @param $text string Title text
+ * @return Content|null The Content object of the title, null if missing
+ */
+ private function getContentInternal( $text ) {
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return null;
+ }
+
+ // Record in templatelinks, so edits cause the page to be refreshed
+ $this->getParser()->getOutput()->addTemplate(
+ $title, $title->getArticleID(), $title->getLatestRevID()
+ );
+ if ( $title->equals( $this->getTitle() ) ) {
+ $this->getParser()->getOutput()->setFlag( 'vary-revision' );
+ }
+
+ $rev = $this->getParser()->fetchCurrentRevisionOfTitle( $title );
+ return $rev ? $rev->getContent() : null;
+ }
+
+ function getContent( $text ) {
+ $this->checkType( 'getContent', 1, $text, 'string' );
+ $content = $this->getContentInternal( $text );
+ return [ $content ? $content->serialize() : null ];
+ }
+
+ function getFileInfo( $text ) {
+ $this->checkType( 'getFileInfo', 1, $text, 'string' );
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return [ false ];
+ }
+ $ns = $title->getNamespace();
+ if ( $ns !== NS_FILE && $ns !== NS_MEDIA ) {
+ return [ false ];
+ }
+
+ $this->incrementExpensiveFunctionCount();
+ $file = wfFindFile( $title );
+ if ( !$file ) {
+ return [ [ 'exists' => false ] ];
+ }
+ $this->getParser()->getOutput()->addImage(
+ $file->getName(), $file->getTimestamp(), $file->getSha1()
+ );
+ if ( !$file->exists() ) {
+ return [ [ 'exists' => false ] ];
+ }
+ $pageCount = $file->pageCount();
+ if ( $pageCount === false ) {
+ $pages = null;
+ } else {
+ $pages = [];
+ for ( $i = 1; $i <= $pageCount; ++$i ) {
+ $pages[$i] = [
+ 'width' => $file->getWidth( $i ),
+ 'height' => $file->getHeight( $i )
+ ];
+ }
+ }
+ return [ [
+ 'exists' => true,
+ 'width' => $file->getWidth(),
+ 'height' => $file->getHeight(),
+ 'mimeType' => $file->getMimeType(),
+ 'size' => $file->getSize(),
+ 'pages' => $pages
+ ] ];
+ }
+
+ private static function makeArrayOneBased( $arr ) {
+ if ( empty( $arr ) ) {
+ return $arr;
+ }
+ return array_combine( range( 1, count( $arr ) ), array_values( $arr ) );
+ }
+
+ public function protectionLevels( $text ) {
+ $this->checkType( 'protectionLevels', 1, $text, 'string' );
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return [ null ];
+ }
+
+ if ( !$title->areRestrictionsLoaded() ) {
+ $this->incrementExpensiveFunctionCount();
+ }
+ return [ array_map(
+ 'Scribunto_LuaTitleLibrary::makeArrayOneBased', $title->getAllRestrictions()
+ ) ];
+ }
+
+ public function cascadingProtection( $text ) {
+ $this->checkType( 'cascadingProtection', 1, $text, 'string' );
+ $title = Title::newFromText( $text );
+ if ( !$title ) {
+ return [ null ];
+ }
+
+ if ( !$title->areCascadeProtectionSourcesLoaded() ) {
+ $this->incrementExpensiveFunctionCount();
+ }
+ list( $sources, $restrictions ) = $title->getCascadeProtectionSources();
+ return [ [
+ 'sources' => self::makeArrayOneBased( array_map(
+ function ( $t ) {
+ return $t->getPrefixedText();
+ },
+ $sources ) ),
+ 'restrictions' => array_map( 'Scribunto_LuaTitleLibrary::makeArrayOneBased', $restrictions )
+ ] ];
+ }
+
+ public function redirectTarget( $text ) {
+ $this->checkType( 'redirectTarget', 1, $text, 'string' );
+ $content = $this->getContentInternal( $text );
+ $redirTitle = $content ? $content->getRedirectTarget() : null;
+ return [ $redirTitle ? $this->getInexpensiveTitleData( $redirTitle ) : null ];
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UriLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UriLibrary.php
new file mode 100644
index 00000000..3492e7b9
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UriLibrary.php
@@ -0,0 +1,56 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaUriLibrary extends Scribunto_LuaLibraryBase {
+ function register() {
+ $lib = [
+ 'anchorEncode' => [ $this, 'anchorEncode' ],
+ 'localUrl' => [ $this, 'localUrl' ],
+ 'fullUrl' => [ $this, 'fullUrl' ],
+ 'canonicalUrl' => [ $this, 'canonicalUrl' ],
+ ];
+
+ return $this->getEngine()->registerInterface( 'mw.uri.lua', $lib, [
+ 'defaultUrl' => $this->getTitle()->getFullUrl(),
+ ] );
+ }
+
+ public function anchorEncode( $s ) {
+ return [ CoreParserFunctions::anchorencode(
+ $this->getParser(), $s
+ ) ];
+ }
+
+ private function getUrl( $func, $page, $query ) {
+ $title = Title::newFromText( $page );
+ if ( !$title ) {
+ $title = Title::newFromURL( urldecode( $page ) );
+ }
+ if ( $title ) {
+ # Convert NS_MEDIA -> NS_FILE
+ if ( $title->getNamespace() == NS_MEDIA ) {
+ $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
+ }
+ if ( $query !== null ) {
+ $text = $title->$func( $query );
+ } else {
+ $text = $title->$func();
+ }
+ return [ $text ];
+ } else {
+ return [ null ];
+ }
+ }
+
+ public function localUrl( $page, $query ) {
+ return $this->getUrl( 'getLocalURL', $page, $query );
+ }
+
+ public function fullUrl( $page, $query ) {
+ return $this->getUrl( 'getFullURL', $page, $query );
+ }
+
+ public function canonicalUrl( $page, $query ) {
+ return $this->getUrl( 'getCanonicalURL', $page, $query );
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UstringLibrary.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UstringLibrary.php
new file mode 100644
index 00000000..d8905845
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/UstringLibrary.php
@@ -0,0 +1,781 @@
+<?php
+
+use UtfNormal\Validator;
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaUstringLibrary extends Scribunto_LuaLibraryBase {
+ /**
+ * Limit on pattern lengths, in bytes not characters
+ * @var integer
+ */
+ private $patternLengthLimit = 10000;
+
+ /**
+ * Limit on string lengths, in bytes not characters
+ * If null, $wgMaxArticleSize * 1024 will be used
+ * @var integer|null
+ */
+ private $stringLengthLimit = null;
+
+ /**
+ * PHP until 5.6.9 are buggy when the regex in preg_replace an
+ * preg_match_all matches the empty string.
+ * @var boolean
+ */
+ private $phpBug53823 = false;
+
+ /**
+ * A cache of patterns and the regexes they generate.
+ * @var MapCacheLRU
+ */
+ private $patternRegexCache = null;
+
+ function __construct( $engine ) {
+ if ( $this->stringLengthLimit === null ) {
+ global $wgMaxArticleSize;
+ $this->stringLengthLimit = $wgMaxArticleSize * 1024;
+ }
+
+ $this->phpBug53823 = preg_replace( '//us', 'x', "\xc3\xa1" ) === "x\xc3x\xa1x";
+ $this->patternRegexCache = new MapCacheLRU( 100 );
+
+ parent::__construct( $engine );
+ }
+
+ function register() {
+ $perf = $this->getEngine()->getPerformanceCharacteristics();
+
+ if ( $perf['phpCallsRequireSerialization'] ) {
+ $lib = [
+ // Pattern matching is still much faster in PHP, even with the
+ // overhead of serialization
+ 'find' => [ $this, 'ustringFind' ],
+ 'match' => [ $this, 'ustringMatch' ],
+ 'gmatch_init' => [ $this, 'ustringGmatchInit' ],
+ 'gmatch_callback' => [ $this, 'ustringGmatchCallback' ],
+ 'gsub' => [ $this, 'ustringGsub' ],
+ ];
+ } else {
+ $lib = [
+ 'isutf8' => [ $this, 'ustringIsUtf8' ],
+ 'byteoffset' => [ $this, 'ustringByteoffset' ],
+ 'codepoint' => [ $this, 'ustringCodepoint' ],
+ 'gcodepoint_init' => [ $this, 'ustringGcodepointInit' ],
+ 'toNFC' => [ $this, 'ustringToNFC' ],
+ 'toNFD' => [ $this, 'ustringToNFD' ],
+ 'toNFKC' => [ $this, 'ustringToNFKC' ],
+ 'toNFKD' => [ $this, 'ustringToNFKD' ],
+ 'char' => [ $this, 'ustringChar' ],
+ 'len' => [ $this, 'ustringLen' ],
+ 'sub' => [ $this, 'ustringSub' ],
+ 'upper' => [ $this, 'ustringUpper' ],
+ 'lower' => [ $this, 'ustringLower' ],
+ 'find' => [ $this, 'ustringFind' ],
+ 'match' => [ $this, 'ustringMatch' ],
+ 'gmatch_init' => [ $this, 'ustringGmatchInit' ],
+ 'gmatch_callback' => [ $this, 'ustringGmatchCallback' ],
+ 'gsub' => [ $this, 'ustringGsub' ],
+ ];
+ }
+ return $this->getEngine()->registerInterface( 'mw.ustring.lua', $lib, [
+ 'stringLengthLimit' => $this->stringLengthLimit,
+ 'patternLengthLimit' => $this->patternLengthLimit,
+ ] );
+ }
+
+ private function checkString( $name, $s, $checkEncoding = true ) {
+ if ( $this->getLuaType( $s ) == 'number' ) {
+ $s = (string)$s;
+ } else {
+ $this->checkType( $name, 1, $s, 'string' );
+ if ( $checkEncoding && !mb_check_encoding( $s, 'UTF-8' ) ) {
+ throw new Scribunto_LuaError( "bad argument #1 to '$name' (string is not UTF-8)" );
+ }
+ if ( strlen( $s ) > $this->stringLengthLimit ) {
+ throw new Scribunto_LuaError(
+ "bad argument #1 to '$name' (string is longer than $this->stringLengthLimit bytes)"
+ );
+ }
+ }
+ }
+
+ public function ustringIsUtf8( $s ) {
+ $this->checkString( 'isutf8', $s, false );
+ return [ mb_check_encoding( $s, 'UTF-8' ) ];
+ }
+
+ public function ustringByteoffset( $s, $l = 1, $i = 1 ) {
+ $this->checkString( 'byteoffset', $s );
+ $this->checkTypeOptional( 'byteoffset', 2, $l, 'number', 1 );
+ $this->checkTypeOptional( 'byteoffset', 3, $i, 'number', 1 );
+
+ $bytelen = strlen( $s );
+ if ( $i < 0 ) {
+ $i = $bytelen + $i + 1;
+ }
+ if ( $i < 1 || $i > $bytelen ) {
+ return [ null ];
+ }
+ $i--;
+ $j = $i;
+ while ( ( ord( $s[$i] ) & 0xc0 ) === 0x80 ) {
+ $i--;
+ }
+ if ( $l > 0 && $j === $i ) {
+ $l--;
+ }
+ $char = mb_strlen( substr( $s, 0, $i ), 'UTF-8' ) + $l;
+ if ( $char < 0 || $char >= mb_strlen( $s, 'UTF-8' ) ) {
+ return [ null ];
+ } else {
+ return [ strlen( mb_substr( $s, 0, $char, 'UTF-8' ) ) + 1 ];
+ }
+ }
+
+ public function ustringCodepoint( $s, $i = 1, $j = null ) {
+ $this->checkString( 'codepoint', $s );
+ $this->checkTypeOptional( 'codepoint', 2, $i, 'number', 1 );
+ $this->checkTypeOptional( 'codepoint', 3, $j, 'number', $i );
+
+ $l = mb_strlen( $s, 'UTF-8' );
+ if ( $i < 0 ) {
+ $i = $l + $i + 1;
+ }
+ if ( $j < 0 ) {
+ $j = $l + $j + 1;
+ }
+ if ( $j < $i ) {
+ return [];
+ }
+ $i = max( 1, min( $i, $l + 1 ) );
+ $j = max( 1, min( $j, $l + 1 ) );
+ $s = mb_substr( $s, $i - 1, $j - $i + 1, 'UTF-8' );
+ return unpack( 'N*', mb_convert_encoding( $s, 'UTF-32BE', 'UTF-8' ) );
+ }
+
+ public function ustringGcodepointInit( $s, $i = 1, $j = null ) {
+ return [ $this->ustringCodepoint( $s, $i, $j ) ];
+ }
+
+ public function ustringToNFC( $s ) {
+ $this->checkString( 'toNFC', $s, false );
+ if ( !mb_check_encoding( $s, 'UTF-8' ) ) {
+ return [ null ];
+ }
+ return [ Validator::toNFC( $s ) ];
+ }
+
+ public function ustringToNFD( $s ) {
+ $this->checkString( 'toNFD', $s, false );
+ if ( !mb_check_encoding( $s, 'UTF-8' ) ) {
+ return [ null ];
+ }
+ return [ Validator::toNFD( $s ) ];
+ }
+
+ public function ustringToNFKC( $s ) {
+ $this->checkString( 'toNFKC', $s, false );
+ if ( !mb_check_encoding( $s, 'UTF-8' ) ) {
+ return [ null ];
+ }
+ return [ Validator::toNFKC( $s ) ];
+ }
+
+ public function ustringToNFKD( $s ) {
+ $this->checkString( 'toNFKD', $s, false );
+ if ( !mb_check_encoding( $s, 'UTF-8' ) ) {
+ return [ null ];
+ }
+ return [ Validator::toNFKD( $s ) ];
+ }
+
+ /**
+ * @return array
+ */
+ public function ustringChar() {
+ $args = func_get_args();
+ if ( count( $args ) > $this->stringLengthLimit ) {
+ throw new Scribunto_LuaError( "too many arguments to 'char'" );
+ }
+ foreach ( $args as $k => &$v ) {
+ if ( !is_numeric( $v ) ) {
+ $this->checkType( 'char', $k + 1, $v, 'number' );
+ }
+ $v = (int)floor( $v );
+ if ( $v < 0 || $v > 0x10ffff ) {
+ $k++;
+ throw new Scribunto_LuaError( "bad argument #$k to 'char' (value out of range)" );
+ }
+ }
+ array_unshift( $args, 'N*' );
+ $s = call_user_func_array( 'pack', $args );
+ $s = mb_convert_encoding( $s, 'UTF-8', 'UTF-32BE' );
+ if ( strlen( $s ) > $this->stringLengthLimit ) {
+ throw new Scribunto_LuaError( "result to long for 'char'" );
+ }
+ return [ $s ];
+ }
+
+ public function ustringLen( $s ) {
+ $this->checkString( 'len', $s, false );
+ if ( !mb_check_encoding( $s, 'UTF-8' ) ) {
+ return [ null ];
+ }
+ return [ mb_strlen( $s, 'UTF-8' ) ];
+ }
+
+ public function ustringSub( $s, $i=1, $j=-1 ) {
+ $this->checkString( 'sub', $s );
+ $this->checkTypeOptional( 'sub', 2, $i, 'number', 1 );
+ $this->checkTypeOptional( 'sub', 3, $j, 'number', -1 );
+
+ $len = mb_strlen( $s, 'UTF-8' );
+ if ( $i < 0 ) {
+ $i = $len + $i + 1;
+ }
+ if ( $j < 0 ) {
+ $j = $len + $j + 1;
+ }
+ if ( $j < $i ) {
+ return [ '' ];
+ }
+ $i = max( 1, min( $i, $len + 1 ) );
+ $j = max( 1, min( $j, $len + 1 ) );
+ $s = mb_substr( $s, $i - 1, $j - $i + 1, 'UTF-8' );
+ return [ $s ];
+ }
+
+ public function ustringUpper( $s ) {
+ $this->checkString( 'upper', $s );
+ return [ mb_strtoupper( $s, 'UTF-8' ) ];
+ }
+
+ public function ustringLower( $s ) {
+ $this->checkString( 'lower', $s );
+ return [ mb_strtolower( $s, 'UTF-8' ) ];
+ }
+
+ private function checkPattern( $name, $pattern ) {
+ if ( $this->getLuaType( $pattern ) == 'number' ) {
+ $pattern = (string)$pattern;
+ }
+ $this->checkType( $name, 2, $pattern, 'string' );
+ if ( !mb_check_encoding( $pattern, 'UTF-8' ) ) {
+ throw new Scribunto_LuaError( "bad argument #2 to '$name' (string is not UTF-8)" );
+ }
+ if ( strlen( $pattern ) > $this->patternLengthLimit ) {
+ throw new Scribunto_LuaError(
+ "bad argument #2 to '$name' (pattern is longer than $this->patternLengthLimit bytes)"
+ );
+ }
+ }
+
+ /* Convert a Lua pattern into a PCRE regex */
+ private function patternToRegex( $pattern, $anchor, $name ) {
+ $cacheKey = serialize( [ $pattern, $anchor ] );
+ if ( !$this->patternRegexCache->has( $cacheKey ) ) {
+ $this->checkPattern( $name, $pattern );
+ $pat = preg_split( '//us', $pattern, null, PREG_SPLIT_NO_EMPTY );
+
+ static $charsets = null, $brcharsets = null;
+ if ( $charsets === null ) {
+ $charsets = [
+ // If you change these, also change lualib/ustring/make-tables.php
+ // (and run it to regenerate charsets.lua)
+ 'a' => '\p{L}',
+ 'c' => '\p{Cc}',
+ 'd' => '\p{Nd}',
+ 'l' => '\p{Ll}',
+ 'p' => '\p{P}',
+ 's' => '\p{Xps}',
+ 'u' => '\p{Lu}',
+ 'w' => '[\p{L}\p{Nd}]',
+ 'x' => '[0-9A-Fa-f0-9A-Fa-f]',
+ 'z' => '\0',
+
+ // These *must* be the inverse of the above
+ 'A' => '\P{L}',
+ 'C' => '\P{Cc}',
+ 'D' => '\P{Nd}',
+ 'L' => '\P{Ll}',
+ 'P' => '\P{P}',
+ 'S' => '\P{Xps}',
+ 'U' => '\P{Lu}',
+ 'W' => '[^\p{L}\p{Nd}]',
+ 'X' => '[^0-9A-Fa-f0-9A-Fa-f]',
+ 'Z' => '[^\0]',
+ ];
+ $brcharsets = [
+ 'w' => '\p{L}\p{Nd}',
+ 'x' => '0-9A-Fa-f0-9A-Fa-f',
+
+ // Negated sets that are not expressable as a simple \P{} are
+ // unfortunately complicated.
+
+ // Xan is L plus N, so ^Xan plus Nl plus No is anything that's not L or Nd
+ 'W' => '\P{Xan}\p{Nl}\p{No}',
+
+ // Manually constructed. Fun.
+ 'X' => '\x00-\x2f\x3a-\x40\x47-\x60\x67-\x{ff0f}'
+ . '\x{ff1a}-\x{ff20}\x{ff27}-\x{ff40}\x{ff47}-\x{10ffff}',
+
+ // Ha!
+ 'Z' => '\x01-\x{10ffff}',
+ ] + $charsets;
+ }
+
+ $re = '/';
+ $len = count( $pat );
+ $capt = [];
+ $anypos = false;
+ $captparen = [];
+ $opencapt = [];
+ $bct = 0;
+
+ for ( $i = 0; $i < $len; $i++ ) {
+ $ii = $i + 1;
+ $q = false;
+ switch ( $pat[$i] ) {
+ case '^':
+ $q = $i;
+ $re .= ( $anchor === false || $q ) ? '\\^' : $anchor;
+ break;
+
+ case '$':
+ $q = ( $i < $len - 1 );
+ $re .= $q ? '\\$' : '$';
+ break;
+
+ case '(':
+ if ( $i + 1 >= $len ) {
+ throw new Scribunto_LuaError( "Unmatched open-paren at pattern character $ii" );
+ }
+ $n = count( $capt ) + 1;
+ $capt[$n] = ( $pat[$i + 1] === ')' );
+ if ( $capt[$n] ) {
+ $anypos = true;
+ }
+ $re .= "(?<m$n>";
+ $opencapt[] = $n;
+ $captparen[$n] = $ii;
+ break;
+
+ case ')':
+ if ( count( $opencapt ) <= 0 ) {
+ throw new Scribunto_LuaError( "Unmatched close-paren at pattern character $ii" );
+ }
+ array_pop( $opencapt );
+ $re .= $pat[$i];
+ break;
+
+ case '%':
+ $i++;
+ if ( $i >= $len ) {
+ throw new Scribunto_LuaError( "malformed pattern (ends with '%')" );
+ }
+ if ( isset( $charsets[$pat[$i]] ) ) {
+ $re .= $charsets[$pat[$i]];
+ $q = true;
+ } elseif ( $pat[$i] === 'b' ) {
+ if ( $i + 2 >= $len ) {
+ throw new Scribunto_LuaError( "malformed pattern (missing arguments to \'%b\')" );
+ }
+ $d1 = preg_quote( $pat[++$i], '/' );
+ $d2 = preg_quote( $pat[++$i], '/' );
+ if ( $d1 === $d2 ) {
+ $re .= "{$d1}[^$d1]*$d1";
+ } else {
+ $bct++;
+ $re .= "(?<b$bct>$d1(?:(?>[^$d1$d2]+)|(?P>b$bct))*$d2)";
+ }
+ } elseif ( $pat[$i] === 'f' ) {
+ if ( $i + 1 >= $len || $pat[++$i] !== '[' ) {
+ throw new Scribunto_LuaError( "missing '[' after %f in pattern at pattern character $ii" );
+ }
+ list( $i, $re2 ) = $this->bracketedCharSetToRegex( $pat, $i, $len, $brcharsets );
+ // Because %f considers the beginning and end of the string
+ // to be \0, determine if $re2 matches that and take it
+ // into account with "^" and "$".
+ if ( preg_match( "/$re2/us", "\0" ) ) {
+ $re .= "(?<!^)(?<!$re2)(?=$re2|$)";
+ } else {
+ $re .= "(?<!$re2)(?=$re2)";
+ }
+ } elseif ( $pat[$i] >= '0' && $pat[$i] <= '9' ) {
+ $n = ord( $pat[$i] ) - 0x30;
+ if ( $n === 0 || $n > count( $capt ) || in_array( $n, $opencapt ) ) {
+ throw new Scribunto_LuaError( "invalid capture index %$n at pattern character $ii" );
+ }
+ $re .= "\\g{m$n}";
+ } else {
+ $re .= preg_quote( $pat[$i], '/' );
+ $q = true;
+ }
+ break;
+
+ case '[':
+ list( $i, $re2 ) = $this->bracketedCharSetToRegex( $pat, $i, $len, $brcharsets );
+ $re .= $re2;
+ $q = true;
+ break;
+
+ case ']':
+ throw new Scribunto_LuaError( "Unmatched close-bracket at pattern character $ii" );
+
+ case '.':
+ $re .= $pat[$i];
+ $q = true;
+ break;
+
+ default:
+ $re .= preg_quote( $pat[$i], '/' );
+ $q = true;
+ break;
+ }
+ if ( $q && $i + 1 < $len ) {
+ switch ( $pat[$i + 1] ) {
+ case '*':
+ case '+':
+ case '?':
+ $re .= $pat[++$i];
+ break;
+ case '-':
+ $re .= '*?';
+ $i++;
+ break;
+ }
+ }
+ }
+ if ( count( $opencapt ) ) {
+ $ii = $captparen[$opencapt[0]];
+ throw new Scribunto_LuaError( "Unclosed capture beginning at pattern character $ii" );
+ }
+ $re .= '/us';
+
+ $this->patternRegexCache->set( $cacheKey, [ $re, $capt, $anypos ] );
+ }
+ return $this->patternRegexCache->get( $cacheKey );
+ }
+
+ private function bracketedCharSetToRegex( $pat, $i, $len, $brcharsets ) {
+ $ii = $i + 1;
+ $re = '[';
+ $i++;
+ if ( $i < $len && $pat[$i] === '^' ) {
+ $re .= '^';
+ $i++;
+ }
+ for ( $j = $i; $i < $len && ( $j == $i || $pat[$i] !== ']' ); $i++ ) {
+ if ( $pat[$i] === '%' ) {
+ $i++;
+ if ( $i >= $len ) {
+ break;
+ }
+ if ( isset( $brcharsets[$pat[$i]] ) ) {
+ $re .= $brcharsets[$pat[$i]];
+ } else {
+ $re .= preg_quote( $pat[$i], '/' );
+ }
+ } elseif ( $i + 2 < $len &&
+ $pat[$i + 1] === '-' && $pat[$i + 2] !== ']' && $pat[$i + 2] !== '%'
+ ) {
+ if ( $pat[$i] <= $pat[$i + 2] ) {
+ $re .= preg_quote( $pat[$i], '/' ) . '-' . preg_quote( $pat[$i + 2], '/' );
+ }
+ $i += 2;
+ } else {
+ $re .= preg_quote( $pat[$i], '/' );
+ }
+ }
+ if ( $i >= $len ) {
+ throw new Scribunto_LuaError(
+ "Missing close-bracket for character set beginning at pattern character $ii"
+ );
+ }
+ $re .= ']';
+
+ // Lua just ignores invalid ranges, while pcre throws an error.
+ // We filter them out above, but then we need to special-case empty sets
+ if ( $re === '[]' ) {
+ // Can't directly quantify (*FAIL), so wrap it.
+ // "(?!)" would be simpler and could be quantified if not for a bug in PCRE 8.13 to 8.33
+ $re = '(?:(*FAIL))';
+ } elseif ( $re === '[^]' ) {
+ $re = '.'; // 's' modifier is always used, so this works
+ }
+
+ return [ $i, $re ];
+ }
+
+ private function addCapturesFromMatch( $arr, $s, $m, $capt, $m0_if_no_captures ) {
+ if ( count( $capt ) ) {
+ foreach ( $capt as $n => $pos ) {
+ if ( $pos ) {
+ $o = mb_strlen( substr( $s, 0, $m["m$n"][1] ), 'UTF-8' ) + 1;
+ $arr[] = $o;
+ } else {
+ $arr[] = $m["m$n"][0];
+ }
+ }
+ } elseif ( $m0_if_no_captures ) {
+ $arr[] = $m[0][0];
+ }
+ return $arr;
+ }
+
+ public function ustringFind( $s, $pattern, $init = 1, $plain = false ) {
+ $this->checkString( 'find', $s );
+ $this->checkTypeOptional( 'find', 3, $init, 'number', 1 );
+ $this->checkTypeOptional( 'find', 4, $plain, 'boolean', false );
+
+ $len = mb_strlen( $s, 'UTF-8' );
+ if ( $init < 0 ) {
+ $init = $len + $init + 1;
+ } elseif ( $init > $len + 1 ) {
+ $init = $len + 1;
+ }
+
+ if ( $init > 1 ) {
+ $offset = strlen( mb_substr( $s, 0, $init - 1, 'UTF-8' ) );
+ } else {
+ $init = 1;
+ $offset = 0;
+ }
+
+ if ( $plain ) {
+ $this->checkPattern( 'find', $pattern );
+ if ( $pattern !== '' ) {
+ $ret = mb_strpos( $s, $pattern, $init - 1, 'UTF-8' );
+ } else {
+ $ret = $init - 1;
+ }
+ if ( $ret === false ) {
+ return [ null ];
+ } else {
+ return [ $ret + 1, $ret + mb_strlen( $pattern ) ];
+ }
+ } else {
+ list( $re, $capt ) = $this->patternToRegex( $pattern, '\G', 'find' );
+ if ( !preg_match( $re, $s, $m, PREG_OFFSET_CAPTURE, $offset ) ) {
+ return [ null ];
+ }
+ $o = mb_strlen( substr( $s, 0, $m[0][1] ), 'UTF-8' );
+ $ret = [ $o + 1, $o + mb_strlen( $m[0][0], 'UTF-8' ) ];
+ return $this->addCapturesFromMatch( $ret, $s, $m, $capt, false );
+ }
+ }
+
+ public function ustringMatch( $s, $pattern, $init = 1 ) {
+ $this->checkString( 'match', $s );
+ $this->checkTypeOptional( 'match', 3, $init, 'number', 1 );
+
+ $len = mb_strlen( $s, 'UTF-8' );
+ if ( $init < 0 ) {
+ $init = $len + $init + 1;
+ } elseif ( $init > $len + 1 ) {
+ $init = $len + 1;
+ }
+ if ( $init > 1 ) {
+ $offset = strlen( mb_substr( $s, 0, $init - 1, 'UTF-8' ) );
+ } else {
+ $offset = 0;
+ }
+
+ list( $re, $capt ) = $this->patternToRegex( $pattern, '\G', 'match' );
+ if ( !preg_match( $re, $s, $m, PREG_OFFSET_CAPTURE, $offset ) ) {
+ return [ null ];
+ }
+ return $this->addCapturesFromMatch( [], $s, $m, $capt, true );
+ }
+
+ public function ustringGmatchInit( $s, $pattern ) {
+ $this->checkString( 'gmatch', $s );
+
+ list( $re, $capt ) = $this->patternToRegex( $pattern, false, 'gmatch' );
+ return [ $re, $capt ];
+ }
+
+ public function ustringGmatchCallback( $s, $re, $capt, $pos ) {
+ if ( !preg_match( $re, $s, $m, PREG_OFFSET_CAPTURE, $pos ) ) {
+ return [ $pos, [] ];
+ }
+ $pos = $m[0][1] + strlen( $m[0][0] );
+ return [ $pos, $this->addCapturesFromMatch( [ null ], $s, $m, $capt, true ) ];
+ }
+
+ public function ustringGsub( $s, $pattern, $repl, $n = null ) {
+ $this->checkString( 'gsub', $s );
+ $this->checkTypeOptional( 'gsub', 4, $n, 'number', null );
+
+ if ( $n === null ) {
+ $n = -1;
+ } elseif ( $n < 1 ) {
+ return [ $s, 0 ];
+ }
+
+ list( $re, $capt, $anypos ) = $this->patternToRegex( $pattern, '^', 'gsub' );
+ $captures = [];
+
+ if ( $this->phpBug53823 ) {
+ // PHP bug 53823 means that a zero-length match before a UTF-8
+ // character will match again before every byte of that character.
+ // The workaround is to capture the first "character" of/after the
+ // match and verify that its first byte is legal to start a UTF-8
+ // character.
+ $re = '/(?=(?<phpBug53823>.|$))' . substr( $re, 1 );
+ }
+
+ if ( $anypos ) {
+ // preg_replace_callback doesn't take a "flags" argument, so we
+ // can't pass PREG_OFFSET_CAPTURE to it, which is needed to handle
+ // position captures. So instead we have to do a preg_match_all and
+ // handle the captures ourself.
+ $ct = preg_match_all( $re, $s, $mm, PREG_OFFSET_CAPTURE | PREG_SET_ORDER );
+ for ( $i = 0; $i < $ct; $i++ ) {
+ $m = $mm[$i];
+ if ( $this->phpBug53823 ) {
+ $c = ord( $m['phpBug53823'][0] );
+ if ( $c >= 0x80 && $c <= 0xbf ) {
+ continue;
+ }
+ }
+ $c = [ $m[0][0] ];
+ foreach ( $this->addCapturesFromMatch( [], $s, $m, $capt, false ) as $k => $v ) {
+ $k++;
+ $c["m$k"] = $v;
+ }
+ $captures[] = $c;
+ if ( $n >= 0 && count( $captures ) >= $n ) {
+ break;
+ }
+ }
+ }
+
+ switch ( $this->getLuaType( $repl ) ) {
+ case 'string':
+ case 'number':
+ $cb = function ( $m ) use ( $repl, $anypos, &$captures ) {
+ if ( $anypos ) {
+ $m = array_shift( $captures );
+ }
+ return preg_replace_callback( '/%([%0-9])/', function ( $m2 ) use ( $m ) {
+ $x = $m2[1];
+ if ( $x === '%' ) {
+ return '%';
+ } elseif ( $x === '0' ) {
+ return $m[0];
+ } elseif ( isset( $m["m$x"] ) ) {
+ return $m["m$x"];
+ } else {
+ throw new Scribunto_LuaError( "invalid capture index %$x in replacement string" );
+ }
+ }, $repl );
+ };
+ break;
+
+ case 'table':
+ $cb = function ( $m ) use ( $repl, $anypos, &$captures ) {
+ if ( $anypos ) {
+ $m = array_shift( $captures );
+ }
+ $x = isset( $m['m1'] ) ? $m['m1'] : $m[0];
+ return isset( $repl[$x] ) ? $repl[$x] : $m[0];
+ };
+ break;
+
+ case 'function':
+ $interpreter = $this->getInterpreter();
+ $cb = function ( $m ) use ( $interpreter, $capt, $repl, $anypos, &$captures ) {
+ if ( $anypos ) {
+ $m = array_shift( $captures );
+ }
+ $args = [ $repl ];
+ if ( count( $capt ) ) {
+ foreach ( $capt as $i => $pos ) {
+ $args[] = $m["m$i"];
+ }
+ } else {
+ $args[] = $m[0];
+ }
+ $ret = call_user_func_array( [ $interpreter, 'callFunction' ], $args );
+ if ( count( $ret ) === 0 || $ret[0] === null ) {
+ return $m[0];
+ }
+ return $ret[0];
+ };
+ break;
+
+ default:
+ $this->checkType( 'gsub', 3, $repl, 'function or table or string' );
+ }
+
+ $skippedMatches = 0;
+ if ( $this->phpBug53823 ) {
+ // Since we're having bogus matches, we need to keep track of the
+ // necessary adjustment and stop manually once we hit the limit.
+ $maxMatches = $n < 0 ? INF : $n;
+ $n = -1;
+ $realCallback = $cb;
+ $cb = function ( $m ) use ( $realCallback, &$skippedMatches, &$maxMatches ) {
+ $c = ord( $m['phpBug53823'] );
+ if ( $c >= 0x80 && $c <= 0xbf || $maxMatches <= 0 ) {
+ $skippedMatches++;
+ return $m[0];
+ } else {
+ $maxMatches--;
+ return $realCallback( $m );
+ }
+ };
+ }
+
+ $count = 0;
+ $s2 = preg_replace_callback( $re, $cb, $s, $n, $count );
+ if ( $s2 === null ) {
+ self::handlePCREError( preg_last_error(), $pattern );
+ }
+ return [ $s2, $count - $skippedMatches ];
+ }
+
+ /**
+ * Handle a PCRE error
+ * @param int $error From preg_last_error()
+ * @param string $pattern Pattern being matched
+ * @throws Scribunto_LuaError
+ */
+ private function handlePCREError( $error, $pattern ) {
+ $PREG_JIT_STACKLIMIT_ERROR = defined( 'PREG_JIT_STACKLIMIT_ERROR' )
+ ? PREG_JIT_STACKLIMIT_ERROR
+ : 'PREG_JIT_STACKLIMIT_ERROR';
+
+ $error = preg_last_error();
+ switch ( $error ) {
+ case PREG_NO_ERROR:
+ // Huh?
+ break;
+ case PREG_INTERNAL_ERROR:
+ throw new Scribunto_LuaError( "PCRE internal error" );
+ case PREG_BACKTRACK_LIMIT_ERROR:
+ throw new Scribunto_LuaError(
+ "PCRE backtrack limit reached while matching pattern '$pattern'"
+ );
+ case PREG_RECURSION_LIMIT_ERROR:
+ throw new Scribunto_LuaError(
+ "PCRE recursion limit reached while matching pattern '$pattern'"
+ );
+ case PREG_BAD_UTF8_ERROR:
+ // Should have alreay been caught, but just in case
+ throw new Scribunto_LuaError( "PCRE bad UTF-8 error" );
+ case PREG_BAD_UTF8_OFFSET_ERROR:
+ // Shouldn't happen, but just in case
+ throw new Scribunto_LuaError( "PCRE bad UTF-8 offset error" );
+ case $PREG_JIT_STACKLIMIT_ERROR:
+ throw new Scribunto_LuaError(
+ "PCRE JIT stack limit reached while matching pattern '$pattern'"
+ );
+ default:
+ throw new Scribunto_LuaError(
+ "PCRE error code $error while matching pattern '$pattern'"
+ );
+ }
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/bit32.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/bit32.lua
new file mode 100644
index 00000000..3063bfde
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/bit32.lua
@@ -0,0 +1,209 @@
+---
+-- An implementation of the lua 5.2 bit32 library, in pure Lua
+
+-- Note that in Lua, "x % n" is defined such that will always return a number
+-- between 0 and n-1 for positive n. We take advantage of that a lot here.
+
+local bit32 = {}
+
+local function checkint( name, argidx, x, level )
+ local n = tonumber( x )
+ if not n then
+ error( string.format(
+ "bad argument #%d to '%s' (number expected, got %s)",
+ argidx, name, type( x )
+ ), level + 1 )
+ end
+ return math.floor( n )
+end
+
+local function checkint32( name, argidx, x, level )
+ local n = tonumber( x )
+ if not n then
+ error( string.format(
+ "bad argument #%d to '%s' (number expected, got %s)",
+ argidx, name, type( x )
+ ), level + 1 )
+ end
+ return math.floor( n ) % 0x100000000
+end
+
+
+function bit32.bnot( x )
+ x = checkint32( 'bnot', 1, x, 2 )
+
+ -- In two's complement, -x = not(x) + 1
+ -- So not(x) = -x - 1
+ return ( -x - 1 ) % 0x100000000
+end
+
+
+---
+-- Logic tables for and/or/xor. We do pairs of bits here as a tradeoff between
+-- table space and speed. If you change the number of bits, also change the
+-- constants 2 and 4 in comb() below, and the initial value in bit32.band and
+-- bit32.btest
+local logic_and = {
+ [0] = { [0] = 0, 0, 0, 0},
+ [1] = { [0] = 0, 1, 0, 1},
+ [2] = { [0] = 0, 0, 2, 2},
+ [3] = { [0] = 0, 1, 2, 3},
+}
+local logic_or = {
+ [0] = { [0] = 0, 1, 2, 3},
+ [1] = { [0] = 1, 1, 3, 3},
+ [2] = { [0] = 2, 3, 2, 3},
+ [3] = { [0] = 3, 3, 3, 3},
+}
+local logic_xor = {
+ [0] = { [0] = 0, 1, 2, 3},
+ [1] = { [0] = 1, 0, 3, 2},
+ [2] = { [0] = 2, 3, 0, 1},
+ [3] = { [0] = 3, 2, 1, 0},
+}
+
+---
+-- @param name string Function name
+-- @param args table Function args
+-- @param nargs number Arg count
+-- @param s number Start value, 0-3
+-- @param t table Logic table
+-- @return number result
+local function comb( name, args, nargs, s, t )
+ for i = 1, nargs do
+ args[i] = checkint32( name, i, args[i], 3 )
+ end
+
+ local pow = 1
+ local ret = 0
+ for b = 0, 31, 2 do
+ local c = s
+ for i = 1, nargs do
+ c = t[c][args[i] % 4]
+ args[i] = math.floor( args[i] / 4 )
+ end
+ ret = ret + c * pow
+ pow = pow * 4
+ end
+ return ret
+end
+
+function bit32.band( ... )
+ return comb( 'band', { ... }, select( '#', ... ), 3, logic_and )
+end
+
+function bit32.bor( ... )
+ return comb( 'bor', { ... }, select( '#', ... ), 0, logic_or )
+end
+
+function bit32.bxor( ... )
+ return comb( 'bxor', { ... }, select( '#', ... ), 0, logic_xor )
+end
+
+function bit32.btest( ... )
+ return comb( 'btest', { ... }, select( '#', ... ), 3, logic_and ) ~= 0
+end
+
+
+function bit32.extract( n, field, width )
+ n = checkint32( 'extract', 1, n, 2 )
+ field = checkint( 'extract', 2, field, 2 )
+ width = checkint( 'extract', 3, width or 1, 2 )
+ if field < 0 then
+ error( "bad argument #2 to 'extract' (field cannot be negative)", 2 )
+ end
+ if width <= 0 then
+ error( "bad argument #3 to 'extract' (width must be positive)", 2 )
+ end
+ if field + width > 32 then
+ error( 'trying to access non-existent bits', 2 )
+ end
+
+ return math.floor( n / 2^field ) % 2^width
+end
+
+function bit32.replace( n, v, field, width )
+ n = checkint32( 'replace', 1, n, 2 )
+ v = checkint32( 'replace', 2, v, 2 )
+ field = checkint( 'replace', 3, field, 2 )
+ width = checkint( 'replace', 4, width or 1, 2 )
+ if field < 0 then
+ error( "bad argument #3 to 'replace' (field cannot be negative)", 2 )
+ end
+ if width <= 0 then
+ error( "bad argument #4 to 'replace' (width must be positive)", 2 )
+ end
+ if field + width > 32 then
+ error( 'trying to access non-existent bits', 2 )
+ end
+
+ local f = 2^field
+ local w = 2^width
+ local fw = f * w
+ return ( n % f ) + ( v % w ) * f + math.floor( n / fw ) * fw
+end
+
+
+-- For the shifting functions, anything over 32 is the same as 32
+-- and limiting to 32 prevents overflow/underflow
+local function checkdisp( name, x )
+ x = checkint( name, 2, x, 3 )
+ return math.min( math.max( -32, x ), 32 )
+end
+
+function bit32.lshift( x, disp )
+ x = checkint32( 'lshift', 1, x, 2 )
+ disp = checkdisp( 'lshift', disp )
+
+ return math.floor( x * 2^disp ) % 0x100000000
+end
+
+function bit32.rshift( x, disp )
+ x = checkint32( 'rshift', 1, x, 2 )
+ disp = checkdisp( 'rshift', disp )
+
+ return math.floor( x / 2^disp ) % 0x100000000
+end
+
+function bit32.arshift( x, disp )
+ x = checkint32( 'arshift', 1, x, 2 )
+ disp = checkdisp( 'arshift', disp )
+
+ if disp <= 0 then
+ -- Non-positive displacement == left shift
+ -- (since exponent is non-negative, the multipication can never result
+ -- in a fractional part)
+ return ( x * 2^-disp ) % 0x100000000
+ elseif x < 0x80000000 then
+ -- High bit is 0 == right shift
+ -- (since exponent is positive, the division will never increase x)
+ return math.floor( x / 2^disp )
+ elseif disp > 31 then
+ -- Shifting off all bits
+ return 0xffffffff
+ else
+ -- 0x100000000 - 2 ^ ( 32 - disp ) creates a number with the high disp
+ -- bits set. So shift right then add that number.
+ return math.floor( x / 2^disp ) + ( 0x100000000 - 2 ^ ( 32 - disp ) )
+ end
+end
+
+-- For the rotation functions, disp works mod 32.
+-- Note that lrotate( x, disp ) == rrotate( x, -disp ).
+function bit32.lrotate( x, disp )
+ x = checkint32( 'lrotate', 1, x, 2 )
+ disp = checkint( 'lrotate', 2, disp, 2 ) % 32
+
+ local x = x * 2^disp
+ return ( x % 0x100000000 ) + math.floor( x / 0x100000000 )
+end
+
+function bit32.rrotate( x, disp )
+ x = checkint32( 'rrotate', 1, x, 2 )
+ disp = -checkint( 'rrotate', 2, disp, 2 ) % 32
+
+ local x = x * 2^disp
+ return ( x % 0x100000000 ) + math.floor( x / 0x100000000 )
+end
+
+return bit32
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/libraryUtil.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/libraryUtil.lua
new file mode 100644
index 00000000..f14a7950
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/libraryUtil.lua
@@ -0,0 +1,71 @@
+local libraryUtil = {}
+
+function libraryUtil.checkType( name, argIdx, arg, expectType, nilOk )
+ if arg == nil and nilOk then
+ return
+ end
+ if type( arg ) ~= expectType then
+ local msg = string.format( "bad argument #%d to '%s' (%s expected, got %s)",
+ argIdx, name, expectType, type( arg )
+ )
+ error( msg, 3 )
+ end
+end
+
+function libraryUtil.checkTypeMulti( name, argIdx, arg, expectTypes )
+ local argType = type( arg )
+ for _, expectType in ipairs( expectTypes ) do
+ if argType == expectType then
+ return
+ end
+ end
+ local n = #expectTypes
+ local typeList
+ if n > 1 then
+ typeList = table.concat( expectTypes, ', ', 1, n - 1 ) .. ' or ' .. expectTypes[n]
+ else
+ typeList = expectTypes[1]
+ end
+ local msg = string.format( "bad argument #%d to '%s' (%s expected, got %s)",
+ argIdx,
+ name,
+ typeList,
+ type( arg )
+ )
+ error( msg, 3 )
+end
+
+function libraryUtil.checkTypeForIndex( index, value, expectType )
+ if type( value ) ~= expectType then
+ local msg = string.format( "value for index '%s' must be %s, %s given",
+ index, expectType, type( value )
+ )
+ error( msg, 3 )
+ end
+end
+
+function libraryUtil.checkTypeForNamedArg( name, argName, arg, expectType, nilOk )
+ if arg == nil and nilOk then
+ return
+ end
+ if type( arg ) ~= expectType then
+ local msg = string.format( "bad named argument %s to '%s' (%s expected, got %s)",
+ argName, name, expectType, type( arg )
+ )
+ error( msg, 3 )
+ end
+end
+
+function libraryUtil.makeCheckSelfFunction( libraryName, varName, selfObj, selfObjDesc )
+ return function ( self, method )
+ if self ~= selfObj then
+ error( string.format(
+ "%s: invalid %s. Did you call %s with a dot instead of a colon, i.e. " ..
+ "%s.%s() instead of %s:%s()?",
+ libraryName, selfObjDesc, method, varName, method, varName, method
+ ), 3 )
+ end
+ end
+end
+
+return libraryUtil
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/bit.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/bit.lua
new file mode 100644
index 00000000..6bb3f487
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/bit.lua
@@ -0,0 +1,264 @@
+--[[---------------
+LuaBit v0.4
+-------------------
+a bitwise operation lib for lua.
+
+http://luaforge.net/projects/bit/
+
+How to use:
+-------------------
+ bit.bnot(n) -- bitwise not (~n)
+ bit.band(m, n) -- bitwise and (m & n)
+ bit.bor(m, n) -- bitwise or (m | n)
+ bit.bxor(m, n) -- bitwise xor (m ^ n)
+ bit.brshift(n, bits) -- right shift (n >> bits)
+ bit.blshift(n, bits) -- left shift (n << bits)
+ bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
+
+Please note that bit.brshift and bit.blshift only support number within
+32 bits.
+
+2 utility functions are provided too:
+ bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
+ -- high bits first
+ bit.tonumb(bit_tbl) -- convert a bit table into a number
+-------------------
+
+Under the MIT license.
+
+copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
+
+2013-02-20: Brad Jorsch: Fix to not try messing with globals, doesn't work in Scribunto
+--]]---------------
+
+do
+
+------------------------
+-- bit lib implementions
+
+local function check_int(n)
+ -- checking not float
+ if(n - math.floor(n) > 0) then
+ error("trying to use bitwise operation on non-integer!")
+ end
+end
+
+local function to_bits(n)
+ check_int(n)
+ if(n < 0) then
+ -- negative
+ return to_bits(bit.bnot(math.abs(n)) + 1)
+ end
+ -- to bits table
+ local tbl = {}
+ local cnt = 1
+ while (n > 0) do
+ local last = math.mod(n,2)
+ if(last == 1) then
+ tbl[cnt] = 1
+ else
+ tbl[cnt] = 0
+ end
+ n = (n-last)/2
+ cnt = cnt + 1
+ end
+
+ return tbl
+end
+
+local function tbl_to_number(tbl)
+ local n = table.getn(tbl)
+
+ local rslt = 0
+ local power = 1
+ for i = 1, n do
+ rslt = rslt + tbl[i]*power
+ power = power*2
+ end
+
+ return rslt
+end
+
+local function expand(tbl_m, tbl_n)
+ local big = {}
+ local small = {}
+ if(table.getn(tbl_m) > table.getn(tbl_n)) then
+ big = tbl_m
+ small = tbl_n
+ else
+ big = tbl_n
+ small = tbl_m
+ end
+ -- expand small
+ for i = table.getn(small) + 1, table.getn(big) do
+ small[i] = 0
+ end
+
+end
+
+local function bit_or(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 and tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl_to_number(tbl)
+end
+
+local function bit_and(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
+ for i = 1, rslt do
+ if(tbl_m[i]== 0 or tbl_n[i] == 0) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+
+ return tbl_to_number(tbl)
+end
+
+local function bit_not(n)
+
+ local tbl = to_bits(n)
+ local size = math.max(table.getn(tbl), 32)
+ for i = 1, size do
+ if(tbl[i] == 1) then
+ tbl[i] = 0
+ else
+ tbl[i] = 1
+ end
+ end
+ return tbl_to_number(tbl)
+end
+
+local function bit_xor(m, n)
+ local tbl_m = to_bits(m)
+ local tbl_n = to_bits(n)
+ expand(tbl_m, tbl_n)
+
+ local tbl = {}
+ local rslt = math.max(table.getn(tbl_m), table.getn(tbl_n))
+ for i = 1, rslt do
+ if(tbl_m[i] ~= tbl_n[i]) then
+ tbl[i] = 1
+ else
+ tbl[i] = 0
+ end
+ end
+
+ --table.foreach(tbl, print)
+
+ return tbl_to_number(tbl)
+end
+
+local function bit_rshift(n, bits)
+ check_int(n)
+
+ local high_bit = 0
+ if(n < 0) then
+ -- negative
+ n = bit_not(math.abs(n)) + 1
+ high_bit = 2147483648 -- 0x80000000
+ end
+
+ for i=1, bits do
+ n = n/2
+ n = bit_or(math.floor(n), high_bit)
+ end
+ return math.floor(n)
+end
+
+-- logic rightshift assures zero filling shift
+local function bit_logic_rshift(n, bits)
+ check_int(n)
+ if(n < 0) then
+ -- negative
+ n = bit_not(math.abs(n)) + 1
+ end
+ for i=1, bits do
+ n = n/2
+ end
+ return math.floor(n)
+end
+
+local function bit_lshift(n, bits)
+ check_int(n)
+
+ if(n < 0) then
+ -- negative
+ n = bit_not(math.abs(n)) + 1
+ end
+
+ for i=1, bits do
+ n = n*2
+ end
+ return bit_and(n, 4294967295) -- 0xFFFFFFFF
+end
+
+local function bit_xor2(m, n)
+ local rhs = bit_or(bit_not(m), bit_not(n))
+ local lhs = bit_or(m, n)
+ local rslt = bit_and(lhs, rhs)
+ return rslt
+end
+
+--------------------
+-- bit lib interface
+
+local bit = {
+ -- bit operations
+ bnot = bit_not,
+ band = bit_and,
+ bor = bit_or,
+ bxor = bit_xor,
+ brshift = bit_rshift,
+ blshift = bit_lshift,
+ bxor2 = bit_xor2,
+ blogic_rshift = bit_logic_rshift,
+
+ -- utility func
+ tobits = to_bits,
+ tonumb = tbl_to_number,
+}
+
+return bit
+
+end
+
+--[[
+for i = 1, 100 do
+ for j = 1, 100 do
+ if(bit.bxor(i, j) ~= bit.bxor2(i, j)) then
+ error("bit.xor failed.")
+ end
+ end
+end
+--]]
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/hex.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/hex.lua
new file mode 100644
index 00000000..ee6a69e3
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/hex.lua
@@ -0,0 +1,99 @@
+--[[---------------
+Hex v0.4
+-------------------
+Hex conversion lib for lua.
+
+How to use:
+ hex.to_hex(n) -- convert a number to a hex string
+ hex.to_dec(hex) -- convert a hex string(prefix with '0x' or '0X') to number
+
+Part of LuaBit(http://luaforge.net/projects/bit/).
+
+Under the MIT license.
+
+copyright(c) 2006~2007 hanzhao (abrash_han@hotmail.com)
+
+2013-02-20: Brad Jorsch: Fix to not try messing with globals, doesn't work in Scribunto
+--]]---------------
+
+local bit = require 'bit'
+
+do
+
+local function to_hex(n)
+ if(type(n) ~= "number") then
+ error("non-number type passed in.")
+ end
+
+ -- checking not float
+ if(n - math.floor(n) > 0) then
+ error("trying to apply bitwise operation on non-integer!")
+ end
+
+ if(n < 0) then
+ -- negative
+ n = bit.tobits(bit.bnot(math.abs(n)) + 1)
+ n = bit.tonumb(n)
+ end
+
+ hex_tbl = {'A', 'B', 'C', 'D', 'E', 'F'}
+ hex_str = ""
+
+ while(n ~= 0) do
+ last = math.mod(n, 16)
+ if(last < 10) then
+ hex_str = tostring(last) .. hex_str
+ else
+ hex_str = hex_tbl[last-10+1] .. hex_str
+ end
+ n = math.floor(n/16)
+ end
+ if(hex_str == "") then
+ hex_str = "0"
+ end
+ return "0x" .. hex_str
+end
+
+local function to_dec(hex)
+ if(type(hex) ~= "string") then
+ error("non-string type passed in.")
+ end
+
+ head = string.sub(hex, 1, 2)
+
+ if( head ~= "0x" and head ~= "0X") then
+ error("wrong hex format, should lead by 0x or 0X.")
+ end
+
+ v = tonumber(string.sub(hex, 3), 16)
+
+ return v;
+end
+
+--------------------
+-- hex lib interface
+local hex = {
+ to_dec = to_dec,
+ to_hex = to_hex,
+}
+
+return hex
+
+end
+
+--[[
+-- test
+d = 4341688
+h = to_hex(d)
+print(h)
+print(to_dec(h))
+
+
+for i = 1, 100000 do
+ h = hex.to_hex(i)
+ d = hex.to_dec(h)
+ if(d ~= i) then
+ error("failed " .. i .. ", " .. h)
+ end
+end
+--]]
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/readme.txt b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/readme.txt
new file mode 100644
index 00000000..db831723
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/luabit/readme.txt
@@ -0,0 +1,143 @@
+LuaBit
+------
+LuaBit is a bitwise operation lib completely written in Lua. It's
+written in the belief that Lua is self-contained.
+
+The supported operations are: not, and, or, xor, right shift, logic
+right shift and left shift.
+
+Several utilities are designed to leverage the power of bit operation:
+ 1. hex: a dec <-> hex number converter
+ 2. utf8: convert utf8 string to ucs2
+ 3. noki: convert nokia pc suite backuped SMS file to .txt
+
+Under the MIT license.
+
+Visit http://luaforge.net/projects/bit/ to get latest version.
+
+Status
+------
+Now LuaBit is in v0.4.
+Release date: Mar 18, 2007
+
+Content
+-------
+3 files are there for LuaBit:
+ 1) bit.lua
+ is the bitwise operation lib, all operations are implemented here.
+
+ 2) hex.lua
+ is a helper lib for ease of using hex numbers with bitwise
+ operation.
+
+ 3) noki.lua
+ a utility(based on bit and hex) to convert Nokia PC Suite backuped
+ SMS to a unicode .txt file, which is more accessible than the
+ original .nfb or .nfc file.
+
+ 4) utf8.lua
+ convert utf8 string to ucs2 string
+
+How to use
+----------
+Bit
+---
+Just require 'bit' in your project and the bit lib will be
+available:
+ bit.bnot(n) -- bitwise not (~n)
+ bit.band(m, n) -- bitwise and (m & n)
+ bit.bor(m, n) -- bitwise or (m | n)
+ bit.bxor(m, n) -- bitwise xor (m ^ n)
+ bit.brshift(n, bits) -- right shift (n >> bits)
+ bit.blshift(n, bits) -- left shift (n << bits)
+ bit.blogic_rshift(n, bits) -- logic right shift(zero fill >>>)
+
+Please note that bit.brshift and bit.blshift only support number within
+32 bits.
+
+2 utility functions are provided too:
+ bit.tobits(n) -- convert n into a bit table(which is a 1/0 sequence)
+ -- high bits first
+ bit.tonumb(bit_tbl) -- convert a bit table into a number
+
+Hex
+---
+For ease of using hex numbers, a utility hex lib is also included in
+LuaBit. You can require 'hex' to use them:
+ hex.to_hex(n) -- convert a number to a hex string
+ hex.to_dec(hex) -- convert a hex string(prefix with '0x' or '0X') to number
+
+With hex, you can write code like:
+ bit.band(258, hex.to_dec('0xFF'))
+to get the lower 8 bits of 258, that's 2.
+
+Noki
+----
+require 'noki', to save your sms to .txt file:
+ noki.save_sms('nokia.nfb', 'sms.txt')
+and you can view the output sms.txt in notepad or other editor which
+support unicode.
+
+Utf8
+----
+require 'utf8', to convert a utf8 string:
+ ucs2_string = utf8.utf_to_uni(utf8_string)
+
+History
+-------
+v0.4
+* utf8 to ucs2 converter(utf8.lua).
+* clean up for compatible with Lua5.1 and 5.0.
+* add 'How to use' section for bit.lua and hex.lua.
+
+v0.3
+* noki added as an application of bit.
+* typo correction.
+
+v0.2
+* add logic right shift(>>>) support: bit.blogic_rshift.
+* add 2 utility functions: bit.tobits and bit.tonumb.
+* update hex.to_hex(in hex.lua) to support negative number.
+
+v0.1
+LuaBit is written when I do my own game project(Fio at http://fio.edithis.info).
+When loading resources, I have to do some bit operation. And I do not
+like the embedded way of bit operation. So I decide to implement those
+ops in lua. And that's LuaBit. It's not as fast as the embedded one, but
+it works. And Lua is self-contained :-)
+
+To-Do List
+---------
+v0.1
+It'll be useful if LuaBit support those bitwise op like:
+ bit.band(258, '0xFF')
+ease to type and use. This will be supported in next release.
+
+v0.2
+I decide to delay this feature to later version for it'll mess up the
+interface of LuaBit.
+
+v0.3
+May more utility functions add to Noki - phonebook might be a nice candidate.
+
+v0.4
+There's no UCS2 -> UTF8 convertion now, this feature may add in next release
+or when the project need.
+
+Noki'll be be exluded from LuaBit in next release; I decide to let Noki grow
+into a powerful tool to support more Nokia PC Suite backup format(.nfb,
+.nfc and .nbu).
+
+Trial Noki demo at http://nokisms.googlepages.com/(in Chinese)
+
+Known issues
+------------
+LuaBit doesn't play very well with negative number. The return value of the
+bitwise operations might change to positive when applied on negative numbers
+though the bit sequence is correct. So if you want do some arithmetic with
+the result of bit operation, be careful.
+
+Feedback
+--------
+Please send your comments, bugs, patches or change request to
+hanzhao(abrash_han@hotmail.com).
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.hash.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.hash.lua
new file mode 100644
index 00000000..95026e33
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.hash.lua
@@ -0,0 +1,30 @@
+local hash = {}
+local php
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+
+function hash.listAlgorithms()
+ return php.listAlgorithms()
+end
+
+function hash.hashValue( algo, value )
+ checkType( 'hashValue', 1, algo, 'string' )
+ checkType( 'hashValue', 2, value, 'string' )
+
+ return php.hashValue( algo, value )
+end
+
+function hash.setupInterface()
+ -- Boilerplate
+ php = mw_interface
+ mw_interface = nil
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.hash = hash
+
+ package.loaded['mw.hash'] = hash
+end
+
+return hash
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.html.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.html.lua
new file mode 100644
index 00000000..9baf50c1
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.html.lua
@@ -0,0 +1,433 @@
+--[[
+ A module for building complex HTML from Lua using a
+ fluent interface.
+
+ Originally written on the English Wikipedia by
+ Toohool and Mr. Stradivarius.
+
+ Code released under the GPL v2+ as per:
+ https://en.wikipedia.org/w/index.php?diff=next&oldid=581399786
+ https://en.wikipedia.org/w/index.php?diff=next&oldid=581403025
+
+ @license GNU GPL v2+
+ @author Marius Hoch < hoo@online.de >
+]]
+
+local HtmlBuilder = {}
+local options
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+local checkTypeMulti = util.checkTypeMulti
+
+local metatable = {}
+local methodtable = {}
+
+local selfClosingTags = {
+ area = true,
+ base = true,
+ br = true,
+ col = true,
+ command = true,
+ embed = true,
+ hr = true,
+ img = true,
+ input = true,
+ keygen = true,
+ link = true,
+ meta = true,
+ param = true,
+ source = true,
+ track = true,
+ wbr = true,
+}
+
+local htmlencodeMap = {
+ ['>'] = '&gt;',
+ ['<'] = '&lt;',
+ ['&'] = '&amp;',
+ ['"'] = '&quot;',
+}
+
+metatable.__index = methodtable
+
+metatable.__tostring = function( t )
+ local ret = {}
+ t:_build( ret )
+ return table.concat( ret )
+end
+
+-- Get an attribute table (name, value) and its index
+--
+-- @param name
+local function getAttr( t, name )
+ for i, attr in ipairs( t.attributes ) do
+ if attr.name == name then
+ return attr, i
+ end
+ end
+end
+
+-- Is this a valid attribute name?
+--
+-- @param s
+local function isValidAttributeName( s )
+ -- Good estimate: http://www.w3.org/TR/2000/REC-xml-20001006#NT-Name
+ return s:match( '^[a-zA-Z_:][a-zA-Z0-9_.:-]*$' )
+end
+
+-- Is this a valid tag name?
+--
+-- @param s
+local function isValidTag( s )
+ return s:match( '^[a-zA-Z0-9]+$' )
+end
+
+-- Escape a value, for use in HTML
+--
+-- @param s
+local function htmlEncode( s )
+ -- The parentheses ensure that there is only one return value
+ local tmp = string.gsub( s, '[<>&"]', htmlencodeMap );
+ -- Don't encode strip markers here (T110143)
+ tmp = string.gsub( tmp, options.encodedUniqPrefixPat, options.uniqPrefixRepl )
+ tmp = string.gsub( tmp, options.encodedUniqSuffixPat, options.uniqSuffixRepl )
+ return tmp
+end
+
+local function cssEncode( s )
+ -- mw.ustring is so slow that it's worth searching the whole string
+ -- for non-ASCII characters to avoid it if possible
+ return ( string.find( s, '[^%z\1-\127]' ) and mw.ustring or string )
+ -- XXX: I'm not sure this character set is complete.
+ -- bug #68011: allow delete character (\127)
+ .gsub( s, '[^\32-\57\60-\127]', function ( m )
+ return string.format( '\\%X ', mw.ustring.codepoint( m ) )
+ end )
+end
+
+-- Create a builder object. This is a separate function so that we can show the
+-- correct error levels in both HtmlBuilder.create and metatable.tag.
+--
+-- @param tagName
+-- @param args
+local function createBuilder( tagName, args )
+ if tagName ~= nil and tagName ~= '' and not isValidTag( tagName ) then
+ error( string.format( "invalid tag name '%s'", tagName ), 3 )
+ end
+
+ args = args or {}
+ local builder = {}
+ setmetatable( builder, metatable )
+ builder.nodes = {}
+ builder.attributes = {}
+ builder.styles = {}
+
+ if tagName ~= '' then
+ builder.tagName = tagName
+ end
+
+ builder.parent = args.parent
+ builder.selfClosing = selfClosingTags[tagName] or args.selfClosing or false
+ return builder
+end
+
+-- Append a builder to the current node. This is separate from methodtable.node
+-- so that we can show the correct error level in both methodtable.node and
+-- methodtable.wikitext.
+--
+-- @param builder
+local function appendBuilder( t, builder )
+ if t.selfClosing then
+ error( "self-closing tags can't have child nodes", 3 )
+ end
+
+ if builder then
+ table.insert( t.nodes, builder )
+ end
+ return t
+end
+
+methodtable._build = function( t, ret )
+ if t.tagName then
+ table.insert( ret, '<' .. t.tagName )
+ for i, attr in ipairs( t.attributes ) do
+ table.insert(
+ ret,
+ -- Note: Attribute names have already been validated
+ ' ' .. attr.name .. '="' .. htmlEncode( attr.val ) .. '"'
+ )
+ end
+ if #t.styles > 0 then
+ table.insert( ret, ' style="' )
+ local css = {}
+ for i, prop in ipairs( t.styles ) do
+ if type( prop ) ~= 'table' then -- added with cssText()
+ table.insert( css, htmlEncode( prop ) )
+ else -- added with css()
+ table.insert(
+ css,
+ htmlEncode( cssEncode( prop.name ) .. ':' .. cssEncode( prop.val ) )
+ )
+ end
+ end
+ table.insert( ret, table.concat( css, ';' ) )
+ table.insert( ret, '"' )
+ end
+ if t.selfClosing then
+ table.insert( ret, ' />' )
+ return
+ end
+ table.insert( ret, '>' )
+ end
+ for i, node in ipairs( t.nodes ) do
+ if node then
+ if type( node ) == 'table' then
+ node:_build( ret )
+ else
+ table.insert( ret, tostring( node ) )
+ end
+ end
+ end
+ if t.tagName then
+ table.insert( ret, '</' .. t.tagName .. '>' )
+ end
+end
+
+-- Append a builder to the current node
+--
+-- @param builder
+methodtable.node = function( t, builder )
+ return appendBuilder( t, builder )
+end
+
+-- Appends some markup to the node. This will be treated as wikitext.
+methodtable.wikitext = function( t, ... )
+ for k,v in ipairs{...} do
+ checkTypeMulti( 'wikitext', k, v, { 'string', 'number' } )
+ appendBuilder( t, v )
+ end
+ return t
+end
+
+-- Appends a newline character to the node.
+methodtable.newline = function( t )
+ return t:wikitext( '\n' )
+end
+
+-- Appends a new child node to the builder, and returns an HtmlBuilder instance
+-- representing that new node.
+--
+-- @param tagName
+-- @param args
+methodtable.tag = function( t, tagName, args )
+ checkType( 'tag', 1, tagName, 'string' )
+ checkType( 'tag', 2, args, 'table', true )
+ args = args or {}
+
+ args.parent = t
+ local builder = createBuilder( tagName, args )
+ t:node( builder )
+ return builder
+end
+
+-- Get the value of an html attribute
+--
+-- @param name
+methodtable.getAttr = function( t, name )
+ checkType( 'getAttr', 1, name, 'string' )
+
+ local attr = getAttr( t, name )
+ return attr and attr.val
+end
+
+-- Set an HTML attribute on the node.
+--
+-- @param name Attribute to set, alternative table of name-value pairs
+-- @param val Value of the attribute. Nil causes the attribute to be unset
+methodtable.attr = function( t, name, val )
+ if type( name ) == 'table' then
+ if val ~= nil then
+ error(
+ "bad argument #2 to 'attr' " ..
+ '(if argument #1 is a table, argument #2 must be left empty)',
+ 2
+ )
+ end
+
+ local callForTable = function()
+ for attrName, attrValue in pairs( name ) do
+ t:attr( attrName, attrValue )
+ end
+ end
+
+ if not pcall( callForTable ) then
+ error(
+ "bad argument #1 to 'attr' " ..
+ '(table keys must be strings, and values must be strings or numbers)',
+ 2
+ )
+ end
+
+ return t
+ end
+
+ checkType( 'attr', 1, name, 'string' )
+ checkTypeMulti( 'attr', 2, val, { 'string', 'number', 'nil' } )
+
+ -- if caller sets the style attribute explicitly, then replace all styles
+ -- previously added with css() and cssText()
+ if name == 'style' then
+ t.styles = { val }
+ return t
+ end
+
+ if not isValidAttributeName( name ) then
+ error( string.format(
+ "bad argument #1 to 'attr' (invalid attribute name '%s')",
+ name
+ ), 2 )
+ end
+
+ local attr, i = getAttr( t, name )
+ if attr then
+ if val ~= nil then
+ attr.val = val
+ else
+ table.remove( t.attributes, i )
+ end
+ elseif val ~= nil then
+ table.insert( t.attributes, { name = name, val = val } )
+ end
+
+ return t
+end
+
+-- Adds a class name to the node's class attribute. Spaces will be
+-- automatically added to delimit each added class name.
+--
+-- @param class
+methodtable.addClass = function( t, class )
+ checkTypeMulti( 'addClass', 1, class, { 'string', 'number', 'nil' } )
+
+ if class ~= nil then
+ local attr = getAttr( t, 'class' )
+ if attr then
+ attr.val = attr.val .. ' ' .. class
+ else
+ t:attr( 'class', class )
+ end
+ end
+ return t
+end
+
+-- Set a CSS property to be added to the node's style attribute.
+--
+-- @param name CSS attribute to set, alternative table of name-value pairs
+-- @param val The value to set. Nil causes it to be unset
+methodtable.css = function( t, name, val )
+ if type( name ) == 'table' then
+ if val ~= nil then
+ error(
+ "bad argument #2 to 'css' " ..
+ '(if argument #1 is a table, argument #2 must be left empty)',
+ 2
+ )
+ end
+
+ local callForTable = function()
+ for attrName, attrValue in pairs( name ) do
+ t:css( attrName, attrValue )
+ end
+ end
+
+ if not pcall( callForTable ) then
+ error(
+ "bad argument #1 to 'css' " ..
+ '(table keys and values must be strings or numbers)',
+ 2
+ )
+ end
+
+ return t
+ end
+
+ checkTypeMulti( 'css', 1, name, { 'string', 'number' } )
+ checkTypeMulti( 'css', 2, val, { 'string', 'number', 'nil' } )
+
+ for i, prop in ipairs( t.styles ) do
+ if prop.name == name then
+ if val ~= nil then
+ prop.val = val
+ else
+ table.remove( t.styles, i )
+ end
+ return t
+ end
+ end
+
+ if val ~= nil then
+ table.insert( t.styles, { name = name, val = val } )
+ end
+
+ return t
+end
+
+-- Add some raw CSS to the node's style attribute. This is typically used
+-- when a template allows some CSS to be passed in as a parameter
+--
+-- @param css
+methodtable.cssText = function( t, css )
+ checkTypeMulti( 'cssText', 1, css, { 'string', 'number', 'nil' } )
+ table.insert( t.styles, css )
+ return t
+end
+
+-- Returns the parent node under which the current node was created. Like
+-- jQuery.end, this is a convenience function to allow the construction of
+-- several child nodes to be chained together into a single statement.
+methodtable.done = function( t )
+ return t.parent or t
+end
+
+-- Like .done(), but traverses all the way to the root node of the tree and
+-- returns it.
+methodtable.allDone = function( t )
+ while t.parent do
+ t = t.parent
+ end
+ return t
+end
+
+-- Create a new instance
+--
+-- @param tagName
+-- @param args
+function HtmlBuilder.create( tagName, args )
+ checkType( 'mw.html.create', 1, tagName, 'string', true )
+ checkType( 'mw.html.create', 2, args, 'table', true )
+ return createBuilder( tagName, args )
+end
+
+function HtmlBuilder.setupInterface( opts )
+ -- Boilerplate
+ HtmlBuilder.setupInterface = nil
+ mw_interface = nil
+ options = opts
+
+ -- Prepare patterns for unencoding strip markers
+ options.encodedUniqPrefixPat = string.gsub( options.uniqPrefix, '[<>&"]', htmlencodeMap );
+ options.encodedUniqPrefixPat = string.gsub( options.encodedUniqPrefixPat, '%p', '%%%0' );
+ options.uniqPrefixRepl = string.gsub( options.uniqPrefix, '%%', '%%%0' );
+ options.encodedUniqSuffixPat = string.gsub( options.uniqSuffix, '[<>&"]', htmlencodeMap );
+ options.encodedUniqSuffixPat = string.gsub( options.encodedUniqSuffixPat, '%p', '%%%0' );
+ options.uniqSuffixRepl = string.gsub( options.uniqSuffix, '%%', '%%%0' );
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.html = HtmlBuilder
+
+ package.loaded['mw.html'] = HtmlBuilder
+end
+
+return HtmlBuilder
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.language.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.language.lua
new file mode 100644
index 00000000..edd7110f
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.language.lua
@@ -0,0 +1,189 @@
+local language = {}
+local php
+local util = require 'libraryUtil'
+
+function language.setupInterface()
+ -- Boilerplate
+ language.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.language = language
+ mw.getContentLanguage = language.getContentLanguage
+ mw.getLanguage = mw.language.new
+
+ local lang = mw.getContentLanguage();
+
+ -- Extend ustring
+ if mw.ustring then
+ mw.ustring.upper = function ( s )
+ return lang:uc( s )
+ end
+ mw.ustring.lower = function ( s )
+ return lang:lc( s )
+ end
+ string.uupper = mw.ustring.upper
+ string.ulower = mw.ustring.lower
+ end
+
+ package.loaded['mw.language'] = language
+end
+
+function language.isSupportedLanguage( code )
+ return php.isSupportedLanguage( code )
+end
+
+function language.isKnownLanguageTag( code )
+ return php.isKnownLanguageTag( code )
+end
+
+function language.isValidCode( code )
+ return php.isValidCode( code )
+end
+
+function language.isValidBuiltInCode( code )
+ return php.isValidBuiltInCode( code )
+end
+
+function language.fetchLanguageName( code, inLanguage )
+ return php.fetchLanguageName( code, inLanguage )
+end
+
+function language.fetchLanguageNames( inLanguage, include )
+ return php.fetchLanguageNames( inLanguage, include )
+end
+
+function language.getFallbacksFor( code )
+ return php.getFallbacksFor( code )
+end
+
+function language.new( code )
+ if code == nil then
+ error( "too few arguments to mw.language.new()", 2 )
+ end
+
+ local lang = { code = code }
+
+ local checkSelf = util.makeCheckSelfFunction( 'mw.language', 'lang', lang, 'language object' )
+
+ local wrappers = {
+ lcfirst = 1,
+ ucfirst = 1,
+ lc = 1,
+ uc = 1,
+ caseFold = 1,
+ formatNum = 1,
+ formatDate = 1,
+ formatDuration = 1,
+ getDurationIntervals = 1,
+ convertPlural = 2,
+ convertGrammar = 2,
+ gender = 2,
+ }
+
+ for name, numArgs in pairs( wrappers ) do
+ lang[name] = function ( self, ... )
+ checkSelf( self, name )
+ if select( '#', ... ) < numArgs then
+ error( "too few arguments to mw.language:" .. name, 2 )
+ end
+ return php[name]( self.code, ... )
+ end
+ end
+
+ -- This one could use caching
+ function lang:isRTL()
+ checkSelf( self, 'isRTL' )
+ local rtl = php.isRTL( self.code )
+ self.isRTL = function ()
+ return rtl
+ end
+ return rtl
+ end
+
+ -- Fix semantics
+ function lang:parseFormattedNumber( ... )
+ checkSelf( self, 'parseFormattedNumber' )
+ if select( '#', ... ) < 1 then
+ error( "too few arguments to mw.language:parseFormattedNumber", 2 )
+ end
+ return tonumber( php.parseFormattedNumber( self.code, ... ) )
+ end
+
+ -- Alias
+ lang.plural = lang.convertPlural
+
+ -- Parser function compat
+ function lang:grammar( case, word )
+ checkSelf( self, name )
+ return self:convertGrammar( word, case )
+ end
+
+ -- Other functions
+ function lang:getCode()
+ checkSelf( self, 'getCode' )
+ return self.code
+ end
+
+ function lang:getDir()
+ checkSelf( self, 'getDir' )
+ return self:isRTL() and 'rtl' or 'ltr'
+ end
+
+ function lang:getDirMark( opposite )
+ checkSelf( self, 'getDirMark' )
+ local b = self:isRTL()
+ if opposite then
+ b = not b
+ end
+ return b and '\226\128\143' or '\226\128\142'
+ end
+
+ function lang:getDirMarkEntity( opposite )
+ checkSelf( self, 'getDirMarkEntity' )
+ local b = self:isRTL()
+ if opposite then
+ b = not b
+ end
+ return b and '&rlm;' or '&lrm;'
+ end
+
+ function lang:getArrow( direction )
+ checkSelf( self, 'getArrow' )
+ direction = direction or 'forwards'
+ util.checkType( 'getArrow', 1, direction, 'string' )
+ if direction == 'forwards' then
+ return self:isRTL() and '←' or '→'
+ elseif direction == 'backwards' then
+ return self:isRTL() and '→' or '←'
+ elseif direction == 'left' then
+ return '←'
+ elseif direction == 'right' then
+ return '→'
+ elseif direction == 'up' then
+ return '↑'
+ elseif direction == 'down' then
+ return '↓'
+ end
+ end
+
+ function lang:getFallbackLanguages()
+ checkSelf( self, 'getFallbackLanguages' )
+ return language.getFallbacksFor( self.code )
+ end
+
+ return lang
+end
+
+local contLangCode
+
+function language.getContentLanguage()
+ if contLangCode == nil then
+ contLangCode = php.getContLangCode()
+ end
+ return language.new( contLangCode )
+end
+
+return language
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.lua
new file mode 100644
index 00000000..31102782
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.lua
@@ -0,0 +1,784 @@
+mw = mw or {}
+
+local packageCache
+local packageModuleFunc
+local php
+local allowEnvFuncs = false
+local logBuffer = ''
+local currentFrame
+local loadedData = {}
+local executeFunctionDepth = 0
+
+--- Put an isolation-friendly package module into the specified environment
+-- table. The package module will have an empty cache, because caching of
+-- module functions from other cloned environments would break module isolation.
+--
+-- @param env The cloned environment
+local function makePackageModule( env )
+ -- Remove loaders from env, we don't want it inheriting our loadPackage.
+ if env.package then
+ env.package.loaders = nil
+ end
+
+ -- Create the package globals in the given environment
+ setfenv( packageModuleFunc, env )()
+
+ -- Make a loader function
+ local function loadPackage( modName )
+ local init
+ if packageCache[modName] == 'missing' then
+ return nil
+ elseif packageCache[modName] == nil then
+ local lib = php.loadPHPLibrary( modName )
+ if lib ~= nil then
+ init = function ()
+ return mw.clone( lib )
+ end
+ else
+ init = php.loadPackage( modName )
+ if init == nil then
+ packageCache[modName] = 'missing'
+ return nil
+ end
+ end
+ packageCache[modName] = init
+ else
+ init = packageCache[modName]
+ end
+
+ setfenv( init, env )
+ return init
+ end
+
+ table.insert( env.package.loaders, loadPackage )
+end
+
+--- Set up the base environment. The PHP host calls this function after any
+-- necessary host-side initialisation has been done.
+function mw.setupInterface( options )
+ -- Don't allow any more calls
+ mw.setupInterface = nil
+
+ -- Don't allow getmetatable() on a non-table, since if you can get the metatable,
+ -- you can set values in it, breaking isolation
+ local old_getmetatable = getmetatable
+ function getmetatable(obj)
+ if type(obj) == 'table' then
+ return old_getmetatable(obj)
+ else
+ return nil
+ end
+ end
+
+ if options.allowEnvFuncs then
+ allowEnvFuncs = true
+ end
+
+ -- Store the interface table
+ --
+ -- mw_interface.loadPackage() returns function values with their environment
+ -- set to the base environment, which would violate module isolation if they
+ -- were run from a cloned environment. We can only allow access to
+ -- mw_interface.loadPackage via our environment-setting wrapper.
+ --
+ php = mw_interface
+ mw_interface = nil
+
+ packageModuleFunc = php.loadPackage( 'package' )
+ makePackageModule( _G )
+ package.loaded.mw = mw
+ packageCache = {}
+end
+
+--- Create a table like the one os.date() returns, but with a metatable that sets TTLs as the values are looked at.
+local function wrapDateTable( now )
+ return setmetatable( {}, {
+ __index = function( t, k )
+ if k == 'sec' then
+ php.setTTL( 1 )
+ elseif k == 'min' then
+ php.setTTL( 60 - now.sec )
+ elseif k == 'hour' then
+ php.setTTL( 3600 - now.min * 60 - now.sec )
+ elseif now[k] ~= nil then
+ php.setTTL( 86400 - now.hour * 3600 - now.min * 60 - now.sec )
+ end
+ t[k] = now[k]
+ return now[k]
+ end
+ } )
+end
+
+--- Wrappers for os.date() and os.time() that set the TTL of the output, if necessary
+local function ttlDate( format, time )
+ if time == nil and ( format == nil or type( format ) == 'string' ) then
+ local now = os.date( format and format:sub( 1, 1 ) == '!' and '!*t' or '*t' )
+ if format == '!*t' or format == '*t' then
+ return wrapDateTable( now )
+ end
+ local cleanedFormat = format and format:gsub( '%%%%', '' )
+ if not format or cleanedFormat:find( '%%[EO]?[crsSTX+]' ) then
+ php.setTTL( 1 ) -- second
+ elseif cleanedFormat:find( '%%[EO]?[MR]' ) then
+ php.setTTL( 60 - now.sec ) -- minute
+ elseif cleanedFormat:find( '%%[EO]?[HIkl]' ) then
+ php.setTTL( 3600 - now.min * 60 - now.sec ) -- hour
+ elseif cleanedFormat:find( '%%[EO]?[pP]' ) then
+ php.setTTL( 43200 - ( now.hour % 12 ) * 3600 - now.min * 60 - now.sec ) -- am/pm
+ else
+ -- It's not worth the complexity to figure out the exact TTL of larger units than days.
+ -- If they haven't used anything shorter than days, then just set the TTL to expire at
+ -- the end of today.
+ php.setTTL( 86400 - now.hour * 3600 - now.min * 60 - now.sec )
+ end
+ end
+ return os.date( format, time )
+end
+
+local function ttlTime( t )
+ if t == nil then
+ php.setTTL( 1 )
+ end
+ return os.time( t )
+end
+
+local function newFrame( frameId, ... )
+ if not php.frameExists( frameId ) then
+ return nil
+ end
+
+ local frame = {}
+ local parentFrameIds = { ... }
+ local argCache = {}
+ local argNames
+ local args_mt = {}
+
+ local function checkSelf( self, method )
+ if self ~= frame then
+ error( "frame:" .. method .. ": invalid frame object. " ..
+ "Did you call " .. method .. " with a dot instead of a colon, i.e. " ..
+ "frame." .. method .. "() instead of frame:" .. method .. "()?",
+ 3 )
+ end
+ end
+
+ -- Getter for args
+ local function getExpandedArgument( dummy, name )
+ name = tostring( name )
+ if argCache[name] == nil then
+ local arg = php.getExpandedArgument( frameId, name )
+ if arg == nil then
+ argCache[name] = false
+ else
+ argCache[name] = arg
+ end
+ end
+ if argCache[name] == false then
+ return nil
+ else
+ return argCache[name]
+ end
+ end
+
+ args_mt.__index = getExpandedArgument
+
+ -- pairs handler for args
+ args_mt.__pairs = function ()
+ if not argNames then
+ local arguments = php.getAllExpandedArguments( frameId )
+ argNames = {}
+ for name, value in pairs( arguments ) do
+ table.insert( argNames, name )
+ argCache[name] = value
+ end
+ end
+
+ local index = 0
+ return function ()
+ index = index + 1
+ if argNames[index] then
+ return argNames[index], argCache[argNames[index]]
+ end
+ end
+ end
+
+ -- ipairs 'next' function for args
+ local function argsInext( dummy, i )
+ local value = getExpandedArgument( dummy, i + 1 )
+ if value then
+ return i + 1, value
+ end
+ end
+
+ args_mt.__ipairs = function () return argsInext, nil, 0 end
+
+ frame.args = {}
+ setmetatable( frame.args, args_mt )
+
+ local function newCallbackParserValue( callback )
+ local value = {}
+ local cache
+
+ function value:expand()
+ if not cache then
+ cache = callback()
+ end
+ return cache
+ end
+
+ return value
+ end
+
+ function frame:getArgument( opt )
+ checkSelf( self, 'getArgument' )
+
+ local name
+ if type( opt ) == 'table' then
+ name = opt.name
+ else
+ name = opt
+ end
+
+ return newCallbackParserValue(
+ function ()
+ return getExpandedArgument( nil, name )
+ end
+ )
+ end
+
+ function frame:getParent()
+ checkSelf( self, 'getParent' )
+
+ return newFrame( unpack( parentFrameIds ) )
+ end
+
+ local function checkArgs( name, args )
+ local ret = {}
+ for k, v in pairs( args ) do
+ local tp = type( k )
+ if tp ~= 'string' and tp ~= 'number' then
+ error( name .. ": arg keys must be strings or numbers, " .. tp .. " given", 3 )
+ end
+ tp = type( v )
+ if tp == 'boolean' then
+ ret[k] = v and '1' or ''
+ elseif tp == 'string' or tp == 'number' then
+ ret[k] = tostring( v )
+ else
+ error( name .. ": invalid type " .. tp .. " for arg '" .. k .. "'", 3 )
+ end
+ end
+ return ret
+ end
+
+ function frame:newChild( opt )
+ checkSelf( self, 'newChild' )
+
+ if type( opt ) ~= 'table' then
+ error( "frame:newChild: the first parameter must be a table", 2 )
+ end
+
+ local title, args
+ if opt.title == nil then
+ title = false
+ else
+ title = tostring( opt.title )
+ end
+ if opt.args == nil then
+ args = {}
+ elseif type( opt.args ) ~= 'table' then
+ error( "frame:newChild: args must be a table", 2 )
+ else
+ args = checkArgs( 'frame:newChild', opt.args )
+ end
+
+ local newFrameId = php.newChildFrame( frameId, title, args )
+ return newFrame( newFrameId, frameId, unpack( parentFrameIds ) )
+ end
+
+ function frame:expandTemplate( opt )
+ checkSelf( self, 'expandTemplate' )
+
+ local title
+
+ if type( opt ) ~= 'table' then
+ error( "frame:expandTemplate: the first parameter must be a table" )
+ end
+ if opt.title == nil then
+ error( "frame:expandTemplate: a title is required" )
+ else
+ if type( opt.title ) == 'table' and opt.title.namespace == 0 then
+ title = ':' .. tostring( opt.title )
+ else
+ title = tostring( opt.title )
+ end
+ end
+ local args
+ if opt.args == nil then
+ args = {}
+ elseif type( opt.args ) ~= 'table' then
+ error( "frame:expandTemplate: args must be a table" )
+ else
+ args = checkArgs( 'frame:expandTemplate', opt.args )
+ end
+
+ return php.expandTemplate( frameId, title, args )
+ end
+
+ function frame:callParserFunction( name, args, ... )
+ checkSelf( self, 'callParserFunction' )
+
+ if type( name ) == 'table' then
+ name, args = name.name, name.args
+ if type( args ) ~= 'table' then
+ args = { args }
+ end
+ elseif type( args ) ~= 'table' then
+ args = { args, ... }
+ end
+
+ if name == nil then
+ error( "frame:callParserFunction: a function name is required", 2 )
+ elseif type( name ) == 'string' or type( name ) == 'number' then
+ name = tostring( name )
+ else
+ error( "frame:callParserFunction: function name must be a string or number", 2 )
+ end
+
+ args = checkArgs( 'frame:callParserFunction', args )
+
+ return php.callParserFunction( frameId, name, args )
+ end
+
+ function frame:extensionTag( name, content, args )
+ checkSelf( self, 'extensionTag' )
+
+ if type( name ) == 'table' then
+ name, content, args = name.name, name.content, name.args
+ end
+
+ if name == nil then
+ error( "frame:extensionTag: a function name is required", 2 )
+ elseif type( name ) == 'string' or type( name ) == 'number' then
+ name = tostring( name )
+ else
+ error( "frame:extensionTag: tag name must be a string or number", 2 )
+ end
+
+ if content == nil then
+ content = ''
+ elseif type( content ) == 'string' or type( content ) == 'number' then
+ content = tostring( content )
+ else
+ error( "frame:extensionTag: content must be a string or number", 2 )
+ end
+
+ if args == nil then
+ args = { content }
+ elseif type( args ) == 'string' or type( args ) == 'number' then
+ args = { content, args }
+ elseif type( args ) == 'table' then
+ args = checkArgs( 'frame:extensionTag', args )
+ table.insert( args, 1, content )
+ else
+ error( "frame:extensionTag: args must be a string, number, or table", 2 )
+ end
+
+ return php.callParserFunction( frameId, '#tag:' .. name, args )
+ end
+
+ function frame:preprocess( opt )
+ checkSelf( self, 'preprocess' )
+
+ local text
+ if type( opt ) == 'table' then
+ text = opt.text
+ else
+ text = opt
+ end
+ text = tostring( text )
+ return php.preprocess( frameId, text )
+ end
+
+ function frame:newParserValue( opt )
+ checkSelf( self, 'newParserValue' )
+
+ local text
+ if type( opt ) == 'table' then
+ text = opt.text
+ else
+ text = opt
+ end
+
+ return newCallbackParserValue(
+ function ()
+ return self:preprocess( text )
+ end
+ )
+ end
+
+ function frame:newTemplateParserValue( opt )
+ checkSelf( self, 'newTemplateParserValue' )
+
+ if type( opt ) ~= 'table' then
+ error( "frame:newTemplateParserValue: the first parameter must be a table" )
+ end
+ if opt.title == nil then
+ error( "frame:newTemplateParserValue: a title is required" )
+ end
+ return newCallbackParserValue(
+ function ()
+ return self:expandTemplate( opt )
+ end
+ )
+ end
+
+ function frame:getTitle()
+ checkSelf( self, 'getTitle' )
+ return php.getFrameTitle( frameId )
+ end
+
+ -- For backwards compat
+ function frame:argumentPairs()
+ checkSelf( self, 'argumentPairs' )
+ return pairs( self.args )
+ end
+
+ return frame
+end
+
+--- Set up a cloned environment for execution of a module chunk, then execute
+-- the module in that environment. This is called by the host to implement
+-- {{#invoke}}.
+--
+-- @param chunk The module chunk
+-- @param name The name of the function to be returned. Nil or false causes the entire export table to be returned
+-- @return boolean Whether the requested value was able to be returned
+-- @return table|function|string The requested value, or if that was unable to be returned, the type of the value returned by the module
+function mw.executeModule( chunk, name )
+ local env = mw.clone( _G )
+ makePackageModule( env )
+
+ -- These are unsafe
+ env.mw.makeProtectedEnvFuncs = nil
+ env.mw.executeModule = nil
+ if name ~= false then -- console sets name to false when evaluating its code and nil when evaluating a module's
+ env.mw.getLogBuffer = nil
+ env.mw.clearLogBuffer = nil
+ end
+
+ if allowEnvFuncs then
+ env.setfenv, env.getfenv = mw.makeProtectedEnvFuncs( {[_G] = true}, {} )
+ else
+ env.setfenv = nil
+ env.getfenv = nil
+ end
+
+ env.os.date = ttlDate
+ env.os.time = ttlTime
+
+ setfenv( chunk, env )
+
+ local oldFrame = currentFrame
+ if not currentFrame then
+ currentFrame = newFrame( 'current', 'parent' )
+ end
+ local res = chunk()
+ currentFrame = oldFrame
+
+ if not name then -- catch console whether it's evaluating its own code or a module's
+ return true, res
+ end
+ if type(res) ~= 'table' then
+ return false, type(res)
+ end
+ return true, res[name]
+end
+
+function mw.executeFunction( chunk )
+ local frame = newFrame( 'current', 'parent' )
+ local oldFrame = currentFrame
+
+ if executeFunctionDepth == 0 then
+ -- math.random is defined as using C's rand(), and C's rand() uses 1 as
+ -- a seed if not explicitly seeded. So reseed with 1 for each top-level
+ -- #invoke to avoid people passing state via the RNG.
+ math.randomseed( 1 )
+ end
+ executeFunctionDepth = executeFunctionDepth + 1
+
+ currentFrame = frame
+ local results = { chunk( frame ) }
+ currentFrame = oldFrame
+
+ local stringResults = {}
+ for i, result in ipairs( results ) do
+ stringResults[i] = tostring( result )
+ end
+
+ executeFunctionDepth = executeFunctionDepth - 1
+
+ return table.concat( stringResults )
+end
+
+function mw.allToString( ... )
+ local t = { ... }
+ for i = 1, select( '#', ... ) do
+ t[i] = tostring( t[i] )
+ end
+ return table.concat( t, '\t' )
+end
+
+function mw.log( ... )
+ logBuffer = logBuffer .. mw.allToString( ... ) .. '\n'
+end
+
+function mw.dumpObject( object )
+ local doneTable = {}
+ local doneObj = {}
+ local ct = {}
+ local function sorter( a, b )
+ local ta, tb = type( a ), type( b )
+ if ta ~= tb then
+ return ta < tb
+ end
+ if ta == 'string' or ta == 'number' then
+ return a < b
+ end
+ if ta == 'boolean' then
+ return tostring( a ) < tostring( b )
+ end
+ return false -- Incomparable
+ end
+ local function _dumpObject( object, indent, expandTable )
+ local tp = type( object )
+ if tp == 'number' or tp == 'nil' or tp == 'boolean' then
+ return tostring( object )
+ elseif tp == 'string' then
+ return string.format( "%q", object )
+ elseif tp == 'table' then
+ if not doneObj[object] then
+ local s = tostring( object )
+ if s == 'table' then
+ ct[tp] = ( ct[tp] or 0 ) + 1
+ doneObj[object] = 'table#' .. ct[tp]
+ else
+ doneObj[object] = s
+ doneTable[object] = true
+ end
+ end
+ if doneTable[object] or not expandTable then
+ return doneObj[object]
+ end
+ doneTable[object] = true
+
+ local ret = { doneObj[object], ' {\n' }
+ local mt = getmetatable( object )
+ if mt then
+ ret[#ret + 1] = string.rep( " ", indent + 2 )
+ ret[#ret + 1] = 'metatable = '
+ ret[#ret + 1] = _dumpObject( mt, indent + 2, false )
+ ret[#ret + 1] = "\n"
+ end
+
+ local doneKeys = {}
+ for key, value in ipairs( object ) do
+ doneKeys[key] = true
+ ret[#ret + 1] = string.rep( " ", indent + 2 )
+ ret[#ret + 1] = _dumpObject( value, indent + 2, true )
+ ret[#ret + 1] = ',\n'
+ end
+ local keys = {}
+ for key in pairs( object ) do
+ if not doneKeys[key] then
+ keys[#keys + 1] = key
+ end
+ end
+ table.sort( keys, sorter )
+ for i = 1, #keys do
+ local key = keys[i]
+ ret[#ret + 1] = string.rep( " ", indent + 2 )
+ ret[#ret + 1] = '['
+ ret[#ret + 1] = _dumpObject( key, indent + 3, false )
+ ret[#ret + 1] = '] = '
+ ret[#ret + 1] = _dumpObject( object[key], indent + 2, true )
+ ret[#ret + 1] = ",\n"
+ end
+ ret[#ret + 1] = string.rep( " ", indent )
+ ret[#ret + 1] = '}'
+ return table.concat( ret )
+ else
+ if not doneObj[object] then
+ ct[tp] = ( ct[tp] or 0 ) + 1
+ doneObj[object] = tostring( object ) .. '#' .. ct[tp]
+ end
+ return doneObj[object]
+ end
+ end
+ return _dumpObject( object, 0, true )
+end
+
+function mw.logObject( object, prefix )
+ if prefix and prefix ~= '' then
+ logBuffer = logBuffer .. prefix .. ' = '
+ end
+ logBuffer = logBuffer .. mw.dumpObject( object ) .. '\n'
+end
+
+function mw.clearLogBuffer()
+ logBuffer = ''
+end
+
+function mw.getLogBuffer()
+ return logBuffer
+end
+
+function mw.getCurrentFrame()
+ if not currentFrame then
+ currentFrame = newFrame( 'current', 'parent' )
+ end
+ return currentFrame
+end
+
+function mw.isSubsting()
+ return php.isSubsting()
+end
+
+function mw.incrementExpensiveFunctionCount()
+ php.incrementExpensiveFunctionCount()
+end
+
+function mw.addWarning( text )
+ php.addWarning( text )
+end
+
+---
+-- Wrapper for mw.loadData. This creates the read-only dummy table for
+-- accessing the real data.
+--
+-- @param data table Data to access
+-- @param seen table|nil Table of already-seen tables.
+-- @return table
+local function dataWrapper( data, seen )
+ local t = {}
+ seen = seen or { [data] = t }
+
+ local function pairsfunc( s, k )
+ k = next( data, k )
+ if k ~= nil then
+ return k, t[k]
+ end
+ return nil
+ end
+
+ local function ipairsfunc( s, i )
+ i = i + 1
+ if data[i] ~= nil then
+ return i, t[i]
+ end
+ return -- no nil to match default ipairs()
+ end
+
+ local mt = {
+ mw_loadData = true,
+ __index = function ( tt, k )
+ assert( t == tt )
+ local v = data[k]
+ if type( v ) == 'table' then
+ seen[v] = seen[v] or dataWrapper( v, seen )
+ return seen[v]
+ end
+ return v
+ end,
+ __newindex = function ( t, k, v )
+ error( "table from mw.loadData is read-only", 2 )
+ end,
+ __pairs = function ( tt )
+ assert( t == tt )
+ return pairsfunc, t, nil
+ end,
+ __ipairs = function ( tt )
+ assert( t == tt )
+ return ipairsfunc, t, 0
+ end,
+ }
+ -- This is just to make setmetatable() fail
+ mt.__metatable = mt
+
+ return setmetatable( t, mt )
+end
+
+---
+-- Validator for mw.loadData. This scans through the data looking for things
+-- that are not supported, e.g. functions (which may be closures).
+--
+-- @param d table Data to access.
+-- @param seen table|nil Table of already-seen tables.
+-- @return string|nil Error message, if any
+local function validateData( d, seen )
+ seen = seen or {}
+ local tp = type( d )
+ if tp == 'nil' or tp == 'boolean' or tp == 'number' or tp == 'string' then
+ return nil
+ elseif tp == 'table' then
+ if seen[d] then
+ return nil
+ end
+ seen[d] = true
+ if getmetatable( d ) ~= nil then
+ return "data for mw.loadData contains a table with a metatable"
+ end
+ for k, v in pairs( d ) do
+ if type( k ) == 'table' then
+ return "data for mw.loadData contains a table as a key"
+ end
+ local err = validateData( k, seen ) or validateData( v, seen )
+ if err then
+ return err
+ end
+ end
+ return nil
+ else
+ return "data for mw.loadData contains unsupported data type '" .. tp .. "'"
+ end
+end
+
+function mw.loadData( module )
+ local data = loadedData[module]
+ if type( data ) == 'string' then
+ -- No point in re-validating
+ error( data, 2 )
+ end
+ if not data then
+ -- Don't allow accessing the current frame's info (bug 65687)
+ local oldFrame = currentFrame
+ currentFrame = newFrame( 'empty' )
+
+ -- The point of this is to load big data, so don't save it in package.loaded
+ -- where it will have to be copied for all future modules.
+ local l = package.loaded[module]
+ local _
+
+ _, data = mw.executeModule( function() return require( module ) end )
+
+ package.loaded[module] = l
+ currentFrame = oldFrame
+
+ -- Validate data
+ local err
+ if type( data ) == 'table' then
+ err = validateData( data )
+ else
+ err = module .. ' returned ' .. type( data ) .. ', table expected'
+ end
+ if err then
+ loadedData[module] = err
+ error( err, 2 )
+ end
+ loadedData[module] = data
+ end
+
+ return dataWrapper( data )
+end
+
+return mw
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.message.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.message.lua
new file mode 100644
index 00000000..b80c931c
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.message.lua
@@ -0,0 +1,198 @@
+local message = {}
+local php
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+
+local valuemt = {
+ __tostring = function ( t )
+ return tostring( t.raw or t.num )
+ end
+}
+
+local function checkScalar( name, argIdx, arg, level, valuemtOk )
+ local tp = type( arg )
+
+ -- If special params are ok, detect them
+ if valuemtOk and tp == 'table' and getmetatable( arg ) == valuemt then
+ return arg
+ end
+
+ -- If it's a table with a custom __tostring function, use that string
+ if tp == 'table' and getmetatable( arg ) and getmetatable( arg ).__tostring then
+ return tostring( arg )
+ end
+
+ if tp ~= 'string' and tp ~= 'number' then
+ error( string.format(
+ "bad argument #%d to '%s' (string or number expected, got %s)",
+ argIdx, name, tp
+ ), level + 1 )
+ end
+
+ return arg
+end
+
+local function checkParams( name, valueOk, ... )
+ -- Accept an array of params, or params as individual command line arguments
+ local params, nparams
+ local first = select( 1, ... )
+ if type( first ) == 'table' and
+ not ( getmetatable( first ) and getmetatable( first ).__tostring )
+ then
+ if select( '#', ... ) == 1 then
+ params = first
+ nparams = table.maxn( params )
+ else
+ error(
+ "bad arguments to '" .. name .. "' (pass either a table of params or params as individual arguments)",
+ 3
+ )
+ end
+ else
+ params = { ... }
+ nparams = select( '#', ... )
+ end
+ for i = 1, nparams do
+ params[i] = checkScalar( 'params', i, params[i], 3, valueOk )
+ end
+ return params
+end
+
+function message.setupInterface( options )
+ -- Boilerplate
+ message.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+ php.options = options
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.message = message
+
+ package.loaded['mw.message'] = message
+end
+
+local function makeMessage( options )
+ local obj = {}
+ local checkSelf = util.makeCheckSelfFunction( 'mw.message', 'msg', obj, 'message object' )
+
+ local data = {
+ keys = options.keys,
+ rawMessage = options.rawMessage,
+ params = {},
+ lang = php.options.lang,
+ useDB = true,
+ }
+
+ function obj:params( ... )
+ checkSelf( self, 'params' )
+ local params = checkParams( 'params', true, ... )
+ local j = #data.params
+ for i = 1, #params do
+ data.params[j + i] = params[i]
+ end
+ return self
+ end
+
+ function obj:rawParams( ... )
+ checkSelf( self, 'rawParams' )
+ local params = checkParams( 'rawParams', false, ... )
+ local j = #data.params
+ for i = 1, #params do
+ data.params[j + i] = setmetatable( { raw = params[i] }, valuemt )
+ end
+ return self
+ end
+
+ function obj:numParams( ... )
+ checkSelf( self, 'numParams' )
+ local params = checkParams( 'numParams', false, ... )
+ local j = #data.params
+ for i = 1, #params do
+ data.params[j + i] = setmetatable( { num = params[i] }, valuemt )
+ end
+ return self
+ end
+
+ function obj:inLanguage( lang )
+ checkSelf( self, 'inLanguage' )
+ if type( lang ) == 'table' and lang.getCode then
+ -- probably a mw.language object
+ lang = lang:getCode()
+ end
+ checkType( 'inLanguage', 1, lang, 'string' )
+ data.lang = lang
+ return self
+ end
+
+ function obj:useDatabase( value )
+ checkSelf( self, 'useDatabase' )
+ checkType( 'useDatabase', 1, value, 'boolean' )
+ data.useDB = value
+ return self
+ end
+
+ function obj:plain()
+ checkSelf( self, 'plain' )
+ return php.plain( data )
+ end
+
+ function obj:exists()
+ checkSelf( self, 'exists' )
+ return php.check( 'exists', data )
+ end
+
+ function obj:isBlank()
+ checkSelf( self, 'isBlank' )
+ return php.check( 'isBlank', data )
+ end
+
+ function obj:isDisabled()
+ checkSelf( self, 'isDisabled' )
+ return php.check( 'isDisabled', data )
+ end
+
+ return setmetatable( obj, {
+ __tostring = function ( t )
+ return t:plain()
+ end
+ } )
+end
+
+function message.new( key, ... )
+ checkType( 'message.new', 1, key, 'string' )
+ return makeMessage{ keys = { key } }:params( ... )
+end
+
+function message.newFallbackSequence( ... )
+ for i = 1, math.max( 1, select( '#', ... ) ) do
+ checkType( 'message.newFallbackSequence', i, select( i, ... ), 'string' )
+ end
+ return makeMessage{ keys = { ... } }
+end
+
+function message.newRawMessage( msg, ... )
+ checkType( 'message.newRawMessage', 1, msg, 'string' )
+ return makeMessage{ rawMessage = msg }:params( ... )
+end
+
+function message.rawParam( value )
+ value = checkScalar( 'message.rawParam', 1, value )
+ return setmetatable( { raw = value }, valuemt )
+end
+
+function message.numParam( value )
+ value = checkScalar( 'message.numParam', 1, value )
+ return setmetatable( { num = value }, valuemt )
+end
+
+function message.getDefaultLanguage()
+ if mw.language then
+ return mw.language.new( php.options.lang )
+ else
+ return php.options.lang
+ end
+end
+
+return message
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.site.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.site.lua
new file mode 100644
index 00000000..09943a83
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.site.lua
@@ -0,0 +1,86 @@
+local site = {}
+
+function site.setupInterface( info )
+ -- Boilerplate
+ site.setupInterface = nil
+ local php = mw_interface
+ mw_interface = nil
+
+ site.siteName = info.siteName
+ site.server = info.server
+ site.scriptPath = info.scriptPath
+ site.stylePath = info.stylePath
+ site.currentVersion = info.currentVersion
+ site.stats = info.stats
+ site.stats.pagesInCategory = php.pagesInCategory
+ site.stats.pagesInNamespace = php.pagesInNamespace
+ site.stats.usersInGroup = php.usersInGroup
+ site.interwikiMap = php.interwikiMap
+
+ -- Process namespace list into more useful tables
+ site.namespaces = {}
+ local namespacesByName = {}
+ site.subjectNamespaces = {}
+ site.talkNamespaces = {}
+ site.contentNamespaces = {}
+ for ns, data in pairs( info.namespaces ) do
+ data.subject = info.namespaces[data.subject]
+ data.talk = info.namespaces[data.talk]
+ data.associated = info.namespaces[data.associated]
+
+ site.namespaces[ns] = data
+
+ namespacesByName[data.name] = data
+ if data.canonicalName then
+ namespacesByName[data.canonicalName] = data
+ end
+ for i = 1, #data.aliases do
+ namespacesByName[data.aliases[i]] = data
+ end
+
+ if data.isSubject then
+ site.subjectNamespaces[ns] = data
+ end
+ if data.isTalk then
+ site.talkNamespaces[ns] = data
+ end
+ if data.isContent then
+ site.contentNamespaces[ns] = data
+ end
+ end
+
+ -- Set __index for namespacesByName to handle names-with-underscores
+ -- and non-standard case
+ local getNsIndex = php.getNsIndex
+ setmetatable( namespacesByName, {
+ __index = function ( t, k )
+ if type( k ) == 'string' then
+ -- Try with fixed underscores
+ k = string.gsub( k, '_', ' ' )
+ if rawget( t, k ) then
+ return rawget( t, k )
+ end
+
+ -- Ask PHP, because names are case-insensitive
+ local ns = getNsIndex( k )
+ if ns then
+ rawset( t, k, site.namespaces[ns] )
+ end
+ end
+ return rawget( t, k )
+ end
+ } )
+
+ -- Set namespacesByName as the lookup table for site.namespaces, so
+ -- something like site.namespaces.Wikipedia works without having
+ -- pairs( site.namespaces ) iterate all those names.
+ setmetatable( site.namespaces, { __index = namespacesByName } )
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.site = site
+
+ package.loaded['mw.site'] = site
+end
+
+return site
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.text.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.text.lua
new file mode 100644
index 00000000..04399662
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.text.lua
@@ -0,0 +1,330 @@
+local mwtext = {}
+local php
+local options
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+local checkTypeForNamedArg = util.checkTypeForNamedArg
+
+function mwtext.setupInterface( opts )
+ -- Boilerplate
+ mwtext.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+ options = opts
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.text = mwtext
+
+ package.loaded['mw.text'] = mwtext
+end
+
+function mwtext.trim( s, charset )
+ charset = charset or '\t\r\n\f '
+ s = mw.ustring.gsub( s, '^[' .. charset .. ']*(.-)[' .. charset .. ']*$', '%1' )
+ return s
+end
+
+local htmlencode_map = {
+ ['>'] = '&gt;',
+ ['<'] = '&lt;',
+ ['&'] = '&amp;',
+ ['"'] = '&quot;',
+ ["'"] = '&#039;',
+ ['\194\160'] = '&nbsp;',
+}
+local htmldecode_map = {}
+for k, v in pairs( htmlencode_map ) do
+ htmldecode_map[v] = k
+end
+local decode_named_entities = nil
+
+function mwtext.encode( s, charset )
+ charset = charset or '<>&"\'\194\160'
+ s = mw.ustring.gsub( s, '[' .. charset .. ']', function ( m )
+ if not htmlencode_map[m] then
+ local e = string.format( '&#%d;', mw.ustring.codepoint( m ) )
+ htmlencode_map[m] = e
+ htmldecode_map[e] = m
+ end
+ return htmlencode_map[m]
+ end )
+ return s
+end
+
+function mwtext.decode( s, decodeNamedEntities )
+ local dec
+ if decodeNamedEntities then
+ if decode_named_entities == nil then
+ decode_named_entities = php.getEntityTable()
+ setmetatable( decode_named_entities, { __index = htmldecode_map } )
+ end
+ dec = decode_named_entities
+ else
+ dec = htmldecode_map
+ end
+ -- string.gsub is safe here, because only ASCII chars are in the pattern
+ s = string.gsub( s, '(&(#?x?)([a-zA-Z0-9]+);)', function ( m, flg, name )
+ if not dec[m] then
+ local n = nil
+ if flg == '#' then
+ n = tonumber( name, 10 )
+ elseif flg == '#x' then
+ n = tonumber( name, 16 )
+ end
+ if n and n <= 0x10ffff then
+ n = mw.ustring.char( n )
+ if n then
+ htmldecode_map[m] = n
+ htmlencode_map[n] = m
+ end
+ end
+ end
+ return dec[m]
+ end )
+ return s
+end
+
+local nowikiRepl1 = {
+ ['"'] = '&#34;',
+ ['&'] = '&#38;',
+ ["'"] = '&#39;',
+ ['<'] = '&#60;',
+ ['='] = '&#61;',
+ ['>'] = '&#62;',
+ ['['] = '&#91;',
+ [']'] = '&#93;',
+ ['{'] = '&#123;',
+ ['|'] = '&#124;',
+ ['}'] = '&#125;',
+}
+
+local nowikiRepl2 = {
+ ["\n#"] = "\n&#35;", ["\r#"] = "\r&#35;",
+ ["\n*"] = "\n&#42;", ["\r*"] = "\r&#42;",
+ ["\n:"] = "\n&#58;", ["\r:"] = "\r&#58;",
+ ["\n;"] = "\n&#59;", ["\r;"] = "\r&#59;",
+ ["\n "] = "\n&#32;", ["\r "] = "\r&#32;",
+ ["\n\n"] = "\n&#10;", ["\r\n"] = "&#13;\n",
+ ["\n\r"] = "\n&#13;", ["\r\r"] = "\r&#13;",
+ ["\n\t"] = "\n&#9;", ["\r\t"] = "\r&#9;",
+}
+
+local nowikiReplMagic = {}
+for sp, esc in pairs( {
+ [' '] = '&#32;',
+ ['\t'] = '&#9;',
+ ['\r'] = '&#13;',
+ ['\n'] = '&#10;',
+ ['\f'] = '&#12;',
+} ) do
+ nowikiReplMagic['ISBN' .. sp] = 'ISBN' .. esc
+ nowikiReplMagic['RFC' .. sp] = 'RFC' .. esc
+ nowikiReplMagic['PMID' .. sp] = 'PMID' .. esc
+end
+
+function mwtext.nowiki( s )
+ -- string.gsub is safe here, because we're only caring about ASCII chars
+ s = string.gsub( s, '["&\'<=>%[%]{|}]', nowikiRepl1 )
+ s = '\n' .. s
+ s = string.gsub( s, '[\r\n][#*:; \n\r\t]', nowikiRepl2 )
+ s = string.gsub( s, '([\r\n])%-%-%-%-', '%1&#45;---' )
+ s = string.sub( s, 2 )
+ s = string.gsub( s, '__', '_&#95;' )
+ s = string.gsub( s, '://', '&#58;//' )
+ s = string.gsub( s, 'ISBN%s', nowikiReplMagic )
+ s = string.gsub( s, 'RFC%s', nowikiReplMagic )
+ s = string.gsub( s, 'PMID%s', nowikiReplMagic )
+ for k, v in pairs( options.nowiki_protocols ) do
+ s = string.gsub( s, k, v )
+ end
+
+ return s
+end
+
+function mwtext.tag( name, attrs, content )
+ local named = false
+ if type( name ) == 'table' then
+ named = true
+ name, attrs, content = name.name, name.attrs, name.content
+ checkTypeForNamedArg( 'tag', 'name', name, 'string' )
+ checkTypeForNamedArg( 'tag', 'attrs', attrs, 'table', true )
+ else
+ checkType( 'tag', 1, name, 'string' )
+ checkType( 'tag', 2, attrs, 'table', true )
+ end
+
+ local ret = { '<' .. name }
+ for k, v in pairs( attrs or {} ) do
+ if type( k ) ~= 'string' then
+ error( "bad named argument attrs to 'tag' (keys must be strings, found " .. type( k ) .. ")", 2 )
+ end
+ if string.match( k, '[\t\r\n\f /<>"\'=]' ) then
+ error( "bad named argument attrs to 'tag' (invalid key '" .. k .. "')", 2 )
+ end
+ local tp = type( v )
+ if tp == 'boolean' then
+ if v then
+ ret[#ret+1] = ' ' .. k
+ end
+ elseif tp == 'string' or tp == 'number' then
+ ret[#ret+1] = string.format( ' %s="%s"', k, mwtext.encode( tostring( v ) ) )
+ else
+ error( "bad named argument attrs to 'tag' (value for key '" .. k .. "' may not be " .. tp .. ")", 2 )
+ end
+ end
+
+ local tp = type( content )
+ if content == nil then
+ ret[#ret+1] = '>'
+ elseif content == false then
+ ret[#ret+1] = ' />'
+ elseif tp == 'string' or tp == 'number' then
+ ret[#ret+1] = '>'
+ ret[#ret+1] = content
+ ret[#ret+1] = '</' .. name .. '>'
+ else
+ if named then
+ checkTypeForNamedArg( 'tag', 'content', content, 'string, number, nil, or false' )
+ else
+ checkType( 'tag', 3, content, 'string, number, nil, or false' )
+ end
+ end
+
+ return table.concat( ret )
+end
+
+function mwtext.unstrip( s )
+ return php.unstrip( s )
+end
+
+function mwtext.unstripNoWiki( s )
+ return php.unstripNoWiki( s )
+end
+
+function mwtext.killMarkers( s )
+ return php.killMarkers( s )
+end
+
+function mwtext.split( text, pattern, plain )
+ local ret = {}
+ for m in mwtext.gsplit( text, pattern, plain ) do
+ ret[#ret+1] = m
+ end
+ return ret
+end
+
+function mwtext.gsplit( text, pattern, plain )
+ local s, l = 1, mw.ustring.len( text )
+ return function ()
+ if s then
+ local e, n = mw.ustring.find( text, pattern, s, plain )
+ local ret
+ if not e then
+ ret = mw.ustring.sub( text, s )
+ s = nil
+ elseif n < e then
+ -- Empty separator!
+ ret = mw.ustring.sub( text, s, e )
+ if e < l then
+ s = e + 1
+ else
+ s = nil
+ end
+ else
+ ret = e > s and mw.ustring.sub( text, s, e - 1 ) or ''
+ s = n + 1
+ end
+ return ret
+ end
+ end, nil, nil
+end
+
+function mwtext.listToText( list, separator, conjunction )
+ separator = separator or options.comma
+ conjunction = conjunction or options['and']
+ local n = #list
+
+ local ret
+ if n > 1 then
+ ret = table.concat( list, separator, 1, n - 1 ) .. conjunction .. list[n]
+ else
+ ret = tostring( list[1] or '' )
+ end
+
+ return ret
+end
+
+function mwtext.truncate( text, length, ellipsis, adjustLength )
+ local l = mw.ustring.len( text )
+ if l <= math.abs( length ) then
+ return text
+ end
+
+ ellipsis = ellipsis or options.ellipsis
+ local elen = 0
+ if adjustLength then
+ elen = mw.ustring.len( ellipsis )
+ end
+
+ local ret
+ if math.abs( length ) <= elen then
+ ret = ellipsis
+ elseif length > 0 then
+ ret = mw.ustring.sub( text, 1, length - elen ) .. ellipsis
+ else
+ ret = ellipsis .. mw.ustring.sub( text, length + elen )
+ end
+
+ if mw.ustring.len( ret ) < l then
+ return ret
+ else
+ return text
+ end
+end
+
+-- Check for stuff that can't even be passed to PHP properly and other stuff
+-- that gives different error messages in different versions of PHP
+local function checkForJsonEncode( t, seen, lvl )
+ local tp = type( t )
+ if tp == 'table' then
+ if seen[t] then
+ error( "mw.text.jsonEncode: Cannot use recursive tables", lvl )
+ end
+ seen[t] = 1
+ for k, v in pairs( t ) do
+ if type( k ) == 'number' then
+ if k >= math.huge or k <= -math.huge then
+ error( string.format( "mw.text.jsonEncode: Cannot use 'inf' as a table key", type( k ) ), lvl )
+ end
+ elseif type( k ) ~= 'string' then
+ error( string.format( "mw.text.jsonEncode: Cannot use type '%s' as a table key", type( k ) ), lvl )
+ end
+ checkForJsonEncode( v, seen, lvl + 1 )
+ end
+ seen[t] = nil
+ elseif tp == 'number' then
+ if t ~= t or t >= math.huge or t <= -math.huge then
+ error( "mw.text.jsonEncode: Cannot encode non-finite numbers", lvl )
+ end
+ elseif tp ~= 'boolean' and tp ~= 'string' and tp ~= 'nil' then
+ error( string.format( "mw.text.jsonEncode: Cannot encode type '%s'", tp ), lvl )
+ end
+end
+
+function mwtext.jsonEncode( value, flags )
+ checkForJsonEncode( value, {}, 3 )
+ return php.jsonEncode( value, flags )
+end
+
+function mwtext.jsonDecode( json, flags )
+ return php.jsonDecode( json, flags )
+end
+
+-- Matches PHP Scribunto_LuaTextLibrary constants
+mwtext.JSON_PRESERVE_KEYS = 1
+mwtext.JSON_TRY_FIXING = 2
+mwtext.JSON_PRETTY = 4
+
+return mwtext
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.title.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.title.lua
new file mode 100644
index 00000000..5cd72abf
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.title.lua
@@ -0,0 +1,337 @@
+local title = {}
+local php
+local NS_MEDIA = -2
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+local checkTypeForIndex = util.checkTypeForIndex
+
+local function checkNamespace( name, argIdx, arg )
+ if type( arg ) == 'string' and tostring( tonumber( arg ) ) == arg then
+ arg = tonumber( arg )
+ end
+ if type( arg ) == 'number' then
+ arg = math.floor( arg + 0.5 )
+ if not mw.site.namespaces[arg] then
+ local msg = string.format( "bad argument #%d to '%s' (unrecognized namespace number '%s')",
+ argIdx, name, arg
+ )
+ error( msg, 3 )
+ end
+ elseif type( arg ) == 'string' then
+ local ns = mw.site.namespaces[arg]
+ if not ns then
+ local msg = string.format( "bad argument #%d to '%s' (unrecognized namespace name '%s')",
+ argIdx, name, arg
+ )
+ error( msg, 3 )
+ end
+ arg = ns.id
+ else
+ local msg = string.format( "bad argument #%d to '%s' (string or number expected, got %s)",
+ argIdx, name, type( arg )
+ )
+ error( msg, 3 )
+ end
+ return arg
+end
+
+
+local function lt( a, b )
+ if a.interwiki ~= b.interwiki then
+ return a.interwiki < b.interwiki
+ end
+ if a.namespace ~= b.namespace then
+ return a.namespace < b.namespace
+ end
+ return a.text < b.text
+end
+
+local function makeTitleObject( data )
+ if not data then
+ return nil
+ end
+
+ local obj = {}
+ local checkSelf = util.makeCheckSelfFunction( 'mw.title', 'title', obj, 'title object' );
+ local ns = mw.site.namespaces[data.namespace]
+
+ data.isContentPage = ns.isContent
+ data.isExternal = data.interwiki ~= ''
+ data.isSpecialPage = data.namespace == mw.site.namespaces.Special.id
+ data.isTalkPage = ns.isTalk
+ data.subjectNsText = ns.subject.name
+ data.canTalk = ns.talk ~= nil
+
+ data.prefixedText = data.text
+ if data.nsText ~= '' then
+ data.prefixedText = string.gsub( data.nsText .. ':' .. data.prefixedText, '_', ' ' )
+ end
+ if data.interwiki ~= '' then
+ data.prefixedText = data.interwiki .. ':' .. data.prefixedText
+ end
+
+ local firstSlash, lastSlash
+ if ns.hasSubpages then
+ firstSlash, lastSlash = string.match( data.text, '^[^/]*().*()/[^/]*$' )
+ end
+ if firstSlash then
+ data.isSubpage = true
+ data.rootText = string.sub( data.text, 1, firstSlash - 1 )
+ data.baseText = string.sub( data.text, 1, lastSlash - 1 )
+ data.subpageText = string.sub( data.text, lastSlash + 1 )
+ else
+ data.isSubpage = false
+ data.rootText = data.text
+ data.baseText = data.text
+ data.subpageText = data.text
+ end
+
+ function data:inNamespace( ns )
+ checkSelf( self, 'inNamespace' )
+ ns = checkNamespace( 'inNamespace', 1, ns )
+ return ns == self.namespace
+ end
+
+ function data:inNamespaces( ... )
+ checkSelf( self, 'inNamespaces' )
+ for i = 1, select( '#', ... ) do
+ local ns = checkNamespace( 'inNamespaces', i, select( i, ... ) )
+ if ns == self.namespace then
+ return true
+ end
+ end
+ return false
+ end
+
+ function data:hasSubjectNamespace( ns )
+ checkSelf( self, 'hasSubjectNamespace' )
+ ns = checkNamespace( 'hasSubjectNamespace', 1, ns )
+ return ns == mw.site.namespaces[self.namespace].subject.id
+ end
+
+ function data:isSubpageOf( title )
+ checkSelf( self, 'isSubpageOf' )
+ checkType( 'isSubpageOf', 1, title, 'table' )
+ return self.interwiki == title.interwiki and
+ self.namespace == title.namespace and
+ title.text .. '/' == string.sub( self.text, 1, #title.text + 1 )
+ end
+
+ function data:subPageTitle( text )
+ checkSelf( self, 'subpageTitle' )
+ checkType( 'subpageTitle', 1, text, 'string' )
+ return title.makeTitle( data.namespace, data.text .. '/' .. text )
+ end
+
+ function data:partialUrl()
+ checkSelf( self, 'partialUrl' )
+ return data.thePartialUrl
+ end
+
+ function data:fullUrl( query, proto )
+ checkSelf( self, 'fullUrl' )
+ return php.getUrl( self.fullText, 'fullUrl', query, proto )
+ end
+
+ function data:localUrl( query )
+ checkSelf( self, 'localUrl' )
+ return php.getUrl( self.fullText, 'localUrl', query )
+ end
+
+ function data:canonicalUrl( query )
+ checkSelf( self, 'canonicalUrl' )
+ return php.getUrl( self.fullText, 'canonicalUrl', query )
+ end
+
+ function data:getContent()
+ checkSelf( self, 'getContent' )
+ local content = php.getContent( self.fullText )
+ data.getContent = function ( self )
+ checkSelf( self, 'getContent' )
+ return content
+ end
+ return content
+ end
+
+ -- Known fields, both those defined above and any dynamically handled in
+ -- __index. Truthy values represent read-only, and falsey values represent
+ -- read-write. If the value is the string 'e', expensive data will be loaded
+ -- if the field is read.
+ local readOnlyFields = {
+ fragment = false,
+ fullText = true,
+ rootPageTitle = true,
+ basePageTitle = true,
+ talkPageTitle = true,
+ subjectPageTitle = true,
+ fileExists = true,
+ file = true,
+ protectionLevels = true,
+ cascadingProtection = true,
+ exists = 'e',
+ isRedirect = 'e',
+ contentModel = 'e',
+ id = 'e',
+ redirectTarget = true,
+ }
+ for k in pairs( data ) do
+ readOnlyFields[k] = true
+ end
+
+ local function pairsfunc( t, k )
+ local v
+ repeat
+ k = next( readOnlyFields, k )
+ if k == nil then
+ return nil
+ end
+ v = t[k]
+ until v ~= nil
+ return k, v
+ end
+
+ return setmetatable( obj, {
+ __eq = title.equals,
+ __lt = lt,
+ __pairs = function ( t )
+ return pairsfunc, t, nil
+ end,
+ __index = function ( t, k )
+ if k == 'exists' and data.namespace == NS_MEDIA then
+ k = 'fileExists'
+ end
+
+ if readOnlyFields[k] == 'e' and data[k] == nil then
+ for k,v in pairs( php.getExpensiveData( t.fullText ) ) do
+ data[k] = v
+ end
+ end
+
+ if k == 'fullText' then
+ if data.fragment ~= '' then
+ return data.prefixedText .. '#' .. data.fragment
+ else
+ return data.prefixedText
+ end
+ end
+
+ if k == 'rootPageTitle' then
+ return title.makeTitle( data.namespace, data.rootText )
+ end
+ if k == 'basePageTitle' then
+ return title.makeTitle( data.namespace, data.baseText )
+ end
+ if k == 'talkPageTitle' then
+ local ns = mw.site.namespaces[data.namespace].talk
+ if not ns then
+ return nil
+ end
+ if ns.id == data.namespace then
+ return obj
+ end
+ return title.makeTitle( ns.id, data.text )
+ end
+ if k == 'subjectPageTitle' then
+ local ns = mw.site.namespaces[data.namespace].subject
+ if ns.id == data.namespace then
+ return obj
+ end
+ return title.makeTitle( ns.id, data.text )
+ end
+ if k == 'file' then
+ if data.file == nil then
+ data.file = php.getFileInfo( data.prefixedText )
+ end
+ return data.file or nil
+ end
+ if k == 'fileExists' then -- Kept for backward compatibility. Since 1.25, file.exists is preferred over this
+ return t.file and t.file.exists
+ end
+ if k == 'protectionLevels' then
+ if data.protectionLevels == nil then
+ data.protectionLevels = php.protectionLevels( data.prefixedText )
+ end
+ return data.protectionLevels
+ end
+ if k == 'cascadingProtection' then
+ if data.cascadingProtection == nil then
+ data.cascadingProtection = php.cascadingProtection( data.prefixedText )
+ end
+ return data.cascadingProtection
+ end
+ if k == 'redirectTarget' then
+ if data.redirectTarget == nil then
+ data.redirectTarget = makeTitleObject( php.redirectTarget( data.prefixedText ) ) or false
+ end
+ return data.redirectTarget
+ end
+
+ return data[k]
+ end,
+ __newindex = function ( t, k, v )
+ if k == 'fragment' then
+ checkTypeForIndex( k, v, 'string' )
+ v = string.gsub( v, '[%s_]+', ' ' )
+ v = string.gsub( v, '^(.-) ?$', '%1' )
+ data[k] = v
+ elseif readOnlyFields[k] then
+ error( "index '" .. k .. "' is read only", 2 )
+ else
+ readOnlyFields[k] = v and false -- assigns nil if v == nil, false otherwise
+ rawset( t, k, v )
+ end
+ end,
+ __tostring = function ( t )
+ return t.prefixedText
+ end
+ } )
+end
+
+function title.setupInterface( options )
+ -- Boilerplate
+ title.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+ NS_MEDIA = options.NS_MEDIA
+
+ -- Set current title
+ title.getCurrentTitle = function ()
+ return makeTitleObject( mw.clone( options.thisTitle ) )
+ end
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.title = title
+
+ package.loaded['mw.title'] = title
+end
+
+function title.new( text_or_id, defaultNamespace )
+ return makeTitleObject( php.newTitle( text_or_id, defaultNamespace ) )
+end
+
+function title.makeTitle( ns, title, fragment, interwiki )
+ return makeTitleObject( php.makeTitle( ns, title, fragment, interwiki ) )
+end
+
+function title.equals( a, b )
+ return a.interwiki == b.interwiki and
+ a.namespace == b.namespace and
+ a.text == b.text
+end
+
+function title.compare( a, b )
+ if a.interwiki ~= b.interwiki then
+ return a.interwiki < b.interwiki and -1 or 1
+ end
+ if a.namespace ~= b.namespace then
+ return a.namespace < b.namespace and -1 or 1
+ end
+ if a.text ~= b.text then
+ return a.text < b.text and -1 or 1
+ end
+ return 0
+end
+
+return title
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.uri.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.uri.lua
new file mode 100644
index 00000000..ff00eae8
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.uri.lua
@@ -0,0 +1,623 @@
+local uri = {}
+local urifuncs = {}
+local urimt = {}
+local php
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+local checkTypeForIndex = util.checkTypeForIndex
+
+function uri.setupInterface( options )
+ -- Boilerplate
+ uri.setupInterface = nil
+ php = mw_interface
+ mw_interface = nil
+
+ -- Store options
+ php.options = options
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.uri = uri
+
+ package.loaded['mw.uri'] = uri
+end
+
+local function rawencode( s, space )
+ space = space or '%20'
+ local ret = string.gsub( s, '([^a-zA-Z0-9_.~-])', function ( c )
+ if c == ' ' then
+ return space
+ else
+ return string.format( '%%%02X', string.byte( c, 1, 1 ) )
+ end
+ end );
+ return ret
+end
+
+local function wikiencode( s )
+ local ret = string.gsub( s, '([^a-zA-Z0-9!$()*,./:;@~_-])', function ( c )
+ if c == ' ' then
+ return '_'
+ else
+ return string.format( '%%%02X', string.byte( c, 1, 1 ) )
+ end
+ end );
+ return ret
+end
+
+local function rawdecode( s )
+ local ret = string.gsub( s, '%%(%x%x)', function ( hex )
+ return string.char( tonumber( hex, 16 ) )
+ end );
+ return ret
+end
+
+function uri.encode( s, enctype )
+ checkType( 'encode', 1, s, 'string' )
+
+ enctype = string.upper( enctype or 'QUERY' )
+ if enctype == 'QUERY' then
+ return rawencode( s, '+' )
+ elseif enctype == 'PATH' then
+ return rawencode( s, '%20' )
+ elseif enctype == 'WIKI' then
+ return wikiencode( s )
+ else
+ error( "bad argument #2 to 'encode' (expected QUERY, PATH, or WIKI)", 2 )
+ end
+end
+
+function uri.decode( s, enctype )
+ checkType( 'decode', 1, s, 'string' )
+
+ enctype = string.upper( enctype or 'QUERY' )
+ if enctype == 'QUERY' then
+ return rawdecode( string.gsub( s, '%+', ' ' ) )
+ elseif enctype == 'PATH' then
+ return rawdecode( s )
+ elseif enctype == 'WIKI' then
+ return rawdecode( string.gsub( s, '_', ' ' ) )
+ else
+ error( "bad argument #2 to 'decode' (expected QUERY, PATH, or WIKI)", 2 )
+ end
+end
+
+function uri.anchorEncode( s )
+ checkType( 'anchorEncode', 1, s, 'string' )
+ return php.anchorEncode( s )
+end
+
+function uri.localUrl( page, query )
+ checkType( 'localurl', 1, page, 'string' )
+ if query ~= nil and type( query ) ~= 'string' and type( query ) ~= 'table' then
+ checkType( 'localurl', 2, query, 'string or table' )
+ end
+ local url = php.localUrl( page, query )
+ if not url then
+ return nil
+ end
+ return uri.new( url )
+end
+
+function uri.fullUrl( page, query )
+ checkType( 'fullurl', 1, page, 'string' )
+ if query ~= nil and type( query ) ~= 'string' and type( query ) ~= 'table' then
+ checkType( 'fullurl', 2, query, 'string or table' )
+ end
+ local url = php.fullUrl( page, query )
+ if not url then
+ return nil
+ end
+ return uri.new( url )
+end
+
+function uri.canonicalUrl( page, query )
+ checkType( 'canonicalurl', 1, page, 'string' )
+ if query ~= nil and type( query ) ~= 'string' and type( query ) ~= 'table' then
+ checkType( 'canonicalurl', 2, query, 'string or table' )
+ end
+ local url = php.canonicalUrl( page, query )
+ if not url then
+ return nil
+ end
+ return uri.new( url )
+end
+
+
+function uri.new( s )
+ if s == nil or type( s ) == 'string' then
+ local obj = {
+ -- Yes, technically all this does nothing.
+ protocol = nil,
+ user = nil,
+ password = nil,
+ host = nil,
+ port = nil,
+ path = nil,
+ query = nil,
+ fragment = nil,
+ }
+ setmetatable( obj, urimt )
+ obj:parse( s or php.options.defaultUrl )
+ return obj
+ elseif type( s ) == 'table' then
+ local obj = {
+ protocol = s.protocol,
+ user = s.user,
+ password = s.password,
+ host = s.host,
+ port = s.port,
+ path = s.path,
+ query = mw.clone( s.query ),
+ fragment = s.fragment,
+ }
+ setmetatable( obj, urimt )
+ return obj
+ else
+ checkType( 'new', 1, s, 'string or table or nil' )
+ end
+end
+
+function uri.validate( obj )
+ checkType( 'validate', 1, obj, 'table' )
+
+ local err = {}
+
+ if obj.protocol then
+ if type( obj.protocol ) ~= 'string' then
+ err[#err+1] = '.protocol must be a string, not ' .. type( obj.protocol )
+ elseif not string.match( obj.protocol, '^[^:/?#]+$' ) then
+ err[#err+1] = 'invalid .protocol'
+ end
+ end
+
+ if obj.user then
+ if type( obj.user ) ~= 'string' then
+ err[#err+1] = '.user must be a string, not ' .. type( obj.user )
+ elseif not string.match( obj.user, '^[^:@/?#]*$' ) then
+ err[#err+1] = 'invalid .user'
+ end
+ end
+
+ if obj.password then
+ if type( obj.password ) ~= 'string' then
+ err[#err+1] = '.password must be a string, not ' .. type( obj.password )
+ elseif not string.match( obj.password, '^[^:@/?#]*$' ) then
+ err[#err+1] = 'invalid .password'
+ end
+ end
+
+ if obj.host then
+ if type( obj.host ) ~= 'string' then
+ err[#err+1] = '.host must be a string, not ' .. type( obj.host )
+ elseif not string.match( obj.host, '^[^:/?#]*$' ) then
+ err[#err+1] = 'invalid .host'
+ end
+ end
+
+ if obj.port then
+ if type( obj.port ) ~= 'number' or math.floor( obj.port ) ~= obj.port then
+ err[#err+1] = '.port must be an integer, not ' .. type( obj.port )
+ elseif obj.port < 1 or obj.port > 65535 then
+ err[#err+1] = 'invalid .port'
+ end
+ end
+
+ local authority = obj.user or obj.password or obj.host or obj.port
+ if not obj.path then
+ err[#err+1] = 'missing .path'
+ elseif type( obj.path ) ~= 'string' then
+ err[#err+1] = '.path must be a string, not ' .. type( obj.path )
+ elseif authority and not ( obj.path == '' or string.match( obj.path, '^/[^?#]*$' ) ) then
+ err[#err+1] = 'invalid .path'
+ elseif not authority and not (
+ obj.path == '' or
+ obj.path == '/' or
+ string.match( obj.path, '^/[^?#/][^?#]*$' ) or
+ obj.protocol and string.match( obj.path, '^[^?#/][^?#]*$' ) or
+ not obj.protocol and string.match( obj.path, '^[^?#/:]+$' ) or
+ not obj.protocol and string.match( obj.path, '^[^?#/:]+/[^?#]*$' )
+ ) then
+ err[#err+1] = 'invalid .path'
+ end
+
+ if obj.query and type( obj.query ) ~= 'table' then
+ err[#err+1] = '.query must be a table, not ' .. type( obj.query )
+ end
+
+ if obj.fragment and type( obj.fragment ) ~= 'string' then
+ err[#err+1] = '.fragment must be a string, not ' .. type( obj.fragment )
+ end
+
+ return #err == 0, table.concat( err, '; ' )
+end
+
+-- Lua tables are unsorted, but we want to preserve the insertion order.
+-- So, track the insertion order explicitly.
+local function makeQueryTable()
+ local ret = {}
+ local keys = {}
+ local seenkeys = {}
+
+ setmetatable( ret, {
+ __newindex = function ( t, k, v )
+ if seenkeys[k] and not t[k] then
+ for i = 1, #keys do
+ if keys[i] == k then
+ table.remove( keys, i )
+ break
+ end
+ end
+ end
+ seenkeys[k] = 1
+ keys[#keys+1] = k
+ rawset( t, k, v )
+ end,
+ __pairs = function ( t )
+ local i, l = 0, #keys
+ return function ()
+ while i < l do
+ i = i + 1
+ local k = keys[i]
+ if t[k] ~= nil then
+ return k, t[k]
+ end
+ end
+ return nil
+ end
+ end
+ } )
+
+ return ret
+end
+
+function uri.parseQueryString( s, i, j )
+ checkType( 'parseQueryString', 1, s, 'string' )
+ checkType( 'parseQueryString', 2, i, 'number', true )
+ checkType( 'parseQueryString', 3, j, 'number', true )
+
+ s = string.gsub( string.sub( s, i or 1, j or -1 ), '%+', ' ' )
+ i = 1
+ j = string.len( s )
+
+ local qs = makeQueryTable()
+ if string.sub( s, i, 1 ) == '?' then
+ i = i + 1
+ end
+ while i <= j do
+ local amp = string.find( s, '&', i, true )
+ if not amp or amp > j then
+ amp = j + 1
+ end
+ local eq = string.find( s, '=', i, true )
+ local k, v
+ if not eq or eq > amp then
+ k = rawdecode( string.sub( s, i, amp - 1 ) )
+ v = false
+ else
+ k = rawdecode( string.sub( s, i, eq - 1 ) )
+ v = rawdecode( string.sub( s, eq + 1, amp - 1 ) )
+ end
+ if qs[k] then
+ if type( qs[k] ) ~= 'table' then
+ qs[k] = { qs[k], v }
+ else
+ table.insert( qs[k], v )
+ end
+ else
+ qs[k] = v
+ end
+ i = amp + 1
+ end
+ return qs
+end
+
+function uri.buildQueryString( qs )
+ checkType( 'buildQueryString', 1, qs, 'table' )
+
+ local t = {}
+ for k, v in pairs( qs ) do
+ if type( v ) ~= 'table' then
+ v = { v }
+ end
+ for i = 1, #v do
+ t[#t+1] = '&'
+ t[#t+1] = rawencode( k, '+' )
+ if v[i] then
+ t[#t+1] = '='
+ t[#t+1] = rawencode( v[i], '+' )
+ end
+ end
+ end
+ return table.concat( t, '', 2 )
+end
+
+-- Fields mapped to whether they're handled by __index
+local knownFields = {
+ protocol = false,
+ user = false,
+ password = false,
+ host = false,
+ port = false,
+ path = false,
+ query = false,
+ fragment = false,
+ userInfo = true,
+ hostPort = true,
+ authority = true,
+ queryString = true,
+ relativePath = true,
+}
+
+local function pairsfunc( t, k )
+ local v, f
+ repeat
+ k, f = next( knownFields, k )
+ if k == nil then
+ return nil
+ end
+ if f then
+ v = t[k]
+ else
+ v = rawget( t, k )
+ end
+ until v ~= nil
+ return k, v
+end
+function urimt:__pairs()
+ return pairsfunc, self, nil
+end
+
+function urimt:__index( key )
+ if urifuncs[key] then
+ return urifuncs[key]
+ end
+
+ if key == 'userInfo' then
+ local user = rawget( self, 'user' )
+ local password = rawget( self, 'password' )
+ if user and password then
+ return user .. ':' .. password
+ else
+ return user
+ end
+ end
+
+ if key == 'hostPort' then
+ local host = rawget( self, 'host' )
+ local port = rawget( self, 'port' )
+ if port then
+ return ( host or '' ) .. ':' .. port
+ else
+ return host
+ end
+ end
+
+ if key == 'authority' then
+ local info = self.userInfo
+ local hostPort = self.hostPort
+ if info then
+ return info .. '@' .. ( hostPort or '' )
+ else
+ return hostPort
+ end
+ end
+
+ if key == 'queryString' then
+ local query = rawget( self, 'query' )
+ if not query then
+ return nil
+ end
+ return uri.buildQueryString( query )
+ end
+
+ if key == 'relativePath' then
+ local ret = rawget( self, 'path' ) or ''
+ local qs = self.queryString
+ if qs then
+ ret = ret .. '?' .. qs
+ end
+ local fragment = rawget( self, 'fragment' )
+ if fragment then
+ ret = ret .. '#' .. fragment
+ end
+ return ret
+ end
+
+ return nil
+end
+
+function urimt:__newindex( key, value )
+ if key == 'userInfo' then
+ local user, password = nil, nil
+ if value then
+ checkTypeForIndex( key, value, 'string' )
+ local i = string.find( value, ':', 1, true )
+ if i then
+ user = string.sub( value, 1, i - 1 )
+ password = string.sub( value, i + 1 )
+ else
+ user = value
+ end
+ end
+ rawset( self, 'user', user )
+ rawset( self, 'password', password )
+ return
+ end
+
+ if key == 'hostPort' then
+ local host, port = nil, nil
+ if value then
+ checkTypeForIndex( key, value, 'string' )
+ local i = string.find( value, ':', 1, true )
+ if i then
+ host = string.sub( value, 1, i - 1 )
+ port = tonumber( string.sub( value, i + 1 ) )
+ if not port then
+ error( string.format( "Invalid port in '%s'", value ), 2 )
+ end
+ else
+ host = value
+ end
+ end
+ rawset( self, 'host', host )
+ rawset( self, 'port', port )
+ return
+ end
+
+ if key == 'authority' then
+ if value then
+ checkTypeForIndex( key, value, 'string' )
+ local i = string.find( value, '@', 1, true )
+ if i then
+ self.userInfo = string.sub( value, 1, i - 1 )
+ self.hostPort = string.sub( value, i + 1 )
+ else
+ self.userInfo = nil
+ self.hostPort = value
+ end
+ else
+ self.userInfo = nil
+ self.hostPort = nil
+ end
+ return
+ end
+
+ if key == 'queryString' then
+ if value then
+ checkTypeForIndex( key, value, 'string' )
+ rawset( self, 'query', uri.parseQueryString( value ) )
+ else
+ rawset( self, 'query', nil )
+ end
+ return
+ end
+
+ if key == 'relativePath' then
+ local path, query, fragment = nil, nil, nil
+ if value then
+ checkTypeForIndex( key, value, 'string' )
+ local i, j = nil, string.len( value )
+ i = string.find( value, '#', 1, true )
+ if i and i <= j then
+ fragment = string.sub( value, i + 1, j )
+ j = i - 1
+ end
+ i = string.find( value, '?', 1, true )
+ if i and i <= j then
+ query = uri.parseQueryString( string.sub( value, i + 1, j ) )
+ j = i - 1
+ end
+ path = string.sub( value, 1, j )
+ end
+ rawset( self, 'path', path )
+ rawset( self, 'query', query )
+ rawset( self, 'fragment', fragment )
+ return
+ end
+
+ if knownFields[key] then
+ error( "index '" .. key .. "' is read only", 2 )
+ end
+
+ -- Default behavior
+ knownFields[key] = false
+ rawset( self, key, value )
+end
+
+function urimt:__tostring()
+ local ret = ''
+ local protocol = self.protocol
+ local authority = self.authority
+ if protocol then
+ ret = protocol .. ':'
+ end
+ if authority then
+ ret = ret .. '//' .. authority
+ end
+ return ret .. self.relativePath
+end
+
+urifuncs.validate = uri.validate
+
+function urifuncs:parse( s )
+ checkType( 'uri:parse', 1, s, 'string' )
+
+ -- Since Lua's patterns can't do (...)?, we have to try with and without each part.
+ local protocol, authority, relativePath = string.match( s, '^([^:/?#]+)://([^/?#]*)(.*)$' )
+ if not ( protocol or authority or relativePath ) then
+ authority, relativePath = string.match( s, '^//([^/?#]*)(.*)$' )
+ end
+ if not ( protocol or authority or relativePath ) then
+ protocol, relativePath = string.match( s, '^([^:/?#]+):(.*)$' )
+ end
+ if not ( protocol or authority or relativePath ) then
+ relativePath = s
+ end
+
+ -- Parse it into a temporary object, so if there's an error we didn't break the real one
+ local tmp = { protocol = protocol }
+ setmetatable( tmp, urimt )
+ if not pcall( urimt.__newindex, tmp, 'authority', authority ) then
+ error( 'Invalid port number in string', 2 )
+ end
+ tmp.relativePath = relativePath
+
+ -- Check for validity
+ local ok, err = uri.validate( tmp )
+ if not ok then
+ error( err, 2 )
+ end
+
+ -- Merge in fields
+ if tmp.protocol then
+ self.protocol = tmp.protocol
+ end
+ if tmp.user or tmp.password then
+ self.user, self.password = tmp.user, tmp.password
+ end
+ if tmp.host then
+ self.host = tmp.host
+ end
+ if tmp.port then
+ self.port = tmp.port
+ end
+ if tmp.path then
+ self.path = tmp.path
+ end
+ if tmp.query then
+ self.query = tmp.query
+ end
+ if tmp.fragment then
+ self.fragment = tmp.fragment
+ end
+
+ return self
+end
+
+function urifuncs:clone()
+ return uri.new( self )
+end
+
+function urifuncs:extend( parameters )
+ checkType( 'uri:extend', 1, parameters, 'table' )
+
+ local query = self.query
+ if not query then
+ query = makeQueryTable()
+ self.query = query
+ end
+ for k, v in pairs( parameters ) do
+ query[k] = v
+ end
+
+ return self
+end
+
+-- Add all urifuncs as known fields
+for k in pairs( urifuncs ) do
+ knownFields[k] = true
+end
+
+return uri
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.ustring.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.ustring.lua
new file mode 100644
index 00000000..0825a738
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mw.ustring.lua
@@ -0,0 +1,108 @@
+-- Get a fresh copy of the basic ustring
+local old_ustring = package.loaded.ustring
+package.loaded.ustring = nil
+local ustring = require( 'ustring' )
+package.loaded.ustring = old_ustring
+old_ustring = nil
+
+local util = require 'libraryUtil'
+local checkType = util.checkType
+
+local gmatch_init = nil
+local gmatch_callback = nil
+local function php_gmatch( s, pattern )
+ checkType( 'gmatch', 1, s, 'string' )
+ checkType( 'gmatch', 2, pattern, 'string' )
+
+ local re, capt = gmatch_init( s, pattern )
+ local pos = 0
+ return function()
+ local ret
+ pos, ret = gmatch_callback( s, re, capt, pos )
+ return unpack( ret )
+ end, nil, nil
+end
+
+local gcodepoint_init = nil
+local function php_gcodepoint( s, i, j )
+ checkType( 'gcodepoint', 1, s, 'string' )
+ checkType( 'gcodepoint', 2, i, 'number', true )
+ checkType( 'gcodepoint', 3, j, 'number', true )
+ local cp = gcodepoint_init( s, i, j or -1 )
+ local pos, len = 1, #cp
+ return function ()
+ if pos <= len then
+ local tmp = cp[pos]
+ pos = pos + 1
+ return tmp
+ end
+ end
+end
+
+function ustring.setupInterface( opt )
+ -- Boilerplate
+ ustring.setupInterface = nil
+
+ -- Set string limits
+ ustring.maxStringLength = opt.stringLengthLimit
+ ustring.maxPatternLength = opt.patternLengthLimit
+
+ -- Gmatch
+ if mw_interface.gmatch_callback and mw_interface.gmatch_init then
+ gmatch_init = mw_interface.gmatch_init
+ gmatch_callback = mw_interface.gmatch_callback
+ ustring.gmatch = php_gmatch
+ end
+ mw_interface.gmatch_init = nil
+ mw_interface.gmatch_callback = nil
+
+ -- codepoint and gcodepoint
+ if mw_interface.gcodepoint_init then
+ gcodepoint_init = mw_interface.gcodepoint_init
+ ustring.gcodepoint = php_gcodepoint
+ end
+ mw_interface.gcodepoint_init = nil
+
+ -- Replace pure-lua implementation with php callbacks
+ local nargs = {
+ char = 0,
+ find = 2,
+ match = 2,
+ gsub = 3,
+ }
+ for k, v in pairs( mw_interface ) do
+ local n = nargs[k] or 1
+ if n == 0 then
+ ustring[k] = v
+ else
+ -- Avoid PHP warnings for missing arguments by checking before
+ -- calling PHP.
+ ustring[k] = function ( ... )
+ if select( '#', ... ) < n then
+ error( "too few arguments to mw.ustring." .. k, 2 )
+ end
+ return v( ... )
+ end
+ end
+ end
+ mw_interface = nil
+
+ -- Replace upper/lower with mw.language versions if available
+ if mw and mw.language then
+ local lang = mw.language.getContentLanguage()
+ ustring.upper = function ( s )
+ return lang:uc( s )
+ end
+ ustring.lower = function ( s )
+ return lang:lc( s )
+ end
+ end
+
+ -- Register this library in the "mw" global
+ mw = mw or {}
+ mw.ustring = ustring
+
+ package.loaded['mw.ustring'] = ustring
+end
+
+return ustring
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mwInit.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mwInit.lua
new file mode 100644
index 00000000..c1667efb
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/mwInit.lua
@@ -0,0 +1,143 @@
+-- This file is for anything that needs to be set up before a Lua engine can
+-- start. Things in this file may run more than once, so avoid putting anything
+-- other than function definitions in it. Also, because this can run before
+-- PHP can do anything, mw_interface is unavailable here.
+
+mw = mw or {}
+
+-- Extend pairs and ipairs to recognize __pairs and __ipairs, if they don't already
+do
+ local t = {}
+ setmetatable( t, { __pairs = function() return 1, 2, 3 end } )
+ local f = pairs( t )
+ if f ~= 1 then
+ local old_pairs = pairs
+ pairs = function ( t )
+ local mt = getmetatable( t )
+ local f, s, var = ( mt and mt.__pairs or old_pairs )( t )
+ return f, s, var
+ end
+ local old_ipairs = ipairs
+ ipairs = function ( t )
+ local mt = getmetatable( t )
+ local f, s, var = ( mt and mt.__ipairs or old_ipairs )( t )
+ return f, s, var
+ end
+ end
+end
+
+-- Reduce precision on os.clock to mitigate timing attacks
+do
+ local old_clock = os.clock
+ os.clock = function ()
+ local v = old_clock()
+ return math.floor( v * 50000 + 0.5 ) / 50000
+ end
+end
+
+--- Do a "deep copy" of a table or other value.
+function mw.clone( val )
+ local tableRefs = {}
+ local function recursiveClone( val )
+ if type( val ) == 'table' then
+ -- Encode circular references correctly
+ if tableRefs[val] ~= nil then
+ return tableRefs[val]
+ end
+
+ local retVal
+ retVal = {}
+ tableRefs[val] = retVal
+
+ -- Copy metatable
+ if getmetatable( val ) then
+ setmetatable( retVal, recursiveClone( getmetatable( val ) ) )
+ end
+
+ for key, elt in pairs( val ) do
+ retVal[key] = recursiveClone( elt )
+ end
+ return retVal
+ else
+ return val
+ end
+ end
+ return recursiveClone( val )
+end
+
+--- Make isolation-safe setfenv and getfenv functions
+--
+-- @param protectedEnvironments A table where the keys are protected environment
+-- tables. These environments cannot be accessed with getfenv(), and
+-- functions with these environments cannot be modified or accessed using
+-- integer indexes to setfenv(). However, functions with these environments
+-- can have their environment set with setfenv() with a function value
+-- argument.
+--
+-- @param protectedFunctions A table where the keys are protected functions,
+-- which cannot have their environments set by setfenv() with a function
+-- value argument.
+--
+-- @return setfenv
+-- @return getfenv
+function mw.makeProtectedEnvFuncs( protectedEnvironments, protectedFunctions )
+ local old_setfenv = setfenv
+ local old_getfenv = getfenv
+
+ local function my_setfenv( func, newEnv )
+ if type( func ) == 'number' then
+ local stackIndex = math.floor( func )
+ if stackIndex <= 0 then
+ error( "'setfenv' cannot set the global environment, it is protected", 2 )
+ end
+ if stackIndex > 10 then
+ error( "'setfenv' cannot set an environment at a level greater than 10", 2 )
+ end
+
+ -- Add one because we are still in Lua and 1 is right here
+ stackIndex = stackIndex + 1
+
+ local env = old_getfenv( stackIndex )
+ if env == nil or protectedEnvironments[ env ] then
+ error( "'setfenv' cannot set the requested environment, it is protected", 2 )
+ end
+ func = old_setfenv( stackIndex, newEnv )
+ elseif type( func ) == 'function' then
+ if protectedFunctions[func] then
+ error( "'setfenv' cannot be called on a protected function", 2 )
+ end
+ local env = old_getfenv( func )
+ if env == nil or protectedEnvironments[ env ] then
+ error( "'setfenv' cannot set the requested environment, it is protected", 2 )
+ end
+ old_setfenv( func, newEnv )
+ else
+ error( "'setfenv' can only be called with a function or integer as the first argument", 2 )
+ end
+ return func
+ end
+
+ local function my_getfenv( func )
+ local env
+ if type( func ) == 'number' then
+ if func <= 0 then
+ error( "'getfenv' cannot get the global environment" )
+ end
+ env = old_getfenv( func + 1 )
+ elseif type( func ) == 'function' then
+ env = old_getfenv( func )
+ else
+ error( "'getfenv' cannot get the global environment" )
+ end
+
+ if protectedEnvironments[env] then
+ return nil
+ else
+ return env
+ end
+ end
+
+ return my_setfenv, my_getfenv
+end
+
+return mw
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/package.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/package.lua
new file mode 100644
index 00000000..572e5931
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/package.lua
@@ -0,0 +1,127 @@
+--[[
+-- A package library similar to the one that comes with Lua 5.1, but without
+-- the local filesystem access. Based on Compat-5.1 which comes with the
+-- following license notice:
+--
+-- Copyright © 2004-2006 The Kepler Project.
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy of
+-- this software and associated documentation files (the "Software"), to deal in
+-- the Software without restriction, including without limitation the rights to
+-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+-- the Software, and to permit persons to whom the Software is furnished to do so,
+-- subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in all
+-- copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+-- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+-- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+-- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+-- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--]]
+
+
+local assert, error, ipairs, setmetatable, type = assert, error, ipairs, setmetatable, type
+local format = string.format
+
+--
+-- avoid overwriting the package table if it's already there
+--
+package = package or {}
+local _PACKAGE = package
+
+package.loaded = package.loaded or {}
+package.loaded.debug = debug
+package.loaded.string = string
+package.loaded.math = math
+package.loaded.io = io
+package.loaded.os = os
+package.loaded.table = table
+package.loaded._G = _G
+package.loaded.coroutine = coroutine
+package.loaded.package = package
+local _LOADED = package.loaded
+
+--
+-- avoid overwriting the package.preload table if it's already there
+--
+package.preload = package.preload or {}
+local _PRELOAD = package.preload
+
+--
+-- check whether library is already loaded
+--
+local function loader_preload (name)
+ assert (type(name) == "string", format (
+ "bad argument #1 to 'require' (string expected, got %s)", type(name)))
+ assert (type(_PRELOAD) == "table", "'package.preload' must be a table")
+ return _PRELOAD[name]
+end
+
+-- create 'loaders' table
+package.loaders = package.loaders or { loader_preload }
+local _LOADERS = package.loaders
+
+--
+-- iterate over available loaders
+--
+local function load (name, loaders)
+ -- iterate over available loaders
+ assert (type (loaders) == "table", "'package.loaders' must be a table")
+ for i, loader in ipairs (loaders) do
+ local f = loader (name)
+ if f then
+ return f
+ end
+ end
+ error (format ("module '%s' not found", name))
+end
+
+-- sentinel
+local sentinel = function () end
+
+--
+-- require
+--
+function _G.require (modname)
+ assert (type(modname) == "string", format (
+ "bad argument #1 to 'require' (string expected, got %s)", type(modname)))
+ local p = _LOADED[modname]
+ if p then -- is it there?
+ if p == sentinel then
+ error (format ("loop or previous error loading module '%s'", modname))
+ end
+ return p -- package is already loaded
+ end
+ local init = load (modname, _LOADERS)
+ _LOADED[modname] = sentinel
+ local actual_arg = _G.arg
+ _G.arg = { modname }
+ local res = init (modname)
+ if res then
+ _LOADED[modname] = res
+ end
+ _G.arg = actual_arg
+ if _LOADED[modname] == sentinel then
+ _LOADED[modname] = true
+ end
+ return _LOADED[modname]
+end
+
+
+--
+-- package.seeall function
+--
+function _PACKAGE.seeall (module)
+ local t = type(module)
+ assert (t == "table", "bad argument #1 to package.seeall (table expected, got "..t..")")
+ local meta = getmetatable (module)
+ if not meta then
+ meta = {}
+ setmetatable (module, meta)
+ end
+ meta.__index = _G
+end
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/README b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/README
new file mode 100644
index 00000000..d211589f
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/README
@@ -0,0 +1,51 @@
+This is ustring, a pure-Lua library to handle UTF-8 strings.
+
+It implements generally the same interface as the standard string library, with
+the following differences:
+* Most functions work on codepoints rather than bytes or characters. Yes, this
+ means that even though "á" and "á" should appear identical and represent the
+ same character, the former is one codepoint (U+00E1) while the latter is two
+ (U+0061 U+0301).
+* Added functions isutf8, byteoffset, codepoint, gcodepoint, toNFC, toNFD.
+* No workalike for string.reverse is provided.
+
+Contents:
+* README - This file.
+* ustring.lua - The main file for the library.
+* string.lua - Extend the string metatable with methods from this library.
+* upper.lua - Data table for ustring.upper.
+* lower.lua - Data table for ustring.lower.
+* charsets.lua - Data tables for pattern matching functions.
+* make-tables.php - Regenerate upper.lua and lower.lua using PHP's multibyte
+ string library, and charsets.lua using PCRE.
+* normalization-data.lua - Data tables for toNFC and toNFD.
+* make-normalization-table.php - Regenerate normalization-data.lua based on the
+ file includes/libs/normal/UtfNormalData.inc from MediaWiki core.
+
+
+This library (consisting of the files described above) is released under the MIT
+License:
+
+Copyright (C) 2012 Brad Jorsch <bjorsch@wikimedia.org>
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/charsets.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/charsets.lua
new file mode 100644
index 00000000..7c0d98db
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/charsets.lua
@@ -0,0 +1,3117 @@
+-- This file is automatically generated by make-tables.php
+local pats = {
+ [0x61] = {
+ [0x0000aa] = 1,
+ [0x0000ba] = 1,
+ [0x0001bb] = 1,
+ [0x0001c0] = 1,
+ [0x0001c1] = 1,
+ [0x0001c2] = 1,
+ [0x0001c3] = 1,
+ [0x0001c5] = 1,
+ [0x0001c8] = 1,
+ [0x0001cb] = 1,
+ [0x0001f2] = 1,
+ [0x000294] = 1,
+ [0x0002e0] = 1,
+ [0x0002e1] = 1,
+ [0x0002e2] = 1,
+ [0x0002e3] = 1,
+ [0x0002e4] = 1,
+ [0x0002ec] = 1,
+ [0x0002ee] = 1,
+ [0x000374] = 1,
+ [0x00037a] = 1,
+ [0x000559] = 1,
+ [0x0005f0] = 1,
+ [0x0005f1] = 1,
+ [0x0005f2] = 1,
+ [0x00066e] = 1,
+ [0x00066f] = 1,
+ [0x0006d5] = 1,
+ [0x0006e5] = 1,
+ [0x0006e6] = 1,
+ [0x0006ee] = 1,
+ [0x0006ef] = 1,
+ [0x0006fa] = 1,
+ [0x0006fb] = 1,
+ [0x0006fc] = 1,
+ [0x0006ff] = 1,
+ [0x000710] = 1,
+ [0x0007b1] = 1,
+ [0x0007f4] = 1,
+ [0x0007f5] = 1,
+ [0x0007fa] = 1,
+ [0x00081a] = 1,
+ [0x000824] = 1,
+ [0x000828] = 1,
+ [0x0008a0] = 1,
+ [0x00093d] = 1,
+ [0x000950] = 1,
+ [0x000971] = 1,
+ [0x000972] = 1,
+ [0x000973] = 1,
+ [0x000974] = 1,
+ [0x000975] = 1,
+ [0x000976] = 1,
+ [0x000977] = 1,
+ [0x000979] = 1,
+ [0x00097a] = 1,
+ [0x00097b] = 1,
+ [0x00097c] = 1,
+ [0x00097d] = 1,
+ [0x00097e] = 1,
+ [0x00097f] = 1,
+ [0x000985] = 1,
+ [0x000986] = 1,
+ [0x000987] = 1,
+ [0x000988] = 1,
+ [0x000989] = 1,
+ [0x00098a] = 1,
+ [0x00098b] = 1,
+ [0x00098c] = 1,
+ [0x00098f] = 1,
+ [0x000990] = 1,
+ [0x0009aa] = 1,
+ [0x0009ab] = 1,
+ [0x0009ac] = 1,
+ [0x0009ad] = 1,
+ [0x0009ae] = 1,
+ [0x0009af] = 1,
+ [0x0009b0] = 1,
+ [0x0009b2] = 1,
+ [0x0009b6] = 1,
+ [0x0009b7] = 1,
+ [0x0009b8] = 1,
+ [0x0009b9] = 1,
+ [0x0009bd] = 1,
+ [0x0009ce] = 1,
+ [0x0009dc] = 1,
+ [0x0009dd] = 1,
+ [0x0009df] = 1,
+ [0x0009e0] = 1,
+ [0x0009e1] = 1,
+ [0x0009f0] = 1,
+ [0x0009f1] = 1,
+ [0x000a05] = 1,
+ [0x000a06] = 1,
+ [0x000a07] = 1,
+ [0x000a08] = 1,
+ [0x000a09] = 1,
+ [0x000a0a] = 1,
+ [0x000a0f] = 1,
+ [0x000a10] = 1,
+ [0x000a2a] = 1,
+ [0x000a2b] = 1,
+ [0x000a2c] = 1,
+ [0x000a2d] = 1,
+ [0x000a2e] = 1,
+ [0x000a2f] = 1,
+ [0x000a30] = 1,
+ [0x000a32] = 1,
+ [0x000a33] = 1,
+ [0x000a35] = 1,
+ [0x000a36] = 1,
+ [0x000a38] = 1,
+ [0x000a39] = 1,
+ [0x000a59] = 1,
+ [0x000a5a] = 1,
+ [0x000a5b] = 1,
+ [0x000a5c] = 1,
+ [0x000a5e] = 1,
+ [0x000a72] = 1,
+ [0x000a73] = 1,
+ [0x000a74] = 1,
+ [0x000a85] = 1,
+ [0x000a86] = 1,
+ [0x000a87] = 1,
+ [0x000a88] = 1,
+ [0x000a89] = 1,
+ [0x000a8a] = 1,
+ [0x000a8b] = 1,
+ [0x000a8c] = 1,
+ [0x000a8d] = 1,
+ [0x000a8f] = 1,
+ [0x000a90] = 1,
+ [0x000a91] = 1,
+ [0x000aaa] = 1,
+ [0x000aab] = 1,
+ [0x000aac] = 1,
+ [0x000aad] = 1,
+ [0x000aae] = 1,
+ [0x000aaf] = 1,
+ [0x000ab0] = 1,
+ [0x000ab2] = 1,
+ [0x000ab3] = 1,
+ [0x000ab5] = 1,
+ [0x000ab6] = 1,
+ [0x000ab7] = 1,
+ [0x000ab8] = 1,
+ [0x000ab9] = 1,
+ [0x000abd] = 1,
+ [0x000ad0] = 1,
+ [0x000ae0] = 1,
+ [0x000ae1] = 1,
+ [0x000b05] = 1,
+ [0x000b06] = 1,
+ [0x000b07] = 1,
+ [0x000b08] = 1,
+ [0x000b09] = 1,
+ [0x000b0a] = 1,
+ [0x000b0b] = 1,
+ [0x000b0c] = 1,
+ [0x000b0f] = 1,
+ [0x000b10] = 1,
+ [0x000b2a] = 1,
+ [0x000b2b] = 1,
+ [0x000b2c] = 1,
+ [0x000b2d] = 1,
+ [0x000b2e] = 1,
+ [0x000b2f] = 1,
+ [0x000b30] = 1,
+ [0x000b32] = 1,
+ [0x000b33] = 1,
+ [0x000b35] = 1,
+ [0x000b36] = 1,
+ [0x000b37] = 1,
+ [0x000b38] = 1,
+ [0x000b39] = 1,
+ [0x000b3d] = 1,
+ [0x000b5c] = 1,
+ [0x000b5d] = 1,
+ [0x000b5f] = 1,
+ [0x000b60] = 1,
+ [0x000b61] = 1,
+ [0x000b71] = 1,
+ [0x000b83] = 1,
+ [0x000b85] = 1,
+ [0x000b86] = 1,
+ [0x000b87] = 1,
+ [0x000b88] = 1,
+ [0x000b89] = 1,
+ [0x000b8a] = 1,
+ [0x000b8e] = 1,
+ [0x000b8f] = 1,
+ [0x000b90] = 1,
+ [0x000b92] = 1,
+ [0x000b93] = 1,
+ [0x000b94] = 1,
+ [0x000b95] = 1,
+ [0x000b99] = 1,
+ [0x000b9a] = 1,
+ [0x000b9c] = 1,
+ [0x000b9e] = 1,
+ [0x000b9f] = 1,
+ [0x000ba3] = 1,
+ [0x000ba4] = 1,
+ [0x000ba8] = 1,
+ [0x000ba9] = 1,
+ [0x000baa] = 1,
+ [0x000bd0] = 1,
+ [0x000c05] = 1,
+ [0x000c06] = 1,
+ [0x000c07] = 1,
+ [0x000c08] = 1,
+ [0x000c09] = 1,
+ [0x000c0a] = 1,
+ [0x000c0b] = 1,
+ [0x000c0c] = 1,
+ [0x000c0e] = 1,
+ [0x000c0f] = 1,
+ [0x000c10] = 1,
+ [0x000c35] = 1,
+ [0x000c36] = 1,
+ [0x000c37] = 1,
+ [0x000c38] = 1,
+ [0x000c39] = 1,
+ [0x000c3d] = 1,
+ [0x000c58] = 1,
+ [0x000c59] = 1,
+ [0x000c60] = 1,
+ [0x000c61] = 1,
+ [0x000c85] = 1,
+ [0x000c86] = 1,
+ [0x000c87] = 1,
+ [0x000c88] = 1,
+ [0x000c89] = 1,
+ [0x000c8a] = 1,
+ [0x000c8b] = 1,
+ [0x000c8c] = 1,
+ [0x000c8e] = 1,
+ [0x000c8f] = 1,
+ [0x000c90] = 1,
+ [0x000cb5] = 1,
+ [0x000cb6] = 1,
+ [0x000cb7] = 1,
+ [0x000cb8] = 1,
+ [0x000cb9] = 1,
+ [0x000cbd] = 1,
+ [0x000cde] = 1,
+ [0x000ce0] = 1,
+ [0x000ce1] = 1,
+ [0x000cf1] = 1,
+ [0x000cf2] = 1,
+ [0x000d05] = 1,
+ [0x000d06] = 1,
+ [0x000d07] = 1,
+ [0x000d08] = 1,
+ [0x000d09] = 1,
+ [0x000d0a] = 1,
+ [0x000d0b] = 1,
+ [0x000d0c] = 1,
+ [0x000d0e] = 1,
+ [0x000d0f] = 1,
+ [0x000d10] = 1,
+ [0x000d3d] = 1,
+ [0x000d4e] = 1,
+ [0x000d60] = 1,
+ [0x000d61] = 1,
+ [0x000d7a] = 1,
+ [0x000d7b] = 1,
+ [0x000d7c] = 1,
+ [0x000d7d] = 1,
+ [0x000d7e] = 1,
+ [0x000d7f] = 1,
+ [0x000db3] = 1,
+ [0x000db4] = 1,
+ [0x000db5] = 1,
+ [0x000db6] = 1,
+ [0x000db7] = 1,
+ [0x000db8] = 1,
+ [0x000db9] = 1,
+ [0x000dba] = 1,
+ [0x000dbb] = 1,
+ [0x000dbd] = 1,
+ [0x000dc0] = 1,
+ [0x000dc1] = 1,
+ [0x000dc2] = 1,
+ [0x000dc3] = 1,
+ [0x000dc4] = 1,
+ [0x000dc5] = 1,
+ [0x000dc6] = 1,
+ [0x000e32] = 1,
+ [0x000e33] = 1,
+ [0x000e40] = 1,
+ [0x000e41] = 1,
+ [0x000e42] = 1,
+ [0x000e43] = 1,
+ [0x000e44] = 1,
+ [0x000e45] = 1,
+ [0x000e46] = 1,
+ [0x000e81] = 1,
+ [0x000e82] = 1,
+ [0x000e84] = 1,
+ [0x000e87] = 1,
+ [0x000e88] = 1,
+ [0x000e8a] = 1,
+ [0x000e8d] = 1,
+ [0x000e94] = 1,
+ [0x000e95] = 1,
+ [0x000e96] = 1,
+ [0x000e97] = 1,
+ [0x000e99] = 1,
+ [0x000e9a] = 1,
+ [0x000e9b] = 1,
+ [0x000e9c] = 1,
+ [0x000e9d] = 1,
+ [0x000e9e] = 1,
+ [0x000e9f] = 1,
+ [0x000ea1] = 1,
+ [0x000ea2] = 1,
+ [0x000ea3] = 1,
+ [0x000ea5] = 1,
+ [0x000ea7] = 1,
+ [0x000eaa] = 1,
+ [0x000eab] = 1,
+ [0x000ead] = 1,
+ [0x000eae] = 1,
+ [0x000eaf] = 1,
+ [0x000eb0] = 1,
+ [0x000eb2] = 1,
+ [0x000eb3] = 1,
+ [0x000ebd] = 1,
+ [0x000ec0] = 1,
+ [0x000ec1] = 1,
+ [0x000ec2] = 1,
+ [0x000ec3] = 1,
+ [0x000ec4] = 1,
+ [0x000ec6] = 1,
+ [0x000edc] = 1,
+ [0x000edd] = 1,
+ [0x000ede] = 1,
+ [0x000edf] = 1,
+ [0x000f00] = 1,
+ [0x000f40] = 1,
+ [0x000f41] = 1,
+ [0x000f42] = 1,
+ [0x000f43] = 1,
+ [0x000f44] = 1,
+ [0x000f45] = 1,
+ [0x000f46] = 1,
+ [0x000f47] = 1,
+ [0x000f88] = 1,
+ [0x000f89] = 1,
+ [0x000f8a] = 1,
+ [0x000f8b] = 1,
+ [0x000f8c] = 1,
+ [0x00103f] = 1,
+ [0x001050] = 1,
+ [0x001051] = 1,
+ [0x001052] = 1,
+ [0x001053] = 1,
+ [0x001054] = 1,
+ [0x001055] = 1,
+ [0x00105a] = 1,
+ [0x00105b] = 1,
+ [0x00105c] = 1,
+ [0x00105d] = 1,
+ [0x001061] = 1,
+ [0x001065] = 1,
+ [0x001066] = 1,
+ [0x00106e] = 1,
+ [0x00106f] = 1,
+ [0x001070] = 1,
+ [0x00108e] = 1,
+ [0x00124a] = 1,
+ [0x00124b] = 1,
+ [0x00124c] = 1,
+ [0x00124d] = 1,
+ [0x001250] = 1,
+ [0x001251] = 1,
+ [0x001252] = 1,
+ [0x001253] = 1,
+ [0x001254] = 1,
+ [0x001255] = 1,
+ [0x001256] = 1,
+ [0x001258] = 1,
+ [0x00125a] = 1,
+ [0x00125b] = 1,
+ [0x00125c] = 1,
+ [0x00125d] = 1,
+ [0x00128a] = 1,
+ [0x00128b] = 1,
+ [0x00128c] = 1,
+ [0x00128d] = 1,
+ [0x0012b2] = 1,
+ [0x0012b3] = 1,
+ [0x0012b4] = 1,
+ [0x0012b5] = 1,
+ [0x0012b8] = 1,
+ [0x0012b9] = 1,
+ [0x0012ba] = 1,
+ [0x0012bb] = 1,
+ [0x0012bc] = 1,
+ [0x0012bd] = 1,
+ [0x0012be] = 1,
+ [0x0012c0] = 1,
+ [0x0012c2] = 1,
+ [0x0012c3] = 1,
+ [0x0012c4] = 1,
+ [0x0012c5] = 1,
+ [0x001312] = 1,
+ [0x001313] = 1,
+ [0x001314] = 1,
+ [0x001315] = 1,
+ [0x00170e] = 1,
+ [0x00170f] = 1,
+ [0x001710] = 1,
+ [0x001711] = 1,
+ [0x00176e] = 1,
+ [0x00176f] = 1,
+ [0x001770] = 1,
+ [0x0017d7] = 1,
+ [0x0017dc] = 1,
+ [0x0018aa] = 1,
+ [0x001970] = 1,
+ [0x001971] = 1,
+ [0x001972] = 1,
+ [0x001973] = 1,
+ [0x001974] = 1,
+ [0x0019c1] = 1,
+ [0x0019c2] = 1,
+ [0x0019c3] = 1,
+ [0x0019c4] = 1,
+ [0x0019c5] = 1,
+ [0x0019c6] = 1,
+ [0x0019c7] = 1,
+ [0x001aa7] = 1,
+ [0x001b45] = 1,
+ [0x001b46] = 1,
+ [0x001b47] = 1,
+ [0x001b48] = 1,
+ [0x001b49] = 1,
+ [0x001b4a] = 1,
+ [0x001b4b] = 1,
+ [0x001bae] = 1,
+ [0x001baf] = 1,
+ [0x001c4d] = 1,
+ [0x001c4e] = 1,
+ [0x001c4f] = 1,
+ [0x001ce9] = 1,
+ [0x001cea] = 1,
+ [0x001ceb] = 1,
+ [0x001cec] = 1,
+ [0x001cee] = 1,
+ [0x001cef] = 1,
+ [0x001cf0] = 1,
+ [0x001cf1] = 1,
+ [0x001cf5] = 1,
+ [0x001cf6] = 1,
+ [0x001d78] = 1,
+ [0x001f88] = 1,
+ [0x001f89] = 1,
+ [0x001f8a] = 1,
+ [0x001f8b] = 1,
+ [0x001f8c] = 1,
+ [0x001f8d] = 1,
+ [0x001f8e] = 1,
+ [0x001f8f] = 1,
+ [0x001f98] = 1,
+ [0x001f99] = 1,
+ [0x001f9a] = 1,
+ [0x001f9b] = 1,
+ [0x001f9c] = 1,
+ [0x001f9d] = 1,
+ [0x001f9e] = 1,
+ [0x001f9f] = 1,
+ [0x001fa8] = 1,
+ [0x001fa9] = 1,
+ [0x001faa] = 1,
+ [0x001fab] = 1,
+ [0x001fac] = 1,
+ [0x001fad] = 1,
+ [0x001fae] = 1,
+ [0x001faf] = 1,
+ [0x001fbc] = 1,
+ [0x001fcc] = 1,
+ [0x001ffc] = 1,
+ [0x002071] = 1,
+ [0x00207f] = 1,
+ [0x002135] = 1,
+ [0x002136] = 1,
+ [0x002137] = 1,
+ [0x002138] = 1,
+ [0x002c7c] = 1,
+ [0x002c7d] = 1,
+ [0x002d6f] = 1,
+ [0x002da0] = 1,
+ [0x002da1] = 1,
+ [0x002da2] = 1,
+ [0x002da3] = 1,
+ [0x002da4] = 1,
+ [0x002da5] = 1,
+ [0x002da6] = 1,
+ [0x002da8] = 1,
+ [0x002da9] = 1,
+ [0x002daa] = 1,
+ [0x002dab] = 1,
+ [0x002dac] = 1,
+ [0x002dad] = 1,
+ [0x002dae] = 1,
+ [0x002db0] = 1,
+ [0x002db1] = 1,
+ [0x002db2] = 1,
+ [0x002db3] = 1,
+ [0x002db4] = 1,
+ [0x002db5] = 1,
+ [0x002db6] = 1,
+ [0x002db8] = 1,
+ [0x002db9] = 1,
+ [0x002dba] = 1,
+ [0x002dbb] = 1,
+ [0x002dbc] = 1,
+ [0x002dbd] = 1,
+ [0x002dbe] = 1,
+ [0x002dc0] = 1,
+ [0x002dc1] = 1,
+ [0x002dc2] = 1,
+ [0x002dc3] = 1,
+ [0x002dc4] = 1,
+ [0x002dc5] = 1,
+ [0x002dc6] = 1,
+ [0x002dc8] = 1,
+ [0x002dc9] = 1,
+ [0x002dca] = 1,
+ [0x002dcb] = 1,
+ [0x002dcc] = 1,
+ [0x002dcd] = 1,
+ [0x002dce] = 1,
+ [0x002dd0] = 1,
+ [0x002dd1] = 1,
+ [0x002dd2] = 1,
+ [0x002dd3] = 1,
+ [0x002dd4] = 1,
+ [0x002dd5] = 1,
+ [0x002dd6] = 1,
+ [0x002dd8] = 1,
+ [0x002dd9] = 1,
+ [0x002dda] = 1,
+ [0x002ddb] = 1,
+ [0x002ddc] = 1,
+ [0x002ddd] = 1,
+ [0x002dde] = 1,
+ [0x002e2f] = 1,
+ [0x003005] = 1,
+ [0x003006] = 1,
+ [0x003031] = 1,
+ [0x003032] = 1,
+ [0x003033] = 1,
+ [0x003034] = 1,
+ [0x003035] = 1,
+ [0x00303b] = 1,
+ [0x00303c] = 1,
+ [0x00309d] = 1,
+ [0x00309e] = 1,
+ [0x00309f] = 1,
+ [0x0030fc] = 1,
+ [0x0030fd] = 1,
+ [0x0030fe] = 1,
+ [0x0030ff] = 1,
+ [0x00a62a] = 1,
+ [0x00a62b] = 1,
+ [0x00a66e] = 1,
+ [0x00a67f] = 1,
+ [0x00a717] = 1,
+ [0x00a718] = 1,
+ [0x00a719] = 1,
+ [0x00a71a] = 1,
+ [0x00a71b] = 1,
+ [0x00a71c] = 1,
+ [0x00a71d] = 1,
+ [0x00a71e] = 1,
+ [0x00a71f] = 1,
+ [0x00a770] = 1,
+ [0x00a788] = 1,
+ [0x00a7f8] = 1,
+ [0x00a7f9] = 1,
+ [0x00a7fb] = 1,
+ [0x00a7fc] = 1,
+ [0x00a7fd] = 1,
+ [0x00a7fe] = 1,
+ [0x00a7ff] = 1,
+ [0x00a800] = 1,
+ [0x00a801] = 1,
+ [0x00a803] = 1,
+ [0x00a804] = 1,
+ [0x00a805] = 1,
+ [0x00a807] = 1,
+ [0x00a808] = 1,
+ [0x00a809] = 1,
+ [0x00a80a] = 1,
+ [0x00a8f2] = 1,
+ [0x00a8f3] = 1,
+ [0x00a8f4] = 1,
+ [0x00a8f5] = 1,
+ [0x00a8f6] = 1,
+ [0x00a8f7] = 1,
+ [0x00a8fb] = 1,
+ [0x00a9cf] = 1,
+ [0x00aa40] = 1,
+ [0x00aa41] = 1,
+ [0x00aa42] = 1,
+ [0x00aa44] = 1,
+ [0x00aa45] = 1,
+ [0x00aa46] = 1,
+ [0x00aa47] = 1,
+ [0x00aa48] = 1,
+ [0x00aa49] = 1,
+ [0x00aa4a] = 1,
+ [0x00aa4b] = 1,
+ [0x00aa7a] = 1,
+ [0x00aab1] = 1,
+ [0x00aab5] = 1,
+ [0x00aab6] = 1,
+ [0x00aab9] = 1,
+ [0x00aaba] = 1,
+ [0x00aabb] = 1,
+ [0x00aabc] = 1,
+ [0x00aabd] = 1,
+ [0x00aac0] = 1,
+ [0x00aac2] = 1,
+ [0x00aadb] = 1,
+ [0x00aadc] = 1,
+ [0x00aadd] = 1,
+ [0x00aaf2] = 1,
+ [0x00aaf3] = 1,
+ [0x00aaf4] = 1,
+ [0x00ab01] = 1,
+ [0x00ab02] = 1,
+ [0x00ab03] = 1,
+ [0x00ab04] = 1,
+ [0x00ab05] = 1,
+ [0x00ab06] = 1,
+ [0x00ab09] = 1,
+ [0x00ab0a] = 1,
+ [0x00ab0b] = 1,
+ [0x00ab0c] = 1,
+ [0x00ab0d] = 1,
+ [0x00ab0e] = 1,
+ [0x00ab11] = 1,
+ [0x00ab12] = 1,
+ [0x00ab13] = 1,
+ [0x00ab14] = 1,
+ [0x00ab15] = 1,
+ [0x00ab16] = 1,
+ [0x00ab20] = 1,
+ [0x00ab21] = 1,
+ [0x00ab22] = 1,
+ [0x00ab23] = 1,
+ [0x00ab24] = 1,
+ [0x00ab25] = 1,
+ [0x00ab26] = 1,
+ [0x00ab28] = 1,
+ [0x00ab29] = 1,
+ [0x00ab2a] = 1,
+ [0x00ab2b] = 1,
+ [0x00ab2c] = 1,
+ [0x00ab2d] = 1,
+ [0x00ab2e] = 1,
+ [0x00fb1d] = 1,
+ [0x00fb38] = 1,
+ [0x00fb39] = 1,
+ [0x00fb3a] = 1,
+ [0x00fb3b] = 1,
+ [0x00fb3c] = 1,
+ [0x00fb3e] = 1,
+ [0x00fb40] = 1,
+ [0x00fb41] = 1,
+ [0x00fb43] = 1,
+ [0x00fb44] = 1,
+ [0x00fe70] = 1,
+ [0x00fe71] = 1,
+ [0x00fe72] = 1,
+ [0x00fe73] = 1,
+ [0x00fe74] = 1,
+ [0x00ffc2] = 1,
+ [0x00ffc3] = 1,
+ [0x00ffc4] = 1,
+ [0x00ffc5] = 1,
+ [0x00ffc6] = 1,
+ [0x00ffc7] = 1,
+ [0x00ffca] = 1,
+ [0x00ffcb] = 1,
+ [0x00ffcc] = 1,
+ [0x00ffcd] = 1,
+ [0x00ffce] = 1,
+ [0x00ffcf] = 1,
+ [0x00ffd2] = 1,
+ [0x00ffd3] = 1,
+ [0x00ffd4] = 1,
+ [0x00ffd5] = 1,
+ [0x00ffd6] = 1,
+ [0x00ffd7] = 1,
+ [0x00ffda] = 1,
+ [0x00ffdb] = 1,
+ [0x00ffdc] = 1,
+ [0x01003c] = 1,
+ [0x01003d] = 1,
+ [0x010342] = 1,
+ [0x010343] = 1,
+ [0x010344] = 1,
+ [0x010345] = 1,
+ [0x010346] = 1,
+ [0x010347] = 1,
+ [0x010348] = 1,
+ [0x010349] = 1,
+ [0x0103c8] = 1,
+ [0x0103c9] = 1,
+ [0x0103ca] = 1,
+ [0x0103cb] = 1,
+ [0x0103cc] = 1,
+ [0x0103cd] = 1,
+ [0x0103ce] = 1,
+ [0x0103cf] = 1,
+ [0x010800] = 1,
+ [0x010801] = 1,
+ [0x010802] = 1,
+ [0x010803] = 1,
+ [0x010804] = 1,
+ [0x010805] = 1,
+ [0x010808] = 1,
+ [0x010837] = 1,
+ [0x010838] = 1,
+ [0x01083c] = 1,
+ [0x0109be] = 1,
+ [0x0109bf] = 1,
+ [0x010a00] = 1,
+ [0x010a10] = 1,
+ [0x010a11] = 1,
+ [0x010a12] = 1,
+ [0x010a13] = 1,
+ [0x010a15] = 1,
+ [0x010a16] = 1,
+ [0x010a17] = 1,
+ [0x0111c1] = 1,
+ [0x0111c2] = 1,
+ [0x0111c3] = 1,
+ [0x0111c4] = 1,
+ [0x016f50] = 1,
+ [0x01b000] = 1,
+ [0x01b001] = 1,
+ [0x01ee00] = 1,
+ [0x01ee01] = 1,
+ [0x01ee02] = 1,
+ [0x01ee03] = 1,
+ [0x01ee21] = 1,
+ [0x01ee22] = 1,
+ [0x01ee24] = 1,
+ [0x01ee27] = 1,
+ [0x01ee34] = 1,
+ [0x01ee35] = 1,
+ [0x01ee36] = 1,
+ [0x01ee37] = 1,
+ [0x01ee39] = 1,
+ [0x01ee3b] = 1,
+ [0x01ee42] = 1,
+ [0x01ee47] = 1,
+ [0x01ee49] = 1,
+ [0x01ee4b] = 1,
+ [0x01ee4d] = 1,
+ [0x01ee4e] = 1,
+ [0x01ee4f] = 1,
+ [0x01ee51] = 1,
+ [0x01ee52] = 1,
+ [0x01ee54] = 1,
+ [0x01ee57] = 1,
+ [0x01ee59] = 1,
+ [0x01ee5b] = 1,
+ [0x01ee5d] = 1,
+ [0x01ee5f] = 1,
+ [0x01ee61] = 1,
+ [0x01ee62] = 1,
+ [0x01ee64] = 1,
+ [0x01ee67] = 1,
+ [0x01ee68] = 1,
+ [0x01ee69] = 1,
+ [0x01ee6a] = 1,
+ [0x01ee6c] = 1,
+ [0x01ee6d] = 1,
+ [0x01ee6e] = 1,
+ [0x01ee6f] = 1,
+ [0x01ee70] = 1,
+ [0x01ee71] = 1,
+ [0x01ee72] = 1,
+ [0x01ee74] = 1,
+ [0x01ee75] = 1,
+ [0x01ee76] = 1,
+ [0x01ee77] = 1,
+ [0x01ee79] = 1,
+ [0x01ee7a] = 1,
+ [0x01ee7b] = 1,
+ [0x01ee7c] = 1,
+ [0x01ee7e] = 1,
+ [0x01eea1] = 1,
+ [0x01eea2] = 1,
+ [0x01eea3] = 1,
+ [0x01eea5] = 1,
+ [0x01eea6] = 1,
+ [0x01eea7] = 1,
+ [0x01eea8] = 1,
+ [0x01eea9] = 1,
+ },
+ [0x63] = {
+ },
+ [0x64] = {
+ [0x000030] = 1,
+ [0x000031] = 1,
+ [0x000032] = 1,
+ [0x000033] = 1,
+ [0x000034] = 1,
+ [0x000035] = 1,
+ [0x000036] = 1,
+ [0x000037] = 1,
+ [0x000038] = 1,
+ [0x000039] = 1,
+ },
+ [0x6c] = {
+ [0x000061] = 1,
+ [0x000062] = 1,
+ [0x000063] = 1,
+ [0x000064] = 1,
+ [0x000065] = 1,
+ [0x000066] = 1,
+ [0x000067] = 1,
+ [0x000068] = 1,
+ [0x000069] = 1,
+ [0x00006a] = 1,
+ [0x00006b] = 1,
+ [0x00006c] = 1,
+ [0x00006d] = 1,
+ [0x00006e] = 1,
+ [0x00006f] = 1,
+ [0x000070] = 1,
+ [0x000071] = 1,
+ [0x000072] = 1,
+ [0x000073] = 1,
+ [0x000074] = 1,
+ [0x000075] = 1,
+ [0x000076] = 1,
+ [0x000077] = 1,
+ [0x000078] = 1,
+ [0x000079] = 1,
+ [0x00007a] = 1,
+ [0x0000b5] = 1,
+ [0x0000f8] = 1,
+ [0x0000f9] = 1,
+ [0x0000fa] = 1,
+ [0x0000fb] = 1,
+ [0x0000fc] = 1,
+ [0x0000fd] = 1,
+ [0x0000fe] = 1,
+ [0x0000ff] = 1,
+ [0x000101] = 1,
+ [0x000103] = 1,
+ [0x000105] = 1,
+ [0x000107] = 1,
+ [0x000109] = 1,
+ [0x00010b] = 1,
+ [0x00010d] = 1,
+ [0x00010f] = 1,
+ [0x000111] = 1,
+ [0x000113] = 1,
+ [0x000115] = 1,
+ [0x000117] = 1,
+ [0x000119] = 1,
+ [0x00011b] = 1,
+ [0x00011d] = 1,
+ [0x00011f] = 1,
+ [0x000121] = 1,
+ [0x000123] = 1,
+ [0x000125] = 1,
+ [0x000127] = 1,
+ [0x000129] = 1,
+ [0x00012b] = 1,
+ [0x00012d] = 1,
+ [0x00012f] = 1,
+ [0x000131] = 1,
+ [0x000133] = 1,
+ [0x000135] = 1,
+ [0x000137] = 1,
+ [0x000138] = 1,
+ [0x00013a] = 1,
+ [0x00013c] = 1,
+ [0x00013e] = 1,
+ [0x000140] = 1,
+ [0x000142] = 1,
+ [0x000144] = 1,
+ [0x000146] = 1,
+ [0x000148] = 1,
+ [0x000149] = 1,
+ [0x00014b] = 1,
+ [0x00014d] = 1,
+ [0x00014f] = 1,
+ [0x000151] = 1,
+ [0x000153] = 1,
+ [0x000155] = 1,
+ [0x000157] = 1,
+ [0x000159] = 1,
+ [0x00015b] = 1,
+ [0x00015d] = 1,
+ [0x00015f] = 1,
+ [0x000161] = 1,
+ [0x000163] = 1,
+ [0x000165] = 1,
+ [0x000167] = 1,
+ [0x000169] = 1,
+ [0x00016b] = 1,
+ [0x00016d] = 1,
+ [0x00016f] = 1,
+ [0x000171] = 1,
+ [0x000173] = 1,
+ [0x000175] = 1,
+ [0x000177] = 1,
+ [0x00017a] = 1,
+ [0x00017c] = 1,
+ [0x00017e] = 1,
+ [0x00017f] = 1,
+ [0x000180] = 1,
+ [0x000183] = 1,
+ [0x000185] = 1,
+ [0x000188] = 1,
+ [0x00018c] = 1,
+ [0x00018d] = 1,
+ [0x000192] = 1,
+ [0x000195] = 1,
+ [0x000199] = 1,
+ [0x00019a] = 1,
+ [0x00019b] = 1,
+ [0x00019e] = 1,
+ [0x0001a1] = 1,
+ [0x0001a3] = 1,
+ [0x0001a5] = 1,
+ [0x0001a8] = 1,
+ [0x0001aa] = 1,
+ [0x0001ab] = 1,
+ [0x0001ad] = 1,
+ [0x0001b0] = 1,
+ [0x0001b4] = 1,
+ [0x0001b6] = 1,
+ [0x0001b9] = 1,
+ [0x0001ba] = 1,
+ [0x0001bd] = 1,
+ [0x0001be] = 1,
+ [0x0001bf] = 1,
+ [0x0001c6] = 1,
+ [0x0001c9] = 1,
+ [0x0001cc] = 1,
+ [0x0001ce] = 1,
+ [0x0001d0] = 1,
+ [0x0001d2] = 1,
+ [0x0001d4] = 1,
+ [0x0001d6] = 1,
+ [0x0001d8] = 1,
+ [0x0001da] = 1,
+ [0x0001dc] = 1,
+ [0x0001dd] = 1,
+ [0x0001df] = 1,
+ [0x0001e1] = 1,
+ [0x0001e3] = 1,
+ [0x0001e5] = 1,
+ [0x0001e7] = 1,
+ [0x0001e9] = 1,
+ [0x0001eb] = 1,
+ [0x0001ed] = 1,
+ [0x0001ef] = 1,
+ [0x0001f0] = 1,
+ [0x0001f3] = 1,
+ [0x0001f5] = 1,
+ [0x0001f9] = 1,
+ [0x0001fb] = 1,
+ [0x0001fd] = 1,
+ [0x0001ff] = 1,
+ [0x000201] = 1,
+ [0x000203] = 1,
+ [0x000205] = 1,
+ [0x000207] = 1,
+ [0x000209] = 1,
+ [0x00020b] = 1,
+ [0x00020d] = 1,
+ [0x00020f] = 1,
+ [0x000211] = 1,
+ [0x000213] = 1,
+ [0x000215] = 1,
+ [0x000217] = 1,
+ [0x000219] = 1,
+ [0x00021b] = 1,
+ [0x00021d] = 1,
+ [0x00021f] = 1,
+ [0x000221] = 1,
+ [0x000223] = 1,
+ [0x000225] = 1,
+ [0x000227] = 1,
+ [0x000229] = 1,
+ [0x00022b] = 1,
+ [0x00022d] = 1,
+ [0x00022f] = 1,
+ [0x000231] = 1,
+ [0x000233] = 1,
+ [0x000234] = 1,
+ [0x000235] = 1,
+ [0x000236] = 1,
+ [0x000237] = 1,
+ [0x000238] = 1,
+ [0x000239] = 1,
+ [0x00023c] = 1,
+ [0x00023f] = 1,
+ [0x000240] = 1,
+ [0x000242] = 1,
+ [0x000247] = 1,
+ [0x000249] = 1,
+ [0x00024b] = 1,
+ [0x00024d] = 1,
+ [0x000371] = 1,
+ [0x000373] = 1,
+ [0x000377] = 1,
+ [0x00037b] = 1,
+ [0x00037c] = 1,
+ [0x00037d] = 1,
+ [0x000390] = 1,
+ [0x0003d0] = 1,
+ [0x0003d1] = 1,
+ [0x0003d5] = 1,
+ [0x0003d6] = 1,
+ [0x0003d7] = 1,
+ [0x0003d9] = 1,
+ [0x0003db] = 1,
+ [0x0003dd] = 1,
+ [0x0003df] = 1,
+ [0x0003e1] = 1,
+ [0x0003e3] = 1,
+ [0x0003e5] = 1,
+ [0x0003e7] = 1,
+ [0x0003e9] = 1,
+ [0x0003eb] = 1,
+ [0x0003ed] = 1,
+ [0x0003ef] = 1,
+ [0x0003f0] = 1,
+ [0x0003f1] = 1,
+ [0x0003f2] = 1,
+ [0x0003f3] = 1,
+ [0x0003f5] = 1,
+ [0x0003f8] = 1,
+ [0x0003fb] = 1,
+ [0x0003fc] = 1,
+ [0x000461] = 1,
+ [0x000463] = 1,
+ [0x000465] = 1,
+ [0x000467] = 1,
+ [0x000469] = 1,
+ [0x00046b] = 1,
+ [0x00046d] = 1,
+ [0x00046f] = 1,
+ [0x000471] = 1,
+ [0x000473] = 1,
+ [0x000475] = 1,
+ [0x000477] = 1,
+ [0x000479] = 1,
+ [0x00047b] = 1,
+ [0x00047d] = 1,
+ [0x00047f] = 1,
+ [0x000481] = 1,
+ [0x00048b] = 1,
+ [0x00048d] = 1,
+ [0x00048f] = 1,
+ [0x000491] = 1,
+ [0x000493] = 1,
+ [0x000495] = 1,
+ [0x000497] = 1,
+ [0x000499] = 1,
+ [0x00049b] = 1,
+ [0x00049d] = 1,
+ [0x00049f] = 1,
+ [0x0004a1] = 1,
+ [0x0004a3] = 1,
+ [0x0004a5] = 1,
+ [0x0004a7] = 1,
+ [0x0004a9] = 1,
+ [0x0004ab] = 1,
+ [0x0004ad] = 1,
+ [0x0004af] = 1,
+ [0x0004b1] = 1,
+ [0x0004b3] = 1,
+ [0x0004b5] = 1,
+ [0x0004b7] = 1,
+ [0x0004b9] = 1,
+ [0x0004bb] = 1,
+ [0x0004bd] = 1,
+ [0x0004bf] = 1,
+ [0x0004c2] = 1,
+ [0x0004c4] = 1,
+ [0x0004c6] = 1,
+ [0x0004c8] = 1,
+ [0x0004ca] = 1,
+ [0x0004cc] = 1,
+ [0x0004ce] = 1,
+ [0x0004cf] = 1,
+ [0x0004d1] = 1,
+ [0x0004d3] = 1,
+ [0x0004d5] = 1,
+ [0x0004d7] = 1,
+ [0x0004d9] = 1,
+ [0x0004db] = 1,
+ [0x0004dd] = 1,
+ [0x0004df] = 1,
+ [0x0004e1] = 1,
+ [0x0004e3] = 1,
+ [0x0004e5] = 1,
+ [0x0004e7] = 1,
+ [0x0004e9] = 1,
+ [0x0004eb] = 1,
+ [0x0004ed] = 1,
+ [0x0004ef] = 1,
+ [0x0004f1] = 1,
+ [0x0004f3] = 1,
+ [0x0004f5] = 1,
+ [0x0004f7] = 1,
+ [0x0004f9] = 1,
+ [0x0004fb] = 1,
+ [0x0004fd] = 1,
+ [0x0004ff] = 1,
+ [0x000501] = 1,
+ [0x000503] = 1,
+ [0x000505] = 1,
+ [0x000507] = 1,
+ [0x000509] = 1,
+ [0x00050b] = 1,
+ [0x00050d] = 1,
+ [0x00050f] = 1,
+ [0x000511] = 1,
+ [0x000513] = 1,
+ [0x000515] = 1,
+ [0x000517] = 1,
+ [0x000519] = 1,
+ [0x00051b] = 1,
+ [0x00051d] = 1,
+ [0x00051f] = 1,
+ [0x000521] = 1,
+ [0x000523] = 1,
+ [0x000525] = 1,
+ [0x000527] = 1,
+ [0x001e01] = 1,
+ [0x001e03] = 1,
+ [0x001e05] = 1,
+ [0x001e07] = 1,
+ [0x001e09] = 1,
+ [0x001e0b] = 1,
+ [0x001e0d] = 1,
+ [0x001e0f] = 1,
+ [0x001e11] = 1,
+ [0x001e13] = 1,
+ [0x001e15] = 1,
+ [0x001e17] = 1,
+ [0x001e19] = 1,
+ [0x001e1b] = 1,
+ [0x001e1d] = 1,
+ [0x001e1f] = 1,
+ [0x001e21] = 1,
+ [0x001e23] = 1,
+ [0x001e25] = 1,
+ [0x001e27] = 1,
+ [0x001e29] = 1,
+ [0x001e2b] = 1,
+ [0x001e2d] = 1,
+ [0x001e2f] = 1,
+ [0x001e31] = 1,
+ [0x001e33] = 1,
+ [0x001e35] = 1,
+ [0x001e37] = 1,
+ [0x001e39] = 1,
+ [0x001e3b] = 1,
+ [0x001e3d] = 1,
+ [0x001e3f] = 1,
+ [0x001e41] = 1,
+ [0x001e43] = 1,
+ [0x001e45] = 1,
+ [0x001e47] = 1,
+ [0x001e49] = 1,
+ [0x001e4b] = 1,
+ [0x001e4d] = 1,
+ [0x001e4f] = 1,
+ [0x001e51] = 1,
+ [0x001e53] = 1,
+ [0x001e55] = 1,
+ [0x001e57] = 1,
+ [0x001e59] = 1,
+ [0x001e5b] = 1,
+ [0x001e5d] = 1,
+ [0x001e5f] = 1,
+ [0x001e61] = 1,
+ [0x001e63] = 1,
+ [0x001e65] = 1,
+ [0x001e67] = 1,
+ [0x001e69] = 1,
+ [0x001e6b] = 1,
+ [0x001e6d] = 1,
+ [0x001e6f] = 1,
+ [0x001e71] = 1,
+ [0x001e73] = 1,
+ [0x001e75] = 1,
+ [0x001e77] = 1,
+ [0x001e79] = 1,
+ [0x001e7b] = 1,
+ [0x001e7d] = 1,
+ [0x001e7f] = 1,
+ [0x001e81] = 1,
+ [0x001e83] = 1,
+ [0x001e85] = 1,
+ [0x001e87] = 1,
+ [0x001e89] = 1,
+ [0x001e8b] = 1,
+ [0x001e8d] = 1,
+ [0x001e8f] = 1,
+ [0x001e91] = 1,
+ [0x001e93] = 1,
+ [0x001e95] = 1,
+ [0x001e96] = 1,
+ [0x001e97] = 1,
+ [0x001e98] = 1,
+ [0x001e99] = 1,
+ [0x001e9a] = 1,
+ [0x001e9b] = 1,
+ [0x001e9c] = 1,
+ [0x001e9d] = 1,
+ [0x001e9f] = 1,
+ [0x001ea1] = 1,
+ [0x001ea3] = 1,
+ [0x001ea5] = 1,
+ [0x001ea7] = 1,
+ [0x001ea9] = 1,
+ [0x001eab] = 1,
+ [0x001ead] = 1,
+ [0x001eaf] = 1,
+ [0x001eb1] = 1,
+ [0x001eb3] = 1,
+ [0x001eb5] = 1,
+ [0x001eb7] = 1,
+ [0x001eb9] = 1,
+ [0x001ebb] = 1,
+ [0x001ebd] = 1,
+ [0x001ebf] = 1,
+ [0x001ec1] = 1,
+ [0x001ec3] = 1,
+ [0x001ec5] = 1,
+ [0x001ec7] = 1,
+ [0x001ec9] = 1,
+ [0x001ecb] = 1,
+ [0x001ecd] = 1,
+ [0x001ecf] = 1,
+ [0x001ed1] = 1,
+ [0x001ed3] = 1,
+ [0x001ed5] = 1,
+ [0x001ed7] = 1,
+ [0x001ed9] = 1,
+ [0x001edb] = 1,
+ [0x001edd] = 1,
+ [0x001edf] = 1,
+ [0x001ee1] = 1,
+ [0x001ee3] = 1,
+ [0x001ee5] = 1,
+ [0x001ee7] = 1,
+ [0x001ee9] = 1,
+ [0x001eeb] = 1,
+ [0x001eed] = 1,
+ [0x001eef] = 1,
+ [0x001ef1] = 1,
+ [0x001ef3] = 1,
+ [0x001ef5] = 1,
+ [0x001ef7] = 1,
+ [0x001ef9] = 1,
+ [0x001efb] = 1,
+ [0x001efd] = 1,
+ [0x001eff] = 1,
+ [0x001f00] = 1,
+ [0x001f01] = 1,
+ [0x001f02] = 1,
+ [0x001f03] = 1,
+ [0x001f04] = 1,
+ [0x001f05] = 1,
+ [0x001f06] = 1,
+ [0x001f07] = 1,
+ [0x001f10] = 1,
+ [0x001f11] = 1,
+ [0x001f12] = 1,
+ [0x001f13] = 1,
+ [0x001f14] = 1,
+ [0x001f15] = 1,
+ [0x001f20] = 1,
+ [0x001f21] = 1,
+ [0x001f22] = 1,
+ [0x001f23] = 1,
+ [0x001f24] = 1,
+ [0x001f25] = 1,
+ [0x001f26] = 1,
+ [0x001f27] = 1,
+ [0x001f30] = 1,
+ [0x001f31] = 1,
+ [0x001f32] = 1,
+ [0x001f33] = 1,
+ [0x001f34] = 1,
+ [0x001f35] = 1,
+ [0x001f36] = 1,
+ [0x001f37] = 1,
+ [0x001f40] = 1,
+ [0x001f41] = 1,
+ [0x001f42] = 1,
+ [0x001f43] = 1,
+ [0x001f44] = 1,
+ [0x001f45] = 1,
+ [0x001f50] = 1,
+ [0x001f51] = 1,
+ [0x001f52] = 1,
+ [0x001f53] = 1,
+ [0x001f54] = 1,
+ [0x001f55] = 1,
+ [0x001f56] = 1,
+ [0x001f57] = 1,
+ [0x001f60] = 1,
+ [0x001f61] = 1,
+ [0x001f62] = 1,
+ [0x001f63] = 1,
+ [0x001f64] = 1,
+ [0x001f65] = 1,
+ [0x001f66] = 1,
+ [0x001f67] = 1,
+ [0x001f80] = 1,
+ [0x001f81] = 1,
+ [0x001f82] = 1,
+ [0x001f83] = 1,
+ [0x001f84] = 1,
+ [0x001f85] = 1,
+ [0x001f86] = 1,
+ [0x001f87] = 1,
+ [0x001f90] = 1,
+ [0x001f91] = 1,
+ [0x001f92] = 1,
+ [0x001f93] = 1,
+ [0x001f94] = 1,
+ [0x001f95] = 1,
+ [0x001f96] = 1,
+ [0x001f97] = 1,
+ [0x001fa0] = 1,
+ [0x001fa1] = 1,
+ [0x001fa2] = 1,
+ [0x001fa3] = 1,
+ [0x001fa4] = 1,
+ [0x001fa5] = 1,
+ [0x001fa6] = 1,
+ [0x001fa7] = 1,
+ [0x001fb0] = 1,
+ [0x001fb1] = 1,
+ [0x001fb2] = 1,
+ [0x001fb3] = 1,
+ [0x001fb4] = 1,
+ [0x001fb6] = 1,
+ [0x001fb7] = 1,
+ [0x001fbe] = 1,
+ [0x001fc2] = 1,
+ [0x001fc3] = 1,
+ [0x001fc4] = 1,
+ [0x001fc6] = 1,
+ [0x001fc7] = 1,
+ [0x001fd0] = 1,
+ [0x001fd1] = 1,
+ [0x001fd2] = 1,
+ [0x001fd3] = 1,
+ [0x001fd6] = 1,
+ [0x001fd7] = 1,
+ [0x001fe0] = 1,
+ [0x001fe1] = 1,
+ [0x001fe2] = 1,
+ [0x001fe3] = 1,
+ [0x001fe4] = 1,
+ [0x001fe5] = 1,
+ [0x001fe6] = 1,
+ [0x001fe7] = 1,
+ [0x001ff2] = 1,
+ [0x001ff3] = 1,
+ [0x001ff4] = 1,
+ [0x001ff6] = 1,
+ [0x001ff7] = 1,
+ [0x00210a] = 1,
+ [0x00210e] = 1,
+ [0x00210f] = 1,
+ [0x002113] = 1,
+ [0x00212f] = 1,
+ [0x002134] = 1,
+ [0x002139] = 1,
+ [0x00213c] = 1,
+ [0x00213d] = 1,
+ [0x002146] = 1,
+ [0x002147] = 1,
+ [0x002148] = 1,
+ [0x002149] = 1,
+ [0x00214e] = 1,
+ [0x002184] = 1,
+ [0x002c61] = 1,
+ [0x002c65] = 1,
+ [0x002c66] = 1,
+ [0x002c68] = 1,
+ [0x002c6a] = 1,
+ [0x002c6c] = 1,
+ [0x002c71] = 1,
+ [0x002c73] = 1,
+ [0x002c74] = 1,
+ [0x002c76] = 1,
+ [0x002c77] = 1,
+ [0x002c78] = 1,
+ [0x002c79] = 1,
+ [0x002c7a] = 1,
+ [0x002c7b] = 1,
+ [0x002c81] = 1,
+ [0x002c83] = 1,
+ [0x002c85] = 1,
+ [0x002c87] = 1,
+ [0x002c89] = 1,
+ [0x002c8b] = 1,
+ [0x002c8d] = 1,
+ [0x002c8f] = 1,
+ [0x002c91] = 1,
+ [0x002c93] = 1,
+ [0x002c95] = 1,
+ [0x002c97] = 1,
+ [0x002c99] = 1,
+ [0x002c9b] = 1,
+ [0x002c9d] = 1,
+ [0x002c9f] = 1,
+ [0x002ca1] = 1,
+ [0x002ca3] = 1,
+ [0x002ca5] = 1,
+ [0x002ca7] = 1,
+ [0x002ca9] = 1,
+ [0x002cab] = 1,
+ [0x002cad] = 1,
+ [0x002caf] = 1,
+ [0x002cb1] = 1,
+ [0x002cb3] = 1,
+ [0x002cb5] = 1,
+ [0x002cb7] = 1,
+ [0x002cb9] = 1,
+ [0x002cbb] = 1,
+ [0x002cbd] = 1,
+ [0x002cbf] = 1,
+ [0x002cc1] = 1,
+ [0x002cc3] = 1,
+ [0x002cc5] = 1,
+ [0x002cc7] = 1,
+ [0x002cc9] = 1,
+ [0x002ccb] = 1,
+ [0x002ccd] = 1,
+ [0x002ccf] = 1,
+ [0x002cd1] = 1,
+ [0x002cd3] = 1,
+ [0x002cd5] = 1,
+ [0x002cd7] = 1,
+ [0x002cd9] = 1,
+ [0x002cdb] = 1,
+ [0x002cdd] = 1,
+ [0x002cdf] = 1,
+ [0x002ce1] = 1,
+ [0x002ce3] = 1,
+ [0x002ce4] = 1,
+ [0x002cec] = 1,
+ [0x002cee] = 1,
+ [0x002cf3] = 1,
+ [0x002d27] = 1,
+ [0x002d2d] = 1,
+ [0x00a641] = 1,
+ [0x00a643] = 1,
+ [0x00a645] = 1,
+ [0x00a647] = 1,
+ [0x00a649] = 1,
+ [0x00a64b] = 1,
+ [0x00a64d] = 1,
+ [0x00a64f] = 1,
+ [0x00a651] = 1,
+ [0x00a653] = 1,
+ [0x00a655] = 1,
+ [0x00a657] = 1,
+ [0x00a659] = 1,
+ [0x00a65b] = 1,
+ [0x00a65d] = 1,
+ [0x00a65f] = 1,
+ [0x00a661] = 1,
+ [0x00a663] = 1,
+ [0x00a665] = 1,
+ [0x00a667] = 1,
+ [0x00a669] = 1,
+ [0x00a66b] = 1,
+ [0x00a66d] = 1,
+ [0x00a681] = 1,
+ [0x00a683] = 1,
+ [0x00a685] = 1,
+ [0x00a687] = 1,
+ [0x00a689] = 1,
+ [0x00a68b] = 1,
+ [0x00a68d] = 1,
+ [0x00a68f] = 1,
+ [0x00a691] = 1,
+ [0x00a693] = 1,
+ [0x00a695] = 1,
+ [0x00a697] = 1,
+ [0x00a723] = 1,
+ [0x00a725] = 1,
+ [0x00a727] = 1,
+ [0x00a729] = 1,
+ [0x00a72b] = 1,
+ [0x00a72d] = 1,
+ [0x00a72f] = 1,
+ [0x00a730] = 1,
+ [0x00a731] = 1,
+ [0x00a733] = 1,
+ [0x00a735] = 1,
+ [0x00a737] = 1,
+ [0x00a739] = 1,
+ [0x00a73b] = 1,
+ [0x00a73d] = 1,
+ [0x00a73f] = 1,
+ [0x00a741] = 1,
+ [0x00a743] = 1,
+ [0x00a745] = 1,
+ [0x00a747] = 1,
+ [0x00a749] = 1,
+ [0x00a74b] = 1,
+ [0x00a74d] = 1,
+ [0x00a74f] = 1,
+ [0x00a751] = 1,
+ [0x00a753] = 1,
+ [0x00a755] = 1,
+ [0x00a757] = 1,
+ [0x00a759] = 1,
+ [0x00a75b] = 1,
+ [0x00a75d] = 1,
+ [0x00a75f] = 1,
+ [0x00a761] = 1,
+ [0x00a763] = 1,
+ [0x00a765] = 1,
+ [0x00a767] = 1,
+ [0x00a769] = 1,
+ [0x00a76b] = 1,
+ [0x00a76d] = 1,
+ [0x00a76f] = 1,
+ [0x00a771] = 1,
+ [0x00a772] = 1,
+ [0x00a773] = 1,
+ [0x00a774] = 1,
+ [0x00a775] = 1,
+ [0x00a776] = 1,
+ [0x00a777] = 1,
+ [0x00a778] = 1,
+ [0x00a77a] = 1,
+ [0x00a77c] = 1,
+ [0x00a77f] = 1,
+ [0x00a781] = 1,
+ [0x00a783] = 1,
+ [0x00a785] = 1,
+ [0x00a787] = 1,
+ [0x00a78c] = 1,
+ [0x00a78e] = 1,
+ [0x00a791] = 1,
+ [0x00a793] = 1,
+ [0x00a7a1] = 1,
+ [0x00a7a3] = 1,
+ [0x00a7a5] = 1,
+ [0x00a7a7] = 1,
+ [0x00a7a9] = 1,
+ [0x00a7fa] = 1,
+ [0x00fb00] = 1,
+ [0x00fb01] = 1,
+ [0x00fb02] = 1,
+ [0x00fb03] = 1,
+ [0x00fb04] = 1,
+ [0x00fb05] = 1,
+ [0x00fb06] = 1,
+ [0x00fb13] = 1,
+ [0x00fb14] = 1,
+ [0x00fb15] = 1,
+ [0x00fb16] = 1,
+ [0x00fb17] = 1,
+ [0x01d44e] = 1,
+ [0x01d44f] = 1,
+ [0x01d450] = 1,
+ [0x01d451] = 1,
+ [0x01d452] = 1,
+ [0x01d453] = 1,
+ [0x01d454] = 1,
+ [0x01d4b6] = 1,
+ [0x01d4b7] = 1,
+ [0x01d4b8] = 1,
+ [0x01d4b9] = 1,
+ [0x01d4bb] = 1,
+ [0x01d4bd] = 1,
+ [0x01d4be] = 1,
+ [0x01d4bf] = 1,
+ [0x01d4c0] = 1,
+ [0x01d4c1] = 1,
+ [0x01d4c2] = 1,
+ [0x01d4c3] = 1,
+ [0x01d6dc] = 1,
+ [0x01d6dd] = 1,
+ [0x01d6de] = 1,
+ [0x01d6df] = 1,
+ [0x01d6e0] = 1,
+ [0x01d6e1] = 1,
+ [0x01d716] = 1,
+ [0x01d717] = 1,
+ [0x01d718] = 1,
+ [0x01d719] = 1,
+ [0x01d71a] = 1,
+ [0x01d71b] = 1,
+ [0x01d750] = 1,
+ [0x01d751] = 1,
+ [0x01d752] = 1,
+ [0x01d753] = 1,
+ [0x01d754] = 1,
+ [0x01d755] = 1,
+ [0x01d78a] = 1,
+ [0x01d78b] = 1,
+ [0x01d78c] = 1,
+ [0x01d78d] = 1,
+ [0x01d78e] = 1,
+ [0x01d78f] = 1,
+ [0x01d7c4] = 1,
+ [0x01d7c5] = 1,
+ [0x01d7c6] = 1,
+ [0x01d7c7] = 1,
+ [0x01d7c8] = 1,
+ [0x01d7c9] = 1,
+ [0x01d7cb] = 1,
+ },
+ [0x70] = {
+ [0x000021] = 1,
+ [0x000022] = 1,
+ [0x000023] = 1,
+ [0x000025] = 1,
+ [0x000026] = 1,
+ [0x000027] = 1,
+ [0x000028] = 1,
+ [0x000029] = 1,
+ [0x00002a] = 1,
+ [0x00002c] = 1,
+ [0x00002d] = 1,
+ [0x00002e] = 1,
+ [0x00002f] = 1,
+ [0x00003a] = 1,
+ [0x00003b] = 1,
+ [0x00003f] = 1,
+ [0x000040] = 1,
+ [0x00005b] = 1,
+ [0x00005c] = 1,
+ [0x00005d] = 1,
+ [0x00005f] = 1,
+ [0x00007b] = 1,
+ [0x00007d] = 1,
+ [0x0000a1] = 1,
+ [0x0000a7] = 1,
+ [0x0000ab] = 1,
+ [0x0000b6] = 1,
+ [0x0000b7] = 1,
+ [0x0000bb] = 1,
+ [0x0000bf] = 1,
+ [0x00037e] = 1,
+ [0x000387] = 1,
+ [0x00055a] = 1,
+ [0x00055b] = 1,
+ [0x00055c] = 1,
+ [0x00055d] = 1,
+ [0x00055e] = 1,
+ [0x00055f] = 1,
+ [0x000589] = 1,
+ [0x00058a] = 1,
+ [0x0005be] = 1,
+ [0x0005c0] = 1,
+ [0x0005c3] = 1,
+ [0x0005c6] = 1,
+ [0x0005f3] = 1,
+ [0x0005f4] = 1,
+ [0x000609] = 1,
+ [0x00060a] = 1,
+ [0x00060c] = 1,
+ [0x00060d] = 1,
+ [0x00061b] = 1,
+ [0x00061e] = 1,
+ [0x00061f] = 1,
+ [0x00066a] = 1,
+ [0x00066b] = 1,
+ [0x00066c] = 1,
+ [0x00066d] = 1,
+ [0x0006d4] = 1,
+ [0x0007f7] = 1,
+ [0x0007f8] = 1,
+ [0x0007f9] = 1,
+ [0x00085e] = 1,
+ [0x000964] = 1,
+ [0x000965] = 1,
+ [0x000970] = 1,
+ [0x000af0] = 1,
+ [0x000df4] = 1,
+ [0x000e4f] = 1,
+ [0x000e5a] = 1,
+ [0x000e5b] = 1,
+ [0x000f14] = 1,
+ [0x000f3a] = 1,
+ [0x000f3b] = 1,
+ [0x000f3c] = 1,
+ [0x000f3d] = 1,
+ [0x000f85] = 1,
+ [0x000fd0] = 1,
+ [0x000fd1] = 1,
+ [0x000fd2] = 1,
+ [0x000fd3] = 1,
+ [0x000fd4] = 1,
+ [0x000fd9] = 1,
+ [0x000fda] = 1,
+ [0x00104a] = 1,
+ [0x00104b] = 1,
+ [0x00104c] = 1,
+ [0x00104d] = 1,
+ [0x00104e] = 1,
+ [0x00104f] = 1,
+ [0x0010fb] = 1,
+ [0x001360] = 1,
+ [0x001361] = 1,
+ [0x001362] = 1,
+ [0x001363] = 1,
+ [0x001364] = 1,
+ [0x001365] = 1,
+ [0x001366] = 1,
+ [0x001367] = 1,
+ [0x001368] = 1,
+ [0x001400] = 1,
+ [0x00166d] = 1,
+ [0x00166e] = 1,
+ [0x00169b] = 1,
+ [0x00169c] = 1,
+ [0x0016eb] = 1,
+ [0x0016ec] = 1,
+ [0x0016ed] = 1,
+ [0x001735] = 1,
+ [0x001736] = 1,
+ [0x0017d4] = 1,
+ [0x0017d5] = 1,
+ [0x0017d6] = 1,
+ [0x0017d8] = 1,
+ [0x0017d9] = 1,
+ [0x0017da] = 1,
+ [0x001944] = 1,
+ [0x001945] = 1,
+ [0x001a1e] = 1,
+ [0x001a1f] = 1,
+ [0x001aa0] = 1,
+ [0x001aa1] = 1,
+ [0x001aa2] = 1,
+ [0x001aa3] = 1,
+ [0x001aa4] = 1,
+ [0x001aa5] = 1,
+ [0x001aa6] = 1,
+ [0x001aa8] = 1,
+ [0x001aa9] = 1,
+ [0x001aaa] = 1,
+ [0x001aab] = 1,
+ [0x001aac] = 1,
+ [0x001aad] = 1,
+ [0x001b5a] = 1,
+ [0x001b5b] = 1,
+ [0x001b5c] = 1,
+ [0x001b5d] = 1,
+ [0x001b5e] = 1,
+ [0x001b5f] = 1,
+ [0x001b60] = 1,
+ [0x001bfc] = 1,
+ [0x001bfd] = 1,
+ [0x001bfe] = 1,
+ [0x001bff] = 1,
+ [0x001c3b] = 1,
+ [0x001c3c] = 1,
+ [0x001c3d] = 1,
+ [0x001c3e] = 1,
+ [0x001c3f] = 1,
+ [0x001c7e] = 1,
+ [0x001c7f] = 1,
+ [0x001cc0] = 1,
+ [0x001cc1] = 1,
+ [0x001cc2] = 1,
+ [0x001cc3] = 1,
+ [0x001cc4] = 1,
+ [0x001cc5] = 1,
+ [0x001cc6] = 1,
+ [0x001cc7] = 1,
+ [0x001cd3] = 1,
+ [0x00207d] = 1,
+ [0x00207e] = 1,
+ [0x00208d] = 1,
+ [0x00208e] = 1,
+ [0x002308] = 1,
+ [0x002309] = 1,
+ [0x00230a] = 1,
+ [0x00230b] = 1,
+ [0x002329] = 1,
+ [0x00232a] = 1,
+ [0x0027c5] = 1,
+ [0x0027c6] = 1,
+ [0x0029d8] = 1,
+ [0x0029d9] = 1,
+ [0x0029da] = 1,
+ [0x0029db] = 1,
+ [0x0029fc] = 1,
+ [0x0029fd] = 1,
+ [0x002cf9] = 1,
+ [0x002cfa] = 1,
+ [0x002cfb] = 1,
+ [0x002cfc] = 1,
+ [0x002cfe] = 1,
+ [0x002cff] = 1,
+ [0x002d70] = 1,
+ [0x003001] = 1,
+ [0x003002] = 1,
+ [0x003003] = 1,
+ [0x003030] = 1,
+ [0x00303d] = 1,
+ [0x0030a0] = 1,
+ [0x0030fb] = 1,
+ [0x00a4fe] = 1,
+ [0x00a4ff] = 1,
+ [0x00a60d] = 1,
+ [0x00a60e] = 1,
+ [0x00a60f] = 1,
+ [0x00a673] = 1,
+ [0x00a67e] = 1,
+ [0x00a6f2] = 1,
+ [0x00a6f3] = 1,
+ [0x00a6f4] = 1,
+ [0x00a6f5] = 1,
+ [0x00a6f6] = 1,
+ [0x00a6f7] = 1,
+ [0x00a874] = 1,
+ [0x00a875] = 1,
+ [0x00a876] = 1,
+ [0x00a877] = 1,
+ [0x00a8ce] = 1,
+ [0x00a8cf] = 1,
+ [0x00a8f8] = 1,
+ [0x00a8f9] = 1,
+ [0x00a8fa] = 1,
+ [0x00a92e] = 1,
+ [0x00a92f] = 1,
+ [0x00a95f] = 1,
+ [0x00a9de] = 1,
+ [0x00a9df] = 1,
+ [0x00aa5c] = 1,
+ [0x00aa5d] = 1,
+ [0x00aa5e] = 1,
+ [0x00aa5f] = 1,
+ [0x00aade] = 1,
+ [0x00aadf] = 1,
+ [0x00aaf0] = 1,
+ [0x00aaf1] = 1,
+ [0x00abeb] = 1,
+ [0x00fd3e] = 1,
+ [0x00fd3f] = 1,
+ [0x00fe63] = 1,
+ [0x00fe68] = 1,
+ [0x00fe6a] = 1,
+ [0x00fe6b] = 1,
+ [0x00ff01] = 1,
+ [0x00ff02] = 1,
+ [0x00ff03] = 1,
+ [0x00ff05] = 1,
+ [0x00ff06] = 1,
+ [0x00ff07] = 1,
+ [0x00ff08] = 1,
+ [0x00ff09] = 1,
+ [0x00ff0a] = 1,
+ [0x00ff0c] = 1,
+ [0x00ff0d] = 1,
+ [0x00ff0e] = 1,
+ [0x00ff0f] = 1,
+ [0x00ff1a] = 1,
+ [0x00ff1b] = 1,
+ [0x00ff1f] = 1,
+ [0x00ff20] = 1,
+ [0x00ff3b] = 1,
+ [0x00ff3c] = 1,
+ [0x00ff3d] = 1,
+ [0x00ff3f] = 1,
+ [0x00ff5b] = 1,
+ [0x00ff5d] = 1,
+ [0x00ff5f] = 1,
+ [0x00ff60] = 1,
+ [0x00ff61] = 1,
+ [0x00ff62] = 1,
+ [0x00ff63] = 1,
+ [0x00ff64] = 1,
+ [0x00ff65] = 1,
+ [0x010100] = 1,
+ [0x010101] = 1,
+ [0x010102] = 1,
+ [0x01039f] = 1,
+ [0x0103d0] = 1,
+ [0x010857] = 1,
+ [0x01091f] = 1,
+ [0x01093f] = 1,
+ [0x010a50] = 1,
+ [0x010a51] = 1,
+ [0x010a52] = 1,
+ [0x010a53] = 1,
+ [0x010a54] = 1,
+ [0x010a55] = 1,
+ [0x010a56] = 1,
+ [0x010a57] = 1,
+ [0x010a58] = 1,
+ [0x010a7f] = 1,
+ [0x010b39] = 1,
+ [0x010b3a] = 1,
+ [0x010b3b] = 1,
+ [0x010b3c] = 1,
+ [0x010b3d] = 1,
+ [0x010b3e] = 1,
+ [0x010b3f] = 1,
+ [0x011047] = 1,
+ [0x011048] = 1,
+ [0x011049] = 1,
+ [0x01104a] = 1,
+ [0x01104b] = 1,
+ [0x01104c] = 1,
+ [0x01104d] = 1,
+ [0x0110bb] = 1,
+ [0x0110bc] = 1,
+ [0x0110be] = 1,
+ [0x0110bf] = 1,
+ [0x0110c0] = 1,
+ [0x0110c1] = 1,
+ [0x011140] = 1,
+ [0x011141] = 1,
+ [0x011142] = 1,
+ [0x011143] = 1,
+ [0x0111c5] = 1,
+ [0x0111c6] = 1,
+ [0x0111c7] = 1,
+ [0x0111c8] = 1,
+ [0x012470] = 1,
+ [0x012471] = 1,
+ [0x012472] = 1,
+ [0x012473] = 1,
+ },
+ [0x73] = {
+ [0x000009] = 1,
+ [0x00000a] = 1,
+ [0x00000b] = 1,
+ [0x00000c] = 1,
+ [0x00000d] = 1,
+ [0x000020] = 1,
+ [0x000085] = 1,
+ [0x0000a0] = 1,
+ [0x001680] = 1,
+ [0x00180e] = 1,
+ [0x002028] = 1,
+ [0x002029] = 1,
+ [0x00202f] = 1,
+ [0x00205f] = 1,
+ [0x003000] = 1,
+ },
+ [0x75] = {
+ [0x000041] = 1,
+ [0x000042] = 1,
+ [0x000043] = 1,
+ [0x000044] = 1,
+ [0x000045] = 1,
+ [0x000046] = 1,
+ [0x000047] = 1,
+ [0x000048] = 1,
+ [0x000049] = 1,
+ [0x00004a] = 1,
+ [0x00004b] = 1,
+ [0x00004c] = 1,
+ [0x00004d] = 1,
+ [0x00004e] = 1,
+ [0x00004f] = 1,
+ [0x000050] = 1,
+ [0x000051] = 1,
+ [0x000052] = 1,
+ [0x000053] = 1,
+ [0x000054] = 1,
+ [0x000055] = 1,
+ [0x000056] = 1,
+ [0x000057] = 1,
+ [0x000058] = 1,
+ [0x000059] = 1,
+ [0x00005a] = 1,
+ [0x0000d8] = 1,
+ [0x0000d9] = 1,
+ [0x0000da] = 1,
+ [0x0000db] = 1,
+ [0x0000dc] = 1,
+ [0x0000dd] = 1,
+ [0x0000de] = 1,
+ [0x000100] = 1,
+ [0x000102] = 1,
+ [0x000104] = 1,
+ [0x000106] = 1,
+ [0x000108] = 1,
+ [0x00010a] = 1,
+ [0x00010c] = 1,
+ [0x00010e] = 1,
+ [0x000110] = 1,
+ [0x000112] = 1,
+ [0x000114] = 1,
+ [0x000116] = 1,
+ [0x000118] = 1,
+ [0x00011a] = 1,
+ [0x00011c] = 1,
+ [0x00011e] = 1,
+ [0x000120] = 1,
+ [0x000122] = 1,
+ [0x000124] = 1,
+ [0x000126] = 1,
+ [0x000128] = 1,
+ [0x00012a] = 1,
+ [0x00012c] = 1,
+ [0x00012e] = 1,
+ [0x000130] = 1,
+ [0x000132] = 1,
+ [0x000134] = 1,
+ [0x000136] = 1,
+ [0x000139] = 1,
+ [0x00013b] = 1,
+ [0x00013d] = 1,
+ [0x00013f] = 1,
+ [0x000141] = 1,
+ [0x000143] = 1,
+ [0x000145] = 1,
+ [0x000147] = 1,
+ [0x00014a] = 1,
+ [0x00014c] = 1,
+ [0x00014e] = 1,
+ [0x000150] = 1,
+ [0x000152] = 1,
+ [0x000154] = 1,
+ [0x000156] = 1,
+ [0x000158] = 1,
+ [0x00015a] = 1,
+ [0x00015c] = 1,
+ [0x00015e] = 1,
+ [0x000160] = 1,
+ [0x000162] = 1,
+ [0x000164] = 1,
+ [0x000166] = 1,
+ [0x000168] = 1,
+ [0x00016a] = 1,
+ [0x00016c] = 1,
+ [0x00016e] = 1,
+ [0x000170] = 1,
+ [0x000172] = 1,
+ [0x000174] = 1,
+ [0x000176] = 1,
+ [0x000178] = 1,
+ [0x000179] = 1,
+ [0x00017b] = 1,
+ [0x00017d] = 1,
+ [0x000181] = 1,
+ [0x000182] = 1,
+ [0x000184] = 1,
+ [0x000186] = 1,
+ [0x000187] = 1,
+ [0x000189] = 1,
+ [0x00018a] = 1,
+ [0x00018b] = 1,
+ [0x00018e] = 1,
+ [0x00018f] = 1,
+ [0x000190] = 1,
+ [0x000191] = 1,
+ [0x000193] = 1,
+ [0x000194] = 1,
+ [0x000196] = 1,
+ [0x000197] = 1,
+ [0x000198] = 1,
+ [0x00019c] = 1,
+ [0x00019d] = 1,
+ [0x00019f] = 1,
+ [0x0001a0] = 1,
+ [0x0001a2] = 1,
+ [0x0001a4] = 1,
+ [0x0001a6] = 1,
+ [0x0001a7] = 1,
+ [0x0001a9] = 1,
+ [0x0001ac] = 1,
+ [0x0001ae] = 1,
+ [0x0001af] = 1,
+ [0x0001b1] = 1,
+ [0x0001b2] = 1,
+ [0x0001b3] = 1,
+ [0x0001b5] = 1,
+ [0x0001b7] = 1,
+ [0x0001b8] = 1,
+ [0x0001bc] = 1,
+ [0x0001c4] = 1,
+ [0x0001c7] = 1,
+ [0x0001ca] = 1,
+ [0x0001cd] = 1,
+ [0x0001cf] = 1,
+ [0x0001d1] = 1,
+ [0x0001d3] = 1,
+ [0x0001d5] = 1,
+ [0x0001d7] = 1,
+ [0x0001d9] = 1,
+ [0x0001db] = 1,
+ [0x0001de] = 1,
+ [0x0001e0] = 1,
+ [0x0001e2] = 1,
+ [0x0001e4] = 1,
+ [0x0001e6] = 1,
+ [0x0001e8] = 1,
+ [0x0001ea] = 1,
+ [0x0001ec] = 1,
+ [0x0001ee] = 1,
+ [0x0001f1] = 1,
+ [0x0001f4] = 1,
+ [0x0001f6] = 1,
+ [0x0001f7] = 1,
+ [0x0001f8] = 1,
+ [0x0001fa] = 1,
+ [0x0001fc] = 1,
+ [0x0001fe] = 1,
+ [0x000200] = 1,
+ [0x000202] = 1,
+ [0x000204] = 1,
+ [0x000206] = 1,
+ [0x000208] = 1,
+ [0x00020a] = 1,
+ [0x00020c] = 1,
+ [0x00020e] = 1,
+ [0x000210] = 1,
+ [0x000212] = 1,
+ [0x000214] = 1,
+ [0x000216] = 1,
+ [0x000218] = 1,
+ [0x00021a] = 1,
+ [0x00021c] = 1,
+ [0x00021e] = 1,
+ [0x000220] = 1,
+ [0x000222] = 1,
+ [0x000224] = 1,
+ [0x000226] = 1,
+ [0x000228] = 1,
+ [0x00022a] = 1,
+ [0x00022c] = 1,
+ [0x00022e] = 1,
+ [0x000230] = 1,
+ [0x000232] = 1,
+ [0x00023a] = 1,
+ [0x00023b] = 1,
+ [0x00023d] = 1,
+ [0x00023e] = 1,
+ [0x000241] = 1,
+ [0x000243] = 1,
+ [0x000244] = 1,
+ [0x000245] = 1,
+ [0x000246] = 1,
+ [0x000248] = 1,
+ [0x00024a] = 1,
+ [0x00024c] = 1,
+ [0x00024e] = 1,
+ [0x000370] = 1,
+ [0x000372] = 1,
+ [0x000376] = 1,
+ [0x000386] = 1,
+ [0x000388] = 1,
+ [0x000389] = 1,
+ [0x00038a] = 1,
+ [0x00038c] = 1,
+ [0x00038e] = 1,
+ [0x00038f] = 1,
+ [0x0003a3] = 1,
+ [0x0003a4] = 1,
+ [0x0003a5] = 1,
+ [0x0003a6] = 1,
+ [0x0003a7] = 1,
+ [0x0003a8] = 1,
+ [0x0003a9] = 1,
+ [0x0003aa] = 1,
+ [0x0003ab] = 1,
+ [0x0003cf] = 1,
+ [0x0003d2] = 1,
+ [0x0003d3] = 1,
+ [0x0003d4] = 1,
+ [0x0003d8] = 1,
+ [0x0003da] = 1,
+ [0x0003dc] = 1,
+ [0x0003de] = 1,
+ [0x0003e0] = 1,
+ [0x0003e2] = 1,
+ [0x0003e4] = 1,
+ [0x0003e6] = 1,
+ [0x0003e8] = 1,
+ [0x0003ea] = 1,
+ [0x0003ec] = 1,
+ [0x0003ee] = 1,
+ [0x0003f4] = 1,
+ [0x0003f7] = 1,
+ [0x0003f9] = 1,
+ [0x0003fa] = 1,
+ [0x000460] = 1,
+ [0x000462] = 1,
+ [0x000464] = 1,
+ [0x000466] = 1,
+ [0x000468] = 1,
+ [0x00046a] = 1,
+ [0x00046c] = 1,
+ [0x00046e] = 1,
+ [0x000470] = 1,
+ [0x000472] = 1,
+ [0x000474] = 1,
+ [0x000476] = 1,
+ [0x000478] = 1,
+ [0x00047a] = 1,
+ [0x00047c] = 1,
+ [0x00047e] = 1,
+ [0x000480] = 1,
+ [0x00048a] = 1,
+ [0x00048c] = 1,
+ [0x00048e] = 1,
+ [0x000490] = 1,
+ [0x000492] = 1,
+ [0x000494] = 1,
+ [0x000496] = 1,
+ [0x000498] = 1,
+ [0x00049a] = 1,
+ [0x00049c] = 1,
+ [0x00049e] = 1,
+ [0x0004a0] = 1,
+ [0x0004a2] = 1,
+ [0x0004a4] = 1,
+ [0x0004a6] = 1,
+ [0x0004a8] = 1,
+ [0x0004aa] = 1,
+ [0x0004ac] = 1,
+ [0x0004ae] = 1,
+ [0x0004b0] = 1,
+ [0x0004b2] = 1,
+ [0x0004b4] = 1,
+ [0x0004b6] = 1,
+ [0x0004b8] = 1,
+ [0x0004ba] = 1,
+ [0x0004bc] = 1,
+ [0x0004be] = 1,
+ [0x0004c0] = 1,
+ [0x0004c1] = 1,
+ [0x0004c3] = 1,
+ [0x0004c5] = 1,
+ [0x0004c7] = 1,
+ [0x0004c9] = 1,
+ [0x0004cb] = 1,
+ [0x0004cd] = 1,
+ [0x0004d0] = 1,
+ [0x0004d2] = 1,
+ [0x0004d4] = 1,
+ [0x0004d6] = 1,
+ [0x0004d8] = 1,
+ [0x0004da] = 1,
+ [0x0004dc] = 1,
+ [0x0004de] = 1,
+ [0x0004e0] = 1,
+ [0x0004e2] = 1,
+ [0x0004e4] = 1,
+ [0x0004e6] = 1,
+ [0x0004e8] = 1,
+ [0x0004ea] = 1,
+ [0x0004ec] = 1,
+ [0x0004ee] = 1,
+ [0x0004f0] = 1,
+ [0x0004f2] = 1,
+ [0x0004f4] = 1,
+ [0x0004f6] = 1,
+ [0x0004f8] = 1,
+ [0x0004fa] = 1,
+ [0x0004fc] = 1,
+ [0x0004fe] = 1,
+ [0x000500] = 1,
+ [0x000502] = 1,
+ [0x000504] = 1,
+ [0x000506] = 1,
+ [0x000508] = 1,
+ [0x00050a] = 1,
+ [0x00050c] = 1,
+ [0x00050e] = 1,
+ [0x000510] = 1,
+ [0x000512] = 1,
+ [0x000514] = 1,
+ [0x000516] = 1,
+ [0x000518] = 1,
+ [0x00051a] = 1,
+ [0x00051c] = 1,
+ [0x00051e] = 1,
+ [0x000520] = 1,
+ [0x000522] = 1,
+ [0x000524] = 1,
+ [0x000526] = 1,
+ [0x0010c7] = 1,
+ [0x0010cd] = 1,
+ [0x001e00] = 1,
+ [0x001e02] = 1,
+ [0x001e04] = 1,
+ [0x001e06] = 1,
+ [0x001e08] = 1,
+ [0x001e0a] = 1,
+ [0x001e0c] = 1,
+ [0x001e0e] = 1,
+ [0x001e10] = 1,
+ [0x001e12] = 1,
+ [0x001e14] = 1,
+ [0x001e16] = 1,
+ [0x001e18] = 1,
+ [0x001e1a] = 1,
+ [0x001e1c] = 1,
+ [0x001e1e] = 1,
+ [0x001e20] = 1,
+ [0x001e22] = 1,
+ [0x001e24] = 1,
+ [0x001e26] = 1,
+ [0x001e28] = 1,
+ [0x001e2a] = 1,
+ [0x001e2c] = 1,
+ [0x001e2e] = 1,
+ [0x001e30] = 1,
+ [0x001e32] = 1,
+ [0x001e34] = 1,
+ [0x001e36] = 1,
+ [0x001e38] = 1,
+ [0x001e3a] = 1,
+ [0x001e3c] = 1,
+ [0x001e3e] = 1,
+ [0x001e40] = 1,
+ [0x001e42] = 1,
+ [0x001e44] = 1,
+ [0x001e46] = 1,
+ [0x001e48] = 1,
+ [0x001e4a] = 1,
+ [0x001e4c] = 1,
+ [0x001e4e] = 1,
+ [0x001e50] = 1,
+ [0x001e52] = 1,
+ [0x001e54] = 1,
+ [0x001e56] = 1,
+ [0x001e58] = 1,
+ [0x001e5a] = 1,
+ [0x001e5c] = 1,
+ [0x001e5e] = 1,
+ [0x001e60] = 1,
+ [0x001e62] = 1,
+ [0x001e64] = 1,
+ [0x001e66] = 1,
+ [0x001e68] = 1,
+ [0x001e6a] = 1,
+ [0x001e6c] = 1,
+ [0x001e6e] = 1,
+ [0x001e70] = 1,
+ [0x001e72] = 1,
+ [0x001e74] = 1,
+ [0x001e76] = 1,
+ [0x001e78] = 1,
+ [0x001e7a] = 1,
+ [0x001e7c] = 1,
+ [0x001e7e] = 1,
+ [0x001e80] = 1,
+ [0x001e82] = 1,
+ [0x001e84] = 1,
+ [0x001e86] = 1,
+ [0x001e88] = 1,
+ [0x001e8a] = 1,
+ [0x001e8c] = 1,
+ [0x001e8e] = 1,
+ [0x001e90] = 1,
+ [0x001e92] = 1,
+ [0x001e94] = 1,
+ [0x001e9e] = 1,
+ [0x001ea0] = 1,
+ [0x001ea2] = 1,
+ [0x001ea4] = 1,
+ [0x001ea6] = 1,
+ [0x001ea8] = 1,
+ [0x001eaa] = 1,
+ [0x001eac] = 1,
+ [0x001eae] = 1,
+ [0x001eb0] = 1,
+ [0x001eb2] = 1,
+ [0x001eb4] = 1,
+ [0x001eb6] = 1,
+ [0x001eb8] = 1,
+ [0x001eba] = 1,
+ [0x001ebc] = 1,
+ [0x001ebe] = 1,
+ [0x001ec0] = 1,
+ [0x001ec2] = 1,
+ [0x001ec4] = 1,
+ [0x001ec6] = 1,
+ [0x001ec8] = 1,
+ [0x001eca] = 1,
+ [0x001ecc] = 1,
+ [0x001ece] = 1,
+ [0x001ed0] = 1,
+ [0x001ed2] = 1,
+ [0x001ed4] = 1,
+ [0x001ed6] = 1,
+ [0x001ed8] = 1,
+ [0x001eda] = 1,
+ [0x001edc] = 1,
+ [0x001ede] = 1,
+ [0x001ee0] = 1,
+ [0x001ee2] = 1,
+ [0x001ee4] = 1,
+ [0x001ee6] = 1,
+ [0x001ee8] = 1,
+ [0x001eea] = 1,
+ [0x001eec] = 1,
+ [0x001eee] = 1,
+ [0x001ef0] = 1,
+ [0x001ef2] = 1,
+ [0x001ef4] = 1,
+ [0x001ef6] = 1,
+ [0x001ef8] = 1,
+ [0x001efa] = 1,
+ [0x001efc] = 1,
+ [0x001efe] = 1,
+ [0x001f08] = 1,
+ [0x001f09] = 1,
+ [0x001f0a] = 1,
+ [0x001f0b] = 1,
+ [0x001f0c] = 1,
+ [0x001f0d] = 1,
+ [0x001f0e] = 1,
+ [0x001f0f] = 1,
+ [0x001f18] = 1,
+ [0x001f19] = 1,
+ [0x001f1a] = 1,
+ [0x001f1b] = 1,
+ [0x001f1c] = 1,
+ [0x001f1d] = 1,
+ [0x001f28] = 1,
+ [0x001f29] = 1,
+ [0x001f2a] = 1,
+ [0x001f2b] = 1,
+ [0x001f2c] = 1,
+ [0x001f2d] = 1,
+ [0x001f2e] = 1,
+ [0x001f2f] = 1,
+ [0x001f38] = 1,
+ [0x001f39] = 1,
+ [0x001f3a] = 1,
+ [0x001f3b] = 1,
+ [0x001f3c] = 1,
+ [0x001f3d] = 1,
+ [0x001f3e] = 1,
+ [0x001f3f] = 1,
+ [0x001f48] = 1,
+ [0x001f49] = 1,
+ [0x001f4a] = 1,
+ [0x001f4b] = 1,
+ [0x001f4c] = 1,
+ [0x001f4d] = 1,
+ [0x001f59] = 1,
+ [0x001f5b] = 1,
+ [0x001f5d] = 1,
+ [0x001f5f] = 1,
+ [0x001f68] = 1,
+ [0x001f69] = 1,
+ [0x001f6a] = 1,
+ [0x001f6b] = 1,
+ [0x001f6c] = 1,
+ [0x001f6d] = 1,
+ [0x001f6e] = 1,
+ [0x001f6f] = 1,
+ [0x001fb8] = 1,
+ [0x001fb9] = 1,
+ [0x001fba] = 1,
+ [0x001fbb] = 1,
+ [0x001fc8] = 1,
+ [0x001fc9] = 1,
+ [0x001fca] = 1,
+ [0x001fcb] = 1,
+ [0x001fd8] = 1,
+ [0x001fd9] = 1,
+ [0x001fda] = 1,
+ [0x001fdb] = 1,
+ [0x001fe8] = 1,
+ [0x001fe9] = 1,
+ [0x001fea] = 1,
+ [0x001feb] = 1,
+ [0x001fec] = 1,
+ [0x001ff8] = 1,
+ [0x001ff9] = 1,
+ [0x001ffa] = 1,
+ [0x001ffb] = 1,
+ [0x002102] = 1,
+ [0x002107] = 1,
+ [0x00210b] = 1,
+ [0x00210c] = 1,
+ [0x00210d] = 1,
+ [0x002110] = 1,
+ [0x002111] = 1,
+ [0x002112] = 1,
+ [0x002115] = 1,
+ [0x002119] = 1,
+ [0x00211a] = 1,
+ [0x00211b] = 1,
+ [0x00211c] = 1,
+ [0x00211d] = 1,
+ [0x002124] = 1,
+ [0x002126] = 1,
+ [0x002128] = 1,
+ [0x00212a] = 1,
+ [0x00212b] = 1,
+ [0x00212c] = 1,
+ [0x00212d] = 1,
+ [0x002130] = 1,
+ [0x002131] = 1,
+ [0x002132] = 1,
+ [0x002133] = 1,
+ [0x00213e] = 1,
+ [0x00213f] = 1,
+ [0x002145] = 1,
+ [0x002183] = 1,
+ [0x002c60] = 1,
+ [0x002c62] = 1,
+ [0x002c63] = 1,
+ [0x002c64] = 1,
+ [0x002c67] = 1,
+ [0x002c69] = 1,
+ [0x002c6b] = 1,
+ [0x002c6d] = 1,
+ [0x002c6e] = 1,
+ [0x002c6f] = 1,
+ [0x002c70] = 1,
+ [0x002c72] = 1,
+ [0x002c75] = 1,
+ [0x002c7e] = 1,
+ [0x002c7f] = 1,
+ [0x002c80] = 1,
+ [0x002c82] = 1,
+ [0x002c84] = 1,
+ [0x002c86] = 1,
+ [0x002c88] = 1,
+ [0x002c8a] = 1,
+ [0x002c8c] = 1,
+ [0x002c8e] = 1,
+ [0x002c90] = 1,
+ [0x002c92] = 1,
+ [0x002c94] = 1,
+ [0x002c96] = 1,
+ [0x002c98] = 1,
+ [0x002c9a] = 1,
+ [0x002c9c] = 1,
+ [0x002c9e] = 1,
+ [0x002ca0] = 1,
+ [0x002ca2] = 1,
+ [0x002ca4] = 1,
+ [0x002ca6] = 1,
+ [0x002ca8] = 1,
+ [0x002caa] = 1,
+ [0x002cac] = 1,
+ [0x002cae] = 1,
+ [0x002cb0] = 1,
+ [0x002cb2] = 1,
+ [0x002cb4] = 1,
+ [0x002cb6] = 1,
+ [0x002cb8] = 1,
+ [0x002cba] = 1,
+ [0x002cbc] = 1,
+ [0x002cbe] = 1,
+ [0x002cc0] = 1,
+ [0x002cc2] = 1,
+ [0x002cc4] = 1,
+ [0x002cc6] = 1,
+ [0x002cc8] = 1,
+ [0x002cca] = 1,
+ [0x002ccc] = 1,
+ [0x002cce] = 1,
+ [0x002cd0] = 1,
+ [0x002cd2] = 1,
+ [0x002cd4] = 1,
+ [0x002cd6] = 1,
+ [0x002cd8] = 1,
+ [0x002cda] = 1,
+ [0x002cdc] = 1,
+ [0x002cde] = 1,
+ [0x002ce0] = 1,
+ [0x002ce2] = 1,
+ [0x002ceb] = 1,
+ [0x002ced] = 1,
+ [0x002cf2] = 1,
+ [0x00a640] = 1,
+ [0x00a642] = 1,
+ [0x00a644] = 1,
+ [0x00a646] = 1,
+ [0x00a648] = 1,
+ [0x00a64a] = 1,
+ [0x00a64c] = 1,
+ [0x00a64e] = 1,
+ [0x00a650] = 1,
+ [0x00a652] = 1,
+ [0x00a654] = 1,
+ [0x00a656] = 1,
+ [0x00a658] = 1,
+ [0x00a65a] = 1,
+ [0x00a65c] = 1,
+ [0x00a65e] = 1,
+ [0x00a660] = 1,
+ [0x00a662] = 1,
+ [0x00a664] = 1,
+ [0x00a666] = 1,
+ [0x00a668] = 1,
+ [0x00a66a] = 1,
+ [0x00a66c] = 1,
+ [0x00a680] = 1,
+ [0x00a682] = 1,
+ [0x00a684] = 1,
+ [0x00a686] = 1,
+ [0x00a688] = 1,
+ [0x00a68a] = 1,
+ [0x00a68c] = 1,
+ [0x00a68e] = 1,
+ [0x00a690] = 1,
+ [0x00a692] = 1,
+ [0x00a694] = 1,
+ [0x00a696] = 1,
+ [0x00a722] = 1,
+ [0x00a724] = 1,
+ [0x00a726] = 1,
+ [0x00a728] = 1,
+ [0x00a72a] = 1,
+ [0x00a72c] = 1,
+ [0x00a72e] = 1,
+ [0x00a732] = 1,
+ [0x00a734] = 1,
+ [0x00a736] = 1,
+ [0x00a738] = 1,
+ [0x00a73a] = 1,
+ [0x00a73c] = 1,
+ [0x00a73e] = 1,
+ [0x00a740] = 1,
+ [0x00a742] = 1,
+ [0x00a744] = 1,
+ [0x00a746] = 1,
+ [0x00a748] = 1,
+ [0x00a74a] = 1,
+ [0x00a74c] = 1,
+ [0x00a74e] = 1,
+ [0x00a750] = 1,
+ [0x00a752] = 1,
+ [0x00a754] = 1,
+ [0x00a756] = 1,
+ [0x00a758] = 1,
+ [0x00a75a] = 1,
+ [0x00a75c] = 1,
+ [0x00a75e] = 1,
+ [0x00a760] = 1,
+ [0x00a762] = 1,
+ [0x00a764] = 1,
+ [0x00a766] = 1,
+ [0x00a768] = 1,
+ [0x00a76a] = 1,
+ [0x00a76c] = 1,
+ [0x00a76e] = 1,
+ [0x00a779] = 1,
+ [0x00a77b] = 1,
+ [0x00a77d] = 1,
+ [0x00a77e] = 1,
+ [0x00a780] = 1,
+ [0x00a782] = 1,
+ [0x00a784] = 1,
+ [0x00a786] = 1,
+ [0x00a78b] = 1,
+ [0x00a78d] = 1,
+ [0x00a790] = 1,
+ [0x00a792] = 1,
+ [0x00a7a0] = 1,
+ [0x00a7a2] = 1,
+ [0x00a7a4] = 1,
+ [0x00a7a6] = 1,
+ [0x00a7a8] = 1,
+ [0x00a7aa] = 1,
+ [0x01d49c] = 1,
+ [0x01d49e] = 1,
+ [0x01d49f] = 1,
+ [0x01d4a2] = 1,
+ [0x01d4a5] = 1,
+ [0x01d4a6] = 1,
+ [0x01d4a9] = 1,
+ [0x01d4aa] = 1,
+ [0x01d4ab] = 1,
+ [0x01d4ac] = 1,
+ [0x01d4ae] = 1,
+ [0x01d4af] = 1,
+ [0x01d4b0] = 1,
+ [0x01d4b1] = 1,
+ [0x01d4b2] = 1,
+ [0x01d4b3] = 1,
+ [0x01d4b4] = 1,
+ [0x01d4b5] = 1,
+ [0x01d504] = 1,
+ [0x01d505] = 1,
+ [0x01d507] = 1,
+ [0x01d508] = 1,
+ [0x01d509] = 1,
+ [0x01d50a] = 1,
+ [0x01d50d] = 1,
+ [0x01d50e] = 1,
+ [0x01d50f] = 1,
+ [0x01d510] = 1,
+ [0x01d511] = 1,
+ [0x01d512] = 1,
+ [0x01d513] = 1,
+ [0x01d514] = 1,
+ [0x01d516] = 1,
+ [0x01d517] = 1,
+ [0x01d518] = 1,
+ [0x01d519] = 1,
+ [0x01d51a] = 1,
+ [0x01d51b] = 1,
+ [0x01d51c] = 1,
+ [0x01d538] = 1,
+ [0x01d539] = 1,
+ [0x01d53b] = 1,
+ [0x01d53c] = 1,
+ [0x01d53d] = 1,
+ [0x01d53e] = 1,
+ [0x01d540] = 1,
+ [0x01d541] = 1,
+ [0x01d542] = 1,
+ [0x01d543] = 1,
+ [0x01d544] = 1,
+ [0x01d546] = 1,
+ [0x01d54a] = 1,
+ [0x01d54b] = 1,
+ [0x01d54c] = 1,
+ [0x01d54d] = 1,
+ [0x01d54e] = 1,
+ [0x01d54f] = 1,
+ [0x01d550] = 1,
+ [0x01d7ca] = 1,
+ },
+ [0x77] = {},
+ [0x78] = {
+ [0x000030] = 1,
+ [0x000031] = 1,
+ [0x000032] = 1,
+ [0x000033] = 1,
+ [0x000034] = 1,
+ [0x000035] = 1,
+ [0x000036] = 1,
+ [0x000037] = 1,
+ [0x000038] = 1,
+ [0x000039] = 1,
+ [0x000041] = 1,
+ [0x000042] = 1,
+ [0x000043] = 1,
+ [0x000044] = 1,
+ [0x000045] = 1,
+ [0x000046] = 1,
+ [0x000061] = 1,
+ [0x000062] = 1,
+ [0x000063] = 1,
+ [0x000064] = 1,
+ [0x000065] = 1,
+ [0x000066] = 1,
+ [0x00ff21] = 1,
+ [0x00ff22] = 1,
+ [0x00ff23] = 1,
+ [0x00ff24] = 1,
+ [0x00ff25] = 1,
+ [0x00ff26] = 1,
+ [0x00ff41] = 1,
+ [0x00ff42] = 1,
+ [0x00ff43] = 1,
+ [0x00ff44] = 1,
+ [0x00ff45] = 1,
+ [0x00ff46] = 1,
+ },
+ [0x7a] = {
+ [0x000000] = 1,
+ },
+ [0x41] = {},
+ [0x43] = {},
+ [0x44] = {},
+ [0x4c] = {},
+ [0x50] = {},
+ [0x53] = {},
+ [0x55] = {},
+ [0x57] = {},
+ [0x58] = {},
+ [0x5a] = {},
+}
+setmetatable( pats[0x61], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return pats[0x6c][k] or
+ pats[0x75][k] or
+ c >= 0x0002b0 and c < 0x0002c2 or
+ c >= 0x0002c6 and c < 0x0002d2 or
+ c >= 0x0005d0 and c < 0x0005eb or
+ c >= 0x000620 and c < 0x00064b or
+ c >= 0x000671 and c < 0x0006d4 or
+ c >= 0x000712 and c < 0x000730 or
+ c >= 0x00074d and c < 0x0007a6 or
+ c >= 0x0007ca and c < 0x0007eb or
+ c >= 0x000800 and c < 0x000816 or
+ c >= 0x000840 and c < 0x000859 or
+ c >= 0x0008a2 and c < 0x0008ad or
+ c >= 0x000904 and c < 0x00093a or
+ c >= 0x000958 and c < 0x000962 or
+ c >= 0x000993 and c < 0x0009a9 or
+ c >= 0x000a13 and c < 0x000a29 or
+ c >= 0x000a93 and c < 0x000aa9 or
+ c >= 0x000b13 and c < 0x000b29 or
+ c >= 0x000bae and c < 0x000bba or
+ c >= 0x000c12 and c < 0x000c29 or
+ c >= 0x000c2a and c < 0x000c34 or
+ c >= 0x000c92 and c < 0x000ca9 or
+ c >= 0x000caa and c < 0x000cb4 or
+ c >= 0x000d12 and c < 0x000d3b or
+ c >= 0x000d85 and c < 0x000d97 or
+ c >= 0x000d9a and c < 0x000db2 or
+ c >= 0x000e01 and c < 0x000e31 or
+ c >= 0x000f49 and c < 0x000f6d or
+ c >= 0x001000 and c < 0x00102b or
+ c >= 0x001075 and c < 0x001082 or
+ c >= 0x0010d0 and c < 0x0010fb or
+ c >= 0x0010fc and c < 0x001249 or
+ c >= 0x001260 and c < 0x001289 or
+ c >= 0x001290 and c < 0x0012b1 or
+ c >= 0x0012c8 and c < 0x0012d7 or
+ c >= 0x0012d8 and c < 0x001311 or
+ c >= 0x001318 and c < 0x00135b or
+ c >= 0x001380 and c < 0x001390 or
+ c >= 0x0013a0 and c < 0x0013f5 or
+ c >= 0x001401 and c < 0x00166d or
+ c >= 0x00166f and c < 0x001680 or
+ c >= 0x001681 and c < 0x00169b or
+ c >= 0x0016a0 and c < 0x0016eb or
+ c >= 0x001700 and c < 0x00170d or
+ c >= 0x001720 and c < 0x001732 or
+ c >= 0x001740 and c < 0x001752 or
+ c >= 0x001760 and c < 0x00176d or
+ c >= 0x001780 and c < 0x0017b4 or
+ c >= 0x001820 and c < 0x001878 or
+ c >= 0x001880 and c < 0x0018a9 or
+ c >= 0x0018b0 and c < 0x0018f6 or
+ c >= 0x001900 and c < 0x00191d or
+ c >= 0x001950 and c < 0x00196e or
+ c >= 0x001980 and c < 0x0019ac or
+ c >= 0x001a00 and c < 0x001a17 or
+ c >= 0x001a20 and c < 0x001a55 or
+ c >= 0x001b05 and c < 0x001b34 or
+ c >= 0x001b83 and c < 0x001ba1 or
+ c >= 0x001bba and c < 0x001be6 or
+ c >= 0x001c00 and c < 0x001c24 or
+ c >= 0x001c5a and c < 0x001c7e or
+ c >= 0x001d2c and c < 0x001d6b or
+ c >= 0x001d9b and c < 0x001dc0 or
+ c >= 0x002090 and c < 0x00209d or
+ c >= 0x002d30 and c < 0x002d68 or
+ c >= 0x002d80 and c < 0x002d97 or
+ c >= 0x003041 and c < 0x003097 or
+ c >= 0x0030a1 and c < 0x0030fb or
+ c >= 0x003105 and c < 0x00312e or
+ c >= 0x003131 and c < 0x00318f or
+ c >= 0x0031a0 and c < 0x0031bb or
+ c >= 0x0031f0 and c < 0x003200 or
+ c >= 0x003400 and c < 0x004db6 or
+ c >= 0x004e00 and c < 0x009fcd or
+ c >= 0x00a000 and c < 0x00a48d or
+ c >= 0x00a4d0 and c < 0x00a4fe or
+ c >= 0x00a500 and c < 0x00a60d or
+ c >= 0x00a610 and c < 0x00a620 or
+ c >= 0x00a6a0 and c < 0x00a6e6 or
+ c >= 0x00a80c and c < 0x00a823 or
+ c >= 0x00a840 and c < 0x00a874 or
+ c >= 0x00a882 and c < 0x00a8b4 or
+ c >= 0x00a90a and c < 0x00a926 or
+ c >= 0x00a930 and c < 0x00a947 or
+ c >= 0x00a960 and c < 0x00a97d or
+ c >= 0x00a984 and c < 0x00a9b3 or
+ c >= 0x00aa00 and c < 0x00aa29 or
+ c >= 0x00aa60 and c < 0x00aa77 or
+ c >= 0x00aa80 and c < 0x00aab0 or
+ c >= 0x00aae0 and c < 0x00aaeb or
+ c >= 0x00abc0 and c < 0x00abe3 or
+ c >= 0x00ac00 and c < 0x00d7a4 or
+ c >= 0x00d7b0 and c < 0x00d7c7 or
+ c >= 0x00d7cb and c < 0x00d7fc or
+ c >= 0x00f900 and c < 0x00fa6e or
+ c >= 0x00fa70 and c < 0x00fada or
+ c >= 0x00fb1f and c < 0x00fb29 or
+ c >= 0x00fb2a and c < 0x00fb37 or
+ c >= 0x00fb46 and c < 0x00fbb2 or
+ c >= 0x00fbd3 and c < 0x00fd3e or
+ c >= 0x00fd50 and c < 0x00fd90 or
+ c >= 0x00fd92 and c < 0x00fdc8 or
+ c >= 0x00fdf0 and c < 0x00fdfc or
+ c >= 0x00fe76 and c < 0x00fefd or
+ c >= 0x00ff66 and c < 0x00ffbf or
+ c >= 0x010000 and c < 0x01000c or
+ c >= 0x01000d and c < 0x010027 or
+ c >= 0x010028 and c < 0x01003b or
+ c >= 0x01003f and c < 0x01004e or
+ c >= 0x010050 and c < 0x01005e or
+ c >= 0x010080 and c < 0x0100fb or
+ c >= 0x010280 and c < 0x01029d or
+ c >= 0x0102a0 and c < 0x0102d1 or
+ c >= 0x010300 and c < 0x01031f or
+ c >= 0x010330 and c < 0x010341 or
+ c >= 0x010380 and c < 0x01039e or
+ c >= 0x0103a0 and c < 0x0103c4 or
+ c >= 0x010450 and c < 0x01049e or
+ c >= 0x01080a and c < 0x010836 or
+ c >= 0x01083f and c < 0x010856 or
+ c >= 0x010900 and c < 0x010916 or
+ c >= 0x010920 and c < 0x01093a or
+ c >= 0x010980 and c < 0x0109b8 or
+ c >= 0x010a19 and c < 0x010a34 or
+ c >= 0x010a60 and c < 0x010a7d or
+ c >= 0x010b00 and c < 0x010b36 or
+ c >= 0x010b40 and c < 0x010b56 or
+ c >= 0x010b60 and c < 0x010b73 or
+ c >= 0x010c00 and c < 0x010c49 or
+ c >= 0x011003 and c < 0x011038 or
+ c >= 0x011083 and c < 0x0110b0 or
+ c >= 0x0110d0 and c < 0x0110e9 or
+ c >= 0x011103 and c < 0x011127 or
+ c >= 0x011183 and c < 0x0111b3 or
+ c >= 0x011680 and c < 0x0116ab or
+ c >= 0x012000 and c < 0x01236f or
+ c >= 0x013000 and c < 0x01342f or
+ c >= 0x016800 and c < 0x016a39 or
+ c >= 0x016f00 and c < 0x016f45 or
+ c >= 0x016f93 and c < 0x016fa0 or
+ c >= 0x01ee05 and c < 0x01ee20 or
+ c >= 0x01ee29 and c < 0x01ee33 or
+ c >= 0x01ee80 and c < 0x01ee8a or
+ c >= 0x01ee8b and c < 0x01ee9c or
+ c >= 0x01eeab and c < 0x01eebc or
+ c >= 0x020000 and c < 0x02a6d7 or
+ c >= 0x02a700 and c < 0x02b735 or
+ c >= 0x02b740 and c < 0x02b81e or
+ c >= 0x02f800 and c < 0x02fa1e
+end } )
+setmetatable( pats[0x63], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x000000 and c < 0x000020 or
+ c >= 0x00007f and c < 0x0000a0
+end } )
+setmetatable( pats[0x64], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x000660 and c < 0x00066a or
+ c >= 0x0006f0 and c < 0x0006fa or
+ c >= 0x0007c0 and c < 0x0007ca or
+ c >= 0x000966 and c < 0x000970 or
+ c >= 0x0009e6 and c < 0x0009f0 or
+ c >= 0x000a66 and c < 0x000a70 or
+ c >= 0x000ae6 and c < 0x000af0 or
+ c >= 0x000b66 and c < 0x000b70 or
+ c >= 0x000be6 and c < 0x000bf0 or
+ c >= 0x000c66 and c < 0x000c70 or
+ c >= 0x000ce6 and c < 0x000cf0 or
+ c >= 0x000d66 and c < 0x000d70 or
+ c >= 0x000e50 and c < 0x000e5a or
+ c >= 0x000ed0 and c < 0x000eda or
+ c >= 0x000f20 and c < 0x000f2a or
+ c >= 0x001040 and c < 0x00104a or
+ c >= 0x001090 and c < 0x00109a or
+ c >= 0x0017e0 and c < 0x0017ea or
+ c >= 0x001810 and c < 0x00181a or
+ c >= 0x001946 and c < 0x001950 or
+ c >= 0x0019d0 and c < 0x0019da or
+ c >= 0x001a80 and c < 0x001a8a or
+ c >= 0x001a90 and c < 0x001a9a or
+ c >= 0x001b50 and c < 0x001b5a or
+ c >= 0x001bb0 and c < 0x001bba or
+ c >= 0x001c40 and c < 0x001c4a or
+ c >= 0x001c50 and c < 0x001c5a or
+ c >= 0x00a620 and c < 0x00a62a or
+ c >= 0x00a8d0 and c < 0x00a8da or
+ c >= 0x00a900 and c < 0x00a90a or
+ c >= 0x00a9d0 and c < 0x00a9da or
+ c >= 0x00aa50 and c < 0x00aa5a or
+ c >= 0x00abf0 and c < 0x00abfa or
+ c >= 0x00ff10 and c < 0x00ff1a or
+ c >= 0x0104a0 and c < 0x0104aa or
+ c >= 0x011066 and c < 0x011070 or
+ c >= 0x0110f0 and c < 0x0110fa or
+ c >= 0x011136 and c < 0x011140 or
+ c >= 0x0111d0 and c < 0x0111da or
+ c >= 0x0116c0 and c < 0x0116ca or
+ c >= 0x01d7ce and c < 0x01d800
+end } )
+setmetatable( pats[0x6c], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x0000df and c < 0x0000f7 or
+ c >= 0x00024f and c < 0x000294 or
+ c >= 0x000295 and c < 0x0002b0 or
+ c >= 0x0003ac and c < 0x0003cf or
+ c >= 0x000430 and c < 0x000460 or
+ c >= 0x000561 and c < 0x000588 or
+ c >= 0x001d00 and c < 0x001d2c or
+ c >= 0x001d6b and c < 0x001d78 or
+ c >= 0x001d79 and c < 0x001d9b or
+ c >= 0x001f70 and c < 0x001f7e or
+ c >= 0x002c30 and c < 0x002c5f or
+ c >= 0x002d00 and c < 0x002d26 or
+ c >= 0x00ff41 and c < 0x00ff5b or
+ c >= 0x010428 and c < 0x010450 or
+ c >= 0x01d41a and c < 0x01d434 or
+ c >= 0x01d456 and c < 0x01d468 or
+ c >= 0x01d482 and c < 0x01d49c or
+ c >= 0x01d4c5 and c < 0x01d4d0 or
+ c >= 0x01d4ea and c < 0x01d504 or
+ c >= 0x01d51e and c < 0x01d538 or
+ c >= 0x01d552 and c < 0x01d56c or
+ c >= 0x01d586 and c < 0x01d5a0 or
+ c >= 0x01d5ba and c < 0x01d5d4 or
+ c >= 0x01d5ee and c < 0x01d608 or
+ c >= 0x01d622 and c < 0x01d63c or
+ c >= 0x01d656 and c < 0x01d670 or
+ c >= 0x01d68a and c < 0x01d6a6 or
+ c >= 0x01d6c2 and c < 0x01d6db or
+ c >= 0x01d6fc and c < 0x01d715 or
+ c >= 0x01d736 and c < 0x01d74f or
+ c >= 0x01d770 and c < 0x01d789 or
+ c >= 0x01d7aa and c < 0x01d7c3
+end } )
+setmetatable( pats[0x70], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x000700 and c < 0x00070e or
+ c >= 0x000830 and c < 0x00083f or
+ c >= 0x000f04 and c < 0x000f13 or
+ c >= 0x001800 and c < 0x00180b or
+ c >= 0x002010 and c < 0x002028 or
+ c >= 0x002030 and c < 0x002044 or
+ c >= 0x002045 and c < 0x002052 or
+ c >= 0x002053 and c < 0x00205f or
+ c >= 0x002768 and c < 0x002776 or
+ c >= 0x0027e6 and c < 0x0027f0 or
+ c >= 0x002983 and c < 0x002999 or
+ c >= 0x002e00 and c < 0x002e2f or
+ c >= 0x002e30 and c < 0x002e3c or
+ c >= 0x003008 and c < 0x003012 or
+ c >= 0x003014 and c < 0x003020 or
+ c >= 0x00a9c1 and c < 0x00a9ce or
+ c >= 0x00fe10 and c < 0x00fe1a or
+ c >= 0x00fe30 and c < 0x00fe53 or
+ c >= 0x00fe54 and c < 0x00fe62
+end } )
+setmetatable( pats[0x73], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x002000 and c < 0x00200b
+end } )
+setmetatable( pats[0x75], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x0000c0 and c < 0x0000d7 or
+ c >= 0x000391 and c < 0x0003a2 or
+ c >= 0x0003fd and c < 0x000430 or
+ c >= 0x000531 and c < 0x000557 or
+ c >= 0x0010a0 and c < 0x0010c6 or
+ c >= 0x002c00 and c < 0x002c2f or
+ c >= 0x00ff21 and c < 0x00ff3b or
+ c >= 0x010400 and c < 0x010428 or
+ c >= 0x01d400 and c < 0x01d41a or
+ c >= 0x01d434 and c < 0x01d44e or
+ c >= 0x01d468 and c < 0x01d482 or
+ c >= 0x01d4d0 and c < 0x01d4ea or
+ c >= 0x01d56c and c < 0x01d586 or
+ c >= 0x01d5a0 and c < 0x01d5ba or
+ c >= 0x01d5d4 and c < 0x01d5ee or
+ c >= 0x01d608 and c < 0x01d622 or
+ c >= 0x01d63c and c < 0x01d656 or
+ c >= 0x01d670 and c < 0x01d68a or
+ c >= 0x01d6a8 and c < 0x01d6c1 or
+ c >= 0x01d6e2 and c < 0x01d6fb or
+ c >= 0x01d71c and c < 0x01d735 or
+ c >= 0x01d756 and c < 0x01d76f or
+ c >= 0x01d790 and c < 0x01d7a9
+end } )
+setmetatable( pats[0x77], { __index = function ( t, k )
+ return pats[0x64][k] or
+ pats[0x61][k]
+end } )
+setmetatable( pats[0x78], { __index = function ( t, k )
+ local c = tonumber( k ) or 0/0;
+ return c >= 0x00ff10 and c < 0x00ff1a
+end } )
+setmetatable( pats[0x41], { __index = function ( t, k ) return k and not pats[0x61][k] end } )
+setmetatable( pats[0x43], { __index = function ( t, k ) return k and not pats[0x63][k] end } )
+setmetatable( pats[0x44], { __index = function ( t, k ) return k and not pats[0x64][k] end } )
+setmetatable( pats[0x4c], { __index = function ( t, k ) return k and not pats[0x6c][k] end } )
+setmetatable( pats[0x50], { __index = function ( t, k ) return k and not pats[0x70][k] end } )
+setmetatable( pats[0x53], { __index = function ( t, k ) return k and not pats[0x73][k] end } )
+setmetatable( pats[0x55], { __index = function ( t, k ) return k and not pats[0x75][k] end } )
+setmetatable( pats[0x57], { __index = function ( t, k ) return k and not pats[0x77][k] end } )
+setmetatable( pats[0x58], { __index = function ( t, k ) return k and not pats[0x78][k] end } )
+setmetatable( pats[0x5a], { __index = function ( t, k ) return k and not pats[0x7a][k] end } )
+
+-- For speed, cache printable ASCII characters in main tables
+for k, t in pairs( pats ) do
+ if k >= 0x61 then
+ for i = 0x20, 0x7e do
+ t[i] = t[i] or false
+ end
+ end
+end
+
+return pats
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/lower.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/lower.lua
new file mode 100644
index 00000000..c5678d30
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/lower.lua
@@ -0,0 +1,679 @@
+-- This file is automatically generated by make-tables.php
+return {
+ ["A"] = "a",
+ ["B"] = "b",
+ ["C"] = "c",
+ ["D"] = "d",
+ ["E"] = "e",
+ ["F"] = "f",
+ ["G"] = "g",
+ ["H"] = "h",
+ ["I"] = "i",
+ ["J"] = "j",
+ ["K"] = "k",
+ ["L"] = "l",
+ ["M"] = "m",
+ ["N"] = "n",
+ ["O"] = "o",
+ ["P"] = "p",
+ ["Q"] = "q",
+ ["R"] = "r",
+ ["S"] = "s",
+ ["T"] = "t",
+ ["U"] = "u",
+ ["V"] = "v",
+ ["W"] = "w",
+ ["X"] = "x",
+ ["Y"] = "y",
+ ["Z"] = "z",
+ ["À"] = "à",
+ ["Á"] = "á",
+ ["Â"] = "â",
+ ["Ã"] = "ã",
+ ["Ä"] = "ä",
+ ["Å"] = "å",
+ ["Æ"] = "æ",
+ ["Ç"] = "ç",
+ ["È"] = "è",
+ ["É"] = "é",
+ ["Ê"] = "ê",
+ ["Ë"] = "ë",
+ ["Ì"] = "ì",
+ ["Í"] = "í",
+ ["Î"] = "î",
+ ["Ï"] = "ï",
+ ["Ð"] = "ð",
+ ["Ñ"] = "ñ",
+ ["Ò"] = "ò",
+ ["Ó"] = "ó",
+ ["Ô"] = "ô",
+ ["Õ"] = "õ",
+ ["Ö"] = "ö",
+ ["Ø"] = "ø",
+ ["Ù"] = "ù",
+ ["Ú"] = "ú",
+ ["Û"] = "û",
+ ["Ü"] = "ü",
+ ["Ý"] = "ý",
+ ["Þ"] = "þ",
+ ["Ā"] = "ā",
+ ["Ă"] = "ă",
+ ["Ą"] = "ą",
+ ["Ć"] = "ć",
+ ["Ĉ"] = "ĉ",
+ ["Ċ"] = "ċ",
+ ["Č"] = "č",
+ ["Ď"] = "ď",
+ ["Đ"] = "đ",
+ ["Ē"] = "ē",
+ ["Ĕ"] = "ĕ",
+ ["Ė"] = "ė",
+ ["Ę"] = "ę",
+ ["Ě"] = "ě",
+ ["Ĝ"] = "ĝ",
+ ["Ğ"] = "ğ",
+ ["Ġ"] = "ġ",
+ ["Ģ"] = "ģ",
+ ["Ĥ"] = "ĥ",
+ ["Ħ"] = "ħ",
+ ["Ĩ"] = "ĩ",
+ ["Ī"] = "ī",
+ ["Ĭ"] = "ĭ",
+ ["Į"] = "į",
+ ["İ"] = "i",
+ ["IJ"] = "ij",
+ ["Ĵ"] = "ĵ",
+ ["Ķ"] = "ķ",
+ ["Ĺ"] = "ĺ",
+ ["Ļ"] = "ļ",
+ ["Ľ"] = "ľ",
+ ["Ŀ"] = "ŀ",
+ ["Ł"] = "ł",
+ ["Ń"] = "ń",
+ ["Ņ"] = "ņ",
+ ["Ň"] = "ň",
+ ["Ŋ"] = "ŋ",
+ ["Ō"] = "ō",
+ ["Ŏ"] = "ŏ",
+ ["Ő"] = "ő",
+ ["Œ"] = "œ",
+ ["Ŕ"] = "ŕ",
+ ["Ŗ"] = "ŗ",
+ ["Ř"] = "ř",
+ ["Ś"] = "ś",
+ ["Ŝ"] = "ŝ",
+ ["Ş"] = "ş",
+ ["Š"] = "š",
+ ["Ţ"] = "ţ",
+ ["Ť"] = "ť",
+ ["Ŧ"] = "ŧ",
+ ["Ũ"] = "ũ",
+ ["Ū"] = "ū",
+ ["Ŭ"] = "ŭ",
+ ["Ů"] = "ů",
+ ["Ű"] = "ű",
+ ["Ų"] = "ų",
+ ["Ŵ"] = "ŵ",
+ ["Ŷ"] = "ŷ",
+ ["Ÿ"] = "ÿ",
+ ["Ź"] = "ź",
+ ["Ż"] = "ż",
+ ["Ž"] = "ž",
+ ["Ɓ"] = "ɓ",
+ ["Ƃ"] = "ƃ",
+ ["Ƅ"] = "ƅ",
+ ["Ɔ"] = "ɔ",
+ ["Ƈ"] = "ƈ",
+ ["Ɖ"] = "ɖ",
+ ["Ɗ"] = "ɗ",
+ ["Ƌ"] = "ƌ",
+ ["Ǝ"] = "ǝ",
+ ["Ə"] = "ə",
+ ["Ɛ"] = "ɛ",
+ ["Ƒ"] = "ƒ",
+ ["Ɠ"] = "ɠ",
+ ["Ɣ"] = "ɣ",
+ ["Ɩ"] = "ɩ",
+ ["Ɨ"] = "ɨ",
+ ["Ƙ"] = "ƙ",
+ ["Ɯ"] = "ɯ",
+ ["Ɲ"] = "ɲ",
+ ["Ɵ"] = "ɵ",
+ ["Ơ"] = "ơ",
+ ["Ƣ"] = "ƣ",
+ ["Ƥ"] = "ƥ",
+ ["Ʀ"] = "ʀ",
+ ["Ƨ"] = "ƨ",
+ ["Ʃ"] = "ʃ",
+ ["Ƭ"] = "ƭ",
+ ["Ʈ"] = "ʈ",
+ ["Ư"] = "ư",
+ ["Ʊ"] = "ʊ",
+ ["Ʋ"] = "ʋ",
+ ["Ƴ"] = "ƴ",
+ ["Ƶ"] = "ƶ",
+ ["Ʒ"] = "ʒ",
+ ["Ƹ"] = "ƹ",
+ ["Ƽ"] = "ƽ",
+ ["DŽ"] = "dž",
+ ["LJ"] = "lj",
+ ["NJ"] = "nj",
+ ["Ǎ"] = "ǎ",
+ ["Ǐ"] = "ǐ",
+ ["Ǒ"] = "ǒ",
+ ["Ǔ"] = "ǔ",
+ ["Ǖ"] = "ǖ",
+ ["Ǘ"] = "ǘ",
+ ["Ǚ"] = "ǚ",
+ ["Ǜ"] = "ǜ",
+ ["Ǟ"] = "ǟ",
+ ["Ǡ"] = "ǡ",
+ ["Ǣ"] = "ǣ",
+ ["Ǥ"] = "ǥ",
+ ["Ǧ"] = "ǧ",
+ ["Ǩ"] = "ǩ",
+ ["Ǫ"] = "ǫ",
+ ["Ǭ"] = "ǭ",
+ ["Ǯ"] = "ǯ",
+ ["DZ"] = "dz",
+ ["Ǵ"] = "ǵ",
+ ["Ƕ"] = "ƕ",
+ ["Ƿ"] = "ƿ",
+ ["Ǹ"] = "ǹ",
+ ["Ǻ"] = "ǻ",
+ ["Ǽ"] = "ǽ",
+ ["Ǿ"] = "ǿ",
+ ["Ȁ"] = "ȁ",
+ ["Ȃ"] = "ȃ",
+ ["Ȅ"] = "ȅ",
+ ["Ȇ"] = "ȇ",
+ ["Ȉ"] = "ȉ",
+ ["Ȋ"] = "ȋ",
+ ["Ȍ"] = "ȍ",
+ ["Ȏ"] = "ȏ",
+ ["Ȑ"] = "ȑ",
+ ["Ȓ"] = "ȓ",
+ ["Ȕ"] = "ȕ",
+ ["Ȗ"] = "ȗ",
+ ["Ș"] = "ș",
+ ["Ț"] = "ț",
+ ["Ȝ"] = "ȝ",
+ ["Ȟ"] = "ȟ",
+ ["Ƞ"] = "ƞ",
+ ["Ȣ"] = "ȣ",
+ ["Ȥ"] = "ȥ",
+ ["Ȧ"] = "ȧ",
+ ["Ȩ"] = "ȩ",
+ ["Ȫ"] = "ȫ",
+ ["Ȭ"] = "ȭ",
+ ["Ȯ"] = "ȯ",
+ ["Ȱ"] = "ȱ",
+ ["Ȳ"] = "ȳ",
+ ["Ά"] = "ά",
+ ["Έ"] = "έ",
+ ["Ή"] = "ή",
+ ["Ί"] = "ί",
+ ["Ό"] = "ό",
+ ["Ύ"] = "ύ",
+ ["Ώ"] = "ώ",
+ ["Α"] = "α",
+ ["Β"] = "β",
+ ["Γ"] = "γ",
+ ["Δ"] = "δ",
+ ["Ε"] = "ε",
+ ["Ζ"] = "ζ",
+ ["Η"] = "η",
+ ["Θ"] = "θ",
+ ["Ι"] = "ι",
+ ["Κ"] = "κ",
+ ["Λ"] = "λ",
+ ["Μ"] = "μ",
+ ["Ν"] = "ν",
+ ["Ξ"] = "ξ",
+ ["Ο"] = "ο",
+ ["Π"] = "π",
+ ["Ρ"] = "ρ",
+ ["Σ"] = "σ",
+ ["Τ"] = "τ",
+ ["Υ"] = "υ",
+ ["Φ"] = "φ",
+ ["Χ"] = "χ",
+ ["Ψ"] = "ψ",
+ ["Ω"] = "ω",
+ ["Ϊ"] = "ϊ",
+ ["Ϋ"] = "ϋ",
+ ["Ϙ"] = "ϙ",
+ ["Ϛ"] = "ϛ",
+ ["Ϝ"] = "ϝ",
+ ["Ϟ"] = "ϟ",
+ ["Ϡ"] = "ϡ",
+ ["Ϣ"] = "ϣ",
+ ["Ϥ"] = "ϥ",
+ ["Ϧ"] = "ϧ",
+ ["Ϩ"] = "ϩ",
+ ["Ϫ"] = "ϫ",
+ ["Ϭ"] = "ϭ",
+ ["Ϯ"] = "ϯ",
+ ["ϴ"] = "θ",
+ ["Ѐ"] = "ѐ",
+ ["Ё"] = "ё",
+ ["Ђ"] = "ђ",
+ ["Ѓ"] = "ѓ",
+ ["Є"] = "є",
+ ["Ѕ"] = "ѕ",
+ ["І"] = "і",
+ ["Ї"] = "ї",
+ ["Ј"] = "ј",
+ ["Љ"] = "љ",
+ ["Њ"] = "њ",
+ ["Ћ"] = "ћ",
+ ["Ќ"] = "ќ",
+ ["Ѝ"] = "ѝ",
+ ["Ў"] = "ў",
+ ["Џ"] = "џ",
+ ["А"] = "а",
+ ["Б"] = "б",
+ ["В"] = "в",
+ ["Г"] = "г",
+ ["Д"] = "д",
+ ["Е"] = "е",
+ ["Ж"] = "ж",
+ ["З"] = "з",
+ ["И"] = "и",
+ ["Й"] = "й",
+ ["К"] = "к",
+ ["Л"] = "л",
+ ["М"] = "м",
+ ["Н"] = "н",
+ ["О"] = "о",
+ ["П"] = "п",
+ ["Р"] = "р",
+ ["С"] = "с",
+ ["Т"] = "т",
+ ["У"] = "у",
+ ["Ф"] = "ф",
+ ["Х"] = "х",
+ ["Ц"] = "ц",
+ ["Ч"] = "ч",
+ ["Ш"] = "ш",
+ ["Щ"] = "щ",
+ ["Ъ"] = "ъ",
+ ["Ы"] = "ы",
+ ["Ь"] = "ь",
+ ["Э"] = "э",
+ ["Ю"] = "ю",
+ ["Я"] = "я",
+ ["Ѡ"] = "ѡ",
+ ["Ѣ"] = "ѣ",
+ ["Ѥ"] = "ѥ",
+ ["Ѧ"] = "ѧ",
+ ["Ѩ"] = "ѩ",
+ ["Ѫ"] = "ѫ",
+ ["Ѭ"] = "ѭ",
+ ["Ѯ"] = "ѯ",
+ ["Ѱ"] = "ѱ",
+ ["Ѳ"] = "ѳ",
+ ["Ѵ"] = "ѵ",
+ ["Ѷ"] = "ѷ",
+ ["Ѹ"] = "ѹ",
+ ["Ѻ"] = "ѻ",
+ ["Ѽ"] = "ѽ",
+ ["Ѿ"] = "ѿ",
+ ["Ҁ"] = "ҁ",
+ ["Ҋ"] = "ҋ",
+ ["Ҍ"] = "ҍ",
+ ["Ҏ"] = "ҏ",
+ ["Ґ"] = "ґ",
+ ["Ғ"] = "ғ",
+ ["Ҕ"] = "ҕ",
+ ["Җ"] = "җ",
+ ["Ҙ"] = "ҙ",
+ ["Қ"] = "қ",
+ ["Ҝ"] = "ҝ",
+ ["Ҟ"] = "ҟ",
+ ["Ҡ"] = "ҡ",
+ ["Ң"] = "ң",
+ ["Ҥ"] = "ҥ",
+ ["Ҧ"] = "ҧ",
+ ["Ҩ"] = "ҩ",
+ ["Ҫ"] = "ҫ",
+ ["Ҭ"] = "ҭ",
+ ["Ү"] = "ү",
+ ["Ұ"] = "ұ",
+ ["Ҳ"] = "ҳ",
+ ["Ҵ"] = "ҵ",
+ ["Ҷ"] = "ҷ",
+ ["Ҹ"] = "ҹ",
+ ["Һ"] = "һ",
+ ["Ҽ"] = "ҽ",
+ ["Ҿ"] = "ҿ",
+ ["Ӂ"] = "ӂ",
+ ["Ӄ"] = "ӄ",
+ ["Ӆ"] = "ӆ",
+ ["Ӈ"] = "ӈ",
+ ["Ӊ"] = "ӊ",
+ ["Ӌ"] = "ӌ",
+ ["Ӎ"] = "ӎ",
+ ["Ӑ"] = "ӑ",
+ ["Ӓ"] = "ӓ",
+ ["Ӕ"] = "ӕ",
+ ["Ӗ"] = "ӗ",
+ ["Ә"] = "ә",
+ ["Ӛ"] = "ӛ",
+ ["Ӝ"] = "ӝ",
+ ["Ӟ"] = "ӟ",
+ ["Ӡ"] = "ӡ",
+ ["Ӣ"] = "ӣ",
+ ["Ӥ"] = "ӥ",
+ ["Ӧ"] = "ӧ",
+ ["Ө"] = "ө",
+ ["Ӫ"] = "ӫ",
+ ["Ӭ"] = "ӭ",
+ ["Ӯ"] = "ӯ",
+ ["Ӱ"] = "ӱ",
+ ["Ӳ"] = "ӳ",
+ ["Ӵ"] = "ӵ",
+ ["Ӹ"] = "ӹ",
+ ["Ԁ"] = "ԁ",
+ ["Ԃ"] = "ԃ",
+ ["Ԅ"] = "ԅ",
+ ["Ԇ"] = "ԇ",
+ ["Ԉ"] = "ԉ",
+ ["Ԋ"] = "ԋ",
+ ["Ԍ"] = "ԍ",
+ ["Ԏ"] = "ԏ",
+ ["Ա"] = "ա",
+ ["Բ"] = "բ",
+ ["Գ"] = "գ",
+ ["Դ"] = "դ",
+ ["Ե"] = "ե",
+ ["Զ"] = "զ",
+ ["Է"] = "է",
+ ["Ը"] = "ը",
+ ["Թ"] = "թ",
+ ["Ժ"] = "ժ",
+ ["Ի"] = "ի",
+ ["Լ"] = "լ",
+ ["Խ"] = "խ",
+ ["Ծ"] = "ծ",
+ ["Կ"] = "կ",
+ ["Հ"] = "հ",
+ ["Ձ"] = "ձ",
+ ["Ղ"] = "ղ",
+ ["Ճ"] = "ճ",
+ ["Մ"] = "մ",
+ ["Յ"] = "յ",
+ ["Ն"] = "ն",
+ ["Շ"] = "շ",
+ ["Ո"] = "ո",
+ ["Չ"] = "չ",
+ ["Պ"] = "պ",
+ ["Ջ"] = "ջ",
+ ["Ռ"] = "ռ",
+ ["Ս"] = "ս",
+ ["Վ"] = "վ",
+ ["Տ"] = "տ",
+ ["Ր"] = "ր",
+ ["Ց"] = "ց",
+ ["Ւ"] = "ւ",
+ ["Փ"] = "փ",
+ ["Ք"] = "ք",
+ ["Օ"] = "օ",
+ ["Ֆ"] = "ֆ",
+ ["Ḁ"] = "ḁ",
+ ["Ḃ"] = "ḃ",
+ ["Ḅ"] = "ḅ",
+ ["Ḇ"] = "ḇ",
+ ["Ḉ"] = "ḉ",
+ ["Ḋ"] = "ḋ",
+ ["Ḍ"] = "ḍ",
+ ["Ḏ"] = "ḏ",
+ ["Ḑ"] = "ḑ",
+ ["Ḓ"] = "ḓ",
+ ["Ḕ"] = "ḕ",
+ ["Ḗ"] = "ḗ",
+ ["Ḙ"] = "ḙ",
+ ["Ḛ"] = "ḛ",
+ ["Ḝ"] = "ḝ",
+ ["Ḟ"] = "ḟ",
+ ["Ḡ"] = "ḡ",
+ ["Ḣ"] = "ḣ",
+ ["Ḥ"] = "ḥ",
+ ["Ḧ"] = "ḧ",
+ ["Ḩ"] = "ḩ",
+ ["Ḫ"] = "ḫ",
+ ["Ḭ"] = "ḭ",
+ ["Ḯ"] = "ḯ",
+ ["Ḱ"] = "ḱ",
+ ["Ḳ"] = "ḳ",
+ ["Ḵ"] = "ḵ",
+ ["Ḷ"] = "ḷ",
+ ["Ḹ"] = "ḹ",
+ ["Ḻ"] = "ḻ",
+ ["Ḽ"] = "ḽ",
+ ["Ḿ"] = "ḿ",
+ ["Ṁ"] = "ṁ",
+ ["Ṃ"] = "ṃ",
+ ["Ṅ"] = "ṅ",
+ ["Ṇ"] = "ṇ",
+ ["Ṉ"] = "ṉ",
+ ["Ṋ"] = "ṋ",
+ ["Ṍ"] = "ṍ",
+ ["Ṏ"] = "ṏ",
+ ["Ṑ"] = "ṑ",
+ ["Ṓ"] = "ṓ",
+ ["Ṕ"] = "ṕ",
+ ["Ṗ"] = "ṗ",
+ ["Ṙ"] = "ṙ",
+ ["Ṛ"] = "ṛ",
+ ["Ṝ"] = "ṝ",
+ ["Ṟ"] = "ṟ",
+ ["Ṡ"] = "ṡ",
+ ["Ṣ"] = "ṣ",
+ ["Ṥ"] = "ṥ",
+ ["Ṧ"] = "ṧ",
+ ["Ṩ"] = "ṩ",
+ ["Ṫ"] = "ṫ",
+ ["Ṭ"] = "ṭ",
+ ["Ṯ"] = "ṯ",
+ ["Ṱ"] = "ṱ",
+ ["Ṳ"] = "ṳ",
+ ["Ṵ"] = "ṵ",
+ ["Ṷ"] = "ṷ",
+ ["Ṹ"] = "ṹ",
+ ["Ṻ"] = "ṻ",
+ ["Ṽ"] = "ṽ",
+ ["Ṿ"] = "ṿ",
+ ["Ẁ"] = "ẁ",
+ ["Ẃ"] = "ẃ",
+ ["Ẅ"] = "ẅ",
+ ["Ẇ"] = "ẇ",
+ ["Ẉ"] = "ẉ",
+ ["Ẋ"] = "ẋ",
+ ["Ẍ"] = "ẍ",
+ ["Ẏ"] = "ẏ",
+ ["Ẑ"] = "ẑ",
+ ["Ẓ"] = "ẓ",
+ ["Ẕ"] = "ẕ",
+ ["Ạ"] = "ạ",
+ ["Ả"] = "ả",
+ ["Ấ"] = "ấ",
+ ["Ầ"] = "ầ",
+ ["Ẩ"] = "ẩ",
+ ["Ẫ"] = "ẫ",
+ ["Ậ"] = "ậ",
+ ["Ắ"] = "ắ",
+ ["Ằ"] = "ằ",
+ ["Ẳ"] = "ẳ",
+ ["Ẵ"] = "ẵ",
+ ["Ặ"] = "ặ",
+ ["Ẹ"] = "ẹ",
+ ["Ẻ"] = "ẻ",
+ ["Ẽ"] = "ẽ",
+ ["Ế"] = "ế",
+ ["Ề"] = "ề",
+ ["Ể"] = "ể",
+ ["Ễ"] = "ễ",
+ ["Ệ"] = "ệ",
+ ["Ỉ"] = "ỉ",
+ ["Ị"] = "ị",
+ ["Ọ"] = "ọ",
+ ["Ỏ"] = "ỏ",
+ ["Ố"] = "ố",
+ ["Ồ"] = "ồ",
+ ["Ổ"] = "ổ",
+ ["Ỗ"] = "ỗ",
+ ["Ộ"] = "ộ",
+ ["Ớ"] = "ớ",
+ ["Ờ"] = "ờ",
+ ["Ở"] = "ở",
+ ["Ỡ"] = "ỡ",
+ ["Ợ"] = "ợ",
+ ["Ụ"] = "ụ",
+ ["Ủ"] = "ủ",
+ ["Ứ"] = "ứ",
+ ["Ừ"] = "ừ",
+ ["Ử"] = "ử",
+ ["Ữ"] = "ữ",
+ ["Ự"] = "ự",
+ ["Ỳ"] = "ỳ",
+ ["Ỵ"] = "ỵ",
+ ["Ỷ"] = "ỷ",
+ ["Ỹ"] = "ỹ",
+ ["Ἀ"] = "ἀ",
+ ["Ἁ"] = "ἁ",
+ ["Ἂ"] = "ἂ",
+ ["Ἃ"] = "ἃ",
+ ["Ἄ"] = "ἄ",
+ ["Ἅ"] = "ἅ",
+ ["Ἆ"] = "ἆ",
+ ["Ἇ"] = "ἇ",
+ ["Ἐ"] = "ἐ",
+ ["Ἑ"] = "ἑ",
+ ["Ἒ"] = "ἒ",
+ ["Ἓ"] = "ἓ",
+ ["Ἔ"] = "ἔ",
+ ["Ἕ"] = "ἕ",
+ ["Ἠ"] = "ἠ",
+ ["Ἡ"] = "ἡ",
+ ["Ἢ"] = "ἢ",
+ ["Ἣ"] = "ἣ",
+ ["Ἤ"] = "ἤ",
+ ["Ἥ"] = "ἥ",
+ ["Ἦ"] = "ἦ",
+ ["Ἧ"] = "ἧ",
+ ["Ἰ"] = "ἰ",
+ ["Ἱ"] = "ἱ",
+ ["Ἲ"] = "ἲ",
+ ["Ἳ"] = "ἳ",
+ ["Ἴ"] = "ἴ",
+ ["Ἵ"] = "ἵ",
+ ["Ἶ"] = "ἶ",
+ ["Ἷ"] = "ἷ",
+ ["Ὀ"] = "ὀ",
+ ["Ὁ"] = "ὁ",
+ ["Ὂ"] = "ὂ",
+ ["Ὃ"] = "ὃ",
+ ["Ὄ"] = "ὄ",
+ ["Ὅ"] = "ὅ",
+ ["Ὑ"] = "ὑ",
+ ["Ὓ"] = "ὓ",
+ ["Ὕ"] = "ὕ",
+ ["Ὗ"] = "ὗ",
+ ["Ὠ"] = "ὠ",
+ ["Ὡ"] = "ὡ",
+ ["Ὢ"] = "ὢ",
+ ["Ὣ"] = "ὣ",
+ ["Ὤ"] = "ὤ",
+ ["Ὥ"] = "ὥ",
+ ["Ὦ"] = "ὦ",
+ ["Ὧ"] = "ὧ",
+ ["Ᾰ"] = "ᾰ",
+ ["Ᾱ"] = "ᾱ",
+ ["Ὰ"] = "ὰ",
+ ["Ά"] = "ά",
+ ["Ὲ"] = "ὲ",
+ ["Έ"] = "έ",
+ ["Ὴ"] = "ὴ",
+ ["Ή"] = "ή",
+ ["Ῐ"] = "ῐ",
+ ["Ῑ"] = "ῑ",
+ ["Ὶ"] = "ὶ",
+ ["Ί"] = "ί",
+ ["Ῠ"] = "ῠ",
+ ["Ῡ"] = "ῡ",
+ ["Ὺ"] = "ὺ",
+ ["Ύ"] = "ύ",
+ ["Ῥ"] = "ῥ",
+ ["Ὸ"] = "ὸ",
+ ["Ό"] = "ό",
+ ["Ὼ"] = "ὼ",
+ ["Ώ"] = "ώ",
+ ["Ω"] = "ω",
+ ["K"] = "k",
+ ["Å"] = "å",
+ ["A"] = "a",
+ ["B"] = "b",
+ ["C"] = "c",
+ ["D"] = "d",
+ ["E"] = "e",
+ ["F"] = "f",
+ ["G"] = "g",
+ ["H"] = "h",
+ ["I"] = "i",
+ ["J"] = "j",
+ ["K"] = "k",
+ ["L"] = "l",
+ ["M"] = "m",
+ ["N"] = "n",
+ ["O"] = "o",
+ ["P"] = "p",
+ ["Q"] = "q",
+ ["R"] = "r",
+ ["S"] = "s",
+ ["T"] = "t",
+ ["U"] = "u",
+ ["V"] = "v",
+ ["W"] = "w",
+ ["X"] = "x",
+ ["Y"] = "y",
+ ["Z"] = "z",
+ ["𐐀"] = "𐐨",
+ ["𐐁"] = "𐐩",
+ ["𐐂"] = "𐐪",
+ ["𐐃"] = "𐐫",
+ ["𐐄"] = "𐐬",
+ ["𐐅"] = "𐐭",
+ ["𐐆"] = "𐐮",
+ ["𐐇"] = "𐐯",
+ ["𐐈"] = "𐐰",
+ ["𐐉"] = "𐐱",
+ ["𐐊"] = "𐐲",
+ ["𐐋"] = "𐐳",
+ ["𐐌"] = "𐐴",
+ ["𐐍"] = "𐐵",
+ ["𐐎"] = "𐐶",
+ ["𐐏"] = "𐐷",
+ ["𐐐"] = "𐐸",
+ ["𐐑"] = "𐐹",
+ ["𐐒"] = "𐐺",
+ ["𐐓"] = "𐐻",
+ ["𐐔"] = "𐐼",
+ ["𐐕"] = "𐐽",
+ ["𐐖"] = "𐐾",
+ ["𐐗"] = "𐐿",
+ ["𐐘"] = "𐑀",
+ ["𐐙"] = "𐑁",
+ ["𐐚"] = "𐑂",
+ ["𐐛"] = "𐑃",
+ ["𐐜"] = "𐑄",
+ ["𐐝"] = "𐑅",
+ ["𐐞"] = "𐑆",
+ ["𐐟"] = "𐑇",
+ ["𐐠"] = "𐑈",
+ ["𐐡"] = "𐑉",
+ ["𐐢"] = "𐑊",
+ ["𐐣"] = "𐑋",
+ ["𐐤"] = "𐑌",
+ ["𐐥"] = "𐑍",
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-normalization-table.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-normalization-table.php
new file mode 100755
index 00000000..f35ff7a4
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-normalization-table.php
@@ -0,0 +1,237 @@
+#!/usr/bin/php
+<?php
+
+if ( PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ) {
+ die( "This script may only be executed from the command line.\n" );
+}
+
+$datafile = null;
+if ( count( $argv ) > 1 ) {
+ $datafile = $argv[1];
+ if ( !file_exists( $datafile ) ) {
+ die( "The specified file '$datafile' does not exist\n" );
+ }
+} else {
+ foreach ( [
+ __DIR__ . '/../../../../../../core/vendor/wikimedia/utfnormal/src/UtfNormalData.inc',
+ __DIR__ . '/../../../../../../vendor/wikimedia/utfnormal/src/UtfNormalData.inc',
+ ] as $tryfile ) {
+ $tryfile = realpath( $tryfile );
+ if ( file_exists( $tryfile ) ) {
+ $datafile = $tryfile;
+ break;
+ }
+ }
+ if ( !$datafile ) {
+ die( "Cannot find UtfNormalData.inc. Please specify the path explicitly.\n" );
+ }
+}
+
+$datafileK = null;
+if ( count( $argv ) > 2 ) {
+ $datafileK = $argv[2];
+ if ( !file_exists( $datafileK ) ) {
+ die( "The specified file '$datafileK' does not exist\n" );
+ }
+} else {
+ foreach ( [
+ dirname( $datafile ) . '/UtfNormalDataK.inc',
+ __DIR__ . '/../../../../../../core/vendor/wikimedia/utfnormal/src/UtfNormalData.inc',
+ __DIR__ . '/../../../../../../vendor/wikimedia/utfnormal/src/UtfNormalData.inc',
+ ] as $tryfile ) {
+ $tryfile = realpath( $tryfile );
+ if ( file_exists( $tryfile ) ) {
+ $datafileK = $tryfile;
+ break;
+ }
+ }
+ if ( !$datafileK ) {
+ die( "Cannot find UtfNormalDataK.inc. Please specify the path explicitly.\n" );
+ }
+}
+
+class UtfNormal {
+ public static $utfCheckNFC = null;
+ public static $utfCombiningClass = null;
+ public static $utfCanonicalDecomp = null;
+ public static $utfCanonicalComp = null;
+ public static $utfCompatibilityDecomp = null;
+}
+class_alias( UtfNormal::class, \UtfNormal\Validator::class );
+
+echo "Loading data file $datafile...\n";
+require_once $datafile;
+
+echo "Loading data file $datafileK...\n";
+require_once $datafileK;
+
+if ( !UtfNormal::$utfCheckNFC ||
+ !UtfNormal::$utfCombiningClass ||
+ !UtfNormal::$utfCanonicalDecomp ||
+ !UtfNormal::$utfCanonicalComp
+) {
+ die( "Data file $datafile did not contain needed data.\n" );
+}
+if ( !UtfNormal::$utfCompatibilityDecomp ) {
+ die( "Data file $datafileK did not contain needed data.\n" );
+}
+
+// @codingStandardsIgnoreLine MediaWiki.NamingConventions.PrefixedGlobalFunctions
+function uord( $c, $firstOnly ) {
+ $ret = unpack( 'N*', mb_convert_encoding( $c, 'UTF-32BE', 'UTF-8' ) );
+ return $firstOnly ? $ret[1] : $ret;
+}
+
+echo "Creating normalization table...\n";
+$X = fopen( __DIR__ . '/normalization-data.lua', 'w' );
+if ( !$X ) {
+ die( "Failed to open normalization-data.lua\n" );
+}
+fprintf( $X, "-- This file is automatically generated by make-normalization-table.php\n" );
+fprintf( $X, "local normal = {\n" );
+fprintf( $X, "\t-- Characters that might change depending on the following combiner\n" );
+fprintf( $X, "\t-- (minus any that are themselves combiners, those are added later)\n" );
+fprintf( $X, "\tcheck = {\n" );
+foreach ( UtfNormal::$utfCheckNFC as $k => $v ) {
+ if ( isset( UtfNormal::$utfCombiningClass[$k] ) ) {
+ // Skip, because it's in the other table already
+ continue;
+ }
+ fprintf( $X, "\t\t[0x%06x] = 1,\n", uord( $k, true ) );
+}
+fprintf( $X, "\t},\n\n" );
+fprintf( $X, "\t-- Combining characters, mapped to combining class\n" );
+fprintf( $X, "\tcombclass = {\n" );
+$comb = [];
+foreach ( UtfNormal::$utfCombiningClass as $k => $v ) {
+ $cp = uord( $k, true );
+ $comb[$cp] = 1;
+ fprintf( $X, "\t\t[0x%06x] = %d,\n", $cp, $v );
+}
+fprintf( $X, "\t},\n\n" );
+fprintf( $X, "\t-- Characters mapped to what they decompose to\n" );
+fprintf( $X, "\t-- Note Hangul to Jamo is done separately below\n" );
+fprintf( $X, "\tdecomp = {\n" );
+foreach ( UtfNormal::$utfCanonicalDecomp as $k => $v ) {
+ fprintf( $X, "\t\t[0x%06x] = { ", uord( $k, true ) );
+ $fmt = "0x%06x";
+ foreach ( uord( $v, false ) as $c ) {
+ fprintf( $X, $fmt, $c );
+ $fmt = ", 0x%06x";
+ }
+ fprintf( $X, " },\n" );
+}
+fprintf( $X, "\t},\n\n" );
+
+fprintf( $X, "\tdecompK = {\n" );
+foreach ( UtfNormal::$utfCompatibilityDecomp as $k => $v ) {
+ if ( isset( UtfNormal::$utfCanonicalDecomp[$k] ) && UtfNormal::$utfCanonicalDecomp[$k] === $v ) {
+ // Skip duplicates
+ continue;
+ }
+ fprintf( $X, "\t\t[0x%06x] = { ", uord( $k, true ) );
+ $fmt = "0x%06x";
+ foreach ( uord( $v, false ) as $c ) {
+ fprintf( $X, $fmt, $c );
+ $fmt = ", 0x%06x";
+ }
+ fprintf( $X, " },\n" );
+}
+fprintf( $X, "\t},\n\n" );
+
+fprintf( $X, "\t-- Character-pairs mapped to what they compose to\n" );
+fprintf( $X, "\t-- Note Jamo to Hangul is done separately below\n" );
+$t = [];
+foreach ( UtfNormal::$utfCanonicalComp as $k => $v ) {
+ $k = uord( $k, false );
+ if ( count( $k ) == 1 ) {
+ // No idea why these are in the file
+ continue;
+ }
+ if ( isset( $comb[$k[1]] ) ) {
+ // Non-starter, no idea why these are in the file either
+ continue;
+ }
+ $t[$k[1]][$k[2]] = uord( $v, true );
+}
+fprintf( $X, "\tcomp = {\n" );
+ksort( $t );
+foreach ( $t as $k1 => $v1 ) {
+ fprintf( $X, "\t\t[0x%06x] = {\n", $k1 );
+ ksort( $v1 );
+ foreach ( $v1 as $k2 => $v2 ) {
+ if ( $k2 < 0 ) {
+ fprintf( $X, "\t\t\t[-1] = 0x%06x,\n", $v2 );
+ } else {
+ fprintf( $X, "\t\t\t[0x%06x] = 0x%06x,\n", $k2, $v2 );
+ }
+ }
+ fprintf( $X, "\t\t},\n" );
+}
+fprintf( $X, "\t},\n" );
+
+fprintf( $X, "}\n" );
+
+fprintf( $X, "\n%s\n", <<<LUA
+-- All combining characters need to be checked, so just do that
+setmetatable( normal.check, { __index = normal.combclass } )
+
+-- Handle Hangul to Jamo decomposition
+setmetatable( normal.decomp, { __index = function ( _, k )
+ if k >= 0xac00 and k <= 0xd7a3 then
+ -- Decompose a Hangul syllable into Jamo
+ k = k - 0xac00
+ local ret = {
+ 0x1100 + math.floor( k / 588 ),
+ 0x1161 + math.floor( ( k % 588 ) / 28 )
+ }
+ if k % 28 ~= 0 then
+ ret[3] = 0x11a7 + ( k % 28 )
+ end
+ return ret
+ end
+ return nil
+end } )
+
+-- Handle Jamo to Hangul composition
+local jamo_l_v_mt = { __index = function ( t, k )
+ if k >= 0x1161 and k <= 0x1175 then
+ -- Jamo leading + Jamo vowel
+ return t.base + 28 * ( k - 0x1161 )
+ end
+ return nil
+end }
+local hangul_jamo_mt = { __index = function ( t, k )
+ if k >= 0x11a7 and k <= 0x11c2 then
+ -- Hangul + jamo final
+ return t.base + k - 0x11a7
+ end
+ return nil
+end }
+setmetatable( normal.comp, { __index = function ( t, k )
+ if k >= 0x1100 and k <= 0x1112 then
+ -- Jamo leading, return a second table that combines with a Jamo vowel
+ local t2 = { base = 0xac00 + 588 * ( k - 0x1100 ) }
+ setmetatable( t2, jamo_l_v_mt )
+ t[k] = t2 -- cache it
+ return t2
+ elseif k >= 0xac00 and k <= 0xd7a3 and k % 28 == 16 then
+ -- Hangul. "k % 28 == 16" picks out just the ones that are
+ -- Jamo leading + vowel, no final. Return a second table that combines
+ -- with a Jamo final.
+ local t2 = { base = k }
+ setmetatable( t2, hangul_jamo_mt )
+ t[k] = t2 -- cache it
+ return t2
+ end
+ return nil
+end } )
+
+-- Compatibility decomposition falls back to the normal decomposition
+setmetatable( normal.decompK, { __index = normal.decomp } )
+
+return normal
+LUA
+);
+
+fclose( $X );
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-tables.php b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-tables.php
new file mode 100755
index 00000000..feeb5fa1
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/make-tables.php
@@ -0,0 +1,154 @@
+#!/usr/bin/php
+<?php
+
+if ( PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' ) {
+ die( "This script may only be executed from the command line.\n" );
+}
+
+$chars = [];
+for ( $i = 0; $i <= 0x10ffff; $i++ ) {
+ if ( $i < 0xd800 || $i > 0xdfff ) { // Skip UTF-16 surrogates
+ $chars[$i] = mb_convert_encoding( pack( 'N', $i ), 'UTF-8', 'UTF-32BE' );
+ }
+}
+
+### Uppercase and Lowercase mappings
+echo "Creating upper and lower tables...\n";
+$L = fopen( __DIR__ . '/lower.lua', 'w' );
+if ( !$L ) {
+ die( "Failed to open lower.lua\n" );
+}
+$U = fopen( __DIR__ . '/upper.lua', 'w' );
+if ( !$U ) {
+ die( "Failed to open upper.lua\n" );
+}
+fprintf( $L, "-- This file is automatically generated by make-tables.php\n" );
+fprintf( $L, "return {\n" );
+fprintf( $U, "-- This file is automatically generated by make-tables.php\n" );
+fprintf( $U, "return {\n" );
+foreach ( $chars as $i => $c ) {
+ $l = mb_strtolower( $c, 'UTF-8' );
+ $u = mb_strtoupper( $c, 'UTF-8' );
+ if ( $c !== $l ) {
+ fprintf( $L, "\t[\"%s\"] = \"%s\",\n", $c, $l );
+ }
+ if ( $c !== $u ) {
+ fprintf( $U, "\t[\"%s\"] = \"%s\",\n", $c, $u );
+ }
+}
+fprintf( $L, "}\n" );
+fprintf( $U, "}\n" );
+fclose( $L );
+fclose( $U );
+
+### Pattern code mappings
+echo "Creating charsets table...\n";
+$fh = fopen( __DIR__ . '/charsets.lua', 'w' );
+if ( !$fh ) {
+ die( "Failed to open charsets.lua\n" );
+}
+$pats = [
+ // These should match the expressions in UstringLibrary::patternToRegex()
+ 'a' => [ '\p{L}', 'lu' ],
+ 'c' => [ '\p{Cc}', null ],
+ 'd' => [ '\p{Nd}', null ],
+ 'l' => [ '\p{Ll}', null ],
+ 'p' => [ '\p{P}', null ],
+ 's' => [ '\p{Xps}', null ],
+ 'u' => [ '\p{Lu}', null ],
+ 'w' => [ null, 'da' ], # '[\p{L}\p{Nd}]' exactly matches 'a' + 'd'
+ 'x' => [ '[0-9A-Fa-f0-9A-Fa-f]', null ],
+ 'z' => [ '\0', null ],
+];
+
+$ranges = [];
+// @codingStandardsIgnoreLine MediaWiki.NamingConventions.PrefixedGlobalFunctions
+function addRange( $k, $start, $end ) {
+ // @codingStandardsIgnoreLine MediaWiki.NamingConventions.ValidGlobalName
+ global $fh, $ranges;
+ // Speed/memory tradeoff
+ if ( !( $start >= 0x20 && $start < 0x7f ) && $end - $start >= 10 ) {
+ $ranges[$k][] = sprintf( "c >= 0x%06x and c < 0x%06x", $start, $end );
+ } else {
+ for ( $i = $start; $i < $end; $i++ ) {
+ fprintf( $fh, "\t\t[0x%06x] = 1,\n", $i );
+ }
+ }
+}
+
+fprintf( $fh, "-- This file is automatically generated by make-tables.php\n" );
+fprintf( $fh, "local pats = {\n" );
+foreach ( $pats as $k => $pp ) {
+ $ranges[$k] = [];
+ $re = $pp[0];
+ if ( !$re ) {
+ fprintf( $fh, "\t[0x%02x] = {},\n", ord( $k ) );
+ continue;
+ }
+
+ $re2 = 'fail';
+ if ( $pp[1] ) {
+ $re2 = [];
+ foreach ( str_split( $pp[1] ) as $p ) {
+ $re2[] = $pats[$p][0];
+ }
+ $re2 = implode( '|', $re2 );
+ }
+
+ fprintf( $fh, "\t[0x%02x] = {\n", ord( $k ) );
+ $rstart = null;
+ foreach ( $chars as $i => $c ) {
+ if ( preg_match( "/^$re$/u", $c ) && !preg_match( "/^$re2$/u", $c ) ) {
+ if ( $rstart === null ) {
+ $rstart = $i;
+ }
+ } else {
+ if ( $rstart !== null ) {
+ addRange( $k, $rstart, $i );
+ $rstart = null;
+ }
+ }
+ }
+ if ( $rstart !== null ) {
+ addRange( $k, $rstart, 0x110000 );
+ }
+ fprintf( $fh, "\t},\n" );
+}
+foreach ( $pats as $k => $pp ) {
+ $kk = strtoupper( $k );
+ fprintf( $fh, "\t[0x%02x] = {},\n", ord( $kk ) );
+}
+fprintf( $fh, "}\n" );
+foreach ( $pats as $k => $pp ) {
+ $body = '';
+ $check = [];
+ if ( $pp[1] ) {
+ foreach ( str_split( $pp[1] ) as $p ) {
+ $check[] = sprintf( "pats[0x%02x][k]", ord( $p ) );
+ }
+ }
+ if ( $ranges[$k] ) {
+ $body = "\tlocal c = tonumber( k ) or 0/0;\n";
+ $check = array_merge( $check, $ranges[$k] );
+ }
+ if ( $check ) {
+ $body .= "\treturn " . implode( " or\n\t\t", $check );
+ fprintf( $fh, "setmetatable( pats[0x%02x], { __index = function ( t, k )\n%s\nend } )\n",
+ ord( $k ), $body );
+ }
+}
+foreach ( $pats as $k => $pp ) {
+ fprintf( $fh, "setmetatable( pats[0x%02x], { ", ord( strtoupper( $k ) ) );
+ fprintf( $fh, "__index = function ( t, k ) return k and not pats[0x%02x][k] end", ord( $k ) );
+ fprintf( $fh, " } )\n" );
+}
+fprintf( $fh, "\n-- For speed, cache printable ASCII characters in main tables\n" );
+fprintf( $fh, "for k, t in pairs( pats ) do\n" );
+fprintf( $fh, "\tif k >= 0x61 then\n" );
+fprintf( $fh, "\t\tfor i = 0x20, 0x7e do\n" );
+fprintf( $fh, "\t\t\tt[i] = t[i] or false\n" );
+fprintf( $fh, "\t\tend\n" );
+fprintf( $fh, "\tend\n" );
+fprintf( $fh, "end\n" );
+fprintf( $fh, "\nreturn pats\n" );
+fclose( $fh );
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/normalization-data.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/normalization-data.lua
new file mode 100644
index 00000000..5d110c41
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/normalization-data.lua
@@ -0,0 +1,9450 @@
+-- This file is automatically generated by make-normalization-table.php
+local normal = {
+ -- Characters that might change depending on the following combiner
+ -- (minus any that are themselves combiners, those are added later)
+ check = {
+ [0x000374] = 1,
+ [0x00037e] = 1,
+ [0x000387] = 1,
+ [0x000958] = 1,
+ [0x000959] = 1,
+ [0x00095a] = 1,
+ [0x00095b] = 1,
+ [0x00095c] = 1,
+ [0x00095d] = 1,
+ [0x00095e] = 1,
+ [0x00095f] = 1,
+ [0x0009dc] = 1,
+ [0x0009dd] = 1,
+ [0x0009df] = 1,
+ [0x000a33] = 1,
+ [0x000a36] = 1,
+ [0x000a59] = 1,
+ [0x000a5a] = 1,
+ [0x000a5b] = 1,
+ [0x000a5e] = 1,
+ [0x000b5c] = 1,
+ [0x000b5d] = 1,
+ [0x000f43] = 1,
+ [0x000f4d] = 1,
+ [0x000f52] = 1,
+ [0x000f57] = 1,
+ [0x000f5c] = 1,
+ [0x000f69] = 1,
+ [0x000f73] = 1,
+ [0x000f75] = 1,
+ [0x000f76] = 1,
+ [0x000f78] = 1,
+ [0x000f81] = 1,
+ [0x000f93] = 1,
+ [0x000f9d] = 1,
+ [0x000fa2] = 1,
+ [0x000fa7] = 1,
+ [0x000fac] = 1,
+ [0x000fb9] = 1,
+ [0x001f71] = 1,
+ [0x001f73] = 1,
+ [0x001f75] = 1,
+ [0x001f77] = 1,
+ [0x001f79] = 1,
+ [0x001f7b] = 1,
+ [0x001f7d] = 1,
+ [0x001fbb] = 1,
+ [0x001fbe] = 1,
+ [0x001fc9] = 1,
+ [0x001fcb] = 1,
+ [0x001fd3] = 1,
+ [0x001fdb] = 1,
+ [0x001fe3] = 1,
+ [0x001feb] = 1,
+ [0x001fee] = 1,
+ [0x001fef] = 1,
+ [0x001ff9] = 1,
+ [0x001ffb] = 1,
+ [0x001ffd] = 1,
+ [0x002000] = 1,
+ [0x002001] = 1,
+ [0x002126] = 1,
+ [0x00212a] = 1,
+ [0x00212b] = 1,
+ [0x002329] = 1,
+ [0x00232a] = 1,
+ [0x002adc] = 1,
+ [0x00f900] = 1,
+ [0x00f901] = 1,
+ [0x00f902] = 1,
+ [0x00f903] = 1,
+ [0x00f904] = 1,
+ [0x00f905] = 1,
+ [0x00f906] = 1,
+ [0x00f907] = 1,
+ [0x00f908] = 1,
+ [0x00f909] = 1,
+ [0x00f90a] = 1,
+ [0x00f90b] = 1,
+ [0x00f90c] = 1,
+ [0x00f90d] = 1,
+ [0x00f90e] = 1,
+ [0x00f90f] = 1,
+ [0x00f910] = 1,
+ [0x00f911] = 1,
+ [0x00f912] = 1,
+ [0x00f913] = 1,
+ [0x00f914] = 1,
+ [0x00f915] = 1,
+ [0x00f916] = 1,
+ [0x00f917] = 1,
+ [0x00f918] = 1,
+ [0x00f919] = 1,
+ [0x00f91a] = 1,
+ [0x00f91b] = 1,
+ [0x00f91c] = 1,
+ [0x00f91d] = 1,
+ [0x00f91e] = 1,
+ [0x00f91f] = 1,
+ [0x00f920] = 1,
+ [0x00f921] = 1,
+ [0x00f922] = 1,
+ [0x00f923] = 1,
+ [0x00f924] = 1,
+ [0x00f925] = 1,
+ [0x00f926] = 1,
+ [0x00f927] = 1,
+ [0x00f928] = 1,
+ [0x00f929] = 1,
+ [0x00f92a] = 1,
+ [0x00f92b] = 1,
+ [0x00f92c] = 1,
+ [0x00f92d] = 1,
+ [0x00f92e] = 1,
+ [0x00f92f] = 1,
+ [0x00f930] = 1,
+ [0x00f931] = 1,
+ [0x00f932] = 1,
+ [0x00f933] = 1,
+ [0x00f934] = 1,
+ [0x00f935] = 1,
+ [0x00f936] = 1,
+ [0x00f937] = 1,
+ [0x00f938] = 1,
+ [0x00f939] = 1,
+ [0x00f93a] = 1,
+ [0x00f93b] = 1,
+ [0x00f93c] = 1,
+ [0x00f93d] = 1,
+ [0x00f93e] = 1,
+ [0x00f93f] = 1,
+ [0x00f940] = 1,
+ [0x00f941] = 1,
+ [0x00f942] = 1,
+ [0x00f943] = 1,
+ [0x00f944] = 1,
+ [0x00f945] = 1,
+ [0x00f946] = 1,
+ [0x00f947] = 1,
+ [0x00f948] = 1,
+ [0x00f949] = 1,
+ [0x00f94a] = 1,
+ [0x00f94b] = 1,
+ [0x00f94c] = 1,
+ [0x00f94d] = 1,
+ [0x00f94e] = 1,
+ [0x00f94f] = 1,
+ [0x00f950] = 1,
+ [0x00f951] = 1,
+ [0x00f952] = 1,
+ [0x00f953] = 1,
+ [0x00f954] = 1,
+ [0x00f955] = 1,
+ [0x00f956] = 1,
+ [0x00f957] = 1,
+ [0x00f958] = 1,
+ [0x00f959] = 1,
+ [0x00f95a] = 1,
+ [0x00f95b] = 1,
+ [0x00f95c] = 1,
+ [0x00f95d] = 1,
+ [0x00f95e] = 1,
+ [0x00f95f] = 1,
+ [0x00f960] = 1,
+ [0x00f961] = 1,
+ [0x00f962] = 1,
+ [0x00f963] = 1,
+ [0x00f964] = 1,
+ [0x00f965] = 1,
+ [0x00f966] = 1,
+ [0x00f967] = 1,
+ [0x00f968] = 1,
+ [0x00f969] = 1,
+ [0x00f96a] = 1,
+ [0x00f96b] = 1,
+ [0x00f96c] = 1,
+ [0x00f96d] = 1,
+ [0x00f96e] = 1,
+ [0x00f96f] = 1,
+ [0x00f970] = 1,
+ [0x00f971] = 1,
+ [0x00f972] = 1,
+ [0x00f973] = 1,
+ [0x00f974] = 1,
+ [0x00f975] = 1,
+ [0x00f976] = 1,
+ [0x00f977] = 1,
+ [0x00f978] = 1,
+ [0x00f979] = 1,
+ [0x00f97a] = 1,
+ [0x00f97b] = 1,
+ [0x00f97c] = 1,
+ [0x00f97d] = 1,
+ [0x00f97e] = 1,
+ [0x00f97f] = 1,
+ [0x00f980] = 1,
+ [0x00f981] = 1,
+ [0x00f982] = 1,
+ [0x00f983] = 1,
+ [0x00f984] = 1,
+ [0x00f985] = 1,
+ [0x00f986] = 1,
+ [0x00f987] = 1,
+ [0x00f988] = 1,
+ [0x00f989] = 1,
+ [0x00f98a] = 1,
+ [0x00f98b] = 1,
+ [0x00f98c] = 1,
+ [0x00f98d] = 1,
+ [0x00f98e] = 1,
+ [0x00f98f] = 1,
+ [0x00f990] = 1,
+ [0x00f991] = 1,
+ [0x00f992] = 1,
+ [0x00f993] = 1,
+ [0x00f994] = 1,
+ [0x00f995] = 1,
+ [0x00f996] = 1,
+ [0x00f997] = 1,
+ [0x00f998] = 1,
+ [0x00f999] = 1,
+ [0x00f99a] = 1,
+ [0x00f99b] = 1,
+ [0x00f99c] = 1,
+ [0x00f99d] = 1,
+ [0x00f99e] = 1,
+ [0x00f99f] = 1,
+ [0x00f9a0] = 1,
+ [0x00f9a1] = 1,
+ [0x00f9a2] = 1,
+ [0x00f9a3] = 1,
+ [0x00f9a4] = 1,
+ [0x00f9a5] = 1,
+ [0x00f9a6] = 1,
+ [0x00f9a7] = 1,
+ [0x00f9a8] = 1,
+ [0x00f9a9] = 1,
+ [0x00f9aa] = 1,
+ [0x00f9ab] = 1,
+ [0x00f9ac] = 1,
+ [0x00f9ad] = 1,
+ [0x00f9ae] = 1,
+ [0x00f9af] = 1,
+ [0x00f9b0] = 1,
+ [0x00f9b1] = 1,
+ [0x00f9b2] = 1,
+ [0x00f9b3] = 1,
+ [0x00f9b4] = 1,
+ [0x00f9b5] = 1,
+ [0x00f9b6] = 1,
+ [0x00f9b7] = 1,
+ [0x00f9b8] = 1,
+ [0x00f9b9] = 1,
+ [0x00f9ba] = 1,
+ [0x00f9bb] = 1,
+ [0x00f9bc] = 1,
+ [0x00f9bd] = 1,
+ [0x00f9be] = 1,
+ [0x00f9bf] = 1,
+ [0x00f9c0] = 1,
+ [0x00f9c1] = 1,
+ [0x00f9c2] = 1,
+ [0x00f9c3] = 1,
+ [0x00f9c4] = 1,
+ [0x00f9c5] = 1,
+ [0x00f9c6] = 1,
+ [0x00f9c7] = 1,
+ [0x00f9c8] = 1,
+ [0x00f9c9] = 1,
+ [0x00f9ca] = 1,
+ [0x00f9cb] = 1,
+ [0x00f9cc] = 1,
+ [0x00f9cd] = 1,
+ [0x00f9ce] = 1,
+ [0x00f9cf] = 1,
+ [0x00f9d0] = 1,
+ [0x00f9d1] = 1,
+ [0x00f9d2] = 1,
+ [0x00f9d3] = 1,
+ [0x00f9d4] = 1,
+ [0x00f9d5] = 1,
+ [0x00f9d6] = 1,
+ [0x00f9d7] = 1,
+ [0x00f9d8] = 1,
+ [0x00f9d9] = 1,
+ [0x00f9da] = 1,
+ [0x00f9db] = 1,
+ [0x00f9dc] = 1,
+ [0x00f9dd] = 1,
+ [0x00f9de] = 1,
+ [0x00f9df] = 1,
+ [0x00f9e0] = 1,
+ [0x00f9e1] = 1,
+ [0x00f9e2] = 1,
+ [0x00f9e3] = 1,
+ [0x00f9e4] = 1,
+ [0x00f9e5] = 1,
+ [0x00f9e6] = 1,
+ [0x00f9e7] = 1,
+ [0x00f9e8] = 1,
+ [0x00f9e9] = 1,
+ [0x00f9ea] = 1,
+ [0x00f9eb] = 1,
+ [0x00f9ec] = 1,
+ [0x00f9ed] = 1,
+ [0x00f9ee] = 1,
+ [0x00f9ef] = 1,
+ [0x00f9f0] = 1,
+ [0x00f9f1] = 1,
+ [0x00f9f2] = 1,
+ [0x00f9f3] = 1,
+ [0x00f9f4] = 1,
+ [0x00f9f5] = 1,
+ [0x00f9f6] = 1,
+ [0x00f9f7] = 1,
+ [0x00f9f8] = 1,
+ [0x00f9f9] = 1,
+ [0x00f9fa] = 1,
+ [0x00f9fb] = 1,
+ [0x00f9fc] = 1,
+ [0x00f9fd] = 1,
+ [0x00f9fe] = 1,
+ [0x00f9ff] = 1,
+ [0x00fa00] = 1,
+ [0x00fa01] = 1,
+ [0x00fa02] = 1,
+ [0x00fa03] = 1,
+ [0x00fa04] = 1,
+ [0x00fa05] = 1,
+ [0x00fa06] = 1,
+ [0x00fa07] = 1,
+ [0x00fa08] = 1,
+ [0x00fa09] = 1,
+ [0x00fa0a] = 1,
+ [0x00fa0b] = 1,
+ [0x00fa0c] = 1,
+ [0x00fa0d] = 1,
+ [0x00fa10] = 1,
+ [0x00fa12] = 1,
+ [0x00fa15] = 1,
+ [0x00fa16] = 1,
+ [0x00fa17] = 1,
+ [0x00fa18] = 1,
+ [0x00fa19] = 1,
+ [0x00fa1a] = 1,
+ [0x00fa1b] = 1,
+ [0x00fa1c] = 1,
+ [0x00fa1d] = 1,
+ [0x00fa1e] = 1,
+ [0x00fa20] = 1,
+ [0x00fa22] = 1,
+ [0x00fa25] = 1,
+ [0x00fa26] = 1,
+ [0x00fa2a] = 1,
+ [0x00fa2b] = 1,
+ [0x00fa2c] = 1,
+ [0x00fa2d] = 1,
+ [0x00fa2e] = 1,
+ [0x00fa2f] = 1,
+ [0x00fa30] = 1,
+ [0x00fa31] = 1,
+ [0x00fa32] = 1,
+ [0x00fa33] = 1,
+ [0x00fa34] = 1,
+ [0x00fa35] = 1,
+ [0x00fa36] = 1,
+ [0x00fa37] = 1,
+ [0x00fa38] = 1,
+ [0x00fa39] = 1,
+ [0x00fa3a] = 1,
+ [0x00fa3b] = 1,
+ [0x00fa3c] = 1,
+ [0x00fa3d] = 1,
+ [0x00fa3e] = 1,
+ [0x00fa3f] = 1,
+ [0x00fa40] = 1,
+ [0x00fa41] = 1,
+ [0x00fa42] = 1,
+ [0x00fa43] = 1,
+ [0x00fa44] = 1,
+ [0x00fa45] = 1,
+ [0x00fa46] = 1,
+ [0x00fa47] = 1,
+ [0x00fa48] = 1,
+ [0x00fa49] = 1,
+ [0x00fa4a] = 1,
+ [0x00fa4b] = 1,
+ [0x00fa4c] = 1,
+ [0x00fa4d] = 1,
+ [0x00fa4e] = 1,
+ [0x00fa4f] = 1,
+ [0x00fa50] = 1,
+ [0x00fa51] = 1,
+ [0x00fa52] = 1,
+ [0x00fa53] = 1,
+ [0x00fa54] = 1,
+ [0x00fa55] = 1,
+ [0x00fa56] = 1,
+ [0x00fa57] = 1,
+ [0x00fa58] = 1,
+ [0x00fa59] = 1,
+ [0x00fa5a] = 1,
+ [0x00fa5b] = 1,
+ [0x00fa5c] = 1,
+ [0x00fa5d] = 1,
+ [0x00fa5e] = 1,
+ [0x00fa5f] = 1,
+ [0x00fa60] = 1,
+ [0x00fa61] = 1,
+ [0x00fa62] = 1,
+ [0x00fa63] = 1,
+ [0x00fa64] = 1,
+ [0x00fa65] = 1,
+ [0x00fa66] = 1,
+ [0x00fa67] = 1,
+ [0x00fa68] = 1,
+ [0x00fa69] = 1,
+ [0x00fa6a] = 1,
+ [0x00fa6b] = 1,
+ [0x00fa6c] = 1,
+ [0x00fa6d] = 1,
+ [0x00fa70] = 1,
+ [0x00fa71] = 1,
+ [0x00fa72] = 1,
+ [0x00fa73] = 1,
+ [0x00fa74] = 1,
+ [0x00fa75] = 1,
+ [0x00fa76] = 1,
+ [0x00fa77] = 1,
+ [0x00fa78] = 1,
+ [0x00fa79] = 1,
+ [0x00fa7a] = 1,
+ [0x00fa7b] = 1,
+ [0x00fa7c] = 1,
+ [0x00fa7d] = 1,
+ [0x00fa7e] = 1,
+ [0x00fa7f] = 1,
+ [0x00fa80] = 1,
+ [0x00fa81] = 1,
+ [0x00fa82] = 1,
+ [0x00fa83] = 1,
+ [0x00fa84] = 1,
+ [0x00fa85] = 1,
+ [0x00fa86] = 1,
+ [0x00fa87] = 1,
+ [0x00fa88] = 1,
+ [0x00fa89] = 1,
+ [0x00fa8a] = 1,
+ [0x00fa8b] = 1,
+ [0x00fa8c] = 1,
+ [0x00fa8d] = 1,
+ [0x00fa8e] = 1,
+ [0x00fa8f] = 1,
+ [0x00fa90] = 1,
+ [0x00fa91] = 1,
+ [0x00fa92] = 1,
+ [0x00fa93] = 1,
+ [0x00fa94] = 1,
+ [0x00fa95] = 1,
+ [0x00fa96] = 1,
+ [0x00fa97] = 1,
+ [0x00fa98] = 1,
+ [0x00fa99] = 1,
+ [0x00fa9a] = 1,
+ [0x00fa9b] = 1,
+ [0x00fa9c] = 1,
+ [0x00fa9d] = 1,
+ [0x00fa9e] = 1,
+ [0x00fa9f] = 1,
+ [0x00faa0] = 1,
+ [0x00faa1] = 1,
+ [0x00faa2] = 1,
+ [0x00faa3] = 1,
+ [0x00faa4] = 1,
+ [0x00faa5] = 1,
+ [0x00faa6] = 1,
+ [0x00faa7] = 1,
+ [0x00faa8] = 1,
+ [0x00faa9] = 1,
+ [0x00faaa] = 1,
+ [0x00faab] = 1,
+ [0x00faac] = 1,
+ [0x00faad] = 1,
+ [0x00faae] = 1,
+ [0x00faaf] = 1,
+ [0x00fab0] = 1,
+ [0x00fab1] = 1,
+ [0x00fab2] = 1,
+ [0x00fab3] = 1,
+ [0x00fab4] = 1,
+ [0x00fab5] = 1,
+ [0x00fab6] = 1,
+ [0x00fab7] = 1,
+ [0x00fab8] = 1,
+ [0x00fab9] = 1,
+ [0x00faba] = 1,
+ [0x00fabb] = 1,
+ [0x00fabc] = 1,
+ [0x00fabd] = 1,
+ [0x00fabe] = 1,
+ [0x00fabf] = 1,
+ [0x00fac0] = 1,
+ [0x00fac1] = 1,
+ [0x00fac2] = 1,
+ [0x00fac3] = 1,
+ [0x00fac4] = 1,
+ [0x00fac5] = 1,
+ [0x00fac6] = 1,
+ [0x00fac7] = 1,
+ [0x00fac8] = 1,
+ [0x00fac9] = 1,
+ [0x00faca] = 1,
+ [0x00facb] = 1,
+ [0x00facc] = 1,
+ [0x00facd] = 1,
+ [0x00face] = 1,
+ [0x00facf] = 1,
+ [0x00fad0] = 1,
+ [0x00fad1] = 1,
+ [0x00fad2] = 1,
+ [0x00fad3] = 1,
+ [0x00fad4] = 1,
+ [0x00fad5] = 1,
+ [0x00fad6] = 1,
+ [0x00fad7] = 1,
+ [0x00fad8] = 1,
+ [0x00fad9] = 1,
+ [0x00fb1d] = 1,
+ [0x00fb1f] = 1,
+ [0x00fb2a] = 1,
+ [0x00fb2b] = 1,
+ [0x00fb2c] = 1,
+ [0x00fb2d] = 1,
+ [0x00fb2e] = 1,
+ [0x00fb2f] = 1,
+ [0x00fb30] = 1,
+ [0x00fb31] = 1,
+ [0x00fb32] = 1,
+ [0x00fb33] = 1,
+ [0x00fb34] = 1,
+ [0x00fb35] = 1,
+ [0x00fb36] = 1,
+ [0x00fb38] = 1,
+ [0x00fb39] = 1,
+ [0x00fb3a] = 1,
+ [0x00fb3b] = 1,
+ [0x00fb3c] = 1,
+ [0x00fb3e] = 1,
+ [0x00fb40] = 1,
+ [0x00fb41] = 1,
+ [0x00fb43] = 1,
+ [0x00fb44] = 1,
+ [0x00fb46] = 1,
+ [0x00fb47] = 1,
+ [0x00fb48] = 1,
+ [0x00fb49] = 1,
+ [0x00fb4a] = 1,
+ [0x00fb4b] = 1,
+ [0x00fb4c] = 1,
+ [0x00fb4d] = 1,
+ [0x00fb4e] = 1,
+ [0x01d15e] = 1,
+ [0x01d15f] = 1,
+ [0x01d160] = 1,
+ [0x01d161] = 1,
+ [0x01d162] = 1,
+ [0x01d163] = 1,
+ [0x01d164] = 1,
+ [0x01d1bb] = 1,
+ [0x01d1bc] = 1,
+ [0x01d1bd] = 1,
+ [0x01d1be] = 1,
+ [0x01d1bf] = 1,
+ [0x01d1c0] = 1,
+ [0x02f800] = 1,
+ [0x02f801] = 1,
+ [0x02f802] = 1,
+ [0x02f803] = 1,
+ [0x02f804] = 1,
+ [0x02f805] = 1,
+ [0x02f806] = 1,
+ [0x02f807] = 1,
+ [0x02f808] = 1,
+ [0x02f809] = 1,
+ [0x02f80a] = 1,
+ [0x02f80b] = 1,
+ [0x02f80c] = 1,
+ [0x02f80d] = 1,
+ [0x02f80e] = 1,
+ [0x02f80f] = 1,
+ [0x02f810] = 1,
+ [0x02f811] = 1,
+ [0x02f812] = 1,
+ [0x02f813] = 1,
+ [0x02f814] = 1,
+ [0x02f815] = 1,
+ [0x02f816] = 1,
+ [0x02f817] = 1,
+ [0x02f818] = 1,
+ [0x02f819] = 1,
+ [0x02f81a] = 1,
+ [0x02f81b] = 1,
+ [0x02f81c] = 1,
+ [0x02f81d] = 1,
+ [0x02f81e] = 1,
+ [0x02f81f] = 1,
+ [0x02f820] = 1,
+ [0x02f821] = 1,
+ [0x02f822] = 1,
+ [0x02f823] = 1,
+ [0x02f824] = 1,
+ [0x02f825] = 1,
+ [0x02f826] = 1,
+ [0x02f827] = 1,
+ [0x02f828] = 1,
+ [0x02f829] = 1,
+ [0x02f82a] = 1,
+ [0x02f82b] = 1,
+ [0x02f82c] = 1,
+ [0x02f82d] = 1,
+ [0x02f82e] = 1,
+ [0x02f82f] = 1,
+ [0x02f830] = 1,
+ [0x02f831] = 1,
+ [0x02f832] = 1,
+ [0x02f833] = 1,
+ [0x02f834] = 1,
+ [0x02f835] = 1,
+ [0x02f836] = 1,
+ [0x02f837] = 1,
+ [0x02f838] = 1,
+ [0x02f839] = 1,
+ [0x02f83a] = 1,
+ [0x02f83b] = 1,
+ [0x02f83c] = 1,
+ [0x02f83d] = 1,
+ [0x02f83e] = 1,
+ [0x02f83f] = 1,
+ [0x02f840] = 1,
+ [0x02f841] = 1,
+ [0x02f842] = 1,
+ [0x02f843] = 1,
+ [0x02f844] = 1,
+ [0x02f845] = 1,
+ [0x02f846] = 1,
+ [0x02f847] = 1,
+ [0x02f848] = 1,
+ [0x02f849] = 1,
+ [0x02f84a] = 1,
+ [0x02f84b] = 1,
+ [0x02f84c] = 1,
+ [0x02f84d] = 1,
+ [0x02f84e] = 1,
+ [0x02f84f] = 1,
+ [0x02f850] = 1,
+ [0x02f851] = 1,
+ [0x02f852] = 1,
+ [0x02f853] = 1,
+ [0x02f854] = 1,
+ [0x02f855] = 1,
+ [0x02f856] = 1,
+ [0x02f857] = 1,
+ [0x02f858] = 1,
+ [0x02f859] = 1,
+ [0x02f85a] = 1,
+ [0x02f85b] = 1,
+ [0x02f85c] = 1,
+ [0x02f85d] = 1,
+ [0x02f85e] = 1,
+ [0x02f85f] = 1,
+ [0x02f860] = 1,
+ [0x02f861] = 1,
+ [0x02f862] = 1,
+ [0x02f863] = 1,
+ [0x02f864] = 1,
+ [0x02f865] = 1,
+ [0x02f866] = 1,
+ [0x02f867] = 1,
+ [0x02f868] = 1,
+ [0x02f869] = 1,
+ [0x02f86a] = 1,
+ [0x02f86b] = 1,
+ [0x02f86c] = 1,
+ [0x02f86d] = 1,
+ [0x02f86e] = 1,
+ [0x02f86f] = 1,
+ [0x02f870] = 1,
+ [0x02f871] = 1,
+ [0x02f872] = 1,
+ [0x02f873] = 1,
+ [0x02f874] = 1,
+ [0x02f875] = 1,
+ [0x02f876] = 1,
+ [0x02f877] = 1,
+ [0x02f878] = 1,
+ [0x02f879] = 1,
+ [0x02f87a] = 1,
+ [0x02f87b] = 1,
+ [0x02f87c] = 1,
+ [0x02f87d] = 1,
+ [0x02f87e] = 1,
+ [0x02f87f] = 1,
+ [0x02f880] = 1,
+ [0x02f881] = 1,
+ [0x02f882] = 1,
+ [0x02f883] = 1,
+ [0x02f884] = 1,
+ [0x02f885] = 1,
+ [0x02f886] = 1,
+ [0x02f887] = 1,
+ [0x02f888] = 1,
+ [0x02f889] = 1,
+ [0x02f88a] = 1,
+ [0x02f88b] = 1,
+ [0x02f88c] = 1,
+ [0x02f88d] = 1,
+ [0x02f88e] = 1,
+ [0x02f88f] = 1,
+ [0x02f890] = 1,
+ [0x02f891] = 1,
+ [0x02f892] = 1,
+ [0x02f893] = 1,
+ [0x02f894] = 1,
+ [0x02f895] = 1,
+ [0x02f896] = 1,
+ [0x02f897] = 1,
+ [0x02f898] = 1,
+ [0x02f899] = 1,
+ [0x02f89a] = 1,
+ [0x02f89b] = 1,
+ [0x02f89c] = 1,
+ [0x02f89d] = 1,
+ [0x02f89e] = 1,
+ [0x02f89f] = 1,
+ [0x02f8a0] = 1,
+ [0x02f8a1] = 1,
+ [0x02f8a2] = 1,
+ [0x02f8a3] = 1,
+ [0x02f8a4] = 1,
+ [0x02f8a5] = 1,
+ [0x02f8a6] = 1,
+ [0x02f8a7] = 1,
+ [0x02f8a8] = 1,
+ [0x02f8a9] = 1,
+ [0x02f8aa] = 1,
+ [0x02f8ab] = 1,
+ [0x02f8ac] = 1,
+ [0x02f8ad] = 1,
+ [0x02f8ae] = 1,
+ [0x02f8af] = 1,
+ [0x02f8b0] = 1,
+ [0x02f8b1] = 1,
+ [0x02f8b2] = 1,
+ [0x02f8b3] = 1,
+ [0x02f8b4] = 1,
+ [0x02f8b5] = 1,
+ [0x02f8b6] = 1,
+ [0x02f8b7] = 1,
+ [0x02f8b8] = 1,
+ [0x02f8b9] = 1,
+ [0x02f8ba] = 1,
+ [0x02f8bb] = 1,
+ [0x02f8bc] = 1,
+ [0x02f8bd] = 1,
+ [0x02f8be] = 1,
+ [0x02f8bf] = 1,
+ [0x02f8c0] = 1,
+ [0x02f8c1] = 1,
+ [0x02f8c2] = 1,
+ [0x02f8c3] = 1,
+ [0x02f8c4] = 1,
+ [0x02f8c5] = 1,
+ [0x02f8c6] = 1,
+ [0x02f8c7] = 1,
+ [0x02f8c8] = 1,
+ [0x02f8c9] = 1,
+ [0x02f8ca] = 1,
+ [0x02f8cb] = 1,
+ [0x02f8cc] = 1,
+ [0x02f8cd] = 1,
+ [0x02f8ce] = 1,
+ [0x02f8cf] = 1,
+ [0x02f8d0] = 1,
+ [0x02f8d1] = 1,
+ [0x02f8d2] = 1,
+ [0x02f8d3] = 1,
+ [0x02f8d4] = 1,
+ [0x02f8d5] = 1,
+ [0x02f8d6] = 1,
+ [0x02f8d7] = 1,
+ [0x02f8d8] = 1,
+ [0x02f8d9] = 1,
+ [0x02f8da] = 1,
+ [0x02f8db] = 1,
+ [0x02f8dc] = 1,
+ [0x02f8dd] = 1,
+ [0x02f8de] = 1,
+ [0x02f8df] = 1,
+ [0x02f8e0] = 1,
+ [0x02f8e1] = 1,
+ [0x02f8e2] = 1,
+ [0x02f8e3] = 1,
+ [0x02f8e4] = 1,
+ [0x02f8e5] = 1,
+ [0x02f8e6] = 1,
+ [0x02f8e7] = 1,
+ [0x02f8e8] = 1,
+ [0x02f8e9] = 1,
+ [0x02f8ea] = 1,
+ [0x02f8eb] = 1,
+ [0x02f8ec] = 1,
+ [0x02f8ed] = 1,
+ [0x02f8ee] = 1,
+ [0x02f8ef] = 1,
+ [0x02f8f0] = 1,
+ [0x02f8f1] = 1,
+ [0x02f8f2] = 1,
+ [0x02f8f3] = 1,
+ [0x02f8f4] = 1,
+ [0x02f8f5] = 1,
+ [0x02f8f6] = 1,
+ [0x02f8f7] = 1,
+ [0x02f8f8] = 1,
+ [0x02f8f9] = 1,
+ [0x02f8fa] = 1,
+ [0x02f8fb] = 1,
+ [0x02f8fc] = 1,
+ [0x02f8fd] = 1,
+ [0x02f8fe] = 1,
+ [0x02f8ff] = 1,
+ [0x02f900] = 1,
+ [0x02f901] = 1,
+ [0x02f902] = 1,
+ [0x02f903] = 1,
+ [0x02f904] = 1,
+ [0x02f905] = 1,
+ [0x02f906] = 1,
+ [0x02f907] = 1,
+ [0x02f908] = 1,
+ [0x02f909] = 1,
+ [0x02f90a] = 1,
+ [0x02f90b] = 1,
+ [0x02f90c] = 1,
+ [0x02f90d] = 1,
+ [0x02f90e] = 1,
+ [0x02f90f] = 1,
+ [0x02f910] = 1,
+ [0x02f911] = 1,
+ [0x02f912] = 1,
+ [0x02f913] = 1,
+ [0x02f914] = 1,
+ [0x02f915] = 1,
+ [0x02f916] = 1,
+ [0x02f917] = 1,
+ [0x02f918] = 1,
+ [0x02f919] = 1,
+ [0x02f91a] = 1,
+ [0x02f91b] = 1,
+ [0x02f91c] = 1,
+ [0x02f91d] = 1,
+ [0x02f91e] = 1,
+ [0x02f91f] = 1,
+ [0x02f920] = 1,
+ [0x02f921] = 1,
+ [0x02f922] = 1,
+ [0x02f923] = 1,
+ [0x02f924] = 1,
+ [0x02f925] = 1,
+ [0x02f926] = 1,
+ [0x02f927] = 1,
+ [0x02f928] = 1,
+ [0x02f929] = 1,
+ [0x02f92a] = 1,
+ [0x02f92b] = 1,
+ [0x02f92c] = 1,
+ [0x02f92d] = 1,
+ [0x02f92e] = 1,
+ [0x02f92f] = 1,
+ [0x02f930] = 1,
+ [0x02f931] = 1,
+ [0x02f932] = 1,
+ [0x02f933] = 1,
+ [0x02f934] = 1,
+ [0x02f935] = 1,
+ [0x02f936] = 1,
+ [0x02f937] = 1,
+ [0x02f938] = 1,
+ [0x02f939] = 1,
+ [0x02f93a] = 1,
+ [0x02f93b] = 1,
+ [0x02f93c] = 1,
+ [0x02f93d] = 1,
+ [0x02f93e] = 1,
+ [0x02f93f] = 1,
+ [0x02f940] = 1,
+ [0x02f941] = 1,
+ [0x02f942] = 1,
+ [0x02f943] = 1,
+ [0x02f944] = 1,
+ [0x02f945] = 1,
+ [0x02f946] = 1,
+ [0x02f947] = 1,
+ [0x02f948] = 1,
+ [0x02f949] = 1,
+ [0x02f94a] = 1,
+ [0x02f94b] = 1,
+ [0x02f94c] = 1,
+ [0x02f94d] = 1,
+ [0x02f94e] = 1,
+ [0x02f94f] = 1,
+ [0x02f950] = 1,
+ [0x02f951] = 1,
+ [0x02f952] = 1,
+ [0x02f953] = 1,
+ [0x02f954] = 1,
+ [0x02f955] = 1,
+ [0x02f956] = 1,
+ [0x02f957] = 1,
+ [0x02f958] = 1,
+ [0x02f959] = 1,
+ [0x02f95a] = 1,
+ [0x02f95b] = 1,
+ [0x02f95c] = 1,
+ [0x02f95d] = 1,
+ [0x02f95e] = 1,
+ [0x02f95f] = 1,
+ [0x02f960] = 1,
+ [0x02f961] = 1,
+ [0x02f962] = 1,
+ [0x02f963] = 1,
+ [0x02f964] = 1,
+ [0x02f965] = 1,
+ [0x02f966] = 1,
+ [0x02f967] = 1,
+ [0x02f968] = 1,
+ [0x02f969] = 1,
+ [0x02f96a] = 1,
+ [0x02f96b] = 1,
+ [0x02f96c] = 1,
+ [0x02f96d] = 1,
+ [0x02f96e] = 1,
+ [0x02f96f] = 1,
+ [0x02f970] = 1,
+ [0x02f971] = 1,
+ [0x02f972] = 1,
+ [0x02f973] = 1,
+ [0x02f974] = 1,
+ [0x02f975] = 1,
+ [0x02f976] = 1,
+ [0x02f977] = 1,
+ [0x02f978] = 1,
+ [0x02f979] = 1,
+ [0x02f97a] = 1,
+ [0x02f97b] = 1,
+ [0x02f97c] = 1,
+ [0x02f97d] = 1,
+ [0x02f97e] = 1,
+ [0x02f97f] = 1,
+ [0x02f980] = 1,
+ [0x02f981] = 1,
+ [0x02f982] = 1,
+ [0x02f983] = 1,
+ [0x02f984] = 1,
+ [0x02f985] = 1,
+ [0x02f986] = 1,
+ [0x02f987] = 1,
+ [0x02f988] = 1,
+ [0x02f989] = 1,
+ [0x02f98a] = 1,
+ [0x02f98b] = 1,
+ [0x02f98c] = 1,
+ [0x02f98d] = 1,
+ [0x02f98e] = 1,
+ [0x02f98f] = 1,
+ [0x02f990] = 1,
+ [0x02f991] = 1,
+ [0x02f992] = 1,
+ [0x02f993] = 1,
+ [0x02f994] = 1,
+ [0x02f995] = 1,
+ [0x02f996] = 1,
+ [0x02f997] = 1,
+ [0x02f998] = 1,
+ [0x02f999] = 1,
+ [0x02f99a] = 1,
+ [0x02f99b] = 1,
+ [0x02f99c] = 1,
+ [0x02f99d] = 1,
+ [0x02f99e] = 1,
+ [0x02f99f] = 1,
+ [0x02f9a0] = 1,
+ [0x02f9a1] = 1,
+ [0x02f9a2] = 1,
+ [0x02f9a3] = 1,
+ [0x02f9a4] = 1,
+ [0x02f9a5] = 1,
+ [0x02f9a6] = 1,
+ [0x02f9a7] = 1,
+ [0x02f9a8] = 1,
+ [0x02f9a9] = 1,
+ [0x02f9aa] = 1,
+ [0x02f9ab] = 1,
+ [0x02f9ac] = 1,
+ [0x02f9ad] = 1,
+ [0x02f9ae] = 1,
+ [0x02f9af] = 1,
+ [0x02f9b0] = 1,
+ [0x02f9b1] = 1,
+ [0x02f9b2] = 1,
+ [0x02f9b3] = 1,
+ [0x02f9b4] = 1,
+ [0x02f9b5] = 1,
+ [0x02f9b6] = 1,
+ [0x02f9b7] = 1,
+ [0x02f9b8] = 1,
+ [0x02f9b9] = 1,
+ [0x02f9ba] = 1,
+ [0x02f9bb] = 1,
+ [0x02f9bc] = 1,
+ [0x02f9bd] = 1,
+ [0x02f9be] = 1,
+ [0x02f9bf] = 1,
+ [0x02f9c0] = 1,
+ [0x02f9c1] = 1,
+ [0x02f9c2] = 1,
+ [0x02f9c3] = 1,
+ [0x02f9c4] = 1,
+ [0x02f9c5] = 1,
+ [0x02f9c6] = 1,
+ [0x02f9c7] = 1,
+ [0x02f9c8] = 1,
+ [0x02f9c9] = 1,
+ [0x02f9ca] = 1,
+ [0x02f9cb] = 1,
+ [0x02f9cc] = 1,
+ [0x02f9cd] = 1,
+ [0x02f9ce] = 1,
+ [0x02f9cf] = 1,
+ [0x02f9d0] = 1,
+ [0x02f9d1] = 1,
+ [0x02f9d2] = 1,
+ [0x02f9d3] = 1,
+ [0x02f9d4] = 1,
+ [0x02f9d5] = 1,
+ [0x02f9d6] = 1,
+ [0x02f9d7] = 1,
+ [0x02f9d8] = 1,
+ [0x02f9d9] = 1,
+ [0x02f9da] = 1,
+ [0x02f9db] = 1,
+ [0x02f9dc] = 1,
+ [0x02f9dd] = 1,
+ [0x02f9de] = 1,
+ [0x02f9df] = 1,
+ [0x02f9e0] = 1,
+ [0x02f9e1] = 1,
+ [0x02f9e2] = 1,
+ [0x02f9e3] = 1,
+ [0x02f9e4] = 1,
+ [0x02f9e5] = 1,
+ [0x02f9e6] = 1,
+ [0x02f9e7] = 1,
+ [0x02f9e8] = 1,
+ [0x02f9e9] = 1,
+ [0x02f9ea] = 1,
+ [0x02f9eb] = 1,
+ [0x02f9ec] = 1,
+ [0x02f9ed] = 1,
+ [0x02f9ee] = 1,
+ [0x02f9ef] = 1,
+ [0x02f9f0] = 1,
+ [0x02f9f1] = 1,
+ [0x02f9f2] = 1,
+ [0x02f9f3] = 1,
+ [0x02f9f4] = 1,
+ [0x02f9f5] = 1,
+ [0x02f9f6] = 1,
+ [0x02f9f7] = 1,
+ [0x02f9f8] = 1,
+ [0x02f9f9] = 1,
+ [0x02f9fa] = 1,
+ [0x02f9fb] = 1,
+ [0x02f9fc] = 1,
+ [0x02f9fd] = 1,
+ [0x02f9fe] = 1,
+ [0x02f9ff] = 1,
+ [0x02fa00] = 1,
+ [0x02fa01] = 1,
+ [0x02fa02] = 1,
+ [0x02fa03] = 1,
+ [0x02fa04] = 1,
+ [0x02fa05] = 1,
+ [0x02fa06] = 1,
+ [0x02fa07] = 1,
+ [0x02fa08] = 1,
+ [0x02fa09] = 1,
+ [0x02fa0a] = 1,
+ [0x02fa0b] = 1,
+ [0x02fa0c] = 1,
+ [0x02fa0d] = 1,
+ [0x02fa0e] = 1,
+ [0x02fa0f] = 1,
+ [0x02fa10] = 1,
+ [0x02fa11] = 1,
+ [0x02fa12] = 1,
+ [0x02fa13] = 1,
+ [0x02fa14] = 1,
+ [0x02fa15] = 1,
+ [0x02fa16] = 1,
+ [0x02fa17] = 1,
+ [0x02fa18] = 1,
+ [0x02fa19] = 1,
+ [0x02fa1a] = 1,
+ [0x02fa1b] = 1,
+ [0x02fa1c] = 1,
+ [0x02fa1d] = 1,
+ [0x0009be] = 1,
+ [0x0009d7] = 1,
+ [0x000b3e] = 1,
+ [0x000b56] = 1,
+ [0x000b57] = 1,
+ [0x000bbe] = 1,
+ [0x000bd7] = 1,
+ [0x000cc2] = 1,
+ [0x000cd5] = 1,
+ [0x000cd6] = 1,
+ [0x000d3e] = 1,
+ [0x000d57] = 1,
+ [0x000dcf] = 1,
+ [0x000ddf] = 1,
+ [0x00102e] = 1,
+ [0x001161] = 1,
+ [0x001162] = 1,
+ [0x001163] = 1,
+ [0x001164] = 1,
+ [0x001165] = 1,
+ [0x001166] = 1,
+ [0x001167] = 1,
+ [0x001168] = 1,
+ [0x001169] = 1,
+ [0x00116a] = 1,
+ [0x00116b] = 1,
+ [0x00116c] = 1,
+ [0x00116d] = 1,
+ [0x00116e] = 1,
+ [0x00116f] = 1,
+ [0x001170] = 1,
+ [0x001171] = 1,
+ [0x001172] = 1,
+ [0x001173] = 1,
+ [0x001174] = 1,
+ [0x001175] = 1,
+ [0x0011a8] = 1,
+ [0x0011a9] = 1,
+ [0x0011aa] = 1,
+ [0x0011ab] = 1,
+ [0x0011ac] = 1,
+ [0x0011ad] = 1,
+ [0x0011ae] = 1,
+ [0x0011af] = 1,
+ [0x0011b0] = 1,
+ [0x0011b1] = 1,
+ [0x0011b2] = 1,
+ [0x0011b3] = 1,
+ [0x0011b4] = 1,
+ [0x0011b5] = 1,
+ [0x0011b6] = 1,
+ [0x0011b7] = 1,
+ [0x0011b8] = 1,
+ [0x0011b9] = 1,
+ [0x0011ba] = 1,
+ [0x0011bb] = 1,
+ [0x0011bc] = 1,
+ [0x0011bd] = 1,
+ [0x0011be] = 1,
+ [0x0011bf] = 1,
+ [0x0011c0] = 1,
+ [0x0011c1] = 1,
+ [0x0011c2] = 1,
+ [0x001b35] = 1,
+ [0x011127] = 1,
+ [0x01133e] = 1,
+ [0x011357] = 1,
+ [0x0114b0] = 1,
+ [0x0114ba] = 1,
+ [0x0114bd] = 1,
+ [0x0115af] = 1,
+ },
+
+ -- Combining characters, mapped to combining class
+ combclass = {
+ [0x000300] = 230,
+ [0x000301] = 230,
+ [0x000302] = 230,
+ [0x000303] = 230,
+ [0x000304] = 230,
+ [0x000305] = 230,
+ [0x000306] = 230,
+ [0x000307] = 230,
+ [0x000308] = 230,
+ [0x000309] = 230,
+ [0x00030a] = 230,
+ [0x00030b] = 230,
+ [0x00030c] = 230,
+ [0x00030d] = 230,
+ [0x00030e] = 230,
+ [0x00030f] = 230,
+ [0x000310] = 230,
+ [0x000311] = 230,
+ [0x000312] = 230,
+ [0x000313] = 230,
+ [0x000314] = 230,
+ [0x000315] = 232,
+ [0x000316] = 220,
+ [0x000317] = 220,
+ [0x000318] = 220,
+ [0x000319] = 220,
+ [0x00031a] = 232,
+ [0x00031b] = 216,
+ [0x00031c] = 220,
+ [0x00031d] = 220,
+ [0x00031e] = 220,
+ [0x00031f] = 220,
+ [0x000320] = 220,
+ [0x000321] = 202,
+ [0x000322] = 202,
+ [0x000323] = 220,
+ [0x000324] = 220,
+ [0x000325] = 220,
+ [0x000326] = 220,
+ [0x000327] = 202,
+ [0x000328] = 202,
+ [0x000329] = 220,
+ [0x00032a] = 220,
+ [0x00032b] = 220,
+ [0x00032c] = 220,
+ [0x00032d] = 220,
+ [0x00032e] = 220,
+ [0x00032f] = 220,
+ [0x000330] = 220,
+ [0x000331] = 220,
+ [0x000332] = 220,
+ [0x000333] = 220,
+ [0x000334] = 1,
+ [0x000335] = 1,
+ [0x000336] = 1,
+ [0x000337] = 1,
+ [0x000338] = 1,
+ [0x000339] = 220,
+ [0x00033a] = 220,
+ [0x00033b] = 220,
+ [0x00033c] = 220,
+ [0x00033d] = 230,
+ [0x00033e] = 230,
+ [0x00033f] = 230,
+ [0x000340] = 230,
+ [0x000341] = 230,
+ [0x000342] = 230,
+ [0x000343] = 230,
+ [0x000344] = 230,
+ [0x000345] = 240,
+ [0x000346] = 230,
+ [0x000347] = 220,
+ [0x000348] = 220,
+ [0x000349] = 220,
+ [0x00034a] = 230,
+ [0x00034b] = 230,
+ [0x00034c] = 230,
+ [0x00034d] = 220,
+ [0x00034e] = 220,
+ [0x000350] = 230,
+ [0x000351] = 230,
+ [0x000352] = 230,
+ [0x000353] = 220,
+ [0x000354] = 220,
+ [0x000355] = 220,
+ [0x000356] = 220,
+ [0x000357] = 230,
+ [0x000358] = 232,
+ [0x000359] = 220,
+ [0x00035a] = 220,
+ [0x00035b] = 230,
+ [0x00035c] = 233,
+ [0x00035d] = 234,
+ [0x00035e] = 234,
+ [0x00035f] = 233,
+ [0x000360] = 234,
+ [0x000361] = 234,
+ [0x000362] = 233,
+ [0x000363] = 230,
+ [0x000364] = 230,
+ [0x000365] = 230,
+ [0x000366] = 230,
+ [0x000367] = 230,
+ [0x000368] = 230,
+ [0x000369] = 230,
+ [0x00036a] = 230,
+ [0x00036b] = 230,
+ [0x00036c] = 230,
+ [0x00036d] = 230,
+ [0x00036e] = 230,
+ [0x00036f] = 230,
+ [0x000483] = 230,
+ [0x000484] = 230,
+ [0x000485] = 230,
+ [0x000486] = 230,
+ [0x000487] = 230,
+ [0x000591] = 220,
+ [0x000592] = 230,
+ [0x000593] = 230,
+ [0x000594] = 230,
+ [0x000595] = 230,
+ [0x000596] = 220,
+ [0x000597] = 230,
+ [0x000598] = 230,
+ [0x000599] = 230,
+ [0x00059a] = 222,
+ [0x00059b] = 220,
+ [0x00059c] = 230,
+ [0x00059d] = 230,
+ [0x00059e] = 230,
+ [0x00059f] = 230,
+ [0x0005a0] = 230,
+ [0x0005a1] = 230,
+ [0x0005a2] = 220,
+ [0x0005a3] = 220,
+ [0x0005a4] = 220,
+ [0x0005a5] = 220,
+ [0x0005a6] = 220,
+ [0x0005a7] = 220,
+ [0x0005a8] = 230,
+ [0x0005a9] = 230,
+ [0x0005aa] = 220,
+ [0x0005ab] = 230,
+ [0x0005ac] = 230,
+ [0x0005ad] = 222,
+ [0x0005ae] = 228,
+ [0x0005af] = 230,
+ [0x0005b0] = 10,
+ [0x0005b1] = 11,
+ [0x0005b2] = 12,
+ [0x0005b3] = 13,
+ [0x0005b4] = 14,
+ [0x0005b5] = 15,
+ [0x0005b6] = 16,
+ [0x0005b7] = 17,
+ [0x0005b8] = 18,
+ [0x0005b9] = 19,
+ [0x0005ba] = 19,
+ [0x0005bb] = 20,
+ [0x0005bc] = 21,
+ [0x0005bd] = 22,
+ [0x0005bf] = 23,
+ [0x0005c1] = 24,
+ [0x0005c2] = 25,
+ [0x0005c4] = 230,
+ [0x0005c5] = 220,
+ [0x0005c7] = 18,
+ [0x000610] = 230,
+ [0x000611] = 230,
+ [0x000612] = 230,
+ [0x000613] = 230,
+ [0x000614] = 230,
+ [0x000615] = 230,
+ [0x000616] = 230,
+ [0x000617] = 230,
+ [0x000618] = 30,
+ [0x000619] = 31,
+ [0x00061a] = 32,
+ [0x00064b] = 27,
+ [0x00064c] = 28,
+ [0x00064d] = 29,
+ [0x00064e] = 30,
+ [0x00064f] = 31,
+ [0x000650] = 32,
+ [0x000651] = 33,
+ [0x000652] = 34,
+ [0x000653] = 230,
+ [0x000654] = 230,
+ [0x000655] = 220,
+ [0x000656] = 220,
+ [0x000657] = 230,
+ [0x000658] = 230,
+ [0x000659] = 230,
+ [0x00065a] = 230,
+ [0x00065b] = 230,
+ [0x00065c] = 220,
+ [0x00065d] = 230,
+ [0x00065e] = 230,
+ [0x00065f] = 220,
+ [0x000670] = 35,
+ [0x0006d6] = 230,
+ [0x0006d7] = 230,
+ [0x0006d8] = 230,
+ [0x0006d9] = 230,
+ [0x0006da] = 230,
+ [0x0006db] = 230,
+ [0x0006dc] = 230,
+ [0x0006df] = 230,
+ [0x0006e0] = 230,
+ [0x0006e1] = 230,
+ [0x0006e2] = 230,
+ [0x0006e3] = 220,
+ [0x0006e4] = 230,
+ [0x0006e7] = 230,
+ [0x0006e8] = 230,
+ [0x0006ea] = 220,
+ [0x0006eb] = 230,
+ [0x0006ec] = 230,
+ [0x0006ed] = 220,
+ [0x000711] = 36,
+ [0x000730] = 230,
+ [0x000731] = 220,
+ [0x000732] = 230,
+ [0x000733] = 230,
+ [0x000734] = 220,
+ [0x000735] = 230,
+ [0x000736] = 230,
+ [0x000737] = 220,
+ [0x000738] = 220,
+ [0x000739] = 220,
+ [0x00073a] = 230,
+ [0x00073b] = 220,
+ [0x00073c] = 220,
+ [0x00073d] = 230,
+ [0x00073e] = 220,
+ [0x00073f] = 230,
+ [0x000740] = 230,
+ [0x000741] = 230,
+ [0x000742] = 220,
+ [0x000743] = 230,
+ [0x000744] = 220,
+ [0x000745] = 230,
+ [0x000746] = 220,
+ [0x000747] = 230,
+ [0x000748] = 220,
+ [0x000749] = 230,
+ [0x00074a] = 230,
+ [0x0007eb] = 230,
+ [0x0007ec] = 230,
+ [0x0007ed] = 230,
+ [0x0007ee] = 230,
+ [0x0007ef] = 230,
+ [0x0007f0] = 230,
+ [0x0007f1] = 230,
+ [0x0007f2] = 220,
+ [0x0007f3] = 230,
+ [0x000816] = 230,
+ [0x000817] = 230,
+ [0x000818] = 230,
+ [0x000819] = 230,
+ [0x00081b] = 230,
+ [0x00081c] = 230,
+ [0x00081d] = 230,
+ [0x00081e] = 230,
+ [0x00081f] = 230,
+ [0x000820] = 230,
+ [0x000821] = 230,
+ [0x000822] = 230,
+ [0x000823] = 230,
+ [0x000825] = 230,
+ [0x000826] = 230,
+ [0x000827] = 230,
+ [0x000829] = 230,
+ [0x00082a] = 230,
+ [0x00082b] = 230,
+ [0x00082c] = 230,
+ [0x00082d] = 230,
+ [0x000859] = 220,
+ [0x00085a] = 220,
+ [0x00085b] = 220,
+ [0x0008e3] = 220,
+ [0x0008e4] = 230,
+ [0x0008e5] = 230,
+ [0x0008e6] = 220,
+ [0x0008e7] = 230,
+ [0x0008e8] = 230,
+ [0x0008e9] = 220,
+ [0x0008ea] = 230,
+ [0x0008eb] = 230,
+ [0x0008ec] = 230,
+ [0x0008ed] = 220,
+ [0x0008ee] = 220,
+ [0x0008ef] = 220,
+ [0x0008f0] = 27,
+ [0x0008f1] = 28,
+ [0x0008f2] = 29,
+ [0x0008f3] = 230,
+ [0x0008f4] = 230,
+ [0x0008f5] = 230,
+ [0x0008f6] = 220,
+ [0x0008f7] = 230,
+ [0x0008f8] = 230,
+ [0x0008f9] = 220,
+ [0x0008fa] = 220,
+ [0x0008fb] = 230,
+ [0x0008fc] = 230,
+ [0x0008fd] = 230,
+ [0x0008fe] = 230,
+ [0x0008ff] = 230,
+ [0x00093c] = 7,
+ [0x00094d] = 9,
+ [0x000951] = 230,
+ [0x000952] = 220,
+ [0x000953] = 230,
+ [0x000954] = 230,
+ [0x0009bc] = 7,
+ [0x0009cd] = 9,
+ [0x000a3c] = 7,
+ [0x000a4d] = 9,
+ [0x000abc] = 7,
+ [0x000acd] = 9,
+ [0x000b3c] = 7,
+ [0x000b4d] = 9,
+ [0x000bcd] = 9,
+ [0x000c4d] = 9,
+ [0x000c55] = 84,
+ [0x000c56] = 91,
+ [0x000cbc] = 7,
+ [0x000ccd] = 9,
+ [0x000d4d] = 9,
+ [0x000dca] = 9,
+ [0x000e38] = 103,
+ [0x000e39] = 103,
+ [0x000e3a] = 9,
+ [0x000e48] = 107,
+ [0x000e49] = 107,
+ [0x000e4a] = 107,
+ [0x000e4b] = 107,
+ [0x000eb8] = 118,
+ [0x000eb9] = 118,
+ [0x000ec8] = 122,
+ [0x000ec9] = 122,
+ [0x000eca] = 122,
+ [0x000ecb] = 122,
+ [0x000f18] = 220,
+ [0x000f19] = 220,
+ [0x000f35] = 220,
+ [0x000f37] = 220,
+ [0x000f39] = 216,
+ [0x000f71] = 129,
+ [0x000f72] = 130,
+ [0x000f74] = 132,
+ [0x000f7a] = 130,
+ [0x000f7b] = 130,
+ [0x000f7c] = 130,
+ [0x000f7d] = 130,
+ [0x000f80] = 130,
+ [0x000f82] = 230,
+ [0x000f83] = 230,
+ [0x000f84] = 9,
+ [0x000f86] = 230,
+ [0x000f87] = 230,
+ [0x000fc6] = 220,
+ [0x001037] = 7,
+ [0x001039] = 9,
+ [0x00103a] = 9,
+ [0x00108d] = 220,
+ [0x00135d] = 230,
+ [0x00135e] = 230,
+ [0x00135f] = 230,
+ [0x001714] = 9,
+ [0x001734] = 9,
+ [0x0017d2] = 9,
+ [0x0017dd] = 230,
+ [0x0018a9] = 228,
+ [0x001939] = 222,
+ [0x00193a] = 230,
+ [0x00193b] = 220,
+ [0x001a17] = 230,
+ [0x001a18] = 220,
+ [0x001a60] = 9,
+ [0x001a75] = 230,
+ [0x001a76] = 230,
+ [0x001a77] = 230,
+ [0x001a78] = 230,
+ [0x001a79] = 230,
+ [0x001a7a] = 230,
+ [0x001a7b] = 230,
+ [0x001a7c] = 230,
+ [0x001a7f] = 220,
+ [0x001ab0] = 230,
+ [0x001ab1] = 230,
+ [0x001ab2] = 230,
+ [0x001ab3] = 230,
+ [0x001ab4] = 230,
+ [0x001ab5] = 220,
+ [0x001ab6] = 220,
+ [0x001ab7] = 220,
+ [0x001ab8] = 220,
+ [0x001ab9] = 220,
+ [0x001aba] = 220,
+ [0x001abb] = 230,
+ [0x001abc] = 230,
+ [0x001abd] = 220,
+ [0x001b34] = 7,
+ [0x001b44] = 9,
+ [0x001b6b] = 230,
+ [0x001b6c] = 220,
+ [0x001b6d] = 230,
+ [0x001b6e] = 230,
+ [0x001b6f] = 230,
+ [0x001b70] = 230,
+ [0x001b71] = 230,
+ [0x001b72] = 230,
+ [0x001b73] = 230,
+ [0x001baa] = 9,
+ [0x001bab] = 9,
+ [0x001be6] = 7,
+ [0x001bf2] = 9,
+ [0x001bf3] = 9,
+ [0x001c37] = 7,
+ [0x001cd0] = 230,
+ [0x001cd1] = 230,
+ [0x001cd2] = 230,
+ [0x001cd4] = 1,
+ [0x001cd5] = 220,
+ [0x001cd6] = 220,
+ [0x001cd7] = 220,
+ [0x001cd8] = 220,
+ [0x001cd9] = 220,
+ [0x001cda] = 230,
+ [0x001cdb] = 230,
+ [0x001cdc] = 220,
+ [0x001cdd] = 220,
+ [0x001cde] = 220,
+ [0x001cdf] = 220,
+ [0x001ce0] = 230,
+ [0x001ce2] = 1,
+ [0x001ce3] = 1,
+ [0x001ce4] = 1,
+ [0x001ce5] = 1,
+ [0x001ce6] = 1,
+ [0x001ce7] = 1,
+ [0x001ce8] = 1,
+ [0x001ced] = 220,
+ [0x001cf4] = 230,
+ [0x001cf8] = 230,
+ [0x001cf9] = 230,
+ [0x001dc0] = 230,
+ [0x001dc1] = 230,
+ [0x001dc2] = 220,
+ [0x001dc3] = 230,
+ [0x001dc4] = 230,
+ [0x001dc5] = 230,
+ [0x001dc6] = 230,
+ [0x001dc7] = 230,
+ [0x001dc8] = 230,
+ [0x001dc9] = 230,
+ [0x001dca] = 220,
+ [0x001dcb] = 230,
+ [0x001dcc] = 230,
+ [0x001dcd] = 234,
+ [0x001dce] = 214,
+ [0x001dcf] = 220,
+ [0x001dd0] = 202,
+ [0x001dd1] = 230,
+ [0x001dd2] = 230,
+ [0x001dd3] = 230,
+ [0x001dd4] = 230,
+ [0x001dd5] = 230,
+ [0x001dd6] = 230,
+ [0x001dd7] = 230,
+ [0x001dd8] = 230,
+ [0x001dd9] = 230,
+ [0x001dda] = 230,
+ [0x001ddb] = 230,
+ [0x001ddc] = 230,
+ [0x001ddd] = 230,
+ [0x001dde] = 230,
+ [0x001ddf] = 230,
+ [0x001de0] = 230,
+ [0x001de1] = 230,
+ [0x001de2] = 230,
+ [0x001de3] = 230,
+ [0x001de4] = 230,
+ [0x001de5] = 230,
+ [0x001de6] = 230,
+ [0x001de7] = 230,
+ [0x001de8] = 230,
+ [0x001de9] = 230,
+ [0x001dea] = 230,
+ [0x001deb] = 230,
+ [0x001dec] = 230,
+ [0x001ded] = 230,
+ [0x001dee] = 230,
+ [0x001def] = 230,
+ [0x001df0] = 230,
+ [0x001df1] = 230,
+ [0x001df2] = 230,
+ [0x001df3] = 230,
+ [0x001df4] = 230,
+ [0x001df5] = 230,
+ [0x001dfc] = 233,
+ [0x001dfd] = 220,
+ [0x001dfe] = 230,
+ [0x001dff] = 220,
+ [0x0020d0] = 230,
+ [0x0020d1] = 230,
+ [0x0020d2] = 1,
+ [0x0020d3] = 1,
+ [0x0020d4] = 230,
+ [0x0020d5] = 230,
+ [0x0020d6] = 230,
+ [0x0020d7] = 230,
+ [0x0020d8] = 1,
+ [0x0020d9] = 1,
+ [0x0020da] = 1,
+ [0x0020db] = 230,
+ [0x0020dc] = 230,
+ [0x0020e1] = 230,
+ [0x0020e5] = 1,
+ [0x0020e6] = 1,
+ [0x0020e7] = 230,
+ [0x0020e8] = 220,
+ [0x0020e9] = 230,
+ [0x0020ea] = 1,
+ [0x0020eb] = 1,
+ [0x0020ec] = 220,
+ [0x0020ed] = 220,
+ [0x0020ee] = 220,
+ [0x0020ef] = 220,
+ [0x0020f0] = 230,
+ [0x002cef] = 230,
+ [0x002cf0] = 230,
+ [0x002cf1] = 230,
+ [0x002d7f] = 9,
+ [0x002de0] = 230,
+ [0x002de1] = 230,
+ [0x002de2] = 230,
+ [0x002de3] = 230,
+ [0x002de4] = 230,
+ [0x002de5] = 230,
+ [0x002de6] = 230,
+ [0x002de7] = 230,
+ [0x002de8] = 230,
+ [0x002de9] = 230,
+ [0x002dea] = 230,
+ [0x002deb] = 230,
+ [0x002dec] = 230,
+ [0x002ded] = 230,
+ [0x002dee] = 230,
+ [0x002def] = 230,
+ [0x002df0] = 230,
+ [0x002df1] = 230,
+ [0x002df2] = 230,
+ [0x002df3] = 230,
+ [0x002df4] = 230,
+ [0x002df5] = 230,
+ [0x002df6] = 230,
+ [0x002df7] = 230,
+ [0x002df8] = 230,
+ [0x002df9] = 230,
+ [0x002dfa] = 230,
+ [0x002dfb] = 230,
+ [0x002dfc] = 230,
+ [0x002dfd] = 230,
+ [0x002dfe] = 230,
+ [0x002dff] = 230,
+ [0x00302a] = 218,
+ [0x00302b] = 228,
+ [0x00302c] = 232,
+ [0x00302d] = 222,
+ [0x00302e] = 224,
+ [0x00302f] = 224,
+ [0x003099] = 8,
+ [0x00309a] = 8,
+ [0x00a66f] = 230,
+ [0x00a674] = 230,
+ [0x00a675] = 230,
+ [0x00a676] = 230,
+ [0x00a677] = 230,
+ [0x00a678] = 230,
+ [0x00a679] = 230,
+ [0x00a67a] = 230,
+ [0x00a67b] = 230,
+ [0x00a67c] = 230,
+ [0x00a67d] = 230,
+ [0x00a69e] = 230,
+ [0x00a69f] = 230,
+ [0x00a6f0] = 230,
+ [0x00a6f1] = 230,
+ [0x00a806] = 9,
+ [0x00a8c4] = 9,
+ [0x00a8e0] = 230,
+ [0x00a8e1] = 230,
+ [0x00a8e2] = 230,
+ [0x00a8e3] = 230,
+ [0x00a8e4] = 230,
+ [0x00a8e5] = 230,
+ [0x00a8e6] = 230,
+ [0x00a8e7] = 230,
+ [0x00a8e8] = 230,
+ [0x00a8e9] = 230,
+ [0x00a8ea] = 230,
+ [0x00a8eb] = 230,
+ [0x00a8ec] = 230,
+ [0x00a8ed] = 230,
+ [0x00a8ee] = 230,
+ [0x00a8ef] = 230,
+ [0x00a8f0] = 230,
+ [0x00a8f1] = 230,
+ [0x00a92b] = 220,
+ [0x00a92c] = 220,
+ [0x00a92d] = 220,
+ [0x00a953] = 9,
+ [0x00a9b3] = 7,
+ [0x00a9c0] = 9,
+ [0x00aab0] = 230,
+ [0x00aab2] = 230,
+ [0x00aab3] = 230,
+ [0x00aab4] = 220,
+ [0x00aab7] = 230,
+ [0x00aab8] = 230,
+ [0x00aabe] = 230,
+ [0x00aabf] = 230,
+ [0x00aac1] = 230,
+ [0x00aaf6] = 9,
+ [0x00abed] = 9,
+ [0x00fb1e] = 26,
+ [0x00fe20] = 230,
+ [0x00fe21] = 230,
+ [0x00fe22] = 230,
+ [0x00fe23] = 230,
+ [0x00fe24] = 230,
+ [0x00fe25] = 230,
+ [0x00fe26] = 230,
+ [0x00fe27] = 220,
+ [0x00fe28] = 220,
+ [0x00fe29] = 220,
+ [0x00fe2a] = 220,
+ [0x00fe2b] = 220,
+ [0x00fe2c] = 220,
+ [0x00fe2d] = 220,
+ [0x00fe2e] = 230,
+ [0x00fe2f] = 230,
+ [0x0101fd] = 220,
+ [0x0102e0] = 220,
+ [0x010376] = 230,
+ [0x010377] = 230,
+ [0x010378] = 230,
+ [0x010379] = 230,
+ [0x01037a] = 230,
+ [0x010a0d] = 220,
+ [0x010a0f] = 230,
+ [0x010a38] = 230,
+ [0x010a39] = 1,
+ [0x010a3a] = 220,
+ [0x010a3f] = 9,
+ [0x010ae5] = 230,
+ [0x010ae6] = 220,
+ [0x011046] = 9,
+ [0x01107f] = 9,
+ [0x0110b9] = 9,
+ [0x0110ba] = 7,
+ [0x011100] = 230,
+ [0x011101] = 230,
+ [0x011102] = 230,
+ [0x011133] = 9,
+ [0x011134] = 9,
+ [0x011173] = 7,
+ [0x0111c0] = 9,
+ [0x0111ca] = 7,
+ [0x011235] = 9,
+ [0x011236] = 7,
+ [0x0112e9] = 7,
+ [0x0112ea] = 9,
+ [0x01133c] = 7,
+ [0x01134d] = 9,
+ [0x011366] = 230,
+ [0x011367] = 230,
+ [0x011368] = 230,
+ [0x011369] = 230,
+ [0x01136a] = 230,
+ [0x01136b] = 230,
+ [0x01136c] = 230,
+ [0x011370] = 230,
+ [0x011371] = 230,
+ [0x011372] = 230,
+ [0x011373] = 230,
+ [0x011374] = 230,
+ [0x0114c2] = 9,
+ [0x0114c3] = 7,
+ [0x0115bf] = 9,
+ [0x0115c0] = 7,
+ [0x01163f] = 9,
+ [0x0116b6] = 9,
+ [0x0116b7] = 7,
+ [0x01172b] = 9,
+ [0x016af0] = 1,
+ [0x016af1] = 1,
+ [0x016af2] = 1,
+ [0x016af3] = 1,
+ [0x016af4] = 1,
+ [0x016b30] = 230,
+ [0x016b31] = 230,
+ [0x016b32] = 230,
+ [0x016b33] = 230,
+ [0x016b34] = 230,
+ [0x016b35] = 230,
+ [0x016b36] = 230,
+ [0x01bc9e] = 1,
+ [0x01d165] = 216,
+ [0x01d166] = 216,
+ [0x01d167] = 1,
+ [0x01d168] = 1,
+ [0x01d169] = 1,
+ [0x01d16d] = 226,
+ [0x01d16e] = 216,
+ [0x01d16f] = 216,
+ [0x01d170] = 216,
+ [0x01d171] = 216,
+ [0x01d172] = 216,
+ [0x01d17b] = 220,
+ [0x01d17c] = 220,
+ [0x01d17d] = 220,
+ [0x01d17e] = 220,
+ [0x01d17f] = 220,
+ [0x01d180] = 220,
+ [0x01d181] = 220,
+ [0x01d182] = 220,
+ [0x01d185] = 230,
+ [0x01d186] = 230,
+ [0x01d187] = 230,
+ [0x01d188] = 230,
+ [0x01d189] = 230,
+ [0x01d18a] = 220,
+ [0x01d18b] = 220,
+ [0x01d1aa] = 230,
+ [0x01d1ab] = 230,
+ [0x01d1ac] = 230,
+ [0x01d1ad] = 230,
+ [0x01d242] = 230,
+ [0x01d243] = 230,
+ [0x01d244] = 230,
+ [0x01e8d0] = 220,
+ [0x01e8d1] = 220,
+ [0x01e8d2] = 220,
+ [0x01e8d3] = 220,
+ [0x01e8d4] = 220,
+ [0x01e8d5] = 220,
+ [0x01e8d6] = 220,
+ },
+
+ -- Characters mapped to what they decompose to
+ -- Note Hangul to Jamo is done separately below
+ decomp = {
+ [0x0000c0] = { 0x000041, 0x000300 },
+ [0x0000c1] = { 0x000041, 0x000301 },
+ [0x0000c2] = { 0x000041, 0x000302 },
+ [0x0000c3] = { 0x000041, 0x000303 },
+ [0x0000c4] = { 0x000041, 0x000308 },
+ [0x0000c5] = { 0x000041, 0x00030a },
+ [0x0000c7] = { 0x000043, 0x000327 },
+ [0x0000c8] = { 0x000045, 0x000300 },
+ [0x0000c9] = { 0x000045, 0x000301 },
+ [0x0000ca] = { 0x000045, 0x000302 },
+ [0x0000cb] = { 0x000045, 0x000308 },
+ [0x0000cc] = { 0x000049, 0x000300 },
+ [0x0000cd] = { 0x000049, 0x000301 },
+ [0x0000ce] = { 0x000049, 0x000302 },
+ [0x0000cf] = { 0x000049, 0x000308 },
+ [0x0000d1] = { 0x00004e, 0x000303 },
+ [0x0000d2] = { 0x00004f, 0x000300 },
+ [0x0000d3] = { 0x00004f, 0x000301 },
+ [0x0000d4] = { 0x00004f, 0x000302 },
+ [0x0000d5] = { 0x00004f, 0x000303 },
+ [0x0000d6] = { 0x00004f, 0x000308 },
+ [0x0000d9] = { 0x000055, 0x000300 },
+ [0x0000da] = { 0x000055, 0x000301 },
+ [0x0000db] = { 0x000055, 0x000302 },
+ [0x0000dc] = { 0x000055, 0x000308 },
+ [0x0000dd] = { 0x000059, 0x000301 },
+ [0x0000e0] = { 0x000061, 0x000300 },
+ [0x0000e1] = { 0x000061, 0x000301 },
+ [0x0000e2] = { 0x000061, 0x000302 },
+ [0x0000e3] = { 0x000061, 0x000303 },
+ [0x0000e4] = { 0x000061, 0x000308 },
+ [0x0000e5] = { 0x000061, 0x00030a },
+ [0x0000e7] = { 0x000063, 0x000327 },
+ [0x0000e8] = { 0x000065, 0x000300 },
+ [0x0000e9] = { 0x000065, 0x000301 },
+ [0x0000ea] = { 0x000065, 0x000302 },
+ [0x0000eb] = { 0x000065, 0x000308 },
+ [0x0000ec] = { 0x000069, 0x000300 },
+ [0x0000ed] = { 0x000069, 0x000301 },
+ [0x0000ee] = { 0x000069, 0x000302 },
+ [0x0000ef] = { 0x000069, 0x000308 },
+ [0x0000f1] = { 0x00006e, 0x000303 },
+ [0x0000f2] = { 0x00006f, 0x000300 },
+ [0x0000f3] = { 0x00006f, 0x000301 },
+ [0x0000f4] = { 0x00006f, 0x000302 },
+ [0x0000f5] = { 0x00006f, 0x000303 },
+ [0x0000f6] = { 0x00006f, 0x000308 },
+ [0x0000f9] = { 0x000075, 0x000300 },
+ [0x0000fa] = { 0x000075, 0x000301 },
+ [0x0000fb] = { 0x000075, 0x000302 },
+ [0x0000fc] = { 0x000075, 0x000308 },
+ [0x0000fd] = { 0x000079, 0x000301 },
+ [0x0000ff] = { 0x000079, 0x000308 },
+ [0x000100] = { 0x000041, 0x000304 },
+ [0x000101] = { 0x000061, 0x000304 },
+ [0x000102] = { 0x000041, 0x000306 },
+ [0x000103] = { 0x000061, 0x000306 },
+ [0x000104] = { 0x000041, 0x000328 },
+ [0x000105] = { 0x000061, 0x000328 },
+ [0x000106] = { 0x000043, 0x000301 },
+ [0x000107] = { 0x000063, 0x000301 },
+ [0x000108] = { 0x000043, 0x000302 },
+ [0x000109] = { 0x000063, 0x000302 },
+ [0x00010a] = { 0x000043, 0x000307 },
+ [0x00010b] = { 0x000063, 0x000307 },
+ [0x00010c] = { 0x000043, 0x00030c },
+ [0x00010d] = { 0x000063, 0x00030c },
+ [0x00010e] = { 0x000044, 0x00030c },
+ [0x00010f] = { 0x000064, 0x00030c },
+ [0x000112] = { 0x000045, 0x000304 },
+ [0x000113] = { 0x000065, 0x000304 },
+ [0x000114] = { 0x000045, 0x000306 },
+ [0x000115] = { 0x000065, 0x000306 },
+ [0x000116] = { 0x000045, 0x000307 },
+ [0x000117] = { 0x000065, 0x000307 },
+ [0x000118] = { 0x000045, 0x000328 },
+ [0x000119] = { 0x000065, 0x000328 },
+ [0x00011a] = { 0x000045, 0x00030c },
+ [0x00011b] = { 0x000065, 0x00030c },
+ [0x00011c] = { 0x000047, 0x000302 },
+ [0x00011d] = { 0x000067, 0x000302 },
+ [0x00011e] = { 0x000047, 0x000306 },
+ [0x00011f] = { 0x000067, 0x000306 },
+ [0x000120] = { 0x000047, 0x000307 },
+ [0x000121] = { 0x000067, 0x000307 },
+ [0x000122] = { 0x000047, 0x000327 },
+ [0x000123] = { 0x000067, 0x000327 },
+ [0x000124] = { 0x000048, 0x000302 },
+ [0x000125] = { 0x000068, 0x000302 },
+ [0x000128] = { 0x000049, 0x000303 },
+ [0x000129] = { 0x000069, 0x000303 },
+ [0x00012a] = { 0x000049, 0x000304 },
+ [0x00012b] = { 0x000069, 0x000304 },
+ [0x00012c] = { 0x000049, 0x000306 },
+ [0x00012d] = { 0x000069, 0x000306 },
+ [0x00012e] = { 0x000049, 0x000328 },
+ [0x00012f] = { 0x000069, 0x000328 },
+ [0x000130] = { 0x000049, 0x000307 },
+ [0x000134] = { 0x00004a, 0x000302 },
+ [0x000135] = { 0x00006a, 0x000302 },
+ [0x000136] = { 0x00004b, 0x000327 },
+ [0x000137] = { 0x00006b, 0x000327 },
+ [0x000139] = { 0x00004c, 0x000301 },
+ [0x00013a] = { 0x00006c, 0x000301 },
+ [0x00013b] = { 0x00004c, 0x000327 },
+ [0x00013c] = { 0x00006c, 0x000327 },
+ [0x00013d] = { 0x00004c, 0x00030c },
+ [0x00013e] = { 0x00006c, 0x00030c },
+ [0x000143] = { 0x00004e, 0x000301 },
+ [0x000144] = { 0x00006e, 0x000301 },
+ [0x000145] = { 0x00004e, 0x000327 },
+ [0x000146] = { 0x00006e, 0x000327 },
+ [0x000147] = { 0x00004e, 0x00030c },
+ [0x000148] = { 0x00006e, 0x00030c },
+ [0x00014c] = { 0x00004f, 0x000304 },
+ [0x00014d] = { 0x00006f, 0x000304 },
+ [0x00014e] = { 0x00004f, 0x000306 },
+ [0x00014f] = { 0x00006f, 0x000306 },
+ [0x000150] = { 0x00004f, 0x00030b },
+ [0x000151] = { 0x00006f, 0x00030b },
+ [0x000154] = { 0x000052, 0x000301 },
+ [0x000155] = { 0x000072, 0x000301 },
+ [0x000156] = { 0x000052, 0x000327 },
+ [0x000157] = { 0x000072, 0x000327 },
+ [0x000158] = { 0x000052, 0x00030c },
+ [0x000159] = { 0x000072, 0x00030c },
+ [0x00015a] = { 0x000053, 0x000301 },
+ [0x00015b] = { 0x000073, 0x000301 },
+ [0x00015c] = { 0x000053, 0x000302 },
+ [0x00015d] = { 0x000073, 0x000302 },
+ [0x00015e] = { 0x000053, 0x000327 },
+ [0x00015f] = { 0x000073, 0x000327 },
+ [0x000160] = { 0x000053, 0x00030c },
+ [0x000161] = { 0x000073, 0x00030c },
+ [0x000162] = { 0x000054, 0x000327 },
+ [0x000163] = { 0x000074, 0x000327 },
+ [0x000164] = { 0x000054, 0x00030c },
+ [0x000165] = { 0x000074, 0x00030c },
+ [0x000168] = { 0x000055, 0x000303 },
+ [0x000169] = { 0x000075, 0x000303 },
+ [0x00016a] = { 0x000055, 0x000304 },
+ [0x00016b] = { 0x000075, 0x000304 },
+ [0x00016c] = { 0x000055, 0x000306 },
+ [0x00016d] = { 0x000075, 0x000306 },
+ [0x00016e] = { 0x000055, 0x00030a },
+ [0x00016f] = { 0x000075, 0x00030a },
+ [0x000170] = { 0x000055, 0x00030b },
+ [0x000171] = { 0x000075, 0x00030b },
+ [0x000172] = { 0x000055, 0x000328 },
+ [0x000173] = { 0x000075, 0x000328 },
+ [0x000174] = { 0x000057, 0x000302 },
+ [0x000175] = { 0x000077, 0x000302 },
+ [0x000176] = { 0x000059, 0x000302 },
+ [0x000177] = { 0x000079, 0x000302 },
+ [0x000178] = { 0x000059, 0x000308 },
+ [0x000179] = { 0x00005a, 0x000301 },
+ [0x00017a] = { 0x00007a, 0x000301 },
+ [0x00017b] = { 0x00005a, 0x000307 },
+ [0x00017c] = { 0x00007a, 0x000307 },
+ [0x00017d] = { 0x00005a, 0x00030c },
+ [0x00017e] = { 0x00007a, 0x00030c },
+ [0x0001a0] = { 0x00004f, 0x00031b },
+ [0x0001a1] = { 0x00006f, 0x00031b },
+ [0x0001af] = { 0x000055, 0x00031b },
+ [0x0001b0] = { 0x000075, 0x00031b },
+ [0x0001cd] = { 0x000041, 0x00030c },
+ [0x0001ce] = { 0x000061, 0x00030c },
+ [0x0001cf] = { 0x000049, 0x00030c },
+ [0x0001d0] = { 0x000069, 0x00030c },
+ [0x0001d1] = { 0x00004f, 0x00030c },
+ [0x0001d2] = { 0x00006f, 0x00030c },
+ [0x0001d3] = { 0x000055, 0x00030c },
+ [0x0001d4] = { 0x000075, 0x00030c },
+ [0x0001d5] = { 0x000055, 0x000308, 0x000304 },
+ [0x0001d6] = { 0x000075, 0x000308, 0x000304 },
+ [0x0001d7] = { 0x000055, 0x000308, 0x000301 },
+ [0x0001d8] = { 0x000075, 0x000308, 0x000301 },
+ [0x0001d9] = { 0x000055, 0x000308, 0x00030c },
+ [0x0001da] = { 0x000075, 0x000308, 0x00030c },
+ [0x0001db] = { 0x000055, 0x000308, 0x000300 },
+ [0x0001dc] = { 0x000075, 0x000308, 0x000300 },
+ [0x0001de] = { 0x000041, 0x000308, 0x000304 },
+ [0x0001df] = { 0x000061, 0x000308, 0x000304 },
+ [0x0001e0] = { 0x000041, 0x000307, 0x000304 },
+ [0x0001e1] = { 0x000061, 0x000307, 0x000304 },
+ [0x0001e2] = { 0x0000c6, 0x000304 },
+ [0x0001e3] = { 0x0000e6, 0x000304 },
+ [0x0001e6] = { 0x000047, 0x00030c },
+ [0x0001e7] = { 0x000067, 0x00030c },
+ [0x0001e8] = { 0x00004b, 0x00030c },
+ [0x0001e9] = { 0x00006b, 0x00030c },
+ [0x0001ea] = { 0x00004f, 0x000328 },
+ [0x0001eb] = { 0x00006f, 0x000328 },
+ [0x0001ec] = { 0x00004f, 0x000328, 0x000304 },
+ [0x0001ed] = { 0x00006f, 0x000328, 0x000304 },
+ [0x0001ee] = { 0x0001b7, 0x00030c },
+ [0x0001ef] = { 0x000292, 0x00030c },
+ [0x0001f0] = { 0x00006a, 0x00030c },
+ [0x0001f4] = { 0x000047, 0x000301 },
+ [0x0001f5] = { 0x000067, 0x000301 },
+ [0x0001f8] = { 0x00004e, 0x000300 },
+ [0x0001f9] = { 0x00006e, 0x000300 },
+ [0x0001fa] = { 0x000041, 0x00030a, 0x000301 },
+ [0x0001fb] = { 0x000061, 0x00030a, 0x000301 },
+ [0x0001fc] = { 0x0000c6, 0x000301 },
+ [0x0001fd] = { 0x0000e6, 0x000301 },
+ [0x0001fe] = { 0x0000d8, 0x000301 },
+ [0x0001ff] = { 0x0000f8, 0x000301 },
+ [0x000200] = { 0x000041, 0x00030f },
+ [0x000201] = { 0x000061, 0x00030f },
+ [0x000202] = { 0x000041, 0x000311 },
+ [0x000203] = { 0x000061, 0x000311 },
+ [0x000204] = { 0x000045, 0x00030f },
+ [0x000205] = { 0x000065, 0x00030f },
+ [0x000206] = { 0x000045, 0x000311 },
+ [0x000207] = { 0x000065, 0x000311 },
+ [0x000208] = { 0x000049, 0x00030f },
+ [0x000209] = { 0x000069, 0x00030f },
+ [0x00020a] = { 0x000049, 0x000311 },
+ [0x00020b] = { 0x000069, 0x000311 },
+ [0x00020c] = { 0x00004f, 0x00030f },
+ [0x00020d] = { 0x00006f, 0x00030f },
+ [0x00020e] = { 0x00004f, 0x000311 },
+ [0x00020f] = { 0x00006f, 0x000311 },
+ [0x000210] = { 0x000052, 0x00030f },
+ [0x000211] = { 0x000072, 0x00030f },
+ [0x000212] = { 0x000052, 0x000311 },
+ [0x000213] = { 0x000072, 0x000311 },
+ [0x000214] = { 0x000055, 0x00030f },
+ [0x000215] = { 0x000075, 0x00030f },
+ [0x000216] = { 0x000055, 0x000311 },
+ [0x000217] = { 0x000075, 0x000311 },
+ [0x000218] = { 0x000053, 0x000326 },
+ [0x000219] = { 0x000073, 0x000326 },
+ [0x00021a] = { 0x000054, 0x000326 },
+ [0x00021b] = { 0x000074, 0x000326 },
+ [0x00021e] = { 0x000048, 0x00030c },
+ [0x00021f] = { 0x000068, 0x00030c },
+ [0x000226] = { 0x000041, 0x000307 },
+ [0x000227] = { 0x000061, 0x000307 },
+ [0x000228] = { 0x000045, 0x000327 },
+ [0x000229] = { 0x000065, 0x000327 },
+ [0x00022a] = { 0x00004f, 0x000308, 0x000304 },
+ [0x00022b] = { 0x00006f, 0x000308, 0x000304 },
+ [0x00022c] = { 0x00004f, 0x000303, 0x000304 },
+ [0x00022d] = { 0x00006f, 0x000303, 0x000304 },
+ [0x00022e] = { 0x00004f, 0x000307 },
+ [0x00022f] = { 0x00006f, 0x000307 },
+ [0x000230] = { 0x00004f, 0x000307, 0x000304 },
+ [0x000231] = { 0x00006f, 0x000307, 0x000304 },
+ [0x000232] = { 0x000059, 0x000304 },
+ [0x000233] = { 0x000079, 0x000304 },
+ [0x000340] = { 0x000300 },
+ [0x000341] = { 0x000301 },
+ [0x000343] = { 0x000313 },
+ [0x000344] = { 0x000308, 0x000301 },
+ [0x000374] = { 0x0002b9 },
+ [0x00037e] = { 0x00003b },
+ [0x000385] = { 0x0000a8, 0x000301 },
+ [0x000386] = { 0x000391, 0x000301 },
+ [0x000387] = { 0x0000b7 },
+ [0x000388] = { 0x000395, 0x000301 },
+ [0x000389] = { 0x000397, 0x000301 },
+ [0x00038a] = { 0x000399, 0x000301 },
+ [0x00038c] = { 0x00039f, 0x000301 },
+ [0x00038e] = { 0x0003a5, 0x000301 },
+ [0x00038f] = { 0x0003a9, 0x000301 },
+ [0x000390] = { 0x0003b9, 0x000308, 0x000301 },
+ [0x0003aa] = { 0x000399, 0x000308 },
+ [0x0003ab] = { 0x0003a5, 0x000308 },
+ [0x0003ac] = { 0x0003b1, 0x000301 },
+ [0x0003ad] = { 0x0003b5, 0x000301 },
+ [0x0003ae] = { 0x0003b7, 0x000301 },
+ [0x0003af] = { 0x0003b9, 0x000301 },
+ [0x0003b0] = { 0x0003c5, 0x000308, 0x000301 },
+ [0x0003ca] = { 0x0003b9, 0x000308 },
+ [0x0003cb] = { 0x0003c5, 0x000308 },
+ [0x0003cc] = { 0x0003bf, 0x000301 },
+ [0x0003cd] = { 0x0003c5, 0x000301 },
+ [0x0003ce] = { 0x0003c9, 0x000301 },
+ [0x0003d3] = { 0x0003d2, 0x000301 },
+ [0x0003d4] = { 0x0003d2, 0x000308 },
+ [0x000400] = { 0x000415, 0x000300 },
+ [0x000401] = { 0x000415, 0x000308 },
+ [0x000403] = { 0x000413, 0x000301 },
+ [0x000407] = { 0x000406, 0x000308 },
+ [0x00040c] = { 0x00041a, 0x000301 },
+ [0x00040d] = { 0x000418, 0x000300 },
+ [0x00040e] = { 0x000423, 0x000306 },
+ [0x000419] = { 0x000418, 0x000306 },
+ [0x000439] = { 0x000438, 0x000306 },
+ [0x000450] = { 0x000435, 0x000300 },
+ [0x000451] = { 0x000435, 0x000308 },
+ [0x000453] = { 0x000433, 0x000301 },
+ [0x000457] = { 0x000456, 0x000308 },
+ [0x00045c] = { 0x00043a, 0x000301 },
+ [0x00045d] = { 0x000438, 0x000300 },
+ [0x00045e] = { 0x000443, 0x000306 },
+ [0x000476] = { 0x000474, 0x00030f },
+ [0x000477] = { 0x000475, 0x00030f },
+ [0x0004c1] = { 0x000416, 0x000306 },
+ [0x0004c2] = { 0x000436, 0x000306 },
+ [0x0004d0] = { 0x000410, 0x000306 },
+ [0x0004d1] = { 0x000430, 0x000306 },
+ [0x0004d2] = { 0x000410, 0x000308 },
+ [0x0004d3] = { 0x000430, 0x000308 },
+ [0x0004d6] = { 0x000415, 0x000306 },
+ [0x0004d7] = { 0x000435, 0x000306 },
+ [0x0004da] = { 0x0004d8, 0x000308 },
+ [0x0004db] = { 0x0004d9, 0x000308 },
+ [0x0004dc] = { 0x000416, 0x000308 },
+ [0x0004dd] = { 0x000436, 0x000308 },
+ [0x0004de] = { 0x000417, 0x000308 },
+ [0x0004df] = { 0x000437, 0x000308 },
+ [0x0004e2] = { 0x000418, 0x000304 },
+ [0x0004e3] = { 0x000438, 0x000304 },
+ [0x0004e4] = { 0x000418, 0x000308 },
+ [0x0004e5] = { 0x000438, 0x000308 },
+ [0x0004e6] = { 0x00041e, 0x000308 },
+ [0x0004e7] = { 0x00043e, 0x000308 },
+ [0x0004ea] = { 0x0004e8, 0x000308 },
+ [0x0004eb] = { 0x0004e9, 0x000308 },
+ [0x0004ec] = { 0x00042d, 0x000308 },
+ [0x0004ed] = { 0x00044d, 0x000308 },
+ [0x0004ee] = { 0x000423, 0x000304 },
+ [0x0004ef] = { 0x000443, 0x000304 },
+ [0x0004f0] = { 0x000423, 0x000308 },
+ [0x0004f1] = { 0x000443, 0x000308 },
+ [0x0004f2] = { 0x000423, 0x00030b },
+ [0x0004f3] = { 0x000443, 0x00030b },
+ [0x0004f4] = { 0x000427, 0x000308 },
+ [0x0004f5] = { 0x000447, 0x000308 },
+ [0x0004f8] = { 0x00042b, 0x000308 },
+ [0x0004f9] = { 0x00044b, 0x000308 },
+ [0x000622] = { 0x000627, 0x000653 },
+ [0x000623] = { 0x000627, 0x000654 },
+ [0x000624] = { 0x000648, 0x000654 },
+ [0x000625] = { 0x000627, 0x000655 },
+ [0x000626] = { 0x00064a, 0x000654 },
+ [0x0006c0] = { 0x0006d5, 0x000654 },
+ [0x0006c2] = { 0x0006c1, 0x000654 },
+ [0x0006d3] = { 0x0006d2, 0x000654 },
+ [0x000929] = { 0x000928, 0x00093c },
+ [0x000931] = { 0x000930, 0x00093c },
+ [0x000934] = { 0x000933, 0x00093c },
+ [0x000958] = { 0x000915, 0x00093c },
+ [0x000959] = { 0x000916, 0x00093c },
+ [0x00095a] = { 0x000917, 0x00093c },
+ [0x00095b] = { 0x00091c, 0x00093c },
+ [0x00095c] = { 0x000921, 0x00093c },
+ [0x00095d] = { 0x000922, 0x00093c },
+ [0x00095e] = { 0x00092b, 0x00093c },
+ [0x00095f] = { 0x00092f, 0x00093c },
+ [0x0009cb] = { 0x0009c7, 0x0009be },
+ [0x0009cc] = { 0x0009c7, 0x0009d7 },
+ [0x0009dc] = { 0x0009a1, 0x0009bc },
+ [0x0009dd] = { 0x0009a2, 0x0009bc },
+ [0x0009df] = { 0x0009af, 0x0009bc },
+ [0x000a33] = { 0x000a32, 0x000a3c },
+ [0x000a36] = { 0x000a38, 0x000a3c },
+ [0x000a59] = { 0x000a16, 0x000a3c },
+ [0x000a5a] = { 0x000a17, 0x000a3c },
+ [0x000a5b] = { 0x000a1c, 0x000a3c },
+ [0x000a5e] = { 0x000a2b, 0x000a3c },
+ [0x000b48] = { 0x000b47, 0x000b56 },
+ [0x000b4b] = { 0x000b47, 0x000b3e },
+ [0x000b4c] = { 0x000b47, 0x000b57 },
+ [0x000b5c] = { 0x000b21, 0x000b3c },
+ [0x000b5d] = { 0x000b22, 0x000b3c },
+ [0x000b94] = { 0x000b92, 0x000bd7 },
+ [0x000bca] = { 0x000bc6, 0x000bbe },
+ [0x000bcb] = { 0x000bc7, 0x000bbe },
+ [0x000bcc] = { 0x000bc6, 0x000bd7 },
+ [0x000c48] = { 0x000c46, 0x000c56 },
+ [0x000cc0] = { 0x000cbf, 0x000cd5 },
+ [0x000cc7] = { 0x000cc6, 0x000cd5 },
+ [0x000cc8] = { 0x000cc6, 0x000cd6 },
+ [0x000cca] = { 0x000cc6, 0x000cc2 },
+ [0x000ccb] = { 0x000cc6, 0x000cc2, 0x000cd5 },
+ [0x000d4a] = { 0x000d46, 0x000d3e },
+ [0x000d4b] = { 0x000d47, 0x000d3e },
+ [0x000d4c] = { 0x000d46, 0x000d57 },
+ [0x000dda] = { 0x000dd9, 0x000dca },
+ [0x000ddc] = { 0x000dd9, 0x000dcf },
+ [0x000ddd] = { 0x000dd9, 0x000dcf, 0x000dca },
+ [0x000dde] = { 0x000dd9, 0x000ddf },
+ [0x000f43] = { 0x000f42, 0x000fb7 },
+ [0x000f4d] = { 0x000f4c, 0x000fb7 },
+ [0x000f52] = { 0x000f51, 0x000fb7 },
+ [0x000f57] = { 0x000f56, 0x000fb7 },
+ [0x000f5c] = { 0x000f5b, 0x000fb7 },
+ [0x000f69] = { 0x000f40, 0x000fb5 },
+ [0x000f73] = { 0x000f71, 0x000f72 },
+ [0x000f75] = { 0x000f71, 0x000f74 },
+ [0x000f76] = { 0x000fb2, 0x000f80 },
+ [0x000f78] = { 0x000fb3, 0x000f80 },
+ [0x000f81] = { 0x000f71, 0x000f80 },
+ [0x000f93] = { 0x000f92, 0x000fb7 },
+ [0x000f9d] = { 0x000f9c, 0x000fb7 },
+ [0x000fa2] = { 0x000fa1, 0x000fb7 },
+ [0x000fa7] = { 0x000fa6, 0x000fb7 },
+ [0x000fac] = { 0x000fab, 0x000fb7 },
+ [0x000fb9] = { 0x000f90, 0x000fb5 },
+ [0x001026] = { 0x001025, 0x00102e },
+ [0x001b06] = { 0x001b05, 0x001b35 },
+ [0x001b08] = { 0x001b07, 0x001b35 },
+ [0x001b0a] = { 0x001b09, 0x001b35 },
+ [0x001b0c] = { 0x001b0b, 0x001b35 },
+ [0x001b0e] = { 0x001b0d, 0x001b35 },
+ [0x001b12] = { 0x001b11, 0x001b35 },
+ [0x001b3b] = { 0x001b3a, 0x001b35 },
+ [0x001b3d] = { 0x001b3c, 0x001b35 },
+ [0x001b40] = { 0x001b3e, 0x001b35 },
+ [0x001b41] = { 0x001b3f, 0x001b35 },
+ [0x001b43] = { 0x001b42, 0x001b35 },
+ [0x001e00] = { 0x000041, 0x000325 },
+ [0x001e01] = { 0x000061, 0x000325 },
+ [0x001e02] = { 0x000042, 0x000307 },
+ [0x001e03] = { 0x000062, 0x000307 },
+ [0x001e04] = { 0x000042, 0x000323 },
+ [0x001e05] = { 0x000062, 0x000323 },
+ [0x001e06] = { 0x000042, 0x000331 },
+ [0x001e07] = { 0x000062, 0x000331 },
+ [0x001e08] = { 0x000043, 0x000327, 0x000301 },
+ [0x001e09] = { 0x000063, 0x000327, 0x000301 },
+ [0x001e0a] = { 0x000044, 0x000307 },
+ [0x001e0b] = { 0x000064, 0x000307 },
+ [0x001e0c] = { 0x000044, 0x000323 },
+ [0x001e0d] = { 0x000064, 0x000323 },
+ [0x001e0e] = { 0x000044, 0x000331 },
+ [0x001e0f] = { 0x000064, 0x000331 },
+ [0x001e10] = { 0x000044, 0x000327 },
+ [0x001e11] = { 0x000064, 0x000327 },
+ [0x001e12] = { 0x000044, 0x00032d },
+ [0x001e13] = { 0x000064, 0x00032d },
+ [0x001e14] = { 0x000045, 0x000304, 0x000300 },
+ [0x001e15] = { 0x000065, 0x000304, 0x000300 },
+ [0x001e16] = { 0x000045, 0x000304, 0x000301 },
+ [0x001e17] = { 0x000065, 0x000304, 0x000301 },
+ [0x001e18] = { 0x000045, 0x00032d },
+ [0x001e19] = { 0x000065, 0x00032d },
+ [0x001e1a] = { 0x000045, 0x000330 },
+ [0x001e1b] = { 0x000065, 0x000330 },
+ [0x001e1c] = { 0x000045, 0x000327, 0x000306 },
+ [0x001e1d] = { 0x000065, 0x000327, 0x000306 },
+ [0x001e1e] = { 0x000046, 0x000307 },
+ [0x001e1f] = { 0x000066, 0x000307 },
+ [0x001e20] = { 0x000047, 0x000304 },
+ [0x001e21] = { 0x000067, 0x000304 },
+ [0x001e22] = { 0x000048, 0x000307 },
+ [0x001e23] = { 0x000068, 0x000307 },
+ [0x001e24] = { 0x000048, 0x000323 },
+ [0x001e25] = { 0x000068, 0x000323 },
+ [0x001e26] = { 0x000048, 0x000308 },
+ [0x001e27] = { 0x000068, 0x000308 },
+ [0x001e28] = { 0x000048, 0x000327 },
+ [0x001e29] = { 0x000068, 0x000327 },
+ [0x001e2a] = { 0x000048, 0x00032e },
+ [0x001e2b] = { 0x000068, 0x00032e },
+ [0x001e2c] = { 0x000049, 0x000330 },
+ [0x001e2d] = { 0x000069, 0x000330 },
+ [0x001e2e] = { 0x000049, 0x000308, 0x000301 },
+ [0x001e2f] = { 0x000069, 0x000308, 0x000301 },
+ [0x001e30] = { 0x00004b, 0x000301 },
+ [0x001e31] = { 0x00006b, 0x000301 },
+ [0x001e32] = { 0x00004b, 0x000323 },
+ [0x001e33] = { 0x00006b, 0x000323 },
+ [0x001e34] = { 0x00004b, 0x000331 },
+ [0x001e35] = { 0x00006b, 0x000331 },
+ [0x001e36] = { 0x00004c, 0x000323 },
+ [0x001e37] = { 0x00006c, 0x000323 },
+ [0x001e38] = { 0x00004c, 0x000323, 0x000304 },
+ [0x001e39] = { 0x00006c, 0x000323, 0x000304 },
+ [0x001e3a] = { 0x00004c, 0x000331 },
+ [0x001e3b] = { 0x00006c, 0x000331 },
+ [0x001e3c] = { 0x00004c, 0x00032d },
+ [0x001e3d] = { 0x00006c, 0x00032d },
+ [0x001e3e] = { 0x00004d, 0x000301 },
+ [0x001e3f] = { 0x00006d, 0x000301 },
+ [0x001e40] = { 0x00004d, 0x000307 },
+ [0x001e41] = { 0x00006d, 0x000307 },
+ [0x001e42] = { 0x00004d, 0x000323 },
+ [0x001e43] = { 0x00006d, 0x000323 },
+ [0x001e44] = { 0x00004e, 0x000307 },
+ [0x001e45] = { 0x00006e, 0x000307 },
+ [0x001e46] = { 0x00004e, 0x000323 },
+ [0x001e47] = { 0x00006e, 0x000323 },
+ [0x001e48] = { 0x00004e, 0x000331 },
+ [0x001e49] = { 0x00006e, 0x000331 },
+ [0x001e4a] = { 0x00004e, 0x00032d },
+ [0x001e4b] = { 0x00006e, 0x00032d },
+ [0x001e4c] = { 0x00004f, 0x000303, 0x000301 },
+ [0x001e4d] = { 0x00006f, 0x000303, 0x000301 },
+ [0x001e4e] = { 0x00004f, 0x000303, 0x000308 },
+ [0x001e4f] = { 0x00006f, 0x000303, 0x000308 },
+ [0x001e50] = { 0x00004f, 0x000304, 0x000300 },
+ [0x001e51] = { 0x00006f, 0x000304, 0x000300 },
+ [0x001e52] = { 0x00004f, 0x000304, 0x000301 },
+ [0x001e53] = { 0x00006f, 0x000304, 0x000301 },
+ [0x001e54] = { 0x000050, 0x000301 },
+ [0x001e55] = { 0x000070, 0x000301 },
+ [0x001e56] = { 0x000050, 0x000307 },
+ [0x001e57] = { 0x000070, 0x000307 },
+ [0x001e58] = { 0x000052, 0x000307 },
+ [0x001e59] = { 0x000072, 0x000307 },
+ [0x001e5a] = { 0x000052, 0x000323 },
+ [0x001e5b] = { 0x000072, 0x000323 },
+ [0x001e5c] = { 0x000052, 0x000323, 0x000304 },
+ [0x001e5d] = { 0x000072, 0x000323, 0x000304 },
+ [0x001e5e] = { 0x000052, 0x000331 },
+ [0x001e5f] = { 0x000072, 0x000331 },
+ [0x001e60] = { 0x000053, 0x000307 },
+ [0x001e61] = { 0x000073, 0x000307 },
+ [0x001e62] = { 0x000053, 0x000323 },
+ [0x001e63] = { 0x000073, 0x000323 },
+ [0x001e64] = { 0x000053, 0x000301, 0x000307 },
+ [0x001e65] = { 0x000073, 0x000301, 0x000307 },
+ [0x001e66] = { 0x000053, 0x00030c, 0x000307 },
+ [0x001e67] = { 0x000073, 0x00030c, 0x000307 },
+ [0x001e68] = { 0x000053, 0x000323, 0x000307 },
+ [0x001e69] = { 0x000073, 0x000323, 0x000307 },
+ [0x001e6a] = { 0x000054, 0x000307 },
+ [0x001e6b] = { 0x000074, 0x000307 },
+ [0x001e6c] = { 0x000054, 0x000323 },
+ [0x001e6d] = { 0x000074, 0x000323 },
+ [0x001e6e] = { 0x000054, 0x000331 },
+ [0x001e6f] = { 0x000074, 0x000331 },
+ [0x001e70] = { 0x000054, 0x00032d },
+ [0x001e71] = { 0x000074, 0x00032d },
+ [0x001e72] = { 0x000055, 0x000324 },
+ [0x001e73] = { 0x000075, 0x000324 },
+ [0x001e74] = { 0x000055, 0x000330 },
+ [0x001e75] = { 0x000075, 0x000330 },
+ [0x001e76] = { 0x000055, 0x00032d },
+ [0x001e77] = { 0x000075, 0x00032d },
+ [0x001e78] = { 0x000055, 0x000303, 0x000301 },
+ [0x001e79] = { 0x000075, 0x000303, 0x000301 },
+ [0x001e7a] = { 0x000055, 0x000304, 0x000308 },
+ [0x001e7b] = { 0x000075, 0x000304, 0x000308 },
+ [0x001e7c] = { 0x000056, 0x000303 },
+ [0x001e7d] = { 0x000076, 0x000303 },
+ [0x001e7e] = { 0x000056, 0x000323 },
+ [0x001e7f] = { 0x000076, 0x000323 },
+ [0x001e80] = { 0x000057, 0x000300 },
+ [0x001e81] = { 0x000077, 0x000300 },
+ [0x001e82] = { 0x000057, 0x000301 },
+ [0x001e83] = { 0x000077, 0x000301 },
+ [0x001e84] = { 0x000057, 0x000308 },
+ [0x001e85] = { 0x000077, 0x000308 },
+ [0x001e86] = { 0x000057, 0x000307 },
+ [0x001e87] = { 0x000077, 0x000307 },
+ [0x001e88] = { 0x000057, 0x000323 },
+ [0x001e89] = { 0x000077, 0x000323 },
+ [0x001e8a] = { 0x000058, 0x000307 },
+ [0x001e8b] = { 0x000078, 0x000307 },
+ [0x001e8c] = { 0x000058, 0x000308 },
+ [0x001e8d] = { 0x000078, 0x000308 },
+ [0x001e8e] = { 0x000059, 0x000307 },
+ [0x001e8f] = { 0x000079, 0x000307 },
+ [0x001e90] = { 0x00005a, 0x000302 },
+ [0x001e91] = { 0x00007a, 0x000302 },
+ [0x001e92] = { 0x00005a, 0x000323 },
+ [0x001e93] = { 0x00007a, 0x000323 },
+ [0x001e94] = { 0x00005a, 0x000331 },
+ [0x001e95] = { 0x00007a, 0x000331 },
+ [0x001e96] = { 0x000068, 0x000331 },
+ [0x001e97] = { 0x000074, 0x000308 },
+ [0x001e98] = { 0x000077, 0x00030a },
+ [0x001e99] = { 0x000079, 0x00030a },
+ [0x001e9b] = { 0x00017f, 0x000307 },
+ [0x001ea0] = { 0x000041, 0x000323 },
+ [0x001ea1] = { 0x000061, 0x000323 },
+ [0x001ea2] = { 0x000041, 0x000309 },
+ [0x001ea3] = { 0x000061, 0x000309 },
+ [0x001ea4] = { 0x000041, 0x000302, 0x000301 },
+ [0x001ea5] = { 0x000061, 0x000302, 0x000301 },
+ [0x001ea6] = { 0x000041, 0x000302, 0x000300 },
+ [0x001ea7] = { 0x000061, 0x000302, 0x000300 },
+ [0x001ea8] = { 0x000041, 0x000302, 0x000309 },
+ [0x001ea9] = { 0x000061, 0x000302, 0x000309 },
+ [0x001eaa] = { 0x000041, 0x000302, 0x000303 },
+ [0x001eab] = { 0x000061, 0x000302, 0x000303 },
+ [0x001eac] = { 0x000041, 0x000323, 0x000302 },
+ [0x001ead] = { 0x000061, 0x000323, 0x000302 },
+ [0x001eae] = { 0x000041, 0x000306, 0x000301 },
+ [0x001eaf] = { 0x000061, 0x000306, 0x000301 },
+ [0x001eb0] = { 0x000041, 0x000306, 0x000300 },
+ [0x001eb1] = { 0x000061, 0x000306, 0x000300 },
+ [0x001eb2] = { 0x000041, 0x000306, 0x000309 },
+ [0x001eb3] = { 0x000061, 0x000306, 0x000309 },
+ [0x001eb4] = { 0x000041, 0x000306, 0x000303 },
+ [0x001eb5] = { 0x000061, 0x000306, 0x000303 },
+ [0x001eb6] = { 0x000041, 0x000323, 0x000306 },
+ [0x001eb7] = { 0x000061, 0x000323, 0x000306 },
+ [0x001eb8] = { 0x000045, 0x000323 },
+ [0x001eb9] = { 0x000065, 0x000323 },
+ [0x001eba] = { 0x000045, 0x000309 },
+ [0x001ebb] = { 0x000065, 0x000309 },
+ [0x001ebc] = { 0x000045, 0x000303 },
+ [0x001ebd] = { 0x000065, 0x000303 },
+ [0x001ebe] = { 0x000045, 0x000302, 0x000301 },
+ [0x001ebf] = { 0x000065, 0x000302, 0x000301 },
+ [0x001ec0] = { 0x000045, 0x000302, 0x000300 },
+ [0x001ec1] = { 0x000065, 0x000302, 0x000300 },
+ [0x001ec2] = { 0x000045, 0x000302, 0x000309 },
+ [0x001ec3] = { 0x000065, 0x000302, 0x000309 },
+ [0x001ec4] = { 0x000045, 0x000302, 0x000303 },
+ [0x001ec5] = { 0x000065, 0x000302, 0x000303 },
+ [0x001ec6] = { 0x000045, 0x000323, 0x000302 },
+ [0x001ec7] = { 0x000065, 0x000323, 0x000302 },
+ [0x001ec8] = { 0x000049, 0x000309 },
+ [0x001ec9] = { 0x000069, 0x000309 },
+ [0x001eca] = { 0x000049, 0x000323 },
+ [0x001ecb] = { 0x000069, 0x000323 },
+ [0x001ecc] = { 0x00004f, 0x000323 },
+ [0x001ecd] = { 0x00006f, 0x000323 },
+ [0x001ece] = { 0x00004f, 0x000309 },
+ [0x001ecf] = { 0x00006f, 0x000309 },
+ [0x001ed0] = { 0x00004f, 0x000302, 0x000301 },
+ [0x001ed1] = { 0x00006f, 0x000302, 0x000301 },
+ [0x001ed2] = { 0x00004f, 0x000302, 0x000300 },
+ [0x001ed3] = { 0x00006f, 0x000302, 0x000300 },
+ [0x001ed4] = { 0x00004f, 0x000302, 0x000309 },
+ [0x001ed5] = { 0x00006f, 0x000302, 0x000309 },
+ [0x001ed6] = { 0x00004f, 0x000302, 0x000303 },
+ [0x001ed7] = { 0x00006f, 0x000302, 0x000303 },
+ [0x001ed8] = { 0x00004f, 0x000323, 0x000302 },
+ [0x001ed9] = { 0x00006f, 0x000323, 0x000302 },
+ [0x001eda] = { 0x00004f, 0x00031b, 0x000301 },
+ [0x001edb] = { 0x00006f, 0x00031b, 0x000301 },
+ [0x001edc] = { 0x00004f, 0x00031b, 0x000300 },
+ [0x001edd] = { 0x00006f, 0x00031b, 0x000300 },
+ [0x001ede] = { 0x00004f, 0x00031b, 0x000309 },
+ [0x001edf] = { 0x00006f, 0x00031b, 0x000309 },
+ [0x001ee0] = { 0x00004f, 0x00031b, 0x000303 },
+ [0x001ee1] = { 0x00006f, 0x00031b, 0x000303 },
+ [0x001ee2] = { 0x00004f, 0x00031b, 0x000323 },
+ [0x001ee3] = { 0x00006f, 0x00031b, 0x000323 },
+ [0x001ee4] = { 0x000055, 0x000323 },
+ [0x001ee5] = { 0x000075, 0x000323 },
+ [0x001ee6] = { 0x000055, 0x000309 },
+ [0x001ee7] = { 0x000075, 0x000309 },
+ [0x001ee8] = { 0x000055, 0x00031b, 0x000301 },
+ [0x001ee9] = { 0x000075, 0x00031b, 0x000301 },
+ [0x001eea] = { 0x000055, 0x00031b, 0x000300 },
+ [0x001eeb] = { 0x000075, 0x00031b, 0x000300 },
+ [0x001eec] = { 0x000055, 0x00031b, 0x000309 },
+ [0x001eed] = { 0x000075, 0x00031b, 0x000309 },
+ [0x001eee] = { 0x000055, 0x00031b, 0x000303 },
+ [0x001eef] = { 0x000075, 0x00031b, 0x000303 },
+ [0x001ef0] = { 0x000055, 0x00031b, 0x000323 },
+ [0x001ef1] = { 0x000075, 0x00031b, 0x000323 },
+ [0x001ef2] = { 0x000059, 0x000300 },
+ [0x001ef3] = { 0x000079, 0x000300 },
+ [0x001ef4] = { 0x000059, 0x000323 },
+ [0x001ef5] = { 0x000079, 0x000323 },
+ [0x001ef6] = { 0x000059, 0x000309 },
+ [0x001ef7] = { 0x000079, 0x000309 },
+ [0x001ef8] = { 0x000059, 0x000303 },
+ [0x001ef9] = { 0x000079, 0x000303 },
+ [0x001f00] = { 0x0003b1, 0x000313 },
+ [0x001f01] = { 0x0003b1, 0x000314 },
+ [0x001f02] = { 0x0003b1, 0x000313, 0x000300 },
+ [0x001f03] = { 0x0003b1, 0x000314, 0x000300 },
+ [0x001f04] = { 0x0003b1, 0x000313, 0x000301 },
+ [0x001f05] = { 0x0003b1, 0x000314, 0x000301 },
+ [0x001f06] = { 0x0003b1, 0x000313, 0x000342 },
+ [0x001f07] = { 0x0003b1, 0x000314, 0x000342 },
+ [0x001f08] = { 0x000391, 0x000313 },
+ [0x001f09] = { 0x000391, 0x000314 },
+ [0x001f0a] = { 0x000391, 0x000313, 0x000300 },
+ [0x001f0b] = { 0x000391, 0x000314, 0x000300 },
+ [0x001f0c] = { 0x000391, 0x000313, 0x000301 },
+ [0x001f0d] = { 0x000391, 0x000314, 0x000301 },
+ [0x001f0e] = { 0x000391, 0x000313, 0x000342 },
+ [0x001f0f] = { 0x000391, 0x000314, 0x000342 },
+ [0x001f10] = { 0x0003b5, 0x000313 },
+ [0x001f11] = { 0x0003b5, 0x000314 },
+ [0x001f12] = { 0x0003b5, 0x000313, 0x000300 },
+ [0x001f13] = { 0x0003b5, 0x000314, 0x000300 },
+ [0x001f14] = { 0x0003b5, 0x000313, 0x000301 },
+ [0x001f15] = { 0x0003b5, 0x000314, 0x000301 },
+ [0x001f18] = { 0x000395, 0x000313 },
+ [0x001f19] = { 0x000395, 0x000314 },
+ [0x001f1a] = { 0x000395, 0x000313, 0x000300 },
+ [0x001f1b] = { 0x000395, 0x000314, 0x000300 },
+ [0x001f1c] = { 0x000395, 0x000313, 0x000301 },
+ [0x001f1d] = { 0x000395, 0x000314, 0x000301 },
+ [0x001f20] = { 0x0003b7, 0x000313 },
+ [0x001f21] = { 0x0003b7, 0x000314 },
+ [0x001f22] = { 0x0003b7, 0x000313, 0x000300 },
+ [0x001f23] = { 0x0003b7, 0x000314, 0x000300 },
+ [0x001f24] = { 0x0003b7, 0x000313, 0x000301 },
+ [0x001f25] = { 0x0003b7, 0x000314, 0x000301 },
+ [0x001f26] = { 0x0003b7, 0x000313, 0x000342 },
+ [0x001f27] = { 0x0003b7, 0x000314, 0x000342 },
+ [0x001f28] = { 0x000397, 0x000313 },
+ [0x001f29] = { 0x000397, 0x000314 },
+ [0x001f2a] = { 0x000397, 0x000313, 0x000300 },
+ [0x001f2b] = { 0x000397, 0x000314, 0x000300 },
+ [0x001f2c] = { 0x000397, 0x000313, 0x000301 },
+ [0x001f2d] = { 0x000397, 0x000314, 0x000301 },
+ [0x001f2e] = { 0x000397, 0x000313, 0x000342 },
+ [0x001f2f] = { 0x000397, 0x000314, 0x000342 },
+ [0x001f30] = { 0x0003b9, 0x000313 },
+ [0x001f31] = { 0x0003b9, 0x000314 },
+ [0x001f32] = { 0x0003b9, 0x000313, 0x000300 },
+ [0x001f33] = { 0x0003b9, 0x000314, 0x000300 },
+ [0x001f34] = { 0x0003b9, 0x000313, 0x000301 },
+ [0x001f35] = { 0x0003b9, 0x000314, 0x000301 },
+ [0x001f36] = { 0x0003b9, 0x000313, 0x000342 },
+ [0x001f37] = { 0x0003b9, 0x000314, 0x000342 },
+ [0x001f38] = { 0x000399, 0x000313 },
+ [0x001f39] = { 0x000399, 0x000314 },
+ [0x001f3a] = { 0x000399, 0x000313, 0x000300 },
+ [0x001f3b] = { 0x000399, 0x000314, 0x000300 },
+ [0x001f3c] = { 0x000399, 0x000313, 0x000301 },
+ [0x001f3d] = { 0x000399, 0x000314, 0x000301 },
+ [0x001f3e] = { 0x000399, 0x000313, 0x000342 },
+ [0x001f3f] = { 0x000399, 0x000314, 0x000342 },
+ [0x001f40] = { 0x0003bf, 0x000313 },
+ [0x001f41] = { 0x0003bf, 0x000314 },
+ [0x001f42] = { 0x0003bf, 0x000313, 0x000300 },
+ [0x001f43] = { 0x0003bf, 0x000314, 0x000300 },
+ [0x001f44] = { 0x0003bf, 0x000313, 0x000301 },
+ [0x001f45] = { 0x0003bf, 0x000314, 0x000301 },
+ [0x001f48] = { 0x00039f, 0x000313 },
+ [0x001f49] = { 0x00039f, 0x000314 },
+ [0x001f4a] = { 0x00039f, 0x000313, 0x000300 },
+ [0x001f4b] = { 0x00039f, 0x000314, 0x000300 },
+ [0x001f4c] = { 0x00039f, 0x000313, 0x000301 },
+ [0x001f4d] = { 0x00039f, 0x000314, 0x000301 },
+ [0x001f50] = { 0x0003c5, 0x000313 },
+ [0x001f51] = { 0x0003c5, 0x000314 },
+ [0x001f52] = { 0x0003c5, 0x000313, 0x000300 },
+ [0x001f53] = { 0x0003c5, 0x000314, 0x000300 },
+ [0x001f54] = { 0x0003c5, 0x000313, 0x000301 },
+ [0x001f55] = { 0x0003c5, 0x000314, 0x000301 },
+ [0x001f56] = { 0x0003c5, 0x000313, 0x000342 },
+ [0x001f57] = { 0x0003c5, 0x000314, 0x000342 },
+ [0x001f59] = { 0x0003a5, 0x000314 },
+ [0x001f5b] = { 0x0003a5, 0x000314, 0x000300 },
+ [0x001f5d] = { 0x0003a5, 0x000314, 0x000301 },
+ [0x001f5f] = { 0x0003a5, 0x000314, 0x000342 },
+ [0x001f60] = { 0x0003c9, 0x000313 },
+ [0x001f61] = { 0x0003c9, 0x000314 },
+ [0x001f62] = { 0x0003c9, 0x000313, 0x000300 },
+ [0x001f63] = { 0x0003c9, 0x000314, 0x000300 },
+ [0x001f64] = { 0x0003c9, 0x000313, 0x000301 },
+ [0x001f65] = { 0x0003c9, 0x000314, 0x000301 },
+ [0x001f66] = { 0x0003c9, 0x000313, 0x000342 },
+ [0x001f67] = { 0x0003c9, 0x000314, 0x000342 },
+ [0x001f68] = { 0x0003a9, 0x000313 },
+ [0x001f69] = { 0x0003a9, 0x000314 },
+ [0x001f6a] = { 0x0003a9, 0x000313, 0x000300 },
+ [0x001f6b] = { 0x0003a9, 0x000314, 0x000300 },
+ [0x001f6c] = { 0x0003a9, 0x000313, 0x000301 },
+ [0x001f6d] = { 0x0003a9, 0x000314, 0x000301 },
+ [0x001f6e] = { 0x0003a9, 0x000313, 0x000342 },
+ [0x001f6f] = { 0x0003a9, 0x000314, 0x000342 },
+ [0x001f70] = { 0x0003b1, 0x000300 },
+ [0x001f71] = { 0x0003b1, 0x000301 },
+ [0x001f72] = { 0x0003b5, 0x000300 },
+ [0x001f73] = { 0x0003b5, 0x000301 },
+ [0x001f74] = { 0x0003b7, 0x000300 },
+ [0x001f75] = { 0x0003b7, 0x000301 },
+ [0x001f76] = { 0x0003b9, 0x000300 },
+ [0x001f77] = { 0x0003b9, 0x000301 },
+ [0x001f78] = { 0x0003bf, 0x000300 },
+ [0x001f79] = { 0x0003bf, 0x000301 },
+ [0x001f7a] = { 0x0003c5, 0x000300 },
+ [0x001f7b] = { 0x0003c5, 0x000301 },
+ [0x001f7c] = { 0x0003c9, 0x000300 },
+ [0x001f7d] = { 0x0003c9, 0x000301 },
+ [0x001f80] = { 0x0003b1, 0x000313, 0x000345 },
+ [0x001f81] = { 0x0003b1, 0x000314, 0x000345 },
+ [0x001f82] = { 0x0003b1, 0x000313, 0x000300, 0x000345 },
+ [0x001f83] = { 0x0003b1, 0x000314, 0x000300, 0x000345 },
+ [0x001f84] = { 0x0003b1, 0x000313, 0x000301, 0x000345 },
+ [0x001f85] = { 0x0003b1, 0x000314, 0x000301, 0x000345 },
+ [0x001f86] = { 0x0003b1, 0x000313, 0x000342, 0x000345 },
+ [0x001f87] = { 0x0003b1, 0x000314, 0x000342, 0x000345 },
+ [0x001f88] = { 0x000391, 0x000313, 0x000345 },
+ [0x001f89] = { 0x000391, 0x000314, 0x000345 },
+ [0x001f8a] = { 0x000391, 0x000313, 0x000300, 0x000345 },
+ [0x001f8b] = { 0x000391, 0x000314, 0x000300, 0x000345 },
+ [0x001f8c] = { 0x000391, 0x000313, 0x000301, 0x000345 },
+ [0x001f8d] = { 0x000391, 0x000314, 0x000301, 0x000345 },
+ [0x001f8e] = { 0x000391, 0x000313, 0x000342, 0x000345 },
+ [0x001f8f] = { 0x000391, 0x000314, 0x000342, 0x000345 },
+ [0x001f90] = { 0x0003b7, 0x000313, 0x000345 },
+ [0x001f91] = { 0x0003b7, 0x000314, 0x000345 },
+ [0x001f92] = { 0x0003b7, 0x000313, 0x000300, 0x000345 },
+ [0x001f93] = { 0x0003b7, 0x000314, 0x000300, 0x000345 },
+ [0x001f94] = { 0x0003b7, 0x000313, 0x000301, 0x000345 },
+ [0x001f95] = { 0x0003b7, 0x000314, 0x000301, 0x000345 },
+ [0x001f96] = { 0x0003b7, 0x000313, 0x000342, 0x000345 },
+ [0x001f97] = { 0x0003b7, 0x000314, 0x000342, 0x000345 },
+ [0x001f98] = { 0x000397, 0x000313, 0x000345 },
+ [0x001f99] = { 0x000397, 0x000314, 0x000345 },
+ [0x001f9a] = { 0x000397, 0x000313, 0x000300, 0x000345 },
+ [0x001f9b] = { 0x000397, 0x000314, 0x000300, 0x000345 },
+ [0x001f9c] = { 0x000397, 0x000313, 0x000301, 0x000345 },
+ [0x001f9d] = { 0x000397, 0x000314, 0x000301, 0x000345 },
+ [0x001f9e] = { 0x000397, 0x000313, 0x000342, 0x000345 },
+ [0x001f9f] = { 0x000397, 0x000314, 0x000342, 0x000345 },
+ [0x001fa0] = { 0x0003c9, 0x000313, 0x000345 },
+ [0x001fa1] = { 0x0003c9, 0x000314, 0x000345 },
+ [0x001fa2] = { 0x0003c9, 0x000313, 0x000300, 0x000345 },
+ [0x001fa3] = { 0x0003c9, 0x000314, 0x000300, 0x000345 },
+ [0x001fa4] = { 0x0003c9, 0x000313, 0x000301, 0x000345 },
+ [0x001fa5] = { 0x0003c9, 0x000314, 0x000301, 0x000345 },
+ [0x001fa6] = { 0x0003c9, 0x000313, 0x000342, 0x000345 },
+ [0x001fa7] = { 0x0003c9, 0x000314, 0x000342, 0x000345 },
+ [0x001fa8] = { 0x0003a9, 0x000313, 0x000345 },
+ [0x001fa9] = { 0x0003a9, 0x000314, 0x000345 },
+ [0x001faa] = { 0x0003a9, 0x000313, 0x000300, 0x000345 },
+ [0x001fab] = { 0x0003a9, 0x000314, 0x000300, 0x000345 },
+ [0x001fac] = { 0x0003a9, 0x000313, 0x000301, 0x000345 },
+ [0x001fad] = { 0x0003a9, 0x000314, 0x000301, 0x000345 },
+ [0x001fae] = { 0x0003a9, 0x000313, 0x000342, 0x000345 },
+ [0x001faf] = { 0x0003a9, 0x000314, 0x000342, 0x000345 },
+ [0x001fb0] = { 0x0003b1, 0x000306 },
+ [0x001fb1] = { 0x0003b1, 0x000304 },
+ [0x001fb2] = { 0x0003b1, 0x000300, 0x000345 },
+ [0x001fb3] = { 0x0003b1, 0x000345 },
+ [0x001fb4] = { 0x0003b1, 0x000301, 0x000345 },
+ [0x001fb6] = { 0x0003b1, 0x000342 },
+ [0x001fb7] = { 0x0003b1, 0x000342, 0x000345 },
+ [0x001fb8] = { 0x000391, 0x000306 },
+ [0x001fb9] = { 0x000391, 0x000304 },
+ [0x001fba] = { 0x000391, 0x000300 },
+ [0x001fbb] = { 0x000391, 0x000301 },
+ [0x001fbc] = { 0x000391, 0x000345 },
+ [0x001fbe] = { 0x0003b9 },
+ [0x001fc1] = { 0x0000a8, 0x000342 },
+ [0x001fc2] = { 0x0003b7, 0x000300, 0x000345 },
+ [0x001fc3] = { 0x0003b7, 0x000345 },
+ [0x001fc4] = { 0x0003b7, 0x000301, 0x000345 },
+ [0x001fc6] = { 0x0003b7, 0x000342 },
+ [0x001fc7] = { 0x0003b7, 0x000342, 0x000345 },
+ [0x001fc8] = { 0x000395, 0x000300 },
+ [0x001fc9] = { 0x000395, 0x000301 },
+ [0x001fca] = { 0x000397, 0x000300 },
+ [0x001fcb] = { 0x000397, 0x000301 },
+ [0x001fcc] = { 0x000397, 0x000345 },
+ [0x001fcd] = { 0x001fbf, 0x000300 },
+ [0x001fce] = { 0x001fbf, 0x000301 },
+ [0x001fcf] = { 0x001fbf, 0x000342 },
+ [0x001fd0] = { 0x0003b9, 0x000306 },
+ [0x001fd1] = { 0x0003b9, 0x000304 },
+ [0x001fd2] = { 0x0003b9, 0x000308, 0x000300 },
+ [0x001fd3] = { 0x0003b9, 0x000308, 0x000301 },
+ [0x001fd6] = { 0x0003b9, 0x000342 },
+ [0x001fd7] = { 0x0003b9, 0x000308, 0x000342 },
+ [0x001fd8] = { 0x000399, 0x000306 },
+ [0x001fd9] = { 0x000399, 0x000304 },
+ [0x001fda] = { 0x000399, 0x000300 },
+ [0x001fdb] = { 0x000399, 0x000301 },
+ [0x001fdd] = { 0x001ffe, 0x000300 },
+ [0x001fde] = { 0x001ffe, 0x000301 },
+ [0x001fdf] = { 0x001ffe, 0x000342 },
+ [0x001fe0] = { 0x0003c5, 0x000306 },
+ [0x001fe1] = { 0x0003c5, 0x000304 },
+ [0x001fe2] = { 0x0003c5, 0x000308, 0x000300 },
+ [0x001fe3] = { 0x0003c5, 0x000308, 0x000301 },
+ [0x001fe4] = { 0x0003c1, 0x000313 },
+ [0x001fe5] = { 0x0003c1, 0x000314 },
+ [0x001fe6] = { 0x0003c5, 0x000342 },
+ [0x001fe7] = { 0x0003c5, 0x000308, 0x000342 },
+ [0x001fe8] = { 0x0003a5, 0x000306 },
+ [0x001fe9] = { 0x0003a5, 0x000304 },
+ [0x001fea] = { 0x0003a5, 0x000300 },
+ [0x001feb] = { 0x0003a5, 0x000301 },
+ [0x001fec] = { 0x0003a1, 0x000314 },
+ [0x001fed] = { 0x0000a8, 0x000300 },
+ [0x001fee] = { 0x0000a8, 0x000301 },
+ [0x001fef] = { 0x000060 },
+ [0x001ff2] = { 0x0003c9, 0x000300, 0x000345 },
+ [0x001ff3] = { 0x0003c9, 0x000345 },
+ [0x001ff4] = { 0x0003c9, 0x000301, 0x000345 },
+ [0x001ff6] = { 0x0003c9, 0x000342 },
+ [0x001ff7] = { 0x0003c9, 0x000342, 0x000345 },
+ [0x001ff8] = { 0x00039f, 0x000300 },
+ [0x001ff9] = { 0x00039f, 0x000301 },
+ [0x001ffa] = { 0x0003a9, 0x000300 },
+ [0x001ffb] = { 0x0003a9, 0x000301 },
+ [0x001ffc] = { 0x0003a9, 0x000345 },
+ [0x001ffd] = { 0x0000b4 },
+ [0x002000] = { 0x002002 },
+ [0x002001] = { 0x002003 },
+ [0x002126] = { 0x0003a9 },
+ [0x00212a] = { 0x00004b },
+ [0x00212b] = { 0x000041, 0x00030a },
+ [0x00219a] = { 0x002190, 0x000338 },
+ [0x00219b] = { 0x002192, 0x000338 },
+ [0x0021ae] = { 0x002194, 0x000338 },
+ [0x0021cd] = { 0x0021d0, 0x000338 },
+ [0x0021ce] = { 0x0021d4, 0x000338 },
+ [0x0021cf] = { 0x0021d2, 0x000338 },
+ [0x002204] = { 0x002203, 0x000338 },
+ [0x002209] = { 0x002208, 0x000338 },
+ [0x00220c] = { 0x00220b, 0x000338 },
+ [0x002224] = { 0x002223, 0x000338 },
+ [0x002226] = { 0x002225, 0x000338 },
+ [0x002241] = { 0x00223c, 0x000338 },
+ [0x002244] = { 0x002243, 0x000338 },
+ [0x002247] = { 0x002245, 0x000338 },
+ [0x002249] = { 0x002248, 0x000338 },
+ [0x002260] = { 0x00003d, 0x000338 },
+ [0x002262] = { 0x002261, 0x000338 },
+ [0x00226d] = { 0x00224d, 0x000338 },
+ [0x00226e] = { 0x00003c, 0x000338 },
+ [0x00226f] = { 0x00003e, 0x000338 },
+ [0x002270] = { 0x002264, 0x000338 },
+ [0x002271] = { 0x002265, 0x000338 },
+ [0x002274] = { 0x002272, 0x000338 },
+ [0x002275] = { 0x002273, 0x000338 },
+ [0x002278] = { 0x002276, 0x000338 },
+ [0x002279] = { 0x002277, 0x000338 },
+ [0x002280] = { 0x00227a, 0x000338 },
+ [0x002281] = { 0x00227b, 0x000338 },
+ [0x002284] = { 0x002282, 0x000338 },
+ [0x002285] = { 0x002283, 0x000338 },
+ [0x002288] = { 0x002286, 0x000338 },
+ [0x002289] = { 0x002287, 0x000338 },
+ [0x0022ac] = { 0x0022a2, 0x000338 },
+ [0x0022ad] = { 0x0022a8, 0x000338 },
+ [0x0022ae] = { 0x0022a9, 0x000338 },
+ [0x0022af] = { 0x0022ab, 0x000338 },
+ [0x0022e0] = { 0x00227c, 0x000338 },
+ [0x0022e1] = { 0x00227d, 0x000338 },
+ [0x0022e2] = { 0x002291, 0x000338 },
+ [0x0022e3] = { 0x002292, 0x000338 },
+ [0x0022ea] = { 0x0022b2, 0x000338 },
+ [0x0022eb] = { 0x0022b3, 0x000338 },
+ [0x0022ec] = { 0x0022b4, 0x000338 },
+ [0x0022ed] = { 0x0022b5, 0x000338 },
+ [0x002329] = { 0x003008 },
+ [0x00232a] = { 0x003009 },
+ [0x002adc] = { 0x002add, 0x000338 },
+ [0x00304c] = { 0x00304b, 0x003099 },
+ [0x00304e] = { 0x00304d, 0x003099 },
+ [0x003050] = { 0x00304f, 0x003099 },
+ [0x003052] = { 0x003051, 0x003099 },
+ [0x003054] = { 0x003053, 0x003099 },
+ [0x003056] = { 0x003055, 0x003099 },
+ [0x003058] = { 0x003057, 0x003099 },
+ [0x00305a] = { 0x003059, 0x003099 },
+ [0x00305c] = { 0x00305b, 0x003099 },
+ [0x00305e] = { 0x00305d, 0x003099 },
+ [0x003060] = { 0x00305f, 0x003099 },
+ [0x003062] = { 0x003061, 0x003099 },
+ [0x003065] = { 0x003064, 0x003099 },
+ [0x003067] = { 0x003066, 0x003099 },
+ [0x003069] = { 0x003068, 0x003099 },
+ [0x003070] = { 0x00306f, 0x003099 },
+ [0x003071] = { 0x00306f, 0x00309a },
+ [0x003073] = { 0x003072, 0x003099 },
+ [0x003074] = { 0x003072, 0x00309a },
+ [0x003076] = { 0x003075, 0x003099 },
+ [0x003077] = { 0x003075, 0x00309a },
+ [0x003079] = { 0x003078, 0x003099 },
+ [0x00307a] = { 0x003078, 0x00309a },
+ [0x00307c] = { 0x00307b, 0x003099 },
+ [0x00307d] = { 0x00307b, 0x00309a },
+ [0x003094] = { 0x003046, 0x003099 },
+ [0x00309e] = { 0x00309d, 0x003099 },
+ [0x0030ac] = { 0x0030ab, 0x003099 },
+ [0x0030ae] = { 0x0030ad, 0x003099 },
+ [0x0030b0] = { 0x0030af, 0x003099 },
+ [0x0030b2] = { 0x0030b1, 0x003099 },
+ [0x0030b4] = { 0x0030b3, 0x003099 },
+ [0x0030b6] = { 0x0030b5, 0x003099 },
+ [0x0030b8] = { 0x0030b7, 0x003099 },
+ [0x0030ba] = { 0x0030b9, 0x003099 },
+ [0x0030bc] = { 0x0030bb, 0x003099 },
+ [0x0030be] = { 0x0030bd, 0x003099 },
+ [0x0030c0] = { 0x0030bf, 0x003099 },
+ [0x0030c2] = { 0x0030c1, 0x003099 },
+ [0x0030c5] = { 0x0030c4, 0x003099 },
+ [0x0030c7] = { 0x0030c6, 0x003099 },
+ [0x0030c9] = { 0x0030c8, 0x003099 },
+ [0x0030d0] = { 0x0030cf, 0x003099 },
+ [0x0030d1] = { 0x0030cf, 0x00309a },
+ [0x0030d3] = { 0x0030d2, 0x003099 },
+ [0x0030d4] = { 0x0030d2, 0x00309a },
+ [0x0030d6] = { 0x0030d5, 0x003099 },
+ [0x0030d7] = { 0x0030d5, 0x00309a },
+ [0x0030d9] = { 0x0030d8, 0x003099 },
+ [0x0030da] = { 0x0030d8, 0x00309a },
+ [0x0030dc] = { 0x0030db, 0x003099 },
+ [0x0030dd] = { 0x0030db, 0x00309a },
+ [0x0030f4] = { 0x0030a6, 0x003099 },
+ [0x0030f7] = { 0x0030ef, 0x003099 },
+ [0x0030f8] = { 0x0030f0, 0x003099 },
+ [0x0030f9] = { 0x0030f1, 0x003099 },
+ [0x0030fa] = { 0x0030f2, 0x003099 },
+ [0x0030fe] = { 0x0030fd, 0x003099 },
+ [0x00f900] = { 0x008c48 },
+ [0x00f901] = { 0x0066f4 },
+ [0x00f902] = { 0x008eca },
+ [0x00f903] = { 0x008cc8 },
+ [0x00f904] = { 0x006ed1 },
+ [0x00f905] = { 0x004e32 },
+ [0x00f906] = { 0x0053e5 },
+ [0x00f907] = { 0x009f9c },
+ [0x00f908] = { 0x009f9c },
+ [0x00f909] = { 0x005951 },
+ [0x00f90a] = { 0x0091d1 },
+ [0x00f90b] = { 0x005587 },
+ [0x00f90c] = { 0x005948 },
+ [0x00f90d] = { 0x0061f6 },
+ [0x00f90e] = { 0x007669 },
+ [0x00f90f] = { 0x007f85 },
+ [0x00f910] = { 0x00863f },
+ [0x00f911] = { 0x0087ba },
+ [0x00f912] = { 0x0088f8 },
+ [0x00f913] = { 0x00908f },
+ [0x00f914] = { 0x006a02 },
+ [0x00f915] = { 0x006d1b },
+ [0x00f916] = { 0x0070d9 },
+ [0x00f917] = { 0x0073de },
+ [0x00f918] = { 0x00843d },
+ [0x00f919] = { 0x00916a },
+ [0x00f91a] = { 0x0099f1 },
+ [0x00f91b] = { 0x004e82 },
+ [0x00f91c] = { 0x005375 },
+ [0x00f91d] = { 0x006b04 },
+ [0x00f91e] = { 0x00721b },
+ [0x00f91f] = { 0x00862d },
+ [0x00f920] = { 0x009e1e },
+ [0x00f921] = { 0x005d50 },
+ [0x00f922] = { 0x006feb },
+ [0x00f923] = { 0x0085cd },
+ [0x00f924] = { 0x008964 },
+ [0x00f925] = { 0x0062c9 },
+ [0x00f926] = { 0x0081d8 },
+ [0x00f927] = { 0x00881f },
+ [0x00f928] = { 0x005eca },
+ [0x00f929] = { 0x006717 },
+ [0x00f92a] = { 0x006d6a },
+ [0x00f92b] = { 0x0072fc },
+ [0x00f92c] = { 0x0090ce },
+ [0x00f92d] = { 0x004f86 },
+ [0x00f92e] = { 0x0051b7 },
+ [0x00f92f] = { 0x0052de },
+ [0x00f930] = { 0x0064c4 },
+ [0x00f931] = { 0x006ad3 },
+ [0x00f932] = { 0x007210 },
+ [0x00f933] = { 0x0076e7 },
+ [0x00f934] = { 0x008001 },
+ [0x00f935] = { 0x008606 },
+ [0x00f936] = { 0x00865c },
+ [0x00f937] = { 0x008def },
+ [0x00f938] = { 0x009732 },
+ [0x00f939] = { 0x009b6f },
+ [0x00f93a] = { 0x009dfa },
+ [0x00f93b] = { 0x00788c },
+ [0x00f93c] = { 0x00797f },
+ [0x00f93d] = { 0x007da0 },
+ [0x00f93e] = { 0x0083c9 },
+ [0x00f93f] = { 0x009304 },
+ [0x00f940] = { 0x009e7f },
+ [0x00f941] = { 0x008ad6 },
+ [0x00f942] = { 0x0058df },
+ [0x00f943] = { 0x005f04 },
+ [0x00f944] = { 0x007c60 },
+ [0x00f945] = { 0x00807e },
+ [0x00f946] = { 0x007262 },
+ [0x00f947] = { 0x0078ca },
+ [0x00f948] = { 0x008cc2 },
+ [0x00f949] = { 0x0096f7 },
+ [0x00f94a] = { 0x0058d8 },
+ [0x00f94b] = { 0x005c62 },
+ [0x00f94c] = { 0x006a13 },
+ [0x00f94d] = { 0x006dda },
+ [0x00f94e] = { 0x006f0f },
+ [0x00f94f] = { 0x007d2f },
+ [0x00f950] = { 0x007e37 },
+ [0x00f951] = { 0x00964b },
+ [0x00f952] = { 0x0052d2 },
+ [0x00f953] = { 0x00808b },
+ [0x00f954] = { 0x0051dc },
+ [0x00f955] = { 0x0051cc },
+ [0x00f956] = { 0x007a1c },
+ [0x00f957] = { 0x007dbe },
+ [0x00f958] = { 0x0083f1 },
+ [0x00f959] = { 0x009675 },
+ [0x00f95a] = { 0x008b80 },
+ [0x00f95b] = { 0x0062cf },
+ [0x00f95c] = { 0x006a02 },
+ [0x00f95d] = { 0x008afe },
+ [0x00f95e] = { 0x004e39 },
+ [0x00f95f] = { 0x005be7 },
+ [0x00f960] = { 0x006012 },
+ [0x00f961] = { 0x007387 },
+ [0x00f962] = { 0x007570 },
+ [0x00f963] = { 0x005317 },
+ [0x00f964] = { 0x0078fb },
+ [0x00f965] = { 0x004fbf },
+ [0x00f966] = { 0x005fa9 },
+ [0x00f967] = { 0x004e0d },
+ [0x00f968] = { 0x006ccc },
+ [0x00f969] = { 0x006578 },
+ [0x00f96a] = { 0x007d22 },
+ [0x00f96b] = { 0x0053c3 },
+ [0x00f96c] = { 0x00585e },
+ [0x00f96d] = { 0x007701 },
+ [0x00f96e] = { 0x008449 },
+ [0x00f96f] = { 0x008aaa },
+ [0x00f970] = { 0x006bba },
+ [0x00f971] = { 0x008fb0 },
+ [0x00f972] = { 0x006c88 },
+ [0x00f973] = { 0x0062fe },
+ [0x00f974] = { 0x0082e5 },
+ [0x00f975] = { 0x0063a0 },
+ [0x00f976] = { 0x007565 },
+ [0x00f977] = { 0x004eae },
+ [0x00f978] = { 0x005169 },
+ [0x00f979] = { 0x0051c9 },
+ [0x00f97a] = { 0x006881 },
+ [0x00f97b] = { 0x007ce7 },
+ [0x00f97c] = { 0x00826f },
+ [0x00f97d] = { 0x008ad2 },
+ [0x00f97e] = { 0x0091cf },
+ [0x00f97f] = { 0x0052f5 },
+ [0x00f980] = { 0x005442 },
+ [0x00f981] = { 0x005973 },
+ [0x00f982] = { 0x005eec },
+ [0x00f983] = { 0x0065c5 },
+ [0x00f984] = { 0x006ffe },
+ [0x00f985] = { 0x00792a },
+ [0x00f986] = { 0x0095ad },
+ [0x00f987] = { 0x009a6a },
+ [0x00f988] = { 0x009e97 },
+ [0x00f989] = { 0x009ece },
+ [0x00f98a] = { 0x00529b },
+ [0x00f98b] = { 0x0066c6 },
+ [0x00f98c] = { 0x006b77 },
+ [0x00f98d] = { 0x008f62 },
+ [0x00f98e] = { 0x005e74 },
+ [0x00f98f] = { 0x006190 },
+ [0x00f990] = { 0x006200 },
+ [0x00f991] = { 0x00649a },
+ [0x00f992] = { 0x006f23 },
+ [0x00f993] = { 0x007149 },
+ [0x00f994] = { 0x007489 },
+ [0x00f995] = { 0x0079ca },
+ [0x00f996] = { 0x007df4 },
+ [0x00f997] = { 0x00806f },
+ [0x00f998] = { 0x008f26 },
+ [0x00f999] = { 0x0084ee },
+ [0x00f99a] = { 0x009023 },
+ [0x00f99b] = { 0x00934a },
+ [0x00f99c] = { 0x005217 },
+ [0x00f99d] = { 0x0052a3 },
+ [0x00f99e] = { 0x0054bd },
+ [0x00f99f] = { 0x0070c8 },
+ [0x00f9a0] = { 0x0088c2 },
+ [0x00f9a1] = { 0x008aaa },
+ [0x00f9a2] = { 0x005ec9 },
+ [0x00f9a3] = { 0x005ff5 },
+ [0x00f9a4] = { 0x00637b },
+ [0x00f9a5] = { 0x006bae },
+ [0x00f9a6] = { 0x007c3e },
+ [0x00f9a7] = { 0x007375 },
+ [0x00f9a8] = { 0x004ee4 },
+ [0x00f9a9] = { 0x0056f9 },
+ [0x00f9aa] = { 0x005be7 },
+ [0x00f9ab] = { 0x005dba },
+ [0x00f9ac] = { 0x00601c },
+ [0x00f9ad] = { 0x0073b2 },
+ [0x00f9ae] = { 0x007469 },
+ [0x00f9af] = { 0x007f9a },
+ [0x00f9b0] = { 0x008046 },
+ [0x00f9b1] = { 0x009234 },
+ [0x00f9b2] = { 0x0096f6 },
+ [0x00f9b3] = { 0x009748 },
+ [0x00f9b4] = { 0x009818 },
+ [0x00f9b5] = { 0x004f8b },
+ [0x00f9b6] = { 0x0079ae },
+ [0x00f9b7] = { 0x0091b4 },
+ [0x00f9b8] = { 0x0096b8 },
+ [0x00f9b9] = { 0x0060e1 },
+ [0x00f9ba] = { 0x004e86 },
+ [0x00f9bb] = { 0x0050da },
+ [0x00f9bc] = { 0x005bee },
+ [0x00f9bd] = { 0x005c3f },
+ [0x00f9be] = { 0x006599 },
+ [0x00f9bf] = { 0x006a02 },
+ [0x00f9c0] = { 0x0071ce },
+ [0x00f9c1] = { 0x007642 },
+ [0x00f9c2] = { 0x0084fc },
+ [0x00f9c3] = { 0x00907c },
+ [0x00f9c4] = { 0x009f8d },
+ [0x00f9c5] = { 0x006688 },
+ [0x00f9c6] = { 0x00962e },
+ [0x00f9c7] = { 0x005289 },
+ [0x00f9c8] = { 0x00677b },
+ [0x00f9c9] = { 0x0067f3 },
+ [0x00f9ca] = { 0x006d41 },
+ [0x00f9cb] = { 0x006e9c },
+ [0x00f9cc] = { 0x007409 },
+ [0x00f9cd] = { 0x007559 },
+ [0x00f9ce] = { 0x00786b },
+ [0x00f9cf] = { 0x007d10 },
+ [0x00f9d0] = { 0x00985e },
+ [0x00f9d1] = { 0x00516d },
+ [0x00f9d2] = { 0x00622e },
+ [0x00f9d3] = { 0x009678 },
+ [0x00f9d4] = { 0x00502b },
+ [0x00f9d5] = { 0x005d19 },
+ [0x00f9d6] = { 0x006dea },
+ [0x00f9d7] = { 0x008f2a },
+ [0x00f9d8] = { 0x005f8b },
+ [0x00f9d9] = { 0x006144 },
+ [0x00f9da] = { 0x006817 },
+ [0x00f9db] = { 0x007387 },
+ [0x00f9dc] = { 0x009686 },
+ [0x00f9dd] = { 0x005229 },
+ [0x00f9de] = { 0x00540f },
+ [0x00f9df] = { 0x005c65 },
+ [0x00f9e0] = { 0x006613 },
+ [0x00f9e1] = { 0x00674e },
+ [0x00f9e2] = { 0x0068a8 },
+ [0x00f9e3] = { 0x006ce5 },
+ [0x00f9e4] = { 0x007406 },
+ [0x00f9e5] = { 0x0075e2 },
+ [0x00f9e6] = { 0x007f79 },
+ [0x00f9e7] = { 0x0088cf },
+ [0x00f9e8] = { 0x0088e1 },
+ [0x00f9e9] = { 0x0091cc },
+ [0x00f9ea] = { 0x0096e2 },
+ [0x00f9eb] = { 0x00533f },
+ [0x00f9ec] = { 0x006eba },
+ [0x00f9ed] = { 0x00541d },
+ [0x00f9ee] = { 0x0071d0 },
+ [0x00f9ef] = { 0x007498 },
+ [0x00f9f0] = { 0x0085fa },
+ [0x00f9f1] = { 0x0096a3 },
+ [0x00f9f2] = { 0x009c57 },
+ [0x00f9f3] = { 0x009e9f },
+ [0x00f9f4] = { 0x006797 },
+ [0x00f9f5] = { 0x006dcb },
+ [0x00f9f6] = { 0x0081e8 },
+ [0x00f9f7] = { 0x007acb },
+ [0x00f9f8] = { 0x007b20 },
+ [0x00f9f9] = { 0x007c92 },
+ [0x00f9fa] = { 0x0072c0 },
+ [0x00f9fb] = { 0x007099 },
+ [0x00f9fc] = { 0x008b58 },
+ [0x00f9fd] = { 0x004ec0 },
+ [0x00f9fe] = { 0x008336 },
+ [0x00f9ff] = { 0x00523a },
+ [0x00fa00] = { 0x005207 },
+ [0x00fa01] = { 0x005ea6 },
+ [0x00fa02] = { 0x0062d3 },
+ [0x00fa03] = { 0x007cd6 },
+ [0x00fa04] = { 0x005b85 },
+ [0x00fa05] = { 0x006d1e },
+ [0x00fa06] = { 0x0066b4 },
+ [0x00fa07] = { 0x008f3b },
+ [0x00fa08] = { 0x00884c },
+ [0x00fa09] = { 0x00964d },
+ [0x00fa0a] = { 0x00898b },
+ [0x00fa0b] = { 0x005ed3 },
+ [0x00fa0c] = { 0x005140 },
+ [0x00fa0d] = { 0x0055c0 },
+ [0x00fa10] = { 0x00585a },
+ [0x00fa12] = { 0x006674 },
+ [0x00fa15] = { 0x0051de },
+ [0x00fa16] = { 0x00732a },
+ [0x00fa17] = { 0x0076ca },
+ [0x00fa18] = { 0x00793c },
+ [0x00fa19] = { 0x00795e },
+ [0x00fa1a] = { 0x007965 },
+ [0x00fa1b] = { 0x00798f },
+ [0x00fa1c] = { 0x009756 },
+ [0x00fa1d] = { 0x007cbe },
+ [0x00fa1e] = { 0x007fbd },
+ [0x00fa20] = { 0x008612 },
+ [0x00fa22] = { 0x008af8 },
+ [0x00fa25] = { 0x009038 },
+ [0x00fa26] = { 0x0090fd },
+ [0x00fa2a] = { 0x0098ef },
+ [0x00fa2b] = { 0x0098fc },
+ [0x00fa2c] = { 0x009928 },
+ [0x00fa2d] = { 0x009db4 },
+ [0x00fa2e] = { 0x0090de },
+ [0x00fa2f] = { 0x0096b7 },
+ [0x00fa30] = { 0x004fae },
+ [0x00fa31] = { 0x0050e7 },
+ [0x00fa32] = { 0x00514d },
+ [0x00fa33] = { 0x0052c9 },
+ [0x00fa34] = { 0x0052e4 },
+ [0x00fa35] = { 0x005351 },
+ [0x00fa36] = { 0x00559d },
+ [0x00fa37] = { 0x005606 },
+ [0x00fa38] = { 0x005668 },
+ [0x00fa39] = { 0x005840 },
+ [0x00fa3a] = { 0x0058a8 },
+ [0x00fa3b] = { 0x005c64 },
+ [0x00fa3c] = { 0x005c6e },
+ [0x00fa3d] = { 0x006094 },
+ [0x00fa3e] = { 0x006168 },
+ [0x00fa3f] = { 0x00618e },
+ [0x00fa40] = { 0x0061f2 },
+ [0x00fa41] = { 0x00654f },
+ [0x00fa42] = { 0x0065e2 },
+ [0x00fa43] = { 0x006691 },
+ [0x00fa44] = { 0x006885 },
+ [0x00fa45] = { 0x006d77 },
+ [0x00fa46] = { 0x006e1a },
+ [0x00fa47] = { 0x006f22 },
+ [0x00fa48] = { 0x00716e },
+ [0x00fa49] = { 0x00722b },
+ [0x00fa4a] = { 0x007422 },
+ [0x00fa4b] = { 0x007891 },
+ [0x00fa4c] = { 0x00793e },
+ [0x00fa4d] = { 0x007949 },
+ [0x00fa4e] = { 0x007948 },
+ [0x00fa4f] = { 0x007950 },
+ [0x00fa50] = { 0x007956 },
+ [0x00fa51] = { 0x00795d },
+ [0x00fa52] = { 0x00798d },
+ [0x00fa53] = { 0x00798e },
+ [0x00fa54] = { 0x007a40 },
+ [0x00fa55] = { 0x007a81 },
+ [0x00fa56] = { 0x007bc0 },
+ [0x00fa57] = { 0x007df4 },
+ [0x00fa58] = { 0x007e09 },
+ [0x00fa59] = { 0x007e41 },
+ [0x00fa5a] = { 0x007f72 },
+ [0x00fa5b] = { 0x008005 },
+ [0x00fa5c] = { 0x0081ed },
+ [0x00fa5d] = { 0x008279 },
+ [0x00fa5e] = { 0x008279 },
+ [0x00fa5f] = { 0x008457 },
+ [0x00fa60] = { 0x008910 },
+ [0x00fa61] = { 0x008996 },
+ [0x00fa62] = { 0x008b01 },
+ [0x00fa63] = { 0x008b39 },
+ [0x00fa64] = { 0x008cd3 },
+ [0x00fa65] = { 0x008d08 },
+ [0x00fa66] = { 0x008fb6 },
+ [0x00fa67] = { 0x009038 },
+ [0x00fa68] = { 0x0096e3 },
+ [0x00fa69] = { 0x0097ff },
+ [0x00fa6a] = { 0x00983b },
+ [0x00fa6b] = { 0x006075 },
+ [0x00fa6c] = { 0x0242ee },
+ [0x00fa6d] = { 0x008218 },
+ [0x00fa70] = { 0x004e26 },
+ [0x00fa71] = { 0x0051b5 },
+ [0x00fa72] = { 0x005168 },
+ [0x00fa73] = { 0x004f80 },
+ [0x00fa74] = { 0x005145 },
+ [0x00fa75] = { 0x005180 },
+ [0x00fa76] = { 0x0052c7 },
+ [0x00fa77] = { 0x0052fa },
+ [0x00fa78] = { 0x00559d },
+ [0x00fa79] = { 0x005555 },
+ [0x00fa7a] = { 0x005599 },
+ [0x00fa7b] = { 0x0055e2 },
+ [0x00fa7c] = { 0x00585a },
+ [0x00fa7d] = { 0x0058b3 },
+ [0x00fa7e] = { 0x005944 },
+ [0x00fa7f] = { 0x005954 },
+ [0x00fa80] = { 0x005a62 },
+ [0x00fa81] = { 0x005b28 },
+ [0x00fa82] = { 0x005ed2 },
+ [0x00fa83] = { 0x005ed9 },
+ [0x00fa84] = { 0x005f69 },
+ [0x00fa85] = { 0x005fad },
+ [0x00fa86] = { 0x0060d8 },
+ [0x00fa87] = { 0x00614e },
+ [0x00fa88] = { 0x006108 },
+ [0x00fa89] = { 0x00618e },
+ [0x00fa8a] = { 0x006160 },
+ [0x00fa8b] = { 0x0061f2 },
+ [0x00fa8c] = { 0x006234 },
+ [0x00fa8d] = { 0x0063c4 },
+ [0x00fa8e] = { 0x00641c },
+ [0x00fa8f] = { 0x006452 },
+ [0x00fa90] = { 0x006556 },
+ [0x00fa91] = { 0x006674 },
+ [0x00fa92] = { 0x006717 },
+ [0x00fa93] = { 0x00671b },
+ [0x00fa94] = { 0x006756 },
+ [0x00fa95] = { 0x006b79 },
+ [0x00fa96] = { 0x006bba },
+ [0x00fa97] = { 0x006d41 },
+ [0x00fa98] = { 0x006edb },
+ [0x00fa99] = { 0x006ecb },
+ [0x00fa9a] = { 0x006f22 },
+ [0x00fa9b] = { 0x00701e },
+ [0x00fa9c] = { 0x00716e },
+ [0x00fa9d] = { 0x0077a7 },
+ [0x00fa9e] = { 0x007235 },
+ [0x00fa9f] = { 0x0072af },
+ [0x00faa0] = { 0x00732a },
+ [0x00faa1] = { 0x007471 },
+ [0x00faa2] = { 0x007506 },
+ [0x00faa3] = { 0x00753b },
+ [0x00faa4] = { 0x00761d },
+ [0x00faa5] = { 0x00761f },
+ [0x00faa6] = { 0x0076ca },
+ [0x00faa7] = { 0x0076db },
+ [0x00faa8] = { 0x0076f4 },
+ [0x00faa9] = { 0x00774a },
+ [0x00faaa] = { 0x007740 },
+ [0x00faab] = { 0x0078cc },
+ [0x00faac] = { 0x007ab1 },
+ [0x00faad] = { 0x007bc0 },
+ [0x00faae] = { 0x007c7b },
+ [0x00faaf] = { 0x007d5b },
+ [0x00fab0] = { 0x007df4 },
+ [0x00fab1] = { 0x007f3e },
+ [0x00fab2] = { 0x008005 },
+ [0x00fab3] = { 0x008352 },
+ [0x00fab4] = { 0x0083ef },
+ [0x00fab5] = { 0x008779 },
+ [0x00fab6] = { 0x008941 },
+ [0x00fab7] = { 0x008986 },
+ [0x00fab8] = { 0x008996 },
+ [0x00fab9] = { 0x008abf },
+ [0x00faba] = { 0x008af8 },
+ [0x00fabb] = { 0x008acb },
+ [0x00fabc] = { 0x008b01 },
+ [0x00fabd] = { 0x008afe },
+ [0x00fabe] = { 0x008aed },
+ [0x00fabf] = { 0x008b39 },
+ [0x00fac0] = { 0x008b8a },
+ [0x00fac1] = { 0x008d08 },
+ [0x00fac2] = { 0x008f38 },
+ [0x00fac3] = { 0x009072 },
+ [0x00fac4] = { 0x009199 },
+ [0x00fac5] = { 0x009276 },
+ [0x00fac6] = { 0x00967c },
+ [0x00fac7] = { 0x0096e3 },
+ [0x00fac8] = { 0x009756 },
+ [0x00fac9] = { 0x0097db },
+ [0x00faca] = { 0x0097ff },
+ [0x00facb] = { 0x00980b },
+ [0x00facc] = { 0x00983b },
+ [0x00facd] = { 0x009b12 },
+ [0x00face] = { 0x009f9c },
+ [0x00facf] = { 0x02284a },
+ [0x00fad0] = { 0x022844 },
+ [0x00fad1] = { 0x0233d5 },
+ [0x00fad2] = { 0x003b9d },
+ [0x00fad3] = { 0x004018 },
+ [0x00fad4] = { 0x004039 },
+ [0x00fad5] = { 0x025249 },
+ [0x00fad6] = { 0x025cd0 },
+ [0x00fad7] = { 0x027ed3 },
+ [0x00fad8] = { 0x009f43 },
+ [0x00fad9] = { 0x009f8e },
+ [0x00fb1d] = { 0x0005d9, 0x0005b4 },
+ [0x00fb1f] = { 0x0005f2, 0x0005b7 },
+ [0x00fb2a] = { 0x0005e9, 0x0005c1 },
+ [0x00fb2b] = { 0x0005e9, 0x0005c2 },
+ [0x00fb2c] = { 0x0005e9, 0x0005bc, 0x0005c1 },
+ [0x00fb2d] = { 0x0005e9, 0x0005bc, 0x0005c2 },
+ [0x00fb2e] = { 0x0005d0, 0x0005b7 },
+ [0x00fb2f] = { 0x0005d0, 0x0005b8 },
+ [0x00fb30] = { 0x0005d0, 0x0005bc },
+ [0x00fb31] = { 0x0005d1, 0x0005bc },
+ [0x00fb32] = { 0x0005d2, 0x0005bc },
+ [0x00fb33] = { 0x0005d3, 0x0005bc },
+ [0x00fb34] = { 0x0005d4, 0x0005bc },
+ [0x00fb35] = { 0x0005d5, 0x0005bc },
+ [0x00fb36] = { 0x0005d6, 0x0005bc },
+ [0x00fb38] = { 0x0005d8, 0x0005bc },
+ [0x00fb39] = { 0x0005d9, 0x0005bc },
+ [0x00fb3a] = { 0x0005da, 0x0005bc },
+ [0x00fb3b] = { 0x0005db, 0x0005bc },
+ [0x00fb3c] = { 0x0005dc, 0x0005bc },
+ [0x00fb3e] = { 0x0005de, 0x0005bc },
+ [0x00fb40] = { 0x0005e0, 0x0005bc },
+ [0x00fb41] = { 0x0005e1, 0x0005bc },
+ [0x00fb43] = { 0x0005e3, 0x0005bc },
+ [0x00fb44] = { 0x0005e4, 0x0005bc },
+ [0x00fb46] = { 0x0005e6, 0x0005bc },
+ [0x00fb47] = { 0x0005e7, 0x0005bc },
+ [0x00fb48] = { 0x0005e8, 0x0005bc },
+ [0x00fb49] = { 0x0005e9, 0x0005bc },
+ [0x00fb4a] = { 0x0005ea, 0x0005bc },
+ [0x00fb4b] = { 0x0005d5, 0x0005b9 },
+ [0x00fb4c] = { 0x0005d1, 0x0005bf },
+ [0x00fb4d] = { 0x0005db, 0x0005bf },
+ [0x00fb4e] = { 0x0005e4, 0x0005bf },
+ [0x01109a] = { 0x011099, 0x0110ba },
+ [0x01109c] = { 0x01109b, 0x0110ba },
+ [0x0110ab] = { 0x0110a5, 0x0110ba },
+ [0x01112e] = { 0x011131, 0x011127 },
+ [0x01112f] = { 0x011132, 0x011127 },
+ [0x01134b] = { 0x011347, 0x01133e },
+ [0x01134c] = { 0x011347, 0x011357 },
+ [0x0114bb] = { 0x0114b9, 0x0114ba },
+ [0x0114bc] = { 0x0114b9, 0x0114b0 },
+ [0x0114be] = { 0x0114b9, 0x0114bd },
+ [0x0115ba] = { 0x0115b8, 0x0115af },
+ [0x0115bb] = { 0x0115b9, 0x0115af },
+ [0x01d15e] = { 0x01d157, 0x01d165 },
+ [0x01d15f] = { 0x01d158, 0x01d165 },
+ [0x01d160] = { 0x01d158, 0x01d165, 0x01d16e },
+ [0x01d161] = { 0x01d158, 0x01d165, 0x01d16f },
+ [0x01d162] = { 0x01d158, 0x01d165, 0x01d170 },
+ [0x01d163] = { 0x01d158, 0x01d165, 0x01d171 },
+ [0x01d164] = { 0x01d158, 0x01d165, 0x01d172 },
+ [0x01d1bb] = { 0x01d1b9, 0x01d165 },
+ [0x01d1bc] = { 0x01d1ba, 0x01d165 },
+ [0x01d1bd] = { 0x01d1b9, 0x01d165, 0x01d16e },
+ [0x01d1be] = { 0x01d1ba, 0x01d165, 0x01d16e },
+ [0x01d1bf] = { 0x01d1b9, 0x01d165, 0x01d16f },
+ [0x01d1c0] = { 0x01d1ba, 0x01d165, 0x01d16f },
+ [0x02f800] = { 0x004e3d },
+ [0x02f801] = { 0x004e38 },
+ [0x02f802] = { 0x004e41 },
+ [0x02f803] = { 0x020122 },
+ [0x02f804] = { 0x004f60 },
+ [0x02f805] = { 0x004fae },
+ [0x02f806] = { 0x004fbb },
+ [0x02f807] = { 0x005002 },
+ [0x02f808] = { 0x00507a },
+ [0x02f809] = { 0x005099 },
+ [0x02f80a] = { 0x0050e7 },
+ [0x02f80b] = { 0x0050cf },
+ [0x02f80c] = { 0x00349e },
+ [0x02f80d] = { 0x02063a },
+ [0x02f80e] = { 0x00514d },
+ [0x02f80f] = { 0x005154 },
+ [0x02f810] = { 0x005164 },
+ [0x02f811] = { 0x005177 },
+ [0x02f812] = { 0x02051c },
+ [0x02f813] = { 0x0034b9 },
+ [0x02f814] = { 0x005167 },
+ [0x02f815] = { 0x00518d },
+ [0x02f816] = { 0x02054b },
+ [0x02f817] = { 0x005197 },
+ [0x02f818] = { 0x0051a4 },
+ [0x02f819] = { 0x004ecc },
+ [0x02f81a] = { 0x0051ac },
+ [0x02f81b] = { 0x0051b5 },
+ [0x02f81c] = { 0x0291df },
+ [0x02f81d] = { 0x0051f5 },
+ [0x02f81e] = { 0x005203 },
+ [0x02f81f] = { 0x0034df },
+ [0x02f820] = { 0x00523b },
+ [0x02f821] = { 0x005246 },
+ [0x02f822] = { 0x005272 },
+ [0x02f823] = { 0x005277 },
+ [0x02f824] = { 0x003515 },
+ [0x02f825] = { 0x0052c7 },
+ [0x02f826] = { 0x0052c9 },
+ [0x02f827] = { 0x0052e4 },
+ [0x02f828] = { 0x0052fa },
+ [0x02f829] = { 0x005305 },
+ [0x02f82a] = { 0x005306 },
+ [0x02f82b] = { 0x005317 },
+ [0x02f82c] = { 0x005349 },
+ [0x02f82d] = { 0x005351 },
+ [0x02f82e] = { 0x00535a },
+ [0x02f82f] = { 0x005373 },
+ [0x02f830] = { 0x00537d },
+ [0x02f831] = { 0x00537f },
+ [0x02f832] = { 0x00537f },
+ [0x02f833] = { 0x00537f },
+ [0x02f834] = { 0x020a2c },
+ [0x02f835] = { 0x007070 },
+ [0x02f836] = { 0x0053ca },
+ [0x02f837] = { 0x0053df },
+ [0x02f838] = { 0x020b63 },
+ [0x02f839] = { 0x0053eb },
+ [0x02f83a] = { 0x0053f1 },
+ [0x02f83b] = { 0x005406 },
+ [0x02f83c] = { 0x00549e },
+ [0x02f83d] = { 0x005438 },
+ [0x02f83e] = { 0x005448 },
+ [0x02f83f] = { 0x005468 },
+ [0x02f840] = { 0x0054a2 },
+ [0x02f841] = { 0x0054f6 },
+ [0x02f842] = { 0x005510 },
+ [0x02f843] = { 0x005553 },
+ [0x02f844] = { 0x005563 },
+ [0x02f845] = { 0x005584 },
+ [0x02f846] = { 0x005584 },
+ [0x02f847] = { 0x005599 },
+ [0x02f848] = { 0x0055ab },
+ [0x02f849] = { 0x0055b3 },
+ [0x02f84a] = { 0x0055c2 },
+ [0x02f84b] = { 0x005716 },
+ [0x02f84c] = { 0x005606 },
+ [0x02f84d] = { 0x005717 },
+ [0x02f84e] = { 0x005651 },
+ [0x02f84f] = { 0x005674 },
+ [0x02f850] = { 0x005207 },
+ [0x02f851] = { 0x0058ee },
+ [0x02f852] = { 0x0057ce },
+ [0x02f853] = { 0x0057f4 },
+ [0x02f854] = { 0x00580d },
+ [0x02f855] = { 0x00578b },
+ [0x02f856] = { 0x005832 },
+ [0x02f857] = { 0x005831 },
+ [0x02f858] = { 0x0058ac },
+ [0x02f859] = { 0x0214e4 },
+ [0x02f85a] = { 0x0058f2 },
+ [0x02f85b] = { 0x0058f7 },
+ [0x02f85c] = { 0x005906 },
+ [0x02f85d] = { 0x00591a },
+ [0x02f85e] = { 0x005922 },
+ [0x02f85f] = { 0x005962 },
+ [0x02f860] = { 0x0216a8 },
+ [0x02f861] = { 0x0216ea },
+ [0x02f862] = { 0x0059ec },
+ [0x02f863] = { 0x005a1b },
+ [0x02f864] = { 0x005a27 },
+ [0x02f865] = { 0x0059d8 },
+ [0x02f866] = { 0x005a66 },
+ [0x02f867] = { 0x0036ee },
+ [0x02f868] = { 0x0036fc },
+ [0x02f869] = { 0x005b08 },
+ [0x02f86a] = { 0x005b3e },
+ [0x02f86b] = { 0x005b3e },
+ [0x02f86c] = { 0x0219c8 },
+ [0x02f86d] = { 0x005bc3 },
+ [0x02f86e] = { 0x005bd8 },
+ [0x02f86f] = { 0x005be7 },
+ [0x02f870] = { 0x005bf3 },
+ [0x02f871] = { 0x021b18 },
+ [0x02f872] = { 0x005bff },
+ [0x02f873] = { 0x005c06 },
+ [0x02f874] = { 0x005f53 },
+ [0x02f875] = { 0x005c22 },
+ [0x02f876] = { 0x003781 },
+ [0x02f877] = { 0x005c60 },
+ [0x02f878] = { 0x005c6e },
+ [0x02f879] = { 0x005cc0 },
+ [0x02f87a] = { 0x005c8d },
+ [0x02f87b] = { 0x021de4 },
+ [0x02f87c] = { 0x005d43 },
+ [0x02f87d] = { 0x021de6 },
+ [0x02f87e] = { 0x005d6e },
+ [0x02f87f] = { 0x005d6b },
+ [0x02f880] = { 0x005d7c },
+ [0x02f881] = { 0x005de1 },
+ [0x02f882] = { 0x005de2 },
+ [0x02f883] = { 0x00382f },
+ [0x02f884] = { 0x005dfd },
+ [0x02f885] = { 0x005e28 },
+ [0x02f886] = { 0x005e3d },
+ [0x02f887] = { 0x005e69 },
+ [0x02f888] = { 0x003862 },
+ [0x02f889] = { 0x022183 },
+ [0x02f88a] = { 0x00387c },
+ [0x02f88b] = { 0x005eb0 },
+ [0x02f88c] = { 0x005eb3 },
+ [0x02f88d] = { 0x005eb6 },
+ [0x02f88e] = { 0x005eca },
+ [0x02f88f] = { 0x02a392 },
+ [0x02f890] = { 0x005efe },
+ [0x02f891] = { 0x022331 },
+ [0x02f892] = { 0x022331 },
+ [0x02f893] = { 0x008201 },
+ [0x02f894] = { 0x005f22 },
+ [0x02f895] = { 0x005f22 },
+ [0x02f896] = { 0x0038c7 },
+ [0x02f897] = { 0x0232b8 },
+ [0x02f898] = { 0x0261da },
+ [0x02f899] = { 0x005f62 },
+ [0x02f89a] = { 0x005f6b },
+ [0x02f89b] = { 0x0038e3 },
+ [0x02f89c] = { 0x005f9a },
+ [0x02f89d] = { 0x005fcd },
+ [0x02f89e] = { 0x005fd7 },
+ [0x02f89f] = { 0x005ff9 },
+ [0x02f8a0] = { 0x006081 },
+ [0x02f8a1] = { 0x00393a },
+ [0x02f8a2] = { 0x00391c },
+ [0x02f8a3] = { 0x006094 },
+ [0x02f8a4] = { 0x0226d4 },
+ [0x02f8a5] = { 0x0060c7 },
+ [0x02f8a6] = { 0x006148 },
+ [0x02f8a7] = { 0x00614c },
+ [0x02f8a8] = { 0x00614e },
+ [0x02f8a9] = { 0x00614c },
+ [0x02f8aa] = { 0x00617a },
+ [0x02f8ab] = { 0x00618e },
+ [0x02f8ac] = { 0x0061b2 },
+ [0x02f8ad] = { 0x0061a4 },
+ [0x02f8ae] = { 0x0061af },
+ [0x02f8af] = { 0x0061de },
+ [0x02f8b0] = { 0x0061f2 },
+ [0x02f8b1] = { 0x0061f6 },
+ [0x02f8b2] = { 0x006210 },
+ [0x02f8b3] = { 0x00621b },
+ [0x02f8b4] = { 0x00625d },
+ [0x02f8b5] = { 0x0062b1 },
+ [0x02f8b6] = { 0x0062d4 },
+ [0x02f8b7] = { 0x006350 },
+ [0x02f8b8] = { 0x022b0c },
+ [0x02f8b9] = { 0x00633d },
+ [0x02f8ba] = { 0x0062fc },
+ [0x02f8bb] = { 0x006368 },
+ [0x02f8bc] = { 0x006383 },
+ [0x02f8bd] = { 0x0063e4 },
+ [0x02f8be] = { 0x022bf1 },
+ [0x02f8bf] = { 0x006422 },
+ [0x02f8c0] = { 0x0063c5 },
+ [0x02f8c1] = { 0x0063a9 },
+ [0x02f8c2] = { 0x003a2e },
+ [0x02f8c3] = { 0x006469 },
+ [0x02f8c4] = { 0x00647e },
+ [0x02f8c5] = { 0x00649d },
+ [0x02f8c6] = { 0x006477 },
+ [0x02f8c7] = { 0x003a6c },
+ [0x02f8c8] = { 0x00654f },
+ [0x02f8c9] = { 0x00656c },
+ [0x02f8ca] = { 0x02300a },
+ [0x02f8cb] = { 0x0065e3 },
+ [0x02f8cc] = { 0x0066f8 },
+ [0x02f8cd] = { 0x006649 },
+ [0x02f8ce] = { 0x003b19 },
+ [0x02f8cf] = { 0x006691 },
+ [0x02f8d0] = { 0x003b08 },
+ [0x02f8d1] = { 0x003ae4 },
+ [0x02f8d2] = { 0x005192 },
+ [0x02f8d3] = { 0x005195 },
+ [0x02f8d4] = { 0x006700 },
+ [0x02f8d5] = { 0x00669c },
+ [0x02f8d6] = { 0x0080ad },
+ [0x02f8d7] = { 0x0043d9 },
+ [0x02f8d8] = { 0x006717 },
+ [0x02f8d9] = { 0x00671b },
+ [0x02f8da] = { 0x006721 },
+ [0x02f8db] = { 0x00675e },
+ [0x02f8dc] = { 0x006753 },
+ [0x02f8dd] = { 0x0233c3 },
+ [0x02f8de] = { 0x003b49 },
+ [0x02f8df] = { 0x0067fa },
+ [0x02f8e0] = { 0x006785 },
+ [0x02f8e1] = { 0x006852 },
+ [0x02f8e2] = { 0x006885 },
+ [0x02f8e3] = { 0x02346d },
+ [0x02f8e4] = { 0x00688e },
+ [0x02f8e5] = { 0x00681f },
+ [0x02f8e6] = { 0x006914 },
+ [0x02f8e7] = { 0x003b9d },
+ [0x02f8e8] = { 0x006942 },
+ [0x02f8e9] = { 0x0069a3 },
+ [0x02f8ea] = { 0x0069ea },
+ [0x02f8eb] = { 0x006aa8 },
+ [0x02f8ec] = { 0x0236a3 },
+ [0x02f8ed] = { 0x006adb },
+ [0x02f8ee] = { 0x003c18 },
+ [0x02f8ef] = { 0x006b21 },
+ [0x02f8f0] = { 0x0238a7 },
+ [0x02f8f1] = { 0x006b54 },
+ [0x02f8f2] = { 0x003c4e },
+ [0x02f8f3] = { 0x006b72 },
+ [0x02f8f4] = { 0x006b9f },
+ [0x02f8f5] = { 0x006bba },
+ [0x02f8f6] = { 0x006bbb },
+ [0x02f8f7] = { 0x023a8d },
+ [0x02f8f8] = { 0x021d0b },
+ [0x02f8f9] = { 0x023afa },
+ [0x02f8fa] = { 0x006c4e },
+ [0x02f8fb] = { 0x023cbc },
+ [0x02f8fc] = { 0x006cbf },
+ [0x02f8fd] = { 0x006ccd },
+ [0x02f8fe] = { 0x006c67 },
+ [0x02f8ff] = { 0x006d16 },
+ [0x02f900] = { 0x006d3e },
+ [0x02f901] = { 0x006d77 },
+ [0x02f902] = { 0x006d41 },
+ [0x02f903] = { 0x006d69 },
+ [0x02f904] = { 0x006d78 },
+ [0x02f905] = { 0x006d85 },
+ [0x02f906] = { 0x023d1e },
+ [0x02f907] = { 0x006d34 },
+ [0x02f908] = { 0x006e2f },
+ [0x02f909] = { 0x006e6e },
+ [0x02f90a] = { 0x003d33 },
+ [0x02f90b] = { 0x006ecb },
+ [0x02f90c] = { 0x006ec7 },
+ [0x02f90d] = { 0x023ed1 },
+ [0x02f90e] = { 0x006df9 },
+ [0x02f90f] = { 0x006f6e },
+ [0x02f910] = { 0x023f5e },
+ [0x02f911] = { 0x023f8e },
+ [0x02f912] = { 0x006fc6 },
+ [0x02f913] = { 0x007039 },
+ [0x02f914] = { 0x00701e },
+ [0x02f915] = { 0x00701b },
+ [0x02f916] = { 0x003d96 },
+ [0x02f917] = { 0x00704a },
+ [0x02f918] = { 0x00707d },
+ [0x02f919] = { 0x007077 },
+ [0x02f91a] = { 0x0070ad },
+ [0x02f91b] = { 0x020525 },
+ [0x02f91c] = { 0x007145 },
+ [0x02f91d] = { 0x024263 },
+ [0x02f91e] = { 0x00719c },
+ [0x02f91f] = { 0x0243ab },
+ [0x02f920] = { 0x007228 },
+ [0x02f921] = { 0x007235 },
+ [0x02f922] = { 0x007250 },
+ [0x02f923] = { 0x024608 },
+ [0x02f924] = { 0x007280 },
+ [0x02f925] = { 0x007295 },
+ [0x02f926] = { 0x024735 },
+ [0x02f927] = { 0x024814 },
+ [0x02f928] = { 0x00737a },
+ [0x02f929] = { 0x00738b },
+ [0x02f92a] = { 0x003eac },
+ [0x02f92b] = { 0x0073a5 },
+ [0x02f92c] = { 0x003eb8 },
+ [0x02f92d] = { 0x003eb8 },
+ [0x02f92e] = { 0x007447 },
+ [0x02f92f] = { 0x00745c },
+ [0x02f930] = { 0x007471 },
+ [0x02f931] = { 0x007485 },
+ [0x02f932] = { 0x0074ca },
+ [0x02f933] = { 0x003f1b },
+ [0x02f934] = { 0x007524 },
+ [0x02f935] = { 0x024c36 },
+ [0x02f936] = { 0x00753e },
+ [0x02f937] = { 0x024c92 },
+ [0x02f938] = { 0x007570 },
+ [0x02f939] = { 0x02219f },
+ [0x02f93a] = { 0x007610 },
+ [0x02f93b] = { 0x024fa1 },
+ [0x02f93c] = { 0x024fb8 },
+ [0x02f93d] = { 0x025044 },
+ [0x02f93e] = { 0x003ffc },
+ [0x02f93f] = { 0x004008 },
+ [0x02f940] = { 0x0076f4 },
+ [0x02f941] = { 0x0250f3 },
+ [0x02f942] = { 0x0250f2 },
+ [0x02f943] = { 0x025119 },
+ [0x02f944] = { 0x025133 },
+ [0x02f945] = { 0x00771e },
+ [0x02f946] = { 0x00771f },
+ [0x02f947] = { 0x00771f },
+ [0x02f948] = { 0x00774a },
+ [0x02f949] = { 0x004039 },
+ [0x02f94a] = { 0x00778b },
+ [0x02f94b] = { 0x004046 },
+ [0x02f94c] = { 0x004096 },
+ [0x02f94d] = { 0x02541d },
+ [0x02f94e] = { 0x00784e },
+ [0x02f94f] = { 0x00788c },
+ [0x02f950] = { 0x0078cc },
+ [0x02f951] = { 0x0040e3 },
+ [0x02f952] = { 0x025626 },
+ [0x02f953] = { 0x007956 },
+ [0x02f954] = { 0x02569a },
+ [0x02f955] = { 0x0256c5 },
+ [0x02f956] = { 0x00798f },
+ [0x02f957] = { 0x0079eb },
+ [0x02f958] = { 0x00412f },
+ [0x02f959] = { 0x007a40 },
+ [0x02f95a] = { 0x007a4a },
+ [0x02f95b] = { 0x007a4f },
+ [0x02f95c] = { 0x02597c },
+ [0x02f95d] = { 0x025aa7 },
+ [0x02f95e] = { 0x025aa7 },
+ [0x02f95f] = { 0x007aee },
+ [0x02f960] = { 0x004202 },
+ [0x02f961] = { 0x025bab },
+ [0x02f962] = { 0x007bc6 },
+ [0x02f963] = { 0x007bc9 },
+ [0x02f964] = { 0x004227 },
+ [0x02f965] = { 0x025c80 },
+ [0x02f966] = { 0x007cd2 },
+ [0x02f967] = { 0x0042a0 },
+ [0x02f968] = { 0x007ce8 },
+ [0x02f969] = { 0x007ce3 },
+ [0x02f96a] = { 0x007d00 },
+ [0x02f96b] = { 0x025f86 },
+ [0x02f96c] = { 0x007d63 },
+ [0x02f96d] = { 0x004301 },
+ [0x02f96e] = { 0x007dc7 },
+ [0x02f96f] = { 0x007e02 },
+ [0x02f970] = { 0x007e45 },
+ [0x02f971] = { 0x004334 },
+ [0x02f972] = { 0x026228 },
+ [0x02f973] = { 0x026247 },
+ [0x02f974] = { 0x004359 },
+ [0x02f975] = { 0x0262d9 },
+ [0x02f976] = { 0x007f7a },
+ [0x02f977] = { 0x02633e },
+ [0x02f978] = { 0x007f95 },
+ [0x02f979] = { 0x007ffa },
+ [0x02f97a] = { 0x008005 },
+ [0x02f97b] = { 0x0264da },
+ [0x02f97c] = { 0x026523 },
+ [0x02f97d] = { 0x008060 },
+ [0x02f97e] = { 0x0265a8 },
+ [0x02f97f] = { 0x008070 },
+ [0x02f980] = { 0x02335f },
+ [0x02f981] = { 0x0043d5 },
+ [0x02f982] = { 0x0080b2 },
+ [0x02f983] = { 0x008103 },
+ [0x02f984] = { 0x00440b },
+ [0x02f985] = { 0x00813e },
+ [0x02f986] = { 0x005ab5 },
+ [0x02f987] = { 0x0267a7 },
+ [0x02f988] = { 0x0267b5 },
+ [0x02f989] = { 0x023393 },
+ [0x02f98a] = { 0x02339c },
+ [0x02f98b] = { 0x008201 },
+ [0x02f98c] = { 0x008204 },
+ [0x02f98d] = { 0x008f9e },
+ [0x02f98e] = { 0x00446b },
+ [0x02f98f] = { 0x008291 },
+ [0x02f990] = { 0x00828b },
+ [0x02f991] = { 0x00829d },
+ [0x02f992] = { 0x0052b3 },
+ [0x02f993] = { 0x0082b1 },
+ [0x02f994] = { 0x0082b3 },
+ [0x02f995] = { 0x0082bd },
+ [0x02f996] = { 0x0082e6 },
+ [0x02f997] = { 0x026b3c },
+ [0x02f998] = { 0x0082e5 },
+ [0x02f999] = { 0x00831d },
+ [0x02f99a] = { 0x008363 },
+ [0x02f99b] = { 0x0083ad },
+ [0x02f99c] = { 0x008323 },
+ [0x02f99d] = { 0x0083bd },
+ [0x02f99e] = { 0x0083e7 },
+ [0x02f99f] = { 0x008457 },
+ [0x02f9a0] = { 0x008353 },
+ [0x02f9a1] = { 0x0083ca },
+ [0x02f9a2] = { 0x0083cc },
+ [0x02f9a3] = { 0x0083dc },
+ [0x02f9a4] = { 0x026c36 },
+ [0x02f9a5] = { 0x026d6b },
+ [0x02f9a6] = { 0x026cd5 },
+ [0x02f9a7] = { 0x00452b },
+ [0x02f9a8] = { 0x0084f1 },
+ [0x02f9a9] = { 0x0084f3 },
+ [0x02f9aa] = { 0x008516 },
+ [0x02f9ab] = { 0x0273ca },
+ [0x02f9ac] = { 0x008564 },
+ [0x02f9ad] = { 0x026f2c },
+ [0x02f9ae] = { 0x00455d },
+ [0x02f9af] = { 0x004561 },
+ [0x02f9b0] = { 0x026fb1 },
+ [0x02f9b1] = { 0x0270d2 },
+ [0x02f9b2] = { 0x00456b },
+ [0x02f9b3] = { 0x008650 },
+ [0x02f9b4] = { 0x00865c },
+ [0x02f9b5] = { 0x008667 },
+ [0x02f9b6] = { 0x008669 },
+ [0x02f9b7] = { 0x0086a9 },
+ [0x02f9b8] = { 0x008688 },
+ [0x02f9b9] = { 0x00870e },
+ [0x02f9ba] = { 0x0086e2 },
+ [0x02f9bb] = { 0x008779 },
+ [0x02f9bc] = { 0x008728 },
+ [0x02f9bd] = { 0x00876b },
+ [0x02f9be] = { 0x008786 },
+ [0x02f9bf] = { 0x0045d7 },
+ [0x02f9c0] = { 0x0087e1 },
+ [0x02f9c1] = { 0x008801 },
+ [0x02f9c2] = { 0x0045f9 },
+ [0x02f9c3] = { 0x008860 },
+ [0x02f9c4] = { 0x008863 },
+ [0x02f9c5] = { 0x027667 },
+ [0x02f9c6] = { 0x0088d7 },
+ [0x02f9c7] = { 0x0088de },
+ [0x02f9c8] = { 0x004635 },
+ [0x02f9c9] = { 0x0088fa },
+ [0x02f9ca] = { 0x0034bb },
+ [0x02f9cb] = { 0x0278ae },
+ [0x02f9cc] = { 0x027966 },
+ [0x02f9cd] = { 0x0046be },
+ [0x02f9ce] = { 0x0046c7 },
+ [0x02f9cf] = { 0x008aa0 },
+ [0x02f9d0] = { 0x008aed },
+ [0x02f9d1] = { 0x008b8a },
+ [0x02f9d2] = { 0x008c55 },
+ [0x02f9d3] = { 0x027ca8 },
+ [0x02f9d4] = { 0x008cab },
+ [0x02f9d5] = { 0x008cc1 },
+ [0x02f9d6] = { 0x008d1b },
+ [0x02f9d7] = { 0x008d77 },
+ [0x02f9d8] = { 0x027f2f },
+ [0x02f9d9] = { 0x020804 },
+ [0x02f9da] = { 0x008dcb },
+ [0x02f9db] = { 0x008dbc },
+ [0x02f9dc] = { 0x008df0 },
+ [0x02f9dd] = { 0x0208de },
+ [0x02f9de] = { 0x008ed4 },
+ [0x02f9df] = { 0x008f38 },
+ [0x02f9e0] = { 0x0285d2 },
+ [0x02f9e1] = { 0x0285ed },
+ [0x02f9e2] = { 0x009094 },
+ [0x02f9e3] = { 0x0090f1 },
+ [0x02f9e4] = { 0x009111 },
+ [0x02f9e5] = { 0x02872e },
+ [0x02f9e6] = { 0x00911b },
+ [0x02f9e7] = { 0x009238 },
+ [0x02f9e8] = { 0x0092d7 },
+ [0x02f9e9] = { 0x0092d8 },
+ [0x02f9ea] = { 0x00927c },
+ [0x02f9eb] = { 0x0093f9 },
+ [0x02f9ec] = { 0x009415 },
+ [0x02f9ed] = { 0x028bfa },
+ [0x02f9ee] = { 0x00958b },
+ [0x02f9ef] = { 0x004995 },
+ [0x02f9f0] = { 0x0095b7 },
+ [0x02f9f1] = { 0x028d77 },
+ [0x02f9f2] = { 0x0049e6 },
+ [0x02f9f3] = { 0x0096c3 },
+ [0x02f9f4] = { 0x005db2 },
+ [0x02f9f5] = { 0x009723 },
+ [0x02f9f6] = { 0x029145 },
+ [0x02f9f7] = { 0x02921a },
+ [0x02f9f8] = { 0x004a6e },
+ [0x02f9f9] = { 0x004a76 },
+ [0x02f9fa] = { 0x0097e0 },
+ [0x02f9fb] = { 0x02940a },
+ [0x02f9fc] = { 0x004ab2 },
+ [0x02f9fd] = { 0x029496 },
+ [0x02f9fe] = { 0x00980b },
+ [0x02f9ff] = { 0x00980b },
+ [0x02fa00] = { 0x009829 },
+ [0x02fa01] = { 0x0295b6 },
+ [0x02fa02] = { 0x0098e2 },
+ [0x02fa03] = { 0x004b33 },
+ [0x02fa04] = { 0x009929 },
+ [0x02fa05] = { 0x0099a7 },
+ [0x02fa06] = { 0x0099c2 },
+ [0x02fa07] = { 0x0099fe },
+ [0x02fa08] = { 0x004bce },
+ [0x02fa09] = { 0x029b30 },
+ [0x02fa0a] = { 0x009b12 },
+ [0x02fa0b] = { 0x009c40 },
+ [0x02fa0c] = { 0x009cfd },
+ [0x02fa0d] = { 0x004cce },
+ [0x02fa0e] = { 0x004ced },
+ [0x02fa0f] = { 0x009d67 },
+ [0x02fa10] = { 0x02a0ce },
+ [0x02fa11] = { 0x004cf8 },
+ [0x02fa12] = { 0x02a105 },
+ [0x02fa13] = { 0x02a20e },
+ [0x02fa14] = { 0x02a291 },
+ [0x02fa15] = { 0x009ebb },
+ [0x02fa16] = { 0x004d56 },
+ [0x02fa17] = { 0x009ef9 },
+ [0x02fa18] = { 0x009efe },
+ [0x02fa19] = { 0x009f05 },
+ [0x02fa1a] = { 0x009f0f },
+ [0x02fa1b] = { 0x009f16 },
+ [0x02fa1c] = { 0x009f3b },
+ [0x02fa1d] = { 0x02a600 },
+ },
+
+ decompK = {
+ [0x0000a0] = { 0x000020 },
+ [0x0000a8] = { 0x000020, 0x000308 },
+ [0x0000aa] = { 0x000061 },
+ [0x0000af] = { 0x000020, 0x000304 },
+ [0x0000b2] = { 0x000032 },
+ [0x0000b3] = { 0x000033 },
+ [0x0000b4] = { 0x000020, 0x000301 },
+ [0x0000b5] = { 0x0003bc },
+ [0x0000b8] = { 0x000020, 0x000327 },
+ [0x0000b9] = { 0x000031 },
+ [0x0000ba] = { 0x00006f },
+ [0x0000bc] = { 0x000031, 0x002044, 0x000034 },
+ [0x0000bd] = { 0x000031, 0x002044, 0x000032 },
+ [0x0000be] = { 0x000033, 0x002044, 0x000034 },
+ [0x000132] = { 0x000049, 0x00004a },
+ [0x000133] = { 0x000069, 0x00006a },
+ [0x00013f] = { 0x00004c, 0x0000b7 },
+ [0x000140] = { 0x00006c, 0x0000b7 },
+ [0x000149] = { 0x0002bc, 0x00006e },
+ [0x00017f] = { 0x000073 },
+ [0x0001c4] = { 0x000044, 0x00005a, 0x00030c },
+ [0x0001c5] = { 0x000044, 0x00007a, 0x00030c },
+ [0x0001c6] = { 0x000064, 0x00007a, 0x00030c },
+ [0x0001c7] = { 0x00004c, 0x00004a },
+ [0x0001c8] = { 0x00004c, 0x00006a },
+ [0x0001c9] = { 0x00006c, 0x00006a },
+ [0x0001ca] = { 0x00004e, 0x00004a },
+ [0x0001cb] = { 0x00004e, 0x00006a },
+ [0x0001cc] = { 0x00006e, 0x00006a },
+ [0x0001f1] = { 0x000044, 0x00005a },
+ [0x0001f2] = { 0x000044, 0x00007a },
+ [0x0001f3] = { 0x000064, 0x00007a },
+ [0x0002b0] = { 0x000068 },
+ [0x0002b1] = { 0x000266 },
+ [0x0002b2] = { 0x00006a },
+ [0x0002b3] = { 0x000072 },
+ [0x0002b4] = { 0x000279 },
+ [0x0002b5] = { 0x00027b },
+ [0x0002b6] = { 0x000281 },
+ [0x0002b7] = { 0x000077 },
+ [0x0002b8] = { 0x000079 },
+ [0x0002d8] = { 0x000020, 0x000306 },
+ [0x0002d9] = { 0x000020, 0x000307 },
+ [0x0002da] = { 0x000020, 0x00030a },
+ [0x0002db] = { 0x000020, 0x000328 },
+ [0x0002dc] = { 0x000020, 0x000303 },
+ [0x0002dd] = { 0x000020, 0x00030b },
+ [0x0002e0] = { 0x000263 },
+ [0x0002e1] = { 0x00006c },
+ [0x0002e2] = { 0x000073 },
+ [0x0002e3] = { 0x000078 },
+ [0x0002e4] = { 0x000295 },
+ [0x00037a] = { 0x000020, 0x000345 },
+ [0x000384] = { 0x000020, 0x000301 },
+ [0x000385] = { 0x000020, 0x000308, 0x000301 },
+ [0x0003d0] = { 0x0003b2 },
+ [0x0003d1] = { 0x0003b8 },
+ [0x0003d2] = { 0x0003a5 },
+ [0x0003d3] = { 0x0003a5, 0x000301 },
+ [0x0003d4] = { 0x0003a5, 0x000308 },
+ [0x0003d5] = { 0x0003c6 },
+ [0x0003d6] = { 0x0003c0 },
+ [0x0003f0] = { 0x0003ba },
+ [0x0003f1] = { 0x0003c1 },
+ [0x0003f2] = { 0x0003c2 },
+ [0x0003f4] = { 0x000398 },
+ [0x0003f5] = { 0x0003b5 },
+ [0x0003f9] = { 0x0003a3 },
+ [0x000587] = { 0x000565, 0x000582 },
+ [0x000675] = { 0x000627, 0x000674 },
+ [0x000676] = { 0x000648, 0x000674 },
+ [0x000677] = { 0x0006c7, 0x000674 },
+ [0x000678] = { 0x00064a, 0x000674 },
+ [0x000e33] = { 0x000e4d, 0x000e32 },
+ [0x000eb3] = { 0x000ecd, 0x000eb2 },
+ [0x000edc] = { 0x000eab, 0x000e99 },
+ [0x000edd] = { 0x000eab, 0x000ea1 },
+ [0x000f0c] = { 0x000f0b },
+ [0x000f77] = { 0x000fb2, 0x000f71, 0x000f80 },
+ [0x000f79] = { 0x000fb3, 0x000f71, 0x000f80 },
+ [0x0010fc] = { 0x0010dc },
+ [0x001d2c] = { 0x000041 },
+ [0x001d2d] = { 0x0000c6 },
+ [0x001d2e] = { 0x000042 },
+ [0x001d30] = { 0x000044 },
+ [0x001d31] = { 0x000045 },
+ [0x001d32] = { 0x00018e },
+ [0x001d33] = { 0x000047 },
+ [0x001d34] = { 0x000048 },
+ [0x001d35] = { 0x000049 },
+ [0x001d36] = { 0x00004a },
+ [0x001d37] = { 0x00004b },
+ [0x001d38] = { 0x00004c },
+ [0x001d39] = { 0x00004d },
+ [0x001d3a] = { 0x00004e },
+ [0x001d3c] = { 0x00004f },
+ [0x001d3d] = { 0x000222 },
+ [0x001d3e] = { 0x000050 },
+ [0x001d3f] = { 0x000052 },
+ [0x001d40] = { 0x000054 },
+ [0x001d41] = { 0x000055 },
+ [0x001d42] = { 0x000057 },
+ [0x001d43] = { 0x000061 },
+ [0x001d44] = { 0x000250 },
+ [0x001d45] = { 0x000251 },
+ [0x001d46] = { 0x001d02 },
+ [0x001d47] = { 0x000062 },
+ [0x001d48] = { 0x000064 },
+ [0x001d49] = { 0x000065 },
+ [0x001d4a] = { 0x000259 },
+ [0x001d4b] = { 0x00025b },
+ [0x001d4c] = { 0x00025c },
+ [0x001d4d] = { 0x000067 },
+ [0x001d4f] = { 0x00006b },
+ [0x001d50] = { 0x00006d },
+ [0x001d51] = { 0x00014b },
+ [0x001d52] = { 0x00006f },
+ [0x001d53] = { 0x000254 },
+ [0x001d54] = { 0x001d16 },
+ [0x001d55] = { 0x001d17 },
+ [0x001d56] = { 0x000070 },
+ [0x001d57] = { 0x000074 },
+ [0x001d58] = { 0x000075 },
+ [0x001d59] = { 0x001d1d },
+ [0x001d5a] = { 0x00026f },
+ [0x001d5b] = { 0x000076 },
+ [0x001d5c] = { 0x001d25 },
+ [0x001d5d] = { 0x0003b2 },
+ [0x001d5e] = { 0x0003b3 },
+ [0x001d5f] = { 0x0003b4 },
+ [0x001d60] = { 0x0003c6 },
+ [0x001d61] = { 0x0003c7 },
+ [0x001d62] = { 0x000069 },
+ [0x001d63] = { 0x000072 },
+ [0x001d64] = { 0x000075 },
+ [0x001d65] = { 0x000076 },
+ [0x001d66] = { 0x0003b2 },
+ [0x001d67] = { 0x0003b3 },
+ [0x001d68] = { 0x0003c1 },
+ [0x001d69] = { 0x0003c6 },
+ [0x001d6a] = { 0x0003c7 },
+ [0x001d78] = { 0x00043d },
+ [0x001d9b] = { 0x000252 },
+ [0x001d9c] = { 0x000063 },
+ [0x001d9d] = { 0x000255 },
+ [0x001d9e] = { 0x0000f0 },
+ [0x001d9f] = { 0x00025c },
+ [0x001da0] = { 0x000066 },
+ [0x001da1] = { 0x00025f },
+ [0x001da2] = { 0x000261 },
+ [0x001da3] = { 0x000265 },
+ [0x001da4] = { 0x000268 },
+ [0x001da5] = { 0x000269 },
+ [0x001da6] = { 0x00026a },
+ [0x001da7] = { 0x001d7b },
+ [0x001da8] = { 0x00029d },
+ [0x001da9] = { 0x00026d },
+ [0x001daa] = { 0x001d85 },
+ [0x001dab] = { 0x00029f },
+ [0x001dac] = { 0x000271 },
+ [0x001dad] = { 0x000270 },
+ [0x001dae] = { 0x000272 },
+ [0x001daf] = { 0x000273 },
+ [0x001db0] = { 0x000274 },
+ [0x001db1] = { 0x000275 },
+ [0x001db2] = { 0x000278 },
+ [0x001db3] = { 0x000282 },
+ [0x001db4] = { 0x000283 },
+ [0x001db5] = { 0x0001ab },
+ [0x001db6] = { 0x000289 },
+ [0x001db7] = { 0x00028a },
+ [0x001db8] = { 0x001d1c },
+ [0x001db9] = { 0x00028b },
+ [0x001dba] = { 0x00028c },
+ [0x001dbb] = { 0x00007a },
+ [0x001dbc] = { 0x000290 },
+ [0x001dbd] = { 0x000291 },
+ [0x001dbe] = { 0x000292 },
+ [0x001dbf] = { 0x0003b8 },
+ [0x001e9a] = { 0x000061, 0x0002be },
+ [0x001e9b] = { 0x000073, 0x000307 },
+ [0x001fbd] = { 0x000020, 0x000313 },
+ [0x001fbf] = { 0x000020, 0x000313 },
+ [0x001fc0] = { 0x000020, 0x000342 },
+ [0x001fc1] = { 0x000020, 0x000308, 0x000342 },
+ [0x001fcd] = { 0x000020, 0x000313, 0x000300 },
+ [0x001fce] = { 0x000020, 0x000313, 0x000301 },
+ [0x001fcf] = { 0x000020, 0x000313, 0x000342 },
+ [0x001fdd] = { 0x000020, 0x000314, 0x000300 },
+ [0x001fde] = { 0x000020, 0x000314, 0x000301 },
+ [0x001fdf] = { 0x000020, 0x000314, 0x000342 },
+ [0x001fed] = { 0x000020, 0x000308, 0x000300 },
+ [0x001fee] = { 0x000020, 0x000308, 0x000301 },
+ [0x001ffd] = { 0x000020, 0x000301 },
+ [0x001ffe] = { 0x000020, 0x000314 },
+ [0x002000] = { 0x000020 },
+ [0x002001] = { 0x000020 },
+ [0x002002] = { 0x000020 },
+ [0x002003] = { 0x000020 },
+ [0x002004] = { 0x000020 },
+ [0x002005] = { 0x000020 },
+ [0x002006] = { 0x000020 },
+ [0x002007] = { 0x000020 },
+ [0x002008] = { 0x000020 },
+ [0x002009] = { 0x000020 },
+ [0x00200a] = { 0x000020 },
+ [0x002011] = { 0x002010 },
+ [0x002017] = { 0x000020, 0x000333 },
+ [0x002024] = { 0x00002e },
+ [0x002025] = { 0x00002e, 0x00002e },
+ [0x002026] = { 0x00002e, 0x00002e, 0x00002e },
+ [0x00202f] = { 0x000020 },
+ [0x002033] = { 0x002032, 0x002032 },
+ [0x002034] = { 0x002032, 0x002032, 0x002032 },
+ [0x002036] = { 0x002035, 0x002035 },
+ [0x002037] = { 0x002035, 0x002035, 0x002035 },
+ [0x00203c] = { 0x000021, 0x000021 },
+ [0x00203e] = { 0x000020, 0x000305 },
+ [0x002047] = { 0x00003f, 0x00003f },
+ [0x002048] = { 0x00003f, 0x000021 },
+ [0x002049] = { 0x000021, 0x00003f },
+ [0x002057] = { 0x002032, 0x002032, 0x002032, 0x002032 },
+ [0x00205f] = { 0x000020 },
+ [0x002070] = { 0x000030 },
+ [0x002071] = { 0x000069 },
+ [0x002074] = { 0x000034 },
+ [0x002075] = { 0x000035 },
+ [0x002076] = { 0x000036 },
+ [0x002077] = { 0x000037 },
+ [0x002078] = { 0x000038 },
+ [0x002079] = { 0x000039 },
+ [0x00207a] = { 0x00002b },
+ [0x00207b] = { 0x002212 },
+ [0x00207c] = { 0x00003d },
+ [0x00207d] = { 0x000028 },
+ [0x00207e] = { 0x000029 },
+ [0x00207f] = { 0x00006e },
+ [0x002080] = { 0x000030 },
+ [0x002081] = { 0x000031 },
+ [0x002082] = { 0x000032 },
+ [0x002083] = { 0x000033 },
+ [0x002084] = { 0x000034 },
+ [0x002085] = { 0x000035 },
+ [0x002086] = { 0x000036 },
+ [0x002087] = { 0x000037 },
+ [0x002088] = { 0x000038 },
+ [0x002089] = { 0x000039 },
+ [0x00208a] = { 0x00002b },
+ [0x00208b] = { 0x002212 },
+ [0x00208c] = { 0x00003d },
+ [0x00208d] = { 0x000028 },
+ [0x00208e] = { 0x000029 },
+ [0x002090] = { 0x000061 },
+ [0x002091] = { 0x000065 },
+ [0x002092] = { 0x00006f },
+ [0x002093] = { 0x000078 },
+ [0x002094] = { 0x000259 },
+ [0x002095] = { 0x000068 },
+ [0x002096] = { 0x00006b },
+ [0x002097] = { 0x00006c },
+ [0x002098] = { 0x00006d },
+ [0x002099] = { 0x00006e },
+ [0x00209a] = { 0x000070 },
+ [0x00209b] = { 0x000073 },
+ [0x00209c] = { 0x000074 },
+ [0x0020a8] = { 0x000052, 0x000073 },
+ [0x002100] = { 0x000061, 0x00002f, 0x000063 },
+ [0x002101] = { 0x000061, 0x00002f, 0x000073 },
+ [0x002102] = { 0x000043 },
+ [0x002103] = { 0x0000b0, 0x000043 },
+ [0x002105] = { 0x000063, 0x00002f, 0x00006f },
+ [0x002106] = { 0x000063, 0x00002f, 0x000075 },
+ [0x002107] = { 0x000190 },
+ [0x002109] = { 0x0000b0, 0x000046 },
+ [0x00210a] = { 0x000067 },
+ [0x00210b] = { 0x000048 },
+ [0x00210c] = { 0x000048 },
+ [0x00210d] = { 0x000048 },
+ [0x00210e] = { 0x000068 },
+ [0x00210f] = { 0x000127 },
+ [0x002110] = { 0x000049 },
+ [0x002111] = { 0x000049 },
+ [0x002112] = { 0x00004c },
+ [0x002113] = { 0x00006c },
+ [0x002115] = { 0x00004e },
+ [0x002116] = { 0x00004e, 0x00006f },
+ [0x002119] = { 0x000050 },
+ [0x00211a] = { 0x000051 },
+ [0x00211b] = { 0x000052 },
+ [0x00211c] = { 0x000052 },
+ [0x00211d] = { 0x000052 },
+ [0x002120] = { 0x000053, 0x00004d },
+ [0x002121] = { 0x000054, 0x000045, 0x00004c },
+ [0x002122] = { 0x000054, 0x00004d },
+ [0x002124] = { 0x00005a },
+ [0x002128] = { 0x00005a },
+ [0x00212c] = { 0x000042 },
+ [0x00212d] = { 0x000043 },
+ [0x00212f] = { 0x000065 },
+ [0x002130] = { 0x000045 },
+ [0x002131] = { 0x000046 },
+ [0x002133] = { 0x00004d },
+ [0x002134] = { 0x00006f },
+ [0x002135] = { 0x0005d0 },
+ [0x002136] = { 0x0005d1 },
+ [0x002137] = { 0x0005d2 },
+ [0x002138] = { 0x0005d3 },
+ [0x002139] = { 0x000069 },
+ [0x00213b] = { 0x000046, 0x000041, 0x000058 },
+ [0x00213c] = { 0x0003c0 },
+ [0x00213d] = { 0x0003b3 },
+ [0x00213e] = { 0x000393 },
+ [0x00213f] = { 0x0003a0 },
+ [0x002140] = { 0x002211 },
+ [0x002145] = { 0x000044 },
+ [0x002146] = { 0x000064 },
+ [0x002147] = { 0x000065 },
+ [0x002148] = { 0x000069 },
+ [0x002149] = { 0x00006a },
+ [0x002150] = { 0x000031, 0x002044, 0x000037 },
+ [0x002151] = { 0x000031, 0x002044, 0x000039 },
+ [0x002152] = { 0x000031, 0x002044, 0x000031, 0x000030 },
+ [0x002153] = { 0x000031, 0x002044, 0x000033 },
+ [0x002154] = { 0x000032, 0x002044, 0x000033 },
+ [0x002155] = { 0x000031, 0x002044, 0x000035 },
+ [0x002156] = { 0x000032, 0x002044, 0x000035 },
+ [0x002157] = { 0x000033, 0x002044, 0x000035 },
+ [0x002158] = { 0x000034, 0x002044, 0x000035 },
+ [0x002159] = { 0x000031, 0x002044, 0x000036 },
+ [0x00215a] = { 0x000035, 0x002044, 0x000036 },
+ [0x00215b] = { 0x000031, 0x002044, 0x000038 },
+ [0x00215c] = { 0x000033, 0x002044, 0x000038 },
+ [0x00215d] = { 0x000035, 0x002044, 0x000038 },
+ [0x00215e] = { 0x000037, 0x002044, 0x000038 },
+ [0x00215f] = { 0x000031, 0x002044 },
+ [0x002160] = { 0x000049 },
+ [0x002161] = { 0x000049, 0x000049 },
+ [0x002162] = { 0x000049, 0x000049, 0x000049 },
+ [0x002163] = { 0x000049, 0x000056 },
+ [0x002164] = { 0x000056 },
+ [0x002165] = { 0x000056, 0x000049 },
+ [0x002166] = { 0x000056, 0x000049, 0x000049 },
+ [0x002167] = { 0x000056, 0x000049, 0x000049, 0x000049 },
+ [0x002168] = { 0x000049, 0x000058 },
+ [0x002169] = { 0x000058 },
+ [0x00216a] = { 0x000058, 0x000049 },
+ [0x00216b] = { 0x000058, 0x000049, 0x000049 },
+ [0x00216c] = { 0x00004c },
+ [0x00216d] = { 0x000043 },
+ [0x00216e] = { 0x000044 },
+ [0x00216f] = { 0x00004d },
+ [0x002170] = { 0x000069 },
+ [0x002171] = { 0x000069, 0x000069 },
+ [0x002172] = { 0x000069, 0x000069, 0x000069 },
+ [0x002173] = { 0x000069, 0x000076 },
+ [0x002174] = { 0x000076 },
+ [0x002175] = { 0x000076, 0x000069 },
+ [0x002176] = { 0x000076, 0x000069, 0x000069 },
+ [0x002177] = { 0x000076, 0x000069, 0x000069, 0x000069 },
+ [0x002178] = { 0x000069, 0x000078 },
+ [0x002179] = { 0x000078 },
+ [0x00217a] = { 0x000078, 0x000069 },
+ [0x00217b] = { 0x000078, 0x000069, 0x000069 },
+ [0x00217c] = { 0x00006c },
+ [0x00217d] = { 0x000063 },
+ [0x00217e] = { 0x000064 },
+ [0x00217f] = { 0x00006d },
+ [0x002189] = { 0x000030, 0x002044, 0x000033 },
+ [0x00222c] = { 0x00222b, 0x00222b },
+ [0x00222d] = { 0x00222b, 0x00222b, 0x00222b },
+ [0x00222f] = { 0x00222e, 0x00222e },
+ [0x002230] = { 0x00222e, 0x00222e, 0x00222e },
+ [0x002460] = { 0x000031 },
+ [0x002461] = { 0x000032 },
+ [0x002462] = { 0x000033 },
+ [0x002463] = { 0x000034 },
+ [0x002464] = { 0x000035 },
+ [0x002465] = { 0x000036 },
+ [0x002466] = { 0x000037 },
+ [0x002467] = { 0x000038 },
+ [0x002468] = { 0x000039 },
+ [0x002469] = { 0x000031, 0x000030 },
+ [0x00246a] = { 0x000031, 0x000031 },
+ [0x00246b] = { 0x000031, 0x000032 },
+ [0x00246c] = { 0x000031, 0x000033 },
+ [0x00246d] = { 0x000031, 0x000034 },
+ [0x00246e] = { 0x000031, 0x000035 },
+ [0x00246f] = { 0x000031, 0x000036 },
+ [0x002470] = { 0x000031, 0x000037 },
+ [0x002471] = { 0x000031, 0x000038 },
+ [0x002472] = { 0x000031, 0x000039 },
+ [0x002473] = { 0x000032, 0x000030 },
+ [0x002474] = { 0x000028, 0x000031, 0x000029 },
+ [0x002475] = { 0x000028, 0x000032, 0x000029 },
+ [0x002476] = { 0x000028, 0x000033, 0x000029 },
+ [0x002477] = { 0x000028, 0x000034, 0x000029 },
+ [0x002478] = { 0x000028, 0x000035, 0x000029 },
+ [0x002479] = { 0x000028, 0x000036, 0x000029 },
+ [0x00247a] = { 0x000028, 0x000037, 0x000029 },
+ [0x00247b] = { 0x000028, 0x000038, 0x000029 },
+ [0x00247c] = { 0x000028, 0x000039, 0x000029 },
+ [0x00247d] = { 0x000028, 0x000031, 0x000030, 0x000029 },
+ [0x00247e] = { 0x000028, 0x000031, 0x000031, 0x000029 },
+ [0x00247f] = { 0x000028, 0x000031, 0x000032, 0x000029 },
+ [0x002480] = { 0x000028, 0x000031, 0x000033, 0x000029 },
+ [0x002481] = { 0x000028, 0x000031, 0x000034, 0x000029 },
+ [0x002482] = { 0x000028, 0x000031, 0x000035, 0x000029 },
+ [0x002483] = { 0x000028, 0x000031, 0x000036, 0x000029 },
+ [0x002484] = { 0x000028, 0x000031, 0x000037, 0x000029 },
+ [0x002485] = { 0x000028, 0x000031, 0x000038, 0x000029 },
+ [0x002486] = { 0x000028, 0x000031, 0x000039, 0x000029 },
+ [0x002487] = { 0x000028, 0x000032, 0x000030, 0x000029 },
+ [0x002488] = { 0x000031, 0x00002e },
+ [0x002489] = { 0x000032, 0x00002e },
+ [0x00248a] = { 0x000033, 0x00002e },
+ [0x00248b] = { 0x000034, 0x00002e },
+ [0x00248c] = { 0x000035, 0x00002e },
+ [0x00248d] = { 0x000036, 0x00002e },
+ [0x00248e] = { 0x000037, 0x00002e },
+ [0x00248f] = { 0x000038, 0x00002e },
+ [0x002490] = { 0x000039, 0x00002e },
+ [0x002491] = { 0x000031, 0x000030, 0x00002e },
+ [0x002492] = { 0x000031, 0x000031, 0x00002e },
+ [0x002493] = { 0x000031, 0x000032, 0x00002e },
+ [0x002494] = { 0x000031, 0x000033, 0x00002e },
+ [0x002495] = { 0x000031, 0x000034, 0x00002e },
+ [0x002496] = { 0x000031, 0x000035, 0x00002e },
+ [0x002497] = { 0x000031, 0x000036, 0x00002e },
+ [0x002498] = { 0x000031, 0x000037, 0x00002e },
+ [0x002499] = { 0x000031, 0x000038, 0x00002e },
+ [0x00249a] = { 0x000031, 0x000039, 0x00002e },
+ [0x00249b] = { 0x000032, 0x000030, 0x00002e },
+ [0x00249c] = { 0x000028, 0x000061, 0x000029 },
+ [0x00249d] = { 0x000028, 0x000062, 0x000029 },
+ [0x00249e] = { 0x000028, 0x000063, 0x000029 },
+ [0x00249f] = { 0x000028, 0x000064, 0x000029 },
+ [0x0024a0] = { 0x000028, 0x000065, 0x000029 },
+ [0x0024a1] = { 0x000028, 0x000066, 0x000029 },
+ [0x0024a2] = { 0x000028, 0x000067, 0x000029 },
+ [0x0024a3] = { 0x000028, 0x000068, 0x000029 },
+ [0x0024a4] = { 0x000028, 0x000069, 0x000029 },
+ [0x0024a5] = { 0x000028, 0x00006a, 0x000029 },
+ [0x0024a6] = { 0x000028, 0x00006b, 0x000029 },
+ [0x0024a7] = { 0x000028, 0x00006c, 0x000029 },
+ [0x0024a8] = { 0x000028, 0x00006d, 0x000029 },
+ [0x0024a9] = { 0x000028, 0x00006e, 0x000029 },
+ [0x0024aa] = { 0x000028, 0x00006f, 0x000029 },
+ [0x0024ab] = { 0x000028, 0x000070, 0x000029 },
+ [0x0024ac] = { 0x000028, 0x000071, 0x000029 },
+ [0x0024ad] = { 0x000028, 0x000072, 0x000029 },
+ [0x0024ae] = { 0x000028, 0x000073, 0x000029 },
+ [0x0024af] = { 0x000028, 0x000074, 0x000029 },
+ [0x0024b0] = { 0x000028, 0x000075, 0x000029 },
+ [0x0024b1] = { 0x000028, 0x000076, 0x000029 },
+ [0x0024b2] = { 0x000028, 0x000077, 0x000029 },
+ [0x0024b3] = { 0x000028, 0x000078, 0x000029 },
+ [0x0024b4] = { 0x000028, 0x000079, 0x000029 },
+ [0x0024b5] = { 0x000028, 0x00007a, 0x000029 },
+ [0x0024b6] = { 0x000041 },
+ [0x0024b7] = { 0x000042 },
+ [0x0024b8] = { 0x000043 },
+ [0x0024b9] = { 0x000044 },
+ [0x0024ba] = { 0x000045 },
+ [0x0024bb] = { 0x000046 },
+ [0x0024bc] = { 0x000047 },
+ [0x0024bd] = { 0x000048 },
+ [0x0024be] = { 0x000049 },
+ [0x0024bf] = { 0x00004a },
+ [0x0024c0] = { 0x00004b },
+ [0x0024c1] = { 0x00004c },
+ [0x0024c2] = { 0x00004d },
+ [0x0024c3] = { 0x00004e },
+ [0x0024c4] = { 0x00004f },
+ [0x0024c5] = { 0x000050 },
+ [0x0024c6] = { 0x000051 },
+ [0x0024c7] = { 0x000052 },
+ [0x0024c8] = { 0x000053 },
+ [0x0024c9] = { 0x000054 },
+ [0x0024ca] = { 0x000055 },
+ [0x0024cb] = { 0x000056 },
+ [0x0024cc] = { 0x000057 },
+ [0x0024cd] = { 0x000058 },
+ [0x0024ce] = { 0x000059 },
+ [0x0024cf] = { 0x00005a },
+ [0x0024d0] = { 0x000061 },
+ [0x0024d1] = { 0x000062 },
+ [0x0024d2] = { 0x000063 },
+ [0x0024d3] = { 0x000064 },
+ [0x0024d4] = { 0x000065 },
+ [0x0024d5] = { 0x000066 },
+ [0x0024d6] = { 0x000067 },
+ [0x0024d7] = { 0x000068 },
+ [0x0024d8] = { 0x000069 },
+ [0x0024d9] = { 0x00006a },
+ [0x0024da] = { 0x00006b },
+ [0x0024db] = { 0x00006c },
+ [0x0024dc] = { 0x00006d },
+ [0x0024dd] = { 0x00006e },
+ [0x0024de] = { 0x00006f },
+ [0x0024df] = { 0x000070 },
+ [0x0024e0] = { 0x000071 },
+ [0x0024e1] = { 0x000072 },
+ [0x0024e2] = { 0x000073 },
+ [0x0024e3] = { 0x000074 },
+ [0x0024e4] = { 0x000075 },
+ [0x0024e5] = { 0x000076 },
+ [0x0024e6] = { 0x000077 },
+ [0x0024e7] = { 0x000078 },
+ [0x0024e8] = { 0x000079 },
+ [0x0024e9] = { 0x00007a },
+ [0x0024ea] = { 0x000030 },
+ [0x002a0c] = { 0x00222b, 0x00222b, 0x00222b, 0x00222b },
+ [0x002a74] = { 0x00003a, 0x00003a, 0x00003d },
+ [0x002a75] = { 0x00003d, 0x00003d },
+ [0x002a76] = { 0x00003d, 0x00003d, 0x00003d },
+ [0x002c7c] = { 0x00006a },
+ [0x002c7d] = { 0x000056 },
+ [0x002d6f] = { 0x002d61 },
+ [0x002e9f] = { 0x006bcd },
+ [0x002ef3] = { 0x009f9f },
+ [0x002f00] = { 0x004e00 },
+ [0x002f01] = { 0x004e28 },
+ [0x002f02] = { 0x004e36 },
+ [0x002f03] = { 0x004e3f },
+ [0x002f04] = { 0x004e59 },
+ [0x002f05] = { 0x004e85 },
+ [0x002f06] = { 0x004e8c },
+ [0x002f07] = { 0x004ea0 },
+ [0x002f08] = { 0x004eba },
+ [0x002f09] = { 0x00513f },
+ [0x002f0a] = { 0x005165 },
+ [0x002f0b] = { 0x00516b },
+ [0x002f0c] = { 0x005182 },
+ [0x002f0d] = { 0x005196 },
+ [0x002f0e] = { 0x0051ab },
+ [0x002f0f] = { 0x0051e0 },
+ [0x002f10] = { 0x0051f5 },
+ [0x002f11] = { 0x005200 },
+ [0x002f12] = { 0x00529b },
+ [0x002f13] = { 0x0052f9 },
+ [0x002f14] = { 0x005315 },
+ [0x002f15] = { 0x00531a },
+ [0x002f16] = { 0x005338 },
+ [0x002f17] = { 0x005341 },
+ [0x002f18] = { 0x00535c },
+ [0x002f19] = { 0x005369 },
+ [0x002f1a] = { 0x005382 },
+ [0x002f1b] = { 0x0053b6 },
+ [0x002f1c] = { 0x0053c8 },
+ [0x002f1d] = { 0x0053e3 },
+ [0x002f1e] = { 0x0056d7 },
+ [0x002f1f] = { 0x00571f },
+ [0x002f20] = { 0x0058eb },
+ [0x002f21] = { 0x005902 },
+ [0x002f22] = { 0x00590a },
+ [0x002f23] = { 0x005915 },
+ [0x002f24] = { 0x005927 },
+ [0x002f25] = { 0x005973 },
+ [0x002f26] = { 0x005b50 },
+ [0x002f27] = { 0x005b80 },
+ [0x002f28] = { 0x005bf8 },
+ [0x002f29] = { 0x005c0f },
+ [0x002f2a] = { 0x005c22 },
+ [0x002f2b] = { 0x005c38 },
+ [0x002f2c] = { 0x005c6e },
+ [0x002f2d] = { 0x005c71 },
+ [0x002f2e] = { 0x005ddb },
+ [0x002f2f] = { 0x005de5 },
+ [0x002f30] = { 0x005df1 },
+ [0x002f31] = { 0x005dfe },
+ [0x002f32] = { 0x005e72 },
+ [0x002f33] = { 0x005e7a },
+ [0x002f34] = { 0x005e7f },
+ [0x002f35] = { 0x005ef4 },
+ [0x002f36] = { 0x005efe },
+ [0x002f37] = { 0x005f0b },
+ [0x002f38] = { 0x005f13 },
+ [0x002f39] = { 0x005f50 },
+ [0x002f3a] = { 0x005f61 },
+ [0x002f3b] = { 0x005f73 },
+ [0x002f3c] = { 0x005fc3 },
+ [0x002f3d] = { 0x006208 },
+ [0x002f3e] = { 0x006236 },
+ [0x002f3f] = { 0x00624b },
+ [0x002f40] = { 0x00652f },
+ [0x002f41] = { 0x006534 },
+ [0x002f42] = { 0x006587 },
+ [0x002f43] = { 0x006597 },
+ [0x002f44] = { 0x0065a4 },
+ [0x002f45] = { 0x0065b9 },
+ [0x002f46] = { 0x0065e0 },
+ [0x002f47] = { 0x0065e5 },
+ [0x002f48] = { 0x0066f0 },
+ [0x002f49] = { 0x006708 },
+ [0x002f4a] = { 0x006728 },
+ [0x002f4b] = { 0x006b20 },
+ [0x002f4c] = { 0x006b62 },
+ [0x002f4d] = { 0x006b79 },
+ [0x002f4e] = { 0x006bb3 },
+ [0x002f4f] = { 0x006bcb },
+ [0x002f50] = { 0x006bd4 },
+ [0x002f51] = { 0x006bdb },
+ [0x002f52] = { 0x006c0f },
+ [0x002f53] = { 0x006c14 },
+ [0x002f54] = { 0x006c34 },
+ [0x002f55] = { 0x00706b },
+ [0x002f56] = { 0x00722a },
+ [0x002f57] = { 0x007236 },
+ [0x002f58] = { 0x00723b },
+ [0x002f59] = { 0x00723f },
+ [0x002f5a] = { 0x007247 },
+ [0x002f5b] = { 0x007259 },
+ [0x002f5c] = { 0x00725b },
+ [0x002f5d] = { 0x0072ac },
+ [0x002f5e] = { 0x007384 },
+ [0x002f5f] = { 0x007389 },
+ [0x002f60] = { 0x0074dc },
+ [0x002f61] = { 0x0074e6 },
+ [0x002f62] = { 0x007518 },
+ [0x002f63] = { 0x00751f },
+ [0x002f64] = { 0x007528 },
+ [0x002f65] = { 0x007530 },
+ [0x002f66] = { 0x00758b },
+ [0x002f67] = { 0x007592 },
+ [0x002f68] = { 0x007676 },
+ [0x002f69] = { 0x00767d },
+ [0x002f6a] = { 0x0076ae },
+ [0x002f6b] = { 0x0076bf },
+ [0x002f6c] = { 0x0076ee },
+ [0x002f6d] = { 0x0077db },
+ [0x002f6e] = { 0x0077e2 },
+ [0x002f6f] = { 0x0077f3 },
+ [0x002f70] = { 0x00793a },
+ [0x002f71] = { 0x0079b8 },
+ [0x002f72] = { 0x0079be },
+ [0x002f73] = { 0x007a74 },
+ [0x002f74] = { 0x007acb },
+ [0x002f75] = { 0x007af9 },
+ [0x002f76] = { 0x007c73 },
+ [0x002f77] = { 0x007cf8 },
+ [0x002f78] = { 0x007f36 },
+ [0x002f79] = { 0x007f51 },
+ [0x002f7a] = { 0x007f8a },
+ [0x002f7b] = { 0x007fbd },
+ [0x002f7c] = { 0x008001 },
+ [0x002f7d] = { 0x00800c },
+ [0x002f7e] = { 0x008012 },
+ [0x002f7f] = { 0x008033 },
+ [0x002f80] = { 0x00807f },
+ [0x002f81] = { 0x008089 },
+ [0x002f82] = { 0x0081e3 },
+ [0x002f83] = { 0x0081ea },
+ [0x002f84] = { 0x0081f3 },
+ [0x002f85] = { 0x0081fc },
+ [0x002f86] = { 0x00820c },
+ [0x002f87] = { 0x00821b },
+ [0x002f88] = { 0x00821f },
+ [0x002f89] = { 0x00826e },
+ [0x002f8a] = { 0x008272 },
+ [0x002f8b] = { 0x008278 },
+ [0x002f8c] = { 0x00864d },
+ [0x002f8d] = { 0x00866b },
+ [0x002f8e] = { 0x008840 },
+ [0x002f8f] = { 0x00884c },
+ [0x002f90] = { 0x008863 },
+ [0x002f91] = { 0x00897e },
+ [0x002f92] = { 0x00898b },
+ [0x002f93] = { 0x0089d2 },
+ [0x002f94] = { 0x008a00 },
+ [0x002f95] = { 0x008c37 },
+ [0x002f96] = { 0x008c46 },
+ [0x002f97] = { 0x008c55 },
+ [0x002f98] = { 0x008c78 },
+ [0x002f99] = { 0x008c9d },
+ [0x002f9a] = { 0x008d64 },
+ [0x002f9b] = { 0x008d70 },
+ [0x002f9c] = { 0x008db3 },
+ [0x002f9d] = { 0x008eab },
+ [0x002f9e] = { 0x008eca },
+ [0x002f9f] = { 0x008f9b },
+ [0x002fa0] = { 0x008fb0 },
+ [0x002fa1] = { 0x008fb5 },
+ [0x002fa2] = { 0x009091 },
+ [0x002fa3] = { 0x009149 },
+ [0x002fa4] = { 0x0091c6 },
+ [0x002fa5] = { 0x0091cc },
+ [0x002fa6] = { 0x0091d1 },
+ [0x002fa7] = { 0x009577 },
+ [0x002fa8] = { 0x009580 },
+ [0x002fa9] = { 0x00961c },
+ [0x002faa] = { 0x0096b6 },
+ [0x002fab] = { 0x0096b9 },
+ [0x002fac] = { 0x0096e8 },
+ [0x002fad] = { 0x009751 },
+ [0x002fae] = { 0x00975e },
+ [0x002faf] = { 0x009762 },
+ [0x002fb0] = { 0x009769 },
+ [0x002fb1] = { 0x0097cb },
+ [0x002fb2] = { 0x0097ed },
+ [0x002fb3] = { 0x0097f3 },
+ [0x002fb4] = { 0x009801 },
+ [0x002fb5] = { 0x0098a8 },
+ [0x002fb6] = { 0x0098db },
+ [0x002fb7] = { 0x0098df },
+ [0x002fb8] = { 0x009996 },
+ [0x002fb9] = { 0x009999 },
+ [0x002fba] = { 0x0099ac },
+ [0x002fbb] = { 0x009aa8 },
+ [0x002fbc] = { 0x009ad8 },
+ [0x002fbd] = { 0x009adf },
+ [0x002fbe] = { 0x009b25 },
+ [0x002fbf] = { 0x009b2f },
+ [0x002fc0] = { 0x009b32 },
+ [0x002fc1] = { 0x009b3c },
+ [0x002fc2] = { 0x009b5a },
+ [0x002fc3] = { 0x009ce5 },
+ [0x002fc4] = { 0x009e75 },
+ [0x002fc5] = { 0x009e7f },
+ [0x002fc6] = { 0x009ea5 },
+ [0x002fc7] = { 0x009ebb },
+ [0x002fc8] = { 0x009ec3 },
+ [0x002fc9] = { 0x009ecd },
+ [0x002fca] = { 0x009ed1 },
+ [0x002fcb] = { 0x009ef9 },
+ [0x002fcc] = { 0x009efd },
+ [0x002fcd] = { 0x009f0e },
+ [0x002fce] = { 0x009f13 },
+ [0x002fcf] = { 0x009f20 },
+ [0x002fd0] = { 0x009f3b },
+ [0x002fd1] = { 0x009f4a },
+ [0x002fd2] = { 0x009f52 },
+ [0x002fd3] = { 0x009f8d },
+ [0x002fd4] = { 0x009f9c },
+ [0x002fd5] = { 0x009fa0 },
+ [0x003000] = { 0x000020 },
+ [0x003036] = { 0x003012 },
+ [0x003038] = { 0x005341 },
+ [0x003039] = { 0x005344 },
+ [0x00303a] = { 0x005345 },
+ [0x00309b] = { 0x000020, 0x003099 },
+ [0x00309c] = { 0x000020, 0x00309a },
+ [0x00309f] = { 0x003088, 0x00308a },
+ [0x0030ff] = { 0x0030b3, 0x0030c8 },
+ [0x003131] = { 0x001100 },
+ [0x003132] = { 0x001101 },
+ [0x003133] = { 0x0011aa },
+ [0x003134] = { 0x001102 },
+ [0x003135] = { 0x0011ac },
+ [0x003136] = { 0x0011ad },
+ [0x003137] = { 0x001103 },
+ [0x003138] = { 0x001104 },
+ [0x003139] = { 0x001105 },
+ [0x00313a] = { 0x0011b0 },
+ [0x00313b] = { 0x0011b1 },
+ [0x00313c] = { 0x0011b2 },
+ [0x00313d] = { 0x0011b3 },
+ [0x00313e] = { 0x0011b4 },
+ [0x00313f] = { 0x0011b5 },
+ [0x003140] = { 0x00111a },
+ [0x003141] = { 0x001106 },
+ [0x003142] = { 0x001107 },
+ [0x003143] = { 0x001108 },
+ [0x003144] = { 0x001121 },
+ [0x003145] = { 0x001109 },
+ [0x003146] = { 0x00110a },
+ [0x003147] = { 0x00110b },
+ [0x003148] = { 0x00110c },
+ [0x003149] = { 0x00110d },
+ [0x00314a] = { 0x00110e },
+ [0x00314b] = { 0x00110f },
+ [0x00314c] = { 0x001110 },
+ [0x00314d] = { 0x001111 },
+ [0x00314e] = { 0x001112 },
+ [0x00314f] = { 0x001161 },
+ [0x003150] = { 0x001162 },
+ [0x003151] = { 0x001163 },
+ [0x003152] = { 0x001164 },
+ [0x003153] = { 0x001165 },
+ [0x003154] = { 0x001166 },
+ [0x003155] = { 0x001167 },
+ [0x003156] = { 0x001168 },
+ [0x003157] = { 0x001169 },
+ [0x003158] = { 0x00116a },
+ [0x003159] = { 0x00116b },
+ [0x00315a] = { 0x00116c },
+ [0x00315b] = { 0x00116d },
+ [0x00315c] = { 0x00116e },
+ [0x00315d] = { 0x00116f },
+ [0x00315e] = { 0x001170 },
+ [0x00315f] = { 0x001171 },
+ [0x003160] = { 0x001172 },
+ [0x003161] = { 0x001173 },
+ [0x003162] = { 0x001174 },
+ [0x003163] = { 0x001175 },
+ [0x003164] = { 0x001160 },
+ [0x003165] = { 0x001114 },
+ [0x003166] = { 0x001115 },
+ [0x003167] = { 0x0011c7 },
+ [0x003168] = { 0x0011c8 },
+ [0x003169] = { 0x0011cc },
+ [0x00316a] = { 0x0011ce },
+ [0x00316b] = { 0x0011d3 },
+ [0x00316c] = { 0x0011d7 },
+ [0x00316d] = { 0x0011d9 },
+ [0x00316e] = { 0x00111c },
+ [0x00316f] = { 0x0011dd },
+ [0x003170] = { 0x0011df },
+ [0x003171] = { 0x00111d },
+ [0x003172] = { 0x00111e },
+ [0x003173] = { 0x001120 },
+ [0x003174] = { 0x001122 },
+ [0x003175] = { 0x001123 },
+ [0x003176] = { 0x001127 },
+ [0x003177] = { 0x001129 },
+ [0x003178] = { 0x00112b },
+ [0x003179] = { 0x00112c },
+ [0x00317a] = { 0x00112d },
+ [0x00317b] = { 0x00112e },
+ [0x00317c] = { 0x00112f },
+ [0x00317d] = { 0x001132 },
+ [0x00317e] = { 0x001136 },
+ [0x00317f] = { 0x001140 },
+ [0x003180] = { 0x001147 },
+ [0x003181] = { 0x00114c },
+ [0x003182] = { 0x0011f1 },
+ [0x003183] = { 0x0011f2 },
+ [0x003184] = { 0x001157 },
+ [0x003185] = { 0x001158 },
+ [0x003186] = { 0x001159 },
+ [0x003187] = { 0x001184 },
+ [0x003188] = { 0x001185 },
+ [0x003189] = { 0x001188 },
+ [0x00318a] = { 0x001191 },
+ [0x00318b] = { 0x001192 },
+ [0x00318c] = { 0x001194 },
+ [0x00318d] = { 0x00119e },
+ [0x00318e] = { 0x0011a1 },
+ [0x003192] = { 0x004e00 },
+ [0x003193] = { 0x004e8c },
+ [0x003194] = { 0x004e09 },
+ [0x003195] = { 0x0056db },
+ [0x003196] = { 0x004e0a },
+ [0x003197] = { 0x004e2d },
+ [0x003198] = { 0x004e0b },
+ [0x003199] = { 0x007532 },
+ [0x00319a] = { 0x004e59 },
+ [0x00319b] = { 0x004e19 },
+ [0x00319c] = { 0x004e01 },
+ [0x00319d] = { 0x005929 },
+ [0x00319e] = { 0x005730 },
+ [0x00319f] = { 0x004eba },
+ [0x003200] = { 0x000028, 0x001100, 0x000029 },
+ [0x003201] = { 0x000028, 0x001102, 0x000029 },
+ [0x003202] = { 0x000028, 0x001103, 0x000029 },
+ [0x003203] = { 0x000028, 0x001105, 0x000029 },
+ [0x003204] = { 0x000028, 0x001106, 0x000029 },
+ [0x003205] = { 0x000028, 0x001107, 0x000029 },
+ [0x003206] = { 0x000028, 0x001109, 0x000029 },
+ [0x003207] = { 0x000028, 0x00110b, 0x000029 },
+ [0x003208] = { 0x000028, 0x00110c, 0x000029 },
+ [0x003209] = { 0x000028, 0x00110e, 0x000029 },
+ [0x00320a] = { 0x000028, 0x00110f, 0x000029 },
+ [0x00320b] = { 0x000028, 0x001110, 0x000029 },
+ [0x00320c] = { 0x000028, 0x001111, 0x000029 },
+ [0x00320d] = { 0x000028, 0x001112, 0x000029 },
+ [0x00320e] = { 0x000028, 0x001100, 0x001161, 0x000029 },
+ [0x00320f] = { 0x000028, 0x001102, 0x001161, 0x000029 },
+ [0x003210] = { 0x000028, 0x001103, 0x001161, 0x000029 },
+ [0x003211] = { 0x000028, 0x001105, 0x001161, 0x000029 },
+ [0x003212] = { 0x000028, 0x001106, 0x001161, 0x000029 },
+ [0x003213] = { 0x000028, 0x001107, 0x001161, 0x000029 },
+ [0x003214] = { 0x000028, 0x001109, 0x001161, 0x000029 },
+ [0x003215] = { 0x000028, 0x00110b, 0x001161, 0x000029 },
+ [0x003216] = { 0x000028, 0x00110c, 0x001161, 0x000029 },
+ [0x003217] = { 0x000028, 0x00110e, 0x001161, 0x000029 },
+ [0x003218] = { 0x000028, 0x00110f, 0x001161, 0x000029 },
+ [0x003219] = { 0x000028, 0x001110, 0x001161, 0x000029 },
+ [0x00321a] = { 0x000028, 0x001111, 0x001161, 0x000029 },
+ [0x00321b] = { 0x000028, 0x001112, 0x001161, 0x000029 },
+ [0x00321c] = { 0x000028, 0x00110c, 0x00116e, 0x000029 },
+ [0x00321d] = { 0x000028, 0x00110b, 0x001169, 0x00110c, 0x001165, 0x0011ab, 0x000029 },
+ [0x00321e] = { 0x000028, 0x00110b, 0x001169, 0x001112, 0x00116e, 0x000029 },
+ [0x003220] = { 0x000028, 0x004e00, 0x000029 },
+ [0x003221] = { 0x000028, 0x004e8c, 0x000029 },
+ [0x003222] = { 0x000028, 0x004e09, 0x000029 },
+ [0x003223] = { 0x000028, 0x0056db, 0x000029 },
+ [0x003224] = { 0x000028, 0x004e94, 0x000029 },
+ [0x003225] = { 0x000028, 0x00516d, 0x000029 },
+ [0x003226] = { 0x000028, 0x004e03, 0x000029 },
+ [0x003227] = { 0x000028, 0x00516b, 0x000029 },
+ [0x003228] = { 0x000028, 0x004e5d, 0x000029 },
+ [0x003229] = { 0x000028, 0x005341, 0x000029 },
+ [0x00322a] = { 0x000028, 0x006708, 0x000029 },
+ [0x00322b] = { 0x000028, 0x00706b, 0x000029 },
+ [0x00322c] = { 0x000028, 0x006c34, 0x000029 },
+ [0x00322d] = { 0x000028, 0x006728, 0x000029 },
+ [0x00322e] = { 0x000028, 0x0091d1, 0x000029 },
+ [0x00322f] = { 0x000028, 0x00571f, 0x000029 },
+ [0x003230] = { 0x000028, 0x0065e5, 0x000029 },
+ [0x003231] = { 0x000028, 0x00682a, 0x000029 },
+ [0x003232] = { 0x000028, 0x006709, 0x000029 },
+ [0x003233] = { 0x000028, 0x00793e, 0x000029 },
+ [0x003234] = { 0x000028, 0x00540d, 0x000029 },
+ [0x003235] = { 0x000028, 0x007279, 0x000029 },
+ [0x003236] = { 0x000028, 0x008ca1, 0x000029 },
+ [0x003237] = { 0x000028, 0x00795d, 0x000029 },
+ [0x003238] = { 0x000028, 0x0052b4, 0x000029 },
+ [0x003239] = { 0x000028, 0x004ee3, 0x000029 },
+ [0x00323a] = { 0x000028, 0x00547c, 0x000029 },
+ [0x00323b] = { 0x000028, 0x005b66, 0x000029 },
+ [0x00323c] = { 0x000028, 0x0076e3, 0x000029 },
+ [0x00323d] = { 0x000028, 0x004f01, 0x000029 },
+ [0x00323e] = { 0x000028, 0x008cc7, 0x000029 },
+ [0x00323f] = { 0x000028, 0x005354, 0x000029 },
+ [0x003240] = { 0x000028, 0x00796d, 0x000029 },
+ [0x003241] = { 0x000028, 0x004f11, 0x000029 },
+ [0x003242] = { 0x000028, 0x0081ea, 0x000029 },
+ [0x003243] = { 0x000028, 0x0081f3, 0x000029 },
+ [0x003244] = { 0x00554f },
+ [0x003245] = { 0x005e7c },
+ [0x003246] = { 0x006587 },
+ [0x003247] = { 0x007b8f },
+ [0x003250] = { 0x000050, 0x000054, 0x000045 },
+ [0x003251] = { 0x000032, 0x000031 },
+ [0x003252] = { 0x000032, 0x000032 },
+ [0x003253] = { 0x000032, 0x000033 },
+ [0x003254] = { 0x000032, 0x000034 },
+ [0x003255] = { 0x000032, 0x000035 },
+ [0x003256] = { 0x000032, 0x000036 },
+ [0x003257] = { 0x000032, 0x000037 },
+ [0x003258] = { 0x000032, 0x000038 },
+ [0x003259] = { 0x000032, 0x000039 },
+ [0x00325a] = { 0x000033, 0x000030 },
+ [0x00325b] = { 0x000033, 0x000031 },
+ [0x00325c] = { 0x000033, 0x000032 },
+ [0x00325d] = { 0x000033, 0x000033 },
+ [0x00325e] = { 0x000033, 0x000034 },
+ [0x00325f] = { 0x000033, 0x000035 },
+ [0x003260] = { 0x001100 },
+ [0x003261] = { 0x001102 },
+ [0x003262] = { 0x001103 },
+ [0x003263] = { 0x001105 },
+ [0x003264] = { 0x001106 },
+ [0x003265] = { 0x001107 },
+ [0x003266] = { 0x001109 },
+ [0x003267] = { 0x00110b },
+ [0x003268] = { 0x00110c },
+ [0x003269] = { 0x00110e },
+ [0x00326a] = { 0x00110f },
+ [0x00326b] = { 0x001110 },
+ [0x00326c] = { 0x001111 },
+ [0x00326d] = { 0x001112 },
+ [0x00326e] = { 0x001100, 0x001161 },
+ [0x00326f] = { 0x001102, 0x001161 },
+ [0x003270] = { 0x001103, 0x001161 },
+ [0x003271] = { 0x001105, 0x001161 },
+ [0x003272] = { 0x001106, 0x001161 },
+ [0x003273] = { 0x001107, 0x001161 },
+ [0x003274] = { 0x001109, 0x001161 },
+ [0x003275] = { 0x00110b, 0x001161 },
+ [0x003276] = { 0x00110c, 0x001161 },
+ [0x003277] = { 0x00110e, 0x001161 },
+ [0x003278] = { 0x00110f, 0x001161 },
+ [0x003279] = { 0x001110, 0x001161 },
+ [0x00327a] = { 0x001111, 0x001161 },
+ [0x00327b] = { 0x001112, 0x001161 },
+ [0x00327c] = { 0x00110e, 0x001161, 0x0011b7, 0x001100, 0x001169 },
+ [0x00327d] = { 0x00110c, 0x00116e, 0x00110b, 0x001174 },
+ [0x00327e] = { 0x00110b, 0x00116e },
+ [0x003280] = { 0x004e00 },
+ [0x003281] = { 0x004e8c },
+ [0x003282] = { 0x004e09 },
+ [0x003283] = { 0x0056db },
+ [0x003284] = { 0x004e94 },
+ [0x003285] = { 0x00516d },
+ [0x003286] = { 0x004e03 },
+ [0x003287] = { 0x00516b },
+ [0x003288] = { 0x004e5d },
+ [0x003289] = { 0x005341 },
+ [0x00328a] = { 0x006708 },
+ [0x00328b] = { 0x00706b },
+ [0x00328c] = { 0x006c34 },
+ [0x00328d] = { 0x006728 },
+ [0x00328e] = { 0x0091d1 },
+ [0x00328f] = { 0x00571f },
+ [0x003290] = { 0x0065e5 },
+ [0x003291] = { 0x00682a },
+ [0x003292] = { 0x006709 },
+ [0x003293] = { 0x00793e },
+ [0x003294] = { 0x00540d },
+ [0x003295] = { 0x007279 },
+ [0x003296] = { 0x008ca1 },
+ [0x003297] = { 0x00795d },
+ [0x003298] = { 0x0052b4 },
+ [0x003299] = { 0x0079d8 },
+ [0x00329a] = { 0x007537 },
+ [0x00329b] = { 0x005973 },
+ [0x00329c] = { 0x009069 },
+ [0x00329d] = { 0x00512a },
+ [0x00329e] = { 0x005370 },
+ [0x00329f] = { 0x006ce8 },
+ [0x0032a0] = { 0x009805 },
+ [0x0032a1] = { 0x004f11 },
+ [0x0032a2] = { 0x005199 },
+ [0x0032a3] = { 0x006b63 },
+ [0x0032a4] = { 0x004e0a },
+ [0x0032a5] = { 0x004e2d },
+ [0x0032a6] = { 0x004e0b },
+ [0x0032a7] = { 0x005de6 },
+ [0x0032a8] = { 0x0053f3 },
+ [0x0032a9] = { 0x00533b },
+ [0x0032aa] = { 0x005b97 },
+ [0x0032ab] = { 0x005b66 },
+ [0x0032ac] = { 0x0076e3 },
+ [0x0032ad] = { 0x004f01 },
+ [0x0032ae] = { 0x008cc7 },
+ [0x0032af] = { 0x005354 },
+ [0x0032b0] = { 0x00591c },
+ [0x0032b1] = { 0x000033, 0x000036 },
+ [0x0032b2] = { 0x000033, 0x000037 },
+ [0x0032b3] = { 0x000033, 0x000038 },
+ [0x0032b4] = { 0x000033, 0x000039 },
+ [0x0032b5] = { 0x000034, 0x000030 },
+ [0x0032b6] = { 0x000034, 0x000031 },
+ [0x0032b7] = { 0x000034, 0x000032 },
+ [0x0032b8] = { 0x000034, 0x000033 },
+ [0x0032b9] = { 0x000034, 0x000034 },
+ [0x0032ba] = { 0x000034, 0x000035 },
+ [0x0032bb] = { 0x000034, 0x000036 },
+ [0x0032bc] = { 0x000034, 0x000037 },
+ [0x0032bd] = { 0x000034, 0x000038 },
+ [0x0032be] = { 0x000034, 0x000039 },
+ [0x0032bf] = { 0x000035, 0x000030 },
+ [0x0032c0] = { 0x000031, 0x006708 },
+ [0x0032c1] = { 0x000032, 0x006708 },
+ [0x0032c2] = { 0x000033, 0x006708 },
+ [0x0032c3] = { 0x000034, 0x006708 },
+ [0x0032c4] = { 0x000035, 0x006708 },
+ [0x0032c5] = { 0x000036, 0x006708 },
+ [0x0032c6] = { 0x000037, 0x006708 },
+ [0x0032c7] = { 0x000038, 0x006708 },
+ [0x0032c8] = { 0x000039, 0x006708 },
+ [0x0032c9] = { 0x000031, 0x000030, 0x006708 },
+ [0x0032ca] = { 0x000031, 0x000031, 0x006708 },
+ [0x0032cb] = { 0x000031, 0x000032, 0x006708 },
+ [0x0032cc] = { 0x000048, 0x000067 },
+ [0x0032cd] = { 0x000065, 0x000072, 0x000067 },
+ [0x0032ce] = { 0x000065, 0x000056 },
+ [0x0032cf] = { 0x00004c, 0x000054, 0x000044 },
+ [0x0032d0] = { 0x0030a2 },
+ [0x0032d1] = { 0x0030a4 },
+ [0x0032d2] = { 0x0030a6 },
+ [0x0032d3] = { 0x0030a8 },
+ [0x0032d4] = { 0x0030aa },
+ [0x0032d5] = { 0x0030ab },
+ [0x0032d6] = { 0x0030ad },
+ [0x0032d7] = { 0x0030af },
+ [0x0032d8] = { 0x0030b1 },
+ [0x0032d9] = { 0x0030b3 },
+ [0x0032da] = { 0x0030b5 },
+ [0x0032db] = { 0x0030b7 },
+ [0x0032dc] = { 0x0030b9 },
+ [0x0032dd] = { 0x0030bb },
+ [0x0032de] = { 0x0030bd },
+ [0x0032df] = { 0x0030bf },
+ [0x0032e0] = { 0x0030c1 },
+ [0x0032e1] = { 0x0030c4 },
+ [0x0032e2] = { 0x0030c6 },
+ [0x0032e3] = { 0x0030c8 },
+ [0x0032e4] = { 0x0030ca },
+ [0x0032e5] = { 0x0030cb },
+ [0x0032e6] = { 0x0030cc },
+ [0x0032e7] = { 0x0030cd },
+ [0x0032e8] = { 0x0030ce },
+ [0x0032e9] = { 0x0030cf },
+ [0x0032ea] = { 0x0030d2 },
+ [0x0032eb] = { 0x0030d5 },
+ [0x0032ec] = { 0x0030d8 },
+ [0x0032ed] = { 0x0030db },
+ [0x0032ee] = { 0x0030de },
+ [0x0032ef] = { 0x0030df },
+ [0x0032f0] = { 0x0030e0 },
+ [0x0032f1] = { 0x0030e1 },
+ [0x0032f2] = { 0x0030e2 },
+ [0x0032f3] = { 0x0030e4 },
+ [0x0032f4] = { 0x0030e6 },
+ [0x0032f5] = { 0x0030e8 },
+ [0x0032f6] = { 0x0030e9 },
+ [0x0032f7] = { 0x0030ea },
+ [0x0032f8] = { 0x0030eb },
+ [0x0032f9] = { 0x0030ec },
+ [0x0032fa] = { 0x0030ed },
+ [0x0032fb] = { 0x0030ef },
+ [0x0032fc] = { 0x0030f0 },
+ [0x0032fd] = { 0x0030f1 },
+ [0x0032fe] = { 0x0030f2 },
+ [0x003300] = { 0x0030a2, 0x0030cf, 0x00309a, 0x0030fc, 0x0030c8 },
+ [0x003301] = { 0x0030a2, 0x0030eb, 0x0030d5, 0x0030a1 },
+ [0x003302] = { 0x0030a2, 0x0030f3, 0x0030d8, 0x00309a, 0x0030a2 },
+ [0x003303] = { 0x0030a2, 0x0030fc, 0x0030eb },
+ [0x003304] = { 0x0030a4, 0x0030cb, 0x0030f3, 0x0030af, 0x003099 },
+ [0x003305] = { 0x0030a4, 0x0030f3, 0x0030c1 },
+ [0x003306] = { 0x0030a6, 0x0030a9, 0x0030f3 },
+ [0x003307] = { 0x0030a8, 0x0030b9, 0x0030af, 0x0030fc, 0x0030c8, 0x003099 },
+ [0x003308] = { 0x0030a8, 0x0030fc, 0x0030ab, 0x0030fc },
+ [0x003309] = { 0x0030aa, 0x0030f3, 0x0030b9 },
+ [0x00330a] = { 0x0030aa, 0x0030fc, 0x0030e0 },
+ [0x00330b] = { 0x0030ab, 0x0030a4, 0x0030ea },
+ [0x00330c] = { 0x0030ab, 0x0030e9, 0x0030c3, 0x0030c8 },
+ [0x00330d] = { 0x0030ab, 0x0030ed, 0x0030ea, 0x0030fc },
+ [0x00330e] = { 0x0030ab, 0x003099, 0x0030ed, 0x0030f3 },
+ [0x00330f] = { 0x0030ab, 0x003099, 0x0030f3, 0x0030de },
+ [0x003310] = { 0x0030ad, 0x003099, 0x0030ab, 0x003099 },
+ [0x003311] = { 0x0030ad, 0x003099, 0x0030cb, 0x0030fc },
+ [0x003312] = { 0x0030ad, 0x0030e5, 0x0030ea, 0x0030fc },
+ [0x003313] = { 0x0030ad, 0x003099, 0x0030eb, 0x0030bf, 0x003099, 0x0030fc },
+ [0x003314] = { 0x0030ad, 0x0030ed },
+ [0x003315] = { 0x0030ad, 0x0030ed, 0x0030af, 0x003099, 0x0030e9, 0x0030e0 },
+ [0x003316] = { 0x0030ad, 0x0030ed, 0x0030e1, 0x0030fc, 0x0030c8, 0x0030eb },
+ [0x003317] = { 0x0030ad, 0x0030ed, 0x0030ef, 0x0030c3, 0x0030c8 },
+ [0x003318] = { 0x0030af, 0x003099, 0x0030e9, 0x0030e0 },
+ [0x003319] = { 0x0030af, 0x003099, 0x0030e9, 0x0030e0, 0x0030c8, 0x0030f3 },
+ [0x00331a] = { 0x0030af, 0x0030eb, 0x0030bb, 0x003099, 0x0030a4, 0x0030ed },
+ [0x00331b] = { 0x0030af, 0x0030ed, 0x0030fc, 0x0030cd },
+ [0x00331c] = { 0x0030b1, 0x0030fc, 0x0030b9 },
+ [0x00331d] = { 0x0030b3, 0x0030eb, 0x0030ca },
+ [0x00331e] = { 0x0030b3, 0x0030fc, 0x0030db, 0x00309a },
+ [0x00331f] = { 0x0030b5, 0x0030a4, 0x0030af, 0x0030eb },
+ [0x003320] = { 0x0030b5, 0x0030f3, 0x0030c1, 0x0030fc, 0x0030e0 },
+ [0x003321] = { 0x0030b7, 0x0030ea, 0x0030f3, 0x0030af, 0x003099 },
+ [0x003322] = { 0x0030bb, 0x0030f3, 0x0030c1 },
+ [0x003323] = { 0x0030bb, 0x0030f3, 0x0030c8 },
+ [0x003324] = { 0x0030bf, 0x003099, 0x0030fc, 0x0030b9 },
+ [0x003325] = { 0x0030c6, 0x003099, 0x0030b7 },
+ [0x003326] = { 0x0030c8, 0x003099, 0x0030eb },
+ [0x003327] = { 0x0030c8, 0x0030f3 },
+ [0x003328] = { 0x0030ca, 0x0030ce },
+ [0x003329] = { 0x0030ce, 0x0030c3, 0x0030c8 },
+ [0x00332a] = { 0x0030cf, 0x0030a4, 0x0030c4 },
+ [0x00332b] = { 0x0030cf, 0x00309a, 0x0030fc, 0x0030bb, 0x0030f3, 0x0030c8 },
+ [0x00332c] = { 0x0030cf, 0x00309a, 0x0030fc, 0x0030c4 },
+ [0x00332d] = { 0x0030cf, 0x003099, 0x0030fc, 0x0030ec, 0x0030eb },
+ [0x00332e] = { 0x0030d2, 0x00309a, 0x0030a2, 0x0030b9, 0x0030c8, 0x0030eb },
+ [0x00332f] = { 0x0030d2, 0x00309a, 0x0030af, 0x0030eb },
+ [0x003330] = { 0x0030d2, 0x00309a, 0x0030b3 },
+ [0x003331] = { 0x0030d2, 0x003099, 0x0030eb },
+ [0x003332] = { 0x0030d5, 0x0030a1, 0x0030e9, 0x0030c3, 0x0030c8, 0x003099 },
+ [0x003333] = { 0x0030d5, 0x0030a3, 0x0030fc, 0x0030c8 },
+ [0x003334] = { 0x0030d5, 0x003099, 0x0030c3, 0x0030b7, 0x0030a7, 0x0030eb },
+ [0x003335] = { 0x0030d5, 0x0030e9, 0x0030f3 },
+ [0x003336] = { 0x0030d8, 0x0030af, 0x0030bf, 0x0030fc, 0x0030eb },
+ [0x003337] = { 0x0030d8, 0x00309a, 0x0030bd },
+ [0x003338] = { 0x0030d8, 0x00309a, 0x0030cb, 0x0030d2 },
+ [0x003339] = { 0x0030d8, 0x0030eb, 0x0030c4 },
+ [0x00333a] = { 0x0030d8, 0x00309a, 0x0030f3, 0x0030b9 },
+ [0x00333b] = { 0x0030d8, 0x00309a, 0x0030fc, 0x0030b7, 0x003099 },
+ [0x00333c] = { 0x0030d8, 0x003099, 0x0030fc, 0x0030bf },
+ [0x00333d] = { 0x0030db, 0x00309a, 0x0030a4, 0x0030f3, 0x0030c8 },
+ [0x00333e] = { 0x0030db, 0x003099, 0x0030eb, 0x0030c8 },
+ [0x00333f] = { 0x0030db, 0x0030f3 },
+ [0x003340] = { 0x0030db, 0x00309a, 0x0030f3, 0x0030c8, 0x003099 },
+ [0x003341] = { 0x0030db, 0x0030fc, 0x0030eb },
+ [0x003342] = { 0x0030db, 0x0030fc, 0x0030f3 },
+ [0x003343] = { 0x0030de, 0x0030a4, 0x0030af, 0x0030ed },
+ [0x003344] = { 0x0030de, 0x0030a4, 0x0030eb },
+ [0x003345] = { 0x0030de, 0x0030c3, 0x0030cf },
+ [0x003346] = { 0x0030de, 0x0030eb, 0x0030af },
+ [0x003347] = { 0x0030de, 0x0030f3, 0x0030b7, 0x0030e7, 0x0030f3 },
+ [0x003348] = { 0x0030df, 0x0030af, 0x0030ed, 0x0030f3 },
+ [0x003349] = { 0x0030df, 0x0030ea },
+ [0x00334a] = { 0x0030df, 0x0030ea, 0x0030cf, 0x003099, 0x0030fc, 0x0030eb },
+ [0x00334b] = { 0x0030e1, 0x0030ab, 0x003099 },
+ [0x00334c] = { 0x0030e1, 0x0030ab, 0x003099, 0x0030c8, 0x0030f3 },
+ [0x00334d] = { 0x0030e1, 0x0030fc, 0x0030c8, 0x0030eb },
+ [0x00334e] = { 0x0030e4, 0x0030fc, 0x0030c8, 0x003099 },
+ [0x00334f] = { 0x0030e4, 0x0030fc, 0x0030eb },
+ [0x003350] = { 0x0030e6, 0x0030a2, 0x0030f3 },
+ [0x003351] = { 0x0030ea, 0x0030c3, 0x0030c8, 0x0030eb },
+ [0x003352] = { 0x0030ea, 0x0030e9 },
+ [0x003353] = { 0x0030eb, 0x0030d2, 0x00309a, 0x0030fc },
+ [0x003354] = { 0x0030eb, 0x0030fc, 0x0030d5, 0x003099, 0x0030eb },
+ [0x003355] = { 0x0030ec, 0x0030e0 },
+ [0x003356] = { 0x0030ec, 0x0030f3, 0x0030c8, 0x0030b1, 0x003099, 0x0030f3 },
+ [0x003357] = { 0x0030ef, 0x0030c3, 0x0030c8 },
+ [0x003358] = { 0x000030, 0x0070b9 },
+ [0x003359] = { 0x000031, 0x0070b9 },
+ [0x00335a] = { 0x000032, 0x0070b9 },
+ [0x00335b] = { 0x000033, 0x0070b9 },
+ [0x00335c] = { 0x000034, 0x0070b9 },
+ [0x00335d] = { 0x000035, 0x0070b9 },
+ [0x00335e] = { 0x000036, 0x0070b9 },
+ [0x00335f] = { 0x000037, 0x0070b9 },
+ [0x003360] = { 0x000038, 0x0070b9 },
+ [0x003361] = { 0x000039, 0x0070b9 },
+ [0x003362] = { 0x000031, 0x000030, 0x0070b9 },
+ [0x003363] = { 0x000031, 0x000031, 0x0070b9 },
+ [0x003364] = { 0x000031, 0x000032, 0x0070b9 },
+ [0x003365] = { 0x000031, 0x000033, 0x0070b9 },
+ [0x003366] = { 0x000031, 0x000034, 0x0070b9 },
+ [0x003367] = { 0x000031, 0x000035, 0x0070b9 },
+ [0x003368] = { 0x000031, 0x000036, 0x0070b9 },
+ [0x003369] = { 0x000031, 0x000037, 0x0070b9 },
+ [0x00336a] = { 0x000031, 0x000038, 0x0070b9 },
+ [0x00336b] = { 0x000031, 0x000039, 0x0070b9 },
+ [0x00336c] = { 0x000032, 0x000030, 0x0070b9 },
+ [0x00336d] = { 0x000032, 0x000031, 0x0070b9 },
+ [0x00336e] = { 0x000032, 0x000032, 0x0070b9 },
+ [0x00336f] = { 0x000032, 0x000033, 0x0070b9 },
+ [0x003370] = { 0x000032, 0x000034, 0x0070b9 },
+ [0x003371] = { 0x000068, 0x000050, 0x000061 },
+ [0x003372] = { 0x000064, 0x000061 },
+ [0x003373] = { 0x000041, 0x000055 },
+ [0x003374] = { 0x000062, 0x000061, 0x000072 },
+ [0x003375] = { 0x00006f, 0x000056 },
+ [0x003376] = { 0x000070, 0x000063 },
+ [0x003377] = { 0x000064, 0x00006d },
+ [0x003378] = { 0x000064, 0x00006d, 0x000032 },
+ [0x003379] = { 0x000064, 0x00006d, 0x000033 },
+ [0x00337a] = { 0x000049, 0x000055 },
+ [0x00337b] = { 0x005e73, 0x006210 },
+ [0x00337c] = { 0x00662d, 0x00548c },
+ [0x00337d] = { 0x005927, 0x006b63 },
+ [0x00337e] = { 0x00660e, 0x006cbb },
+ [0x00337f] = { 0x00682a, 0x005f0f, 0x004f1a, 0x00793e },
+ [0x003380] = { 0x000070, 0x000041 },
+ [0x003381] = { 0x00006e, 0x000041 },
+ [0x003382] = { 0x0003bc, 0x000041 },
+ [0x003383] = { 0x00006d, 0x000041 },
+ [0x003384] = { 0x00006b, 0x000041 },
+ [0x003385] = { 0x00004b, 0x000042 },
+ [0x003386] = { 0x00004d, 0x000042 },
+ [0x003387] = { 0x000047, 0x000042 },
+ [0x003388] = { 0x000063, 0x000061, 0x00006c },
+ [0x003389] = { 0x00006b, 0x000063, 0x000061, 0x00006c },
+ [0x00338a] = { 0x000070, 0x000046 },
+ [0x00338b] = { 0x00006e, 0x000046 },
+ [0x00338c] = { 0x0003bc, 0x000046 },
+ [0x00338d] = { 0x0003bc, 0x000067 },
+ [0x00338e] = { 0x00006d, 0x000067 },
+ [0x00338f] = { 0x00006b, 0x000067 },
+ [0x003390] = { 0x000048, 0x00007a },
+ [0x003391] = { 0x00006b, 0x000048, 0x00007a },
+ [0x003392] = { 0x00004d, 0x000048, 0x00007a },
+ [0x003393] = { 0x000047, 0x000048, 0x00007a },
+ [0x003394] = { 0x000054, 0x000048, 0x00007a },
+ [0x003395] = { 0x0003bc, 0x00006c },
+ [0x003396] = { 0x00006d, 0x00006c },
+ [0x003397] = { 0x000064, 0x00006c },
+ [0x003398] = { 0x00006b, 0x00006c },
+ [0x003399] = { 0x000066, 0x00006d },
+ [0x00339a] = { 0x00006e, 0x00006d },
+ [0x00339b] = { 0x0003bc, 0x00006d },
+ [0x00339c] = { 0x00006d, 0x00006d },
+ [0x00339d] = { 0x000063, 0x00006d },
+ [0x00339e] = { 0x00006b, 0x00006d },
+ [0x00339f] = { 0x00006d, 0x00006d, 0x000032 },
+ [0x0033a0] = { 0x000063, 0x00006d, 0x000032 },
+ [0x0033a1] = { 0x00006d, 0x000032 },
+ [0x0033a2] = { 0x00006b, 0x00006d, 0x000032 },
+ [0x0033a3] = { 0x00006d, 0x00006d, 0x000033 },
+ [0x0033a4] = { 0x000063, 0x00006d, 0x000033 },
+ [0x0033a5] = { 0x00006d, 0x000033 },
+ [0x0033a6] = { 0x00006b, 0x00006d, 0x000033 },
+ [0x0033a7] = { 0x00006d, 0x002215, 0x000073 },
+ [0x0033a8] = { 0x00006d, 0x002215, 0x000073, 0x000032 },
+ [0x0033a9] = { 0x000050, 0x000061 },
+ [0x0033aa] = { 0x00006b, 0x000050, 0x000061 },
+ [0x0033ab] = { 0x00004d, 0x000050, 0x000061 },
+ [0x0033ac] = { 0x000047, 0x000050, 0x000061 },
+ [0x0033ad] = { 0x000072, 0x000061, 0x000064 },
+ [0x0033ae] = { 0x000072, 0x000061, 0x000064, 0x002215, 0x000073 },
+ [0x0033af] = { 0x000072, 0x000061, 0x000064, 0x002215, 0x000073, 0x000032 },
+ [0x0033b0] = { 0x000070, 0x000073 },
+ [0x0033b1] = { 0x00006e, 0x000073 },
+ [0x0033b2] = { 0x0003bc, 0x000073 },
+ [0x0033b3] = { 0x00006d, 0x000073 },
+ [0x0033b4] = { 0x000070, 0x000056 },
+ [0x0033b5] = { 0x00006e, 0x000056 },
+ [0x0033b6] = { 0x0003bc, 0x000056 },
+ [0x0033b7] = { 0x00006d, 0x000056 },
+ [0x0033b8] = { 0x00006b, 0x000056 },
+ [0x0033b9] = { 0x00004d, 0x000056 },
+ [0x0033ba] = { 0x000070, 0x000057 },
+ [0x0033bb] = { 0x00006e, 0x000057 },
+ [0x0033bc] = { 0x0003bc, 0x000057 },
+ [0x0033bd] = { 0x00006d, 0x000057 },
+ [0x0033be] = { 0x00006b, 0x000057 },
+ [0x0033bf] = { 0x00004d, 0x000057 },
+ [0x0033c0] = { 0x00006b, 0x0003a9 },
+ [0x0033c1] = { 0x00004d, 0x0003a9 },
+ [0x0033c2] = { 0x000061, 0x00002e, 0x00006d, 0x00002e },
+ [0x0033c3] = { 0x000042, 0x000071 },
+ [0x0033c4] = { 0x000063, 0x000063 },
+ [0x0033c5] = { 0x000063, 0x000064 },
+ [0x0033c6] = { 0x000043, 0x002215, 0x00006b, 0x000067 },
+ [0x0033c7] = { 0x000043, 0x00006f, 0x00002e },
+ [0x0033c8] = { 0x000064, 0x000042 },
+ [0x0033c9] = { 0x000047, 0x000079 },
+ [0x0033ca] = { 0x000068, 0x000061 },
+ [0x0033cb] = { 0x000048, 0x000050 },
+ [0x0033cc] = { 0x000069, 0x00006e },
+ [0x0033cd] = { 0x00004b, 0x00004b },
+ [0x0033ce] = { 0x00004b, 0x00004d },
+ [0x0033cf] = { 0x00006b, 0x000074 },
+ [0x0033d0] = { 0x00006c, 0x00006d },
+ [0x0033d1] = { 0x00006c, 0x00006e },
+ [0x0033d2] = { 0x00006c, 0x00006f, 0x000067 },
+ [0x0033d3] = { 0x00006c, 0x000078 },
+ [0x0033d4] = { 0x00006d, 0x000062 },
+ [0x0033d5] = { 0x00006d, 0x000069, 0x00006c },
+ [0x0033d6] = { 0x00006d, 0x00006f, 0x00006c },
+ [0x0033d7] = { 0x000050, 0x000048 },
+ [0x0033d8] = { 0x000070, 0x00002e, 0x00006d, 0x00002e },
+ [0x0033d9] = { 0x000050, 0x000050, 0x00004d },
+ [0x0033da] = { 0x000050, 0x000052 },
+ [0x0033db] = { 0x000073, 0x000072 },
+ [0x0033dc] = { 0x000053, 0x000076 },
+ [0x0033dd] = { 0x000057, 0x000062 },
+ [0x0033de] = { 0x000056, 0x002215, 0x00006d },
+ [0x0033df] = { 0x000041, 0x002215, 0x00006d },
+ [0x0033e0] = { 0x000031, 0x0065e5 },
+ [0x0033e1] = { 0x000032, 0x0065e5 },
+ [0x0033e2] = { 0x000033, 0x0065e5 },
+ [0x0033e3] = { 0x000034, 0x0065e5 },
+ [0x0033e4] = { 0x000035, 0x0065e5 },
+ [0x0033e5] = { 0x000036, 0x0065e5 },
+ [0x0033e6] = { 0x000037, 0x0065e5 },
+ [0x0033e7] = { 0x000038, 0x0065e5 },
+ [0x0033e8] = { 0x000039, 0x0065e5 },
+ [0x0033e9] = { 0x000031, 0x000030, 0x0065e5 },
+ [0x0033ea] = { 0x000031, 0x000031, 0x0065e5 },
+ [0x0033eb] = { 0x000031, 0x000032, 0x0065e5 },
+ [0x0033ec] = { 0x000031, 0x000033, 0x0065e5 },
+ [0x0033ed] = { 0x000031, 0x000034, 0x0065e5 },
+ [0x0033ee] = { 0x000031, 0x000035, 0x0065e5 },
+ [0x0033ef] = { 0x000031, 0x000036, 0x0065e5 },
+ [0x0033f0] = { 0x000031, 0x000037, 0x0065e5 },
+ [0x0033f1] = { 0x000031, 0x000038, 0x0065e5 },
+ [0x0033f2] = { 0x000031, 0x000039, 0x0065e5 },
+ [0x0033f3] = { 0x000032, 0x000030, 0x0065e5 },
+ [0x0033f4] = { 0x000032, 0x000031, 0x0065e5 },
+ [0x0033f5] = { 0x000032, 0x000032, 0x0065e5 },
+ [0x0033f6] = { 0x000032, 0x000033, 0x0065e5 },
+ [0x0033f7] = { 0x000032, 0x000034, 0x0065e5 },
+ [0x0033f8] = { 0x000032, 0x000035, 0x0065e5 },
+ [0x0033f9] = { 0x000032, 0x000036, 0x0065e5 },
+ [0x0033fa] = { 0x000032, 0x000037, 0x0065e5 },
+ [0x0033fb] = { 0x000032, 0x000038, 0x0065e5 },
+ [0x0033fc] = { 0x000032, 0x000039, 0x0065e5 },
+ [0x0033fd] = { 0x000033, 0x000030, 0x0065e5 },
+ [0x0033fe] = { 0x000033, 0x000031, 0x0065e5 },
+ [0x0033ff] = { 0x000067, 0x000061, 0x00006c },
+ [0x00a69c] = { 0x00044a },
+ [0x00a69d] = { 0x00044c },
+ [0x00a770] = { 0x00a76f },
+ [0x00a7f8] = { 0x000126 },
+ [0x00a7f9] = { 0x000153 },
+ [0x00ab5c] = { 0x00a727 },
+ [0x00ab5d] = { 0x00ab37 },
+ [0x00ab5e] = { 0x00026b },
+ [0x00ab5f] = { 0x00ab52 },
+ [0x00fb00] = { 0x000066, 0x000066 },
+ [0x00fb01] = { 0x000066, 0x000069 },
+ [0x00fb02] = { 0x000066, 0x00006c },
+ [0x00fb03] = { 0x000066, 0x000066, 0x000069 },
+ [0x00fb04] = { 0x000066, 0x000066, 0x00006c },
+ [0x00fb05] = { 0x000073, 0x000074 },
+ [0x00fb06] = { 0x000073, 0x000074 },
+ [0x00fb13] = { 0x000574, 0x000576 },
+ [0x00fb14] = { 0x000574, 0x000565 },
+ [0x00fb15] = { 0x000574, 0x00056b },
+ [0x00fb16] = { 0x00057e, 0x000576 },
+ [0x00fb17] = { 0x000574, 0x00056d },
+ [0x00fb20] = { 0x0005e2 },
+ [0x00fb21] = { 0x0005d0 },
+ [0x00fb22] = { 0x0005d3 },
+ [0x00fb23] = { 0x0005d4 },
+ [0x00fb24] = { 0x0005db },
+ [0x00fb25] = { 0x0005dc },
+ [0x00fb26] = { 0x0005dd },
+ [0x00fb27] = { 0x0005e8 },
+ [0x00fb28] = { 0x0005ea },
+ [0x00fb29] = { 0x00002b },
+ [0x00fb4f] = { 0x0005d0, 0x0005dc },
+ [0x00fb50] = { 0x000671 },
+ [0x00fb51] = { 0x000671 },
+ [0x00fb52] = { 0x00067b },
+ [0x00fb53] = { 0x00067b },
+ [0x00fb54] = { 0x00067b },
+ [0x00fb55] = { 0x00067b },
+ [0x00fb56] = { 0x00067e },
+ [0x00fb57] = { 0x00067e },
+ [0x00fb58] = { 0x00067e },
+ [0x00fb59] = { 0x00067e },
+ [0x00fb5a] = { 0x000680 },
+ [0x00fb5b] = { 0x000680 },
+ [0x00fb5c] = { 0x000680 },
+ [0x00fb5d] = { 0x000680 },
+ [0x00fb5e] = { 0x00067a },
+ [0x00fb5f] = { 0x00067a },
+ [0x00fb60] = { 0x00067a },
+ [0x00fb61] = { 0x00067a },
+ [0x00fb62] = { 0x00067f },
+ [0x00fb63] = { 0x00067f },
+ [0x00fb64] = { 0x00067f },
+ [0x00fb65] = { 0x00067f },
+ [0x00fb66] = { 0x000679 },
+ [0x00fb67] = { 0x000679 },
+ [0x00fb68] = { 0x000679 },
+ [0x00fb69] = { 0x000679 },
+ [0x00fb6a] = { 0x0006a4 },
+ [0x00fb6b] = { 0x0006a4 },
+ [0x00fb6c] = { 0x0006a4 },
+ [0x00fb6d] = { 0x0006a4 },
+ [0x00fb6e] = { 0x0006a6 },
+ [0x00fb6f] = { 0x0006a6 },
+ [0x00fb70] = { 0x0006a6 },
+ [0x00fb71] = { 0x0006a6 },
+ [0x00fb72] = { 0x000684 },
+ [0x00fb73] = { 0x000684 },
+ [0x00fb74] = { 0x000684 },
+ [0x00fb75] = { 0x000684 },
+ [0x00fb76] = { 0x000683 },
+ [0x00fb77] = { 0x000683 },
+ [0x00fb78] = { 0x000683 },
+ [0x00fb79] = { 0x000683 },
+ [0x00fb7a] = { 0x000686 },
+ [0x00fb7b] = { 0x000686 },
+ [0x00fb7c] = { 0x000686 },
+ [0x00fb7d] = { 0x000686 },
+ [0x00fb7e] = { 0x000687 },
+ [0x00fb7f] = { 0x000687 },
+ [0x00fb80] = { 0x000687 },
+ [0x00fb81] = { 0x000687 },
+ [0x00fb82] = { 0x00068d },
+ [0x00fb83] = { 0x00068d },
+ [0x00fb84] = { 0x00068c },
+ [0x00fb85] = { 0x00068c },
+ [0x00fb86] = { 0x00068e },
+ [0x00fb87] = { 0x00068e },
+ [0x00fb88] = { 0x000688 },
+ [0x00fb89] = { 0x000688 },
+ [0x00fb8a] = { 0x000698 },
+ [0x00fb8b] = { 0x000698 },
+ [0x00fb8c] = { 0x000691 },
+ [0x00fb8d] = { 0x000691 },
+ [0x00fb8e] = { 0x0006a9 },
+ [0x00fb8f] = { 0x0006a9 },
+ [0x00fb90] = { 0x0006a9 },
+ [0x00fb91] = { 0x0006a9 },
+ [0x00fb92] = { 0x0006af },
+ [0x00fb93] = { 0x0006af },
+ [0x00fb94] = { 0x0006af },
+ [0x00fb95] = { 0x0006af },
+ [0x00fb96] = { 0x0006b3 },
+ [0x00fb97] = { 0x0006b3 },
+ [0x00fb98] = { 0x0006b3 },
+ [0x00fb99] = { 0x0006b3 },
+ [0x00fb9a] = { 0x0006b1 },
+ [0x00fb9b] = { 0x0006b1 },
+ [0x00fb9c] = { 0x0006b1 },
+ [0x00fb9d] = { 0x0006b1 },
+ [0x00fb9e] = { 0x0006ba },
+ [0x00fb9f] = { 0x0006ba },
+ [0x00fba0] = { 0x0006bb },
+ [0x00fba1] = { 0x0006bb },
+ [0x00fba2] = { 0x0006bb },
+ [0x00fba3] = { 0x0006bb },
+ [0x00fba4] = { 0x0006d5, 0x000654 },
+ [0x00fba5] = { 0x0006d5, 0x000654 },
+ [0x00fba6] = { 0x0006c1 },
+ [0x00fba7] = { 0x0006c1 },
+ [0x00fba8] = { 0x0006c1 },
+ [0x00fba9] = { 0x0006c1 },
+ [0x00fbaa] = { 0x0006be },
+ [0x00fbab] = { 0x0006be },
+ [0x00fbac] = { 0x0006be },
+ [0x00fbad] = { 0x0006be },
+ [0x00fbae] = { 0x0006d2 },
+ [0x00fbaf] = { 0x0006d2 },
+ [0x00fbb0] = { 0x0006d2, 0x000654 },
+ [0x00fbb1] = { 0x0006d2, 0x000654 },
+ [0x00fbd3] = { 0x0006ad },
+ [0x00fbd4] = { 0x0006ad },
+ [0x00fbd5] = { 0x0006ad },
+ [0x00fbd6] = { 0x0006ad },
+ [0x00fbd7] = { 0x0006c7 },
+ [0x00fbd8] = { 0x0006c7 },
+ [0x00fbd9] = { 0x0006c6 },
+ [0x00fbda] = { 0x0006c6 },
+ [0x00fbdb] = { 0x0006c8 },
+ [0x00fbdc] = { 0x0006c8 },
+ [0x00fbdd] = { 0x0006c7, 0x000674 },
+ [0x00fbde] = { 0x0006cb },
+ [0x00fbdf] = { 0x0006cb },
+ [0x00fbe0] = { 0x0006c5 },
+ [0x00fbe1] = { 0x0006c5 },
+ [0x00fbe2] = { 0x0006c9 },
+ [0x00fbe3] = { 0x0006c9 },
+ [0x00fbe4] = { 0x0006d0 },
+ [0x00fbe5] = { 0x0006d0 },
+ [0x00fbe6] = { 0x0006d0 },
+ [0x00fbe7] = { 0x0006d0 },
+ [0x00fbe8] = { 0x000649 },
+ [0x00fbe9] = { 0x000649 },
+ [0x00fbea] = { 0x00064a, 0x000654, 0x000627 },
+ [0x00fbeb] = { 0x00064a, 0x000654, 0x000627 },
+ [0x00fbec] = { 0x00064a, 0x000654, 0x0006d5 },
+ [0x00fbed] = { 0x00064a, 0x000654, 0x0006d5 },
+ [0x00fbee] = { 0x00064a, 0x000654, 0x000648 },
+ [0x00fbef] = { 0x00064a, 0x000654, 0x000648 },
+ [0x00fbf0] = { 0x00064a, 0x000654, 0x0006c7 },
+ [0x00fbf1] = { 0x00064a, 0x000654, 0x0006c7 },
+ [0x00fbf2] = { 0x00064a, 0x000654, 0x0006c6 },
+ [0x00fbf3] = { 0x00064a, 0x000654, 0x0006c6 },
+ [0x00fbf4] = { 0x00064a, 0x000654, 0x0006c8 },
+ [0x00fbf5] = { 0x00064a, 0x000654, 0x0006c8 },
+ [0x00fbf6] = { 0x00064a, 0x000654, 0x0006d0 },
+ [0x00fbf7] = { 0x00064a, 0x000654, 0x0006d0 },
+ [0x00fbf8] = { 0x00064a, 0x000654, 0x0006d0 },
+ [0x00fbf9] = { 0x00064a, 0x000654, 0x000649 },
+ [0x00fbfa] = { 0x00064a, 0x000654, 0x000649 },
+ [0x00fbfb] = { 0x00064a, 0x000654, 0x000649 },
+ [0x00fbfc] = { 0x0006cc },
+ [0x00fbfd] = { 0x0006cc },
+ [0x00fbfe] = { 0x0006cc },
+ [0x00fbff] = { 0x0006cc },
+ [0x00fc00] = { 0x00064a, 0x000654, 0x00062c },
+ [0x00fc01] = { 0x00064a, 0x000654, 0x00062d },
+ [0x00fc02] = { 0x00064a, 0x000654, 0x000645 },
+ [0x00fc03] = { 0x00064a, 0x000654, 0x000649 },
+ [0x00fc04] = { 0x00064a, 0x000654, 0x00064a },
+ [0x00fc05] = { 0x000628, 0x00062c },
+ [0x00fc06] = { 0x000628, 0x00062d },
+ [0x00fc07] = { 0x000628, 0x00062e },
+ [0x00fc08] = { 0x000628, 0x000645 },
+ [0x00fc09] = { 0x000628, 0x000649 },
+ [0x00fc0a] = { 0x000628, 0x00064a },
+ [0x00fc0b] = { 0x00062a, 0x00062c },
+ [0x00fc0c] = { 0x00062a, 0x00062d },
+ [0x00fc0d] = { 0x00062a, 0x00062e },
+ [0x00fc0e] = { 0x00062a, 0x000645 },
+ [0x00fc0f] = { 0x00062a, 0x000649 },
+ [0x00fc10] = { 0x00062a, 0x00064a },
+ [0x00fc11] = { 0x00062b, 0x00062c },
+ [0x00fc12] = { 0x00062b, 0x000645 },
+ [0x00fc13] = { 0x00062b, 0x000649 },
+ [0x00fc14] = { 0x00062b, 0x00064a },
+ [0x00fc15] = { 0x00062c, 0x00062d },
+ [0x00fc16] = { 0x00062c, 0x000645 },
+ [0x00fc17] = { 0x00062d, 0x00062c },
+ [0x00fc18] = { 0x00062d, 0x000645 },
+ [0x00fc19] = { 0x00062e, 0x00062c },
+ [0x00fc1a] = { 0x00062e, 0x00062d },
+ [0x00fc1b] = { 0x00062e, 0x000645 },
+ [0x00fc1c] = { 0x000633, 0x00062c },
+ [0x00fc1d] = { 0x000633, 0x00062d },
+ [0x00fc1e] = { 0x000633, 0x00062e },
+ [0x00fc1f] = { 0x000633, 0x000645 },
+ [0x00fc20] = { 0x000635, 0x00062d },
+ [0x00fc21] = { 0x000635, 0x000645 },
+ [0x00fc22] = { 0x000636, 0x00062c },
+ [0x00fc23] = { 0x000636, 0x00062d },
+ [0x00fc24] = { 0x000636, 0x00062e },
+ [0x00fc25] = { 0x000636, 0x000645 },
+ [0x00fc26] = { 0x000637, 0x00062d },
+ [0x00fc27] = { 0x000637, 0x000645 },
+ [0x00fc28] = { 0x000638, 0x000645 },
+ [0x00fc29] = { 0x000639, 0x00062c },
+ [0x00fc2a] = { 0x000639, 0x000645 },
+ [0x00fc2b] = { 0x00063a, 0x00062c },
+ [0x00fc2c] = { 0x00063a, 0x000645 },
+ [0x00fc2d] = { 0x000641, 0x00062c },
+ [0x00fc2e] = { 0x000641, 0x00062d },
+ [0x00fc2f] = { 0x000641, 0x00062e },
+ [0x00fc30] = { 0x000641, 0x000645 },
+ [0x00fc31] = { 0x000641, 0x000649 },
+ [0x00fc32] = { 0x000641, 0x00064a },
+ [0x00fc33] = { 0x000642, 0x00062d },
+ [0x00fc34] = { 0x000642, 0x000645 },
+ [0x00fc35] = { 0x000642, 0x000649 },
+ [0x00fc36] = { 0x000642, 0x00064a },
+ [0x00fc37] = { 0x000643, 0x000627 },
+ [0x00fc38] = { 0x000643, 0x00062c },
+ [0x00fc39] = { 0x000643, 0x00062d },
+ [0x00fc3a] = { 0x000643, 0x00062e },
+ [0x00fc3b] = { 0x000643, 0x000644 },
+ [0x00fc3c] = { 0x000643, 0x000645 },
+ [0x00fc3d] = { 0x000643, 0x000649 },
+ [0x00fc3e] = { 0x000643, 0x00064a },
+ [0x00fc3f] = { 0x000644, 0x00062c },
+ [0x00fc40] = { 0x000644, 0x00062d },
+ [0x00fc41] = { 0x000644, 0x00062e },
+ [0x00fc42] = { 0x000644, 0x000645 },
+ [0x00fc43] = { 0x000644, 0x000649 },
+ [0x00fc44] = { 0x000644, 0x00064a },
+ [0x00fc45] = { 0x000645, 0x00062c },
+ [0x00fc46] = { 0x000645, 0x00062d },
+ [0x00fc47] = { 0x000645, 0x00062e },
+ [0x00fc48] = { 0x000645, 0x000645 },
+ [0x00fc49] = { 0x000645, 0x000649 },
+ [0x00fc4a] = { 0x000645, 0x00064a },
+ [0x00fc4b] = { 0x000646, 0x00062c },
+ [0x00fc4c] = { 0x000646, 0x00062d },
+ [0x00fc4d] = { 0x000646, 0x00062e },
+ [0x00fc4e] = { 0x000646, 0x000645 },
+ [0x00fc4f] = { 0x000646, 0x000649 },
+ [0x00fc50] = { 0x000646, 0x00064a },
+ [0x00fc51] = { 0x000647, 0x00062c },
+ [0x00fc52] = { 0x000647, 0x000645 },
+ [0x00fc53] = { 0x000647, 0x000649 },
+ [0x00fc54] = { 0x000647, 0x00064a },
+ [0x00fc55] = { 0x00064a, 0x00062c },
+ [0x00fc56] = { 0x00064a, 0x00062d },
+ [0x00fc57] = { 0x00064a, 0x00062e },
+ [0x00fc58] = { 0x00064a, 0x000645 },
+ [0x00fc59] = { 0x00064a, 0x000649 },
+ [0x00fc5a] = { 0x00064a, 0x00064a },
+ [0x00fc5b] = { 0x000630, 0x000670 },
+ [0x00fc5c] = { 0x000631, 0x000670 },
+ [0x00fc5d] = { 0x000649, 0x000670 },
+ [0x00fc5e] = { 0x000020, 0x00064c, 0x000651 },
+ [0x00fc5f] = { 0x000020, 0x00064d, 0x000651 },
+ [0x00fc60] = { 0x000020, 0x00064e, 0x000651 },
+ [0x00fc61] = { 0x000020, 0x00064f, 0x000651 },
+ [0x00fc62] = { 0x000020, 0x000650, 0x000651 },
+ [0x00fc63] = { 0x000020, 0x000651, 0x000670 },
+ [0x00fc64] = { 0x00064a, 0x000654, 0x000631 },
+ [0x00fc65] = { 0x00064a, 0x000654, 0x000632 },
+ [0x00fc66] = { 0x00064a, 0x000654, 0x000645 },
+ [0x00fc67] = { 0x00064a, 0x000654, 0x000646 },
+ [0x00fc68] = { 0x00064a, 0x000654, 0x000649 },
+ [0x00fc69] = { 0x00064a, 0x000654, 0x00064a },
+ [0x00fc6a] = { 0x000628, 0x000631 },
+ [0x00fc6b] = { 0x000628, 0x000632 },
+ [0x00fc6c] = { 0x000628, 0x000645 },
+ [0x00fc6d] = { 0x000628, 0x000646 },
+ [0x00fc6e] = { 0x000628, 0x000649 },
+ [0x00fc6f] = { 0x000628, 0x00064a },
+ [0x00fc70] = { 0x00062a, 0x000631 },
+ [0x00fc71] = { 0x00062a, 0x000632 },
+ [0x00fc72] = { 0x00062a, 0x000645 },
+ [0x00fc73] = { 0x00062a, 0x000646 },
+ [0x00fc74] = { 0x00062a, 0x000649 },
+ [0x00fc75] = { 0x00062a, 0x00064a },
+ [0x00fc76] = { 0x00062b, 0x000631 },
+ [0x00fc77] = { 0x00062b, 0x000632 },
+ [0x00fc78] = { 0x00062b, 0x000645 },
+ [0x00fc79] = { 0x00062b, 0x000646 },
+ [0x00fc7a] = { 0x00062b, 0x000649 },
+ [0x00fc7b] = { 0x00062b, 0x00064a },
+ [0x00fc7c] = { 0x000641, 0x000649 },
+ [0x00fc7d] = { 0x000641, 0x00064a },
+ [0x00fc7e] = { 0x000642, 0x000649 },
+ [0x00fc7f] = { 0x000642, 0x00064a },
+ [0x00fc80] = { 0x000643, 0x000627 },
+ [0x00fc81] = { 0x000643, 0x000644 },
+ [0x00fc82] = { 0x000643, 0x000645 },
+ [0x00fc83] = { 0x000643, 0x000649 },
+ [0x00fc84] = { 0x000643, 0x00064a },
+ [0x00fc85] = { 0x000644, 0x000645 },
+ [0x00fc86] = { 0x000644, 0x000649 },
+ [0x00fc87] = { 0x000644, 0x00064a },
+ [0x00fc88] = { 0x000645, 0x000627 },
+ [0x00fc89] = { 0x000645, 0x000645 },
+ [0x00fc8a] = { 0x000646, 0x000631 },
+ [0x00fc8b] = { 0x000646, 0x000632 },
+ [0x00fc8c] = { 0x000646, 0x000645 },
+ [0x00fc8d] = { 0x000646, 0x000646 },
+ [0x00fc8e] = { 0x000646, 0x000649 },
+ [0x00fc8f] = { 0x000646, 0x00064a },
+ [0x00fc90] = { 0x000649, 0x000670 },
+ [0x00fc91] = { 0x00064a, 0x000631 },
+ [0x00fc92] = { 0x00064a, 0x000632 },
+ [0x00fc93] = { 0x00064a, 0x000645 },
+ [0x00fc94] = { 0x00064a, 0x000646 },
+ [0x00fc95] = { 0x00064a, 0x000649 },
+ [0x00fc96] = { 0x00064a, 0x00064a },
+ [0x00fc97] = { 0x00064a, 0x000654, 0x00062c },
+ [0x00fc98] = { 0x00064a, 0x000654, 0x00062d },
+ [0x00fc99] = { 0x00064a, 0x000654, 0x00062e },
+ [0x00fc9a] = { 0x00064a, 0x000654, 0x000645 },
+ [0x00fc9b] = { 0x00064a, 0x000654, 0x000647 },
+ [0x00fc9c] = { 0x000628, 0x00062c },
+ [0x00fc9d] = { 0x000628, 0x00062d },
+ [0x00fc9e] = { 0x000628, 0x00062e },
+ [0x00fc9f] = { 0x000628, 0x000645 },
+ [0x00fca0] = { 0x000628, 0x000647 },
+ [0x00fca1] = { 0x00062a, 0x00062c },
+ [0x00fca2] = { 0x00062a, 0x00062d },
+ [0x00fca3] = { 0x00062a, 0x00062e },
+ [0x00fca4] = { 0x00062a, 0x000645 },
+ [0x00fca5] = { 0x00062a, 0x000647 },
+ [0x00fca6] = { 0x00062b, 0x000645 },
+ [0x00fca7] = { 0x00062c, 0x00062d },
+ [0x00fca8] = { 0x00062c, 0x000645 },
+ [0x00fca9] = { 0x00062d, 0x00062c },
+ [0x00fcaa] = { 0x00062d, 0x000645 },
+ [0x00fcab] = { 0x00062e, 0x00062c },
+ [0x00fcac] = { 0x00062e, 0x000645 },
+ [0x00fcad] = { 0x000633, 0x00062c },
+ [0x00fcae] = { 0x000633, 0x00062d },
+ [0x00fcaf] = { 0x000633, 0x00062e },
+ [0x00fcb0] = { 0x000633, 0x000645 },
+ [0x00fcb1] = { 0x000635, 0x00062d },
+ [0x00fcb2] = { 0x000635, 0x00062e },
+ [0x00fcb3] = { 0x000635, 0x000645 },
+ [0x00fcb4] = { 0x000636, 0x00062c },
+ [0x00fcb5] = { 0x000636, 0x00062d },
+ [0x00fcb6] = { 0x000636, 0x00062e },
+ [0x00fcb7] = { 0x000636, 0x000645 },
+ [0x00fcb8] = { 0x000637, 0x00062d },
+ [0x00fcb9] = { 0x000638, 0x000645 },
+ [0x00fcba] = { 0x000639, 0x00062c },
+ [0x00fcbb] = { 0x000639, 0x000645 },
+ [0x00fcbc] = { 0x00063a, 0x00062c },
+ [0x00fcbd] = { 0x00063a, 0x000645 },
+ [0x00fcbe] = { 0x000641, 0x00062c },
+ [0x00fcbf] = { 0x000641, 0x00062d },
+ [0x00fcc0] = { 0x000641, 0x00062e },
+ [0x00fcc1] = { 0x000641, 0x000645 },
+ [0x00fcc2] = { 0x000642, 0x00062d },
+ [0x00fcc3] = { 0x000642, 0x000645 },
+ [0x00fcc4] = { 0x000643, 0x00062c },
+ [0x00fcc5] = { 0x000643, 0x00062d },
+ [0x00fcc6] = { 0x000643, 0x00062e },
+ [0x00fcc7] = { 0x000643, 0x000644 },
+ [0x00fcc8] = { 0x000643, 0x000645 },
+ [0x00fcc9] = { 0x000644, 0x00062c },
+ [0x00fcca] = { 0x000644, 0x00062d },
+ [0x00fccb] = { 0x000644, 0x00062e },
+ [0x00fccc] = { 0x000644, 0x000645 },
+ [0x00fccd] = { 0x000644, 0x000647 },
+ [0x00fcce] = { 0x000645, 0x00062c },
+ [0x00fccf] = { 0x000645, 0x00062d },
+ [0x00fcd0] = { 0x000645, 0x00062e },
+ [0x00fcd1] = { 0x000645, 0x000645 },
+ [0x00fcd2] = { 0x000646, 0x00062c },
+ [0x00fcd3] = { 0x000646, 0x00062d },
+ [0x00fcd4] = { 0x000646, 0x00062e },
+ [0x00fcd5] = { 0x000646, 0x000645 },
+ [0x00fcd6] = { 0x000646, 0x000647 },
+ [0x00fcd7] = { 0x000647, 0x00062c },
+ [0x00fcd8] = { 0x000647, 0x000645 },
+ [0x00fcd9] = { 0x000647, 0x000670 },
+ [0x00fcda] = { 0x00064a, 0x00062c },
+ [0x00fcdb] = { 0x00064a, 0x00062d },
+ [0x00fcdc] = { 0x00064a, 0x00062e },
+ [0x00fcdd] = { 0x00064a, 0x000645 },
+ [0x00fcde] = { 0x00064a, 0x000647 },
+ [0x00fcdf] = { 0x00064a, 0x000654, 0x000645 },
+ [0x00fce0] = { 0x00064a, 0x000654, 0x000647 },
+ [0x00fce1] = { 0x000628, 0x000645 },
+ [0x00fce2] = { 0x000628, 0x000647 },
+ [0x00fce3] = { 0x00062a, 0x000645 },
+ [0x00fce4] = { 0x00062a, 0x000647 },
+ [0x00fce5] = { 0x00062b, 0x000645 },
+ [0x00fce6] = { 0x00062b, 0x000647 },
+ [0x00fce7] = { 0x000633, 0x000645 },
+ [0x00fce8] = { 0x000633, 0x000647 },
+ [0x00fce9] = { 0x000634, 0x000645 },
+ [0x00fcea] = { 0x000634, 0x000647 },
+ [0x00fceb] = { 0x000643, 0x000644 },
+ [0x00fcec] = { 0x000643, 0x000645 },
+ [0x00fced] = { 0x000644, 0x000645 },
+ [0x00fcee] = { 0x000646, 0x000645 },
+ [0x00fcef] = { 0x000646, 0x000647 },
+ [0x00fcf0] = { 0x00064a, 0x000645 },
+ [0x00fcf1] = { 0x00064a, 0x000647 },
+ [0x00fcf2] = { 0x000640, 0x00064e, 0x000651 },
+ [0x00fcf3] = { 0x000640, 0x00064f, 0x000651 },
+ [0x00fcf4] = { 0x000640, 0x000650, 0x000651 },
+ [0x00fcf5] = { 0x000637, 0x000649 },
+ [0x00fcf6] = { 0x000637, 0x00064a },
+ [0x00fcf7] = { 0x000639, 0x000649 },
+ [0x00fcf8] = { 0x000639, 0x00064a },
+ [0x00fcf9] = { 0x00063a, 0x000649 },
+ [0x00fcfa] = { 0x00063a, 0x00064a },
+ [0x00fcfb] = { 0x000633, 0x000649 },
+ [0x00fcfc] = { 0x000633, 0x00064a },
+ [0x00fcfd] = { 0x000634, 0x000649 },
+ [0x00fcfe] = { 0x000634, 0x00064a },
+ [0x00fcff] = { 0x00062d, 0x000649 },
+ [0x00fd00] = { 0x00062d, 0x00064a },
+ [0x00fd01] = { 0x00062c, 0x000649 },
+ [0x00fd02] = { 0x00062c, 0x00064a },
+ [0x00fd03] = { 0x00062e, 0x000649 },
+ [0x00fd04] = { 0x00062e, 0x00064a },
+ [0x00fd05] = { 0x000635, 0x000649 },
+ [0x00fd06] = { 0x000635, 0x00064a },
+ [0x00fd07] = { 0x000636, 0x000649 },
+ [0x00fd08] = { 0x000636, 0x00064a },
+ [0x00fd09] = { 0x000634, 0x00062c },
+ [0x00fd0a] = { 0x000634, 0x00062d },
+ [0x00fd0b] = { 0x000634, 0x00062e },
+ [0x00fd0c] = { 0x000634, 0x000645 },
+ [0x00fd0d] = { 0x000634, 0x000631 },
+ [0x00fd0e] = { 0x000633, 0x000631 },
+ [0x00fd0f] = { 0x000635, 0x000631 },
+ [0x00fd10] = { 0x000636, 0x000631 },
+ [0x00fd11] = { 0x000637, 0x000649 },
+ [0x00fd12] = { 0x000637, 0x00064a },
+ [0x00fd13] = { 0x000639, 0x000649 },
+ [0x00fd14] = { 0x000639, 0x00064a },
+ [0x00fd15] = { 0x00063a, 0x000649 },
+ [0x00fd16] = { 0x00063a, 0x00064a },
+ [0x00fd17] = { 0x000633, 0x000649 },
+ [0x00fd18] = { 0x000633, 0x00064a },
+ [0x00fd19] = { 0x000634, 0x000649 },
+ [0x00fd1a] = { 0x000634, 0x00064a },
+ [0x00fd1b] = { 0x00062d, 0x000649 },
+ [0x00fd1c] = { 0x00062d, 0x00064a },
+ [0x00fd1d] = { 0x00062c, 0x000649 },
+ [0x00fd1e] = { 0x00062c, 0x00064a },
+ [0x00fd1f] = { 0x00062e, 0x000649 },
+ [0x00fd20] = { 0x00062e, 0x00064a },
+ [0x00fd21] = { 0x000635, 0x000649 },
+ [0x00fd22] = { 0x000635, 0x00064a },
+ [0x00fd23] = { 0x000636, 0x000649 },
+ [0x00fd24] = { 0x000636, 0x00064a },
+ [0x00fd25] = { 0x000634, 0x00062c },
+ [0x00fd26] = { 0x000634, 0x00062d },
+ [0x00fd27] = { 0x000634, 0x00062e },
+ [0x00fd28] = { 0x000634, 0x000645 },
+ [0x00fd29] = { 0x000634, 0x000631 },
+ [0x00fd2a] = { 0x000633, 0x000631 },
+ [0x00fd2b] = { 0x000635, 0x000631 },
+ [0x00fd2c] = { 0x000636, 0x000631 },
+ [0x00fd2d] = { 0x000634, 0x00062c },
+ [0x00fd2e] = { 0x000634, 0x00062d },
+ [0x00fd2f] = { 0x000634, 0x00062e },
+ [0x00fd30] = { 0x000634, 0x000645 },
+ [0x00fd31] = { 0x000633, 0x000647 },
+ [0x00fd32] = { 0x000634, 0x000647 },
+ [0x00fd33] = { 0x000637, 0x000645 },
+ [0x00fd34] = { 0x000633, 0x00062c },
+ [0x00fd35] = { 0x000633, 0x00062d },
+ [0x00fd36] = { 0x000633, 0x00062e },
+ [0x00fd37] = { 0x000634, 0x00062c },
+ [0x00fd38] = { 0x000634, 0x00062d },
+ [0x00fd39] = { 0x000634, 0x00062e },
+ [0x00fd3a] = { 0x000637, 0x000645 },
+ [0x00fd3b] = { 0x000638, 0x000645 },
+ [0x00fd3c] = { 0x000627, 0x00064b },
+ [0x00fd3d] = { 0x000627, 0x00064b },
+ [0x00fd50] = { 0x00062a, 0x00062c, 0x000645 },
+ [0x00fd51] = { 0x00062a, 0x00062d, 0x00062c },
+ [0x00fd52] = { 0x00062a, 0x00062d, 0x00062c },
+ [0x00fd53] = { 0x00062a, 0x00062d, 0x000645 },
+ [0x00fd54] = { 0x00062a, 0x00062e, 0x000645 },
+ [0x00fd55] = { 0x00062a, 0x000645, 0x00062c },
+ [0x00fd56] = { 0x00062a, 0x000645, 0x00062d },
+ [0x00fd57] = { 0x00062a, 0x000645, 0x00062e },
+ [0x00fd58] = { 0x00062c, 0x000645, 0x00062d },
+ [0x00fd59] = { 0x00062c, 0x000645, 0x00062d },
+ [0x00fd5a] = { 0x00062d, 0x000645, 0x00064a },
+ [0x00fd5b] = { 0x00062d, 0x000645, 0x000649 },
+ [0x00fd5c] = { 0x000633, 0x00062d, 0x00062c },
+ [0x00fd5d] = { 0x000633, 0x00062c, 0x00062d },
+ [0x00fd5e] = { 0x000633, 0x00062c, 0x000649 },
+ [0x00fd5f] = { 0x000633, 0x000645, 0x00062d },
+ [0x00fd60] = { 0x000633, 0x000645, 0x00062d },
+ [0x00fd61] = { 0x000633, 0x000645, 0x00062c },
+ [0x00fd62] = { 0x000633, 0x000645, 0x000645 },
+ [0x00fd63] = { 0x000633, 0x000645, 0x000645 },
+ [0x00fd64] = { 0x000635, 0x00062d, 0x00062d },
+ [0x00fd65] = { 0x000635, 0x00062d, 0x00062d },
+ [0x00fd66] = { 0x000635, 0x000645, 0x000645 },
+ [0x00fd67] = { 0x000634, 0x00062d, 0x000645 },
+ [0x00fd68] = { 0x000634, 0x00062d, 0x000645 },
+ [0x00fd69] = { 0x000634, 0x00062c, 0x00064a },
+ [0x00fd6a] = { 0x000634, 0x000645, 0x00062e },
+ [0x00fd6b] = { 0x000634, 0x000645, 0x00062e },
+ [0x00fd6c] = { 0x000634, 0x000645, 0x000645 },
+ [0x00fd6d] = { 0x000634, 0x000645, 0x000645 },
+ [0x00fd6e] = { 0x000636, 0x00062d, 0x000649 },
+ [0x00fd6f] = { 0x000636, 0x00062e, 0x000645 },
+ [0x00fd70] = { 0x000636, 0x00062e, 0x000645 },
+ [0x00fd71] = { 0x000637, 0x000645, 0x00062d },
+ [0x00fd72] = { 0x000637, 0x000645, 0x00062d },
+ [0x00fd73] = { 0x000637, 0x000645, 0x000645 },
+ [0x00fd74] = { 0x000637, 0x000645, 0x00064a },
+ [0x00fd75] = { 0x000639, 0x00062c, 0x000645 },
+ [0x00fd76] = { 0x000639, 0x000645, 0x000645 },
+ [0x00fd77] = { 0x000639, 0x000645, 0x000645 },
+ [0x00fd78] = { 0x000639, 0x000645, 0x000649 },
+ [0x00fd79] = { 0x00063a, 0x000645, 0x000645 },
+ [0x00fd7a] = { 0x00063a, 0x000645, 0x00064a },
+ [0x00fd7b] = { 0x00063a, 0x000645, 0x000649 },
+ [0x00fd7c] = { 0x000641, 0x00062e, 0x000645 },
+ [0x00fd7d] = { 0x000641, 0x00062e, 0x000645 },
+ [0x00fd7e] = { 0x000642, 0x000645, 0x00062d },
+ [0x00fd7f] = { 0x000642, 0x000645, 0x000645 },
+ [0x00fd80] = { 0x000644, 0x00062d, 0x000645 },
+ [0x00fd81] = { 0x000644, 0x00062d, 0x00064a },
+ [0x00fd82] = { 0x000644, 0x00062d, 0x000649 },
+ [0x00fd83] = { 0x000644, 0x00062c, 0x00062c },
+ [0x00fd84] = { 0x000644, 0x00062c, 0x00062c },
+ [0x00fd85] = { 0x000644, 0x00062e, 0x000645 },
+ [0x00fd86] = { 0x000644, 0x00062e, 0x000645 },
+ [0x00fd87] = { 0x000644, 0x000645, 0x00062d },
+ [0x00fd88] = { 0x000644, 0x000645, 0x00062d },
+ [0x00fd89] = { 0x000645, 0x00062d, 0x00062c },
+ [0x00fd8a] = { 0x000645, 0x00062d, 0x000645 },
+ [0x00fd8b] = { 0x000645, 0x00062d, 0x00064a },
+ [0x00fd8c] = { 0x000645, 0x00062c, 0x00062d },
+ [0x00fd8d] = { 0x000645, 0x00062c, 0x000645 },
+ [0x00fd8e] = { 0x000645, 0x00062e, 0x00062c },
+ [0x00fd8f] = { 0x000645, 0x00062e, 0x000645 },
+ [0x00fd92] = { 0x000645, 0x00062c, 0x00062e },
+ [0x00fd93] = { 0x000647, 0x000645, 0x00062c },
+ [0x00fd94] = { 0x000647, 0x000645, 0x000645 },
+ [0x00fd95] = { 0x000646, 0x00062d, 0x000645 },
+ [0x00fd96] = { 0x000646, 0x00062d, 0x000649 },
+ [0x00fd97] = { 0x000646, 0x00062c, 0x000645 },
+ [0x00fd98] = { 0x000646, 0x00062c, 0x000645 },
+ [0x00fd99] = { 0x000646, 0x00062c, 0x000649 },
+ [0x00fd9a] = { 0x000646, 0x000645, 0x00064a },
+ [0x00fd9b] = { 0x000646, 0x000645, 0x000649 },
+ [0x00fd9c] = { 0x00064a, 0x000645, 0x000645 },
+ [0x00fd9d] = { 0x00064a, 0x000645, 0x000645 },
+ [0x00fd9e] = { 0x000628, 0x00062e, 0x00064a },
+ [0x00fd9f] = { 0x00062a, 0x00062c, 0x00064a },
+ [0x00fda0] = { 0x00062a, 0x00062c, 0x000649 },
+ [0x00fda1] = { 0x00062a, 0x00062e, 0x00064a },
+ [0x00fda2] = { 0x00062a, 0x00062e, 0x000649 },
+ [0x00fda3] = { 0x00062a, 0x000645, 0x00064a },
+ [0x00fda4] = { 0x00062a, 0x000645, 0x000649 },
+ [0x00fda5] = { 0x00062c, 0x000645, 0x00064a },
+ [0x00fda6] = { 0x00062c, 0x00062d, 0x000649 },
+ [0x00fda7] = { 0x00062c, 0x000645, 0x000649 },
+ [0x00fda8] = { 0x000633, 0x00062e, 0x000649 },
+ [0x00fda9] = { 0x000635, 0x00062d, 0x00064a },
+ [0x00fdaa] = { 0x000634, 0x00062d, 0x00064a },
+ [0x00fdab] = { 0x000636, 0x00062d, 0x00064a },
+ [0x00fdac] = { 0x000644, 0x00062c, 0x00064a },
+ [0x00fdad] = { 0x000644, 0x000645, 0x00064a },
+ [0x00fdae] = { 0x00064a, 0x00062d, 0x00064a },
+ [0x00fdaf] = { 0x00064a, 0x00062c, 0x00064a },
+ [0x00fdb0] = { 0x00064a, 0x000645, 0x00064a },
+ [0x00fdb1] = { 0x000645, 0x000645, 0x00064a },
+ [0x00fdb2] = { 0x000642, 0x000645, 0x00064a },
+ [0x00fdb3] = { 0x000646, 0x00062d, 0x00064a },
+ [0x00fdb4] = { 0x000642, 0x000645, 0x00062d },
+ [0x00fdb5] = { 0x000644, 0x00062d, 0x000645 },
+ [0x00fdb6] = { 0x000639, 0x000645, 0x00064a },
+ [0x00fdb7] = { 0x000643, 0x000645, 0x00064a },
+ [0x00fdb8] = { 0x000646, 0x00062c, 0x00062d },
+ [0x00fdb9] = { 0x000645, 0x00062e, 0x00064a },
+ [0x00fdba] = { 0x000644, 0x00062c, 0x000645 },
+ [0x00fdbb] = { 0x000643, 0x000645, 0x000645 },
+ [0x00fdbc] = { 0x000644, 0x00062c, 0x000645 },
+ [0x00fdbd] = { 0x000646, 0x00062c, 0x00062d },
+ [0x00fdbe] = { 0x00062c, 0x00062d, 0x00064a },
+ [0x00fdbf] = { 0x00062d, 0x00062c, 0x00064a },
+ [0x00fdc0] = { 0x000645, 0x00062c, 0x00064a },
+ [0x00fdc1] = { 0x000641, 0x000645, 0x00064a },
+ [0x00fdc2] = { 0x000628, 0x00062d, 0x00064a },
+ [0x00fdc3] = { 0x000643, 0x000645, 0x000645 },
+ [0x00fdc4] = { 0x000639, 0x00062c, 0x000645 },
+ [0x00fdc5] = { 0x000635, 0x000645, 0x000645 },
+ [0x00fdc6] = { 0x000633, 0x00062e, 0x00064a },
+ [0x00fdc7] = { 0x000646, 0x00062c, 0x00064a },
+ [0x00fdf0] = { 0x000635, 0x000644, 0x0006d2 },
+ [0x00fdf1] = { 0x000642, 0x000644, 0x0006d2 },
+ [0x00fdf2] = { 0x000627, 0x000644, 0x000644, 0x000647 },
+ [0x00fdf3] = { 0x000627, 0x000643, 0x000628, 0x000631 },
+ [0x00fdf4] = { 0x000645, 0x00062d, 0x000645, 0x00062f },
+ [0x00fdf5] = { 0x000635, 0x000644, 0x000639, 0x000645 },
+ [0x00fdf6] = { 0x000631, 0x000633, 0x000648, 0x000644 },
+ [0x00fdf7] = { 0x000639, 0x000644, 0x00064a, 0x000647 },
+ [0x00fdf8] = { 0x000648, 0x000633, 0x000644, 0x000645 },
+ [0x00fdf9] = { 0x000635, 0x000644, 0x000649 },
+ [0x00fdfa] = { 0x000635, 0x000644, 0x000649, 0x000020, 0x000627, 0x000644, 0x000644, 0x000647, 0x000020, 0x000639, 0x000644, 0x00064a, 0x000647, 0x000020, 0x000648, 0x000633, 0x000644, 0x000645 },
+ [0x00fdfb] = { 0x00062c, 0x000644, 0x000020, 0x00062c, 0x000644, 0x000627, 0x000644, 0x000647 },
+ [0x00fdfc] = { 0x000631, 0x0006cc, 0x000627, 0x000644 },
+ [0x00fe10] = { 0x00002c },
+ [0x00fe11] = { 0x003001 },
+ [0x00fe12] = { 0x003002 },
+ [0x00fe13] = { 0x00003a },
+ [0x00fe14] = { 0x00003b },
+ [0x00fe15] = { 0x000021 },
+ [0x00fe16] = { 0x00003f },
+ [0x00fe17] = { 0x003016 },
+ [0x00fe18] = { 0x003017 },
+ [0x00fe19] = { 0x00002e, 0x00002e, 0x00002e },
+ [0x00fe30] = { 0x00002e, 0x00002e },
+ [0x00fe31] = { 0x002014 },
+ [0x00fe32] = { 0x002013 },
+ [0x00fe33] = { 0x00005f },
+ [0x00fe34] = { 0x00005f },
+ [0x00fe35] = { 0x000028 },
+ [0x00fe36] = { 0x000029 },
+ [0x00fe37] = { 0x00007b },
+ [0x00fe38] = { 0x00007d },
+ [0x00fe39] = { 0x003014 },
+ [0x00fe3a] = { 0x003015 },
+ [0x00fe3b] = { 0x003010 },
+ [0x00fe3c] = { 0x003011 },
+ [0x00fe3d] = { 0x00300a },
+ [0x00fe3e] = { 0x00300b },
+ [0x00fe3f] = { 0x003008 },
+ [0x00fe40] = { 0x003009 },
+ [0x00fe41] = { 0x00300c },
+ [0x00fe42] = { 0x00300d },
+ [0x00fe43] = { 0x00300e },
+ [0x00fe44] = { 0x00300f },
+ [0x00fe47] = { 0x00005b },
+ [0x00fe48] = { 0x00005d },
+ [0x00fe49] = { 0x000020, 0x000305 },
+ [0x00fe4a] = { 0x000020, 0x000305 },
+ [0x00fe4b] = { 0x000020, 0x000305 },
+ [0x00fe4c] = { 0x000020, 0x000305 },
+ [0x00fe4d] = { 0x00005f },
+ [0x00fe4e] = { 0x00005f },
+ [0x00fe4f] = { 0x00005f },
+ [0x00fe50] = { 0x00002c },
+ [0x00fe51] = { 0x003001 },
+ [0x00fe52] = { 0x00002e },
+ [0x00fe54] = { 0x00003b },
+ [0x00fe55] = { 0x00003a },
+ [0x00fe56] = { 0x00003f },
+ [0x00fe57] = { 0x000021 },
+ [0x00fe58] = { 0x002014 },
+ [0x00fe59] = { 0x000028 },
+ [0x00fe5a] = { 0x000029 },
+ [0x00fe5b] = { 0x00007b },
+ [0x00fe5c] = { 0x00007d },
+ [0x00fe5d] = { 0x003014 },
+ [0x00fe5e] = { 0x003015 },
+ [0x00fe5f] = { 0x000023 },
+ [0x00fe60] = { 0x000026 },
+ [0x00fe61] = { 0x00002a },
+ [0x00fe62] = { 0x00002b },
+ [0x00fe63] = { 0x00002d },
+ [0x00fe64] = { 0x00003c },
+ [0x00fe65] = { 0x00003e },
+ [0x00fe66] = { 0x00003d },
+ [0x00fe68] = { 0x00005c },
+ [0x00fe69] = { 0x000024 },
+ [0x00fe6a] = { 0x000025 },
+ [0x00fe6b] = { 0x000040 },
+ [0x00fe70] = { 0x000020, 0x00064b },
+ [0x00fe71] = { 0x000640, 0x00064b },
+ [0x00fe72] = { 0x000020, 0x00064c },
+ [0x00fe74] = { 0x000020, 0x00064d },
+ [0x00fe76] = { 0x000020, 0x00064e },
+ [0x00fe77] = { 0x000640, 0x00064e },
+ [0x00fe78] = { 0x000020, 0x00064f },
+ [0x00fe79] = { 0x000640, 0x00064f },
+ [0x00fe7a] = { 0x000020, 0x000650 },
+ [0x00fe7b] = { 0x000640, 0x000650 },
+ [0x00fe7c] = { 0x000020, 0x000651 },
+ [0x00fe7d] = { 0x000640, 0x000651 },
+ [0x00fe7e] = { 0x000020, 0x000652 },
+ [0x00fe7f] = { 0x000640, 0x000652 },
+ [0x00fe80] = { 0x000621 },
+ [0x00fe81] = { 0x000627, 0x000653 },
+ [0x00fe82] = { 0x000627, 0x000653 },
+ [0x00fe83] = { 0x000627, 0x000654 },
+ [0x00fe84] = { 0x000627, 0x000654 },
+ [0x00fe85] = { 0x000648, 0x000654 },
+ [0x00fe86] = { 0x000648, 0x000654 },
+ [0x00fe87] = { 0x000627, 0x000655 },
+ [0x00fe88] = { 0x000627, 0x000655 },
+ [0x00fe89] = { 0x00064a, 0x000654 },
+ [0x00fe8a] = { 0x00064a, 0x000654 },
+ [0x00fe8b] = { 0x00064a, 0x000654 },
+ [0x00fe8c] = { 0x00064a, 0x000654 },
+ [0x00fe8d] = { 0x000627 },
+ [0x00fe8e] = { 0x000627 },
+ [0x00fe8f] = { 0x000628 },
+ [0x00fe90] = { 0x000628 },
+ [0x00fe91] = { 0x000628 },
+ [0x00fe92] = { 0x000628 },
+ [0x00fe93] = { 0x000629 },
+ [0x00fe94] = { 0x000629 },
+ [0x00fe95] = { 0x00062a },
+ [0x00fe96] = { 0x00062a },
+ [0x00fe97] = { 0x00062a },
+ [0x00fe98] = { 0x00062a },
+ [0x00fe99] = { 0x00062b },
+ [0x00fe9a] = { 0x00062b },
+ [0x00fe9b] = { 0x00062b },
+ [0x00fe9c] = { 0x00062b },
+ [0x00fe9d] = { 0x00062c },
+ [0x00fe9e] = { 0x00062c },
+ [0x00fe9f] = { 0x00062c },
+ [0x00fea0] = { 0x00062c },
+ [0x00fea1] = { 0x00062d },
+ [0x00fea2] = { 0x00062d },
+ [0x00fea3] = { 0x00062d },
+ [0x00fea4] = { 0x00062d },
+ [0x00fea5] = { 0x00062e },
+ [0x00fea6] = { 0x00062e },
+ [0x00fea7] = { 0x00062e },
+ [0x00fea8] = { 0x00062e },
+ [0x00fea9] = { 0x00062f },
+ [0x00feaa] = { 0x00062f },
+ [0x00feab] = { 0x000630 },
+ [0x00feac] = { 0x000630 },
+ [0x00fead] = { 0x000631 },
+ [0x00feae] = { 0x000631 },
+ [0x00feaf] = { 0x000632 },
+ [0x00feb0] = { 0x000632 },
+ [0x00feb1] = { 0x000633 },
+ [0x00feb2] = { 0x000633 },
+ [0x00feb3] = { 0x000633 },
+ [0x00feb4] = { 0x000633 },
+ [0x00feb5] = { 0x000634 },
+ [0x00feb6] = { 0x000634 },
+ [0x00feb7] = { 0x000634 },
+ [0x00feb8] = { 0x000634 },
+ [0x00feb9] = { 0x000635 },
+ [0x00feba] = { 0x000635 },
+ [0x00febb] = { 0x000635 },
+ [0x00febc] = { 0x000635 },
+ [0x00febd] = { 0x000636 },
+ [0x00febe] = { 0x000636 },
+ [0x00febf] = { 0x000636 },
+ [0x00fec0] = { 0x000636 },
+ [0x00fec1] = { 0x000637 },
+ [0x00fec2] = { 0x000637 },
+ [0x00fec3] = { 0x000637 },
+ [0x00fec4] = { 0x000637 },
+ [0x00fec5] = { 0x000638 },
+ [0x00fec6] = { 0x000638 },
+ [0x00fec7] = { 0x000638 },
+ [0x00fec8] = { 0x000638 },
+ [0x00fec9] = { 0x000639 },
+ [0x00feca] = { 0x000639 },
+ [0x00fecb] = { 0x000639 },
+ [0x00fecc] = { 0x000639 },
+ [0x00fecd] = { 0x00063a },
+ [0x00fece] = { 0x00063a },
+ [0x00fecf] = { 0x00063a },
+ [0x00fed0] = { 0x00063a },
+ [0x00fed1] = { 0x000641 },
+ [0x00fed2] = { 0x000641 },
+ [0x00fed3] = { 0x000641 },
+ [0x00fed4] = { 0x000641 },
+ [0x00fed5] = { 0x000642 },
+ [0x00fed6] = { 0x000642 },
+ [0x00fed7] = { 0x000642 },
+ [0x00fed8] = { 0x000642 },
+ [0x00fed9] = { 0x000643 },
+ [0x00feda] = { 0x000643 },
+ [0x00fedb] = { 0x000643 },
+ [0x00fedc] = { 0x000643 },
+ [0x00fedd] = { 0x000644 },
+ [0x00fede] = { 0x000644 },
+ [0x00fedf] = { 0x000644 },
+ [0x00fee0] = { 0x000644 },
+ [0x00fee1] = { 0x000645 },
+ [0x00fee2] = { 0x000645 },
+ [0x00fee3] = { 0x000645 },
+ [0x00fee4] = { 0x000645 },
+ [0x00fee5] = { 0x000646 },
+ [0x00fee6] = { 0x000646 },
+ [0x00fee7] = { 0x000646 },
+ [0x00fee8] = { 0x000646 },
+ [0x00fee9] = { 0x000647 },
+ [0x00feea] = { 0x000647 },
+ [0x00feeb] = { 0x000647 },
+ [0x00feec] = { 0x000647 },
+ [0x00feed] = { 0x000648 },
+ [0x00feee] = { 0x000648 },
+ [0x00feef] = { 0x000649 },
+ [0x00fef0] = { 0x000649 },
+ [0x00fef1] = { 0x00064a },
+ [0x00fef2] = { 0x00064a },
+ [0x00fef3] = { 0x00064a },
+ [0x00fef4] = { 0x00064a },
+ [0x00fef5] = { 0x000644, 0x000627, 0x000653 },
+ [0x00fef6] = { 0x000644, 0x000627, 0x000653 },
+ [0x00fef7] = { 0x000644, 0x000627, 0x000654 },
+ [0x00fef8] = { 0x000644, 0x000627, 0x000654 },
+ [0x00fef9] = { 0x000644, 0x000627, 0x000655 },
+ [0x00fefa] = { 0x000644, 0x000627, 0x000655 },
+ [0x00fefb] = { 0x000644, 0x000627 },
+ [0x00fefc] = { 0x000644, 0x000627 },
+ [0x00ff01] = { 0x000021 },
+ [0x00ff02] = { 0x000022 },
+ [0x00ff03] = { 0x000023 },
+ [0x00ff04] = { 0x000024 },
+ [0x00ff05] = { 0x000025 },
+ [0x00ff06] = { 0x000026 },
+ [0x00ff07] = { 0x000027 },
+ [0x00ff08] = { 0x000028 },
+ [0x00ff09] = { 0x000029 },
+ [0x00ff0a] = { 0x00002a },
+ [0x00ff0b] = { 0x00002b },
+ [0x00ff0c] = { 0x00002c },
+ [0x00ff0d] = { 0x00002d },
+ [0x00ff0e] = { 0x00002e },
+ [0x00ff0f] = { 0x00002f },
+ [0x00ff10] = { 0x000030 },
+ [0x00ff11] = { 0x000031 },
+ [0x00ff12] = { 0x000032 },
+ [0x00ff13] = { 0x000033 },
+ [0x00ff14] = { 0x000034 },
+ [0x00ff15] = { 0x000035 },
+ [0x00ff16] = { 0x000036 },
+ [0x00ff17] = { 0x000037 },
+ [0x00ff18] = { 0x000038 },
+ [0x00ff19] = { 0x000039 },
+ [0x00ff1a] = { 0x00003a },
+ [0x00ff1b] = { 0x00003b },
+ [0x00ff1c] = { 0x00003c },
+ [0x00ff1d] = { 0x00003d },
+ [0x00ff1e] = { 0x00003e },
+ [0x00ff1f] = { 0x00003f },
+ [0x00ff20] = { 0x000040 },
+ [0x00ff21] = { 0x000041 },
+ [0x00ff22] = { 0x000042 },
+ [0x00ff23] = { 0x000043 },
+ [0x00ff24] = { 0x000044 },
+ [0x00ff25] = { 0x000045 },
+ [0x00ff26] = { 0x000046 },
+ [0x00ff27] = { 0x000047 },
+ [0x00ff28] = { 0x000048 },
+ [0x00ff29] = { 0x000049 },
+ [0x00ff2a] = { 0x00004a },
+ [0x00ff2b] = { 0x00004b },
+ [0x00ff2c] = { 0x00004c },
+ [0x00ff2d] = { 0x00004d },
+ [0x00ff2e] = { 0x00004e },
+ [0x00ff2f] = { 0x00004f },
+ [0x00ff30] = { 0x000050 },
+ [0x00ff31] = { 0x000051 },
+ [0x00ff32] = { 0x000052 },
+ [0x00ff33] = { 0x000053 },
+ [0x00ff34] = { 0x000054 },
+ [0x00ff35] = { 0x000055 },
+ [0x00ff36] = { 0x000056 },
+ [0x00ff37] = { 0x000057 },
+ [0x00ff38] = { 0x000058 },
+ [0x00ff39] = { 0x000059 },
+ [0x00ff3a] = { 0x00005a },
+ [0x00ff3b] = { 0x00005b },
+ [0x00ff3c] = { 0x00005c },
+ [0x00ff3d] = { 0x00005d },
+ [0x00ff3e] = { 0x00005e },
+ [0x00ff3f] = { 0x00005f },
+ [0x00ff40] = { 0x000060 },
+ [0x00ff41] = { 0x000061 },
+ [0x00ff42] = { 0x000062 },
+ [0x00ff43] = { 0x000063 },
+ [0x00ff44] = { 0x000064 },
+ [0x00ff45] = { 0x000065 },
+ [0x00ff46] = { 0x000066 },
+ [0x00ff47] = { 0x000067 },
+ [0x00ff48] = { 0x000068 },
+ [0x00ff49] = { 0x000069 },
+ [0x00ff4a] = { 0x00006a },
+ [0x00ff4b] = { 0x00006b },
+ [0x00ff4c] = { 0x00006c },
+ [0x00ff4d] = { 0x00006d },
+ [0x00ff4e] = { 0x00006e },
+ [0x00ff4f] = { 0x00006f },
+ [0x00ff50] = { 0x000070 },
+ [0x00ff51] = { 0x000071 },
+ [0x00ff52] = { 0x000072 },
+ [0x00ff53] = { 0x000073 },
+ [0x00ff54] = { 0x000074 },
+ [0x00ff55] = { 0x000075 },
+ [0x00ff56] = { 0x000076 },
+ [0x00ff57] = { 0x000077 },
+ [0x00ff58] = { 0x000078 },
+ [0x00ff59] = { 0x000079 },
+ [0x00ff5a] = { 0x00007a },
+ [0x00ff5b] = { 0x00007b },
+ [0x00ff5c] = { 0x00007c },
+ [0x00ff5d] = { 0x00007d },
+ [0x00ff5e] = { 0x00007e },
+ [0x00ff5f] = { 0x002985 },
+ [0x00ff60] = { 0x002986 },
+ [0x00ff61] = { 0x003002 },
+ [0x00ff62] = { 0x00300c },
+ [0x00ff63] = { 0x00300d },
+ [0x00ff64] = { 0x003001 },
+ [0x00ff65] = { 0x0030fb },
+ [0x00ff66] = { 0x0030f2 },
+ [0x00ff67] = { 0x0030a1 },
+ [0x00ff68] = { 0x0030a3 },
+ [0x00ff69] = { 0x0030a5 },
+ [0x00ff6a] = { 0x0030a7 },
+ [0x00ff6b] = { 0x0030a9 },
+ [0x00ff6c] = { 0x0030e3 },
+ [0x00ff6d] = { 0x0030e5 },
+ [0x00ff6e] = { 0x0030e7 },
+ [0x00ff6f] = { 0x0030c3 },
+ [0x00ff70] = { 0x0030fc },
+ [0x00ff71] = { 0x0030a2 },
+ [0x00ff72] = { 0x0030a4 },
+ [0x00ff73] = { 0x0030a6 },
+ [0x00ff74] = { 0x0030a8 },
+ [0x00ff75] = { 0x0030aa },
+ [0x00ff76] = { 0x0030ab },
+ [0x00ff77] = { 0x0030ad },
+ [0x00ff78] = { 0x0030af },
+ [0x00ff79] = { 0x0030b1 },
+ [0x00ff7a] = { 0x0030b3 },
+ [0x00ff7b] = { 0x0030b5 },
+ [0x00ff7c] = { 0x0030b7 },
+ [0x00ff7d] = { 0x0030b9 },
+ [0x00ff7e] = { 0x0030bb },
+ [0x00ff7f] = { 0x0030bd },
+ [0x00ff80] = { 0x0030bf },
+ [0x00ff81] = { 0x0030c1 },
+ [0x00ff82] = { 0x0030c4 },
+ [0x00ff83] = { 0x0030c6 },
+ [0x00ff84] = { 0x0030c8 },
+ [0x00ff85] = { 0x0030ca },
+ [0x00ff86] = { 0x0030cb },
+ [0x00ff87] = { 0x0030cc },
+ [0x00ff88] = { 0x0030cd },
+ [0x00ff89] = { 0x0030ce },
+ [0x00ff8a] = { 0x0030cf },
+ [0x00ff8b] = { 0x0030d2 },
+ [0x00ff8c] = { 0x0030d5 },
+ [0x00ff8d] = { 0x0030d8 },
+ [0x00ff8e] = { 0x0030db },
+ [0x00ff8f] = { 0x0030de },
+ [0x00ff90] = { 0x0030df },
+ [0x00ff91] = { 0x0030e0 },
+ [0x00ff92] = { 0x0030e1 },
+ [0x00ff93] = { 0x0030e2 },
+ [0x00ff94] = { 0x0030e4 },
+ [0x00ff95] = { 0x0030e6 },
+ [0x00ff96] = { 0x0030e8 },
+ [0x00ff97] = { 0x0030e9 },
+ [0x00ff98] = { 0x0030ea },
+ [0x00ff99] = { 0x0030eb },
+ [0x00ff9a] = { 0x0030ec },
+ [0x00ff9b] = { 0x0030ed },
+ [0x00ff9c] = { 0x0030ef },
+ [0x00ff9d] = { 0x0030f3 },
+ [0x00ff9e] = { 0x003099 },
+ [0x00ff9f] = { 0x00309a },
+ [0x00ffa0] = { 0x001160 },
+ [0x00ffa1] = { 0x001100 },
+ [0x00ffa2] = { 0x001101 },
+ [0x00ffa3] = { 0x0011aa },
+ [0x00ffa4] = { 0x001102 },
+ [0x00ffa5] = { 0x0011ac },
+ [0x00ffa6] = { 0x0011ad },
+ [0x00ffa7] = { 0x001103 },
+ [0x00ffa8] = { 0x001104 },
+ [0x00ffa9] = { 0x001105 },
+ [0x00ffaa] = { 0x0011b0 },
+ [0x00ffab] = { 0x0011b1 },
+ [0x00ffac] = { 0x0011b2 },
+ [0x00ffad] = { 0x0011b3 },
+ [0x00ffae] = { 0x0011b4 },
+ [0x00ffaf] = { 0x0011b5 },
+ [0x00ffb0] = { 0x00111a },
+ [0x00ffb1] = { 0x001106 },
+ [0x00ffb2] = { 0x001107 },
+ [0x00ffb3] = { 0x001108 },
+ [0x00ffb4] = { 0x001121 },
+ [0x00ffb5] = { 0x001109 },
+ [0x00ffb6] = { 0x00110a },
+ [0x00ffb7] = { 0x00110b },
+ [0x00ffb8] = { 0x00110c },
+ [0x00ffb9] = { 0x00110d },
+ [0x00ffba] = { 0x00110e },
+ [0x00ffbb] = { 0x00110f },
+ [0x00ffbc] = { 0x001110 },
+ [0x00ffbd] = { 0x001111 },
+ [0x00ffbe] = { 0x001112 },
+ [0x00ffc2] = { 0x001161 },
+ [0x00ffc3] = { 0x001162 },
+ [0x00ffc4] = { 0x001163 },
+ [0x00ffc5] = { 0x001164 },
+ [0x00ffc6] = { 0x001165 },
+ [0x00ffc7] = { 0x001166 },
+ [0x00ffca] = { 0x001167 },
+ [0x00ffcb] = { 0x001168 },
+ [0x00ffcc] = { 0x001169 },
+ [0x00ffcd] = { 0x00116a },
+ [0x00ffce] = { 0x00116b },
+ [0x00ffcf] = { 0x00116c },
+ [0x00ffd2] = { 0x00116d },
+ [0x00ffd3] = { 0x00116e },
+ [0x00ffd4] = { 0x00116f },
+ [0x00ffd5] = { 0x001170 },
+ [0x00ffd6] = { 0x001171 },
+ [0x00ffd7] = { 0x001172 },
+ [0x00ffda] = { 0x001173 },
+ [0x00ffdb] = { 0x001174 },
+ [0x00ffdc] = { 0x001175 },
+ [0x00ffe0] = { 0x0000a2 },
+ [0x00ffe1] = { 0x0000a3 },
+ [0x00ffe2] = { 0x0000ac },
+ [0x00ffe3] = { 0x000020, 0x000304 },
+ [0x00ffe4] = { 0x0000a6 },
+ [0x00ffe5] = { 0x0000a5 },
+ [0x00ffe6] = { 0x0020a9 },
+ [0x00ffe8] = { 0x002502 },
+ [0x00ffe9] = { 0x002190 },
+ [0x00ffea] = { 0x002191 },
+ [0x00ffeb] = { 0x002192 },
+ [0x00ffec] = { 0x002193 },
+ [0x00ffed] = { 0x0025a0 },
+ [0x00ffee] = { 0x0025cb },
+ [0x01d400] = { 0x000041 },
+ [0x01d401] = { 0x000042 },
+ [0x01d402] = { 0x000043 },
+ [0x01d403] = { 0x000044 },
+ [0x01d404] = { 0x000045 },
+ [0x01d405] = { 0x000046 },
+ [0x01d406] = { 0x000047 },
+ [0x01d407] = { 0x000048 },
+ [0x01d408] = { 0x000049 },
+ [0x01d409] = { 0x00004a },
+ [0x01d40a] = { 0x00004b },
+ [0x01d40b] = { 0x00004c },
+ [0x01d40c] = { 0x00004d },
+ [0x01d40d] = { 0x00004e },
+ [0x01d40e] = { 0x00004f },
+ [0x01d40f] = { 0x000050 },
+ [0x01d410] = { 0x000051 },
+ [0x01d411] = { 0x000052 },
+ [0x01d412] = { 0x000053 },
+ [0x01d413] = { 0x000054 },
+ [0x01d414] = { 0x000055 },
+ [0x01d415] = { 0x000056 },
+ [0x01d416] = { 0x000057 },
+ [0x01d417] = { 0x000058 },
+ [0x01d418] = { 0x000059 },
+ [0x01d419] = { 0x00005a },
+ [0x01d41a] = { 0x000061 },
+ [0x01d41b] = { 0x000062 },
+ [0x01d41c] = { 0x000063 },
+ [0x01d41d] = { 0x000064 },
+ [0x01d41e] = { 0x000065 },
+ [0x01d41f] = { 0x000066 },
+ [0x01d420] = { 0x000067 },
+ [0x01d421] = { 0x000068 },
+ [0x01d422] = { 0x000069 },
+ [0x01d423] = { 0x00006a },
+ [0x01d424] = { 0x00006b },
+ [0x01d425] = { 0x00006c },
+ [0x01d426] = { 0x00006d },
+ [0x01d427] = { 0x00006e },
+ [0x01d428] = { 0x00006f },
+ [0x01d429] = { 0x000070 },
+ [0x01d42a] = { 0x000071 },
+ [0x01d42b] = { 0x000072 },
+ [0x01d42c] = { 0x000073 },
+ [0x01d42d] = { 0x000074 },
+ [0x01d42e] = { 0x000075 },
+ [0x01d42f] = { 0x000076 },
+ [0x01d430] = { 0x000077 },
+ [0x01d431] = { 0x000078 },
+ [0x01d432] = { 0x000079 },
+ [0x01d433] = { 0x00007a },
+ [0x01d434] = { 0x000041 },
+ [0x01d435] = { 0x000042 },
+ [0x01d436] = { 0x000043 },
+ [0x01d437] = { 0x000044 },
+ [0x01d438] = { 0x000045 },
+ [0x01d439] = { 0x000046 },
+ [0x01d43a] = { 0x000047 },
+ [0x01d43b] = { 0x000048 },
+ [0x01d43c] = { 0x000049 },
+ [0x01d43d] = { 0x00004a },
+ [0x01d43e] = { 0x00004b },
+ [0x01d43f] = { 0x00004c },
+ [0x01d440] = { 0x00004d },
+ [0x01d441] = { 0x00004e },
+ [0x01d442] = { 0x00004f },
+ [0x01d443] = { 0x000050 },
+ [0x01d444] = { 0x000051 },
+ [0x01d445] = { 0x000052 },
+ [0x01d446] = { 0x000053 },
+ [0x01d447] = { 0x000054 },
+ [0x01d448] = { 0x000055 },
+ [0x01d449] = { 0x000056 },
+ [0x01d44a] = { 0x000057 },
+ [0x01d44b] = { 0x000058 },
+ [0x01d44c] = { 0x000059 },
+ [0x01d44d] = { 0x00005a },
+ [0x01d44e] = { 0x000061 },
+ [0x01d44f] = { 0x000062 },
+ [0x01d450] = { 0x000063 },
+ [0x01d451] = { 0x000064 },
+ [0x01d452] = { 0x000065 },
+ [0x01d453] = { 0x000066 },
+ [0x01d454] = { 0x000067 },
+ [0x01d456] = { 0x000069 },
+ [0x01d457] = { 0x00006a },
+ [0x01d458] = { 0x00006b },
+ [0x01d459] = { 0x00006c },
+ [0x01d45a] = { 0x00006d },
+ [0x01d45b] = { 0x00006e },
+ [0x01d45c] = { 0x00006f },
+ [0x01d45d] = { 0x000070 },
+ [0x01d45e] = { 0x000071 },
+ [0x01d45f] = { 0x000072 },
+ [0x01d460] = { 0x000073 },
+ [0x01d461] = { 0x000074 },
+ [0x01d462] = { 0x000075 },
+ [0x01d463] = { 0x000076 },
+ [0x01d464] = { 0x000077 },
+ [0x01d465] = { 0x000078 },
+ [0x01d466] = { 0x000079 },
+ [0x01d467] = { 0x00007a },
+ [0x01d468] = { 0x000041 },
+ [0x01d469] = { 0x000042 },
+ [0x01d46a] = { 0x000043 },
+ [0x01d46b] = { 0x000044 },
+ [0x01d46c] = { 0x000045 },
+ [0x01d46d] = { 0x000046 },
+ [0x01d46e] = { 0x000047 },
+ [0x01d46f] = { 0x000048 },
+ [0x01d470] = { 0x000049 },
+ [0x01d471] = { 0x00004a },
+ [0x01d472] = { 0x00004b },
+ [0x01d473] = { 0x00004c },
+ [0x01d474] = { 0x00004d },
+ [0x01d475] = { 0x00004e },
+ [0x01d476] = { 0x00004f },
+ [0x01d477] = { 0x000050 },
+ [0x01d478] = { 0x000051 },
+ [0x01d479] = { 0x000052 },
+ [0x01d47a] = { 0x000053 },
+ [0x01d47b] = { 0x000054 },
+ [0x01d47c] = { 0x000055 },
+ [0x01d47d] = { 0x000056 },
+ [0x01d47e] = { 0x000057 },
+ [0x01d47f] = { 0x000058 },
+ [0x01d480] = { 0x000059 },
+ [0x01d481] = { 0x00005a },
+ [0x01d482] = { 0x000061 },
+ [0x01d483] = { 0x000062 },
+ [0x01d484] = { 0x000063 },
+ [0x01d485] = { 0x000064 },
+ [0x01d486] = { 0x000065 },
+ [0x01d487] = { 0x000066 },
+ [0x01d488] = { 0x000067 },
+ [0x01d489] = { 0x000068 },
+ [0x01d48a] = { 0x000069 },
+ [0x01d48b] = { 0x00006a },
+ [0x01d48c] = { 0x00006b },
+ [0x01d48d] = { 0x00006c },
+ [0x01d48e] = { 0x00006d },
+ [0x01d48f] = { 0x00006e },
+ [0x01d490] = { 0x00006f },
+ [0x01d491] = { 0x000070 },
+ [0x01d492] = { 0x000071 },
+ [0x01d493] = { 0x000072 },
+ [0x01d494] = { 0x000073 },
+ [0x01d495] = { 0x000074 },
+ [0x01d496] = { 0x000075 },
+ [0x01d497] = { 0x000076 },
+ [0x01d498] = { 0x000077 },
+ [0x01d499] = { 0x000078 },
+ [0x01d49a] = { 0x000079 },
+ [0x01d49b] = { 0x00007a },
+ [0x01d49c] = { 0x000041 },
+ [0x01d49e] = { 0x000043 },
+ [0x01d49f] = { 0x000044 },
+ [0x01d4a2] = { 0x000047 },
+ [0x01d4a5] = { 0x00004a },
+ [0x01d4a6] = { 0x00004b },
+ [0x01d4a9] = { 0x00004e },
+ [0x01d4aa] = { 0x00004f },
+ [0x01d4ab] = { 0x000050 },
+ [0x01d4ac] = { 0x000051 },
+ [0x01d4ae] = { 0x000053 },
+ [0x01d4af] = { 0x000054 },
+ [0x01d4b0] = { 0x000055 },
+ [0x01d4b1] = { 0x000056 },
+ [0x01d4b2] = { 0x000057 },
+ [0x01d4b3] = { 0x000058 },
+ [0x01d4b4] = { 0x000059 },
+ [0x01d4b5] = { 0x00005a },
+ [0x01d4b6] = { 0x000061 },
+ [0x01d4b7] = { 0x000062 },
+ [0x01d4b8] = { 0x000063 },
+ [0x01d4b9] = { 0x000064 },
+ [0x01d4bb] = { 0x000066 },
+ [0x01d4bd] = { 0x000068 },
+ [0x01d4be] = { 0x000069 },
+ [0x01d4bf] = { 0x00006a },
+ [0x01d4c0] = { 0x00006b },
+ [0x01d4c1] = { 0x00006c },
+ [0x01d4c2] = { 0x00006d },
+ [0x01d4c3] = { 0x00006e },
+ [0x01d4c5] = { 0x000070 },
+ [0x01d4c6] = { 0x000071 },
+ [0x01d4c7] = { 0x000072 },
+ [0x01d4c8] = { 0x000073 },
+ [0x01d4c9] = { 0x000074 },
+ [0x01d4ca] = { 0x000075 },
+ [0x01d4cb] = { 0x000076 },
+ [0x01d4cc] = { 0x000077 },
+ [0x01d4cd] = { 0x000078 },
+ [0x01d4ce] = { 0x000079 },
+ [0x01d4cf] = { 0x00007a },
+ [0x01d4d0] = { 0x000041 },
+ [0x01d4d1] = { 0x000042 },
+ [0x01d4d2] = { 0x000043 },
+ [0x01d4d3] = { 0x000044 },
+ [0x01d4d4] = { 0x000045 },
+ [0x01d4d5] = { 0x000046 },
+ [0x01d4d6] = { 0x000047 },
+ [0x01d4d7] = { 0x000048 },
+ [0x01d4d8] = { 0x000049 },
+ [0x01d4d9] = { 0x00004a },
+ [0x01d4da] = { 0x00004b },
+ [0x01d4db] = { 0x00004c },
+ [0x01d4dc] = { 0x00004d },
+ [0x01d4dd] = { 0x00004e },
+ [0x01d4de] = { 0x00004f },
+ [0x01d4df] = { 0x000050 },
+ [0x01d4e0] = { 0x000051 },
+ [0x01d4e1] = { 0x000052 },
+ [0x01d4e2] = { 0x000053 },
+ [0x01d4e3] = { 0x000054 },
+ [0x01d4e4] = { 0x000055 },
+ [0x01d4e5] = { 0x000056 },
+ [0x01d4e6] = { 0x000057 },
+ [0x01d4e7] = { 0x000058 },
+ [0x01d4e8] = { 0x000059 },
+ [0x01d4e9] = { 0x00005a },
+ [0x01d4ea] = { 0x000061 },
+ [0x01d4eb] = { 0x000062 },
+ [0x01d4ec] = { 0x000063 },
+ [0x01d4ed] = { 0x000064 },
+ [0x01d4ee] = { 0x000065 },
+ [0x01d4ef] = { 0x000066 },
+ [0x01d4f0] = { 0x000067 },
+ [0x01d4f1] = { 0x000068 },
+ [0x01d4f2] = { 0x000069 },
+ [0x01d4f3] = { 0x00006a },
+ [0x01d4f4] = { 0x00006b },
+ [0x01d4f5] = { 0x00006c },
+ [0x01d4f6] = { 0x00006d },
+ [0x01d4f7] = { 0x00006e },
+ [0x01d4f8] = { 0x00006f },
+ [0x01d4f9] = { 0x000070 },
+ [0x01d4fa] = { 0x000071 },
+ [0x01d4fb] = { 0x000072 },
+ [0x01d4fc] = { 0x000073 },
+ [0x01d4fd] = { 0x000074 },
+ [0x01d4fe] = { 0x000075 },
+ [0x01d4ff] = { 0x000076 },
+ [0x01d500] = { 0x000077 },
+ [0x01d501] = { 0x000078 },
+ [0x01d502] = { 0x000079 },
+ [0x01d503] = { 0x00007a },
+ [0x01d504] = { 0x000041 },
+ [0x01d505] = { 0x000042 },
+ [0x01d507] = { 0x000044 },
+ [0x01d508] = { 0x000045 },
+ [0x01d509] = { 0x000046 },
+ [0x01d50a] = { 0x000047 },
+ [0x01d50d] = { 0x00004a },
+ [0x01d50e] = { 0x00004b },
+ [0x01d50f] = { 0x00004c },
+ [0x01d510] = { 0x00004d },
+ [0x01d511] = { 0x00004e },
+ [0x01d512] = { 0x00004f },
+ [0x01d513] = { 0x000050 },
+ [0x01d514] = { 0x000051 },
+ [0x01d516] = { 0x000053 },
+ [0x01d517] = { 0x000054 },
+ [0x01d518] = { 0x000055 },
+ [0x01d519] = { 0x000056 },
+ [0x01d51a] = { 0x000057 },
+ [0x01d51b] = { 0x000058 },
+ [0x01d51c] = { 0x000059 },
+ [0x01d51e] = { 0x000061 },
+ [0x01d51f] = { 0x000062 },
+ [0x01d520] = { 0x000063 },
+ [0x01d521] = { 0x000064 },
+ [0x01d522] = { 0x000065 },
+ [0x01d523] = { 0x000066 },
+ [0x01d524] = { 0x000067 },
+ [0x01d525] = { 0x000068 },
+ [0x01d526] = { 0x000069 },
+ [0x01d527] = { 0x00006a },
+ [0x01d528] = { 0x00006b },
+ [0x01d529] = { 0x00006c },
+ [0x01d52a] = { 0x00006d },
+ [0x01d52b] = { 0x00006e },
+ [0x01d52c] = { 0x00006f },
+ [0x01d52d] = { 0x000070 },
+ [0x01d52e] = { 0x000071 },
+ [0x01d52f] = { 0x000072 },
+ [0x01d530] = { 0x000073 },
+ [0x01d531] = { 0x000074 },
+ [0x01d532] = { 0x000075 },
+ [0x01d533] = { 0x000076 },
+ [0x01d534] = { 0x000077 },
+ [0x01d535] = { 0x000078 },
+ [0x01d536] = { 0x000079 },
+ [0x01d537] = { 0x00007a },
+ [0x01d538] = { 0x000041 },
+ [0x01d539] = { 0x000042 },
+ [0x01d53b] = { 0x000044 },
+ [0x01d53c] = { 0x000045 },
+ [0x01d53d] = { 0x000046 },
+ [0x01d53e] = { 0x000047 },
+ [0x01d540] = { 0x000049 },
+ [0x01d541] = { 0x00004a },
+ [0x01d542] = { 0x00004b },
+ [0x01d543] = { 0x00004c },
+ [0x01d544] = { 0x00004d },
+ [0x01d546] = { 0x00004f },
+ [0x01d54a] = { 0x000053 },
+ [0x01d54b] = { 0x000054 },
+ [0x01d54c] = { 0x000055 },
+ [0x01d54d] = { 0x000056 },
+ [0x01d54e] = { 0x000057 },
+ [0x01d54f] = { 0x000058 },
+ [0x01d550] = { 0x000059 },
+ [0x01d552] = { 0x000061 },
+ [0x01d553] = { 0x000062 },
+ [0x01d554] = { 0x000063 },
+ [0x01d555] = { 0x000064 },
+ [0x01d556] = { 0x000065 },
+ [0x01d557] = { 0x000066 },
+ [0x01d558] = { 0x000067 },
+ [0x01d559] = { 0x000068 },
+ [0x01d55a] = { 0x000069 },
+ [0x01d55b] = { 0x00006a },
+ [0x01d55c] = { 0x00006b },
+ [0x01d55d] = { 0x00006c },
+ [0x01d55e] = { 0x00006d },
+ [0x01d55f] = { 0x00006e },
+ [0x01d560] = { 0x00006f },
+ [0x01d561] = { 0x000070 },
+ [0x01d562] = { 0x000071 },
+ [0x01d563] = { 0x000072 },
+ [0x01d564] = { 0x000073 },
+ [0x01d565] = { 0x000074 },
+ [0x01d566] = { 0x000075 },
+ [0x01d567] = { 0x000076 },
+ [0x01d568] = { 0x000077 },
+ [0x01d569] = { 0x000078 },
+ [0x01d56a] = { 0x000079 },
+ [0x01d56b] = { 0x00007a },
+ [0x01d56c] = { 0x000041 },
+ [0x01d56d] = { 0x000042 },
+ [0x01d56e] = { 0x000043 },
+ [0x01d56f] = { 0x000044 },
+ [0x01d570] = { 0x000045 },
+ [0x01d571] = { 0x000046 },
+ [0x01d572] = { 0x000047 },
+ [0x01d573] = { 0x000048 },
+ [0x01d574] = { 0x000049 },
+ [0x01d575] = { 0x00004a },
+ [0x01d576] = { 0x00004b },
+ [0x01d577] = { 0x00004c },
+ [0x01d578] = { 0x00004d },
+ [0x01d579] = { 0x00004e },
+ [0x01d57a] = { 0x00004f },
+ [0x01d57b] = { 0x000050 },
+ [0x01d57c] = { 0x000051 },
+ [0x01d57d] = { 0x000052 },
+ [0x01d57e] = { 0x000053 },
+ [0x01d57f] = { 0x000054 },
+ [0x01d580] = { 0x000055 },
+ [0x01d581] = { 0x000056 },
+ [0x01d582] = { 0x000057 },
+ [0x01d583] = { 0x000058 },
+ [0x01d584] = { 0x000059 },
+ [0x01d585] = { 0x00005a },
+ [0x01d586] = { 0x000061 },
+ [0x01d587] = { 0x000062 },
+ [0x01d588] = { 0x000063 },
+ [0x01d589] = { 0x000064 },
+ [0x01d58a] = { 0x000065 },
+ [0x01d58b] = { 0x000066 },
+ [0x01d58c] = { 0x000067 },
+ [0x01d58d] = { 0x000068 },
+ [0x01d58e] = { 0x000069 },
+ [0x01d58f] = { 0x00006a },
+ [0x01d590] = { 0x00006b },
+ [0x01d591] = { 0x00006c },
+ [0x01d592] = { 0x00006d },
+ [0x01d593] = { 0x00006e },
+ [0x01d594] = { 0x00006f },
+ [0x01d595] = { 0x000070 },
+ [0x01d596] = { 0x000071 },
+ [0x01d597] = { 0x000072 },
+ [0x01d598] = { 0x000073 },
+ [0x01d599] = { 0x000074 },
+ [0x01d59a] = { 0x000075 },
+ [0x01d59b] = { 0x000076 },
+ [0x01d59c] = { 0x000077 },
+ [0x01d59d] = { 0x000078 },
+ [0x01d59e] = { 0x000079 },
+ [0x01d59f] = { 0x00007a },
+ [0x01d5a0] = { 0x000041 },
+ [0x01d5a1] = { 0x000042 },
+ [0x01d5a2] = { 0x000043 },
+ [0x01d5a3] = { 0x000044 },
+ [0x01d5a4] = { 0x000045 },
+ [0x01d5a5] = { 0x000046 },
+ [0x01d5a6] = { 0x000047 },
+ [0x01d5a7] = { 0x000048 },
+ [0x01d5a8] = { 0x000049 },
+ [0x01d5a9] = { 0x00004a },
+ [0x01d5aa] = { 0x00004b },
+ [0x01d5ab] = { 0x00004c },
+ [0x01d5ac] = { 0x00004d },
+ [0x01d5ad] = { 0x00004e },
+ [0x01d5ae] = { 0x00004f },
+ [0x01d5af] = { 0x000050 },
+ [0x01d5b0] = { 0x000051 },
+ [0x01d5b1] = { 0x000052 },
+ [0x01d5b2] = { 0x000053 },
+ [0x01d5b3] = { 0x000054 },
+ [0x01d5b4] = { 0x000055 },
+ [0x01d5b5] = { 0x000056 },
+ [0x01d5b6] = { 0x000057 },
+ [0x01d5b7] = { 0x000058 },
+ [0x01d5b8] = { 0x000059 },
+ [0x01d5b9] = { 0x00005a },
+ [0x01d5ba] = { 0x000061 },
+ [0x01d5bb] = { 0x000062 },
+ [0x01d5bc] = { 0x000063 },
+ [0x01d5bd] = { 0x000064 },
+ [0x01d5be] = { 0x000065 },
+ [0x01d5bf] = { 0x000066 },
+ [0x01d5c0] = { 0x000067 },
+ [0x01d5c1] = { 0x000068 },
+ [0x01d5c2] = { 0x000069 },
+ [0x01d5c3] = { 0x00006a },
+ [0x01d5c4] = { 0x00006b },
+ [0x01d5c5] = { 0x00006c },
+ [0x01d5c6] = { 0x00006d },
+ [0x01d5c7] = { 0x00006e },
+ [0x01d5c8] = { 0x00006f },
+ [0x01d5c9] = { 0x000070 },
+ [0x01d5ca] = { 0x000071 },
+ [0x01d5cb] = { 0x000072 },
+ [0x01d5cc] = { 0x000073 },
+ [0x01d5cd] = { 0x000074 },
+ [0x01d5ce] = { 0x000075 },
+ [0x01d5cf] = { 0x000076 },
+ [0x01d5d0] = { 0x000077 },
+ [0x01d5d1] = { 0x000078 },
+ [0x01d5d2] = { 0x000079 },
+ [0x01d5d3] = { 0x00007a },
+ [0x01d5d4] = { 0x000041 },
+ [0x01d5d5] = { 0x000042 },
+ [0x01d5d6] = { 0x000043 },
+ [0x01d5d7] = { 0x000044 },
+ [0x01d5d8] = { 0x000045 },
+ [0x01d5d9] = { 0x000046 },
+ [0x01d5da] = { 0x000047 },
+ [0x01d5db] = { 0x000048 },
+ [0x01d5dc] = { 0x000049 },
+ [0x01d5dd] = { 0x00004a },
+ [0x01d5de] = { 0x00004b },
+ [0x01d5df] = { 0x00004c },
+ [0x01d5e0] = { 0x00004d },
+ [0x01d5e1] = { 0x00004e },
+ [0x01d5e2] = { 0x00004f },
+ [0x01d5e3] = { 0x000050 },
+ [0x01d5e4] = { 0x000051 },
+ [0x01d5e5] = { 0x000052 },
+ [0x01d5e6] = { 0x000053 },
+ [0x01d5e7] = { 0x000054 },
+ [0x01d5e8] = { 0x000055 },
+ [0x01d5e9] = { 0x000056 },
+ [0x01d5ea] = { 0x000057 },
+ [0x01d5eb] = { 0x000058 },
+ [0x01d5ec] = { 0x000059 },
+ [0x01d5ed] = { 0x00005a },
+ [0x01d5ee] = { 0x000061 },
+ [0x01d5ef] = { 0x000062 },
+ [0x01d5f0] = { 0x000063 },
+ [0x01d5f1] = { 0x000064 },
+ [0x01d5f2] = { 0x000065 },
+ [0x01d5f3] = { 0x000066 },
+ [0x01d5f4] = { 0x000067 },
+ [0x01d5f5] = { 0x000068 },
+ [0x01d5f6] = { 0x000069 },
+ [0x01d5f7] = { 0x00006a },
+ [0x01d5f8] = { 0x00006b },
+ [0x01d5f9] = { 0x00006c },
+ [0x01d5fa] = { 0x00006d },
+ [0x01d5fb] = { 0x00006e },
+ [0x01d5fc] = { 0x00006f },
+ [0x01d5fd] = { 0x000070 },
+ [0x01d5fe] = { 0x000071 },
+ [0x01d5ff] = { 0x000072 },
+ [0x01d600] = { 0x000073 },
+ [0x01d601] = { 0x000074 },
+ [0x01d602] = { 0x000075 },
+ [0x01d603] = { 0x000076 },
+ [0x01d604] = { 0x000077 },
+ [0x01d605] = { 0x000078 },
+ [0x01d606] = { 0x000079 },
+ [0x01d607] = { 0x00007a },
+ [0x01d608] = { 0x000041 },
+ [0x01d609] = { 0x000042 },
+ [0x01d60a] = { 0x000043 },
+ [0x01d60b] = { 0x000044 },
+ [0x01d60c] = { 0x000045 },
+ [0x01d60d] = { 0x000046 },
+ [0x01d60e] = { 0x000047 },
+ [0x01d60f] = { 0x000048 },
+ [0x01d610] = { 0x000049 },
+ [0x01d611] = { 0x00004a },
+ [0x01d612] = { 0x00004b },
+ [0x01d613] = { 0x00004c },
+ [0x01d614] = { 0x00004d },
+ [0x01d615] = { 0x00004e },
+ [0x01d616] = { 0x00004f },
+ [0x01d617] = { 0x000050 },
+ [0x01d618] = { 0x000051 },
+ [0x01d619] = { 0x000052 },
+ [0x01d61a] = { 0x000053 },
+ [0x01d61b] = { 0x000054 },
+ [0x01d61c] = { 0x000055 },
+ [0x01d61d] = { 0x000056 },
+ [0x01d61e] = { 0x000057 },
+ [0x01d61f] = { 0x000058 },
+ [0x01d620] = { 0x000059 },
+ [0x01d621] = { 0x00005a },
+ [0x01d622] = { 0x000061 },
+ [0x01d623] = { 0x000062 },
+ [0x01d624] = { 0x000063 },
+ [0x01d625] = { 0x000064 },
+ [0x01d626] = { 0x000065 },
+ [0x01d627] = { 0x000066 },
+ [0x01d628] = { 0x000067 },
+ [0x01d629] = { 0x000068 },
+ [0x01d62a] = { 0x000069 },
+ [0x01d62b] = { 0x00006a },
+ [0x01d62c] = { 0x00006b },
+ [0x01d62d] = { 0x00006c },
+ [0x01d62e] = { 0x00006d },
+ [0x01d62f] = { 0x00006e },
+ [0x01d630] = { 0x00006f },
+ [0x01d631] = { 0x000070 },
+ [0x01d632] = { 0x000071 },
+ [0x01d633] = { 0x000072 },
+ [0x01d634] = { 0x000073 },
+ [0x01d635] = { 0x000074 },
+ [0x01d636] = { 0x000075 },
+ [0x01d637] = { 0x000076 },
+ [0x01d638] = { 0x000077 },
+ [0x01d639] = { 0x000078 },
+ [0x01d63a] = { 0x000079 },
+ [0x01d63b] = { 0x00007a },
+ [0x01d63c] = { 0x000041 },
+ [0x01d63d] = { 0x000042 },
+ [0x01d63e] = { 0x000043 },
+ [0x01d63f] = { 0x000044 },
+ [0x01d640] = { 0x000045 },
+ [0x01d641] = { 0x000046 },
+ [0x01d642] = { 0x000047 },
+ [0x01d643] = { 0x000048 },
+ [0x01d644] = { 0x000049 },
+ [0x01d645] = { 0x00004a },
+ [0x01d646] = { 0x00004b },
+ [0x01d647] = { 0x00004c },
+ [0x01d648] = { 0x00004d },
+ [0x01d649] = { 0x00004e },
+ [0x01d64a] = { 0x00004f },
+ [0x01d64b] = { 0x000050 },
+ [0x01d64c] = { 0x000051 },
+ [0x01d64d] = { 0x000052 },
+ [0x01d64e] = { 0x000053 },
+ [0x01d64f] = { 0x000054 },
+ [0x01d650] = { 0x000055 },
+ [0x01d651] = { 0x000056 },
+ [0x01d652] = { 0x000057 },
+ [0x01d653] = { 0x000058 },
+ [0x01d654] = { 0x000059 },
+ [0x01d655] = { 0x00005a },
+ [0x01d656] = { 0x000061 },
+ [0x01d657] = { 0x000062 },
+ [0x01d658] = { 0x000063 },
+ [0x01d659] = { 0x000064 },
+ [0x01d65a] = { 0x000065 },
+ [0x01d65b] = { 0x000066 },
+ [0x01d65c] = { 0x000067 },
+ [0x01d65d] = { 0x000068 },
+ [0x01d65e] = { 0x000069 },
+ [0x01d65f] = { 0x00006a },
+ [0x01d660] = { 0x00006b },
+ [0x01d661] = { 0x00006c },
+ [0x01d662] = { 0x00006d },
+ [0x01d663] = { 0x00006e },
+ [0x01d664] = { 0x00006f },
+ [0x01d665] = { 0x000070 },
+ [0x01d666] = { 0x000071 },
+ [0x01d667] = { 0x000072 },
+ [0x01d668] = { 0x000073 },
+ [0x01d669] = { 0x000074 },
+ [0x01d66a] = { 0x000075 },
+ [0x01d66b] = { 0x000076 },
+ [0x01d66c] = { 0x000077 },
+ [0x01d66d] = { 0x000078 },
+ [0x01d66e] = { 0x000079 },
+ [0x01d66f] = { 0x00007a },
+ [0x01d670] = { 0x000041 },
+ [0x01d671] = { 0x000042 },
+ [0x01d672] = { 0x000043 },
+ [0x01d673] = { 0x000044 },
+ [0x01d674] = { 0x000045 },
+ [0x01d675] = { 0x000046 },
+ [0x01d676] = { 0x000047 },
+ [0x01d677] = { 0x000048 },
+ [0x01d678] = { 0x000049 },
+ [0x01d679] = { 0x00004a },
+ [0x01d67a] = { 0x00004b },
+ [0x01d67b] = { 0x00004c },
+ [0x01d67c] = { 0x00004d },
+ [0x01d67d] = { 0x00004e },
+ [0x01d67e] = { 0x00004f },
+ [0x01d67f] = { 0x000050 },
+ [0x01d680] = { 0x000051 },
+ [0x01d681] = { 0x000052 },
+ [0x01d682] = { 0x000053 },
+ [0x01d683] = { 0x000054 },
+ [0x01d684] = { 0x000055 },
+ [0x01d685] = { 0x000056 },
+ [0x01d686] = { 0x000057 },
+ [0x01d687] = { 0x000058 },
+ [0x01d688] = { 0x000059 },
+ [0x01d689] = { 0x00005a },
+ [0x01d68a] = { 0x000061 },
+ [0x01d68b] = { 0x000062 },
+ [0x01d68c] = { 0x000063 },
+ [0x01d68d] = { 0x000064 },
+ [0x01d68e] = { 0x000065 },
+ [0x01d68f] = { 0x000066 },
+ [0x01d690] = { 0x000067 },
+ [0x01d691] = { 0x000068 },
+ [0x01d692] = { 0x000069 },
+ [0x01d693] = { 0x00006a },
+ [0x01d694] = { 0x00006b },
+ [0x01d695] = { 0x00006c },
+ [0x01d696] = { 0x00006d },
+ [0x01d697] = { 0x00006e },
+ [0x01d698] = { 0x00006f },
+ [0x01d699] = { 0x000070 },
+ [0x01d69a] = { 0x000071 },
+ [0x01d69b] = { 0x000072 },
+ [0x01d69c] = { 0x000073 },
+ [0x01d69d] = { 0x000074 },
+ [0x01d69e] = { 0x000075 },
+ [0x01d69f] = { 0x000076 },
+ [0x01d6a0] = { 0x000077 },
+ [0x01d6a1] = { 0x000078 },
+ [0x01d6a2] = { 0x000079 },
+ [0x01d6a3] = { 0x00007a },
+ [0x01d6a4] = { 0x000131 },
+ [0x01d6a5] = { 0x000237 },
+ [0x01d6a8] = { 0x000391 },
+ [0x01d6a9] = { 0x000392 },
+ [0x01d6aa] = { 0x000393 },
+ [0x01d6ab] = { 0x000394 },
+ [0x01d6ac] = { 0x000395 },
+ [0x01d6ad] = { 0x000396 },
+ [0x01d6ae] = { 0x000397 },
+ [0x01d6af] = { 0x000398 },
+ [0x01d6b0] = { 0x000399 },
+ [0x01d6b1] = { 0x00039a },
+ [0x01d6b2] = { 0x00039b },
+ [0x01d6b3] = { 0x00039c },
+ [0x01d6b4] = { 0x00039d },
+ [0x01d6b5] = { 0x00039e },
+ [0x01d6b6] = { 0x00039f },
+ [0x01d6b7] = { 0x0003a0 },
+ [0x01d6b8] = { 0x0003a1 },
+ [0x01d6b9] = { 0x000398 },
+ [0x01d6ba] = { 0x0003a3 },
+ [0x01d6bb] = { 0x0003a4 },
+ [0x01d6bc] = { 0x0003a5 },
+ [0x01d6bd] = { 0x0003a6 },
+ [0x01d6be] = { 0x0003a7 },
+ [0x01d6bf] = { 0x0003a8 },
+ [0x01d6c0] = { 0x0003a9 },
+ [0x01d6c1] = { 0x002207 },
+ [0x01d6c2] = { 0x0003b1 },
+ [0x01d6c3] = { 0x0003b2 },
+ [0x01d6c4] = { 0x0003b3 },
+ [0x01d6c5] = { 0x0003b4 },
+ [0x01d6c6] = { 0x0003b5 },
+ [0x01d6c7] = { 0x0003b6 },
+ [0x01d6c8] = { 0x0003b7 },
+ [0x01d6c9] = { 0x0003b8 },
+ [0x01d6ca] = { 0x0003b9 },
+ [0x01d6cb] = { 0x0003ba },
+ [0x01d6cc] = { 0x0003bb },
+ [0x01d6cd] = { 0x0003bc },
+ [0x01d6ce] = { 0x0003bd },
+ [0x01d6cf] = { 0x0003be },
+ [0x01d6d0] = { 0x0003bf },
+ [0x01d6d1] = { 0x0003c0 },
+ [0x01d6d2] = { 0x0003c1 },
+ [0x01d6d3] = { 0x0003c2 },
+ [0x01d6d4] = { 0x0003c3 },
+ [0x01d6d5] = { 0x0003c4 },
+ [0x01d6d6] = { 0x0003c5 },
+ [0x01d6d7] = { 0x0003c6 },
+ [0x01d6d8] = { 0x0003c7 },
+ [0x01d6d9] = { 0x0003c8 },
+ [0x01d6da] = { 0x0003c9 },
+ [0x01d6db] = { 0x002202 },
+ [0x01d6dc] = { 0x0003b5 },
+ [0x01d6dd] = { 0x0003b8 },
+ [0x01d6de] = { 0x0003ba },
+ [0x01d6df] = { 0x0003c6 },
+ [0x01d6e0] = { 0x0003c1 },
+ [0x01d6e1] = { 0x0003c0 },
+ [0x01d6e2] = { 0x000391 },
+ [0x01d6e3] = { 0x000392 },
+ [0x01d6e4] = { 0x000393 },
+ [0x01d6e5] = { 0x000394 },
+ [0x01d6e6] = { 0x000395 },
+ [0x01d6e7] = { 0x000396 },
+ [0x01d6e8] = { 0x000397 },
+ [0x01d6e9] = { 0x000398 },
+ [0x01d6ea] = { 0x000399 },
+ [0x01d6eb] = { 0x00039a },
+ [0x01d6ec] = { 0x00039b },
+ [0x01d6ed] = { 0x00039c },
+ [0x01d6ee] = { 0x00039d },
+ [0x01d6ef] = { 0x00039e },
+ [0x01d6f0] = { 0x00039f },
+ [0x01d6f1] = { 0x0003a0 },
+ [0x01d6f2] = { 0x0003a1 },
+ [0x01d6f3] = { 0x000398 },
+ [0x01d6f4] = { 0x0003a3 },
+ [0x01d6f5] = { 0x0003a4 },
+ [0x01d6f6] = { 0x0003a5 },
+ [0x01d6f7] = { 0x0003a6 },
+ [0x01d6f8] = { 0x0003a7 },
+ [0x01d6f9] = { 0x0003a8 },
+ [0x01d6fa] = { 0x0003a9 },
+ [0x01d6fb] = { 0x002207 },
+ [0x01d6fc] = { 0x0003b1 },
+ [0x01d6fd] = { 0x0003b2 },
+ [0x01d6fe] = { 0x0003b3 },
+ [0x01d6ff] = { 0x0003b4 },
+ [0x01d700] = { 0x0003b5 },
+ [0x01d701] = { 0x0003b6 },
+ [0x01d702] = { 0x0003b7 },
+ [0x01d703] = { 0x0003b8 },
+ [0x01d704] = { 0x0003b9 },
+ [0x01d705] = { 0x0003ba },
+ [0x01d706] = { 0x0003bb },
+ [0x01d707] = { 0x0003bc },
+ [0x01d708] = { 0x0003bd },
+ [0x01d709] = { 0x0003be },
+ [0x01d70a] = { 0x0003bf },
+ [0x01d70b] = { 0x0003c0 },
+ [0x01d70c] = { 0x0003c1 },
+ [0x01d70d] = { 0x0003c2 },
+ [0x01d70e] = { 0x0003c3 },
+ [0x01d70f] = { 0x0003c4 },
+ [0x01d710] = { 0x0003c5 },
+ [0x01d711] = { 0x0003c6 },
+ [0x01d712] = { 0x0003c7 },
+ [0x01d713] = { 0x0003c8 },
+ [0x01d714] = { 0x0003c9 },
+ [0x01d715] = { 0x002202 },
+ [0x01d716] = { 0x0003b5 },
+ [0x01d717] = { 0x0003b8 },
+ [0x01d718] = { 0x0003ba },
+ [0x01d719] = { 0x0003c6 },
+ [0x01d71a] = { 0x0003c1 },
+ [0x01d71b] = { 0x0003c0 },
+ [0x01d71c] = { 0x000391 },
+ [0x01d71d] = { 0x000392 },
+ [0x01d71e] = { 0x000393 },
+ [0x01d71f] = { 0x000394 },
+ [0x01d720] = { 0x000395 },
+ [0x01d721] = { 0x000396 },
+ [0x01d722] = { 0x000397 },
+ [0x01d723] = { 0x000398 },
+ [0x01d724] = { 0x000399 },
+ [0x01d725] = { 0x00039a },
+ [0x01d726] = { 0x00039b },
+ [0x01d727] = { 0x00039c },
+ [0x01d728] = { 0x00039d },
+ [0x01d729] = { 0x00039e },
+ [0x01d72a] = { 0x00039f },
+ [0x01d72b] = { 0x0003a0 },
+ [0x01d72c] = { 0x0003a1 },
+ [0x01d72d] = { 0x000398 },
+ [0x01d72e] = { 0x0003a3 },
+ [0x01d72f] = { 0x0003a4 },
+ [0x01d730] = { 0x0003a5 },
+ [0x01d731] = { 0x0003a6 },
+ [0x01d732] = { 0x0003a7 },
+ [0x01d733] = { 0x0003a8 },
+ [0x01d734] = { 0x0003a9 },
+ [0x01d735] = { 0x002207 },
+ [0x01d736] = { 0x0003b1 },
+ [0x01d737] = { 0x0003b2 },
+ [0x01d738] = { 0x0003b3 },
+ [0x01d739] = { 0x0003b4 },
+ [0x01d73a] = { 0x0003b5 },
+ [0x01d73b] = { 0x0003b6 },
+ [0x01d73c] = { 0x0003b7 },
+ [0x01d73d] = { 0x0003b8 },
+ [0x01d73e] = { 0x0003b9 },
+ [0x01d73f] = { 0x0003ba },
+ [0x01d740] = { 0x0003bb },
+ [0x01d741] = { 0x0003bc },
+ [0x01d742] = { 0x0003bd },
+ [0x01d743] = { 0x0003be },
+ [0x01d744] = { 0x0003bf },
+ [0x01d745] = { 0x0003c0 },
+ [0x01d746] = { 0x0003c1 },
+ [0x01d747] = { 0x0003c2 },
+ [0x01d748] = { 0x0003c3 },
+ [0x01d749] = { 0x0003c4 },
+ [0x01d74a] = { 0x0003c5 },
+ [0x01d74b] = { 0x0003c6 },
+ [0x01d74c] = { 0x0003c7 },
+ [0x01d74d] = { 0x0003c8 },
+ [0x01d74e] = { 0x0003c9 },
+ [0x01d74f] = { 0x002202 },
+ [0x01d750] = { 0x0003b5 },
+ [0x01d751] = { 0x0003b8 },
+ [0x01d752] = { 0x0003ba },
+ [0x01d753] = { 0x0003c6 },
+ [0x01d754] = { 0x0003c1 },
+ [0x01d755] = { 0x0003c0 },
+ [0x01d756] = { 0x000391 },
+ [0x01d757] = { 0x000392 },
+ [0x01d758] = { 0x000393 },
+ [0x01d759] = { 0x000394 },
+ [0x01d75a] = { 0x000395 },
+ [0x01d75b] = { 0x000396 },
+ [0x01d75c] = { 0x000397 },
+ [0x01d75d] = { 0x000398 },
+ [0x01d75e] = { 0x000399 },
+ [0x01d75f] = { 0x00039a },
+ [0x01d760] = { 0x00039b },
+ [0x01d761] = { 0x00039c },
+ [0x01d762] = { 0x00039d },
+ [0x01d763] = { 0x00039e },
+ [0x01d764] = { 0x00039f },
+ [0x01d765] = { 0x0003a0 },
+ [0x01d766] = { 0x0003a1 },
+ [0x01d767] = { 0x000398 },
+ [0x01d768] = { 0x0003a3 },
+ [0x01d769] = { 0x0003a4 },
+ [0x01d76a] = { 0x0003a5 },
+ [0x01d76b] = { 0x0003a6 },
+ [0x01d76c] = { 0x0003a7 },
+ [0x01d76d] = { 0x0003a8 },
+ [0x01d76e] = { 0x0003a9 },
+ [0x01d76f] = { 0x002207 },
+ [0x01d770] = { 0x0003b1 },
+ [0x01d771] = { 0x0003b2 },
+ [0x01d772] = { 0x0003b3 },
+ [0x01d773] = { 0x0003b4 },
+ [0x01d774] = { 0x0003b5 },
+ [0x01d775] = { 0x0003b6 },
+ [0x01d776] = { 0x0003b7 },
+ [0x01d777] = { 0x0003b8 },
+ [0x01d778] = { 0x0003b9 },
+ [0x01d779] = { 0x0003ba },
+ [0x01d77a] = { 0x0003bb },
+ [0x01d77b] = { 0x0003bc },
+ [0x01d77c] = { 0x0003bd },
+ [0x01d77d] = { 0x0003be },
+ [0x01d77e] = { 0x0003bf },
+ [0x01d77f] = { 0x0003c0 },
+ [0x01d780] = { 0x0003c1 },
+ [0x01d781] = { 0x0003c2 },
+ [0x01d782] = { 0x0003c3 },
+ [0x01d783] = { 0x0003c4 },
+ [0x01d784] = { 0x0003c5 },
+ [0x01d785] = { 0x0003c6 },
+ [0x01d786] = { 0x0003c7 },
+ [0x01d787] = { 0x0003c8 },
+ [0x01d788] = { 0x0003c9 },
+ [0x01d789] = { 0x002202 },
+ [0x01d78a] = { 0x0003b5 },
+ [0x01d78b] = { 0x0003b8 },
+ [0x01d78c] = { 0x0003ba },
+ [0x01d78d] = { 0x0003c6 },
+ [0x01d78e] = { 0x0003c1 },
+ [0x01d78f] = { 0x0003c0 },
+ [0x01d790] = { 0x000391 },
+ [0x01d791] = { 0x000392 },
+ [0x01d792] = { 0x000393 },
+ [0x01d793] = { 0x000394 },
+ [0x01d794] = { 0x000395 },
+ [0x01d795] = { 0x000396 },
+ [0x01d796] = { 0x000397 },
+ [0x01d797] = { 0x000398 },
+ [0x01d798] = { 0x000399 },
+ [0x01d799] = { 0x00039a },
+ [0x01d79a] = { 0x00039b },
+ [0x01d79b] = { 0x00039c },
+ [0x01d79c] = { 0x00039d },
+ [0x01d79d] = { 0x00039e },
+ [0x01d79e] = { 0x00039f },
+ [0x01d79f] = { 0x0003a0 },
+ [0x01d7a0] = { 0x0003a1 },
+ [0x01d7a1] = { 0x000398 },
+ [0x01d7a2] = { 0x0003a3 },
+ [0x01d7a3] = { 0x0003a4 },
+ [0x01d7a4] = { 0x0003a5 },
+ [0x01d7a5] = { 0x0003a6 },
+ [0x01d7a6] = { 0x0003a7 },
+ [0x01d7a7] = { 0x0003a8 },
+ [0x01d7a8] = { 0x0003a9 },
+ [0x01d7a9] = { 0x002207 },
+ [0x01d7aa] = { 0x0003b1 },
+ [0x01d7ab] = { 0x0003b2 },
+ [0x01d7ac] = { 0x0003b3 },
+ [0x01d7ad] = { 0x0003b4 },
+ [0x01d7ae] = { 0x0003b5 },
+ [0x01d7af] = { 0x0003b6 },
+ [0x01d7b0] = { 0x0003b7 },
+ [0x01d7b1] = { 0x0003b8 },
+ [0x01d7b2] = { 0x0003b9 },
+ [0x01d7b3] = { 0x0003ba },
+ [0x01d7b4] = { 0x0003bb },
+ [0x01d7b5] = { 0x0003bc },
+ [0x01d7b6] = { 0x0003bd },
+ [0x01d7b7] = { 0x0003be },
+ [0x01d7b8] = { 0x0003bf },
+ [0x01d7b9] = { 0x0003c0 },
+ [0x01d7ba] = { 0x0003c1 },
+ [0x01d7bb] = { 0x0003c2 },
+ [0x01d7bc] = { 0x0003c3 },
+ [0x01d7bd] = { 0x0003c4 },
+ [0x01d7be] = { 0x0003c5 },
+ [0x01d7bf] = { 0x0003c6 },
+ [0x01d7c0] = { 0x0003c7 },
+ [0x01d7c1] = { 0x0003c8 },
+ [0x01d7c2] = { 0x0003c9 },
+ [0x01d7c3] = { 0x002202 },
+ [0x01d7c4] = { 0x0003b5 },
+ [0x01d7c5] = { 0x0003b8 },
+ [0x01d7c6] = { 0x0003ba },
+ [0x01d7c7] = { 0x0003c6 },
+ [0x01d7c8] = { 0x0003c1 },
+ [0x01d7c9] = { 0x0003c0 },
+ [0x01d7ca] = { 0x0003dc },
+ [0x01d7cb] = { 0x0003dd },
+ [0x01d7ce] = { 0x000030 },
+ [0x01d7cf] = { 0x000031 },
+ [0x01d7d0] = { 0x000032 },
+ [0x01d7d1] = { 0x000033 },
+ [0x01d7d2] = { 0x000034 },
+ [0x01d7d3] = { 0x000035 },
+ [0x01d7d4] = { 0x000036 },
+ [0x01d7d5] = { 0x000037 },
+ [0x01d7d6] = { 0x000038 },
+ [0x01d7d7] = { 0x000039 },
+ [0x01d7d8] = { 0x000030 },
+ [0x01d7d9] = { 0x000031 },
+ [0x01d7da] = { 0x000032 },
+ [0x01d7db] = { 0x000033 },
+ [0x01d7dc] = { 0x000034 },
+ [0x01d7dd] = { 0x000035 },
+ [0x01d7de] = { 0x000036 },
+ [0x01d7df] = { 0x000037 },
+ [0x01d7e0] = { 0x000038 },
+ [0x01d7e1] = { 0x000039 },
+ [0x01d7e2] = { 0x000030 },
+ [0x01d7e3] = { 0x000031 },
+ [0x01d7e4] = { 0x000032 },
+ [0x01d7e5] = { 0x000033 },
+ [0x01d7e6] = { 0x000034 },
+ [0x01d7e7] = { 0x000035 },
+ [0x01d7e8] = { 0x000036 },
+ [0x01d7e9] = { 0x000037 },
+ [0x01d7ea] = { 0x000038 },
+ [0x01d7eb] = { 0x000039 },
+ [0x01d7ec] = { 0x000030 },
+ [0x01d7ed] = { 0x000031 },
+ [0x01d7ee] = { 0x000032 },
+ [0x01d7ef] = { 0x000033 },
+ [0x01d7f0] = { 0x000034 },
+ [0x01d7f1] = { 0x000035 },
+ [0x01d7f2] = { 0x000036 },
+ [0x01d7f3] = { 0x000037 },
+ [0x01d7f4] = { 0x000038 },
+ [0x01d7f5] = { 0x000039 },
+ [0x01d7f6] = { 0x000030 },
+ [0x01d7f7] = { 0x000031 },
+ [0x01d7f8] = { 0x000032 },
+ [0x01d7f9] = { 0x000033 },
+ [0x01d7fa] = { 0x000034 },
+ [0x01d7fb] = { 0x000035 },
+ [0x01d7fc] = { 0x000036 },
+ [0x01d7fd] = { 0x000037 },
+ [0x01d7fe] = { 0x000038 },
+ [0x01d7ff] = { 0x000039 },
+ [0x01ee00] = { 0x000627 },
+ [0x01ee01] = { 0x000628 },
+ [0x01ee02] = { 0x00062c },
+ [0x01ee03] = { 0x00062f },
+ [0x01ee05] = { 0x000648 },
+ [0x01ee06] = { 0x000632 },
+ [0x01ee07] = { 0x00062d },
+ [0x01ee08] = { 0x000637 },
+ [0x01ee09] = { 0x00064a },
+ [0x01ee0a] = { 0x000643 },
+ [0x01ee0b] = { 0x000644 },
+ [0x01ee0c] = { 0x000645 },
+ [0x01ee0d] = { 0x000646 },
+ [0x01ee0e] = { 0x000633 },
+ [0x01ee0f] = { 0x000639 },
+ [0x01ee10] = { 0x000641 },
+ [0x01ee11] = { 0x000635 },
+ [0x01ee12] = { 0x000642 },
+ [0x01ee13] = { 0x000631 },
+ [0x01ee14] = { 0x000634 },
+ [0x01ee15] = { 0x00062a },
+ [0x01ee16] = { 0x00062b },
+ [0x01ee17] = { 0x00062e },
+ [0x01ee18] = { 0x000630 },
+ [0x01ee19] = { 0x000636 },
+ [0x01ee1a] = { 0x000638 },
+ [0x01ee1b] = { 0x00063a },
+ [0x01ee1c] = { 0x00066e },
+ [0x01ee1d] = { 0x0006ba },
+ [0x01ee1e] = { 0x0006a1 },
+ [0x01ee1f] = { 0x00066f },
+ [0x01ee21] = { 0x000628 },
+ [0x01ee22] = { 0x00062c },
+ [0x01ee24] = { 0x000647 },
+ [0x01ee27] = { 0x00062d },
+ [0x01ee29] = { 0x00064a },
+ [0x01ee2a] = { 0x000643 },
+ [0x01ee2b] = { 0x000644 },
+ [0x01ee2c] = { 0x000645 },
+ [0x01ee2d] = { 0x000646 },
+ [0x01ee2e] = { 0x000633 },
+ [0x01ee2f] = { 0x000639 },
+ [0x01ee30] = { 0x000641 },
+ [0x01ee31] = { 0x000635 },
+ [0x01ee32] = { 0x000642 },
+ [0x01ee34] = { 0x000634 },
+ [0x01ee35] = { 0x00062a },
+ [0x01ee36] = { 0x00062b },
+ [0x01ee37] = { 0x00062e },
+ [0x01ee39] = { 0x000636 },
+ [0x01ee3b] = { 0x00063a },
+ [0x01ee42] = { 0x00062c },
+ [0x01ee47] = { 0x00062d },
+ [0x01ee49] = { 0x00064a },
+ [0x01ee4b] = { 0x000644 },
+ [0x01ee4d] = { 0x000646 },
+ [0x01ee4e] = { 0x000633 },
+ [0x01ee4f] = { 0x000639 },
+ [0x01ee51] = { 0x000635 },
+ [0x01ee52] = { 0x000642 },
+ [0x01ee54] = { 0x000634 },
+ [0x01ee57] = { 0x00062e },
+ [0x01ee59] = { 0x000636 },
+ [0x01ee5b] = { 0x00063a },
+ [0x01ee5d] = { 0x0006ba },
+ [0x01ee5f] = { 0x00066f },
+ [0x01ee61] = { 0x000628 },
+ [0x01ee62] = { 0x00062c },
+ [0x01ee64] = { 0x000647 },
+ [0x01ee67] = { 0x00062d },
+ [0x01ee68] = { 0x000637 },
+ [0x01ee69] = { 0x00064a },
+ [0x01ee6a] = { 0x000643 },
+ [0x01ee6c] = { 0x000645 },
+ [0x01ee6d] = { 0x000646 },
+ [0x01ee6e] = { 0x000633 },
+ [0x01ee6f] = { 0x000639 },
+ [0x01ee70] = { 0x000641 },
+ [0x01ee71] = { 0x000635 },
+ [0x01ee72] = { 0x000642 },
+ [0x01ee74] = { 0x000634 },
+ [0x01ee75] = { 0x00062a },
+ [0x01ee76] = { 0x00062b },
+ [0x01ee77] = { 0x00062e },
+ [0x01ee79] = { 0x000636 },
+ [0x01ee7a] = { 0x000638 },
+ [0x01ee7b] = { 0x00063a },
+ [0x01ee7c] = { 0x00066e },
+ [0x01ee7e] = { 0x0006a1 },
+ [0x01ee80] = { 0x000627 },
+ [0x01ee81] = { 0x000628 },
+ [0x01ee82] = { 0x00062c },
+ [0x01ee83] = { 0x00062f },
+ [0x01ee84] = { 0x000647 },
+ [0x01ee85] = { 0x000648 },
+ [0x01ee86] = { 0x000632 },
+ [0x01ee87] = { 0x00062d },
+ [0x01ee88] = { 0x000637 },
+ [0x01ee89] = { 0x00064a },
+ [0x01ee8b] = { 0x000644 },
+ [0x01ee8c] = { 0x000645 },
+ [0x01ee8d] = { 0x000646 },
+ [0x01ee8e] = { 0x000633 },
+ [0x01ee8f] = { 0x000639 },
+ [0x01ee90] = { 0x000641 },
+ [0x01ee91] = { 0x000635 },
+ [0x01ee92] = { 0x000642 },
+ [0x01ee93] = { 0x000631 },
+ [0x01ee94] = { 0x000634 },
+ [0x01ee95] = { 0x00062a },
+ [0x01ee96] = { 0x00062b },
+ [0x01ee97] = { 0x00062e },
+ [0x01ee98] = { 0x000630 },
+ [0x01ee99] = { 0x000636 },
+ [0x01ee9a] = { 0x000638 },
+ [0x01ee9b] = { 0x00063a },
+ [0x01eea1] = { 0x000628 },
+ [0x01eea2] = { 0x00062c },
+ [0x01eea3] = { 0x00062f },
+ [0x01eea5] = { 0x000648 },
+ [0x01eea6] = { 0x000632 },
+ [0x01eea7] = { 0x00062d },
+ [0x01eea8] = { 0x000637 },
+ [0x01eea9] = { 0x00064a },
+ [0x01eeab] = { 0x000644 },
+ [0x01eeac] = { 0x000645 },
+ [0x01eead] = { 0x000646 },
+ [0x01eeae] = { 0x000633 },
+ [0x01eeaf] = { 0x000639 },
+ [0x01eeb0] = { 0x000641 },
+ [0x01eeb1] = { 0x000635 },
+ [0x01eeb2] = { 0x000642 },
+ [0x01eeb3] = { 0x000631 },
+ [0x01eeb4] = { 0x000634 },
+ [0x01eeb5] = { 0x00062a },
+ [0x01eeb6] = { 0x00062b },
+ [0x01eeb7] = { 0x00062e },
+ [0x01eeb8] = { 0x000630 },
+ [0x01eeb9] = { 0x000636 },
+ [0x01eeba] = { 0x000638 },
+ [0x01eebb] = { 0x00063a },
+ [0x01f100] = { 0x000030, 0x00002e },
+ [0x01f101] = { 0x000030, 0x00002c },
+ [0x01f102] = { 0x000031, 0x00002c },
+ [0x01f103] = { 0x000032, 0x00002c },
+ [0x01f104] = { 0x000033, 0x00002c },
+ [0x01f105] = { 0x000034, 0x00002c },
+ [0x01f106] = { 0x000035, 0x00002c },
+ [0x01f107] = { 0x000036, 0x00002c },
+ [0x01f108] = { 0x000037, 0x00002c },
+ [0x01f109] = { 0x000038, 0x00002c },
+ [0x01f10a] = { 0x000039, 0x00002c },
+ [0x01f110] = { 0x000028, 0x000041, 0x000029 },
+ [0x01f111] = { 0x000028, 0x000042, 0x000029 },
+ [0x01f112] = { 0x000028, 0x000043, 0x000029 },
+ [0x01f113] = { 0x000028, 0x000044, 0x000029 },
+ [0x01f114] = { 0x000028, 0x000045, 0x000029 },
+ [0x01f115] = { 0x000028, 0x000046, 0x000029 },
+ [0x01f116] = { 0x000028, 0x000047, 0x000029 },
+ [0x01f117] = { 0x000028, 0x000048, 0x000029 },
+ [0x01f118] = { 0x000028, 0x000049, 0x000029 },
+ [0x01f119] = { 0x000028, 0x00004a, 0x000029 },
+ [0x01f11a] = { 0x000028, 0x00004b, 0x000029 },
+ [0x01f11b] = { 0x000028, 0x00004c, 0x000029 },
+ [0x01f11c] = { 0x000028, 0x00004d, 0x000029 },
+ [0x01f11d] = { 0x000028, 0x00004e, 0x000029 },
+ [0x01f11e] = { 0x000028, 0x00004f, 0x000029 },
+ [0x01f11f] = { 0x000028, 0x000050, 0x000029 },
+ [0x01f120] = { 0x000028, 0x000051, 0x000029 },
+ [0x01f121] = { 0x000028, 0x000052, 0x000029 },
+ [0x01f122] = { 0x000028, 0x000053, 0x000029 },
+ [0x01f123] = { 0x000028, 0x000054, 0x000029 },
+ [0x01f124] = { 0x000028, 0x000055, 0x000029 },
+ [0x01f125] = { 0x000028, 0x000056, 0x000029 },
+ [0x01f126] = { 0x000028, 0x000057, 0x000029 },
+ [0x01f127] = { 0x000028, 0x000058, 0x000029 },
+ [0x01f128] = { 0x000028, 0x000059, 0x000029 },
+ [0x01f129] = { 0x000028, 0x00005a, 0x000029 },
+ [0x01f12a] = { 0x003014, 0x000053, 0x003015 },
+ [0x01f12b] = { 0x000043 },
+ [0x01f12c] = { 0x000052 },
+ [0x01f12d] = { 0x000043, 0x000044 },
+ [0x01f12e] = { 0x000057, 0x00005a },
+ [0x01f130] = { 0x000041 },
+ [0x01f131] = { 0x000042 },
+ [0x01f132] = { 0x000043 },
+ [0x01f133] = { 0x000044 },
+ [0x01f134] = { 0x000045 },
+ [0x01f135] = { 0x000046 },
+ [0x01f136] = { 0x000047 },
+ [0x01f137] = { 0x000048 },
+ [0x01f138] = { 0x000049 },
+ [0x01f139] = { 0x00004a },
+ [0x01f13a] = { 0x00004b },
+ [0x01f13b] = { 0x00004c },
+ [0x01f13c] = { 0x00004d },
+ [0x01f13d] = { 0x00004e },
+ [0x01f13e] = { 0x00004f },
+ [0x01f13f] = { 0x000050 },
+ [0x01f140] = { 0x000051 },
+ [0x01f141] = { 0x000052 },
+ [0x01f142] = { 0x000053 },
+ [0x01f143] = { 0x000054 },
+ [0x01f144] = { 0x000055 },
+ [0x01f145] = { 0x000056 },
+ [0x01f146] = { 0x000057 },
+ [0x01f147] = { 0x000058 },
+ [0x01f148] = { 0x000059 },
+ [0x01f149] = { 0x00005a },
+ [0x01f14a] = { 0x000048, 0x000056 },
+ [0x01f14b] = { 0x00004d, 0x000056 },
+ [0x01f14c] = { 0x000053, 0x000044 },
+ [0x01f14d] = { 0x000053, 0x000053 },
+ [0x01f14e] = { 0x000050, 0x000050, 0x000056 },
+ [0x01f14f] = { 0x000057, 0x000043 },
+ [0x01f16a] = { 0x00004d, 0x000043 },
+ [0x01f16b] = { 0x00004d, 0x000044 },
+ [0x01f190] = { 0x000044, 0x00004a },
+ [0x01f200] = { 0x00307b, 0x00304b },
+ [0x01f201] = { 0x0030b3, 0x0030b3 },
+ [0x01f202] = { 0x0030b5 },
+ [0x01f210] = { 0x00624b },
+ [0x01f211] = { 0x005b57 },
+ [0x01f212] = { 0x0053cc },
+ [0x01f213] = { 0x0030c6, 0x003099 },
+ [0x01f214] = { 0x004e8c },
+ [0x01f215] = { 0x00591a },
+ [0x01f216] = { 0x0089e3 },
+ [0x01f217] = { 0x005929 },
+ [0x01f218] = { 0x004ea4 },
+ [0x01f219] = { 0x006620 },
+ [0x01f21a] = { 0x007121 },
+ [0x01f21b] = { 0x006599 },
+ [0x01f21c] = { 0x00524d },
+ [0x01f21d] = { 0x005f8c },
+ [0x01f21e] = { 0x00518d },
+ [0x01f21f] = { 0x0065b0 },
+ [0x01f220] = { 0x00521d },
+ [0x01f221] = { 0x007d42 },
+ [0x01f222] = { 0x00751f },
+ [0x01f223] = { 0x008ca9 },
+ [0x01f224] = { 0x0058f0 },
+ [0x01f225] = { 0x005439 },
+ [0x01f226] = { 0x006f14 },
+ [0x01f227] = { 0x006295 },
+ [0x01f228] = { 0x006355 },
+ [0x01f229] = { 0x004e00 },
+ [0x01f22a] = { 0x004e09 },
+ [0x01f22b] = { 0x00904a },
+ [0x01f22c] = { 0x005de6 },
+ [0x01f22d] = { 0x004e2d },
+ [0x01f22e] = { 0x0053f3 },
+ [0x01f22f] = { 0x006307 },
+ [0x01f230] = { 0x008d70 },
+ [0x01f231] = { 0x006253 },
+ [0x01f232] = { 0x007981 },
+ [0x01f233] = { 0x007a7a },
+ [0x01f234] = { 0x005408 },
+ [0x01f235] = { 0x006e80 },
+ [0x01f236] = { 0x006709 },
+ [0x01f237] = { 0x006708 },
+ [0x01f238] = { 0x007533 },
+ [0x01f239] = { 0x005272 },
+ [0x01f23a] = { 0x0055b6 },
+ [0x01f240] = { 0x003014, 0x00672c, 0x003015 },
+ [0x01f241] = { 0x003014, 0x004e09, 0x003015 },
+ [0x01f242] = { 0x003014, 0x004e8c, 0x003015 },
+ [0x01f243] = { 0x003014, 0x005b89, 0x003015 },
+ [0x01f244] = { 0x003014, 0x0070b9, 0x003015 },
+ [0x01f245] = { 0x003014, 0x006253, 0x003015 },
+ [0x01f246] = { 0x003014, 0x0076d7, 0x003015 },
+ [0x01f247] = { 0x003014, 0x0052dd, 0x003015 },
+ [0x01f248] = { 0x003014, 0x006557, 0x003015 },
+ [0x01f250] = { 0x005f97 },
+ [0x01f251] = { 0x0053ef },
+ },
+
+ -- Character-pairs mapped to what they compose to
+ -- Note Jamo to Hangul is done separately below
+ comp = {
+ [0x00003c] = {
+ [0x000338] = 0x00226e,
+ },
+ [0x00003d] = {
+ [0x000338] = 0x002260,
+ },
+ [0x00003e] = {
+ [0x000338] = 0x00226f,
+ },
+ [0x000041] = {
+ [0x000300] = 0x0000c0,
+ [0x000301] = 0x0000c1,
+ [0x000302] = 0x0000c2,
+ [0x000303] = 0x0000c3,
+ [0x000304] = 0x000100,
+ [0x000306] = 0x000102,
+ [0x000307] = 0x000226,
+ [0x000308] = 0x0000c4,
+ [0x000309] = 0x001ea2,
+ [0x00030a] = 0x0000c5,
+ [0x00030c] = 0x0001cd,
+ [0x00030f] = 0x000200,
+ [0x000311] = 0x000202,
+ [0x000323] = 0x001ea0,
+ [0x000325] = 0x001e00,
+ [0x000328] = 0x000104,
+ },
+ [0x000042] = {
+ [0x000307] = 0x001e02,
+ [0x000323] = 0x001e04,
+ [0x000331] = 0x001e06,
+ },
+ [0x000043] = {
+ [0x000301] = 0x000106,
+ [0x000302] = 0x000108,
+ [0x000307] = 0x00010a,
+ [0x00030c] = 0x00010c,
+ [0x000327] = 0x0000c7,
+ },
+ [0x000044] = {
+ [0x000307] = 0x001e0a,
+ [0x00030c] = 0x00010e,
+ [0x000323] = 0x001e0c,
+ [0x000327] = 0x001e10,
+ [0x00032d] = 0x001e12,
+ [0x000331] = 0x001e0e,
+ },
+ [0x000045] = {
+ [0x000300] = 0x0000c8,
+ [0x000301] = 0x0000c9,
+ [0x000302] = 0x0000ca,
+ [0x000303] = 0x001ebc,
+ [0x000304] = 0x000112,
+ [0x000306] = 0x000114,
+ [0x000307] = 0x000116,
+ [0x000308] = 0x0000cb,
+ [0x000309] = 0x001eba,
+ [0x00030c] = 0x00011a,
+ [0x00030f] = 0x000204,
+ [0x000311] = 0x000206,
+ [0x000323] = 0x001eb8,
+ [0x000327] = 0x000228,
+ [0x000328] = 0x000118,
+ [0x00032d] = 0x001e18,
+ [0x000330] = 0x001e1a,
+ },
+ [0x000046] = {
+ [0x000307] = 0x001e1e,
+ },
+ [0x000047] = {
+ [0x000301] = 0x0001f4,
+ [0x000302] = 0x00011c,
+ [0x000304] = 0x001e20,
+ [0x000306] = 0x00011e,
+ [0x000307] = 0x000120,
+ [0x00030c] = 0x0001e6,
+ [0x000327] = 0x000122,
+ },
+ [0x000048] = {
+ [0x000302] = 0x000124,
+ [0x000307] = 0x001e22,
+ [0x000308] = 0x001e26,
+ [0x00030c] = 0x00021e,
+ [0x000323] = 0x001e24,
+ [0x000327] = 0x001e28,
+ [0x00032e] = 0x001e2a,
+ },
+ [0x000049] = {
+ [0x000300] = 0x0000cc,
+ [0x000301] = 0x0000cd,
+ [0x000302] = 0x0000ce,
+ [0x000303] = 0x000128,
+ [0x000304] = 0x00012a,
+ [0x000306] = 0x00012c,
+ [0x000307] = 0x000130,
+ [0x000308] = 0x0000cf,
+ [0x000309] = 0x001ec8,
+ [0x00030c] = 0x0001cf,
+ [0x00030f] = 0x000208,
+ [0x000311] = 0x00020a,
+ [0x000323] = 0x001eca,
+ [0x000328] = 0x00012e,
+ [0x000330] = 0x001e2c,
+ },
+ [0x00004a] = {
+ [0x000302] = 0x000134,
+ },
+ [0x00004b] = {
+ [0x000301] = 0x001e30,
+ [0x00030c] = 0x0001e8,
+ [0x000323] = 0x001e32,
+ [0x000327] = 0x000136,
+ [0x000331] = 0x001e34,
+ },
+ [0x00004c] = {
+ [0x000301] = 0x000139,
+ [0x00030c] = 0x00013d,
+ [0x000323] = 0x001e36,
+ [0x000327] = 0x00013b,
+ [0x00032d] = 0x001e3c,
+ [0x000331] = 0x001e3a,
+ },
+ [0x00004d] = {
+ [0x000301] = 0x001e3e,
+ [0x000307] = 0x001e40,
+ [0x000323] = 0x001e42,
+ },
+ [0x00004e] = {
+ [0x000300] = 0x0001f8,
+ [0x000301] = 0x000143,
+ [0x000303] = 0x0000d1,
+ [0x000307] = 0x001e44,
+ [0x00030c] = 0x000147,
+ [0x000323] = 0x001e46,
+ [0x000327] = 0x000145,
+ [0x00032d] = 0x001e4a,
+ [0x000331] = 0x001e48,
+ },
+ [0x00004f] = {
+ [0x000300] = 0x0000d2,
+ [0x000301] = 0x0000d3,
+ [0x000302] = 0x0000d4,
+ [0x000303] = 0x0000d5,
+ [0x000304] = 0x00014c,
+ [0x000306] = 0x00014e,
+ [0x000307] = 0x00022e,
+ [0x000308] = 0x0000d6,
+ [0x000309] = 0x001ece,
+ [0x00030b] = 0x000150,
+ [0x00030c] = 0x0001d1,
+ [0x00030f] = 0x00020c,
+ [0x000311] = 0x00020e,
+ [0x00031b] = 0x0001a0,
+ [0x000323] = 0x001ecc,
+ [0x000328] = 0x0001ea,
+ },
+ [0x000050] = {
+ [0x000301] = 0x001e54,
+ [0x000307] = 0x001e56,
+ },
+ [0x000052] = {
+ [0x000301] = 0x000154,
+ [0x000307] = 0x001e58,
+ [0x00030c] = 0x000158,
+ [0x00030f] = 0x000210,
+ [0x000311] = 0x000212,
+ [0x000323] = 0x001e5a,
+ [0x000327] = 0x000156,
+ [0x000331] = 0x001e5e,
+ },
+ [0x000053] = {
+ [0x000301] = 0x00015a,
+ [0x000302] = 0x00015c,
+ [0x000307] = 0x001e60,
+ [0x00030c] = 0x000160,
+ [0x000323] = 0x001e62,
+ [0x000326] = 0x000218,
+ [0x000327] = 0x00015e,
+ },
+ [0x000054] = {
+ [0x000307] = 0x001e6a,
+ [0x00030c] = 0x000164,
+ [0x000323] = 0x001e6c,
+ [0x000326] = 0x00021a,
+ [0x000327] = 0x000162,
+ [0x00032d] = 0x001e70,
+ [0x000331] = 0x001e6e,
+ },
+ [0x000055] = {
+ [0x000300] = 0x0000d9,
+ [0x000301] = 0x0000da,
+ [0x000302] = 0x0000db,
+ [0x000303] = 0x000168,
+ [0x000304] = 0x00016a,
+ [0x000306] = 0x00016c,
+ [0x000308] = 0x0000dc,
+ [0x000309] = 0x001ee6,
+ [0x00030a] = 0x00016e,
+ [0x00030b] = 0x000170,
+ [0x00030c] = 0x0001d3,
+ [0x00030f] = 0x000214,
+ [0x000311] = 0x000216,
+ [0x00031b] = 0x0001af,
+ [0x000323] = 0x001ee4,
+ [0x000324] = 0x001e72,
+ [0x000328] = 0x000172,
+ [0x00032d] = 0x001e76,
+ [0x000330] = 0x001e74,
+ },
+ [0x000056] = {
+ [0x000303] = 0x001e7c,
+ [0x000323] = 0x001e7e,
+ },
+ [0x000057] = {
+ [0x000300] = 0x001e80,
+ [0x000301] = 0x001e82,
+ [0x000302] = 0x000174,
+ [0x000307] = 0x001e86,
+ [0x000308] = 0x001e84,
+ [0x000323] = 0x001e88,
+ },
+ [0x000058] = {
+ [0x000307] = 0x001e8a,
+ [0x000308] = 0x001e8c,
+ },
+ [0x000059] = {
+ [0x000300] = 0x001ef2,
+ [0x000301] = 0x0000dd,
+ [0x000302] = 0x000176,
+ [0x000303] = 0x001ef8,
+ [0x000304] = 0x000232,
+ [0x000307] = 0x001e8e,
+ [0x000308] = 0x000178,
+ [0x000309] = 0x001ef6,
+ [0x000323] = 0x001ef4,
+ },
+ [0x00005a] = {
+ [0x000301] = 0x000179,
+ [0x000302] = 0x001e90,
+ [0x000307] = 0x00017b,
+ [0x00030c] = 0x00017d,
+ [0x000323] = 0x001e92,
+ [0x000331] = 0x001e94,
+ },
+ [0x000061] = {
+ [0x000300] = 0x0000e0,
+ [0x000301] = 0x0000e1,
+ [0x000302] = 0x0000e2,
+ [0x000303] = 0x0000e3,
+ [0x000304] = 0x000101,
+ [0x000306] = 0x000103,
+ [0x000307] = 0x000227,
+ [0x000308] = 0x0000e4,
+ [0x000309] = 0x001ea3,
+ [0x00030a] = 0x0000e5,
+ [0x00030c] = 0x0001ce,
+ [0x00030f] = 0x000201,
+ [0x000311] = 0x000203,
+ [0x000323] = 0x001ea1,
+ [0x000325] = 0x001e01,
+ [0x000328] = 0x000105,
+ },
+ [0x000062] = {
+ [0x000307] = 0x001e03,
+ [0x000323] = 0x001e05,
+ [0x000331] = 0x001e07,
+ },
+ [0x000063] = {
+ [0x000301] = 0x000107,
+ [0x000302] = 0x000109,
+ [0x000307] = 0x00010b,
+ [0x00030c] = 0x00010d,
+ [0x000327] = 0x0000e7,
+ },
+ [0x000064] = {
+ [0x000307] = 0x001e0b,
+ [0x00030c] = 0x00010f,
+ [0x000323] = 0x001e0d,
+ [0x000327] = 0x001e11,
+ [0x00032d] = 0x001e13,
+ [0x000331] = 0x001e0f,
+ },
+ [0x000065] = {
+ [0x000300] = 0x0000e8,
+ [0x000301] = 0x0000e9,
+ [0x000302] = 0x0000ea,
+ [0x000303] = 0x001ebd,
+ [0x000304] = 0x000113,
+ [0x000306] = 0x000115,
+ [0x000307] = 0x000117,
+ [0x000308] = 0x0000eb,
+ [0x000309] = 0x001ebb,
+ [0x00030c] = 0x00011b,
+ [0x00030f] = 0x000205,
+ [0x000311] = 0x000207,
+ [0x000323] = 0x001eb9,
+ [0x000327] = 0x000229,
+ [0x000328] = 0x000119,
+ [0x00032d] = 0x001e19,
+ [0x000330] = 0x001e1b,
+ },
+ [0x000066] = {
+ [0x000307] = 0x001e1f,
+ },
+ [0x000067] = {
+ [0x000301] = 0x0001f5,
+ [0x000302] = 0x00011d,
+ [0x000304] = 0x001e21,
+ [0x000306] = 0x00011f,
+ [0x000307] = 0x000121,
+ [0x00030c] = 0x0001e7,
+ [0x000327] = 0x000123,
+ },
+ [0x000068] = {
+ [0x000302] = 0x000125,
+ [0x000307] = 0x001e23,
+ [0x000308] = 0x001e27,
+ [0x00030c] = 0x00021f,
+ [0x000323] = 0x001e25,
+ [0x000327] = 0x001e29,
+ [0x00032e] = 0x001e2b,
+ [0x000331] = 0x001e96,
+ },
+ [0x000069] = {
+ [0x000300] = 0x0000ec,
+ [0x000301] = 0x0000ed,
+ [0x000302] = 0x0000ee,
+ [0x000303] = 0x000129,
+ [0x000304] = 0x00012b,
+ [0x000306] = 0x00012d,
+ [0x000308] = 0x0000ef,
+ [0x000309] = 0x001ec9,
+ [0x00030c] = 0x0001d0,
+ [0x00030f] = 0x000209,
+ [0x000311] = 0x00020b,
+ [0x000323] = 0x001ecb,
+ [0x000328] = 0x00012f,
+ [0x000330] = 0x001e2d,
+ },
+ [0x00006a] = {
+ [0x000302] = 0x000135,
+ [0x00030c] = 0x0001f0,
+ },
+ [0x00006b] = {
+ [0x000301] = 0x001e31,
+ [0x00030c] = 0x0001e9,
+ [0x000323] = 0x001e33,
+ [0x000327] = 0x000137,
+ [0x000331] = 0x001e35,
+ },
+ [0x00006c] = {
+ [0x000301] = 0x00013a,
+ [0x00030c] = 0x00013e,
+ [0x000323] = 0x001e37,
+ [0x000327] = 0x00013c,
+ [0x00032d] = 0x001e3d,
+ [0x000331] = 0x001e3b,
+ },
+ [0x00006d] = {
+ [0x000301] = 0x001e3f,
+ [0x000307] = 0x001e41,
+ [0x000323] = 0x001e43,
+ },
+ [0x00006e] = {
+ [0x000300] = 0x0001f9,
+ [0x000301] = 0x000144,
+ [0x000303] = 0x0000f1,
+ [0x000307] = 0x001e45,
+ [0x00030c] = 0x000148,
+ [0x000323] = 0x001e47,
+ [0x000327] = 0x000146,
+ [0x00032d] = 0x001e4b,
+ [0x000331] = 0x001e49,
+ },
+ [0x00006f] = {
+ [0x000300] = 0x0000f2,
+ [0x000301] = 0x0000f3,
+ [0x000302] = 0x0000f4,
+ [0x000303] = 0x0000f5,
+ [0x000304] = 0x00014d,
+ [0x000306] = 0x00014f,
+ [0x000307] = 0x00022f,
+ [0x000308] = 0x0000f6,
+ [0x000309] = 0x001ecf,
+ [0x00030b] = 0x000151,
+ [0x00030c] = 0x0001d2,
+ [0x00030f] = 0x00020d,
+ [0x000311] = 0x00020f,
+ [0x00031b] = 0x0001a1,
+ [0x000323] = 0x001ecd,
+ [0x000328] = 0x0001eb,
+ },
+ [0x000070] = {
+ [0x000301] = 0x001e55,
+ [0x000307] = 0x001e57,
+ },
+ [0x000072] = {
+ [0x000301] = 0x000155,
+ [0x000307] = 0x001e59,
+ [0x00030c] = 0x000159,
+ [0x00030f] = 0x000211,
+ [0x000311] = 0x000213,
+ [0x000323] = 0x001e5b,
+ [0x000327] = 0x000157,
+ [0x000331] = 0x001e5f,
+ },
+ [0x000073] = {
+ [0x000301] = 0x00015b,
+ [0x000302] = 0x00015d,
+ [0x000307] = 0x001e61,
+ [0x00030c] = 0x000161,
+ [0x000323] = 0x001e63,
+ [0x000326] = 0x000219,
+ [0x000327] = 0x00015f,
+ },
+ [0x000074] = {
+ [0x000307] = 0x001e6b,
+ [0x000308] = 0x001e97,
+ [0x00030c] = 0x000165,
+ [0x000323] = 0x001e6d,
+ [0x000326] = 0x00021b,
+ [0x000327] = 0x000163,
+ [0x00032d] = 0x001e71,
+ [0x000331] = 0x001e6f,
+ },
+ [0x000075] = {
+ [0x000300] = 0x0000f9,
+ [0x000301] = 0x0000fa,
+ [0x000302] = 0x0000fb,
+ [0x000303] = 0x000169,
+ [0x000304] = 0x00016b,
+ [0x000306] = 0x00016d,
+ [0x000308] = 0x0000fc,
+ [0x000309] = 0x001ee7,
+ [0x00030a] = 0x00016f,
+ [0x00030b] = 0x000171,
+ [0x00030c] = 0x0001d4,
+ [0x00030f] = 0x000215,
+ [0x000311] = 0x000217,
+ [0x00031b] = 0x0001b0,
+ [0x000323] = 0x001ee5,
+ [0x000324] = 0x001e73,
+ [0x000328] = 0x000173,
+ [0x00032d] = 0x001e77,
+ [0x000330] = 0x001e75,
+ },
+ [0x000076] = {
+ [0x000303] = 0x001e7d,
+ [0x000323] = 0x001e7f,
+ },
+ [0x000077] = {
+ [0x000300] = 0x001e81,
+ [0x000301] = 0x001e83,
+ [0x000302] = 0x000175,
+ [0x000307] = 0x001e87,
+ [0x000308] = 0x001e85,
+ [0x00030a] = 0x001e98,
+ [0x000323] = 0x001e89,
+ },
+ [0x000078] = {
+ [0x000307] = 0x001e8b,
+ [0x000308] = 0x001e8d,
+ },
+ [0x000079] = {
+ [0x000300] = 0x001ef3,
+ [0x000301] = 0x0000fd,
+ [0x000302] = 0x000177,
+ [0x000303] = 0x001ef9,
+ [0x000304] = 0x000233,
+ [0x000307] = 0x001e8f,
+ [0x000308] = 0x0000ff,
+ [0x000309] = 0x001ef7,
+ [0x00030a] = 0x001e99,
+ [0x000323] = 0x001ef5,
+ },
+ [0x00007a] = {
+ [0x000301] = 0x00017a,
+ [0x000302] = 0x001e91,
+ [0x000307] = 0x00017c,
+ [0x00030c] = 0x00017e,
+ [0x000323] = 0x001e93,
+ [0x000331] = 0x001e95,
+ },
+ [0x0000a8] = {
+ [0x000300] = 0x001fed,
+ [0x000301] = 0x000385,
+ [0x000342] = 0x001fc1,
+ },
+ [0x0000c2] = {
+ [0x000300] = 0x001ea6,
+ [0x000301] = 0x001ea4,
+ [0x000303] = 0x001eaa,
+ [0x000309] = 0x001ea8,
+ },
+ [0x0000c4] = {
+ [0x000304] = 0x0001de,
+ },
+ [0x0000c5] = {
+ [0x000301] = 0x0001fa,
+ },
+ [0x0000c6] = {
+ [0x000301] = 0x0001fc,
+ [0x000304] = 0x0001e2,
+ },
+ [0x0000c7] = {
+ [0x000301] = 0x001e08,
+ },
+ [0x0000ca] = {
+ [0x000300] = 0x001ec0,
+ [0x000301] = 0x001ebe,
+ [0x000303] = 0x001ec4,
+ [0x000309] = 0x001ec2,
+ },
+ [0x0000cf] = {
+ [0x000301] = 0x001e2e,
+ },
+ [0x0000d4] = {
+ [0x000300] = 0x001ed2,
+ [0x000301] = 0x001ed0,
+ [0x000303] = 0x001ed6,
+ [0x000309] = 0x001ed4,
+ },
+ [0x0000d5] = {
+ [0x000301] = 0x001e4c,
+ [0x000304] = 0x00022c,
+ [0x000308] = 0x001e4e,
+ },
+ [0x0000d6] = {
+ [0x000304] = 0x00022a,
+ },
+ [0x0000d8] = {
+ [0x000301] = 0x0001fe,
+ },
+ [0x0000dc] = {
+ [0x000300] = 0x0001db,
+ [0x000301] = 0x0001d7,
+ [0x000304] = 0x0001d5,
+ [0x00030c] = 0x0001d9,
+ },
+ [0x0000e2] = {
+ [0x000300] = 0x001ea7,
+ [0x000301] = 0x001ea5,
+ [0x000303] = 0x001eab,
+ [0x000309] = 0x001ea9,
+ },
+ [0x0000e4] = {
+ [0x000304] = 0x0001df,
+ },
+ [0x0000e5] = {
+ [0x000301] = 0x0001fb,
+ },
+ [0x0000e6] = {
+ [0x000301] = 0x0001fd,
+ [0x000304] = 0x0001e3,
+ },
+ [0x0000e7] = {
+ [0x000301] = 0x001e09,
+ },
+ [0x0000ea] = {
+ [0x000300] = 0x001ec1,
+ [0x000301] = 0x001ebf,
+ [0x000303] = 0x001ec5,
+ [0x000309] = 0x001ec3,
+ },
+ [0x0000ef] = {
+ [0x000301] = 0x001e2f,
+ },
+ [0x0000f4] = {
+ [0x000300] = 0x001ed3,
+ [0x000301] = 0x001ed1,
+ [0x000303] = 0x001ed7,
+ [0x000309] = 0x001ed5,
+ },
+ [0x0000f5] = {
+ [0x000301] = 0x001e4d,
+ [0x000304] = 0x00022d,
+ [0x000308] = 0x001e4f,
+ },
+ [0x0000f6] = {
+ [0x000304] = 0x00022b,
+ },
+ [0x0000f8] = {
+ [0x000301] = 0x0001ff,
+ },
+ [0x0000fc] = {
+ [0x000300] = 0x0001dc,
+ [0x000301] = 0x0001d8,
+ [0x000304] = 0x0001d6,
+ [0x00030c] = 0x0001da,
+ },
+ [0x000102] = {
+ [0x000300] = 0x001eb0,
+ [0x000301] = 0x001eae,
+ [0x000303] = 0x001eb4,
+ [0x000309] = 0x001eb2,
+ },
+ [0x000103] = {
+ [0x000300] = 0x001eb1,
+ [0x000301] = 0x001eaf,
+ [0x000303] = 0x001eb5,
+ [0x000309] = 0x001eb3,
+ },
+ [0x000112] = {
+ [0x000300] = 0x001e14,
+ [0x000301] = 0x001e16,
+ },
+ [0x000113] = {
+ [0x000300] = 0x001e15,
+ [0x000301] = 0x001e17,
+ },
+ [0x00014c] = {
+ [0x000300] = 0x001e50,
+ [0x000301] = 0x001e52,
+ },
+ [0x00014d] = {
+ [0x000300] = 0x001e51,
+ [0x000301] = 0x001e53,
+ },
+ [0x00015a] = {
+ [0x000307] = 0x001e64,
+ },
+ [0x00015b] = {
+ [0x000307] = 0x001e65,
+ },
+ [0x000160] = {
+ [0x000307] = 0x001e66,
+ },
+ [0x000161] = {
+ [0x000307] = 0x001e67,
+ },
+ [0x000168] = {
+ [0x000301] = 0x001e78,
+ },
+ [0x000169] = {
+ [0x000301] = 0x001e79,
+ },
+ [0x00016a] = {
+ [0x000308] = 0x001e7a,
+ },
+ [0x00016b] = {
+ [0x000308] = 0x001e7b,
+ },
+ [0x00017f] = {
+ [0x000307] = 0x001e9b,
+ },
+ [0x0001a0] = {
+ [0x000300] = 0x001edc,
+ [0x000301] = 0x001eda,
+ [0x000303] = 0x001ee0,
+ [0x000309] = 0x001ede,
+ [0x000323] = 0x001ee2,
+ },
+ [0x0001a1] = {
+ [0x000300] = 0x001edd,
+ [0x000301] = 0x001edb,
+ [0x000303] = 0x001ee1,
+ [0x000309] = 0x001edf,
+ [0x000323] = 0x001ee3,
+ },
+ [0x0001af] = {
+ [0x000300] = 0x001eea,
+ [0x000301] = 0x001ee8,
+ [0x000303] = 0x001eee,
+ [0x000309] = 0x001eec,
+ [0x000323] = 0x001ef0,
+ },
+ [0x0001b0] = {
+ [0x000300] = 0x001eeb,
+ [0x000301] = 0x001ee9,
+ [0x000303] = 0x001eef,
+ [0x000309] = 0x001eed,
+ [0x000323] = 0x001ef1,
+ },
+ [0x0001b7] = {
+ [0x00030c] = 0x0001ee,
+ },
+ [0x0001ea] = {
+ [0x000304] = 0x0001ec,
+ },
+ [0x0001eb] = {
+ [0x000304] = 0x0001ed,
+ },
+ [0x000226] = {
+ [0x000304] = 0x0001e0,
+ },
+ [0x000227] = {
+ [0x000304] = 0x0001e1,
+ },
+ [0x000228] = {
+ [0x000306] = 0x001e1c,
+ },
+ [0x000229] = {
+ [0x000306] = 0x001e1d,
+ },
+ [0x00022e] = {
+ [0x000304] = 0x000230,
+ },
+ [0x00022f] = {
+ [0x000304] = 0x000231,
+ },
+ [0x000292] = {
+ [0x00030c] = 0x0001ef,
+ },
+ [0x000391] = {
+ [0x000300] = 0x001fba,
+ [0x000301] = 0x000386,
+ [0x000304] = 0x001fb9,
+ [0x000306] = 0x001fb8,
+ [0x000313] = 0x001f08,
+ [0x000314] = 0x001f09,
+ [0x000345] = 0x001fbc,
+ },
+ [0x000395] = {
+ [0x000300] = 0x001fc8,
+ [0x000301] = 0x000388,
+ [0x000313] = 0x001f18,
+ [0x000314] = 0x001f19,
+ },
+ [0x000397] = {
+ [0x000300] = 0x001fca,
+ [0x000301] = 0x000389,
+ [0x000313] = 0x001f28,
+ [0x000314] = 0x001f29,
+ [0x000345] = 0x001fcc,
+ },
+ [0x000399] = {
+ [0x000300] = 0x001fda,
+ [0x000301] = 0x00038a,
+ [0x000304] = 0x001fd9,
+ [0x000306] = 0x001fd8,
+ [0x000308] = 0x0003aa,
+ [0x000313] = 0x001f38,
+ [0x000314] = 0x001f39,
+ },
+ [0x00039f] = {
+ [0x000300] = 0x001ff8,
+ [0x000301] = 0x00038c,
+ [0x000313] = 0x001f48,
+ [0x000314] = 0x001f49,
+ },
+ [0x0003a1] = {
+ [0x000314] = 0x001fec,
+ },
+ [0x0003a5] = {
+ [0x000300] = 0x001fea,
+ [0x000301] = 0x00038e,
+ [0x000304] = 0x001fe9,
+ [0x000306] = 0x001fe8,
+ [0x000308] = 0x0003ab,
+ [0x000314] = 0x001f59,
+ },
+ [0x0003a9] = {
+ [0x000300] = 0x001ffa,
+ [0x000301] = 0x00038f,
+ [0x000313] = 0x001f68,
+ [0x000314] = 0x001f69,
+ [0x000345] = 0x001ffc,
+ },
+ [0x0003ac] = {
+ [0x000345] = 0x001fb4,
+ },
+ [0x0003ae] = {
+ [0x000345] = 0x001fc4,
+ },
+ [0x0003b1] = {
+ [0x000300] = 0x001f70,
+ [0x000301] = 0x0003ac,
+ [0x000304] = 0x001fb1,
+ [0x000306] = 0x001fb0,
+ [0x000313] = 0x001f00,
+ [0x000314] = 0x001f01,
+ [0x000342] = 0x001fb6,
+ [0x000345] = 0x001fb3,
+ },
+ [0x0003b5] = {
+ [0x000300] = 0x001f72,
+ [0x000301] = 0x0003ad,
+ [0x000313] = 0x001f10,
+ [0x000314] = 0x001f11,
+ },
+ [0x0003b7] = {
+ [0x000300] = 0x001f74,
+ [0x000301] = 0x0003ae,
+ [0x000313] = 0x001f20,
+ [0x000314] = 0x001f21,
+ [0x000342] = 0x001fc6,
+ [0x000345] = 0x001fc3,
+ },
+ [0x0003b9] = {
+ [0x000300] = 0x001f76,
+ [0x000301] = 0x0003af,
+ [0x000304] = 0x001fd1,
+ [0x000306] = 0x001fd0,
+ [0x000308] = 0x0003ca,
+ [0x000313] = 0x001f30,
+ [0x000314] = 0x001f31,
+ [0x000342] = 0x001fd6,
+ },
+ [0x0003bf] = {
+ [0x000300] = 0x001f78,
+ [0x000301] = 0x0003cc,
+ [0x000313] = 0x001f40,
+ [0x000314] = 0x001f41,
+ },
+ [0x0003c1] = {
+ [0x000313] = 0x001fe4,
+ [0x000314] = 0x001fe5,
+ },
+ [0x0003c5] = {
+ [0x000300] = 0x001f7a,
+ [0x000301] = 0x0003cd,
+ [0x000304] = 0x001fe1,
+ [0x000306] = 0x001fe0,
+ [0x000308] = 0x0003cb,
+ [0x000313] = 0x001f50,
+ [0x000314] = 0x001f51,
+ [0x000342] = 0x001fe6,
+ },
+ [0x0003c9] = {
+ [0x000300] = 0x001f7c,
+ [0x000301] = 0x0003ce,
+ [0x000313] = 0x001f60,
+ [0x000314] = 0x001f61,
+ [0x000342] = 0x001ff6,
+ [0x000345] = 0x001ff3,
+ },
+ [0x0003ca] = {
+ [0x000300] = 0x001fd2,
+ [0x000301] = 0x000390,
+ [0x000342] = 0x001fd7,
+ },
+ [0x0003cb] = {
+ [0x000300] = 0x001fe2,
+ [0x000301] = 0x0003b0,
+ [0x000342] = 0x001fe7,
+ },
+ [0x0003ce] = {
+ [0x000345] = 0x001ff4,
+ },
+ [0x0003d2] = {
+ [0x000301] = 0x0003d3,
+ [0x000308] = 0x0003d4,
+ },
+ [0x000406] = {
+ [0x000308] = 0x000407,
+ },
+ [0x000410] = {
+ [0x000306] = 0x0004d0,
+ [0x000308] = 0x0004d2,
+ },
+ [0x000413] = {
+ [0x000301] = 0x000403,
+ },
+ [0x000415] = {
+ [0x000300] = 0x000400,
+ [0x000306] = 0x0004d6,
+ [0x000308] = 0x000401,
+ },
+ [0x000416] = {
+ [0x000306] = 0x0004c1,
+ [0x000308] = 0x0004dc,
+ },
+ [0x000417] = {
+ [0x000308] = 0x0004de,
+ },
+ [0x000418] = {
+ [0x000300] = 0x00040d,
+ [0x000304] = 0x0004e2,
+ [0x000306] = 0x000419,
+ [0x000308] = 0x0004e4,
+ },
+ [0x00041a] = {
+ [0x000301] = 0x00040c,
+ },
+ [0x00041e] = {
+ [0x000308] = 0x0004e6,
+ },
+ [0x000423] = {
+ [0x000304] = 0x0004ee,
+ [0x000306] = 0x00040e,
+ [0x000308] = 0x0004f0,
+ [0x00030b] = 0x0004f2,
+ },
+ [0x000427] = {
+ [0x000308] = 0x0004f4,
+ },
+ [0x00042b] = {
+ [0x000308] = 0x0004f8,
+ },
+ [0x00042d] = {
+ [0x000308] = 0x0004ec,
+ },
+ [0x000430] = {
+ [0x000306] = 0x0004d1,
+ [0x000308] = 0x0004d3,
+ },
+ [0x000433] = {
+ [0x000301] = 0x000453,
+ },
+ [0x000435] = {
+ [0x000300] = 0x000450,
+ [0x000306] = 0x0004d7,
+ [0x000308] = 0x000451,
+ },
+ [0x000436] = {
+ [0x000306] = 0x0004c2,
+ [0x000308] = 0x0004dd,
+ },
+ [0x000437] = {
+ [0x000308] = 0x0004df,
+ },
+ [0x000438] = {
+ [0x000300] = 0x00045d,
+ [0x000304] = 0x0004e3,
+ [0x000306] = 0x000439,
+ [0x000308] = 0x0004e5,
+ },
+ [0x00043a] = {
+ [0x000301] = 0x00045c,
+ },
+ [0x00043e] = {
+ [0x000308] = 0x0004e7,
+ },
+ [0x000443] = {
+ [0x000304] = 0x0004ef,
+ [0x000306] = 0x00045e,
+ [0x000308] = 0x0004f1,
+ [0x00030b] = 0x0004f3,
+ },
+ [0x000447] = {
+ [0x000308] = 0x0004f5,
+ },
+ [0x00044b] = {
+ [0x000308] = 0x0004f9,
+ },
+ [0x00044d] = {
+ [0x000308] = 0x0004ed,
+ },
+ [0x000456] = {
+ [0x000308] = 0x000457,
+ },
+ [0x000474] = {
+ [0x00030f] = 0x000476,
+ },
+ [0x000475] = {
+ [0x00030f] = 0x000477,
+ },
+ [0x0004d8] = {
+ [0x000308] = 0x0004da,
+ },
+ [0x0004d9] = {
+ [0x000308] = 0x0004db,
+ },
+ [0x0004e8] = {
+ [0x000308] = 0x0004ea,
+ },
+ [0x0004e9] = {
+ [0x000308] = 0x0004eb,
+ },
+ [0x000627] = {
+ [0x000653] = 0x000622,
+ [0x000654] = 0x000623,
+ [0x000655] = 0x000625,
+ },
+ [0x000648] = {
+ [0x000654] = 0x000624,
+ },
+ [0x00064a] = {
+ [0x000654] = 0x000626,
+ },
+ [0x0006c1] = {
+ [0x000654] = 0x0006c2,
+ },
+ [0x0006d2] = {
+ [0x000654] = 0x0006d3,
+ },
+ [0x0006d5] = {
+ [0x000654] = 0x0006c0,
+ },
+ [0x000928] = {
+ [0x00093c] = 0x000929,
+ },
+ [0x000930] = {
+ [0x00093c] = 0x000931,
+ },
+ [0x000933] = {
+ [0x00093c] = 0x000934,
+ },
+ [0x0009c7] = {
+ [0x0009be] = 0x0009cb,
+ [0x0009d7] = 0x0009cc,
+ },
+ [0x000b47] = {
+ [0x000b3e] = 0x000b4b,
+ [0x000b56] = 0x000b48,
+ [0x000b57] = 0x000b4c,
+ },
+ [0x000b92] = {
+ [0x000bd7] = 0x000b94,
+ },
+ [0x000bc6] = {
+ [0x000bbe] = 0x000bca,
+ [0x000bd7] = 0x000bcc,
+ },
+ [0x000bc7] = {
+ [0x000bbe] = 0x000bcb,
+ },
+ [0x000c46] = {
+ [0x000c56] = 0x000c48,
+ },
+ [0x000cbf] = {
+ [0x000cd5] = 0x000cc0,
+ },
+ [0x000cc6] = {
+ [0x000cc2] = 0x000cca,
+ [0x000cd5] = 0x000cc7,
+ [0x000cd6] = 0x000cc8,
+ },
+ [0x000cca] = {
+ [0x000cd5] = 0x000ccb,
+ },
+ [0x000d46] = {
+ [0x000d3e] = 0x000d4a,
+ [0x000d57] = 0x000d4c,
+ },
+ [0x000d47] = {
+ [0x000d3e] = 0x000d4b,
+ },
+ [0x000dd9] = {
+ [0x000dca] = 0x000dda,
+ [0x000dcf] = 0x000ddc,
+ [0x000ddf] = 0x000dde,
+ },
+ [0x000ddc] = {
+ [0x000dca] = 0x000ddd,
+ },
+ [0x001025] = {
+ [0x00102e] = 0x001026,
+ },
+ [0x001b05] = {
+ [0x001b35] = 0x001b06,
+ },
+ [0x001b07] = {
+ [0x001b35] = 0x001b08,
+ },
+ [0x001b09] = {
+ [0x001b35] = 0x001b0a,
+ },
+ [0x001b0b] = {
+ [0x001b35] = 0x001b0c,
+ },
+ [0x001b0d] = {
+ [0x001b35] = 0x001b0e,
+ },
+ [0x001b11] = {
+ [0x001b35] = 0x001b12,
+ },
+ [0x001b3a] = {
+ [0x001b35] = 0x001b3b,
+ },
+ [0x001b3c] = {
+ [0x001b35] = 0x001b3d,
+ },
+ [0x001b3e] = {
+ [0x001b35] = 0x001b40,
+ },
+ [0x001b3f] = {
+ [0x001b35] = 0x001b41,
+ },
+ [0x001b42] = {
+ [0x001b35] = 0x001b43,
+ },
+ [0x001e36] = {
+ [0x000304] = 0x001e38,
+ },
+ [0x001e37] = {
+ [0x000304] = 0x001e39,
+ },
+ [0x001e5a] = {
+ [0x000304] = 0x001e5c,
+ },
+ [0x001e5b] = {
+ [0x000304] = 0x001e5d,
+ },
+ [0x001e62] = {
+ [0x000307] = 0x001e68,
+ },
+ [0x001e63] = {
+ [0x000307] = 0x001e69,
+ },
+ [0x001ea0] = {
+ [0x000302] = 0x001eac,
+ [0x000306] = 0x001eb6,
+ },
+ [0x001ea1] = {
+ [0x000302] = 0x001ead,
+ [0x000306] = 0x001eb7,
+ },
+ [0x001eb8] = {
+ [0x000302] = 0x001ec6,
+ },
+ [0x001eb9] = {
+ [0x000302] = 0x001ec7,
+ },
+ [0x001ecc] = {
+ [0x000302] = 0x001ed8,
+ },
+ [0x001ecd] = {
+ [0x000302] = 0x001ed9,
+ },
+ [0x001f00] = {
+ [0x000300] = 0x001f02,
+ [0x000301] = 0x001f04,
+ [0x000342] = 0x001f06,
+ [0x000345] = 0x001f80,
+ },
+ [0x001f01] = {
+ [0x000300] = 0x001f03,
+ [0x000301] = 0x001f05,
+ [0x000342] = 0x001f07,
+ [0x000345] = 0x001f81,
+ },
+ [0x001f02] = {
+ [0x000345] = 0x001f82,
+ },
+ [0x001f03] = {
+ [0x000345] = 0x001f83,
+ },
+ [0x001f04] = {
+ [0x000345] = 0x001f84,
+ },
+ [0x001f05] = {
+ [0x000345] = 0x001f85,
+ },
+ [0x001f06] = {
+ [0x000345] = 0x001f86,
+ },
+ [0x001f07] = {
+ [0x000345] = 0x001f87,
+ },
+ [0x001f08] = {
+ [0x000300] = 0x001f0a,
+ [0x000301] = 0x001f0c,
+ [0x000342] = 0x001f0e,
+ [0x000345] = 0x001f88,
+ },
+ [0x001f09] = {
+ [0x000300] = 0x001f0b,
+ [0x000301] = 0x001f0d,
+ [0x000342] = 0x001f0f,
+ [0x000345] = 0x001f89,
+ },
+ [0x001f0a] = {
+ [0x000345] = 0x001f8a,
+ },
+ [0x001f0b] = {
+ [0x000345] = 0x001f8b,
+ },
+ [0x001f0c] = {
+ [0x000345] = 0x001f8c,
+ },
+ [0x001f0d] = {
+ [0x000345] = 0x001f8d,
+ },
+ [0x001f0e] = {
+ [0x000345] = 0x001f8e,
+ },
+ [0x001f0f] = {
+ [0x000345] = 0x001f8f,
+ },
+ [0x001f10] = {
+ [0x000300] = 0x001f12,
+ [0x000301] = 0x001f14,
+ },
+ [0x001f11] = {
+ [0x000300] = 0x001f13,
+ [0x000301] = 0x001f15,
+ },
+ [0x001f18] = {
+ [0x000300] = 0x001f1a,
+ [0x000301] = 0x001f1c,
+ },
+ [0x001f19] = {
+ [0x000300] = 0x001f1b,
+ [0x000301] = 0x001f1d,
+ },
+ [0x001f20] = {
+ [0x000300] = 0x001f22,
+ [0x000301] = 0x001f24,
+ [0x000342] = 0x001f26,
+ [0x000345] = 0x001f90,
+ },
+ [0x001f21] = {
+ [0x000300] = 0x001f23,
+ [0x000301] = 0x001f25,
+ [0x000342] = 0x001f27,
+ [0x000345] = 0x001f91,
+ },
+ [0x001f22] = {
+ [0x000345] = 0x001f92,
+ },
+ [0x001f23] = {
+ [0x000345] = 0x001f93,
+ },
+ [0x001f24] = {
+ [0x000345] = 0x001f94,
+ },
+ [0x001f25] = {
+ [0x000345] = 0x001f95,
+ },
+ [0x001f26] = {
+ [0x000345] = 0x001f96,
+ },
+ [0x001f27] = {
+ [0x000345] = 0x001f97,
+ },
+ [0x001f28] = {
+ [0x000300] = 0x001f2a,
+ [0x000301] = 0x001f2c,
+ [0x000342] = 0x001f2e,
+ [0x000345] = 0x001f98,
+ },
+ [0x001f29] = {
+ [0x000300] = 0x001f2b,
+ [0x000301] = 0x001f2d,
+ [0x000342] = 0x001f2f,
+ [0x000345] = 0x001f99,
+ },
+ [0x001f2a] = {
+ [0x000345] = 0x001f9a,
+ },
+ [0x001f2b] = {
+ [0x000345] = 0x001f9b,
+ },
+ [0x001f2c] = {
+ [0x000345] = 0x001f9c,
+ },
+ [0x001f2d] = {
+ [0x000345] = 0x001f9d,
+ },
+ [0x001f2e] = {
+ [0x000345] = 0x001f9e,
+ },
+ [0x001f2f] = {
+ [0x000345] = 0x001f9f,
+ },
+ [0x001f30] = {
+ [0x000300] = 0x001f32,
+ [0x000301] = 0x001f34,
+ [0x000342] = 0x001f36,
+ },
+ [0x001f31] = {
+ [0x000300] = 0x001f33,
+ [0x000301] = 0x001f35,
+ [0x000342] = 0x001f37,
+ },
+ [0x001f38] = {
+ [0x000300] = 0x001f3a,
+ [0x000301] = 0x001f3c,
+ [0x000342] = 0x001f3e,
+ },
+ [0x001f39] = {
+ [0x000300] = 0x001f3b,
+ [0x000301] = 0x001f3d,
+ [0x000342] = 0x001f3f,
+ },
+ [0x001f40] = {
+ [0x000300] = 0x001f42,
+ [0x000301] = 0x001f44,
+ },
+ [0x001f41] = {
+ [0x000300] = 0x001f43,
+ [0x000301] = 0x001f45,
+ },
+ [0x001f48] = {
+ [0x000300] = 0x001f4a,
+ [0x000301] = 0x001f4c,
+ },
+ [0x001f49] = {
+ [0x000300] = 0x001f4b,
+ [0x000301] = 0x001f4d,
+ },
+ [0x001f50] = {
+ [0x000300] = 0x001f52,
+ [0x000301] = 0x001f54,
+ [0x000342] = 0x001f56,
+ },
+ [0x001f51] = {
+ [0x000300] = 0x001f53,
+ [0x000301] = 0x001f55,
+ [0x000342] = 0x001f57,
+ },
+ [0x001f59] = {
+ [0x000300] = 0x001f5b,
+ [0x000301] = 0x001f5d,
+ [0x000342] = 0x001f5f,
+ },
+ [0x001f60] = {
+ [0x000300] = 0x001f62,
+ [0x000301] = 0x001f64,
+ [0x000342] = 0x001f66,
+ [0x000345] = 0x001fa0,
+ },
+ [0x001f61] = {
+ [0x000300] = 0x001f63,
+ [0x000301] = 0x001f65,
+ [0x000342] = 0x001f67,
+ [0x000345] = 0x001fa1,
+ },
+ [0x001f62] = {
+ [0x000345] = 0x001fa2,
+ },
+ [0x001f63] = {
+ [0x000345] = 0x001fa3,
+ },
+ [0x001f64] = {
+ [0x000345] = 0x001fa4,
+ },
+ [0x001f65] = {
+ [0x000345] = 0x001fa5,
+ },
+ [0x001f66] = {
+ [0x000345] = 0x001fa6,
+ },
+ [0x001f67] = {
+ [0x000345] = 0x001fa7,
+ },
+ [0x001f68] = {
+ [0x000300] = 0x001f6a,
+ [0x000301] = 0x001f6c,
+ [0x000342] = 0x001f6e,
+ [0x000345] = 0x001fa8,
+ },
+ [0x001f69] = {
+ [0x000300] = 0x001f6b,
+ [0x000301] = 0x001f6d,
+ [0x000342] = 0x001f6f,
+ [0x000345] = 0x001fa9,
+ },
+ [0x001f6a] = {
+ [0x000345] = 0x001faa,
+ },
+ [0x001f6b] = {
+ [0x000345] = 0x001fab,
+ },
+ [0x001f6c] = {
+ [0x000345] = 0x001fac,
+ },
+ [0x001f6d] = {
+ [0x000345] = 0x001fad,
+ },
+ [0x001f6e] = {
+ [0x000345] = 0x001fae,
+ },
+ [0x001f6f] = {
+ [0x000345] = 0x001faf,
+ },
+ [0x001f70] = {
+ [0x000345] = 0x001fb2,
+ },
+ [0x001f74] = {
+ [0x000345] = 0x001fc2,
+ },
+ [0x001f7c] = {
+ [0x000345] = 0x001ff2,
+ },
+ [0x001fb6] = {
+ [0x000345] = 0x001fb7,
+ },
+ [0x001fbf] = {
+ [0x000300] = 0x001fcd,
+ [0x000301] = 0x001fce,
+ [0x000342] = 0x001fcf,
+ },
+ [0x001fc6] = {
+ [0x000345] = 0x001fc7,
+ },
+ [0x001ff6] = {
+ [0x000345] = 0x001ff7,
+ },
+ [0x001ffe] = {
+ [0x000300] = 0x001fdd,
+ [0x000301] = 0x001fde,
+ [0x000342] = 0x001fdf,
+ },
+ [0x002190] = {
+ [0x000338] = 0x00219a,
+ },
+ [0x002192] = {
+ [0x000338] = 0x00219b,
+ },
+ [0x002194] = {
+ [0x000338] = 0x0021ae,
+ },
+ [0x0021d0] = {
+ [0x000338] = 0x0021cd,
+ },
+ [0x0021d2] = {
+ [0x000338] = 0x0021cf,
+ },
+ [0x0021d4] = {
+ [0x000338] = 0x0021ce,
+ },
+ [0x002203] = {
+ [0x000338] = 0x002204,
+ },
+ [0x002208] = {
+ [0x000338] = 0x002209,
+ },
+ [0x00220b] = {
+ [0x000338] = 0x00220c,
+ },
+ [0x002223] = {
+ [0x000338] = 0x002224,
+ },
+ [0x002225] = {
+ [0x000338] = 0x002226,
+ },
+ [0x00223c] = {
+ [0x000338] = 0x002241,
+ },
+ [0x002243] = {
+ [0x000338] = 0x002244,
+ },
+ [0x002245] = {
+ [0x000338] = 0x002247,
+ },
+ [0x002248] = {
+ [0x000338] = 0x002249,
+ },
+ [0x00224d] = {
+ [0x000338] = 0x00226d,
+ },
+ [0x002261] = {
+ [0x000338] = 0x002262,
+ },
+ [0x002264] = {
+ [0x000338] = 0x002270,
+ },
+ [0x002265] = {
+ [0x000338] = 0x002271,
+ },
+ [0x002272] = {
+ [0x000338] = 0x002274,
+ },
+ [0x002273] = {
+ [0x000338] = 0x002275,
+ },
+ [0x002276] = {
+ [0x000338] = 0x002278,
+ },
+ [0x002277] = {
+ [0x000338] = 0x002279,
+ },
+ [0x00227a] = {
+ [0x000338] = 0x002280,
+ },
+ [0x00227b] = {
+ [0x000338] = 0x002281,
+ },
+ [0x00227c] = {
+ [0x000338] = 0x0022e0,
+ },
+ [0x00227d] = {
+ [0x000338] = 0x0022e1,
+ },
+ [0x002282] = {
+ [0x000338] = 0x002284,
+ },
+ [0x002283] = {
+ [0x000338] = 0x002285,
+ },
+ [0x002286] = {
+ [0x000338] = 0x002288,
+ },
+ [0x002287] = {
+ [0x000338] = 0x002289,
+ },
+ [0x002291] = {
+ [0x000338] = 0x0022e2,
+ },
+ [0x002292] = {
+ [0x000338] = 0x0022e3,
+ },
+ [0x0022a2] = {
+ [0x000338] = 0x0022ac,
+ },
+ [0x0022a8] = {
+ [0x000338] = 0x0022ad,
+ },
+ [0x0022a9] = {
+ [0x000338] = 0x0022ae,
+ },
+ [0x0022ab] = {
+ [0x000338] = 0x0022af,
+ },
+ [0x0022b2] = {
+ [0x000338] = 0x0022ea,
+ },
+ [0x0022b3] = {
+ [0x000338] = 0x0022eb,
+ },
+ [0x0022b4] = {
+ [0x000338] = 0x0022ec,
+ },
+ [0x0022b5] = {
+ [0x000338] = 0x0022ed,
+ },
+ [0x003046] = {
+ [0x003099] = 0x003094,
+ },
+ [0x00304b] = {
+ [0x003099] = 0x00304c,
+ },
+ [0x00304d] = {
+ [0x003099] = 0x00304e,
+ },
+ [0x00304f] = {
+ [0x003099] = 0x003050,
+ },
+ [0x003051] = {
+ [0x003099] = 0x003052,
+ },
+ [0x003053] = {
+ [0x003099] = 0x003054,
+ },
+ [0x003055] = {
+ [0x003099] = 0x003056,
+ },
+ [0x003057] = {
+ [0x003099] = 0x003058,
+ },
+ [0x003059] = {
+ [0x003099] = 0x00305a,
+ },
+ [0x00305b] = {
+ [0x003099] = 0x00305c,
+ },
+ [0x00305d] = {
+ [0x003099] = 0x00305e,
+ },
+ [0x00305f] = {
+ [0x003099] = 0x003060,
+ },
+ [0x003061] = {
+ [0x003099] = 0x003062,
+ },
+ [0x003064] = {
+ [0x003099] = 0x003065,
+ },
+ [0x003066] = {
+ [0x003099] = 0x003067,
+ },
+ [0x003068] = {
+ [0x003099] = 0x003069,
+ },
+ [0x00306f] = {
+ [0x003099] = 0x003070,
+ [0x00309a] = 0x003071,
+ },
+ [0x003072] = {
+ [0x003099] = 0x003073,
+ [0x00309a] = 0x003074,
+ },
+ [0x003075] = {
+ [0x003099] = 0x003076,
+ [0x00309a] = 0x003077,
+ },
+ [0x003078] = {
+ [0x003099] = 0x003079,
+ [0x00309a] = 0x00307a,
+ },
+ [0x00307b] = {
+ [0x003099] = 0x00307c,
+ [0x00309a] = 0x00307d,
+ },
+ [0x00309d] = {
+ [0x003099] = 0x00309e,
+ },
+ [0x0030a6] = {
+ [0x003099] = 0x0030f4,
+ },
+ [0x0030ab] = {
+ [0x003099] = 0x0030ac,
+ },
+ [0x0030ad] = {
+ [0x003099] = 0x0030ae,
+ },
+ [0x0030af] = {
+ [0x003099] = 0x0030b0,
+ },
+ [0x0030b1] = {
+ [0x003099] = 0x0030b2,
+ },
+ [0x0030b3] = {
+ [0x003099] = 0x0030b4,
+ },
+ [0x0030b5] = {
+ [0x003099] = 0x0030b6,
+ },
+ [0x0030b7] = {
+ [0x003099] = 0x0030b8,
+ },
+ [0x0030b9] = {
+ [0x003099] = 0x0030ba,
+ },
+ [0x0030bb] = {
+ [0x003099] = 0x0030bc,
+ },
+ [0x0030bd] = {
+ [0x003099] = 0x0030be,
+ },
+ [0x0030bf] = {
+ [0x003099] = 0x0030c0,
+ },
+ [0x0030c1] = {
+ [0x003099] = 0x0030c2,
+ },
+ [0x0030c4] = {
+ [0x003099] = 0x0030c5,
+ },
+ [0x0030c6] = {
+ [0x003099] = 0x0030c7,
+ },
+ [0x0030c8] = {
+ [0x003099] = 0x0030c9,
+ },
+ [0x0030cf] = {
+ [0x003099] = 0x0030d0,
+ [0x00309a] = 0x0030d1,
+ },
+ [0x0030d2] = {
+ [0x003099] = 0x0030d3,
+ [0x00309a] = 0x0030d4,
+ },
+ [0x0030d5] = {
+ [0x003099] = 0x0030d6,
+ [0x00309a] = 0x0030d7,
+ },
+ [0x0030d8] = {
+ [0x003099] = 0x0030d9,
+ [0x00309a] = 0x0030da,
+ },
+ [0x0030db] = {
+ [0x003099] = 0x0030dc,
+ [0x00309a] = 0x0030dd,
+ },
+ [0x0030ef] = {
+ [0x003099] = 0x0030f7,
+ },
+ [0x0030f0] = {
+ [0x003099] = 0x0030f8,
+ },
+ [0x0030f1] = {
+ [0x003099] = 0x0030f9,
+ },
+ [0x0030f2] = {
+ [0x003099] = 0x0030fa,
+ },
+ [0x0030fd] = {
+ [0x003099] = 0x0030fe,
+ },
+ [0x011099] = {
+ [0x0110ba] = 0x01109a,
+ },
+ [0x01109b] = {
+ [0x0110ba] = 0x01109c,
+ },
+ [0x0110a5] = {
+ [0x0110ba] = 0x0110ab,
+ },
+ [0x011131] = {
+ [0x011127] = 0x01112e,
+ },
+ [0x011132] = {
+ [0x011127] = 0x01112f,
+ },
+ [0x011347] = {
+ [0x01133e] = 0x01134b,
+ [0x011357] = 0x01134c,
+ },
+ [0x0114b9] = {
+ [0x0114b0] = 0x0114bc,
+ [0x0114ba] = 0x0114bb,
+ [0x0114bd] = 0x0114be,
+ },
+ [0x0115b8] = {
+ [0x0115af] = 0x0115ba,
+ },
+ [0x0115b9] = {
+ [0x0115af] = 0x0115bb,
+ },
+ },
+}
+
+-- All combining characters need to be checked, so just do that
+setmetatable( normal.check, { __index = normal.combclass } )
+
+-- Handle Hangul to Jamo decomposition
+setmetatable( normal.decomp, { __index = function ( _, k )
+ if k >= 0xac00 and k <= 0xd7a3 then
+ -- Decompose a Hangul syllable into Jamo
+ k = k - 0xac00
+ local ret = {
+ 0x1100 + math.floor( k / 588 ),
+ 0x1161 + math.floor( ( k % 588 ) / 28 )
+ }
+ if k % 28 ~= 0 then
+ ret[3] = 0x11a7 + ( k % 28 )
+ end
+ return ret
+ end
+ return nil
+end } )
+
+-- Handle Jamo to Hangul composition
+local jamo_l_v_mt = { __index = function ( t, k )
+ if k >= 0x1161 and k <= 0x1175 then
+ -- Jamo leading + Jamo vowel
+ return t.base + 28 * ( k - 0x1161 )
+ end
+ return nil
+end }
+local hangul_jamo_mt = { __index = function ( t, k )
+ if k >= 0x11a7 and k <= 0x11c2 then
+ -- Hangul + jamo final
+ return t.base + k - 0x11a7
+ end
+ return nil
+end }
+setmetatable( normal.comp, { __index = function ( t, k )
+ if k >= 0x1100 and k <= 0x1112 then
+ -- Jamo leading, return a second table that combines with a Jamo vowel
+ local t2 = { base = 0xac00 + 588 * ( k - 0x1100 ) }
+ setmetatable( t2, jamo_l_v_mt )
+ t[k] = t2 -- cache it
+ return t2
+ elseif k >= 0xac00 and k <= 0xd7a3 and k % 28 == 16 then
+ -- Hangul. "k % 28 == 16" picks out just the ones that are
+ -- Jamo leading + vowel, no final. Return a second table that combines
+ -- with a Jamo final.
+ local t2 = { base = k }
+ setmetatable( t2, hangul_jamo_mt )
+ t[k] = t2 -- cache it
+ return t2
+ end
+ return nil
+end } )
+
+-- Compatibility decomposition falls back to the normal decomposition
+setmetatable( normal.decompK, { __index = normal.decomp } )
+
+return normal
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/string.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/string.lua
new file mode 100644
index 00000000..1319e342
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/string.lua
@@ -0,0 +1,15 @@
+string.isutf8 = ustring.isutf8
+string.byteoffset = ustring.byteoffset
+string.codepoint = ustring.codepoint
+string.gcodepoint = ustring.gcodepoint
+string.toNFC = ustring.toNFC
+string.toNFD = ustring.toNFD
+string.uchar = ustring.char
+string.ulen = ustring.len
+string.usub = ustring.sub
+string.uupper = ustring.upper
+string.ulower = ustring.lower
+string.ufind = ustring.find
+string.umatch = ustring.match
+string.ugmatch = ustring.gmatch
+string.ugsub = ustring.gsub
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/upper.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/upper.lua
new file mode 100644
index 00000000..cfb0e158
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/upper.lua
@@ -0,0 +1,715 @@
+-- This file is automatically generated by make-tables.php
+return {
+ ["a"] = "A",
+ ["b"] = "B",
+ ["c"] = "C",
+ ["d"] = "D",
+ ["e"] = "E",
+ ["f"] = "F",
+ ["g"] = "G",
+ ["h"] = "H",
+ ["i"] = "I",
+ ["j"] = "J",
+ ["k"] = "K",
+ ["l"] = "L",
+ ["m"] = "M",
+ ["n"] = "N",
+ ["o"] = "O",
+ ["p"] = "P",
+ ["q"] = "Q",
+ ["r"] = "R",
+ ["s"] = "S",
+ ["t"] = "T",
+ ["u"] = "U",
+ ["v"] = "V",
+ ["w"] = "W",
+ ["x"] = "X",
+ ["y"] = "Y",
+ ["z"] = "Z",
+ ["µ"] = "Μ",
+ ["à"] = "À",
+ ["á"] = "Á",
+ ["â"] = "Â",
+ ["ã"] = "Ã",
+ ["ä"] = "Ä",
+ ["å"] = "Å",
+ ["æ"] = "Æ",
+ ["ç"] = "Ç",
+ ["è"] = "È",
+ ["é"] = "É",
+ ["ê"] = "Ê",
+ ["ë"] = "Ë",
+ ["ì"] = "Ì",
+ ["í"] = "Í",
+ ["î"] = "Î",
+ ["ï"] = "Ï",
+ ["ð"] = "Ð",
+ ["ñ"] = "Ñ",
+ ["ò"] = "Ò",
+ ["ó"] = "Ó",
+ ["ô"] = "Ô",
+ ["õ"] = "Õ",
+ ["ö"] = "Ö",
+ ["ø"] = "Ø",
+ ["ù"] = "Ù",
+ ["ú"] = "Ú",
+ ["û"] = "Û",
+ ["ü"] = "Ü",
+ ["ý"] = "Ý",
+ ["þ"] = "Þ",
+ ["ÿ"] = "Ÿ",
+ ["ā"] = "Ā",
+ ["ă"] = "Ă",
+ ["ą"] = "Ą",
+ ["ć"] = "Ć",
+ ["ĉ"] = "Ĉ",
+ ["ċ"] = "Ċ",
+ ["č"] = "Č",
+ ["ď"] = "Ď",
+ ["đ"] = "Đ",
+ ["ē"] = "Ē",
+ ["ĕ"] = "Ĕ",
+ ["ė"] = "Ė",
+ ["ę"] = "Ę",
+ ["ě"] = "Ě",
+ ["ĝ"] = "Ĝ",
+ ["ğ"] = "Ğ",
+ ["ġ"] = "Ġ",
+ ["ģ"] = "Ģ",
+ ["ĥ"] = "Ĥ",
+ ["ħ"] = "Ħ",
+ ["ĩ"] = "Ĩ",
+ ["ī"] = "Ī",
+ ["ĭ"] = "Ĭ",
+ ["į"] = "Į",
+ ["ı"] = "I",
+ ["ij"] = "IJ",
+ ["ĵ"] = "Ĵ",
+ ["ķ"] = "Ķ",
+ ["ĺ"] = "Ĺ",
+ ["ļ"] = "Ļ",
+ ["ľ"] = "Ľ",
+ ["ŀ"] = "Ŀ",
+ ["ł"] = "Ł",
+ ["ń"] = "Ń",
+ ["ņ"] = "Ņ",
+ ["ň"] = "Ň",
+ ["ŋ"] = "Ŋ",
+ ["ō"] = "Ō",
+ ["ŏ"] = "Ŏ",
+ ["ő"] = "Ő",
+ ["œ"] = "Œ",
+ ["ŕ"] = "Ŕ",
+ ["ŗ"] = "Ŗ",
+ ["ř"] = "Ř",
+ ["ś"] = "Ś",
+ ["ŝ"] = "Ŝ",
+ ["ş"] = "Ş",
+ ["š"] = "Š",
+ ["ţ"] = "Ţ",
+ ["ť"] = "Ť",
+ ["ŧ"] = "Ŧ",
+ ["ũ"] = "Ũ",
+ ["ū"] = "Ū",
+ ["ŭ"] = "Ŭ",
+ ["ů"] = "Ů",
+ ["ű"] = "Ű",
+ ["ų"] = "Ų",
+ ["ŵ"] = "Ŵ",
+ ["ŷ"] = "Ŷ",
+ ["ź"] = "Ź",
+ ["ż"] = "Ż",
+ ["ž"] = "Ž",
+ ["ſ"] = "S",
+ ["ƃ"] = "Ƃ",
+ ["ƅ"] = "Ƅ",
+ ["ƈ"] = "Ƈ",
+ ["ƌ"] = "Ƌ",
+ ["ƒ"] = "Ƒ",
+ ["ƕ"] = "Ƕ",
+ ["ƙ"] = "Ƙ",
+ ["ƞ"] = "Ƞ",
+ ["ơ"] = "Ơ",
+ ["ƣ"] = "Ƣ",
+ ["ƥ"] = "Ƥ",
+ ["ƨ"] = "Ƨ",
+ ["ƭ"] = "Ƭ",
+ ["ư"] = "Ư",
+ ["ƴ"] = "Ƴ",
+ ["ƶ"] = "Ƶ",
+ ["ƹ"] = "Ƹ",
+ ["ƽ"] = "Ƽ",
+ ["ƿ"] = "Ƿ",
+ ["dž"] = "Dž",
+ ["lj"] = "Lj",
+ ["nj"] = "Nj",
+ ["ǎ"] = "Ǎ",
+ ["ǐ"] = "Ǐ",
+ ["ǒ"] = "Ǒ",
+ ["ǔ"] = "Ǔ",
+ ["ǖ"] = "Ǖ",
+ ["ǘ"] = "Ǘ",
+ ["ǚ"] = "Ǚ",
+ ["ǜ"] = "Ǜ",
+ ["ǝ"] = "Ǝ",
+ ["ǟ"] = "Ǟ",
+ ["ǡ"] = "Ǡ",
+ ["ǣ"] = "Ǣ",
+ ["ǥ"] = "Ǥ",
+ ["ǧ"] = "Ǧ",
+ ["ǩ"] = "Ǩ",
+ ["ǫ"] = "Ǫ",
+ ["ǭ"] = "Ǭ",
+ ["ǯ"] = "Ǯ",
+ ["dz"] = "Dz",
+ ["ǵ"] = "Ǵ",
+ ["ǹ"] = "Ǹ",
+ ["ǻ"] = "Ǻ",
+ ["ǽ"] = "Ǽ",
+ ["ǿ"] = "Ǿ",
+ ["ȁ"] = "Ȁ",
+ ["ȃ"] = "Ȃ",
+ ["ȅ"] = "Ȅ",
+ ["ȇ"] = "Ȇ",
+ ["ȉ"] = "Ȉ",
+ ["ȋ"] = "Ȋ",
+ ["ȍ"] = "Ȍ",
+ ["ȏ"] = "Ȏ",
+ ["ȑ"] = "Ȑ",
+ ["ȓ"] = "Ȓ",
+ ["ȕ"] = "Ȕ",
+ ["ȗ"] = "Ȗ",
+ ["ș"] = "Ș",
+ ["ț"] = "Ț",
+ ["ȝ"] = "Ȝ",
+ ["ȟ"] = "Ȟ",
+ ["ȣ"] = "Ȣ",
+ ["ȥ"] = "Ȥ",
+ ["ȧ"] = "Ȧ",
+ ["ȩ"] = "Ȩ",
+ ["ȫ"] = "Ȫ",
+ ["ȭ"] = "Ȭ",
+ ["ȯ"] = "Ȯ",
+ ["ȱ"] = "Ȱ",
+ ["ȳ"] = "Ȳ",
+ ["ɓ"] = "Ɓ",
+ ["ɔ"] = "Ɔ",
+ ["ɖ"] = "Ɖ",
+ ["ɗ"] = "Ɗ",
+ ["ə"] = "Ə",
+ ["ɛ"] = "Ɛ",
+ ["ɠ"] = "Ɠ",
+ ["ɣ"] = "Ɣ",
+ ["ɨ"] = "Ɨ",
+ ["ɩ"] = "Ɩ",
+ ["ɯ"] = "Ɯ",
+ ["ɲ"] = "Ɲ",
+ ["ɵ"] = "Ɵ",
+ ["ʀ"] = "Ʀ",
+ ["ʃ"] = "Ʃ",
+ ["ʈ"] = "Ʈ",
+ ["ʊ"] = "Ʊ",
+ ["ʋ"] = "Ʋ",
+ ["ʒ"] = "Ʒ",
+ ["ά"] = "Ά",
+ ["έ"] = "Έ",
+ ["ή"] = "Ή",
+ ["ί"] = "Ί",
+ ["α"] = "Α",
+ ["β"] = "Β",
+ ["γ"] = "Γ",
+ ["δ"] = "Δ",
+ ["ε"] = "Ε",
+ ["ζ"] = "Ζ",
+ ["η"] = "Η",
+ ["θ"] = "Θ",
+ ["ι"] = "Ι",
+ ["κ"] = "Κ",
+ ["λ"] = "Λ",
+ ["μ"] = "Μ",
+ ["ν"] = "Ν",
+ ["ξ"] = "Ξ",
+ ["ο"] = "Ο",
+ ["π"] = "Π",
+ ["ρ"] = "Ρ",
+ ["ς"] = "Σ",
+ ["σ"] = "Σ",
+ ["τ"] = "Τ",
+ ["υ"] = "Υ",
+ ["φ"] = "Φ",
+ ["χ"] = "Χ",
+ ["ψ"] = "Ψ",
+ ["ω"] = "Ω",
+ ["ϊ"] = "Ϊ",
+ ["ϋ"] = "Ϋ",
+ ["ό"] = "Ό",
+ ["ύ"] = "Ύ",
+ ["ώ"] = "Ώ",
+ ["ϐ"] = "Β",
+ ["ϑ"] = "Θ",
+ ["ϕ"] = "Φ",
+ ["ϖ"] = "Π",
+ ["ϙ"] = "Ϙ",
+ ["ϛ"] = "Ϛ",
+ ["ϝ"] = "Ϝ",
+ ["ϟ"] = "Ϟ",
+ ["ϡ"] = "Ϡ",
+ ["ϣ"] = "Ϣ",
+ ["ϥ"] = "Ϥ",
+ ["ϧ"] = "Ϧ",
+ ["ϩ"] = "Ϩ",
+ ["ϫ"] = "Ϫ",
+ ["ϭ"] = "Ϭ",
+ ["ϯ"] = "Ϯ",
+ ["ϰ"] = "Κ",
+ ["ϱ"] = "Ρ",
+ ["ϲ"] = "Σ",
+ ["ϵ"] = "Ε",
+ ["а"] = "А",
+ ["б"] = "Б",
+ ["в"] = "В",
+ ["г"] = "Г",
+ ["д"] = "Д",
+ ["е"] = "Е",
+ ["ж"] = "Ж",
+ ["з"] = "З",
+ ["и"] = "И",
+ ["й"] = "Й",
+ ["к"] = "К",
+ ["л"] = "Л",
+ ["м"] = "М",
+ ["н"] = "Н",
+ ["о"] = "О",
+ ["п"] = "П",
+ ["р"] = "Р",
+ ["с"] = "С",
+ ["т"] = "Т",
+ ["у"] = "У",
+ ["ф"] = "Ф",
+ ["х"] = "Х",
+ ["ц"] = "Ц",
+ ["ч"] = "Ч",
+ ["ш"] = "Ш",
+ ["щ"] = "Щ",
+ ["ъ"] = "Ъ",
+ ["ы"] = "Ы",
+ ["ь"] = "Ь",
+ ["э"] = "Э",
+ ["ю"] = "Ю",
+ ["я"] = "Я",
+ ["ѐ"] = "Ѐ",
+ ["ё"] = "Ё",
+ ["ђ"] = "Ђ",
+ ["ѓ"] = "Ѓ",
+ ["є"] = "Є",
+ ["ѕ"] = "Ѕ",
+ ["і"] = "І",
+ ["ї"] = "Ї",
+ ["ј"] = "Ј",
+ ["љ"] = "Љ",
+ ["њ"] = "Њ",
+ ["ћ"] = "Ћ",
+ ["ќ"] = "Ќ",
+ ["ѝ"] = "Ѝ",
+ ["ў"] = "Ў",
+ ["џ"] = "Џ",
+ ["ѡ"] = "Ѡ",
+ ["ѣ"] = "Ѣ",
+ ["ѥ"] = "Ѥ",
+ ["ѧ"] = "Ѧ",
+ ["ѩ"] = "Ѩ",
+ ["ѫ"] = "Ѫ",
+ ["ѭ"] = "Ѭ",
+ ["ѯ"] = "Ѯ",
+ ["ѱ"] = "Ѱ",
+ ["ѳ"] = "Ѳ",
+ ["ѵ"] = "Ѵ",
+ ["ѷ"] = "Ѷ",
+ ["ѹ"] = "Ѹ",
+ ["ѻ"] = "Ѻ",
+ ["ѽ"] = "Ѽ",
+ ["ѿ"] = "Ѿ",
+ ["ҁ"] = "Ҁ",
+ ["ҋ"] = "Ҋ",
+ ["ҍ"] = "Ҍ",
+ ["ҏ"] = "Ҏ",
+ ["ґ"] = "Ґ",
+ ["ғ"] = "Ғ",
+ ["ҕ"] = "Ҕ",
+ ["җ"] = "Җ",
+ ["ҙ"] = "Ҙ",
+ ["қ"] = "Қ",
+ ["ҝ"] = "Ҝ",
+ ["ҟ"] = "Ҟ",
+ ["ҡ"] = "Ҡ",
+ ["ң"] = "Ң",
+ ["ҥ"] = "Ҥ",
+ ["ҧ"] = "Ҧ",
+ ["ҩ"] = "Ҩ",
+ ["ҫ"] = "Ҫ",
+ ["ҭ"] = "Ҭ",
+ ["ү"] = "Ү",
+ ["ұ"] = "Ұ",
+ ["ҳ"] = "Ҳ",
+ ["ҵ"] = "Ҵ",
+ ["ҷ"] = "Ҷ",
+ ["ҹ"] = "Ҹ",
+ ["һ"] = "Һ",
+ ["ҽ"] = "Ҽ",
+ ["ҿ"] = "Ҿ",
+ ["ӂ"] = "Ӂ",
+ ["ӄ"] = "Ӄ",
+ ["ӆ"] = "Ӆ",
+ ["ӈ"] = "Ӈ",
+ ["ӊ"] = "Ӊ",
+ ["ӌ"] = "Ӌ",
+ ["ӎ"] = "Ӎ",
+ ["ӑ"] = "Ӑ",
+ ["ӓ"] = "Ӓ",
+ ["ӕ"] = "Ӕ",
+ ["ӗ"] = "Ӗ",
+ ["ә"] = "Ә",
+ ["ӛ"] = "Ӛ",
+ ["ӝ"] = "Ӝ",
+ ["ӟ"] = "Ӟ",
+ ["ӡ"] = "Ӡ",
+ ["ӣ"] = "Ӣ",
+ ["ӥ"] = "Ӥ",
+ ["ӧ"] = "Ӧ",
+ ["ө"] = "Ө",
+ ["ӫ"] = "Ӫ",
+ ["ӭ"] = "Ӭ",
+ ["ӯ"] = "Ӯ",
+ ["ӱ"] = "Ӱ",
+ ["ӳ"] = "Ӳ",
+ ["ӵ"] = "Ӵ",
+ ["ӹ"] = "Ӹ",
+ ["ԁ"] = "Ԁ",
+ ["ԃ"] = "Ԃ",
+ ["ԅ"] = "Ԅ",
+ ["ԇ"] = "Ԇ",
+ ["ԉ"] = "Ԉ",
+ ["ԋ"] = "Ԋ",
+ ["ԍ"] = "Ԍ",
+ ["ԏ"] = "Ԏ",
+ ["ա"] = "Ա",
+ ["բ"] = "Բ",
+ ["գ"] = "Գ",
+ ["դ"] = "Դ",
+ ["ե"] = "Ե",
+ ["զ"] = "Զ",
+ ["է"] = "Է",
+ ["ը"] = "Ը",
+ ["թ"] = "Թ",
+ ["ժ"] = "Ժ",
+ ["ի"] = "Ի",
+ ["լ"] = "Լ",
+ ["խ"] = "Խ",
+ ["ծ"] = "Ծ",
+ ["կ"] = "Կ",
+ ["հ"] = "Հ",
+ ["ձ"] = "Ձ",
+ ["ղ"] = "Ղ",
+ ["ճ"] = "Ճ",
+ ["մ"] = "Մ",
+ ["յ"] = "Յ",
+ ["ն"] = "Ն",
+ ["շ"] = "Շ",
+ ["ո"] = "Ո",
+ ["չ"] = "Չ",
+ ["պ"] = "Պ",
+ ["ջ"] = "Ջ",
+ ["ռ"] = "Ռ",
+ ["ս"] = "Ս",
+ ["վ"] = "Վ",
+ ["տ"] = "Տ",
+ ["ր"] = "Ր",
+ ["ց"] = "Ց",
+ ["ւ"] = "Ւ",
+ ["փ"] = "Փ",
+ ["ք"] = "Ք",
+ ["օ"] = "Օ",
+ ["ֆ"] = "Ֆ",
+ ["ḁ"] = "Ḁ",
+ ["ḃ"] = "Ḃ",
+ ["ḅ"] = "Ḅ",
+ ["ḇ"] = "Ḇ",
+ ["ḉ"] = "Ḉ",
+ ["ḋ"] = "Ḋ",
+ ["ḍ"] = "Ḍ",
+ ["ḏ"] = "Ḏ",
+ ["ḑ"] = "Ḑ",
+ ["ḓ"] = "Ḓ",
+ ["ḕ"] = "Ḕ",
+ ["ḗ"] = "Ḗ",
+ ["ḙ"] = "Ḙ",
+ ["ḛ"] = "Ḛ",
+ ["ḝ"] = "Ḝ",
+ ["ḟ"] = "Ḟ",
+ ["ḡ"] = "Ḡ",
+ ["ḣ"] = "Ḣ",
+ ["ḥ"] = "Ḥ",
+ ["ḧ"] = "Ḧ",
+ ["ḩ"] = "Ḩ",
+ ["ḫ"] = "Ḫ",
+ ["ḭ"] = "Ḭ",
+ ["ḯ"] = "Ḯ",
+ ["ḱ"] = "Ḱ",
+ ["ḳ"] = "Ḳ",
+ ["ḵ"] = "Ḵ",
+ ["ḷ"] = "Ḷ",
+ ["ḹ"] = "Ḹ",
+ ["ḻ"] = "Ḻ",
+ ["ḽ"] = "Ḽ",
+ ["ḿ"] = "Ḿ",
+ ["ṁ"] = "Ṁ",
+ ["ṃ"] = "Ṃ",
+ ["ṅ"] = "Ṅ",
+ ["ṇ"] = "Ṇ",
+ ["ṉ"] = "Ṉ",
+ ["ṋ"] = "Ṋ",
+ ["ṍ"] = "Ṍ",
+ ["ṏ"] = "Ṏ",
+ ["ṑ"] = "Ṑ",
+ ["ṓ"] = "Ṓ",
+ ["ṕ"] = "Ṕ",
+ ["ṗ"] = "Ṗ",
+ ["ṙ"] = "Ṙ",
+ ["ṛ"] = "Ṛ",
+ ["ṝ"] = "Ṝ",
+ ["ṟ"] = "Ṟ",
+ ["ṡ"] = "Ṡ",
+ ["ṣ"] = "Ṣ",
+ ["ṥ"] = "Ṥ",
+ ["ṧ"] = "Ṧ",
+ ["ṩ"] = "Ṩ",
+ ["ṫ"] = "Ṫ",
+ ["ṭ"] = "Ṭ",
+ ["ṯ"] = "Ṯ",
+ ["ṱ"] = "Ṱ",
+ ["ṳ"] = "Ṳ",
+ ["ṵ"] = "Ṵ",
+ ["ṷ"] = "Ṷ",
+ ["ṹ"] = "Ṹ",
+ ["ṻ"] = "Ṻ",
+ ["ṽ"] = "Ṽ",
+ ["ṿ"] = "Ṿ",
+ ["ẁ"] = "Ẁ",
+ ["ẃ"] = "Ẃ",
+ ["ẅ"] = "Ẅ",
+ ["ẇ"] = "Ẇ",
+ ["ẉ"] = "Ẉ",
+ ["ẋ"] = "Ẋ",
+ ["ẍ"] = "Ẍ",
+ ["ẏ"] = "Ẏ",
+ ["ẑ"] = "Ẑ",
+ ["ẓ"] = "Ẓ",
+ ["ẕ"] = "Ẕ",
+ ["ẛ"] = "Ṡ",
+ ["ạ"] = "Ạ",
+ ["ả"] = "Ả",
+ ["ấ"] = "Ấ",
+ ["ầ"] = "Ầ",
+ ["ẩ"] = "Ẩ",
+ ["ẫ"] = "Ẫ",
+ ["ậ"] = "Ậ",
+ ["ắ"] = "Ắ",
+ ["ằ"] = "Ằ",
+ ["ẳ"] = "Ẳ",
+ ["ẵ"] = "Ẵ",
+ ["ặ"] = "Ặ",
+ ["ẹ"] = "Ẹ",
+ ["ẻ"] = "Ẻ",
+ ["ẽ"] = "Ẽ",
+ ["ế"] = "Ế",
+ ["ề"] = "Ề",
+ ["ể"] = "Ể",
+ ["ễ"] = "Ễ",
+ ["ệ"] = "Ệ",
+ ["ỉ"] = "Ỉ",
+ ["ị"] = "Ị",
+ ["ọ"] = "Ọ",
+ ["ỏ"] = "Ỏ",
+ ["ố"] = "Ố",
+ ["ồ"] = "Ồ",
+ ["ổ"] = "Ổ",
+ ["ỗ"] = "Ỗ",
+ ["ộ"] = "Ộ",
+ ["ớ"] = "Ớ",
+ ["ờ"] = "Ờ",
+ ["ở"] = "Ở",
+ ["ỡ"] = "Ỡ",
+ ["ợ"] = "Ợ",
+ ["ụ"] = "Ụ",
+ ["ủ"] = "Ủ",
+ ["ứ"] = "Ứ",
+ ["ừ"] = "Ừ",
+ ["ử"] = "Ử",
+ ["ữ"] = "Ữ",
+ ["ự"] = "Ự",
+ ["ỳ"] = "Ỳ",
+ ["ỵ"] = "Ỵ",
+ ["ỷ"] = "Ỷ",
+ ["ỹ"] = "Ỹ",
+ ["ἀ"] = "Ἀ",
+ ["ἁ"] = "Ἁ",
+ ["ἂ"] = "Ἂ",
+ ["ἃ"] = "Ἃ",
+ ["ἄ"] = "Ἄ",
+ ["ἅ"] = "Ἅ",
+ ["ἆ"] = "Ἆ",
+ ["ἇ"] = "Ἇ",
+ ["ἐ"] = "Ἐ",
+ ["ἑ"] = "Ἑ",
+ ["ἒ"] = "Ἒ",
+ ["ἓ"] = "Ἓ",
+ ["ἔ"] = "Ἔ",
+ ["ἕ"] = "Ἕ",
+ ["ἠ"] = "Ἠ",
+ ["ἡ"] = "Ἡ",
+ ["ἢ"] = "Ἢ",
+ ["ἣ"] = "Ἣ",
+ ["ἤ"] = "Ἤ",
+ ["ἥ"] = "Ἥ",
+ ["ἦ"] = "Ἦ",
+ ["ἧ"] = "Ἧ",
+ ["ἰ"] = "Ἰ",
+ ["ἱ"] = "Ἱ",
+ ["ἲ"] = "Ἲ",
+ ["ἳ"] = "Ἳ",
+ ["ἴ"] = "Ἴ",
+ ["ἵ"] = "Ἵ",
+ ["ἶ"] = "Ἶ",
+ ["ἷ"] = "Ἷ",
+ ["ὀ"] = "Ὀ",
+ ["ὁ"] = "Ὁ",
+ ["ὂ"] = "Ὂ",
+ ["ὃ"] = "Ὃ",
+ ["ὄ"] = "Ὄ",
+ ["ὅ"] = "Ὅ",
+ ["ὑ"] = "Ὑ",
+ ["ὓ"] = "Ὓ",
+ ["ὕ"] = "Ὕ",
+ ["ὗ"] = "Ὗ",
+ ["ὠ"] = "Ὠ",
+ ["ὡ"] = "Ὡ",
+ ["ὢ"] = "Ὢ",
+ ["ὣ"] = "Ὣ",
+ ["ὤ"] = "Ὤ",
+ ["ὥ"] = "Ὥ",
+ ["ὦ"] = "Ὦ",
+ ["ὧ"] = "Ὧ",
+ ["ὰ"] = "Ὰ",
+ ["ά"] = "Ά",
+ ["ὲ"] = "Ὲ",
+ ["έ"] = "Έ",
+ ["ὴ"] = "Ὴ",
+ ["ή"] = "Ή",
+ ["ὶ"] = "Ὶ",
+ ["ί"] = "Ί",
+ ["ὸ"] = "Ὸ",
+ ["ό"] = "Ό",
+ ["ὺ"] = "Ὺ",
+ ["ύ"] = "Ύ",
+ ["ὼ"] = "Ὼ",
+ ["ώ"] = "Ώ",
+ ["ᾀ"] = "ᾈ",
+ ["ᾁ"] = "ᾉ",
+ ["ᾂ"] = "ᾊ",
+ ["ᾃ"] = "ᾋ",
+ ["ᾄ"] = "ᾌ",
+ ["ᾅ"] = "ᾍ",
+ ["ᾆ"] = "ᾎ",
+ ["ᾇ"] = "ᾏ",
+ ["ᾐ"] = "ᾘ",
+ ["ᾑ"] = "ᾙ",
+ ["ᾒ"] = "ᾚ",
+ ["ᾓ"] = "ᾛ",
+ ["ᾔ"] = "ᾜ",
+ ["ᾕ"] = "ᾝ",
+ ["ᾖ"] = "ᾞ",
+ ["ᾗ"] = "ᾟ",
+ ["ᾠ"] = "ᾨ",
+ ["ᾡ"] = "ᾩ",
+ ["ᾢ"] = "ᾪ",
+ ["ᾣ"] = "ᾫ",
+ ["ᾤ"] = "ᾬ",
+ ["ᾥ"] = "ᾭ",
+ ["ᾦ"] = "ᾮ",
+ ["ᾧ"] = "ᾯ",
+ ["ᾰ"] = "Ᾰ",
+ ["ᾱ"] = "Ᾱ",
+ ["ᾳ"] = "ᾼ",
+ ["ι"] = "Ι",
+ ["ῃ"] = "ῌ",
+ ["ῐ"] = "Ῐ",
+ ["ῑ"] = "Ῑ",
+ ["ῠ"] = "Ῠ",
+ ["ῡ"] = "Ῡ",
+ ["ῥ"] = "Ῥ",
+ ["ῳ"] = "ῼ",
+ ["a"] = "A",
+ ["b"] = "B",
+ ["c"] = "C",
+ ["d"] = "D",
+ ["e"] = "E",
+ ["f"] = "F",
+ ["g"] = "G",
+ ["h"] = "H",
+ ["i"] = "I",
+ ["j"] = "J",
+ ["k"] = "K",
+ ["l"] = "L",
+ ["m"] = "M",
+ ["n"] = "N",
+ ["o"] = "O",
+ ["p"] = "P",
+ ["q"] = "Q",
+ ["r"] = "R",
+ ["s"] = "S",
+ ["t"] = "T",
+ ["u"] = "U",
+ ["v"] = "V",
+ ["w"] = "W",
+ ["x"] = "X",
+ ["y"] = "Y",
+ ["z"] = "Z",
+ ["𐐨"] = "𐐀",
+ ["𐐩"] = "𐐁",
+ ["𐐪"] = "𐐂",
+ ["𐐫"] = "𐐃",
+ ["𐐬"] = "𐐄",
+ ["𐐭"] = "𐐅",
+ ["𐐮"] = "𐐆",
+ ["𐐯"] = "𐐇",
+ ["𐐰"] = "𐐈",
+ ["𐐱"] = "𐐉",
+ ["𐐲"] = "𐐊",
+ ["𐐳"] = "𐐋",
+ ["𐐴"] = "𐐌",
+ ["𐐵"] = "𐐍",
+ ["𐐶"] = "𐐎",
+ ["𐐷"] = "𐐏",
+ ["𐐸"] = "𐐐",
+ ["𐐹"] = "𐐑",
+ ["𐐺"] = "𐐒",
+ ["𐐻"] = "𐐓",
+ ["𐐼"] = "𐐔",
+ ["𐐽"] = "𐐕",
+ ["𐐾"] = "𐐖",
+ ["𐐿"] = "𐐗",
+ ["𐑀"] = "𐐘",
+ ["𐑁"] = "𐐙",
+ ["𐑂"] = "𐐚",
+ ["𐑃"] = "𐐛",
+ ["𐑄"] = "𐐜",
+ ["𐑅"] = "𐐝",
+ ["𐑆"] = "𐐞",
+ ["𐑇"] = "𐐟",
+ ["𐑈"] = "𐐠",
+ ["𐑉"] = "𐐡",
+ ["𐑊"] = "𐐢",
+ ["𐑋"] = "𐐣",
+ ["𐑌"] = "𐐤",
+ ["𐑍"] = "𐐥",
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/ustring.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/ustring.lua
new file mode 100644
index 00000000..69bfd1d0
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaCommon/lualib/ustring/ustring.lua
@@ -0,0 +1,1242 @@
+local ustring = {}
+
+-- Copy these, just in case
+local S = {
+ byte = string.byte,
+ char = string.char,
+ len = string.len,
+ sub = string.sub,
+ find = string.find,
+ match = string.match,
+ gmatch = string.gmatch,
+ gsub = string.gsub,
+ format = string.format,
+}
+
+---- Configuration ----
+-- To limit the length of strings or patterns processed, set these
+ustring.maxStringLength = math.huge
+ustring.maxPatternLength = math.huge
+
+---- Utility functions ----
+
+local function checkType( name, argidx, arg, expecttype, nilok )
+ if arg == nil and nilok then
+ return
+ end
+ if type( arg ) ~= expecttype then
+ local msg = S.format( "bad argument #%d to '%s' (%s expected, got %s)",
+ argidx, name, expecttype, type( arg )
+ )
+ error( msg, 3 )
+ end
+end
+
+local function checkString( name, s )
+ if type( s ) == 'number' then
+ s = tostring( s )
+ end
+ if type( s ) ~= 'string' then
+ local msg = S.format( "bad argument #1 to '%s' (string expected, got %s)",
+ name, type( s )
+ )
+ error( msg, 3 )
+ end
+ if S.len( s ) > ustring.maxStringLength then
+ local msg = S.format( "bad argument #1 to '%s' (string is longer than %d bytes)",
+ name, ustring.maxStringLength
+ )
+ error( msg, 3 )
+ end
+end
+
+local function checkPattern( name, pattern )
+ if type( pattern ) == 'number' then
+ pattern = tostring( pattern )
+ end
+ if type( pattern ) ~= 'string' then
+ local msg = S.format( "bad argument #2 to '%s' (string expected, got %s)",
+ name, type( pattern )
+ )
+ error( msg, 3 )
+ end
+ if S.len( pattern ) > ustring.maxPatternLength then
+ local msg = S.format( "bad argument #2 to '%s' (pattern is longer than %d bytes)",
+ name, ustring.maxPatternLength
+ )
+ error( msg, 3 )
+ end
+end
+
+-- A private helper that splits a string into codepoints, and also collects the
+-- starting position of each character and the total length in codepoints.
+--
+-- @param s string utf8-encoded string to decode
+-- @return table
+local function utf8_explode( s )
+ local ret = {
+ len = 0,
+ codepoints = {},
+ bytepos = {},
+ }
+
+ local i = 1
+ local l = S.len( s )
+ local cp, b, b2, trail
+ local min
+ while i <= l do
+ b = S.byte( s, i )
+ if b < 0x80 then
+ -- 1-byte code point, 00-7F
+ cp = b
+ trail = 0
+ min = 0
+ elseif b < 0xc2 then
+ -- Either a non-initial code point (invalid here) or
+ -- an overlong encoding for a 1-byte code point
+ return nil
+ elseif b < 0xe0 then
+ -- 2-byte code point, C2-DF
+ trail = 1
+ cp = b - 0xc0
+ min = 0x80
+ elseif b < 0xf0 then
+ -- 3-byte code point, E0-EF
+ trail = 2
+ cp = b - 0xe0
+ min = 0x800
+ elseif b < 0xf4 then
+ -- 4-byte code point, F0-F3
+ trail = 3
+ cp = b - 0xf0
+ min = 0x10000
+ elseif b == 0xf4 then
+ -- 4-byte code point, F4
+ -- Make sure it doesn't decode to over U+10FFFF
+ if S.byte( s, i + 1 ) > 0x8f then
+ return nil
+ end
+ trail = 3
+ cp = 4
+ min = 0x100000
+ else
+ -- Code point over U+10FFFF, or invalid byte
+ return nil
+ end
+
+ -- Check subsequent bytes for multibyte code points
+ for j = i + 1, i + trail do
+ b = S.byte( s, j )
+ if not b or b < 0x80 or b > 0xbf then
+ return nil
+ end
+ cp = cp * 0x40 + b - 0x80
+ end
+ if cp < min then
+ -- Overlong encoding
+ return nil
+ end
+
+ ret.codepoints[#ret.codepoints + 1] = cp
+ ret.bytepos[#ret.bytepos + 1] = i
+ ret.len = ret.len + 1
+ i = i + 1 + trail
+ end
+
+ -- Two past the end (for sub with empty string)
+ ret.bytepos[#ret.bytepos + 1] = l + 1
+ ret.bytepos[#ret.bytepos + 1] = l + 1
+
+ return ret
+end
+
+-- A private helper that finds the character offset for a byte offset.
+--
+-- @param cps table from utf8_explode
+-- @param i int byte offset
+-- @return int
+local function cpoffset( cps, i )
+ local min, max, p = 0, cps.len + 1
+ if i == 0 then
+ return 0
+ end
+ while min + 1 < max do
+ p = math.floor( ( min + max ) / 2 ) + 1
+ if cps.bytepos[p] <= i then
+ min = p - 1
+ end
+ if cps.bytepos[p] >= i then
+ max = p - 1
+ end
+ end
+ return min + 1
+end
+
+---- Trivial functions ----
+-- These functions are the same as the standard string versions
+
+ustring.byte = string.byte
+ustring.format = string.format
+ustring.rep = string.rep
+
+---- Non-trivial functions ----
+-- These functions actually have to be UTF-8 aware
+
+
+-- Determine if a string is valid UTF-8
+--
+-- @param s string
+-- @return boolean
+function ustring.isutf8( s )
+ checkString( 'isutf8', s )
+ return utf8_explode( s ) ~= nil
+end
+
+-- Return the byte offset of a character in a string
+--
+-- @param s string
+-- @param l int codepoint number [default 1]
+-- @param i int starting byte offset [default 1]
+-- @return int|nil
+function ustring.byteoffset( s, l, i )
+ checkString( 'byteoffset', s )
+ checkType( 'byteoffset', 2, l, 'number', true )
+ checkType( 'byteoffset', 3, i, 'number', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'byteoffset' (string is not UTF-8)", 2 )
+ end
+
+ i = i or 1
+ if i < 0 then
+ i = S.len( s ) + i + 1
+ end
+ if i < 1 or i > S.len( s ) then
+ return nil
+ end
+ local p = cpoffset( cps, i )
+ if l > 0 and cps.bytepos[p] == i then
+ l = l - 1
+ end
+ if p + l > cps.len then
+ return nil
+ end
+ return cps.bytepos[p + l]
+end
+
+-- Return codepoints from a string
+--
+-- @see string.byte
+-- @param s string
+-- @param i int Starting character [default 1]
+-- @param j int Ending character [default i]
+-- @return int* Zero or more codepoints
+function ustring.codepoint( s, i, j )
+ checkString( 'codepoint', s )
+ checkType( 'codepoint', 2, i, 'number', true )
+ checkType( 'codepoint', 3, j, 'number', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'codepoint' (string is not UTF-8)", 2 )
+ end
+ i = i or 1
+ if i < 0 then
+ i = cps.len + i + 1
+ end
+ j = j or i
+ if j < 0 then
+ j = cps.len + j + 1
+ end
+ if j < i then
+ return -- empty result set
+ end
+ i = math.max( 1, math.min( i, cps.len + 1 ) )
+ j = math.max( 1, math.min( j, cps.len + 1 ) )
+ return unpack( cps.codepoints, i, j )
+end
+
+-- Return an iterator over the codepoint (as integers)
+-- for cp in ustring.gcodepoint( s ) do ... end
+--
+-- @param s string
+-- @param i int Starting character [default 1]
+-- @param j int Ending character [default -1]
+-- @return function
+-- @return nil
+-- @return nil
+function ustring.gcodepoint( s, i, j )
+ checkString( 'gcodepoint', s )
+ checkType( 'gcodepoint', 2, i, 'number', true )
+ checkType( 'gcodepoint', 3, j, 'number', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'gcodepoint' (string is not UTF-8)", 2 )
+ end
+ i = i or 1
+ if i < 0 then
+ i = cps.len + i + 1
+ end
+ j = j or -1
+ if j < 0 then
+ j = cps.len + j + 1
+ end
+ if j < i then
+ return function ()
+ return nil
+ end
+ end
+ i = math.max( 1, math.min( i, cps.len + 1 ) )
+ j = math.max( 1, math.min( j, cps.len + 1 ) )
+ return function ()
+ if i <= j then
+ local ret = cps.codepoints[i]
+ i = i + 1
+ return ret
+ end
+ return nil
+ end
+end
+
+-- Convert codepoints to a string
+--
+-- @see string.char
+-- @param ... int List of codepoints
+-- @return string
+local function internalChar( t, s, e )
+ local ret = {}
+ for i = s, e do
+ local v = t[i]
+ if type( v ) ~= 'number' then
+ checkType( 'char', i, v, 'number' )
+ end
+ v = math.floor( v )
+ if v < 0 or v > 0x10ffff then
+ error( S.format( "bad argument #%d to 'char' (value out of range)", i ), 2 )
+ elseif v < 0x80 then
+ ret[#ret + 1] = v
+ elseif v < 0x800 then
+ ret[#ret + 1] = 0xc0 + math.floor( v / 0x40 ) % 0x20
+ ret[#ret + 1] = 0x80 + v % 0x40
+ elseif v < 0x10000 then
+ ret[#ret + 1] = 0xe0 + math.floor( v / 0x1000 ) % 0x10
+ ret[#ret + 1] = 0x80 + math.floor( v / 0x40 ) % 0x40
+ ret[#ret + 1] = 0x80 + v % 0x40
+ else
+ ret[#ret + 1] = 0xf0 + math.floor( v / 0x40000 ) % 0x08
+ ret[#ret + 1] = 0x80 + math.floor( v / 0x1000 ) % 0x40
+ ret[#ret + 1] = 0x80 + math.floor( v / 0x40 ) % 0x40
+ ret[#ret + 1] = 0x80 + v % 0x40
+ end
+ end
+ return S.char( unpack( ret ) )
+end
+function ustring.char( ... )
+ return internalChar( { ... }, 1, select( '#', ... ) )
+end
+
+-- Return the length of a string in codepoints, or
+-- nil if the string is not valid UTF-8.
+--
+-- @see string.len
+-- @param string
+-- @return int|nil
+function ustring.len( s )
+ checkString( 'len', s )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ return nil
+ else
+ return cps.len
+ end
+end
+
+-- Private function to return a substring of a string
+--
+-- @param s string
+-- @param cps table Exploded string
+-- @param i int Starting character [default 1]
+-- @param j int Ending character [default -1]
+-- @return string
+local function sub( s, cps, i, j )
+ return S.sub( s, cps.bytepos[i], cps.bytepos[j+1] - 1 )
+end
+
+-- Return a substring of a string
+--
+-- @see string.sub
+-- @param s string
+-- @param i int Starting character [default 1]
+-- @param j int Ending character [default -1]
+-- @return string
+function ustring.sub( s, i, j )
+ checkString( 'sub', s )
+ checkType( 'sub', 2, i, 'number', true )
+ checkType( 'sub', 3, j, 'number', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'sub' (string is not UTF-8)", 2 )
+ end
+ i = i or 1
+ if i < 0 then
+ i = cps.len + i + 1
+ end
+ j = j or -1
+ if j < 0 then
+ j = cps.len + j + 1
+ end
+ if j < i then
+ return ''
+ end
+ i = math.max( 1, math.min( i, cps.len + 1 ) )
+ j = math.max( 1, math.min( j, cps.len + 1 ) )
+ return sub( s, cps, i, j )
+end
+
+---- Table-driven functions ----
+-- These functions load a conversion table when called
+
+-- Convert a string to uppercase
+--
+-- @see string.upper
+-- @param s string
+-- @return string
+function ustring.upper( s )
+ checkString( 'upper', s )
+ local map = require 'ustring/upper';
+ local ret = S.gsub( s, '([^\128-\191][\128-\191]*)', map )
+ return ret
+end
+
+-- Convert a string to lowercase
+--
+-- @see string.lower
+-- @param s string
+-- @return string
+function ustring.lower( s )
+ checkString( 'lower', s )
+ local map = require 'ustring/lower';
+ local ret = S.gsub( s, '([^\128-\191][\128-\191]*)', map )
+ return ret
+end
+
+---- Pattern functions ----
+-- Ugh. Just ugh.
+
+-- Cache for character sets (e.g. [a-z])
+local charset_cache = {}
+setmetatable( charset_cache, { __weak = 'kv' } )
+
+-- Private function to find a pattern in a string
+-- Yes, this basically reimplements the whole of Lua's pattern matching, in
+-- Lua.
+--
+-- @see ustring.find
+-- @param s string
+-- @param cps table Exploded string
+-- @param rawpat string Pattern
+-- @param pattern table Exploded pattern
+-- @param init int Starting index
+-- @param noAnchor boolean True to ignore '^'
+-- @return int starting index of the match
+-- @return int ending index of the match
+-- @return string|int* captures
+local function find( s, cps, rawpat, pattern, init, noAnchor )
+ local charsets = require 'ustring/charsets'
+ local anchor = false
+ local ncapt, captures
+ local captparen = {}
+
+ -- Extract the value of a capture from the
+ -- upvalues ncapt and capture.
+ local function getcapt( n, err, errl )
+ if n > ncapt then
+ error( err, errl + 1 )
+ elseif type( captures[n] ) == 'table' then
+ if captures[n][2] == '' then
+ error( err, errl + 1 )
+ end
+ return sub( s, cps, captures[n][1], captures[n][2] ), captures[n][2] - captures[n][1] + 1
+ else
+ return captures[n], math.floor( math.log10( captures[n] ) ) + 1
+ end
+ end
+
+ local match, match_charset, parse_charset
+
+ -- Main matching function. Uses tail recursion where possible.
+ -- Returns the position of the character after the match, and updates the
+ -- upvalues ncapt and captures.
+ match = function ( sp, pp )
+ local c = pattern.codepoints[pp]
+ if c == 0x28 then -- '(': starts capture group
+ ncapt = ncapt + 1
+ captparen[ncapt] = pp
+ local ret
+ if pattern.codepoints[pp + 1] == 0x29 then -- ')': Pattern is '()', capture position
+ captures[ncapt] = sp
+ ret = match( sp, pp + 2 )
+ else
+ -- Start capture group
+ captures[ncapt] = { sp, '' }
+ ret = match( sp, pp + 1 )
+ end
+ if ret then
+ return ret
+ else
+ -- Failed, rollback
+ ncapt = ncapt - 1
+ return nil
+ end
+ elseif c == 0x29 then -- ')': ends capture group, pop current capture index from stack
+ for n = ncapt, 1, -1 do
+ if type( captures[n] ) == 'table' and captures[n][2] == '' then
+ captures[n][2] = sp - 1
+ local ret = match( sp, pp + 1 )
+ if ret then
+ return ret
+ else
+ -- Failed, rollback
+ captures[n][2] = ''
+ return nil
+ end
+ end
+ end
+ error( 'Unmatched close-paren at pattern character ' .. pp, 3 )
+ elseif c == 0x5b then -- '[': starts character set
+ return match_charset( sp, parse_charset( pp ) )
+ elseif c == 0x5d then -- ']'
+ error( 'Unmatched close-bracket at pattern character ' .. pp, 3 )
+ elseif c == 0x25 then -- '%'
+ c = pattern.codepoints[pp + 1]
+ if charsets[c] then -- A character set like '%a'
+ return match_charset( sp, pp + 2, charsets[c] )
+ elseif c == 0x62 then -- '%b': balanced delimiter match
+ local d1 = pattern.codepoints[pp + 2]
+ local d2 = pattern.codepoints[pp + 3]
+ if not d1 or not d2 then
+ error( 'malformed pattern (missing arguments to \'%b\')', 3 )
+ end
+ if cps.codepoints[sp] ~= d1 then
+ return nil
+ end
+ sp = sp + 1
+ local ct = 1
+ while true do
+ c = cps.codepoints[sp]
+ sp = sp + 1
+ if not c then
+ return nil
+ elseif c == d2 then
+ if ct == 1 then
+ return match( sp, pp + 4 )
+ end
+ ct = ct - 1
+ elseif c == d1 then
+ ct = ct + 1
+ end
+ end
+ elseif c == 0x66 then -- '%f': frontier pattern match
+ if pattern.codepoints[pp + 2] ~= 0x5b then
+ error( 'missing \'[\' after %f in pattern at pattern character ' .. pp, 3 )
+ end
+ local pp, charset = parse_charset( pp + 2 )
+ local c1 = cps.codepoints[sp - 1] or 0
+ local c2 = cps.codepoints[sp] or 0
+ if not charset[c1] and charset[c2] then
+ return match( sp, pp )
+ else
+ return nil
+ end
+ elseif c >= 0x30 and c <= 0x39 then -- '%0' to '%9': backreference
+ local m, l = getcapt( c - 0x30, 'invalid capture index %' .. c .. ' at pattern character ' .. pp, 3 )
+ local ep = math.min( cps.len + 1, sp + l )
+ if sub( s, cps, sp, ep - 1 ) == m then
+ return match( ep, pp + 2 )
+ else
+ return nil
+ end
+ elseif not c then -- percent at the end of the pattern
+ error( 'malformed pattern (ends with \'%\')', 3 )
+ else -- something else, treat as a literal
+ return match_charset( sp, pp + 2, { [c] = 1 } )
+ end
+ elseif c == 0x2e then -- '.': match anything
+ if not charset_cache['.'] then
+ local t = {}
+ setmetatable( t, { __index = function ( t, k ) return k end } )
+ charset_cache['.'] = { 1, t }
+ end
+ return match_charset( sp, pp + 1, charset_cache['.'][2] )
+ elseif c == nil then -- end of pattern
+ return sp
+ elseif c == 0x24 and pattern.len == pp then -- '$': assert end of string
+ return ( sp == cps.len + 1 ) and sp or nil
+ else
+ -- Any other character matches itself
+ return match_charset( sp, pp + 1, { [c] = 1 } )
+ end
+ end
+
+ -- Parse a bracketed character set (e.g. [a-z])
+ -- Returns the position after the set and a table holding the matching characters
+ parse_charset = function ( pp )
+ local _, ep
+ local epp = pattern.bytepos[pp] + 1
+ if S.sub( rawpat, epp, epp ) == '^' then
+ epp = epp + 1
+ end
+ if S.sub( rawpat, epp, epp ) == ']' then
+ -- Lua's string module effectively does this
+ epp = epp + 1
+ end
+ repeat
+ _, ep = S.find( rawpat, ']', epp, true )
+ if not ep then
+ error( 'Missing close-bracket for character set beginning at pattern character ' .. pp, 3 )
+ end
+ epp = ep + 1
+ until S.byte( rawpat, ep - 1 ) ~= 0x25 or S.byte( rawpat, ep - 2 ) == 0x25
+ local key = S.sub( rawpat, pattern.bytepos[pp], ep )
+ if charset_cache[key] then
+ local pl, cs = unpack( charset_cache[key] )
+ return pp + pl, cs
+ end
+
+ local p0 = pp
+ local cs = {}
+ local csrefs = { cs }
+ local invert = false
+ pp = pp + 1
+ if pattern.codepoints[pp] == 0x5e then -- '^'
+ invert = true
+ pp = pp + 1
+ end
+ local first = true
+ while true do
+ local c = pattern.codepoints[pp]
+ if not first and c == 0x5d then -- closing ']'
+ pp = pp + 1
+ break
+ elseif c == 0x25 then -- '%'
+ c = pattern.codepoints[pp + 1]
+ if charsets[c] then
+ csrefs[#csrefs + 1] = charsets[c]
+ else
+ cs[c] = 1
+ end
+ pp = pp + 2
+ elseif pattern.codepoints[pp + 1] == 0x2d and pattern.codepoints[pp + 2] and pattern.codepoints[pp + 2] ~= 0x5d then -- '-' followed by another char (not ']'), it's a range
+ for i = c, pattern.codepoints[pp + 2] do
+ cs[i] = 1
+ end
+ pp = pp + 3
+ elseif not c then -- Should never get here, but Just In Case...
+ error( 'Missing close-bracket', 3 )
+ else
+ cs[c] = 1
+ pp = pp + 1
+ end
+ first = false
+ end
+
+ local ret
+ if not csrefs[2] then
+ if not invert then
+ -- If there's only the one charset table, we can use it directly
+ ret = cs
+ else
+ -- Simple invert
+ ret = {}
+ setmetatable( ret, { __index = function ( t, k ) return k and not cs[k] end } )
+ end
+ else
+ -- Ok, we have to iterate over multiple charset tables
+ ret = {}
+ setmetatable( ret, { __index = function ( t, k )
+ if not k then
+ return nil
+ end
+ for i = 1, #csrefs do
+ if csrefs[i][k] then
+ return not invert
+ end
+ end
+ return invert
+ end } )
+ end
+
+ charset_cache[key] = { pp - p0, ret }
+ return pp, ret
+ end
+
+ -- Match a character set table with optional quantifier, followed by
+ -- the rest of the pattern.
+ -- Returns same as 'match' above.
+ match_charset = function ( sp, pp, charset )
+ local q = pattern.codepoints[pp]
+ if q == 0x2a then -- '*', 0 or more matches
+ pp = pp + 1
+ local i = 0
+ while charset[cps.codepoints[sp + i]] do
+ i = i + 1
+ end
+ while i >= 0 do
+ local ret = match( sp + i, pp )
+ if ret then
+ return ret
+ end
+ i = i - 1
+ end
+ return nil
+ elseif q == 0x2b then -- '+', 1 or more matches
+ pp = pp + 1
+ local i = 0
+ while charset[cps.codepoints[sp + i]] do
+ i = i + 1
+ end
+ while i > 0 do
+ local ret = match( sp + i, pp )
+ if ret then
+ return ret
+ end
+ i = i - 1
+ end
+ return nil
+ elseif q == 0x2d then -- '-', 0 or more matches non-greedy
+ pp = pp + 1
+ while true do
+ local ret = match( sp, pp )
+ if ret then
+ return ret
+ end
+ if not charset[cps.codepoints[sp]] then
+ return nil
+ end
+ sp = sp + 1
+ end
+ elseif q == 0x3f then -- '?', 0 or 1 match
+ pp = pp + 1
+ if charset[cps.codepoints[sp]] then
+ local ret = match( sp + 1, pp )
+ if ret then
+ return ret
+ end
+ end
+ return match( sp, pp )
+ else -- no suffix, must match 1
+ if charset[cps.codepoints[sp]] then
+ return match( sp + 1, pp )
+ else
+ return nil
+ end
+ end
+ end
+
+ init = init or 1
+ if init < 0 then
+ init = cps.len + init + 1
+ end
+ init = math.max( 1, math.min( init, cps.len + 1 ) )
+
+ -- Here is the actual match loop. It just calls 'match' on successive
+ -- starting positions (or not, if the pattern is anchored) until it finds a
+ -- match.
+ local sp = init
+ local pp = 1
+ if not noAnchor and pattern.codepoints[1] == 0x5e then -- '^': Pattern is anchored
+ anchor = true
+ pp = 2
+ end
+
+ repeat
+ ncapt, captures = 0, {}
+ local ep = match( sp, pp )
+ if ep then
+ for i = 1, ncapt do
+ captures[i] = getcapt( i, 'Unclosed capture beginning at pattern character ' .. captparen[i], 2 )
+ end
+ return sp, ep - 1, unpack( captures )
+ end
+ sp = sp + 1
+ until anchor or sp > cps.len + 1
+ return nil
+end
+
+-- Private function to decide if a pattern looks simple enough to use
+-- Lua's built-in string library. The following make a pattern not simple:
+-- * If it contains any bytes over 0x7f. We could skip these if they're not
+-- inside brackets and aren't followed by quantifiers and aren't part of a
+-- '%b', but that's too complicated to check.
+-- * If it contains a negated character set.
+-- * If it contains "%a" or any of the other %-prefixed character sets except %z.
+-- * If it contains a '.' not followed by '*', '+', '-'. A bare '.' or '.?'
+-- matches a partial UTF-8 character, but the others will happily enough
+-- match a whole UTF-8 character thinking it's 2, 3 or 4.
+-- * If it contains position-captures.
+-- * If it matches the empty string
+--
+-- @param string pattern
+-- @return boolean
+local function patternIsSimple( pattern )
+ local findWithPcall = function ( ... )
+ local ok, ret = pcall( S.find, ... )
+ return ok and ret
+ end
+
+ return not (
+ S.find( pattern, '[\128-\255]' ) or
+ S.find( pattern, '%[%^' ) or
+ S.find( pattern, '%%[acdlpsuwxACDLPSUWXZ]' ) or
+ S.find( pattern, '%.[^*+-]' ) or S.find( pattern, '%.$' ) or
+ S.find( pattern, '()', 1, true ) or
+ pattern == '' or findWithPcall( '', pattern )
+ )
+end
+
+-- Find a pattern in a string
+--
+-- This works just like string.find, with the following changes:
+-- * Everything works on UTF-8 characters rather than bytes
+-- * Character classes are redefined in terms of Unicode properties:
+-- * %a - Letter
+-- * %c - Control
+-- * %d - Decimal Number
+-- * %l - Lower case letter
+-- * %p - Punctuation
+-- * %s - Separator, plus HT, LF, FF, CR, and VT
+-- * %u - Upper case letter
+-- * %w - Letter or Decimal Number
+-- * %x - [0-9A-Fa-f0-9A-Fa-f]
+--
+-- @see string.find
+-- @param s string
+-- @param pattern string Pattern
+-- @param init int Starting index
+-- @param plain boolean Literal match, no pattern matching
+-- @return int starting index of the match
+-- @return int ending index of the match
+-- @return string|int* captures
+function ustring.find( s, pattern, init, plain )
+ checkString( 'find', s )
+ checkPattern( 'find', pattern )
+ checkType( 'find', 3, init, 'number', true )
+ checkType( 'find', 4, plain, 'boolean', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'find' (string is not UTF-8)", 2 )
+ end
+ local pat = utf8_explode( pattern )
+ if pat == nil then
+ error( "bad argument #2 for 'find' (string is not UTF-8)", 2 )
+ end
+
+ if plain or patternIsSimple( pattern ) then
+ if init and init > cps.len + 1 then
+ init = cps.len + 1
+ end
+ local m
+ if plain then
+ m = { true, S.find( s, pattern, cps.bytepos[init], plain ) }
+ else
+ m = { pcall( S.find, s, pattern, cps.bytepos[init], plain ) }
+ end
+ if m[1] then
+ if m[2] then
+ m[2] = cpoffset( cps, m[2] )
+ m[3] = cpoffset( cps, m[3] )
+ end
+ return unpack( m, 2 )
+ end
+ end
+
+ return find( s, cps, pattern, pat, init )
+end
+
+-- Match a string against a pattern
+--
+-- @see ustring.find
+-- @see string.match
+-- @param s string
+-- @param pattern string
+-- @param init int Starting offset for match
+-- @return string|int* captures, or the whole match if there are none
+function ustring.match( s, pattern, init )
+ checkString( 'match', s )
+ checkPattern( 'match', pattern )
+ checkType( 'match', 3, init, 'number', true )
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'match' (string is not UTF-8)", 2 )
+ end
+ local pat = utf8_explode( pattern )
+ if pat == nil then
+ error( "bad argument #2 for 'match' (string is not UTF-8)", 2 )
+ end
+
+ if patternIsSimple( pattern ) then
+ local ret = { pcall( S.match, s, pattern, cps.bytepos[init] ) }
+ if ret[1] then
+ return unpack( ret, 2 )
+ end
+ end
+
+ local m = { find( s, cps, pattern, pat, init ) }
+ if not m[1] then
+ return nil
+ end
+ if m[3] then
+ return unpack( m, 3 )
+ end
+ return sub( s, cps, m[1], m[2] )
+end
+
+-- Return an iterator function over the matches for a pattern
+--
+-- @see ustring.find
+-- @see string.gmatch
+-- @param s string
+-- @param pattern string
+-- @return function
+-- @return nil
+-- @return nil
+function ustring.gmatch( s, pattern )
+ checkString( 'gmatch', s )
+ checkPattern( 'gmatch', pattern )
+ if patternIsSimple( pattern ) then
+ local ret = { pcall( S.gmatch, s, pattern ) }
+ if ret[1] then
+ return unpack( ret, 2 )
+ end
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'gmatch' (string is not UTF-8)", 2 )
+ end
+ local pat = utf8_explode( pattern )
+ if pat == nil then
+ error( "bad argument #2 for 'gmatch' (string is not UTF-8)", 2 )
+ end
+ local init = 1
+
+ return function ()
+ local m = { find( s, cps, pattern, pat, init, true ) }
+ if not m[1] then
+ return nil
+ end
+ init = m[2] + 1
+ if m[3] then
+ return unpack( m, 3 )
+ end
+ return sub( s, cps, m[1], m[2] )
+ end
+end
+
+-- Replace pattern matches in a string
+--
+-- @see ustring.find
+-- @see string.gsub
+-- @param s string
+-- @param pattern string
+-- @param repl string|function|table
+-- @param int n
+-- @return string
+-- @return int
+function ustring.gsub( s, pattern, repl, n )
+ checkString( 'gsub', s )
+ checkPattern( 'gsub', pattern )
+ checkType( 'gsub', 4, n, 'number', true )
+ if patternIsSimple( pattern ) then
+ local ret = { pcall( S.gsub, s, pattern, repl, n ) }
+ if ret[1] then
+ return unpack( ret, 2 )
+ end
+ end
+
+ if n == nil then
+ n = 1e100
+ end
+ if n < 1 then
+ -- No replacement
+ return s, 0
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ error( "bad argument #1 for 'gsub' (string is not UTF-8)", 2 )
+ end
+ local pat = utf8_explode( pattern )
+ if pat == nil then
+ error( "bad argument #2 for 'gsub' (string is not UTF-8)", 2 )
+ end
+
+ if pat.codepoints[1] == 0x5e then -- '^': Pattern is anchored
+ -- There can be only the one match, so make that explicit
+ n = 1
+ end
+
+ local tp
+ if type( repl ) == 'function' then
+ tp = 1
+ elseif type( repl ) == 'table' then
+ tp = 2
+ elseif type( repl ) == 'string' then
+ tp = 3
+ elseif type( repl ) == 'number' then
+ repl = tostring( repl )
+ tp = 3
+ else
+ checkType( 'gsub', 3, repl, 'function or table or string' )
+ end
+
+ local init = 1
+ local ct = 0
+ local ret = {}
+ local zeroAdjustment = 0
+ repeat
+ local m = { find( s, cps, pattern, pat, init + zeroAdjustment ) }
+ if not m[1] then
+ break
+ end
+ if init < m[1] then
+ ret[#ret + 1] = sub( s, cps, init, m[1] - 1 )
+ end
+ local mm = sub( s, cps, m[1], m[2] )
+ local val
+ if tp == 1 then
+ if m[3] then
+ val = repl( unpack( m, 3 ) )
+ else
+ val = repl( mm )
+ end
+ elseif tp == 2 then
+ val = repl[m[3] or mm]
+ elseif tp == 3 then
+ if ct == 0 and #m < 11 then
+ local ss = S.gsub( repl, '%%[%%0-' .. ( #m - 2 ) .. ']', 'x' )
+ ss = S.match( ss, '%%[0-9]' )
+ if ss then
+ error( 'invalid capture index ' .. ss .. ' in replacement string', 2 )
+ end
+ end
+ local t = {
+ ["%0"] = mm,
+ ["%1"] = m[3],
+ ["%2"] = m[4],
+ ["%3"] = m[5],
+ ["%4"] = m[6],
+ ["%5"] = m[7],
+ ["%6"] = m[8],
+ ["%7"] = m[9],
+ ["%8"] = m[10],
+ ["%9"] = m[11],
+ ["%%"] = "%"
+ }
+ val = S.gsub( repl, '%%[%%0-9]', t )
+ end
+ ret[#ret + 1] = val or mm
+ init = m[2] + 1
+ ct = ct + 1
+ zeroAdjustment = m[2] < m[1] and 1 or 0
+ until init > cps.len or ct >= n
+ if init <= cps.len then
+ ret[#ret + 1] = sub( s, cps, init, cps.len )
+ end
+ return table.concat( ret ), ct
+end
+
+---- Unicode Normalization ----
+-- These functions load a conversion table when called
+
+local function internalDecompose( cps, decomp )
+ local cp = {}
+ local normal = require 'ustring/normalization-data'
+
+ -- Decompose into cp, using the lookup table and logic for hangul
+ for i = 1, cps.len do
+ local c = cps.codepoints[i]
+ local m = decomp[c]
+ if m then
+ for j = 0, #m do
+ cp[#cp + 1] = m[j]
+ end
+ else
+ cp[#cp + 1] = c
+ end
+ end
+
+ -- Now sort combiners by class
+ local i, l = 1, #cp
+ while i < l do
+ local cc1 = normal.combclass[cp[i]]
+ local cc2 = normal.combclass[cp[i+1]]
+ if cc1 and cc2 and cc1 > cc2 then
+ cp[i], cp[i+1] = cp[i+1], cp[i]
+ if i > 1 then
+ i = i - 1
+ else
+ i = i + 1
+ end
+ else
+ i = i + 1
+ end
+ end
+
+ return cp, 1, l
+end
+
+local function internalCompose( cp, _, l )
+ local normal = require 'ustring/normalization-data'
+
+ -- Since NFD->NFC can never expand a character sequence, we can do this
+ -- in-place.
+ local comp = normal.comp[cp[1]]
+ local sc = 1
+ local j = 1
+ local lastclass = 0
+ for i = 2, l do
+ local c = cp[i]
+ local ccc = normal.combclass[c]
+ if ccc then
+ -- Trying a combiner with the starter
+ if comp and lastclass < ccc and comp[c] then
+ -- Yes!
+ c = comp[c]
+ cp[sc] = c
+ comp = normal.comp[c]
+ else
+ -- No, copy it to the right place for output
+ j = j + 1
+ cp[j] = c
+ lastclass = ccc
+ end
+ elseif comp and lastclass == 0 and comp[c] then
+ -- Combining two adjacent starters
+ c = comp[c]
+ cp[sc] = c
+ comp = normal.comp[c]
+ else
+ -- New starter, doesn't combine
+ j = j + 1
+ cp[j] = c
+ comp = normal.comp[c]
+ sc = j
+ lastclass = 0
+ end
+ end
+
+ return cp, 1, j
+end
+
+-- Normalize a string to NFC
+--
+-- Based on MediaWiki's UtfNormal class. Returns nil if the string is not valid
+-- UTF-8.
+--
+-- @param s string
+-- @return string|nil
+function ustring.toNFC( s )
+ checkString( 'toNFC', s )
+
+ -- ASCII is always NFC
+ if not S.find( s, '[\128-\255]' ) then
+ return s
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ return nil
+ end
+ local normal = require 'ustring/normalization-data'
+
+ -- First, scan through to see if the string is definitely already NFC
+ local ok = true
+ for i = 1, cps.len do
+ local c = cps.codepoints[i]
+ if normal.check[c] then
+ ok = false
+ break
+ end
+ end
+ if ok then
+ return s
+ end
+
+ -- Next, expand to NFD then recompose
+ return internalChar( internalCompose( internalDecompose( cps, normal.decomp ) ) )
+end
+
+-- Normalize a string to NFD
+--
+-- Based on MediaWiki's UtfNormal class. Returns nil if the string is not valid
+-- UTF-8.
+--
+-- @param s string
+-- @return string|nil
+function ustring.toNFD( s )
+ checkString( 'toNFD', s )
+
+ -- ASCII is always NFD
+ if not S.find( s, '[\128-\255]' ) then
+ return s
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ return nil
+ end
+
+ local normal = require 'ustring/normalization-data'
+ return internalChar( internalDecompose( cps, normal.decomp ) )
+end
+
+-- Normalize a string to NFKC
+--
+-- Based on MediaWiki's UtfNormal class. Returns nil if the string is not valid
+-- UTF-8.
+--
+-- @param s string
+-- @return string|nil
+function ustring.toNFKC( s )
+ checkString( 'toNFKC', s )
+
+ -- ASCII is always NFKC
+ if not S.find( s, '[\128-\255]' ) then
+ return s
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ return nil
+ end
+ local normal = require 'ustring/normalization-data'
+
+ -- Next, expand to NFKD then recompose
+ return internalChar( internalCompose( internalDecompose( cps, normal.decompK ) ) )
+end
+
+-- Normalize a string to NFKD
+--
+-- Based on MediaWiki's UtfNormal class. Returns nil if the string is not valid
+-- UTF-8.
+--
+-- @param s string
+-- @return string|nil
+function ustring.toNFKD( s )
+ checkString( 'toNFKD', s )
+
+ -- ASCII is always NFKD
+ if not S.find( s, '[\128-\255]' ) then
+ return s
+ end
+
+ local cps = utf8_explode( s )
+ if cps == nil then
+ return nil
+ end
+
+ local normal = require 'ustring/normalization-data'
+ return internalChar( internalDecompose( cps, normal.decompK ) )
+end
+
+return ustring
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaSandbox/Engine.php b/www/wiki/extensions/Scribunto/includes/engines/LuaSandbox/Engine.php
new file mode 100644
index 00000000..739650e0
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaSandbox/Engine.php
@@ -0,0 +1,401 @@
+<?php
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaSandboxEngine extends Scribunto_LuaEngine {
+ public $options, $loaded = false;
+ protected $lineCache = [];
+
+ /**
+ * @var Scribunto_LuaSandboxInterpreter
+ */
+ protected $interpreter;
+
+ public function getPerformanceCharacteristics() {
+ return [
+ 'phpCallsRequireSerialization' => false,
+ ];
+ }
+
+ public function getSoftwareInfo( array &$software ) {
+ try {
+ Scribunto_LuaSandboxInterpreter::checkLuaSandboxVersion();
+ } catch ( Scribunto_LuaInterpreterNotFoundError $e ) {
+ // They shouldn't be using this engine if the extension isn't
+ // loaded. But in case they do for some reason, let's not have
+ // Special:Version fatal.
+ return;
+ } catch ( Scribunto_LuaInterpreterBadVersionError $e ) {
+ // Same for if the extension is too old.
+ return;
+ }
+
+ $versions = LuaSandbox::getVersionInfo();
+ $software['[https://www.mediawiki.org/wiki/LuaSandbox LuaSandbox]'] =
+ $versions['LuaSandbox'];
+ $software['[http://www.lua.org/ Lua]'] = str_replace( 'Lua ', '', $versions['Lua'] );
+ if ( isset( $versions['LuaJIT'] ) ) {
+ $software['[http://luajit.org/ LuaJIT]'] = str_replace( 'LuaJIT ', '', $versions['LuaJIT'] );
+ }
+ }
+
+ public function getResourceUsage( $resource ) {
+ $this->load();
+ switch ( $resource ) {
+ case self::MEM_PEAK_BYTES:
+ return $this->interpreter->getPeakMemoryUsage();
+ case self::CPU_SECONDS:
+ return $this->interpreter->getCPUUsage();
+ default:
+ return false;
+ }
+ }
+
+ private function getLimitReportData() {
+ $ret = [];
+ $this->load();
+
+ $t = $this->interpreter->getCPUUsage();
+ $ret['scribunto-limitreport-timeusage'] = [
+ sprintf( "%.3f", $t ),
+ sprintf( "%.3f", $this->options['cpuLimit'] )
+ ];
+ $ret['scribunto-limitreport-memusage'] = [
+ $this->interpreter->getPeakMemoryUsage(),
+ $this->options['memoryLimit'],
+ ];
+
+ $logs = $this->getLogBuffer();
+ if ( $logs !== '' ) {
+ $ret['scribunto-limitreport-logs'] = $logs;
+ }
+
+ if ( $t < 1.0 ) {
+ return $ret;
+ }
+
+ $percentProfile = $this->interpreter->getProfilerFunctionReport(
+ Scribunto_LuaSandboxInterpreter::PERCENT
+ );
+ if ( !count( $percentProfile ) ) {
+ return $ret;
+ }
+ $timeProfile = $this->interpreter->getProfilerFunctionReport(
+ Scribunto_LuaSandboxInterpreter::SECONDS
+ );
+
+ $lines = [];
+ $cumulativePercent = 0;
+ $num = $otherTime = $otherPercent = 0;
+ foreach ( $percentProfile as $name => $percent ) {
+ $time = $timeProfile[$name] * 1000;
+ $num++;
+ if ( $cumulativePercent <= 99 && $num <= 10 ) {
+ // Map some regularly appearing internal names
+ if ( preg_match( '/^<mw.lua:(\d+)>$/', $name, $m ) ) {
+ $line = $this->getMwLuaLine( $m[1] );
+ if ( preg_match( '/^\s*(local\s+)?function ([a-zA-Z0-9_.]*)/', $line, $m ) ) {
+ $name = $m[2] . ' ' . $name;
+ }
+ }
+ $lines[] = [ $name, sprintf( '%.0f', $time ), sprintf( '%.1f', $percent ) ];
+ } else {
+ $otherTime += $time;
+ $otherPercent += $percent;
+ }
+ $cumulativePercent += $percent;
+ }
+ if ( $otherTime ) {
+ $lines[] = [ '[others]', sprintf( '%.0f', $otherTime ), sprintf( '%.1f', $otherPercent ) ];
+ }
+ $ret['scribunto-limitreport-profile'] = $lines;
+ return $ret;
+ }
+
+ public function reportLimitData( ParserOutput $output ) {
+ $data = $this->getLimitReportData();
+ foreach ( $data as $k => $v ) {
+ $output->setLimitReportData( $k, $v );
+ }
+ if ( isset( $data['scribunto-limitreport-logs'] ) ) {
+ $output->addModules( 'ext.scribunto.logs' );
+ }
+ }
+
+ public function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) {
+ global $wgLang;
+ $lang = $localize ? $wgLang : Language::factory( 'en' );
+ switch ( $key ) {
+ case 'scribunto-limitreport-logs':
+ if ( $isHTML ) {
+ $report .= $this->formatHtmlLogs( $value, $localize );
+ }
+ return false;
+
+ case 'scribunto-limitreport-memusage':
+ $value = array_map( [ $lang, 'formatSize' ], $value );
+ break;
+ }
+
+ if ( $key !== 'scribunto-limitreport-profile' ) {
+ return true;
+ }
+
+ $keyMsg = wfMessage( 'scribunto-limitreport-profile' );
+ $msMsg = wfMessage( 'scribunto-limitreport-profile-ms' );
+ $percentMsg = wfMessage( 'scribunto-limitreport-profile-percent' );
+ if ( !$localize ) {
+ $keyMsg->inLanguage( 'en' )->useDatabase( false );
+ $msMsg->inLanguage( 'en' )->useDatabase( false );
+ $percentMsg->inLanguage( 'en' )->useDatabase( false );
+ }
+
+ // To avoid having to do actual work in Message::fetchMessage for each
+ // line in the loops below, call ->exists() here to populate ->message.
+ $msMsg->exists();
+ $percentMsg->exists();
+
+ if ( $isHTML ) {
+ $report .= Html::openElement( 'tr' ) .
+ Html::rawElement( 'th', [ 'colspan' => 2 ], $keyMsg->parse() ) .
+ Html::closeElement( 'tr' ) .
+ Html::openElement( 'tr' ) .
+ Html::openElement( 'td', [ 'colspan' => 2 ] ) .
+ Html::openElement( 'table' );
+ foreach ( $value as $line ) {
+ $name = $line[0];
+ $location = '';
+ if ( preg_match( '/^(.*?) *<([^<>]+):(\d+)>$/', $name, $m ) ) {
+ $name = $m[1];
+ $title = Title::newFromText( $m[2] );
+ if ( $title && $title->hasContentModel( CONTENT_MODEL_SCRIBUNTO ) ) {
+ $location = '&lt;' . Linker::link( $title ) . ":{$m[3]}&gt;";
+ } else {
+ $location = htmlspecialchars( "<{$m[2]}:{$m[3]}>" );
+ }
+ }
+ $ms = clone $msMsg;
+ $ms->params( $line[1] );
+ $pct = clone $percentMsg;
+ $pct->params( $line[2] );
+ $report .= Html::openElement( 'tr' ) .
+ Html::element( 'td', null, $name ) .
+ Html::rawElement( 'td', null, $location ) .
+ Html::rawElement( 'td', [ 'align' => 'right' ], $ms->parse() ) .
+ Html::rawElement( 'td', [ 'align' => 'right' ], $pct->parse() ) .
+ Html::closeElement( 'tr' );
+ }
+ $report .= Html::closeElement( 'table' ) .
+ Html::closeElement( 'td' ) .
+ Html::closeElement( 'tr' );
+ } else {
+ $report .= $keyMsg->text() . ":\n";
+ foreach ( $value as $line ) {
+ $ms = clone $msMsg;
+ $ms->params( $line[1] );
+ $pct = clone $percentMsg;
+ $pct->params( $line[2] );
+ $report .= sprintf( " %-59s %11s %11s\n", $line[0], $ms->text(), $pct->text() );
+ }
+ }
+
+ return false;
+ }
+
+ protected function getMwLuaLine( $lineNum ) {
+ if ( !isset( $this->lineCache['mw.lua'] ) ) {
+ $this->lineCache['mw.lua'] = file( $this->getLuaLibDir() . '/mw.lua' );
+ }
+ return $this->lineCache['mw.lua'][$lineNum - 1];
+ }
+
+ function newInterpreter() {
+ return new Scribunto_LuaSandboxInterpreter( $this, $this->options );
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaSandboxInterpreter extends Scribunto_LuaInterpreter {
+ /**
+ * @var Scribunto_LuaEngine
+ */
+ public $engine;
+
+ /**
+ * @var LuaSandbox
+ */
+ public $sandbox;
+
+ /**
+ * @var bool
+ */
+ public $profilerEnabled;
+
+ const SAMPLES = 0;
+ const SECONDS = 1;
+ const PERCENT = 2;
+
+ /**
+ * Check that php-luasandbox is available and of a recent-enough version
+ * @throws Scribunto_LuaInterpreterNotFoundError
+ * @throws Scribunto_LuaInterpreterBadVersionError
+ */
+ public static function checkLuaSandboxVersion() {
+ if ( !extension_loaded( 'luasandbox' ) ) {
+ throw new Scribunto_LuaInterpreterNotFoundError(
+ 'The luasandbox extension is not present, this engine cannot be used.' );
+ }
+
+ if ( !is_callable( 'LuaSandbox::getVersionInfo' ) ) {
+ throw new Scribunto_LuaInterpreterBadVersionError(
+ 'The luasandbox extension is too old (version 1.6+ is required), ' .
+ 'this engine cannot be used.'
+ );
+ }
+ }
+
+ function __construct( $engine, array $options ) {
+ self::checkLuaSandboxVersion();
+
+ $this->engine = $engine;
+ $this->sandbox = new LuaSandbox;
+ $this->sandbox->setMemoryLimit( $options['memoryLimit'] );
+ $this->sandbox->setCPULimit( $options['cpuLimit'] );
+ if ( !isset( $options['profilerPeriod'] ) ) {
+ $options['profilerPeriod'] = 0.02;
+ }
+ if ( $options['profilerPeriod'] ) {
+ $this->profilerEnabled = true;
+ $this->sandbox->enableProfiler( $options['profilerPeriod'] );
+ }
+ }
+
+ protected function convertSandboxError( LuaSandboxError $e ) {
+ $opts = [];
+ if ( isset( $e->luaTrace ) ) {
+ $opts['trace'] = $e->luaTrace;
+ }
+ $message = $e->getMessage();
+ if ( preg_match( '/^(.*?):(\d+): (.*)$/', $message, $m ) ) {
+ $opts['module'] = $m[1];
+ $opts['line'] = $m[2];
+ $message = $m[3];
+ }
+ return $this->engine->newLuaError( $message, $opts );
+ }
+
+ /**
+ * @param string $text
+ * @param string $chunkName
+ * @return mixed
+ * @throws Scribunto_LuaError
+ */
+ public function loadString( $text, $chunkName ) {
+ try {
+ return $this->sandbox->loadString( $text, $chunkName );
+ } catch ( LuaSandboxError $e ) {
+ throw $this->convertSandboxError( $e );
+ }
+ }
+
+ public function registerLibrary( $name, array $functions ) {
+ $realLibrary = [];
+ foreach ( $functions as $funcName => $callback ) {
+ $realLibrary[$funcName] = [
+ new Scribunto_LuaSandboxCallback( $callback ),
+ $funcName ];
+ }
+ $this->sandbox->registerLibrary( $name, $realLibrary );
+
+ # TODO: replace this with
+ # $this->sandbox->registerVirtualLibrary(
+ # $name, [ $this, 'callback' ], $functions );
+ }
+
+ public function callFunction( $func /*, ... */ ) {
+ $args = func_get_args();
+ $func = array_shift( $args );
+ try {
+ $ret = call_user_func_array( [ $func, 'call' ], $args );
+ if ( $ret === false ) {
+ // Per the documentation on LuaSandboxFunction::call, a return value
+ // of false means that something went wrong and it's PHP's fault,
+ // so throw a "real" exception.
+ throw new MWException(
+ __METHOD__ . ': LuaSandboxFunction::call returned false' );
+ }
+ return $ret;
+ } catch ( LuaSandboxTimeoutError $e ) {
+ throw $this->engine->newException( 'scribunto-common-timeout' );
+ } catch ( LuaSandboxError $e ) {
+ throw $this->convertSandboxError( $e );
+ }
+ }
+
+ public function wrapPhpFunction( $callable ) {
+ return $this->sandbox->wrapPhpFunction( $callable );
+ }
+
+ public function isLuaFunction( $object ) {
+ return $object instanceof LuaSandboxFunction;
+ }
+
+ public function getPeakMemoryUsage() {
+ return $this->sandbox->getPeakMemoryUsage();
+ }
+
+ public function getCPUUsage() {
+ return $this->sandbox->getCPUUsage();
+ }
+
+ public function getProfilerFunctionReport( $units ) {
+ if ( $this->profilerEnabled ) {
+ static $unitsMap;
+ if ( !$unitsMap ) {
+ $unitsMap = [
+ self::SAMPLES => LuaSandbox::SAMPLES,
+ self::SECONDS => LuaSandbox::SECONDS,
+ self::PERCENT => LuaSandbox::PERCENT,
+ ];
+ }
+ return $this->sandbox->getProfilerFunctionReport( $unitsMap[$units] );
+ } else {
+ return [];
+ }
+ }
+
+ public function pauseUsageTimer() {
+ $this->sandbox->pauseUsageTimer();
+ }
+
+ public function unpauseUsageTimer() {
+ $this->sandbox->unpauseUsageTimer();
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaSandboxCallback {
+
+ /**
+ * @var callable
+ */
+ protected $callback;
+
+ function __construct( $callback ) {
+ $this->callback = $callback;
+ }
+
+ /**
+ * We use __call with a variable function name so that LuaSandbox will be
+ * able to return a meaningful function name in profiling data.
+ * @param string $funcName
+ * @param array $args
+ * @return mixed
+ */
+ function __call( $funcName, $args ) {
+ try {
+ return call_user_func_array( $this->callback, $args );
+ } catch ( Scribunto_LuaError $e ) {
+ throw new LuaSandboxRuntimeError( $e->getLuaMessage() );
+ }
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneEngine.php b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneEngine.php
new file mode 100644
index 00000000..330a7b9a
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/LuaStandaloneEngine.php
@@ -0,0 +1,781 @@
+<?php
+
+use MediaWiki\Logger\LoggerFactory;
+use Psr\Log\LoggerInterface;
+use Psr\Log\NullLogger;
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaStandaloneEngine extends Scribunto_LuaEngine {
+ protected static $clockTick;
+ public $initialStatus;
+
+ /**
+ * @var Scribunto_LuaStandaloneInterpreter
+ */
+ protected $interpreter;
+
+ public function load() {
+ parent::load();
+ if ( php_uname( 's' ) === 'Linux' ) {
+ $this->initialStatus = $this->interpreter->getStatus();
+ } else {
+ $this->initialStatus = false;
+ }
+ }
+
+ public function getPerformanceCharacteristics() {
+ return [
+ 'phpCallsRequireSerialization' => true,
+ ];
+ }
+
+ function reportLimitData( ParserOutput $output ) {
+ try {
+ $this->load();
+ } catch ( Exception $e ) {
+ return;
+ }
+ if ( $this->initialStatus ) {
+ $status = $this->interpreter->getStatus();
+ $output->setLimitReportData( 'scribunto-limitreport-timeusage',
+ [
+ sprintf( "%.3f", $status['time'] / $this->getClockTick() ),
+ sprintf( "%.3f", $this->options['cpuLimit'] )
+ ]
+ );
+ $output->setLimitReportData( 'scribunto-limitreport-virtmemusage',
+ [
+ $status['vsize'],
+ $this->options['memoryLimit']
+ ]
+ );
+ $output->setLimitReportData( 'scribunto-limitreport-estmemusage',
+ $status['vsize'] - $this->initialStatus['vsize']
+ );
+ }
+ $logs = $this->getLogBuffer();
+ if ( $logs !== '' ) {
+ $output->addModules( 'ext.scribunto.logs' );
+ $output->setLimitReportData( 'scribunto-limitreport-logs', $logs );
+ }
+ }
+
+ function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) {
+ global $wgLang;
+ $lang = $localize ? $wgLang : Language::factory( 'en' );
+ switch ( $key ) {
+ case 'scribunto-limitreport-logs':
+ if ( $isHTML ) {
+ $report .= $this->formatHtmlLogs( $value, $localize );
+ }
+ return false;
+ case 'scribunto-limitreport-virtmemusage':
+ $value = array_map( [ $lang, 'formatSize' ], $value );
+ break;
+ case 'scribunto-limitreport-estmemusage':
+ /** @suppress PhanTypeMismatchArgument */
+ $value = $lang->formatSize( $value );
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * @return mixed
+ */
+ function getClockTick() {
+ if ( self::$clockTick === null ) {
+ Wikimedia\suppressWarnings();
+ self::$clockTick = intval( shell_exec( 'getconf CLK_TCK' ) );
+ Wikimedia\restoreWarnings();
+ if ( !self::$clockTick ) {
+ self::$clockTick = 100;
+ }
+ }
+ return self::$clockTick;
+ }
+
+ /**
+ * @return Scribunto_LuaStandaloneInterpreter
+ */
+ function newInterpreter() {
+ return new Scribunto_LuaStandaloneInterpreter( $this, $this->options + [
+ 'logger' => LoggerFactory::getInstance( 'Scribunto' )
+ ] );
+ }
+
+ public function getSoftwareInfo( array &$software ) {
+ $ver = Scribunto_LuaStandaloneInterpreter::getLuaVersion( $this->options );
+ if ( $ver !== null ) {
+ if ( substr( $ver, 0, 6 ) === 'LuaJIT' ) {
+ $software['[http://luajit.org/ LuaJIT]'] = str_replace( 'LuaJIT ', '', $ver );
+ } else {
+ $software['[http://www.lua.org/ Lua]'] = str_replace( 'Lua ', '', $ver );
+ }
+ }
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaStandaloneInterpreter extends Scribunto_LuaInterpreter {
+ protected static $nextInterpreterId = 0;
+
+ /**
+ * @var Scribunto_LuaStandaloneEngine
+ */
+ public $engine;
+
+ /**
+ * @var bool
+ */
+ public $enableDebug;
+
+ /**
+ * @var resource
+ */
+ public $proc;
+
+ /**
+ * @var resource
+ */
+ public $writePipe;
+
+ /**
+ * @var resource
+ */
+ public $readPipe;
+
+ /**
+ * @var ScribuntoException
+ */
+ public $exitError;
+
+ /**
+ * @var int
+ */
+ public $id;
+
+ /**
+ * @var LoggerInterface
+ */
+ protected $logger;
+
+ /**
+ * @var callable[]
+ */
+ protected $callbacks;
+
+ /**
+ * @param Scribunto_LuaStandaloneEngine $engine
+ * @param array $options
+ * @throws MWException
+ * @throws Scribunto_LuaInterpreterNotFoundError
+ * @throws ScribuntoException
+ */
+ function __construct( $engine, array $options ) {
+ $this->id = self::$nextInterpreterId++;
+
+ if ( $options['errorFile'] === null ) {
+ $options['errorFile'] = wfGetNull();
+ }
+
+ if ( $options['luaPath'] === null ) {
+ $path = false;
+
+ // Note, if you alter these, also alter getLuaVersion() below
+ if ( PHP_OS == 'Linux' ) {
+ if ( PHP_INT_SIZE == 4 ) {
+ $path = 'lua5_1_5_linux_32_generic/lua';
+ } elseif ( PHP_INT_SIZE == 8 ) {
+ $path = 'lua5_1_5_linux_64_generic/lua';
+ }
+ } elseif ( PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32' ) {
+ if ( PHP_INT_SIZE == 4 ) {
+ $path = 'lua5_1_5_Win32_bin/lua5.1.exe';
+ } elseif ( PHP_INT_SIZE == 8 ) {
+ $path = 'lua5_1_5_Win64_bin/lua5.1.exe';
+ }
+ } elseif ( PHP_OS == 'Darwin' ) {
+ $path = 'lua5_1_5_mac_lion_fat_generic/lua';
+ }
+ if ( $path === false ) {
+ throw new Scribunto_LuaInterpreterNotFoundError(
+ 'No Lua interpreter was given in the configuration, ' .
+ 'and no bundled binary exists for this platform.' );
+ }
+ $options['luaPath'] = __DIR__ . "/binaries/$path";
+
+ if ( !is_executable( $options['luaPath'] ) ) {
+ throw new MWException(
+ sprintf( 'The lua binary (%s) is not executable.', $options['luaPath'] )
+ );
+ }
+ }
+
+ $this->engine = $engine;
+ $this->enableDebug = !empty( $options['debug'] );
+ $this->logger = isset( $options['logger'] )
+ ? $options['logger']
+ : new NullLogger();
+
+ $pipes = null;
+ $cmd = wfEscapeShellArg(
+ $options['luaPath'],
+ __DIR__ . '/mw_main.lua',
+ dirname( dirname( __DIR__ ) ),
+ $this->id,
+ PHP_INT_SIZE
+ );
+ if ( php_uname( 's' ) == 'Linux' ) {
+ // Limit memory and CPU
+ $cmd = wfEscapeShellArg(
+ 'exec', # proc_open() passes $cmd to 'sh -c' on Linux, so add an 'exec' to bypass it
+ '/bin/sh',
+ __DIR__ . '/lua_ulimit.sh',
+ $options['cpuLimit'], # soft limit (SIGXCPU)
+ $options['cpuLimit'] + 1, # hard limit
+ intval( $options['memoryLimit'] / 1024 ),
+ $cmd );
+ }
+
+ if ( php_uname( 's' ) == 'Windows NT' ) {
+ // Like the passthru() in older versions of PHP,
+ // PHP's invokation of cmd.exe in proc_open() is broken:
+ // http://news.php.net/php.internals/21796
+ // Unlike passthru(), it is not fixed in any PHP version,
+ // so we use the fix similar to one in wfShellExec()
+ $cmd = '"' . $cmd . '"';
+ }
+
+ $this->logger->debug( __METHOD__.": creating interpreter: $cmd\n" );
+
+ // Check whether proc_open is available before trying to call it (e.g.
+ // PHP's disable_functions may have removed it)
+ if ( !function_exists( 'proc_open' ) ) {
+ throw $this->engine->newException( 'scribunto-luastandalone-proc-error-proc-open' );
+ }
+
+ // Clear the "last error", so if proc_open fails we can know any
+ // warning was generated by that.
+ Wikimedia\suppressWarnings();
+ trigger_error( '' );
+ Wikimedia\restoreWarnings();
+
+ $this->proc = proc_open(
+ $cmd,
+ [
+ [ 'pipe', 'r' ],
+ [ 'pipe', 'w' ],
+ [ 'file', $options['errorFile'], 'a' ]
+ ],
+ $pipes );
+ if ( !$this->proc ) {
+ $err = error_get_last();
+ if ( !empty( $err['message'] ) ) {
+ throw $this->engine->newException( 'scribunto-luastandalone-proc-error-msg',
+ [ 'args' => [ $err['message'] ] ] );
+ } else {
+ throw $this->engine->newException( 'scribunto-luastandalone-proc-error' );
+ }
+ }
+ $this->writePipe = $pipes[0];
+ $this->readPipe = $pipes[1];
+ }
+
+ function __destruct() {
+ $this->terminate();
+ }
+
+ public static function getLuaVersion( array $options ) {
+ if ( $options['luaPath'] === null ) {
+ // We know which versions are distributed, no need to run them.
+ if ( PHP_OS == 'Linux' ) {
+ return 'Lua 5.1.5';
+ } elseif ( PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32' ) {
+ return 'Lua 5.1.4';
+ } elseif ( PHP_OS == 'Darwin' ) {
+ return 'Lua 5.1.5';
+ } else {
+ return null;
+ }
+ }
+
+ // Ask the interpreter what version it is, using the "-v" option.
+ // The output is expected to be one line, something like these:
+ // Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
+ // LuaJIT 2.0.0 -- Copyright (C) 2005-2012 Mike Pall. http://luajit.org/
+ $cmd = wfEscapeShellArg( $options['luaPath'] ) . ' -v';
+ $handle = popen( $cmd, 'r' );
+ if ( $handle ) {
+ $ret = fgets( $handle, 80 );
+ pclose( $handle );
+ if ( $ret && preg_match( '/^Lua(?:JIT)? \S+/', $ret, $m ) ) {
+ return $m[0];
+ }
+ }
+ return null;
+ }
+
+ public function terminate() {
+ if ( $this->proc ) {
+ $this->logger->debug( __METHOD__.": terminating\n" );
+ proc_terminate( $this->proc );
+ proc_close( $this->proc );
+ $this->proc = false;
+ }
+ }
+
+ public function quit() {
+ if ( !$this->proc ) {
+ return;
+ }
+ $this->dispatch( [ 'op' => 'quit' ] );
+ proc_close( $this->proc );
+ }
+
+ public function testquit() {
+ if ( !$this->proc ) {
+ return;
+ }
+ $this->dispatch( [ 'op' => 'testquit' ] );
+ proc_close( $this->proc );
+ }
+
+ /**
+ * @param string $text
+ * @param string $chunkName
+ * @return Scribunto_LuaStandaloneInterpreterFunction
+ */
+ public function loadString( $text, $chunkName ) {
+ $this->cleanupLuaChunks();
+
+ $result = $this->dispatch( [
+ 'op' => 'loadString',
+ 'text' => $text,
+ 'chunkName' => $chunkName
+ ] );
+ return new Scribunto_LuaStandaloneInterpreterFunction( $this->id, $result[1] );
+ }
+
+ public function callFunction( $func /* ... */ ) {
+ if ( !( $func instanceof Scribunto_LuaStandaloneInterpreterFunction ) ) {
+ throw new MWException( __METHOD__.': invalid function type' );
+ }
+ if ( $func->interpreterId !== $this->id ) {
+ throw new MWException( __METHOD__.': function belongs to a different interpreter' );
+ }
+ $args = func_get_args();
+ unset( $args[0] );
+ // $args is now conveniently a 1-based array, as required by the Lua server
+
+ $this->cleanupLuaChunks();
+
+ $result = $this->dispatch( [
+ 'op' => 'call',
+ 'id' => $func->id,
+ 'nargs' => count( $args ),
+ 'args' => $args,
+ ] );
+ // Convert return values to zero-based
+ return array_values( $result );
+ }
+
+ public function wrapPhpFunction( $callable ) {
+ static $uid = 0;
+ $id = "anonymous*" . ++$uid;
+ $this->callbacks[$id] = $callable;
+ $ret = $this->dispatch( [
+ 'op' => 'wrapPhpFunction',
+ 'id' => $id,
+ ] );
+ return $ret[1];
+ }
+
+ public function cleanupLuaChunks() {
+ if ( isset( Scribunto_LuaStandaloneInterpreterFunction::$anyChunksDestroyed[$this->id] ) ) {
+ unset( Scribunto_LuaStandaloneInterpreterFunction::$anyChunksDestroyed[$this->id] );
+ $this->dispatch( [
+ 'op' => 'cleanupChunks',
+ 'ids' => Scribunto_LuaStandaloneInterpreterFunction::$activeChunkIds[$this->id]
+ ] );
+ }
+ }
+
+ public function isLuaFunction( $object ) {
+ return $object instanceof Scribunto_LuaStandaloneInterpreterFunction;
+ }
+
+ public function registerLibrary( $name, array $functions ) {
+ $functionIds = [];
+ foreach ( $functions as $funcName => $callback ) {
+ $id = "$name-$funcName";
+ $this->callbacks[$id] = $callback;
+ $functionIds[$funcName] = $id;
+ }
+ $this->dispatch( [
+ 'op' => 'registerLibrary',
+ 'name' => $name,
+ 'functions' => $functionIds,
+ ] );
+ }
+
+ public function getStatus() {
+ $result = $this->dispatch( [
+ 'op' => 'getStatus',
+ ] );
+ return $result[1];
+ }
+
+ public function pauseUsageTimer() {
+ }
+
+ public function unpauseUsageTimer() {
+ }
+
+ /**
+ * Fill in missing nulls in a list received from Lua
+ *
+ * @param array $array List received from Lua
+ * @param int $count Number of values that should be in the list
+ * @return array Non-sparse array
+ */
+ private static function fixNulls( array $array, $count ) {
+ if ( count( $array ) === $count ) {
+ return $array;
+ } else {
+ return array_replace( array_fill( 1, $count, null ), $array );
+ }
+ }
+
+ protected function handleCall( $message ) {
+ $message['args'] = self::fixNulls( $message['args'], $message['nargs'] );
+ try {
+ $result = $this->callback( $message['id'], $message['args'] );
+ } catch ( Scribunto_LuaError $e ) {
+ return [
+ 'op' => 'error',
+ 'value' => $e->getLuaMessage(),
+ ];
+ }
+
+ // Convert to a 1-based array
+ if ( $result !== null && count( $result ) ) {
+ $result = array_combine( range( 1, count( $result ) ), $result );
+ } else {
+ $result = [];
+ }
+
+ return [
+ 'op' => 'return',
+ 'nvalues' => count( $result ),
+ 'values' => $result
+ ];
+ }
+
+ protected function callback( $id, array $args ) {
+ return call_user_func_array( $this->callbacks[$id], $args );
+ }
+
+ protected function handleError( $message ) {
+ $opts = [];
+ if ( preg_match( '/^(.*?):(\d+): (.*)$/', $message['value'], $m ) ) {
+ $opts['module'] = $m[1];
+ $opts['line'] = $m[2];
+ $message['value'] = $m[3];
+ }
+ if ( isset( $message['trace'] ) ) {
+ $opts['trace'] = array_values( $message['trace'] );
+ }
+ throw $this->engine->newLuaError( $message['value'], $opts );
+ }
+
+ protected function dispatch( $msgToLua ) {
+ $this->sendMessage( $msgToLua );
+ while ( true ) {
+ $msgFromLua = $this->receiveMessage();
+
+ switch ( $msgFromLua['op'] ) {
+ case 'return':
+ return self::fixNulls( $msgFromLua['values'], $msgFromLua['nvalues'] );
+ case 'call':
+ $msgToLua = $this->handleCall( $msgFromLua );
+ $this->sendMessage( $msgToLua );
+ break;
+ case 'error':
+ $this->handleError( $msgFromLua );
+ return; // not reached
+ default:
+ $this->logger->error( __METHOD__ .": invalid response op \"{$msgFromLua['op']}\"\n" );
+ throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
+ }
+ }
+ }
+
+ protected function sendMessage( $msg ) {
+ $this->debug( "TX ==> {$msg['op']}" );
+ $this->checkValid();
+ // Send the message
+ $encMsg = $this->encodeMessage( $msg );
+ if ( !fwrite( $this->writePipe, $encMsg ) ) {
+ // Write error, probably the process has terminated
+ // If it has, handleIOError() will throw. If not, throw an exception ourselves.
+ $this->handleIOError();
+ throw $this->engine->newException( 'scribunto-luastandalone-write-error' );
+ }
+ }
+
+ protected function receiveMessage() {
+ $this->checkValid();
+ // Read the header
+ $header = fread( $this->readPipe, 16 );
+ if ( strlen( $header ) !== 16 ) {
+ $this->handleIOError();
+ throw $this->engine->newException( 'scribunto-luastandalone-read-error' );
+ }
+ $length = $this->decodeHeader( $header );
+
+ // Read the reply body
+ $body = '';
+ $lengthRemaining = $length;
+ while ( $lengthRemaining ) {
+ $buffer = fread( $this->readPipe, $lengthRemaining );
+ if ( $buffer === false || feof( $this->readPipe ) ) {
+ $this->handleIOError();
+ throw $this->engine->newException( 'scribunto-luastandalone-read-error' );
+ }
+ $body .= $buffer;
+ $lengthRemaining -= strlen( $buffer );
+ }
+ $body = strtr( $body, [
+ '\\r' => "\r",
+ '\\n' => "\n",
+ '\\\\' => '\\',
+ ] );
+ $msg = unserialize( $body );
+ $this->debug( "RX <== {$msg['op']}" );
+ return $msg;
+ }
+
+ protected function encodeMessage( $message ) {
+ $serialized = $this->encodeLuaVar( $message );
+ $length = strlen( $serialized );
+ $check = $length * 2 - 1;
+
+ return sprintf( '%08x%08x%s', $length, $check, $serialized );
+ }
+
+ /**
+ * @param mixed $var
+ * @param int $level
+ *
+ * @return string
+ * @throws MWException
+ */
+ protected function encodeLuaVar( $var, $level = 0 ) {
+ if ( $level > 100 ) {
+ throw new MWException( __METHOD__.': recursion depth limit exceeded' );
+ }
+ $type = gettype( $var );
+ switch ( $type ) {
+ case 'boolean':
+ return $var ? 'true' : 'false';
+ case 'integer':
+ return $var;
+ case 'double':
+ if ( !is_finite( $var ) ) {
+ if ( is_nan( $var ) ) {
+ return '(0/0)';
+ }
+ if ( $var === INF ) {
+ return '(1/0)';
+ }
+ if ( $var === -INF ) {
+ return '(-1/0)';
+ }
+ throw new MWException( __METHOD__.': cannot convert non-finite number' );
+ }
+ return sprintf( '%.17g', $var );
+ case 'string':
+ return '"' .
+ strtr( $var, [
+ '"' => '\\"',
+ '\\' => '\\\\',
+ "\n" => '\\n',
+ "\r" => '\\r',
+ "\000" => '\\000',
+ ] ) .
+ '"';
+ case 'array':
+ $s = '{';
+ foreach ( $var as $key => $element ) {
+ if ( $s !== '{' ) {
+ $s .= ',';
+ }
+
+ // Lua's number type can't represent most integers beyond 2**53, so stringify such keys
+ if ( is_int( $key ) && ( $key > 9007199254740992 || $key < -9007199254740992 ) ) {
+ $key = sprintf( '%d', $key );
+ }
+
+ $s .= '[' . $this->encodeLuaVar( $key, $level + 1 ) . ']' .
+ '=' . $this->encodeLuaVar( $element, $level + 1 );
+ }
+ $s .= '}';
+ return $s;
+ case 'object':
+ if ( !( $var instanceof Scribunto_LuaStandaloneInterpreterFunction ) ) {
+ throw new MWException( __METHOD__.': unable to convert object of type ' .
+ get_class( $var ) );
+ } elseif ( $var->interpreterId !== $this->id ) {
+ throw new MWException(
+ __METHOD__.': unable to convert function belonging to a different interpreter'
+ );
+ } else {
+ return 'chunks[' . intval( $var->id ) . ']';
+ }
+ case 'resource':
+ throw new MWException( __METHOD__.': unable to convert resource' );
+ case 'NULL':
+ return 'nil';
+ default:
+ throw new MWException( __METHOD__.': unable to convert variable of unknown type' );
+ }
+ }
+
+ protected function decodeHeader( $header ) {
+ $length = substr( $header, 0, 8 );
+ $check = substr( $header, 8, 8 );
+ if ( !preg_match( '/^[0-9a-f]+$/', $length ) || !preg_match( '/^[0-9a-f]+$/', $check ) ) {
+ throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
+ }
+ $length = hexdec( $length );
+ $check = hexdec( $check );
+ if ( $length * 2 - 1 !== $check ) {
+ throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
+ }
+ return $length;
+ }
+
+ /**
+ * @throws ScribuntoException
+ */
+ protected function checkValid() {
+ if ( !$this->proc ) {
+ $this->logger->error( __METHOD__ . ": process already terminated\n" );
+ if ( $this->exitError ) {
+ throw $this->exitError;
+ } else {
+ throw $this->engine->newException( 'scribunto-luastandalone-gone' );
+ }
+ }
+ }
+
+ /**
+ * @throws ScribuntoException
+ */
+ protected function handleIOError() {
+ $this->checkValid();
+
+ // Terminate, fetch the status, then close. proc_close()'s return
+ // value isn't helpful here because there's no way to differentiate a
+ // signal-kill from a normal exit.
+ proc_terminate( $this->proc );
+ while ( true ) {
+ $status = proc_get_status( $this->proc );
+ if ( $status === false ) {
+ // WTF? Let the caller throw an appropriate error.
+ return;
+ }
+ if ( !$status['running'] ) {
+ break;
+ }
+ usleep( 10000 ); // Give the killed process a chance to be scheduled
+ }
+ proc_close( $this->proc );
+ $this->proc = false;
+
+ // proc_open() sometimes uses a shell, check for shell-style signal reporting.
+ if ( !$status['signaled'] && ( $status['exitcode'] & 0x80 ) === 0x80 ) {
+ $status['signaled'] = true;
+ $status['termsig'] = $status['exitcode'] - 128;
+ }
+
+ if ( $status['signaled'] ) {
+ if ( defined( 'SIGXCPU' ) && $status['termsig'] === SIGXCPU ) {
+ $this->exitError = $this->engine->newException( 'scribunto-common-timeout' );
+ } else {
+ $this->exitError = $this->engine->newException( 'scribunto-luastandalone-signal',
+ [ 'args' => [ $status['termsig'] ] ] );
+ }
+ } else {
+ $this->exitError = $this->engine->newException( 'scribunto-luastandalone-exited',
+ [ 'args' => [ $status['exitcode'] ] ] );
+ }
+ throw $this->exitError;
+ }
+
+ protected function debug( $msg ) {
+ if ( $this->enableDebug ) {
+ $this->logger->debug( "Lua: $msg\n" );
+ }
+ }
+}
+
+// @codingStandardsIgnoreLine Squiz.Classes.ValidClassName.NotCamelCaps
+class Scribunto_LuaStandaloneInterpreterFunction {
+ public static $anyChunksDestroyed = [];
+ public static $activeChunkIds = [];
+
+ /**
+ * @var int
+ */
+ public $interpreterId;
+
+ /**
+ * @var int
+ */
+ public $id;
+
+ /**
+ * @param int $interpreterId
+ * @param int $id
+ */
+ function __construct( $interpreterId, $id ) {
+ $this->interpreterId = $interpreterId;
+ $this->id = $id;
+ $this->incrementRefCount();
+ }
+
+ function __clone() {
+ $this->incrementRefCount();
+ }
+
+ function __wakeup() {
+ $this->incrementRefCount();
+ }
+
+ function __destruct() {
+ $this->decrementRefCount();
+ }
+
+ private function incrementRefCount() {
+ if ( !isset( self::$activeChunkIds[$this->interpreterId] ) ) {
+ self::$activeChunkIds[$this->interpreterId] = [ $this->id => 1 ];
+ } elseif ( !isset( self::$activeChunkIds[$this->interpreterId][$this->id] ) ) {
+ self::$activeChunkIds[$this->interpreterId][$this->id] = 1;
+ } else {
+ self::$activeChunkIds[$this->interpreterId][$this->id]++;
+ }
+ }
+
+ private function decrementRefCount() {
+ if ( isset( self::$activeChunkIds[$this->interpreterId][$this->id] ) ) {
+ if ( --self::$activeChunkIds[$this->interpreterId][$this->id] <= 0 ) {
+ unset( self::$activeChunkIds[$this->interpreterId][$this->id] );
+ self::$anyChunksDestroyed[$this->interpreterId] = true;
+ }
+ } else {
+ self::$anyChunksDestroyed[$this->interpreterId] = true;
+ }
+ }
+}
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/MWServer.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/MWServer.lua
new file mode 100644
index 00000000..a8227bed
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/MWServer.lua
@@ -0,0 +1,710 @@
+MWServer = {}
+
+--- Create a new MWServer object
+function MWServer:new( interpreterId, intSize )
+ interpreterId = tonumber( interpreterId )
+ if not interpreterId then
+ error( "bad argument #1 to 'MWServer:new' (must be a number or convertible to a number)", 2 )
+ end
+ intSize = tonumber( intSize )
+ if intSize ~= 4 and intSize ~= 8 then
+ error( "bad argument #2 to 'MWServer:new' (must be 4 or 8)", 2 )
+ end
+
+ obj = {
+ interpreterId = interpreterId,
+ nextChunkId = 1,
+ chunks = {},
+ xchunks = {},
+ protectedFunctions = {},
+ protectedEnvironments = {},
+ baseEnv = {}
+ }
+ if intSize == 4 then
+ obj.intMax = 2147483648
+ obj.intKeyMax = 2147483648
+ else
+ -- Lua can't represent most larger integers, so they may as well be sent to PHP as floats.
+ obj.intMax = 9007199254740992
+ obj.intKeyMax = 9223372036854775807
+ end
+ setmetatable( obj, self )
+ self.__index = self
+
+ obj:init()
+
+ return obj
+end
+
+--- Initialise a new MWServer object
+function MWServer:init()
+ self.baseEnv = self:newEnvironment()
+ for funcName, func in pairs( self ) do
+ if type(func) == 'function' then
+ self.protectedFunctions[func] = true
+ end
+ end
+ self.protectedEnvironments[_G] = true
+end
+
+--- Serve requests until exit is requested
+function MWServer:execute()
+ self:dispatch( nil )
+ self:debug( 'MWServer:execute: returning' )
+end
+
+-- Convert a multiple-return-value or a ... into a count and a table
+function MWServer:listToCountAndTable( ... )
+ return select( '#', ... ), { ... }
+end
+
+--- Call a PHP function
+-- Raise an error if the PHP handler requests it. May return any number
+-- of values.
+--
+-- @param id The function ID, specified by a registerLibrary message
+-- @param nargs Count of function arguments
+-- @param args The function arguments
+-- @return The return values from the PHP function
+function MWServer:call( id, nargs, args )
+ local result = self:dispatch( {
+ op = 'call',
+ id = id,
+ nargs = nargs,
+ args = args
+ } )
+ if result.op == 'return' then
+ return unpack( result.values, 1, result.nvalues )
+ elseif result.op == 'error' then
+ -- Raise an error in the actual user code that called the function
+ -- The level is 3 since our immediate caller is a closure
+ error( result.value, 3 )
+ else
+ self:internalError( 'MWServer:call: unexpected result op' )
+ end
+end
+
+--- Handle a "call" message from PHP. Call the relevant function.
+--
+-- @param message The message from PHP
+-- @return A response message to send back to PHP
+function MWServer:handleCall( message )
+ if not self.chunks[message.id] then
+ return {
+ op = 'error',
+ value = 'function id ' .. message.id .. ' does not exist'
+ }
+ end
+
+ local n, result = self:listToCountAndTable( xpcall(
+ function ()
+ return self.chunks[message.id]( unpack( message.args, 1, message.nargs ) )
+ end,
+ function ( err )
+ return MWServer:attachTrace( err )
+ end
+ ) )
+
+ if result[1] then
+ -- table.remove( result, 1 ) renumbers from 2 to #result. But #result
+ -- is not necessarily "right" if result contains nils.
+ result = { unpack( result, 2, n ) }
+ return {
+ op = 'return',
+ nvalues = n - 1,
+ values = result
+ }
+ else
+ if result[2].value and result[2].trace then
+ return {
+ op = 'error',
+ value = result[2].value,
+ trace = result[2].trace,
+ }
+ else
+ return {
+ op = 'error',
+ value = result[2]
+ }
+ end
+ end
+end
+
+--- The xpcall() error handler for handleCall(). Modifies the error object
+-- to include a structured backtrace
+--
+-- @param err The error object
+-- @return The new error object
+function MWServer:attachTrace( err )
+ return {
+ value = err,
+ trace = self:getStructuredTrace( 2 )
+ }
+end
+
+--- Handle a "loadString" message from PHP.
+-- Load the function and return a chunk ID.
+--
+-- @param message The message from PHP
+-- @return A response message to send back to PHP
+function MWServer:handleLoadString( message )
+ if string.find( message.text, '\27Lua', 1, true ) then
+ return {
+ op = 'error',
+ value = 'cannot load code with a Lua binary chunk marker escape sequence in it'
+ }
+ end
+ local chunk, errorMsg = loadstring( message.text, message.chunkName )
+ if chunk then
+ setfenv( chunk, self.baseEnv )
+ local id = self:addChunk( chunk )
+ return {
+ op = 'return',
+ nvalues = 1,
+ values = {id}
+ }
+ else
+ return {
+ op = 'error',
+ value = errorMsg
+ }
+ end
+end
+
+--- Add a function value to the list of tracked chunks and return its associated ID.
+-- Adding a chunk allows it to be referred to in messages from PHP.
+--
+-- @param chunk The function value
+-- @return The chunk ID
+function MWServer:addChunk( chunk )
+ local id = self.nextChunkId
+ self.nextChunkId = id + 1
+ self.chunks[id] = chunk
+ self.xchunks[chunk] = id
+ return id
+end
+
+--- Handle a "cleanupChunks" message from PHP.
+-- Remove any chunks no longer referenced by PHP code.
+--
+-- @param message The message from PHP
+-- @return A response message to send back to PHP
+function MWServer:handleCleanupChunks( message )
+ for id, chunk in pairs( self.chunks ) do
+ if not message.ids[id] then
+ self.chunks[id] = nil
+ self.xchunks[chunk] = nil
+ end
+ end
+
+ return {
+ op = 'return',
+ nvalues = 0,
+ values = {}
+ }
+end
+
+--- Handle a "registerLibrary" message from PHP.
+-- Add the relevant functions to the base environment.
+--
+-- @param message The message from PHP
+-- @return The response message
+function MWServer:handleRegisterLibrary( message )
+ local startPos = 1
+ local component
+ if not self.baseEnv[message.name] then
+ self.baseEnv[message.name] = {}
+ end
+ local t = self.baseEnv[message.name]
+
+ for name, id in pairs( message.functions ) do
+ t[name] = function( ... )
+ return self:call( id, self:listToCountAndTable( ... ) )
+ end
+ -- Protect the function against setfenv()
+ self.protectedFunctions[t[name]] = true
+ end
+
+ return {
+ op = 'return',
+ nvalues = 0,
+ values = {}
+ }
+end
+
+--- Handle a "wrapPhpFunction" message from PHP.
+-- Create an anonymous function
+--
+-- @param message The message from PHP
+-- @return The response message
+function MWServer:handleWrapPhpFunction( message )
+ local id = message.id
+ local func = function( ... )
+ return self:call( id, self:listToCountAndTable( ... ) )
+ end
+ -- Protect the function against setfenv()
+ self.protectedFunctions[func] = true
+
+ return {
+ op = 'return',
+ nvalues = 1,
+ values = { func }
+ }
+end
+
+--- Handle a "getStatus" message from PHP
+--
+-- @param message The request message
+-- @return The response message
+function MWServer:handleGetStatus( message )
+ local nullRet = {
+ op = 'return',
+ nvalues = 0,
+ values = {}
+ }
+ local file = io.open( '/proc/self/stat' )
+ if not file then
+ return nullRet
+ end
+ local s = file:read('*a')
+ file:close()
+ local t = {}
+ for token in string.gmatch(s, '[^ ]+') do
+ t[#t + 1] = token
+ end
+ if #t < 22 then
+ return nullRet
+ end
+ return {
+ op = 'return',
+ nvalues = 1,
+ values = {{
+ pid = tonumber(t[1]),
+ time = tonumber(t[14]) + tonumber(t[15]) + tonumber(t[16]) + tonumber(t[17]),
+ vsize = tonumber(t[23]),
+ }}
+ }
+end
+
+--- The main request/response loop
+--
+-- Send a request message and return its matching reply message. Handle any
+-- intervening requests (i.e. re-entrant calls) by dispatching them to the
+-- relevant handler function.
+--
+-- The request message may optionally be omitted, to listen for request messages
+-- without first sending a request of its own. Such a dispatch() call will
+-- continue running until termination is requested by PHP. Typically, PHP does
+-- this with a SIGTERM signal.
+--
+-- @param msgToPhp The message to send to PHP. Optional.
+-- @return The matching response message
+function MWServer:dispatch( msgToPhp )
+ if msgToPhp then
+ self:sendMessage( msgToPhp, 'call' )
+ end
+ while true do
+ local msgFromPhp = self:receiveMessage()
+ local msgToPhp
+ local op = msgFromPhp.op
+ if op == 'return' or op == 'error' then
+ return msgFromPhp
+ elseif op == 'call' then
+ msgToPhp = self:handleCall( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'loadString' then
+ msgToPhp = self:handleLoadString( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'registerLibrary' then
+ msgToPhp = self:handleRegisterLibrary( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'wrapPhpFunction' then
+ msgToPhp = self:handleWrapPhpFunction( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'cleanupChunks' then
+ msgToPhp = self:handleCleanupChunks( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'getStatus' then
+ msgToPhp = self:handleGetStatus( msgFromPhp )
+ self:sendMessage( msgToPhp, 'reply' )
+ elseif op == 'quit' then
+ self:debug( 'MWServer:dispatch: quit message received' )
+ os.exit(0)
+ elseif op == 'testquit' then
+ self:debug( 'MWServer:dispatch: testquit message received' )
+ os.exit(42)
+ else
+ self:internalError( "Invalid message operation" )
+ end
+ end
+end
+
+--- Write a message to the debug output stream.
+-- Some day this may be configurable, currently it just unconditionally writes
+-- the message to stderr. The PHP host will redirect those errors to /dev/null
+-- by default, but it can be configured to send them to a file.
+--
+-- @param s The message
+function MWServer:debug( s )
+ if ( type(s) == 'string' ) then
+ io.stderr:write( s .. '\n' )
+ else
+ io.stderr:write( self:serialize( s ) .. '\n' )
+ end
+end
+
+--- Raise an internal error
+-- Write a message to stderr and then exit with a failure status. This should
+-- be called for errors which cannot be allowed to be caught with pcall().
+--
+-- This must be used for protocol errors, or indeed any error from a context
+-- where a dispatch() call lies between the error source and a possible pcall()
+-- handler. If dispatch() were terminated by a regular error() call, the
+-- resulting protocol violation could lead to a deadlock.
+--
+-- @param msg The error message
+function MWServer:internalError( msg )
+ io.stderr:write( debug.traceback( msg ) .. '\n' )
+ os.exit( 1 )
+end
+
+--- Raise an I/O error
+-- Helper function for errors from the io and file modules, which may optionally
+-- return an informative error message as their second return value.
+function MWServer:ioError( header, info )
+ if type( info) == 'string' then
+ self:internalError( header .. ': ' .. info )
+ else
+ self:internalError( header )
+ end
+end
+
+--- Send a message to PHP
+-- @param msg The message table
+-- @param direction 'call' or 'reply'
+function MWServer:sendMessage( msg, direction )
+ if not msg.op then
+ self:internalError( "MWServer:sendMessage: invalid message", 2 )
+ end
+ self:debug('TX ==> ' .. msg.op)
+
+ -- If we're making an outgoing call, let errors go to our caller. If we're
+ -- replying to a call from PHP, catch serialization errors and return them
+ -- to PHP.
+ local encMsg;
+ if direction == 'reply' then
+ local ok
+ ok, encMsg = pcall( self.encodeMessage, self, msg )
+ if not ok then
+ self:debug('Serialization failed: ' .. encMsg)
+ self:debug('TX ==> error')
+ encMsg = self:encodeMessage( { op = 'error', value = encMsg } )
+ end
+ else
+ encMsg = self:encodeMessage( msg )
+ end
+
+ local success, errorMsg = io.stdout:write( encMsg )
+ if not success then
+ self:ioError( 'Write error', errorMsg )
+ end
+ io.stdout:flush()
+end
+
+--- Wait for a message from PHP and then decode and return it as a table
+-- @return The received message
+function MWServer:receiveMessage()
+ -- Read the header
+ local header, errorMsg = io.stdin:read( 16 )
+ if header == nil and errorMsg == nil then
+ -- End of file on stdin, exit gracefully
+ os.exit(0)
+ end
+
+ if not header or #header ~= 16 then
+ self:ioError( 'Read error', errorMsg )
+ end
+ local length = self:decodeHeader( header )
+
+ -- Read the body
+ local body, errorMsg = io.stdin:read( length )
+ if not body then
+ self:ioError( 'Read error', errorMsg )
+ end
+ if #body ~= length then
+ self:ioError( 'Read error', errorMsg )
+ end
+
+ -- Unserialize it
+ msg = self:unserialize( body )
+ self:debug('RX <== ' .. msg.op)
+ if msg.op == 'error' then
+ self:debug( 'Error: ' .. tostring( msg.value ) )
+ end
+ return msg
+end
+
+--- Encode a message for sending to PHP
+function MWServer:encodeMessage( message )
+ local serialized = self:serialize( message )
+ local length = #serialized
+ local check = length * 2 - 1
+ return string.format( '%08x%08x', length, check ) .. serialized
+end
+
+-- Faster to create the table once than for each call to MWServer:serialize()
+local serialize_replacements = {
+ ['\r'] = '\\r',
+ ['\n'] = '\\n',
+ ['\\'] = '\\\\',
+}
+
+--- Convert a value to a string suitable for passing to PHP's unserialize().
+-- Note that the following replacements must be performed before calling
+-- unserialize:
+-- "\\r" => "\r"
+-- "\\n" => "\n"
+-- "\\\\" => "\\"
+--
+-- @param var The value.
+function MWServer:serialize( var )
+ local done = {}
+
+ local function isInteger( var, max )
+ return type(var) == 'number'
+ and math.floor( var ) == var
+ and var >= -max
+ and var < max
+ end
+
+ local function recursiveEncode( var, level )
+ local t = type( var )
+ if t == 'nil' then
+ return 'N;'
+ elseif t == 'number' then
+ if isInteger( var, self.intMax ) then
+ return 'i:' .. string.format( '%d', var ) .. ';'
+ elseif var < math.huge and var > -math.huge then
+ return 'd:' .. string.format( '%.17g', var ) .. ';'
+ elseif var == math.huge then
+ return 'd:INF;'
+ elseif var == -math.huge then
+ return 'd:-INF;'
+ else
+ return 'd:NAN;'
+ end
+ elseif t == 'string' then
+ return 's:' .. string.len( var ) .. ':"' .. var .. '";'
+ elseif t == 'boolean' then
+ if var then
+ return 'b:1;'
+ else
+ return 'b:0;'
+ end
+ elseif t == 'table' then
+ if done[var] then
+ error("Cannot pass circular reference to PHP")
+ end
+ done[var] = true
+ local buf = { '' }
+ local numElements = 0
+ local seen = {}
+ for key, value in pairs(var) do
+ local k = key
+ local t = type( k )
+
+ -- Convert integers in range to look like standard integers.
+ -- Use tostring() for the rest. Reject all other non-strings.
+ if isInteger( k, self.intKeyMax ) then
+ k = string.format( '%d', k )
+ elseif t == 'number' then
+ k = tostring( k );
+ elseif t ~= 'string' then
+ error("Cannot use " .. t .. " as an array key when passing data from Lua to PHP");
+ end
+
+ -- Zend PHP doesn't really care whether integer keys are serialized
+ -- as ints or strings, it converts them correctly on unserialize.
+ -- But HHVM does depend on it, so keep doing it for now.
+ local n = nil
+ if k == '0' or k:match( '^-?[1-9]%d*$' ) then
+ n = tonumber( k )
+ if n == -9223372036854775808 and k ~= '-9223372036854775808' then
+ -- Bad edge rounding
+ n = nil
+ end
+ end
+ if isInteger( n, self.intKeyMax ) then
+ buf[#buf + 1] = 'i:' .. k .. ';'
+ else
+ buf[#buf + 1] = recursiveEncode( k, level + 1 )
+ end
+
+ -- Detect collisions, e.g. { [0] = 'foo', ["0"] = 'bar' }
+ if seen[k] then
+ error( 'Collision for array key ' .. k .. ' when passing data from Lua to PHP' );
+ end
+ seen[k] = true
+
+ buf[#buf + 1] = recursiveEncode( value, level + 1 )
+ numElements = numElements + 1
+ end
+ buf[1] = 'a:' .. numElements .. ':{'
+ buf[#buf + 1] = '}'
+ return table.concat(buf)
+ elseif t == 'function' then
+ local id
+ if self.xchunks[var] then
+ id = self.xchunks[var]
+ else
+ id = self:addChunk(var)
+ end
+ return 'O:42:"Scribunto_LuaStandaloneInterpreterFunction":2:{s:13:"interpreterId";i:' ..
+ self.interpreterId .. ';s:2:"id";i:' .. id .. ';}'
+ elseif t == 'thread' then
+ error("Cannot pass thread to PHP")
+ elseif t == 'userdata' then
+ error("Cannot pass userdata to PHP")
+ else
+ error("Cannot pass unrecognised type to PHP")
+ end
+ end
+
+ return recursiveEncode( var, 0 ):gsub( '[\r\n\\]', serialize_replacements )
+end
+
+--- Convert a Lua expression string to its corresponding value.
+-- Convert any references of the form chunk[id] to the corresponding function
+-- values.
+function MWServer:unserialize( text )
+ local func = loadstring( 'return ' .. text )
+ if not func then
+ self:internalError( "MWServer:unserialize: invalid chunk" )
+ end
+ -- Don't waste JIT cache space by storing every message in it
+ if jit then
+ jit.off( func )
+ end
+ setfenv( func, { chunks = self.chunks } )
+ return func()
+end
+
+--- Decode a message header.
+-- @param header The header string
+-- @return The body length
+function MWServer:decodeHeader( header )
+ local length = string.sub( header, 1, 8 )
+ local check = string.sub( header, 9, 16 )
+ if not string.match( length, '^%x+$' ) or not string.match( check, '^%x+$' ) then
+ self:internalError( "Error decoding message header: " .. length .. '/' .. check )
+ end
+ length = tonumber( length, 16 )
+ check = tonumber( check, 16 )
+ if length * 2 - 1 ~= check then
+ self:internalError( "Error decoding message header" )
+ end
+ return length
+end
+
+--- Get a traceback similar to the one from debug.traceback(), but as a table
+-- rather than formatted as a string
+--
+-- @param The level to start at: 1 for the function that called getStructuredTrace()
+-- @return A table with the backtrace information
+function MWServer:getStructuredTrace( level )
+ level = level + 1
+ local trace = {}
+ while true do
+ local rawInfo = debug.getinfo( level, 'nSl' )
+ if rawInfo == nil then
+ break
+ end
+ local info = {}
+ for i, key in ipairs({'short_src', 'what', 'currentline', 'name', 'namewhat', 'linedefined'}) do
+ info[key] = rawInfo[key]
+ end
+ if string.match( info['short_src'], '/MWServer.lua$' ) then
+ info['short_src'] = 'MWServer.lua'
+ end
+ if string.match( rawInfo['short_src'], '/mw_main.lua$' ) then
+ info['short_src'] = 'mw_main.lua'
+ end
+ table.insert( trace, info )
+ level = level + 1
+ end
+ return trace
+end
+
+--- Create a table to be used as a restricted environment, based on the current
+-- global environment.
+--
+-- @return The environment table
+function MWServer:newEnvironment()
+ local allowedGlobals = {
+ -- base
+ "assert",
+ "error",
+ "getmetatable",
+ "ipairs",
+ "next",
+ "pairs",
+ "pcall",
+ "rawequal",
+ "rawget",
+ "rawset",
+ "select",
+ "setmetatable",
+ "tonumber",
+ "type",
+ "unpack",
+ "xpcall",
+ "_VERSION",
+ -- libs
+ "table",
+ "math"
+ }
+
+ local env = {}
+ for i = 1, #allowedGlobals do
+ env[allowedGlobals[i]] = mw.clone( _G[allowedGlobals[i]] )
+ end
+
+ -- Cloning 'string' doesn't work right, because strings still use the old
+ -- 'string' as the metatable. So just copy it.
+ env.string = string
+
+ env._G = env
+ env.tostring = function( val )
+ return self:tostring( val )
+ end
+ env.string.dump = nil
+ env.setfenv, env.getfenv = mw.makeProtectedEnvFuncs(
+ self.protectedEnvironments, self.protectedFunctions )
+ env.debug = {
+ traceback = debug.traceback
+ }
+ env.os = {
+ date = os.date,
+ difftime = os.difftime,
+ time = os.time,
+ clock = os.clock
+ }
+ return env
+end
+
+--- An implementation of tostring() which does not expose pointers.
+function MWServer:tostring(val)
+ local mt = getmetatable( val )
+ if mt and mt.__tostring then
+ return mt.__tostring(val)
+ end
+ local typeName = type(val)
+ local nonPointerTypes = {number = true, string = true, boolean = true, ['nil'] = true}
+ if nonPointerTypes[typeName] then
+ return tostring(val)
+ else
+ return typeName
+ end
+end
+
+return MWServer
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/README b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/README
new file mode 100644
index 00000000..1321af9b
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/README
@@ -0,0 +1,39 @@
+The lua binaries were compiled from a manually patched 5.1.5 source tree, in order
+to address security vulnerabilities reported in CVE-2014-5461.
+
+The Windows binaries were compiled statically and do not link against the Visual C++
+runtime libraries. They should function on Windows 7 and higher, and Windows Server
+2008 and higher.
+
+The Linux binaries were compiled using "make generic". Lua does not use
+autoconf, rather it encourages users to edit the makefile. The makefile patch
+used to create the Linux binaries is in generic.patch.
+
+Compiling with "make generic" avoids introducing dynamic library dependencies
+other than libc. This makes the binaries work on a far greater variety of Linux
+distributions.
+
+More information on the patch process may be found in the corresponding Phabricator
+issue: https://phabricator.wikimedia.org/T72541
+
+The following copyright and license restrictions apply to these Lua binaries:
+
+Copyright © 2005-2011 Tecgraf/PUC-Rio and the Kepler Project.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/generic.patch b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/generic.patch
new file mode 100644
index 00000000..b9262318
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/generic.patch
@@ -0,0 +1,22 @@
+diff -ru lua-5.1.5~/src/Makefile lua-5.1.5/src/Makefile
+--- lua-5.1.5~/src/Makefile 2012-02-14 07:41:22.000000000 +1100
++++ lua-5.1.5/src/Makefile 2012-04-11 16:13:04.548558332 +1000
+@@ -7,15 +7,15 @@
+ # Your platform. See PLATS for possible values.
+ PLAT= none
+
+-CC= gcc
+-CFLAGS= -O2 -Wall $(MYCFLAGS)
++CC=gcc
++CFLAGS=-fpie -O2 -Wall $(MYCFLAGS)
+ AR= ar rcu
+ RANLIB= ranlib
+ RM= rm -f
+ LIBS= -lm $(MYLIBS)
+
+ MYCFLAGS=
+-MYLDFLAGS=
++MYLDFLAGS=-pie
+ MYLIBS=
+
+ # == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win32_bin/lua5.1.exe b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win32_bin/lua5.1.exe
new file mode 100644
index 00000000..b75924f1
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win32_bin/lua5.1.exe
Binary files differ
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win64_bin/lua5.1.exe b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win64_bin/lua5.1.exe
new file mode 100644
index 00000000..2bb611ec
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_Win64_bin/lua5.1.exe
Binary files differ
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_32_generic/lua b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_32_generic/lua
new file mode 100755
index 00000000..82656e64
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_32_generic/lua
Binary files differ
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_64_generic/lua b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_64_generic/lua
new file mode 100755
index 00000000..183f1a98
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_linux_64_generic/lua
Binary files differ
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_mac_lion_fat_generic/lua b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_mac_lion_fat_generic/lua
new file mode 100755
index 00000000..5bcf7369
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/binaries/lua5_1_5_mac_lion_fat_generic/lua
Binary files differ
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/lua_ulimit.sh b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/lua_ulimit.sh
new file mode 100755
index 00000000..a0b48ef0
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/lua_ulimit.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+ulimit -St $1
+ulimit -Ht $2
+ulimit -v $3
+eval "exec $4"
+
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/mw_main.lua b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/mw_main.lua
new file mode 100644
index 00000000..651ab751
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/mw_main.lua
@@ -0,0 +1,8 @@
+package.path = arg[1] .. '/engines/LuaStandalone/?.lua;' ..
+ arg[1] .. '/engines/LuaCommon/lualib/?.lua'
+
+require('MWServer')
+require('mwInit')
+server = MWServer:new( arg[2], arg[3] )
+server:execute()
+
diff --git a/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/protocol.txt b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/protocol.txt
new file mode 100644
index 00000000..ceb74d35
--- /dev/null
+++ b/www/wiki/extensions/Scribunto/includes/engines/LuaStandalone/protocol.txt
@@ -0,0 +1,176 @@
+The Lua standalone engine has a message-based protocol for communicating between
+PHP and Lua.
+
+Messages start with a 16 byte header. The first 8 bytes are the body length in
+hexadecimal. The second 8 bytes are (length * 2 - 1) also in hexadecimal.
+
+For messages passed from PHP to Lua, the body is encoded as a Lua expression.
+The expression may reference a table in a variable called "chunks", which
+contains an array of functions.
+
+Messages passed from Lua to PHP have their body encoded in PHP serialize()
+format, and then "\\", "\r", and "\n" are replaced with "\\\\", "\\r", and
+"\\n" to avoid issues with text-mode file handles. They may include instances
+of function objects which have an "id" member for passing back to Lua as an
+index in the chunk table.
+
+The expressions encoded into the message bodies are associative arrays. The "op"
+member of the array gives the operation to be performed by the message.
+
+Every request message demands exactly one response message in reply. When a
+request message is sent, the responder does not need to send the corresponding
+response message as its next message. It may instead send its own request
+message. In this way, a stack of pending requests can be accumulated. This
+mechanism allows re-entrant and recursive calls.
+
+All numerically-indexed arrays should start from index 1 unless otherwise
+specified. Note that the number of values in an array may not match what Lua's
+'#' operator returns if the array contains nils.
+
+== Request messages sent from PHP to Lua ==
+
+=== loadString ===
+
+Load some executable Lua code (a "chunk") and return the resulting function ID.
+
+Message parameters:
+* op: "loadString"
+* text: The string to load
+* chunkName: The name of the string, for use in error messages
+
+On success, the response message is:
+
+* op: "return"
+* nvalues: 1
+* values: An array with a single element with the ID in it
+
+On failure, the response message is:
+
+* op: "error"
+* value: The error message
+
+=== call ===
+
+Call a Lua function.
+
+Message parameters:
+* op: "call"
+* id: The chunk ID
+* nargs: Number of arguments, including nils
+* args: The argument array
+
+On success, the response message is:
+
+* op: "return"
+* nvalues: Number of return values, including nils
+* values: All return values as an array
+
+On failure, the response message is:
+
+* op: "error"
+* value: The value given to error(), usually an error message
+* trace: A table giving a backtrace of the stack as it was when error() was
+ called, in a similar format to the one used by debug.getinfo(). Element 1 of
+ the table is the function that called error(), element 2 is the function that
+ called that, and so on.
+
+=== registerLibrary ===
+
+Register a set of functions in the sandbox environment.
+
+Message parameters:
+* op: "registerLibrary"
+* name: The global variable name to register. May contain "." characters to
+ specify a global variable subtable.
+* functions: An associative array mapping function name to ID
+
+On success, the response message is:
+
+* op: "return"
+* nvalues: 0
+* values: An empty array
+
+On failure the response message is:
+
+* op: "error"
+* value: The error message
+
+=== getStatus ===
+
+Get status information about the Lua process.
+
+Message parameters:
+* op: "getStatus"
+
+On success, the response message is:
+
+* op: "return"
+* nvalues: 1
+* values: An array with a single element, which is an associative array mapping
+ status key to value. The status keys are:
+** pid: The process identifier
+** time: The amount of user and system time spent by the process, measured in clock ticks
+** vsize: The virtual memory size in bytes
+** rss: The resident set size in bytes
+
+On failure, the response message is:
+
+* op: "return"
+* nvalues: 0
+* values: An empty array
+
+=== cleanupChunks ===
+
+Tell Lua to release any chunks no longer referenced by PHP.
+
+Message parameters:
+* op: "cleanupChunks"
+* ids: Table with keys being the chunk IDs still referenced by PHP, and non-falsey values
+
+The response message is:
+
+* op: "return"
+* nvalues: 0
+* values: An empty array
+
+=== quit ===
+
+Request graceful shutdown.
+
+Message parameters:
+* op: "quit"
+
+No return message will be sent.
+
+=== testquit ===
+
+Request non-graceful shutdown, for testing.
+
+Message parameters:
+* op: "testquit"
+
+No return message will be sent.
+
+== Request messages sent from Lua to PHP ==
+
+=== call ===
+
+Call a PHP function.
+
+Message parameters:
+* op: "call"
+* id: The function ID given by registerLibrary
+* nargs: Number of arguments, including nils
+* args: An array giving the function arguments
+
+On success, the response message is:
+
+* op: "return"
+* nvalues: Number of return values, including nils
+* values: All return values as an array
+
+On failure the response message is:
+
+* op: "error"
+* value: The error message
+